@altopelago/aeos-core 0.9.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 (82) hide show
  1. package/README.md +143 -0
  2. package/dist/bin/aeos-validator.d.ts +16 -0
  3. package/dist/bin/aeos-validator.d.ts.map +1 -0
  4. package/dist/bin/aeos-validator.js +77 -0
  5. package/dist/bin/aeos-validator.js.map +1 -0
  6. package/dist/diag/codes.d.ts +55 -0
  7. package/dist/diag/codes.d.ts.map +1 -0
  8. package/dist/diag/codes.js +69 -0
  9. package/dist/diag/codes.js.map +1 -0
  10. package/dist/diag/emit.d.ts +34 -0
  11. package/dist/diag/emit.d.ts.map +1 -0
  12. package/dist/diag/emit.js +45 -0
  13. package/dist/diag/emit.js.map +1 -0
  14. package/dist/diag/index.d.ts +6 -0
  15. package/dist/diag/index.d.ts.map +1 -0
  16. package/dist/diag/index.js +6 -0
  17. package/dist/diag/index.js.map +1 -0
  18. package/dist/index.d.ts +31 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +31 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/rules/index.d.ts +10 -0
  23. package/dist/rules/index.d.ts.map +1 -0
  24. package/dist/rules/index.js +10 -0
  25. package/dist/rules/index.js.map +1 -0
  26. package/dist/rules/numericForm.d.ts +29 -0
  27. package/dist/rules/numericForm.d.ts.map +1 -0
  28. package/dist/rules/numericForm.js +74 -0
  29. package/dist/rules/numericForm.js.map +1 -0
  30. package/dist/rules/presence.d.ts +20 -0
  31. package/dist/rules/presence.d.ts.map +1 -0
  32. package/dist/rules/presence.js +29 -0
  33. package/dist/rules/presence.js.map +1 -0
  34. package/dist/rules/referenceForm.d.ts +17 -0
  35. package/dist/rules/referenceForm.d.ts.map +1 -0
  36. package/dist/rules/referenceForm.js +78 -0
  37. package/dist/rules/referenceForm.js.map +1 -0
  38. package/dist/rules/schemaIndex.d.ts +34 -0
  39. package/dist/rules/schemaIndex.d.ts.map +1 -0
  40. package/dist/rules/schemaIndex.js +167 -0
  41. package/dist/rules/schemaIndex.js.map +1 -0
  42. package/dist/rules/stringForm.d.ts +48 -0
  43. package/dist/rules/stringForm.d.ts.map +1 -0
  44. package/dist/rules/stringForm.js +96 -0
  45. package/dist/rules/stringForm.js.map +1 -0
  46. package/dist/rules/typeCheck.d.ts +29 -0
  47. package/dist/rules/typeCheck.d.ts.map +1 -0
  48. package/dist/rules/typeCheck.js +99 -0
  49. package/dist/rules/typeCheck.js.map +1 -0
  50. package/dist/types/aes.d.ts +14 -0
  51. package/dist/types/aes.d.ts.map +1 -0
  52. package/dist/types/aes.js +8 -0
  53. package/dist/types/aes.js.map +1 -0
  54. package/dist/types/envelope.d.ts +47 -0
  55. package/dist/types/envelope.d.ts.map +1 -0
  56. package/dist/types/envelope.js +29 -0
  57. package/dist/types/envelope.js.map +1 -0
  58. package/dist/types/index.d.ts +10 -0
  59. package/dist/types/index.d.ts.map +1 -0
  60. package/dist/types/index.js +10 -0
  61. package/dist/types/index.js.map +1 -0
  62. package/dist/types/schema.d.ts +81 -0
  63. package/dist/types/schema.d.ts.map +1 -0
  64. package/dist/types/schema.js +41 -0
  65. package/dist/types/schema.js.map +1 -0
  66. package/dist/types/spans.d.ts +28 -0
  67. package/dist/types/spans.d.ts.map +1 -0
  68. package/dist/types/spans.js +16 -0
  69. package/dist/types/spans.js.map +1 -0
  70. package/dist/util/digits.d.ts +34 -0
  71. package/dist/util/digits.d.ts.map +1 -0
  72. package/dist/util/digits.js +66 -0
  73. package/dist/util/digits.js.map +1 -0
  74. package/dist/util/index.d.ts +5 -0
  75. package/dist/util/index.d.ts.map +1 -0
  76. package/dist/util/index.js +5 -0
  77. package/dist/util/index.js.map +1 -0
  78. package/dist/validate.d.ts +46 -0
  79. package/dist/validate.d.ts.map +1 -0
  80. package/dist/validate.js +633 -0
  81. package/dist/validate.js.map +1 -0
  82. package/package.json +33 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: Numeric Form
3
+ *
4
+ * Phase 6: Numeric form constraints (sign, digit count).
5
+ */
6
+ import { createDiag, emitError } from '../diag/emit.js';
7
+ import { ErrorCodes } from '../diag/codes.js';
8
+ import { countIntegerDigits, isNegative } from '../util/digits.js';
9
+ /**
10
+ * Check numeric form constraints for events matching schema rules.
11
+ *
12
+ * For each event with numeric form constraints (sign, min_digits, max_digits),
13
+ * verify the literal's lexical representation satisfies the constraints.
14
+ *
15
+ * @param ruleIndex - Schema rule index (path → rule)
16
+ * @param events - Map of path → numeric value info
17
+ * @param ctx - Diagnostic context
18
+ */
19
+ export function checkNumericForm(ruleIndex, events, ctx) {
20
+ for (const [path, rule] of ruleIndex) {
21
+ const { sign, min_digits, max_digits, min_value, max_value } = rule.constraints;
22
+ // Skip if no numeric form constraints
23
+ if (sign === undefined && min_digits === undefined && max_digits === undefined && min_value === undefined && max_value === undefined) {
24
+ continue;
25
+ }
26
+ const event = events.get(path);
27
+ if (!event)
28
+ continue; // Missing path handled by presence check
29
+ // Only apply to numeric types
30
+ if (event.type !== 'NumberLiteral' && event.type !== 'IntegerLiteral' && event.type !== 'FloatLiteral') {
31
+ continue;
32
+ }
33
+ const raw = event.raw;
34
+ // Sign constraint
35
+ if (sign !== undefined) {
36
+ if (sign === 'unsigned' && isNegative(raw)) {
37
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: expected unsigned, got negative`, ErrorCodes.NUMERIC_FORM_VIOLATION));
38
+ continue; // Only report first violation per path
39
+ }
40
+ // 'signed' constraint allows both positive and negative
41
+ }
42
+ // Digit count constraints
43
+ const digitCount = countIntegerDigits(raw);
44
+ if (min_digits !== undefined && digitCount < min_digits) {
45
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: expected min ${min_digits} digits, got ${digitCount}`, ErrorCodes.NUMERIC_FORM_VIOLATION));
46
+ continue;
47
+ }
48
+ if (max_digits !== undefined && digitCount > max_digits) {
49
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: expected max ${max_digits} digits, got ${digitCount}`, ErrorCodes.NUMERIC_FORM_VIOLATION));
50
+ continue;
51
+ }
52
+ if (min_value !== undefined || max_value !== undefined) {
53
+ const normalized = normalizeIntegerLiteral(raw);
54
+ if (!normalized) {
55
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: exact integer range constraints require integer literal form`, ErrorCodes.NUMERIC_FORM_VIOLATION));
56
+ continue;
57
+ }
58
+ const numeric = BigInt(normalized);
59
+ if (min_value !== undefined && numeric < BigInt(min_value)) {
60
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: expected value >= ${min_value}, got ${normalized}`, ErrorCodes.NUMERIC_FORM_VIOLATION));
61
+ continue;
62
+ }
63
+ if (max_value !== undefined && numeric > BigInt(max_value)) {
64
+ emitError(ctx, createDiag(path, event.span, `Numeric form violation: expected value <= ${max_value}, got ${normalized}`, ErrorCodes.NUMERIC_FORM_VIOLATION));
65
+ }
66
+ }
67
+ }
68
+ }
69
+ function normalizeIntegerLiteral(raw) {
70
+ if (!/^[+-]?\d[\d_]*$/.test(raw))
71
+ return null;
72
+ return raw.replace(/_/g, '');
73
+ }
74
+ //# sourceMappingURL=numericForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numericForm.js","sourceRoot":"","sources":["../../src/rules/numericForm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: Presence
3
+ *
4
+ * Phase 4: Presence checks for required fields.
5
+ */
6
+ import type { DiagContext } from '../diag/emit.js';
7
+ import type { RuleIndex } from './schemaIndex.js';
8
+ /**
9
+ * Check presence constraints for all rules in the schema.
10
+ *
11
+ * For each rule with `required: true`, verify the path exists in the AES.
12
+ * If missing, emit `missing_required_field` error with null span
13
+ * (since the path doesn't exist in source).
14
+ *
15
+ * @param ruleIndex - Schema rule index (path → rule)
16
+ * @param boundPaths - Set of paths that exist in the AES
17
+ * @param ctx - Diagnostic context
18
+ */
19
+ export declare function checkPresence(ruleIndex: RuleIndex, boundPaths: ReadonlySet<string>, ctx: DiagContext): void;
20
+ //# sourceMappingURL=presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../../src/rules/presence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CACzB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,GAAG,EAAE,WAAW,GACjB,IAAI,CAaN"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: Presence
3
+ *
4
+ * Phase 4: Presence checks for required fields.
5
+ */
6
+ import { createDiag, emitError } from '../diag/emit.js';
7
+ import { ErrorCodes } from '../diag/codes.js';
8
+ /**
9
+ * Check presence constraints for all rules in the schema.
10
+ *
11
+ * For each rule with `required: true`, verify the path exists in the AES.
12
+ * If missing, emit `missing_required_field` error with null span
13
+ * (since the path doesn't exist in source).
14
+ *
15
+ * @param ruleIndex - Schema rule index (path → rule)
16
+ * @param boundPaths - Set of paths that exist in the AES
17
+ * @param ctx - Diagnostic context
18
+ */
19
+ export function checkPresence(ruleIndex, boundPaths, ctx) {
20
+ for (const [path, rule] of ruleIndex) {
21
+ if (rule.constraints.required === true) {
22
+ if (!boundPaths.has(path)) {
23
+ emitError(ctx, createDiag(path, null, // null span for missing paths
24
+ `Missing required field: ${path}`, ErrorCodes.MISSING_REQUIRED_FIELD));
25
+ }
26
+ }
27
+ }
28
+ }
29
+ //# sourceMappingURL=presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/rules/presence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CACzB,SAAoB,EACpB,UAA+B,EAC/B,GAAgB;IAEhB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,SAAS,CAAC,GAAG,EAAE,UAAU,CACrB,IAAI,EACJ,IAAI,EAAE,8BAA8B;gBACpC,2BAA2B,IAAI,EAAE,EACjC,UAAU,CAAC,sBAAsB,CACpC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { type DiagContext } from '../diag/emit.js';
2
+ import type { RuleIndex } from './schemaIndex.js';
3
+ import type { SchemaV1 } from '../types/schema.js';
4
+ type EventInfo = {
5
+ type: string;
6
+ raw: string;
7
+ value: string;
8
+ datatype?: string;
9
+ span: [number, number] | null;
10
+ referencePath?: readonly (string | number | {
11
+ readonly type: 'attr';
12
+ readonly key: string;
13
+ })[];
14
+ };
15
+ export declare function checkReferenceForms(schema: SchemaV1, ruleIndex: RuleIndex, eventsByPath: ReadonlyMap<string, EventInfo>, ctx: DiagContext): void;
16
+ export {};
17
+ //# sourceMappingURL=referenceForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceForm.d.ts","sourceRoot":"","sources":["../../src/rules/referenceForm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,KAAK,SAAS,GAAG;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CAClG,CAAC;AA+BF,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,QAAQ,EAChB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,EAC5C,GAAG,EAAE,WAAW,GACjB,IAAI,CAyEN"}
@@ -0,0 +1,78 @@
1
+ import { createDiag, emitError } from '../diag/emit.js';
2
+ import { ErrorCodes } from '../diag/codes.js';
3
+ function isReferenceType(type) {
4
+ return type === 'CloneReference' || type === 'PointerReference';
5
+ }
6
+ function formatQuotedMemberSegment(key) {
7
+ return `.[${JSON.stringify(key)}]`;
8
+ }
9
+ function formatReferenceTargetPath(segments) {
10
+ if (segments.length === 0)
11
+ return '$';
12
+ let out = '$';
13
+ for (const segment of segments) {
14
+ if (typeof segment === 'number') {
15
+ out += `[${segment}]`;
16
+ continue;
17
+ }
18
+ if (typeof segment === 'string') {
19
+ out += /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(segment)
20
+ ? `.${segment}`
21
+ : formatQuotedMemberSegment(segment);
22
+ continue;
23
+ }
24
+ out += /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(segment.key)
25
+ ? `@${segment.key}`
26
+ : `@[${JSON.stringify(segment.key)}]`;
27
+ }
28
+ return out;
29
+ }
30
+ export function checkReferenceForms(schema, ruleIndex, eventsByPath, ctx) {
31
+ if ((schema.reference_policy ?? 'allow') === 'forbid') {
32
+ for (const [path, event] of eventsByPath.entries()) {
33
+ if (!isReferenceType(event.type))
34
+ continue;
35
+ emitError(ctx, createDiag(path, event.span, `References are forbidden by schema reference_policy, got ${event.type}`, ErrorCodes.REFERENCE_FORBIDDEN));
36
+ }
37
+ }
38
+ for (const [path, rule] of ruleIndex) {
39
+ const reference = rule.constraints.reference;
40
+ const referenceKind = rule.constraints.reference_kind;
41
+ const event = eventsByPath.get(path);
42
+ if (!event)
43
+ continue;
44
+ if (reference === 'forbid') {
45
+ if (!isReferenceType(event.type))
46
+ continue;
47
+ emitError(ctx, createDiag(path, event.span, `Reference not allowed at ${path}, got ${event.type}`, ErrorCodes.REFERENCE_FORBIDDEN));
48
+ continue;
49
+ }
50
+ if (reference === 'allow' || reference === undefined) {
51
+ // Allow still permits target-domain constraints.
52
+ }
53
+ else if (reference === 'require') {
54
+ if (!isReferenceType(event.type)) {
55
+ emitError(ctx, createDiag(path, event.span, `Reference required at ${path}, got ${event.type}`, ErrorCodes.REFERENCE_REQUIRED));
56
+ continue;
57
+ }
58
+ if (referenceKind !== undefined && referenceKind !== 'either') {
59
+ const expectedType = referenceKind === 'clone' ? 'CloneReference' : 'PointerReference';
60
+ if (event.type !== expectedType) {
61
+ emitError(ctx, createDiag(path, event.span, `Reference kind mismatch at ${path}: expected ${expectedType}, got ${event.type}`, ErrorCodes.REFERENCE_KIND_MISMATCH));
62
+ continue;
63
+ }
64
+ }
65
+ }
66
+ const targetPattern = rule.constraints.reference_target_pattern;
67
+ if (targetPattern === undefined) {
68
+ continue;
69
+ }
70
+ if (!isReferenceType(event.type) || !event.referencePath) {
71
+ continue;
72
+ }
73
+ if (!(new RegExp(targetPattern).test(formatReferenceTargetPath(event.referencePath)))) {
74
+ emitError(ctx, createDiag(path, event.span, `Reference target path does not satisfy reference_target_pattern at ${path}`, ErrorCodes.REFERENCE_TARGET_MISMATCH));
75
+ }
76
+ }
77
+ }
78
+ //# sourceMappingURL=referenceForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceForm.js","sourceRoot":"","sources":["../../src/rules/referenceForm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: Schema Index
3
+ *
4
+ * Build a fast lookup index from schema rules.
5
+ */
6
+ import type { SchemaV1, SchemaRule } from '../types/schema.js';
7
+ import type { DiagContext } from '../diag/emit.js';
8
+ /**
9
+ * Rule index: Map from canonical path to rule
10
+ */
11
+ export type RuleIndex = ReadonlyMap<string, SchemaRule>;
12
+ /**
13
+ * Build a rule index from a schema.
14
+ *
15
+ * This preprocesses schema.rules into a Map<path, Rule> for O(1) lookup.
16
+ * Emits errors for:
17
+ * - Missing path in rule
18
+ * - Duplicate rule paths
19
+ * - Unknown constraint keys
20
+ *
21
+ * @param schema - AEOS Schema v1
22
+ * @param ctx - Diagnostic context for errors
23
+ * @returns Rule index map
24
+ */
25
+ export declare function buildRuleIndex(schema: SchemaV1, ctx: DiagContext): RuleIndex;
26
+ /**
27
+ * Check if a rule has numeric form constraints
28
+ */
29
+ export declare function hasNumericFormConstraints(constraints: SchemaRule['constraints']): boolean;
30
+ /**
31
+ * Check if a rule has string form constraints
32
+ */
33
+ export declare function hasStringFormConstraints(constraints: SchemaRule['constraints']): boolean;
34
+ //# sourceMappingURL=schemaIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaIndex.d.ts","sourceRoot":"","sources":["../../src/rules/schemaIndex.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAsMnD;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,GAAG,SAAS,CA+D5E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,UAAU,CAAC,aAAa,CAAC,GAAG,OAAO,CAMzF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,UAAU,CAAC,aAAa,CAAC,GAAG,OAAO,CAMxF"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: Schema Index
3
+ *
4
+ * Build a fast lookup index from schema rules.
5
+ */
6
+ import { hasUnknownConstraintKeys } from '../types/schema.js';
7
+ import { createDiag, emitError } from '../diag/emit.js';
8
+ import { ErrorCodes } from '../diag/codes.js';
9
+ function isReferenceType(type) {
10
+ return type === 'CloneReference' || type === 'PointerReference';
11
+ }
12
+ function validateReferenceConstraints(schema, rulePath, constraints, ctx) {
13
+ const reference = constraints.reference;
14
+ const referenceKind = constraints.reference_kind;
15
+ const referenceTargetPattern = constraints.reference_target_pattern;
16
+ const resolveReferenceForm = constraints.resolve_reference_form;
17
+ const expectedType = typeof constraints.type === 'string' ? constraints.type : undefined;
18
+ const schemaReferencePolicy = schema.reference_policy;
19
+ if (reference !== undefined && (typeof reference !== 'string' || !['allow', 'forbid', 'require'].includes(reference))) {
20
+ emitError(ctx, createDiag(rulePath, null, `Invalid reference constraint for path ${rulePath}: ${String(reference)}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
21
+ return false;
22
+ }
23
+ if (referenceKind !== undefined && (typeof referenceKind !== 'string' || !['clone', 'pointer', 'either'].includes(referenceKind))) {
24
+ emitError(ctx, createDiag(rulePath, null, `Invalid reference_kind constraint for path ${rulePath}: ${String(referenceKind)}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
25
+ return false;
26
+ }
27
+ if (referenceKind !== undefined && reference !== 'require') {
28
+ emitError(ctx, createDiag(rulePath, null, `reference_kind requires reference='require' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
29
+ return false;
30
+ }
31
+ if (referenceTargetPattern !== undefined) {
32
+ if (typeof referenceTargetPattern !== 'string') {
33
+ emitError(ctx, createDiag(rulePath, null, `Invalid reference_target_pattern constraint for path ${rulePath}: ${String(referenceTargetPattern)}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
34
+ return false;
35
+ }
36
+ try {
37
+ new RegExp(referenceTargetPattern);
38
+ }
39
+ catch {
40
+ emitError(ctx, createDiag(rulePath, null, `Invalid reference_target_pattern regex for path ${rulePath}: ${referenceTargetPattern}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
41
+ return false;
42
+ }
43
+ if (reference === 'forbid') {
44
+ emitError(ctx, createDiag(rulePath, null, `reference_target_pattern conflicts with reference='forbid' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
45
+ return false;
46
+ }
47
+ }
48
+ if (resolveReferenceForm !== undefined && typeof resolveReferenceForm !== 'boolean') {
49
+ emitError(ctx, createDiag(rulePath, null, `resolve_reference_form must be boolean for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
50
+ return false;
51
+ }
52
+ if (reference === 'forbid' && expectedType !== undefined && isReferenceType(expectedType)) {
53
+ emitError(ctx, createDiag(rulePath, null, `reference='forbid' conflicts with type='${expectedType}' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
54
+ return false;
55
+ }
56
+ if (reference === 'require' && expectedType !== undefined && !isReferenceType(expectedType)) {
57
+ emitError(ctx, createDiag(rulePath, null, `reference='require' conflicts with non-reference type='${expectedType}' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
58
+ return false;
59
+ }
60
+ if (referenceKind === 'clone' && expectedType === 'PointerReference') {
61
+ emitError(ctx, createDiag(rulePath, null, `reference_kind='clone' conflicts with type='PointerReference' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
62
+ return false;
63
+ }
64
+ if (referenceKind === 'pointer' && expectedType === 'CloneReference') {
65
+ emitError(ctx, createDiag(rulePath, null, `reference_kind='pointer' conflicts with type='CloneReference' for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
66
+ return false;
67
+ }
68
+ if (schemaReferencePolicy === 'forbid' && (reference === 'require' || (expectedType !== undefined && isReferenceType(expectedType)))) {
69
+ emitError(ctx, createDiag(rulePath, null, `schema reference_policy='forbid' conflicts with rule for path ${rulePath}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
70
+ return false;
71
+ }
72
+ return true;
73
+ }
74
+ function validateConstraintTree(schema, rulePath, constraints, ctx) {
75
+ if (hasUnknownConstraintKeys(constraints)) {
76
+ emitError(ctx, createDiag(rulePath, null, `Unknown constraint key in rule for path: ${rulePath}`, ErrorCodes.UNKNOWN_CONSTRAINT_KEY));
77
+ return false;
78
+ }
79
+ if (!validateReferenceConstraints(schema, rulePath, constraints, ctx)) {
80
+ return false;
81
+ }
82
+ const nestedAttributes = constraints.attributes;
83
+ if (nestedAttributes === undefined) {
84
+ return true;
85
+ }
86
+ if (nestedAttributes === null || typeof nestedAttributes !== 'object' || Array.isArray(nestedAttributes)) {
87
+ emitError(ctx, createDiag(rulePath, null, `Invalid attributes constraint for path ${rulePath}`, ErrorCodes.UNKNOWN_CONSTRAINT_KEY));
88
+ return false;
89
+ }
90
+ for (const [key, childConstraints] of Object.entries(nestedAttributes)) {
91
+ if (childConstraints === null || typeof childConstraints !== 'object' || Array.isArray(childConstraints)) {
92
+ emitError(ctx, createDiag(`${rulePath}@${key}`, null, `Invalid attribute constraint for path ${rulePath}@${key}`, ErrorCodes.UNKNOWN_CONSTRAINT_KEY));
93
+ return false;
94
+ }
95
+ if (!validateConstraintTree(schema, `${rulePath}@${key}`, childConstraints, ctx)) {
96
+ return false;
97
+ }
98
+ }
99
+ return true;
100
+ }
101
+ /**
102
+ * Build a rule index from a schema.
103
+ *
104
+ * This preprocesses schema.rules into a Map<path, Rule> for O(1) lookup.
105
+ * Emits errors for:
106
+ * - Missing path in rule
107
+ * - Duplicate rule paths
108
+ * - Unknown constraint keys
109
+ *
110
+ * @param schema - AEOS Schema v1
111
+ * @param ctx - Diagnostic context for errors
112
+ * @returns Rule index map
113
+ */
114
+ export function buildRuleIndex(schema, ctx) {
115
+ const index = new Map();
116
+ // Schema-level allowlist for datatype identifiers (optional)
117
+ const datatypeAllowlist = schema.datatype_allowlist;
118
+ if (schema.reference_policy !== undefined && !['allow', 'forbid'].includes(schema.reference_policy)) {
119
+ emitError(ctx, createDiag('$', null, `Invalid schema reference_policy: ${String(schema.reference_policy)}`, ErrorCodes.INVALID_REFERENCE_CONSTRAINT));
120
+ }
121
+ for (const rule of schema.rules) {
122
+ // Check for missing path
123
+ if (!rule.path || typeof rule.path !== 'string') {
124
+ emitError(ctx, createDiag('<unknown>', null, 'Rule missing required "path" field', ErrorCodes.RULE_MISSING_PATH));
125
+ continue;
126
+ }
127
+ // Check for duplicate rule paths
128
+ if (index.has(rule.path)) {
129
+ emitError(ctx, createDiag(rule.path, null, `Duplicate rule for path: ${rule.path}`, ErrorCodes.DUPLICATE_RULE_PATH));
130
+ continue;
131
+ }
132
+ if (!validateConstraintTree(schema, rule.path, rule.constraints, ctx)) {
133
+ continue;
134
+ }
135
+ // Enforce datatype allow-list if provided at schema level.
136
+ // This is a form-only membership check: the `datatype` string
137
+ // must be present in the schema.datatype_allowlist array when
138
+ // that array is provided. Emit a value-level diagnostic code
139
+ // to indicate the identifier is not allowed.
140
+ if (datatypeAllowlist && rule.constraints && typeof rule.constraints.datatype === 'string') {
141
+ const dt = rule.constraints.datatype;
142
+ if (!datatypeAllowlist.includes(dt)) {
143
+ emitError(ctx, createDiag(rule.path, null, `Datatype '${dt}' not allowed by schema datatype_allowlist`, ErrorCodes.DATATYPE_ALLOWLIST_REJECT));
144
+ // continue; still index the rule so other checks can run
145
+ }
146
+ }
147
+ index.set(rule.path, rule);
148
+ }
149
+ return index;
150
+ }
151
+ /**
152
+ * Check if a rule has numeric form constraints
153
+ */
154
+ export function hasNumericFormConstraints(constraints) {
155
+ return (constraints.sign !== undefined ||
156
+ constraints.min_digits !== undefined ||
157
+ constraints.max_digits !== undefined);
158
+ }
159
+ /**
160
+ * Check if a rule has string form constraints
161
+ */
162
+ export function hasStringFormConstraints(constraints) {
163
+ return (constraints.pattern !== undefined ||
164
+ constraints.min_length !== undefined ||
165
+ constraints.max_length !== undefined);
166
+ }
167
+ //# sourceMappingURL=schemaIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaIndex.js","sourceRoot":"","sources":["../../src/rules/schemaIndex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: String Form
3
+ *
4
+ * Phase 7: String form constraints (min_length, max_length, pattern).
5
+ */
6
+ import type { DiagContext } from '../diag/emit.js';
7
+ import type { Span } from '../types/spans.js';
8
+ import type { RuleIndex } from './schemaIndex.js';
9
+ /**
10
+ * Event value with type, processed value string, and span
11
+ */
12
+ interface StringValue {
13
+ type: string;
14
+ value: string;
15
+ span: Span;
16
+ }
17
+ /**
18
+ * Check string form constraints for events matching schema rules.
19
+ *
20
+ * For each event with string form constraints (min_length, max_length),
21
+ * verify the string value's length satisfies the constraints.
22
+ *
23
+ * AEOS v1 Decision: Length is measured in UTF-16 code units (JavaScript
24
+ * string.length). This means surrogate pairs (emoji, etc.) count as 2.
25
+ * This is intentional for v1 simplicity and JavaScript compatibility.
26
+ *
27
+ * @param ruleIndex - Schema rule index (path → rule)
28
+ * @param events - Map of path → string value info
29
+ * @param ctx - Diagnostic context
30
+ */
31
+ export declare function checkStringForm(ruleIndex: RuleIndex, events: ReadonlyMap<string, StringValue>, ctx: DiagContext): void;
32
+ /**
33
+ * Check pattern constraints for events matching schema rules.
34
+ *
35
+ * For each event with a pattern constraint, verify the string value
36
+ * matches the regex pattern.
37
+ *
38
+ * AEOS v1 Decision: Patterns are ECMAScript regex strings. The pattern
39
+ * must match the entire string (anchored with ^...$). If the pattern
40
+ * does not include anchors, they are added automatically.
41
+ *
42
+ * @param ruleIndex - Schema rule index (path → rule)
43
+ * @param events - Map of path → string value info
44
+ * @param ctx - Diagnostic context
45
+ */
46
+ export declare function checkPatterns(ruleIndex: RuleIndex, events: ReadonlyMap<string, StringValue>, ctx: DiagContext): void;
47
+ export {};
48
+ //# sourceMappingURL=stringForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringForm.d.ts","sourceRoot":"","sources":["../../src/rules/stringForm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC3B,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,GAAG,EAAE,WAAW,GACjB,IAAI,CAwCN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CACzB,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,GAAG,EAAE,WAAW,GACjB,IAAI,CA2CN"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @altopelago/aeos-core - Rules: String Form
3
+ *
4
+ * Phase 7: String form constraints (min_length, max_length, pattern).
5
+ */
6
+ import { createDiag, emitError } from '../diag/emit.js';
7
+ import { ErrorCodes } from '../diag/codes.js';
8
+ /**
9
+ * Check string form constraints for events matching schema rules.
10
+ *
11
+ * For each event with string form constraints (min_length, max_length),
12
+ * verify the string value's length satisfies the constraints.
13
+ *
14
+ * AEOS v1 Decision: Length is measured in UTF-16 code units (JavaScript
15
+ * string.length). This means surrogate pairs (emoji, etc.) count as 2.
16
+ * This is intentional for v1 simplicity and JavaScript compatibility.
17
+ *
18
+ * @param ruleIndex - Schema rule index (path → rule)
19
+ * @param events - Map of path → string value info
20
+ * @param ctx - Diagnostic context
21
+ */
22
+ export function checkStringForm(ruleIndex, events, ctx) {
23
+ for (const [path, rule] of ruleIndex) {
24
+ const { min_length, max_length, pattern } = rule.constraints;
25
+ // Skip if no string length or pattern constraints
26
+ if (min_length === undefined && max_length === undefined && pattern === undefined) {
27
+ continue;
28
+ }
29
+ const event = events.get(path);
30
+ if (!event)
31
+ continue; // Missing path handled by presence check
32
+ // Only apply to string types
33
+ if (event.type !== 'StringLiteral') {
34
+ continue;
35
+ }
36
+ const length = event.value.length;
37
+ if (min_length !== undefined && length < min_length) {
38
+ emitError(ctx, createDiag(path, event.span, `String form violation: expected min length ${min_length}, got ${length}`, ErrorCodes.STRING_LENGTH_VIOLATION));
39
+ continue; // Only report first violation per path
40
+ }
41
+ if (max_length !== undefined && length > max_length) {
42
+ emitError(ctx, createDiag(path, event.span, `String form violation: expected max length ${max_length}, got ${length}`, ErrorCodes.STRING_LENGTH_VIOLATION));
43
+ }
44
+ // Note: pattern enforcement is handled separately in `checkPatterns()`.
45
+ }
46
+ }
47
+ /**
48
+ * Check pattern constraints for events matching schema rules.
49
+ *
50
+ * For each event with a pattern constraint, verify the string value
51
+ * matches the regex pattern.
52
+ *
53
+ * AEOS v1 Decision: Patterns are ECMAScript regex strings. The pattern
54
+ * must match the entire string (anchored with ^...$). If the pattern
55
+ * does not include anchors, they are added automatically.
56
+ *
57
+ * @param ruleIndex - Schema rule index (path → rule)
58
+ * @param events - Map of path → string value info
59
+ * @param ctx - Diagnostic context
60
+ */
61
+ export function checkPatterns(ruleIndex, events, ctx) {
62
+ for (const [path, rule] of ruleIndex) {
63
+ const { pattern } = rule.constraints;
64
+ if (pattern === undefined) {
65
+ continue;
66
+ }
67
+ const event = events.get(path);
68
+ if (!event)
69
+ continue; // Missing path handled by presence check
70
+ // Only apply to string types
71
+ if (event.type !== 'StringLiteral') {
72
+ continue;
73
+ }
74
+ // Compile pattern (add anchors if not present for full-match semantics)
75
+ let regexPattern = pattern;
76
+ if (!regexPattern.startsWith('^')) {
77
+ regexPattern = '^' + regexPattern;
78
+ }
79
+ if (!regexPattern.endsWith('$')) {
80
+ regexPattern = regexPattern + '$';
81
+ }
82
+ let regex;
83
+ try {
84
+ regex = new RegExp(regexPattern);
85
+ }
86
+ catch {
87
+ // Invalid regex is a schema error, not a data error
88
+ // This should have been caught during schema validation
89
+ continue;
90
+ }
91
+ if (!regex.test(event.value)) {
92
+ emitError(ctx, createDiag(path, event.span, `Pattern mismatch: value does not match pattern "${pattern}"`, ErrorCodes.PATTERN_MISMATCH));
93
+ }
94
+ }
95
+ }
96
+ //# sourceMappingURL=stringForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringForm.js","sourceRoot":"","sources":["../../src/rules/stringForm.ts"],"names":[],"mappings":"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"}