@altopelago/aeos-core 0.11.0 → 0.12.1
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.
- package/README.md +9 -0
- package/dist/bin/aeos-validator.d.ts +1 -1
- package/dist/bin/aeos-validator.js +9 -5
- package/dist/bin/aeos-validator.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/numericForm.d.ts.map +1 -1
- package/dist/rules/numericForm.js +1 -9
- package/dist/rules/numericForm.js.map +1 -1
- package/dist/rules/stringForm.js +1 -1
- package/dist/rules/stringForm.js.map +1 -1
- package/dist/rules/typeCheck.d.ts +1 -0
- package/dist/rules/typeCheck.d.ts.map +1 -1
- package/dist/rules/typeCheck.js +6 -2
- package/dist/rules/typeCheck.js.map +1 -1
- package/dist/schema-codec.d.ts.map +1 -1
- package/dist/schema-codec.js +142 -8
- package/dist/schema-codec.js.map +1 -1
- package/dist/schema-tools.d.ts +90 -0
- package/dist/schema-tools.d.ts.map +1 -0
- package/dist/schema-tools.js +465 -0
- package/dist/schema-tools.js.map +1 -0
- package/dist/telex.d.ts +14 -0
- package/dist/telex.d.ts.map +1 -0
- package/dist/telex.js +33 -0
- package/dist/telex.js.map +1 -0
- package/dist/types/aes.d.ts +9 -3
- package/dist/types/aes.d.ts.map +1 -1
- package/dist/types/schema.d.ts +22 -1
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/types/schema.js.map +1 -1
- package/dist/util/datatypes.d.ts +13 -0
- package/dist/util/datatypes.d.ts.map +1 -0
- package/dist/util/datatypes.js +50 -0
- package/dist/util/datatypes.js.map +1 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +207 -42
- package/dist/validate.js.map +1 -1
- package/package.json +6 -6
package/dist/types/aes.d.ts
CHANGED
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
* Re-exports AES types from @altopelago/aeon-aes.
|
|
5
5
|
* These are type-only imports to maintain zero runtime dependencies.
|
|
6
6
|
*/
|
|
7
|
-
import type { AssignmentEvent } from '@altopelago/aeon-aes';
|
|
7
|
+
import type { AssignmentEvent, TelexRecord } from '@altopelago/aeon-aes';
|
|
8
8
|
import type { Span as AeonSpan } from '@altopelago/aeon-lexer';
|
|
9
|
-
export type { AssignmentEvent, AeonSpan };
|
|
9
|
+
export type { AssignmentEvent, AeonSpan, TelexRecord };
|
|
10
|
+
/** A decoded portable AES body record; header-plane records are filtered first. */
|
|
11
|
+
export type PortableAesBodyEvent = TelexRecord & {
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly kind: string;
|
|
14
|
+
readonly header?: never;
|
|
15
|
+
};
|
|
10
16
|
/**
|
|
11
17
|
* Readonly AES array type for validation input
|
|
12
18
|
*/
|
|
13
|
-
export type AES = readonly AssignmentEvent[];
|
|
19
|
+
export type AES = readonly (AssignmentEvent | PortableAesBodyEvent)[];
|
|
14
20
|
//# sourceMappingURL=aes.d.ts.map
|
package/dist/types/aes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../../src/types/aes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../../src/types/aes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG/D,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AAEvD,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,GAAG,GAAG,SAAS,CAAC,eAAe,GAAG,oBAAoB,CAAC,EAAE,CAAC"}
|
package/dist/types/schema.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export interface ConstraintsV1 {
|
|
|
63
63
|
readonly max_length?: number;
|
|
64
64
|
/** AEOS portable pattern for string matching */
|
|
65
65
|
readonly pattern?: string;
|
|
66
|
-
/**
|
|
66
|
+
/** Exact datatype-label constraint; deeper datatype semantics belong in datatype_rules. */
|
|
67
67
|
readonly datatype?: string;
|
|
68
68
|
/** Attribute entry constraints keyed by attribute name */
|
|
69
69
|
readonly attributes?: Readonly<Record<string, AttributeConstraintsV1>>;
|
|
@@ -74,6 +74,14 @@ export interface ConstraintsV1 {
|
|
|
74
74
|
* Schema rule for an exact SANSA path or non-exact SANSA selector
|
|
75
75
|
*/
|
|
76
76
|
export interface SchemaRule {
|
|
77
|
+
/** Stable identity for this declaration across schema versions. */
|
|
78
|
+
readonly declaration_id?: string;
|
|
79
|
+
/** Optional semantic lineage shared by related declarations. */
|
|
80
|
+
readonly lineage_id?: string;
|
|
81
|
+
/** Optional short consumer-facing name; non-operational schema metadata. */
|
|
82
|
+
readonly label?: string;
|
|
83
|
+
/** Optional consumer-facing purpose and usage description; non-operational schema metadata. */
|
|
84
|
+
readonly description?: string;
|
|
77
85
|
/** Exact SANSA path this rule applies to */
|
|
78
86
|
readonly path?: string;
|
|
79
87
|
/** SANSA selector this rule applies to */
|
|
@@ -81,12 +89,25 @@ export interface SchemaRule {
|
|
|
81
89
|
/** Constraints to apply */
|
|
82
90
|
readonly constraints: ConstraintsV1;
|
|
83
91
|
}
|
|
92
|
+
export type SchemaEvolutionKindV1 = 'add' | 'remove' | 'rename' | 'move' | 'constraint-change' | 'datatype-change' | 'split' | 'merge' | 'derive' | 'replace';
|
|
93
|
+
/** Authored temporal intent relating declarations across schema versions. */
|
|
94
|
+
export interface SchemaEvolutionV1 {
|
|
95
|
+
readonly change_id: string;
|
|
96
|
+
readonly kind: SchemaEvolutionKindV1;
|
|
97
|
+
readonly from_declarations: readonly string[];
|
|
98
|
+
readonly to_declarations: readonly string[];
|
|
99
|
+
readonly from_contract?: string;
|
|
100
|
+
readonly transform?: string;
|
|
101
|
+
readonly note?: string;
|
|
102
|
+
}
|
|
84
103
|
/**
|
|
85
104
|
* AEOS Schema v1
|
|
86
105
|
*/
|
|
87
106
|
export interface SchemaV1 {
|
|
88
107
|
/** Array of rules */
|
|
89
108
|
readonly rules: readonly SchemaRule[];
|
|
109
|
+
/** Authored changes from an earlier schema into this schema. */
|
|
110
|
+
readonly evolution?: readonly SchemaEvolutionV1[];
|
|
90
111
|
/** Open-world or closed-world validation policy */
|
|
91
112
|
readonly world?: 'open' | 'closed';
|
|
92
113
|
/** Optional schema-wide reference policy */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,aAAa;CAAG;AAEhE,MAAM,WAAW,aAAa;IAC1B,6BAA6B;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEvB,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAE3C,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAE5B,gEAAgE;IAChE,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAElC,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEzC,mCAAmC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAEnD,yCAAyC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAEpD,uDAAuD;IACvD,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;IAEzD,oFAAoF;IACpF,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAE3C,kFAAkF;IAClF,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAE1C,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAEpC,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,uDAAuD;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,uDAAuD;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAEtC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,8EAA8E;IAC9E,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAE3C,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,iFAAiF;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/types/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/types/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0LH;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAwB,IAAI,GAAG,CAAC;IAC9D,UAAU;IACV,MAAM;IACN,QAAQ;IACR,UAAU;IACV,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,aAAa;IACb,WAAW;IACX,gBAAgB;IAChB,0BAA0B;IAC1B,wBAAwB;IACxB,SAAS;IACT,cAAc;IACd,cAAc;IACd,cAAc;IACd,MAAM;IACN,YAAY;IACZ,YAAY;IACZ,OAAO;IACP,yBAAyB;IACzB,WAAW;IACX,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,SAAS;IACT,UAAU;IACV,YAAY;IACZ,mBAAmB;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAoC;IACzE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return the base name of a datatype without generic parameters or clarifiers.
|
|
3
|
+
*/
|
|
4
|
+
export declare function datatypeBase(datatype: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Parse the JSON-compatible values from a datatype clarifier list.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseClarifierValues(datatype: string): (string | number)[];
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the radix declared by a built-in numeric datatype.
|
|
11
|
+
*/
|
|
12
|
+
export declare function declaredRadixFromDatatype(datatype: string | undefined): number | null;
|
|
13
|
+
//# sourceMappingURL=datatypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datatypes.d.ts","sourceRoot":"","sources":["../../src/util/datatypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAW1E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWrF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return the base name of a datatype without generic parameters or clarifiers.
|
|
3
|
+
*/
|
|
4
|
+
export function datatypeBase(datatype) {
|
|
5
|
+
const genericIdx = datatype.indexOf('<');
|
|
6
|
+
const clarifierIdx = datatype.indexOf('[');
|
|
7
|
+
const endIdx = [genericIdx, clarifierIdx]
|
|
8
|
+
.filter((idx) => idx >= 0)
|
|
9
|
+
.reduce((min, idx) => Math.min(min, idx), datatype.length);
|
|
10
|
+
return datatype.slice(0, endIdx);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Parse the JSON-compatible values from a datatype clarifier list.
|
|
14
|
+
*/
|
|
15
|
+
export function parseClarifierValues(datatype) {
|
|
16
|
+
const start = datatype.indexOf('[');
|
|
17
|
+
if (start < 0 || !datatype.endsWith(']'))
|
|
18
|
+
return [];
|
|
19
|
+
const payload = datatype.slice(start + 1, -1);
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(`[${payload}]`);
|
|
22
|
+
if (!Array.isArray(parsed))
|
|
23
|
+
return [];
|
|
24
|
+
return parsed.filter((value) => typeof value === 'string' || typeof value === 'number');
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the radix declared by a built-in numeric datatype.
|
|
32
|
+
*/
|
|
33
|
+
export function declaredRadixFromDatatype(datatype) {
|
|
34
|
+
if (datatype === undefined)
|
|
35
|
+
return null;
|
|
36
|
+
const trimmed = datatype.trim();
|
|
37
|
+
if (trimmed.toLowerCase() === 'decimal')
|
|
38
|
+
return 10;
|
|
39
|
+
const alias = /^radix(2|6|8|12)$/i.exec(trimmed);
|
|
40
|
+
if (alias)
|
|
41
|
+
return Number(alias[1]);
|
|
42
|
+
if (datatypeBase(trimmed).toLowerCase() !== 'radix')
|
|
43
|
+
return null;
|
|
44
|
+
const values = parseClarifierValues(trimmed);
|
|
45
|
+
if (values.length !== 1 || typeof values[0] !== 'number')
|
|
46
|
+
return null;
|
|
47
|
+
const value = values[0];
|
|
48
|
+
return Number.isInteger(value) && value >= 2 && value <= 64 ? value : null;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=datatypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datatypes.js","sourceRoot":"","sources":["../../src/util/datatypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC;SACpC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;SACzB,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,GAAG,CAAY,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAA4B,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACtH,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAA4B;IAClE,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,OAAO,CAAC,WAAW,EAAE,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,KAAK;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACjE,MAAM,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC"}
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAwB,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAY1D,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAuFzE;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,gCAAgC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IAErE,+DAA+D;IAC/D,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC;CAE9C;AAiJD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CACpB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,QAAQ,EAChB,OAAO,GAAE,eAAoB,GAC9B,cAAc,CAuYhB"}
|
package/dist/validate.js
CHANGED
|
@@ -13,7 +13,9 @@ import { checkTypes } from './rules/typeCheck.js';
|
|
|
13
13
|
import { checkReferenceForms } from './rules/referenceForm.js';
|
|
14
14
|
import { checkNumericForm } from './rules/numericForm.js';
|
|
15
15
|
import { checkStringForm, checkPatterns, matchesPortablePattern } from './rules/stringForm.js';
|
|
16
|
+
import { datatypeBase, declaredRadixFromDatatype, parseClarifierValues } from './util/datatypes.js';
|
|
16
17
|
import { parseAddress, resolveAddress, } from '@altopelago/sansa';
|
|
18
|
+
import { formatDatatypeDescriptor, } from '@altopelago/aeon-aes';
|
|
17
19
|
const TYPE_ALIASES = {
|
|
18
20
|
NumberLiteral: ['NumberLiteral'],
|
|
19
21
|
StringLiteral: ['StringLiteral'],
|
|
@@ -34,10 +36,11 @@ const TYPE_ALIASES = {
|
|
|
34
36
|
DateLiteral: ['DateLiteral'],
|
|
35
37
|
TimeLiteral: ['TimeLiteral'],
|
|
36
38
|
DateTimeLiteral: ['DateTimeLiteral'],
|
|
37
|
-
|
|
39
|
+
WTCDateTimeLiteral: ['WTCDateTimeLiteral'],
|
|
38
40
|
CloneReference: ['CloneReference'],
|
|
39
41
|
PointerReference: ['PointerReference'],
|
|
40
42
|
NodeLiteral: ['NodeLiteral'],
|
|
43
|
+
NodeHead: ['NodeHead'],
|
|
41
44
|
};
|
|
42
45
|
function formatQuotedMemberSegment(key) {
|
|
43
46
|
return `.[${JSON.stringify(String(key))}]`;
|
|
@@ -107,7 +110,7 @@ const STRING_LIKE_VALUE_TYPES = new Set([
|
|
|
107
110
|
'DateLiteral',
|
|
108
111
|
'TimeLiteral',
|
|
109
112
|
'DateTimeLiteral',
|
|
110
|
-
'
|
|
113
|
+
'WTCDateTimeLiteral',
|
|
111
114
|
]);
|
|
112
115
|
function stringLikePayloadLength(event) {
|
|
113
116
|
if (!STRING_LIKE_VALUE_TYPES.has(event.type))
|
|
@@ -206,6 +209,8 @@ export function validate(aes, schema, options = {}) {
|
|
|
206
209
|
// Phase 3: (moved to run after Phase 2)
|
|
207
210
|
// Helpers: format canonical path (local, no runtime AEON deps)
|
|
208
211
|
function formatCanonicalPath(path) {
|
|
212
|
+
if (typeof path === 'string')
|
|
213
|
+
return path;
|
|
209
214
|
if (!path || !Array.isArray(path.segments))
|
|
210
215
|
return '$';
|
|
211
216
|
let result = '';
|
|
@@ -234,6 +239,10 @@ export function validate(aes, schema, options = {}) {
|
|
|
234
239
|
function toTuple(span) {
|
|
235
240
|
if (!span)
|
|
236
241
|
return null;
|
|
242
|
+
if (typeof span === 'string') {
|
|
243
|
+
const match = span.match(/^(0|[1-9][0-9]*):(0|[1-9][0-9]*)$/u);
|
|
244
|
+
return match === null ? null : [Number(match[1]), Number(match[2])];
|
|
245
|
+
}
|
|
237
246
|
if (Array.isArray(span) && span.length === 2 && typeof span[0] === 'number')
|
|
238
247
|
return span;
|
|
239
248
|
if (span.start && span.end && typeof span.start.offset === 'number')
|
|
@@ -243,24 +252,9 @@ export function validate(aes, schema, options = {}) {
|
|
|
243
252
|
function decodeSeparatorChars(datatype) {
|
|
244
253
|
if (!datatype)
|
|
245
254
|
return [];
|
|
246
|
-
|
|
247
|
-
if (!match)
|
|
248
|
-
return [];
|
|
249
|
-
const payload = match[1] ?? '';
|
|
250
|
-
if (payload.length === 0)
|
|
255
|
+
if (datatypeBase(datatype).toLowerCase() !== 'sep')
|
|
251
256
|
return [];
|
|
252
|
-
|
|
253
|
-
let i = 0;
|
|
254
|
-
while (i < payload.length) {
|
|
255
|
-
separators.push(payload[i]);
|
|
256
|
-
i += 1;
|
|
257
|
-
if (i < payload.length) {
|
|
258
|
-
if (payload[i] !== ',')
|
|
259
|
-
return [];
|
|
260
|
-
i += 1;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return separators;
|
|
257
|
+
return parseClarifierValues(datatype).filter((value) => typeof value === 'string');
|
|
264
258
|
}
|
|
265
259
|
// Phase 2 — Baseline invariants
|
|
266
260
|
const seen = new Map();
|
|
@@ -278,6 +272,7 @@ export function validate(aes, schema, options = {}) {
|
|
|
278
272
|
const element = elements[i];
|
|
279
273
|
const attributes = buildAttributeInfoMap(element?.attributes);
|
|
280
274
|
const info = {
|
|
275
|
+
...(typeof element?.structuralId === 'string' ? { identity: element.structuralId } : {}),
|
|
281
276
|
type: typeof element?.type === 'string' ? element.type : 'Unknown',
|
|
282
277
|
raw: typeof element?.raw === 'string' ? element.raw : '',
|
|
283
278
|
value: typeof element?.value === 'string' ? element.value : '',
|
|
@@ -302,6 +297,7 @@ export function validate(aes, schema, options = {}) {
|
|
|
302
297
|
const valueNode = entry?.value;
|
|
303
298
|
const nestedAttributes = buildAttributeInfoMap(entry?.annotations);
|
|
304
299
|
const info = {
|
|
300
|
+
...(typeof entry?.structuralId === 'string' ? { identity: entry.structuralId } : {}),
|
|
305
301
|
type: typeof valueNode?.type === 'string' ? valueNode.type : 'Unknown',
|
|
306
302
|
raw: typeof valueNode?.raw === 'string' ? valueNode.raw : '',
|
|
307
303
|
value: typeof valueNode?.value === 'string' ? valueNode.value : '',
|
|
@@ -319,6 +315,7 @@ export function validate(aes, schema, options = {}) {
|
|
|
319
315
|
for (const [key, attribute] of attributes.entries()) {
|
|
320
316
|
const attributePath = appendAttributePath(basePath, key);
|
|
321
317
|
eventsByPath.set(attributePath, {
|
|
318
|
+
...(attribute.identity !== undefined ? { identity: attribute.identity } : {}),
|
|
322
319
|
type: attribute.type,
|
|
323
320
|
raw: attribute.raw,
|
|
324
321
|
value: attribute.value,
|
|
@@ -332,6 +329,7 @@ export function validate(aes, schema, options = {}) {
|
|
|
332
329
|
for (let i = 0; i < aes.length; i++) {
|
|
333
330
|
const event = aes[i];
|
|
334
331
|
const pathStr = formatCanonicalPath(event.path);
|
|
332
|
+
const portable = isPortableTelexRecord(event);
|
|
335
333
|
if (pathStr.length > resourcePolicy.max_path_length) {
|
|
336
334
|
emitResourceError(ctx, pathStr, `Path length ${pathStr.length} exceeds max_path_length ${resourcePolicy.max_path_length}`, toTuple(event.span));
|
|
337
335
|
}
|
|
@@ -355,9 +353,27 @@ export function validate(aes, schema, options = {}) {
|
|
|
355
353
|
else {
|
|
356
354
|
seen.set(pathStr, event.span);
|
|
357
355
|
// Collect event info for Phase 5-7 checks
|
|
358
|
-
if (
|
|
356
|
+
if (portable) {
|
|
357
|
+
const value = typeof event.value === 'string' ? event.value : '';
|
|
358
|
+
const datatype = portableDatatype(event);
|
|
359
|
+
const info = {
|
|
360
|
+
...(typeof event.identity === 'string' ? { identity: event.identity } : {}),
|
|
361
|
+
type: event.kind,
|
|
362
|
+
raw: value,
|
|
363
|
+
value,
|
|
364
|
+
...(datatype !== undefined ? { datatype } : {}),
|
|
365
|
+
span: toTuple(event.span),
|
|
366
|
+
...((event.kind === 'CloneReference' || event.kind === 'PointerReference')
|
|
367
|
+
&& typeof event.value === 'string'
|
|
368
|
+
? { referencePath: parsePortableReferencePath(event.value) }
|
|
369
|
+
: {}),
|
|
370
|
+
};
|
|
371
|
+
eventsByPath.set(pathStr, info);
|
|
372
|
+
}
|
|
373
|
+
else if (event.value && typeof event.value.type === 'string') {
|
|
359
374
|
const attributes = buildAttributeInfoMap(event.annotations);
|
|
360
375
|
const info = {
|
|
376
|
+
...(typeof event.structuralId === 'string' ? { identity: event.structuralId } : {}),
|
|
361
377
|
type: event.value.type,
|
|
362
378
|
raw: typeof event.value.raw === 'string' ? event.value.raw : '',
|
|
363
379
|
value: typeof event.value.value === 'string' ? event.value.value : '',
|
|
@@ -393,18 +409,26 @@ export function validate(aes, schema, options = {}) {
|
|
|
393
409
|
}
|
|
394
410
|
// Register index even for first occurrence
|
|
395
411
|
}
|
|
412
|
+
hydratePortableAttributes(eventsByPath, aes);
|
|
413
|
+
hydratePortableContainerArities(aes, containerArity, resourcePolicy, ctx, toTuple);
|
|
396
414
|
for (const [path, info] of eventsByPath) {
|
|
397
415
|
enforceStringLengthResourceBudget(info, path, resourcePolicy, ctx);
|
|
398
416
|
}
|
|
399
417
|
// Optional separator literal trailing-delimiter policy
|
|
400
418
|
if (trailingSeparatorPolicy !== 'off') {
|
|
401
419
|
for (const event of aes) {
|
|
402
|
-
|
|
420
|
+
const portable = isPortableTelexRecord(event);
|
|
421
|
+
const kind = portable ? event.kind : event?.value?.type;
|
|
422
|
+
if (kind !== 'SeparatorLiteral')
|
|
403
423
|
continue;
|
|
404
|
-
const payload =
|
|
424
|
+
const payload = portable
|
|
425
|
+
? (typeof event.value === 'string' ? event.value : '')
|
|
426
|
+
: (typeof event.value.value === 'string' ? event.value.value : '');
|
|
405
427
|
if (payload.length === 0)
|
|
406
428
|
continue;
|
|
407
|
-
const separators = decodeSeparatorChars(
|
|
429
|
+
const separators = decodeSeparatorChars(portable
|
|
430
|
+
? portableDatatype(event)
|
|
431
|
+
: (typeof event.datatype === 'string' ? event.datatype : undefined));
|
|
408
432
|
if (separators.length === 0)
|
|
409
433
|
continue;
|
|
410
434
|
const lastChar = payload[payload.length - 1];
|
|
@@ -542,7 +566,7 @@ function checkWorldPolicy(schema, aes, boundPaths, eventsByPath, ctx) {
|
|
|
542
566
|
}
|
|
543
567
|
for (const event of aes) {
|
|
544
568
|
const key = typeof event.key === 'string' ? event.key : '';
|
|
545
|
-
if (key.startsWith('aeon:'))
|
|
569
|
+
if (event.sourcePlane === 'header' || (event.sourcePlane === undefined && key.startsWith('aeon:')))
|
|
546
570
|
continue;
|
|
547
571
|
const path = formatCanonicalPathLocal(event.path);
|
|
548
572
|
if (!boundPaths.has(path))
|
|
@@ -784,6 +808,8 @@ function insertAeosSansaResolvePath(root, path, info) {
|
|
|
784
808
|
}
|
|
785
809
|
}
|
|
786
810
|
current.info = info;
|
|
811
|
+
if (info.identity !== undefined)
|
|
812
|
+
current.identity = info.identity;
|
|
787
813
|
}
|
|
788
814
|
function getOrCreateChildBinding(parent, path, identity) {
|
|
789
815
|
const existing = parent.children.find((child) => identity.name !== undefined
|
|
@@ -1017,14 +1043,6 @@ function validateAttributeEntry(path, entry, constraints, datatypeRules, ctx) {
|
|
|
1017
1043
|
validateAttributeMap(path, entry.attributes, effectiveConstraints, datatypeRules, ctx);
|
|
1018
1044
|
}
|
|
1019
1045
|
}
|
|
1020
|
-
function datatypeBase(datatype) {
|
|
1021
|
-
const genericIdx = datatype.indexOf('<');
|
|
1022
|
-
const separatorIdx = datatype.indexOf('[');
|
|
1023
|
-
const endIdx = [genericIdx, separatorIdx]
|
|
1024
|
-
.filter((idx) => idx >= 0)
|
|
1025
|
-
.reduce((min, idx) => Math.min(min, idx), datatype.length);
|
|
1026
|
-
return datatype.slice(0, endIdx);
|
|
1027
|
-
}
|
|
1028
1046
|
function mergeDatatypeRuleConstraints(constraints, datatype, datatypeRules) {
|
|
1029
1047
|
if (!datatype || !datatypeRules)
|
|
1030
1048
|
return constraints;
|
|
@@ -1158,15 +1176,6 @@ function radixConstraintMatches(datatype, raw, constraints) {
|
|
|
1158
1176
|
return false;
|
|
1159
1177
|
return firstInvalidRadixDigit(raw, constraints.radix) === null;
|
|
1160
1178
|
}
|
|
1161
|
-
function declaredRadixFromDatatype(datatype) {
|
|
1162
|
-
if (datatype === undefined)
|
|
1163
|
-
return null;
|
|
1164
|
-
const match = /^radix(?:\[(\d+)\]|(\d+))$/i.exec(datatype.trim());
|
|
1165
|
-
if (!match)
|
|
1166
|
-
return null;
|
|
1167
|
-
const value = Number(match[1] ?? match[2]);
|
|
1168
|
-
return Number.isInteger(value) && value >= 0 ? value : null;
|
|
1169
|
-
}
|
|
1170
1179
|
function isStringType(type) {
|
|
1171
1180
|
return type === 'StringLiteral'
|
|
1172
1181
|
|| type === 'TrimtickLiteral'
|
|
@@ -1178,7 +1187,7 @@ function isStringType(type) {
|
|
|
1178
1187
|
|| type === 'DateLiteral'
|
|
1179
1188
|
|| type === 'TimeLiteral'
|
|
1180
1189
|
|| type === 'DateTimeLiteral'
|
|
1181
|
-
|| type === '
|
|
1190
|
+
|| type === 'WTCDateTimeLiteral';
|
|
1182
1191
|
}
|
|
1183
1192
|
function countFormDigits(type, raw) {
|
|
1184
1193
|
if (type === 'NumberLiteral')
|
|
@@ -1222,7 +1231,159 @@ function isNegative(raw) {
|
|
|
1222
1231
|
function isFormNegative(raw) {
|
|
1223
1232
|
return /^[$#%^]?-/.test(raw) || raw.startsWith('-');
|
|
1224
1233
|
}
|
|
1234
|
+
function isPortableTelexRecord(value) {
|
|
1235
|
+
if (value === null || typeof value !== 'object')
|
|
1236
|
+
return false;
|
|
1237
|
+
const record = value;
|
|
1238
|
+
return typeof record.path === 'string' && typeof record.kind === 'string' && record.header === undefined;
|
|
1239
|
+
}
|
|
1240
|
+
function portableDatatype(record) {
|
|
1241
|
+
if (typeof record.datatype !== 'string')
|
|
1242
|
+
return undefined;
|
|
1243
|
+
if (!Array.isArray(record.generics) || !Array.isArray(record.clarifiers))
|
|
1244
|
+
return record.datatype;
|
|
1245
|
+
return formatDatatypeDescriptor({
|
|
1246
|
+
datatype: record.datatype,
|
|
1247
|
+
generics: record.generics,
|
|
1248
|
+
clarifiers: record.clarifiers,
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
function parsePortablePath(path) {
|
|
1252
|
+
if (!path.startsWith('$'))
|
|
1253
|
+
throw new TypeError(`Expected absolute portable AES path: ${path}`);
|
|
1254
|
+
const segments = [];
|
|
1255
|
+
const prefixes = [];
|
|
1256
|
+
let cursor = 1;
|
|
1257
|
+
while (cursor < path.length) {
|
|
1258
|
+
const start = cursor;
|
|
1259
|
+
let type;
|
|
1260
|
+
if (path.startsWith('.@.', cursor)) {
|
|
1261
|
+
type = 'attribute';
|
|
1262
|
+
cursor += 3;
|
|
1263
|
+
}
|
|
1264
|
+
else if (path[cursor] === '.') {
|
|
1265
|
+
type = 'member';
|
|
1266
|
+
cursor += 1;
|
|
1267
|
+
}
|
|
1268
|
+
else if (path[cursor] === '[') {
|
|
1269
|
+
const match = path.slice(cursor).match(/^\[(0|[1-9][0-9]*)\]/u);
|
|
1270
|
+
if (match === null)
|
|
1271
|
+
throw new TypeError(`Invalid portable AES index: ${path}`);
|
|
1272
|
+
cursor += match[0].length;
|
|
1273
|
+
segments.push({ type: 'index', index: Number(match[1]) });
|
|
1274
|
+
prefixes.push(path.slice(0, cursor));
|
|
1275
|
+
continue;
|
|
1276
|
+
}
|
|
1277
|
+
else {
|
|
1278
|
+
throw new TypeError(`Invalid portable AES path: ${path}`);
|
|
1279
|
+
}
|
|
1280
|
+
let key;
|
|
1281
|
+
if (path[cursor] === '[' && path[cursor + 1] === '"') {
|
|
1282
|
+
let end = cursor + 2;
|
|
1283
|
+
let escaped = false;
|
|
1284
|
+
for (; end < path.length; end += 1) {
|
|
1285
|
+
const character = path[end];
|
|
1286
|
+
if (escaped)
|
|
1287
|
+
escaped = false;
|
|
1288
|
+
else if (character === '\\')
|
|
1289
|
+
escaped = true;
|
|
1290
|
+
else if (character === '"')
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1293
|
+
if (path[end] !== '"' || path[end + 1] !== ']')
|
|
1294
|
+
throw new TypeError(`Invalid quoted member: ${path}`);
|
|
1295
|
+
key = JSON.parse(path.slice(cursor + 1, end + 1));
|
|
1296
|
+
cursor = end + 2;
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
const match = path.slice(cursor).match(/^[A-Za-z_][A-Za-z0-9_]*/u);
|
|
1300
|
+
if (match === null)
|
|
1301
|
+
throw new TypeError(`Invalid portable AES member: ${path}`);
|
|
1302
|
+
key = match[0];
|
|
1303
|
+
cursor += key.length;
|
|
1304
|
+
}
|
|
1305
|
+
segments.push({ type, key });
|
|
1306
|
+
prefixes.push(path.slice(0, cursor));
|
|
1307
|
+
if (cursor === start)
|
|
1308
|
+
throw new TypeError(`Invalid portable AES path: ${path}`);
|
|
1309
|
+
}
|
|
1310
|
+
return { segments, prefixes };
|
|
1311
|
+
}
|
|
1312
|
+
function parsePortableReferencePath(path) {
|
|
1313
|
+
return parsePortablePath(path).segments.map((segment) => {
|
|
1314
|
+
if (segment.type === 'index')
|
|
1315
|
+
return segment.index;
|
|
1316
|
+
if (segment.type === 'attribute')
|
|
1317
|
+
return { type: 'attr', key: segment.key };
|
|
1318
|
+
return segment.key;
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
function hydratePortableAttributes(eventsByPath, aes) {
|
|
1322
|
+
const attributes = aes
|
|
1323
|
+
.filter(isPortableTelexRecord)
|
|
1324
|
+
.map((record) => {
|
|
1325
|
+
try {
|
|
1326
|
+
return { record, details: parsePortablePath(record.path) };
|
|
1327
|
+
}
|
|
1328
|
+
catch {
|
|
1329
|
+
return null;
|
|
1330
|
+
}
|
|
1331
|
+
})
|
|
1332
|
+
.filter((entry) => entry !== null)
|
|
1333
|
+
.filter(({ details }) => details.segments.at(-1)?.type === 'attribute')
|
|
1334
|
+
.sort((a, b) => a.details.segments.length - b.details.segments.length);
|
|
1335
|
+
for (const { record, details } of attributes) {
|
|
1336
|
+
const final = details.segments.at(-1);
|
|
1337
|
+
if (final?.type !== 'attribute')
|
|
1338
|
+
continue;
|
|
1339
|
+
const ownerPath = details.prefixes.at(-2) ?? '$';
|
|
1340
|
+
const owner = eventsByPath.get(ownerPath);
|
|
1341
|
+
const attribute = eventsByPath.get(record.path);
|
|
1342
|
+
if (owner === undefined || attribute === undefined)
|
|
1343
|
+
continue;
|
|
1344
|
+
const mapped = new Map(owner.attributes ?? []);
|
|
1345
|
+
mapped.set(final.key, attribute);
|
|
1346
|
+
owner.attributes = mapped;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
function hydratePortableContainerArities(aes, containerArity, resourcePolicy, ctx, toTuple) {
|
|
1350
|
+
const records = aes.filter(isPortableTelexRecord);
|
|
1351
|
+
if (records.length === 0)
|
|
1352
|
+
return;
|
|
1353
|
+
const details = new Map();
|
|
1354
|
+
for (const record of records) {
|
|
1355
|
+
try {
|
|
1356
|
+
details.set(record.path, parsePortablePath(record.path));
|
|
1357
|
+
}
|
|
1358
|
+
catch {
|
|
1359
|
+
// The portable AES validation layer reports malformed paths.
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
for (const record of records) {
|
|
1363
|
+
if (!['ObjectNode', 'ListNode', 'TupleLiteral', 'NodeLiteral', 'NodeHead'].includes(record.kind))
|
|
1364
|
+
continue;
|
|
1365
|
+
const childOwner = record.kind === 'NodeLiteral' ? `${record.path}[0]` : record.path;
|
|
1366
|
+
let count = 0;
|
|
1367
|
+
for (const candidate of records) {
|
|
1368
|
+
const candidateDetails = details.get(candidate.path);
|
|
1369
|
+
if (candidateDetails === undefined)
|
|
1370
|
+
continue;
|
|
1371
|
+
const parent = candidateDetails.prefixes.at(-2) ?? '$';
|
|
1372
|
+
const last = candidateDetails.segments.at(-1);
|
|
1373
|
+
if (parent !== childOwner || last === undefined)
|
|
1374
|
+
continue;
|
|
1375
|
+
if (record.kind === 'ObjectNode' ? last.type === 'member' : last.type === 'index')
|
|
1376
|
+
count += 1;
|
|
1377
|
+
}
|
|
1378
|
+
containerArity.set(record.path, count);
|
|
1379
|
+
if (count > resourcePolicy.max_container_children_default) {
|
|
1380
|
+
emitResourceError(ctx, record.path, `Container child count ${count} exceeds max_container_children_default ${resourcePolicy.max_container_children_default}`, toTuple(record.span));
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1225
1384
|
function formatCanonicalPathLocal(path) {
|
|
1385
|
+
if (typeof path === 'string')
|
|
1386
|
+
return path;
|
|
1226
1387
|
if (!path || !Array.isArray(path.segments))
|
|
1227
1388
|
return '$';
|
|
1228
1389
|
let result = '';
|
|
@@ -1251,6 +1412,10 @@ function formatCanonicalPathLocal(path) {
|
|
|
1251
1412
|
function toTupleLocal(span) {
|
|
1252
1413
|
if (!span)
|
|
1253
1414
|
return null;
|
|
1415
|
+
if (typeof span === 'string') {
|
|
1416
|
+
const match = span.match(/^(0|[1-9][0-9]*):(0|[1-9][0-9]*)$/u);
|
|
1417
|
+
return match === null ? null : [Number(match[1]), Number(match[2])];
|
|
1418
|
+
}
|
|
1254
1419
|
if (Array.isArray(span) && span.length === 2 && typeof span[0] === 'number')
|
|
1255
1420
|
return span;
|
|
1256
1421
|
if (span.start && span.end && typeof span.start.offset === 'number')
|