@baron1996/kline-scene-schema 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/generated/schemas.d.ts +308 -0
  2. package/dist/generated/schemas.d.ts.map +1 -1
  3. package/dist/generated/schemas.js +401 -0
  4. package/dist/generated/time-series-scene.d.ts +88 -0
  5. package/dist/generated/time-series-scene.d.ts.map +1 -0
  6. package/dist/generated/time-series-scene.js +2 -0
  7. package/dist/generated/validate-time-series-scene.d.ts +15 -0
  8. package/dist/generated/validate-time-series-scene.d.ts.map +1 -0
  9. package/dist/generated/validate-time-series-scene.js +2359 -0
  10. package/dist/index.d.ts +7 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +7 -1
  13. package/dist/time-series-canonical-json.d.ts +3 -0
  14. package/dist/time-series-canonical-json.d.ts.map +1 -0
  15. package/dist/time-series-canonical-json.js +15 -0
  16. package/dist/time-series-canonicalize.d.ts +3 -0
  17. package/dist/time-series-canonicalize.d.ts.map +1 -0
  18. package/dist/time-series-canonicalize.js +19 -0
  19. package/dist/time-series-errors.d.ts +13 -0
  20. package/dist/time-series-errors.d.ts.map +1 -0
  21. package/dist/time-series-errors.js +12 -0
  22. package/dist/time-series-semantic-validator.d.ts +5 -0
  23. package/dist/time-series-semantic-validator.d.ts.map +1 -0
  24. package/dist/time-series-semantic-validator.js +81 -0
  25. package/dist/time-series-validator.d.ts +4 -0
  26. package/dist/time-series-validator.d.ts.map +1 -0
  27. package/dist/time-series-validator.js +52 -0
  28. package/package.json +1 -1
  29. package/schema/time-series-chart-config.schema.json +75 -0
  30. package/schema/time-series-runtime.schema.json +13 -0
  31. package/schema/time-series-scene.schema.json +154 -0
package/dist/index.d.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  /** 场景协议包版本;Scene version 仍保持 1。 */
2
- export declare const SCENE_PACKAGE_VERSION: "0.2.3";
2
+ export declare const SCENE_PACKAGE_VERSION: "0.3.0";
3
3
  export * from './canonical-json.js';
4
4
  export * from './canonicalize.js';
5
5
  export * from './errors.js';
6
6
  export * from './generated/chart-scene.js';
7
7
  export * from './generated/schemas.js';
8
8
  export * from './semantic-validator.js';
9
+ export * from './generated/time-series-scene.js';
10
+ export * from './time-series-canonical-json.js';
11
+ export * from './time-series-canonicalize.js';
12
+ export * from './time-series-errors.js';
13
+ export * from './time-series-semantic-validator.js';
14
+ export * from './time-series-validator.js';
9
15
  export * from './validator.js';
10
16
  export * from './version.js';
11
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,eAAO,MAAM,qBAAqB,EAAG,OAAgB,CAAC;AAEtD,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,eAAO,MAAM,qBAAqB,EAAG,OAAgB,CAAC;AAEtD,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,qCAAqC,CAAC;AACpD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,16 @@
1
1
  /** 场景协议包版本;Scene version 仍保持 1。 */
2
- export const SCENE_PACKAGE_VERSION = '0.2.3';
2
+ export const SCENE_PACKAGE_VERSION = '0.3.0';
3
3
  export * from './canonical-json.js';
4
4
  export * from './canonicalize.js';
5
5
  export * from './errors.js';
6
6
  export * from './generated/chart-scene.js';
7
7
  export * from './generated/schemas.js';
8
8
  export * from './semantic-validator.js';
9
+ export * from './generated/time-series-scene.js';
10
+ export * from './time-series-canonical-json.js';
11
+ export * from './time-series-canonicalize.js';
12
+ export * from './time-series-errors.js';
13
+ export * from './time-series-semantic-validator.js';
14
+ export * from './time-series-validator.js';
9
15
  export * from './validator.js';
10
16
  export * from './version.js';
@@ -0,0 +1,3 @@
1
+ export declare function serializeCanonicalTimeSeriesScene(scene: unknown): Uint8Array<ArrayBuffer>;
2
+ export declare function hashCanonicalTimeSeriesScene(scene: unknown): Promise<string>;
3
+ //# sourceMappingURL=time-series-canonical-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-series-canonical-json.d.ts","sourceRoot":"","sources":["../src/time-series-canonical-json.ts"],"names":[],"mappings":"AAKA,wBAAgB,iCAAiC,CAChD,KAAK,EAAE,OAAO,GACZ,UAAU,CAAC,WAAW,CAAC,CAWzB;AAED,wBAAsB,4BAA4B,CACjD,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -0,0 +1,15 @@
1
+ import canonicalize from 'canonicalize';
2
+ import { TimeSeriesSceneError } from './time-series-errors.js';
3
+ import { parseTimeSeriesScene } from './time-series-validator.js';
4
+ export function serializeCanonicalTimeSeriesScene(scene) {
5
+ const parsed = parseTimeSeriesScene(scene);
6
+ const serialized = canonicalize(parsed);
7
+ if (serialized === undefined) {
8
+ throw new TimeSeriesSceneError('TIME_SERIES_EXPORT_INVALID', '/', 'TimeSeriesScene could not be serialized.');
9
+ }
10
+ return new TextEncoder().encode(serialized);
11
+ }
12
+ export async function hashCanonicalTimeSeriesScene(scene) {
13
+ const digest = await globalThis.crypto.subtle.digest('SHA-256', serializeCanonicalTimeSeriesScene(scene));
14
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');
15
+ }
@@ -0,0 +1,3 @@
1
+ import type { TimeSeriesScene } from './generated/time-series-scene.js';
2
+ export declare function canonicalizeTimeSeriesScene(scene: TimeSeriesScene): TimeSeriesScene;
3
+ //# sourceMappingURL=time-series-canonicalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-series-canonicalize.d.ts","sourceRoot":"","sources":["../src/time-series-canonicalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEX,eAAe,EACf,MAAM,kCAAkC,CAAC;AAwB1C,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,eAAe,GACpB,eAAe,CAIjB"}
@@ -0,0 +1,19 @@
1
+ function sortTimeSeriesJson(value) {
2
+ if (Array.isArray(value)) {
3
+ return value.map((item) => sortTimeSeriesJson(item));
4
+ }
5
+ if (value !== null && typeof value === 'object') {
6
+ const sorted = {};
7
+ for (const key of Object.keys(value).sort()) {
8
+ const child = value[key];
9
+ if (child !== undefined) {
10
+ sorted[key] = sortTimeSeriesJson(child);
11
+ }
12
+ }
13
+ return sorted;
14
+ }
15
+ return value;
16
+ }
17
+ export function canonicalizeTimeSeriesScene(scene) {
18
+ return sortTimeSeriesJson(structuredClone(scene));
19
+ }
@@ -0,0 +1,13 @@
1
+ export type TimeSeriesSceneErrorCode = 'TIME_SERIES_SCENE_SCHEMA_INVALID' | 'TIME_SERIES_SCENE_VERSION_UNSUPPORTED' | 'TIME_SERIES_ENGINE_VERSION_MISMATCH' | 'TIME_SERIES_DATA_INVALID' | 'TIME_SERIES_UNKNOWN_SERIES' | 'TIME_SERIES_RUNTIME_DESTROYED' | 'TIME_SERIES_ADAPTER_FAILED' | 'TIME_SERIES_EXPORT_INVALID' | 'TIME_SERIES_BROWSER_NOT_INSTALLED' | 'TIME_SERIES_RENDER_FAILED' | 'TIME_SERIES_RENDER_TIMEOUT';
2
+ export interface TimeSeriesSceneIssue {
3
+ readonly code: TimeSeriesSceneErrorCode;
4
+ readonly path: string;
5
+ readonly message: string;
6
+ }
7
+ export declare class TimeSeriesSceneError extends Error {
8
+ readonly code: TimeSeriesSceneErrorCode;
9
+ readonly path: string;
10
+ readonly issues: readonly TimeSeriesSceneIssue[];
11
+ constructor(code: TimeSeriesSceneErrorCode, path: string, message: string, issues?: readonly TimeSeriesSceneIssue[]);
12
+ }
13
+ //# sourceMappingURL=time-series-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-series-errors.d.ts","sourceRoot":"","sources":["../src/time-series-errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GACjC,kCAAkC,GAClC,uCAAuC,GACvC,qCAAqC,GACrC,0BAA0B,GAC1B,4BAA4B,GAC5B,+BAA+B,GAC/B,4BAA4B,GAC5B,4BAA4B,GAC5B,mCAAmC,GACnC,2BAA2B,GAC3B,4BAA4B,CAAC;AAEhC,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,SAAgB,IAAI,EAAE,wBAAwB,CAAC;IAC/C,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;gBAGvD,IAAI,EAAE,wBAAwB,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,SAAS,oBAAoB,EAAE;CAQzC"}
@@ -0,0 +1,12 @@
1
+ export class TimeSeriesSceneError extends Error {
2
+ code;
3
+ path;
4
+ issues;
5
+ constructor(code, path, message, issues) {
6
+ super(message);
7
+ this.name = 'TimeSeriesSceneError';
8
+ this.code = code;
9
+ this.path = path;
10
+ this.issues = issues ?? [{ code, path, message }];
11
+ }
12
+ }
@@ -0,0 +1,5 @@
1
+ import type { TimeSeriesScene } from './generated/time-series-scene.js';
2
+ import { type TimeSeriesSceneIssue } from './time-series-errors.js';
3
+ export declare function collectTimeSeriesSemanticIssues(scene: TimeSeriesScene): readonly TimeSeriesSceneIssue[];
4
+ export declare function assertSemanticTimeSeriesScene(scene: TimeSeriesScene): void;
5
+ //# sourceMappingURL=time-series-semantic-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-series-semantic-validator.d.ts","sourceRoot":"","sources":["../src/time-series-semantic-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAEN,KAAK,oBAAoB,EACzB,MAAM,yBAAyB,CAAC;AAMjC,wBAAgB,+BAA+B,CAC9C,KAAK,EAAE,eAAe,GACpB,SAAS,oBAAoB,EAAE,CA4EjC;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAW1E"}
@@ -0,0 +1,81 @@
1
+ import { TimeSeriesSceneError, } from './time-series-errors.js';
2
+ function pointerToken(value) {
3
+ return value.replaceAll('~', '~0').replaceAll('/', '~1');
4
+ }
5
+ export function collectTimeSeriesSemanticIssues(scene) {
6
+ const issues = [];
7
+ const seriesIds = new Set();
8
+ const firstSeries = scene.series[0];
9
+ for (const [index, series] of scene.series.entries()) {
10
+ if (seriesIds.has(series.id)) {
11
+ issues.push({
12
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
13
+ path: `/series/${index}/id`,
14
+ message: `Duplicate time series id: ${series.id}.`,
15
+ });
16
+ }
17
+ seriesIds.add(series.id);
18
+ if (series.unit !== firstSeries.unit) {
19
+ issues.push({
20
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
21
+ path: `/series/${index}/unit`,
22
+ message: 'All time series must use the same unit.',
23
+ });
24
+ }
25
+ if (series.precision !== firstSeries.precision) {
26
+ issues.push({
27
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
28
+ path: `/series/${index}/precision`,
29
+ message: 'All time series must use the same precision.',
30
+ });
31
+ }
32
+ }
33
+ let previousTimestamp;
34
+ const timestamps = new Set();
35
+ for (const [index, point] of scene.data.entries()) {
36
+ if (previousTimestamp !== undefined &&
37
+ point.timestamp <= previousTimestamp) {
38
+ issues.push({
39
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
40
+ path: `/data/${index}/timestamp`,
41
+ message: 'Time series timestamps must be strictly increasing.',
42
+ });
43
+ }
44
+ previousTimestamp = point.timestamp;
45
+ timestamps.add(point.timestamp);
46
+ const valueIds = Object.keys(point.values);
47
+ for (const seriesId of seriesIds) {
48
+ if (!Object.hasOwn(point.values, seriesId)) {
49
+ issues.push({
50
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
51
+ path: `/data/${index}/values/${pointerToken(seriesId)}`,
52
+ message: `Missing value for time series: ${seriesId}.`,
53
+ });
54
+ }
55
+ }
56
+ for (const valueId of valueIds) {
57
+ if (!seriesIds.has(valueId)) {
58
+ issues.push({
59
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
60
+ path: `/data/${index}/values/${pointerToken(valueId)}`,
61
+ message: `Unknown time series value key: ${valueId}.`,
62
+ });
63
+ }
64
+ }
65
+ }
66
+ if (!timestamps.has(scene.viewport.anchorTimestamp)) {
67
+ issues.push({
68
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
69
+ path: '/viewport/anchorTimestamp',
70
+ message: 'Viewport anchorTimestamp must reference a data point.',
71
+ });
72
+ }
73
+ return issues;
74
+ }
75
+ export function assertSemanticTimeSeriesScene(scene) {
76
+ const issues = collectTimeSeriesSemanticIssues(scene);
77
+ const first = issues[0];
78
+ if (first !== undefined) {
79
+ throw new TimeSeriesSceneError(first.code, first.path, first.message, issues);
80
+ }
81
+ }
@@ -0,0 +1,4 @@
1
+ import type { TimeSeriesScene } from './generated/time-series-scene.js';
2
+ export declare function parseStructuralTimeSeriesScene(value: unknown): TimeSeriesScene;
3
+ export declare function parseTimeSeriesScene(value: unknown): TimeSeriesScene;
4
+ //# sourceMappingURL=time-series-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-series-validator.d.ts","sourceRoot":"","sources":["../src/time-series-validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AA8DxE,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAqB9E;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAIpE"}
@@ -0,0 +1,52 @@
1
+ import { validateTimeSeriesScene as generatedValidator } from './generated/validate-time-series-scene.js';
2
+ import { canonicalizeTimeSeriesScene } from './time-series-canonicalize.js';
3
+ import { TimeSeriesSceneError, } from './time-series-errors.js';
4
+ import { assertSemanticTimeSeriesScene } from './time-series-semantic-validator.js';
5
+ const validateStructural = generatedValidator;
6
+ function pointerToken(value) {
7
+ return value.replaceAll('~', '~0').replaceAll('/', '~1');
8
+ }
9
+ function structuralPath(error) {
10
+ if (error.keyword === 'additionalProperties' &&
11
+ error.params?.additionalProperty !== undefined) {
12
+ return `${error.instancePath}/${pointerToken(error.params.additionalProperty)}` || '/';
13
+ }
14
+ if (error.keyword === 'required' &&
15
+ error.params?.missingProperty !== undefined) {
16
+ return `${error.instancePath}/${pointerToken(error.params.missingProperty)}` || '/';
17
+ }
18
+ return error.instancePath || '/';
19
+ }
20
+ function structuralCode(error) {
21
+ if (error.instancePath === '/version' && error.keyword === 'const') {
22
+ return 'TIME_SERIES_SCENE_VERSION_UNSUPPORTED';
23
+ }
24
+ if ((error.instancePath === '/runtime/engine' ||
25
+ error.instancePath === '/runtime/engineVersion') &&
26
+ error.keyword === 'const') {
27
+ return 'TIME_SERIES_ENGINE_VERSION_MISMATCH';
28
+ }
29
+ return 'TIME_SERIES_SCENE_SCHEMA_INVALID';
30
+ }
31
+ export function parseStructuralTimeSeriesScene(value) {
32
+ if (!validateStructural(value)) {
33
+ const errors = validateStructural.errors ?? [];
34
+ const issues = errors.map((error) => ({
35
+ code: structuralCode(error),
36
+ path: structuralPath(error),
37
+ message: error.message ?? `Schema validation failed at ${error.schemaPath}.`,
38
+ }));
39
+ const first = issues[0] ?? {
40
+ code: 'TIME_SERIES_SCENE_SCHEMA_INVALID',
41
+ path: '/',
42
+ message: 'TimeSeriesScene schema validation failed.',
43
+ };
44
+ throw new TimeSeriesSceneError(first.code, first.path, first.message, issues);
45
+ }
46
+ return structuredClone(value);
47
+ }
48
+ export function parseTimeSeriesScene(value) {
49
+ const structural = parseStructuralTimeSeriesScene(value);
50
+ assertSemanticTimeSeriesScene(structural);
51
+ return canonicalizeTimeSeriesScene(structural);
52
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baron1996/kline-scene-schema",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Strict ChartScene schema, types, validation, and canonical serialization.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://baron.dev/kline-scene/time-series-chart-config.schema.json",
4
+ "title": "TimeSeriesChartConfig",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "locale",
9
+ "timezone",
10
+ "layout",
11
+ "grid",
12
+ "thousandsSeparator",
13
+ "decimalFold",
14
+ "zoomAnchor",
15
+ "dateFormat",
16
+ "largeNumberFormat"
17
+ ],
18
+ "properties": {
19
+ "locale": {
20
+ "type": "string",
21
+ "minLength": 2,
22
+ "maxLength": 64,
23
+ "pattern": "^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
24
+ },
25
+ "timezone": {
26
+ "type": "string",
27
+ "minLength": 1,
28
+ "maxLength": 128,
29
+ "pattern": "^[A-Za-z_+-]+(?:/[A-Za-z0-9_+-]+)*$"
30
+ },
31
+ "layout": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "required": ["backgroundColor", "textColor", "fontFamily", "fontSize"],
35
+ "properties": {
36
+ "backgroundColor": {
37
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/rgbaColor"
38
+ },
39
+ "textColor": {
40
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/rgbaColor"
41
+ },
42
+ "fontFamily": { "type": "string", "minLength": 1, "maxLength": 128 },
43
+ "fontSize": { "type": "number", "minimum": 8, "maximum": 32 }
44
+ }
45
+ },
46
+ "grid": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "required": ["horizontalColor", "verticalColor"],
50
+ "properties": {
51
+ "horizontalColor": {
52
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/rgbaColor"
53
+ },
54
+ "verticalColor": {
55
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/rgbaColor"
56
+ }
57
+ }
58
+ },
59
+ "thousandsSeparator": { "enum": ["", ",", " ", "_"] },
60
+ "decimalFold": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["enabled", "threshold"],
64
+ "properties": {
65
+ "enabled": { "type": "boolean" },
66
+ "threshold": { "type": "integer", "minimum": 1, "maximum": 16 }
67
+ }
68
+ },
69
+ "zoomAnchor": { "enum": ["cursor", "right"] },
70
+ "dateFormat": {
71
+ "enum": ["yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss"]
72
+ },
73
+ "largeNumberFormat": { "enum": ["western", "chinese", "plain"] }
74
+ }
75
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://baron.dev/kline-scene/time-series-runtime.schema.json",
4
+ "title": "TimeSeriesRuntimeIdentity",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["engine", "engineVersion", "runtimeVersion"],
8
+ "properties": {
9
+ "engine": { "const": "klinecharts" },
10
+ "engineVersion": { "const": "10.0.0" },
11
+ "runtimeVersion": { "const": "0.1.0" }
12
+ }
13
+ }
@@ -0,0 +1,154 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://baron.dev/kline-scene/time-series-scene.schema.json",
4
+ "title": "TimeSeriesScene",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schema",
9
+ "version",
10
+ "runtime",
11
+ "period",
12
+ "series",
13
+ "data",
14
+ "chart",
15
+ "viewport",
16
+ "render",
17
+ "metadata"
18
+ ],
19
+ "properties": {
20
+ "schema": { "const": "@baron1996/time-series-scene" },
21
+ "version": { "const": 1 },
22
+ "runtime": {
23
+ "$ref": "https://baron.dev/kline-scene/time-series-runtime.schema.json"
24
+ },
25
+ "period": { "$ref": "#/$defs/timeSeriesPeriod" },
26
+ "series": {
27
+ "type": "array",
28
+ "minItems": 1,
29
+ "maxItems": 64,
30
+ "items": { "$ref": "#/$defs/timeSeriesDefinition" }
31
+ },
32
+ "data": {
33
+ "type": "array",
34
+ "minItems": 1,
35
+ "maxItems": 1000000,
36
+ "items": { "$ref": "#/$defs/timeSeriesPoint" }
37
+ },
38
+ "chart": {
39
+ "$ref": "https://baron.dev/kline-scene/time-series-chart-config.schema.json"
40
+ },
41
+ "viewport": { "$ref": "#/$defs/timeSeriesViewport" },
42
+ "render": { "$ref": "#/$defs/timeSeriesRender" },
43
+ "metadata": { "$ref": "#/$defs/metadata" }
44
+ },
45
+ "$defs": {
46
+ "timeSeriesPeriod": {
47
+ "type": "object",
48
+ "additionalProperties": false,
49
+ "required": ["span", "type"],
50
+ "properties": {
51
+ "span": { "type": "integer", "minimum": 1, "maximum": 100000 },
52
+ "type": {
53
+ "enum": ["second", "minute", "hour", "day", "week", "month", "year"]
54
+ }
55
+ }
56
+ },
57
+ "timeSeriesDefinition": {
58
+ "type": "object",
59
+ "additionalProperties": false,
60
+ "required": ["id", "name", "type", "unit", "precision", "visible", "style"],
61
+ "properties": {
62
+ "id": {
63
+ "type": "string",
64
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$"
65
+ },
66
+ "name": { "type": "string", "minLength": 1, "maxLength": 256 },
67
+ "type": { "const": "line" },
68
+ "unit": { "type": "string", "minLength": 1, "maxLength": 64 },
69
+ "precision": { "type": "integer", "minimum": 0, "maximum": 16 },
70
+ "visible": { "type": "boolean" },
71
+ "style": {
72
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/lineStyle"
73
+ }
74
+ }
75
+ },
76
+ "timeSeriesPoint": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": ["timestamp", "values"],
80
+ "properties": {
81
+ "timestamp": {
82
+ "type": "integer",
83
+ "minimum": 1,
84
+ "maximum": 9007199254740991
85
+ },
86
+ "values": {
87
+ "type": "object",
88
+ "minProperties": 1,
89
+ "maxProperties": 64,
90
+ "propertyNames": { "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$" },
91
+ "additionalProperties": {
92
+ "oneOf": [
93
+ {
94
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/finiteNumber"
95
+ },
96
+ { "type": "null" }
97
+ ]
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "timeSeriesViewport": {
103
+ "type": "object",
104
+ "additionalProperties": false,
105
+ "required": ["barSpace", "rightOffsetDistance", "anchorTimestamp"],
106
+ "properties": {
107
+ "barSpace": { "type": "number", "minimum": 1, "maximum": 100 },
108
+ "rightOffsetDistance": { "type": "number", "minimum": 0, "maximum": 10000 },
109
+ "anchorTimestamp": {
110
+ "type": "integer",
111
+ "minimum": 1,
112
+ "maximum": 9007199254740991
113
+ }
114
+ }
115
+ },
116
+ "timeSeriesRender": {
117
+ "type": "object",
118
+ "additionalProperties": false,
119
+ "required": [
120
+ "width",
121
+ "height",
122
+ "deviceScaleFactor",
123
+ "background",
124
+ "fontFamily",
125
+ "timeoutMs"
126
+ ],
127
+ "properties": {
128
+ "width": { "type": "integer", "minimum": 320, "maximum": 8192 },
129
+ "height": { "type": "integer", "minimum": 240, "maximum": 8192 },
130
+ "deviceScaleFactor": { "type": "number", "minimum": 0.5, "maximum": 4 },
131
+ "background": {
132
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/rgbaColor"
133
+ },
134
+ "fontFamily": { "const": "Baron Sans" },
135
+ "timeoutMs": { "type": "integer", "minimum": 100, "maximum": 120000 }
136
+ }
137
+ },
138
+ "metadata": {
139
+ "type": "object",
140
+ "maxProperties": 64,
141
+ "propertyNames": { "type": "string", "minLength": 1, "maxLength": 128 },
142
+ "additionalProperties": {
143
+ "oneOf": [
144
+ { "type": "null" },
145
+ { "type": "boolean" },
146
+ {
147
+ "$ref": "https://baron.dev/kline-scene/common.schema.json#/$defs/finiteNumber"
148
+ },
149
+ { "type": "string" }
150
+ ]
151
+ }
152
+ }
153
+ }
154
+ }