@xdbml/parse 0.4.0 → 0.5.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.
package/dist/ast.d.ts CHANGED
@@ -38,7 +38,7 @@ export interface ExperimentalDeclaration {
38
38
  features: string[];
39
39
  span: Span;
40
40
  }
41
- export type TopLevelStatement = ProjectDeclaration | ContainerDeclaration | EntityDeclaration | TypeDeclaration | EdgeDeclaration | ViewDeclaration | EnumDeclaration | RefDeclaration | TablePartialDeclaration | TableGroupDeclaration | NoteDeclaration | TopLevelRecordsDeclaration | ModuleImportDirective;
41
+ export type TopLevelStatement = ProjectDeclaration | ContainerDeclaration | EntityDeclaration | TypeDeclaration | EdgeDeclaration | ViewDeclaration | EnumDeclaration | RefDeclaration | TablePartialDeclaration | TableGroupDeclaration | SupertypeGroupDeclaration | NoteDeclaration | TopLevelRecordsDeclaration | ModuleImportDirective;
42
42
  export interface ProjectDeclaration {
43
43
  kind: 'ProjectDeclaration';
44
44
  name: string;
@@ -182,7 +182,7 @@ export interface TypeDeclaration {
182
182
  kind: 'TypeDeclaration';
183
183
  name: string;
184
184
  /**
185
- * v0.2 scalar form (spec §14.7): when present, this Type is an alias
185
+ * v0.2 scalar form (spec §15.7): when present, this Type is an alias
186
186
  * for the given type expression rather than an object-shaped record.
187
187
  * Examples:
188
188
  *
@@ -339,6 +339,21 @@ export interface TableGroupDeclaration {
339
339
  members: string[];
340
340
  span: Span;
341
341
  }
342
+ export interface SupertypeGroupDeclaration {
343
+ kind: 'SupertypeGroupDeclaration';
344
+ name: string;
345
+ settings: Setting[];
346
+ members: SupertypeGroupMember[];
347
+ span: Span;
348
+ }
349
+ export interface SupertypeGroupMember {
350
+ kind: 'SupertypeGroupMember';
351
+ /** Entity path as written: `Person` or `crm.Person`. */
352
+ name: string;
353
+ /** Member settings; `strategy` is the only recognized one (spec §12.7.4). */
354
+ settings: Setting[];
355
+ span: Span;
356
+ }
342
357
  export interface PartialInjection {
343
358
  kind: 'PartialInjection';
344
359
  /** Identifier after the `~`. */
@@ -385,7 +400,7 @@ export interface ModuleImportDirective {
385
400
  /**
386
401
  * Directive mode:
387
402
  * - `'reuse'`: transitive (visible to files that further import this file).
388
- * The recommended default per spec §26.4.
403
+ * The recommended default per spec §27.4.
389
404
  * - `'use'`: non-transitive (private to this file).
390
405
  */
391
406
  mode: 'use' | 'reuse';
@@ -424,9 +439,10 @@ export type ImportSpec = {
424
439
  * type Email as PII_Email
425
440
  * field core.dim_customer.email
426
441
  *
427
- * The element type is one of the keywords from §26.3 (table, entity,
442
+ * The element type is one of the keywords from §27.3 (table, entity,
428
443
  * collection, record, enum, tablepartial, note, schema, container,
429
- * tablegroup, type, edge, view, diagramview, field). Stored lowercased.
444
+ * tablegroup, type, edge, view, diagramview, field, and from v0.5
445
+ * supertypegroup). Stored lowercased.
430
446
  *
431
447
  * The source path follows xDBML's standard dotted form. Container.Entity
432
448
  * for an entity inside a Container; Container.Entity.Field for a field.
@@ -447,7 +463,7 @@ export interface ImportItem {
447
463
  * an entity, type, container, etc. clone). Field imports are not supported
448
464
  * in P4 -- when they land, this type may grow to a wider union.
449
465
  *
450
- * Per spec §26.6, the clone contains exactly the imported declaration(s),
466
+ * Per spec §27.6, the clone contains exactly the imported declaration(s),
451
467
  * without surrounding wrappers from the source file. For an entity clone
452
468
  * the content is the EntityDeclaration alone (no container wrapper); for a
453
469
  * container clone the content is the ContainerDeclaration including its
@@ -459,7 +475,7 @@ export interface CloneBlock {
459
475
  * Statements that the importing file pulls in from the source. Most are
460
476
  * top-level shapes (Entity, Type, Enum, Container, etc.). The one
461
477
  * exception is `FieldDeclaration`: when the parent directive imports
462
- * one or more fields via `field <path>` items (spec §26.8), each field
478
+ * one or more fields via `field <path>` items (spec §27.8), each field
463
479
  * appears here as a bare FieldDeclaration with no entity wrapper.
464
480
  * The `flatten()` pass lifts each bare field into a synthetic
465
481
  * TypeDeclaration at file scope so downstream consumers see a normal
@@ -545,7 +561,7 @@ export interface ParseOptions {
545
561
  * Because this reader is synchronous, a host that supports remote sources
546
562
  * must return the fetched text from a cache it populated beforehand. The
547
563
  * network fetch, and its SSRF / redirect / size / timeout obligations
548
- * (spec §26.14.5), live in the host's resolver, not in the parser.
564
+ * (spec §27.14.5), live in the host's resolver, not in the parser.
549
565
  *
550
566
  * If absent, reference-only directives fall back to the P4 rejection
551
567
  * with a clear "no resolver available" message. Clone-block-bearing
package/dist/index.d.ts CHANGED
@@ -27,13 +27,15 @@
27
27
  export * from './ast.ts';
28
28
  export { tokenize, TokenKind, LexError } from './lexer.ts';
29
29
  export type { Token } from './lexer.ts';
30
- export { parse, Parser, ParseError } from './parser.ts';
30
+ export { parse, Parser, ParseError, SUPPORTED_XDBML_VERSION, compareVersions } from './parser.ts';
31
31
  export { flatten } from './module-resolver.ts';
32
32
  export { classifyModuleSource, isUrlKey, ModuleSourceError, } from './module-resolver.ts';
33
33
  export type { ModuleSource } from './module-resolver.ts';
34
34
  export { resolveNames, SymbolTable } from './name-resolver.ts';
35
35
  export { FOREIGN_MASTER_FLAG, checkRelationships, hasForeignMasterFlag, isForeignMaster, pathToString, refChildEndpoint, refParentEndpoint, relationshipType, versionAtLeast, CONSTRAINT_TYPES, V04_RELATIONSHIP_SETTINGS, constraintType, entityNames, isEntityLevelEndpoint, isUndirected, } from './relationships.ts';
36
36
  export type { RelationshipType, ConstraintType } from './relationships.ts';
37
+ export { SUPERTYPE_GROUP_VALUES, canonicalSupertypeGroupValue, checkSupertypeGroups, resolveSupertypeGroups, subtypeStrategy, supertypeChains, supertypeGroupSettings, } from './supertypes.ts';
38
+ export type { Completeness, Exclusivity, MaterializationStrategy, MergeOption, ResolvedSupertypeGroup, SupertypeGroupSettings, SupertypeGroupValueSetting, } from './supertypes.ts';
37
39
  export type { Diagnostic, DiagnosticCode, ResolutionResult, SymbolEntry, SymbolKind, } from './name-resolver.ts';
38
40
  export { xdbmlLanguageConfig, xdbmlMonarchTokensProvider, } from './monarch.ts';
39
41
  export type { XDbmlLanguageConfiguration, XDbmlMonarchLanguage, } from './monarch.ts';
package/dist/index.js CHANGED
@@ -26,9 +26,10 @@
26
26
  */
27
27
  export * from "./ast.js";
28
28
  export { tokenize, TokenKind, LexError } from "./lexer.js";
29
- export { parse, Parser, ParseError } from "./parser.js";
29
+ export { parse, Parser, ParseError, SUPPORTED_XDBML_VERSION, compareVersions } from "./parser.js";
30
30
  export { flatten } from "./module-resolver.js";
31
31
  export { classifyModuleSource, isUrlKey, ModuleSourceError, } from "./module-resolver.js";
32
32
  export { resolveNames, SymbolTable } from "./name-resolver.js";
33
33
  export { FOREIGN_MASTER_FLAG, checkRelationships, hasForeignMasterFlag, isForeignMaster, pathToString, refChildEndpoint, refParentEndpoint, relationshipType, versionAtLeast, CONSTRAINT_TYPES, V04_RELATIONSHIP_SETTINGS, constraintType, entityNames, isEntityLevelEndpoint, isUndirected, } from "./relationships.js";
34
+ export { SUPERTYPE_GROUP_VALUES, canonicalSupertypeGroupValue, checkSupertypeGroups, resolveSupertypeGroups, subtypeStrategy, supertypeChains, supertypeGroupSettings, } from "./supertypes.js";
34
35
  export { xdbmlLanguageConfig, xdbmlMonarchTokensProvider, } from "./monarch.js";
@@ -33,13 +33,13 @@ export declare const ENTITY_KEYWORDS: readonly ["table", "entity", "collection",
33
33
  * The full set of declaration keywords. Includes containers,
34
34
  * entities, and other top-level constructs.
35
35
  */
36
- export declare const DECLARATION_KEYWORDS: readonly ["project", "container", "schema", "database", "keyspace", "namespace", "dataset", "bucket", "table", "entity", "collection", "record", "type", "edge", "view", "enum", "ref", "note", "tablepartial", "tablegroup", "diagramview"];
36
+ export declare const DECLARATION_KEYWORDS: readonly ["project", "container", "schema", "database", "keyspace", "namespace", "dataset", "bucket", "table", "entity", "collection", "record", "type", "edge", "view", "enum", "ref", "note", "tablepartial", "tablegroup", "supertypegroup", "diagramview"];
37
37
  export declare const STRUCTURAL_TYPE_KEYWORDS: readonly ["object", "struct", "array", "list", "map", "dict", "dictionary", "set", "json", "jsonb", "variant"];
38
38
  export declare const POLYMORPHISM_KEYWORDS: readonly ["union", "oneof", "anyof", "allof"];
39
39
  export declare const SCALAR_TYPES: readonly ["tinyint", "smallint", "mediumint", "int", "integer", "bigint", "int32", "int64", "float", "double", "decimal", "dec", "numeric", "real", "bit", "bool", "boolean", "char", "varchar", "varchar2", "nvarchar", "nvarchar2", "nchar", "text", "mediumtext", "longtext", "string", "ntext", "binary", "varbinary", "blob", "mediumblob", "longblob", "tinyblob", "tinytext", "json", "jsonb", "variant", "xml", "date", "time", "datetime", "datetime2", "timestamp", "timestamptz", "year", "uuid", "inet6", "money", "smallmoney", "enum"];
40
40
  export declare const BSON_TYPES: readonly ["objectid", "decimal128", "bindata", "minkey", "maxkey", "symbol", "regex", "long", "double"];
41
41
  export declare const SETTING_FLAGS: readonly ["pk", "primary", "key", "unique", "null", "not", "required", "increment", "inactive", "foreign_master"];
42
- export declare const SETTING_KEYS: readonly ["note", "default", "ref", "name", "color", "headercolor", "as", "check", "type", "target", "targets", "database_type", "source", "source_cardinality", "target_cardinality", "min_source", "max_source", "min_target", "max_target", "undirected", "source_role", "target_role", "source_verb", "target_verb", "constraint_type", "discriminator", "source_query", "materialized", "refresh_schedule", "refresh_on", "source_database", "storage_options", "pattern", "format", "minlength", "maxlength", "minimum", "maximum", "exclusiveminimum", "exclusivemaximum", "multipleof", "minitems", "maxitems", "uniqueitems", "minproperties", "maxproperties", "synonyms", "business_term", "granularity", "tags", "delete", "update", "indexes", "checks", "replication", "location", "default_charset", "cloned_at"];
42
+ export declare const SETTING_KEYS: readonly ["note", "default", "ref", "name", "color", "headercolor", "as", "check", "type", "target", "targets", "database_type", "source", "source_cardinality", "target_cardinality", "min_source", "max_source", "min_target", "max_target", "undirected", "source_role", "target_role", "source_verb", "target_verb", "constraint_type", "discriminator", "supertype", "completeness", "exclusivity", "strategy", "merge", "source_query", "materialized", "refresh_schedule", "refresh_on", "source_database", "storage_options", "pattern", "format", "minlength", "maxlength", "minimum", "maximum", "exclusiveminimum", "exclusivemaximum", "multipleof", "minitems", "maxitems", "uniqueitems", "minproperties", "maxproperties", "synonyms", "business_term", "granularity", "tags", "delete", "update", "indexes", "checks", "replication", "location", "default_charset", "cloned_at"];
43
43
  export declare const GRANULARITY_VALUES: readonly ["year", "quarter", "month", "week", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"];
44
44
  export declare const DIRECTIVE_KEYWORDS: readonly ["xdbml", "experimental"];
45
45
  export declare const MODULE_KEYWORDS: readonly ["use", "reuse", "from", "as"];
package/dist/keywords.js CHANGED
@@ -66,6 +66,7 @@ export const DECLARATION_KEYWORDS = [
66
66
  'note',
67
67
  'tablepartial',
68
68
  'tablegroup',
69
+ 'supertypegroup',
69
70
  'diagramview',
70
71
  ];
71
72
  /* -------------------------------------------------------------------------
@@ -196,6 +197,12 @@ export const SETTING_KEYS = [
196
197
  'target_verb',
197
198
  'constraint_type',
198
199
  'discriminator',
200
+ // v0.5 supertype groups (spec 12.2); `discriminator` is listed above
201
+ 'supertype',
202
+ 'completeness',
203
+ 'exclusivity',
204
+ 'strategy',
205
+ 'merge',
199
206
  'source_query',
200
207
  'materialized',
201
208
  'refresh_schedule',
@@ -30,13 +30,13 @@ import type { CloneBlock, ModuleImportDirective, ParseOptions, XDbmlDocument } f
30
30
  *
31
31
  * Inside a Container body, each `ModuleImportDirective` is replaced by its
32
32
  * `clone.statements` as `ContainerBodyItem`s. Note that the spec table in
33
- * §26.6 guarantees that clone-block content for entity/edge/view/enum
33
+ * §27.6 guarantees that clone-block content for entity/edge/view/enum
34
34
  * imports is shape-compatible with `ContainerBodyItem`; other shapes
35
35
  * (e.g., a TablePartial clone inside a Container directive) would be
36
36
  * semantically invalid per the spec and would surface as a downstream
37
37
  * type error rather than being caught here.
38
38
  *
39
- * Field-level imports (spec §26.8) get a special transform: the clone
39
+ * Field-level imports (spec §27.8) get a special transform: the clone
40
40
  * block holds a bare `FieldDeclaration`, which `flatten()` lifts into a
41
41
  * synthetic `TypeDeclaration` at file scope. Downstream consumers see
42
42
  * a normal Named Type and can use it as a field type without learning
@@ -59,7 +59,7 @@ export type ParseFn = (source: string, options: ParseOptions, resolutionStack: R
59
59
  * - `kind: 'resolved'` -- the file was opened, parsed, and a clone
60
60
  * block was synthesized
61
61
  * - `kind: 'cycle'` -- the resolution chain already contains this
62
- * file; per spec §26.15 cycles are allowed, so we return an empty
62
+ * file; per spec §27.15 cycles are allowed, so we return an empty
63
63
  * clone block and let name resolution (P6+) handle the actual
64
64
  * cross-file linking
65
65
  * - `kind: 'no-resolver'` -- no `readFile` was supplied; caller should
@@ -30,13 +30,13 @@ import { SCALAR_TYPES, BSON_TYPES } from "./keywords.js";
30
30
  *
31
31
  * Inside a Container body, each `ModuleImportDirective` is replaced by its
32
32
  * `clone.statements` as `ContainerBodyItem`s. Note that the spec table in
33
- * §26.6 guarantees that clone-block content for entity/edge/view/enum
33
+ * §27.6 guarantees that clone-block content for entity/edge/view/enum
34
34
  * imports is shape-compatible with `ContainerBodyItem`; other shapes
35
35
  * (e.g., a TablePartial clone inside a Container directive) would be
36
36
  * semantically invalid per the spec and would surface as a downstream
37
37
  * type error rather than being caught here.
38
38
  *
39
- * Field-level imports (spec §26.8) get a special transform: the clone
39
+ * Field-level imports (spec §27.8) get a special transform: the clone
40
40
  * block holds a bare `FieldDeclaration`, which `flatten()` lifts into a
41
41
  * synthetic `TypeDeclaration` at file scope. Downstream consumers see
42
42
  * a normal Named Type and can use it as a field type without learning
@@ -92,11 +92,11 @@ function flattenTopLevel(stmt, out) {
92
92
  *
93
93
  * - For SCALAR fields (any TypeExpression that isn't ObjectType): the
94
94
  * Type is in scalar form with `scalarBase = field.type`. Equivalent
95
- * to the v0.2 scalar-Named-Type form (spec §14.7).
95
+ * to the v0.2 scalar-Named-Type form (spec §15.7).
96
96
  *
97
97
  * - For OBJECT-typed fields (`field foo object { ... }`): the Type is
98
98
  * in object form with `body = field.type.fields`. Equivalent to the
99
- * v0.1 object-Named-Type form (spec §14).
99
+ * v0.1 object-Named-Type form (spec §15).
100
100
  *
101
101
  * Other type shapes (Array, Map, Set, Tuple, Union, polymorphic types)
102
102
  * are valid as `scalarBase` of a Type and pass through unchanged. The
@@ -225,7 +225,7 @@ export function resolveImport(directive, options, resolutionStack, depth, parseF
225
225
  * import spec. Applies aliases by renaming the extracted declaration.
226
226
  *
227
227
  * For `ImportAll`: every TopLevelStatement except ProjectDeclaration
228
- * (per spec §26.4, Project declarations cannot be imported).
228
+ * (per spec §27.4, Project declarations cannot be imported).
229
229
  *
230
230
  * For `ImportList`: each item is matched by element-type + source path.
231
231
  * Items not found in the source produce nothing (silent for P5; a
@@ -234,7 +234,7 @@ export function resolveImport(directive, options, resolutionStack, depth, parseF
234
234
  function extractImports(spec, sourceDoc) {
235
235
  if (spec.kind === 'ImportAll') {
236
236
  // ImportAll never matches field imports (the `*` form is for top-level
237
- // declarations only per spec §26.2). Return the source's top-level
237
+ // declarations only per spec §27.2). Return the source's top-level
238
238
  // statements minus Project.
239
239
  return sourceDoc.statements
240
240
  .filter((s) => s.kind !== 'ProjectDeclaration')
@@ -248,7 +248,7 @@ function extractImports(spec, sourceDoc) {
248
248
  out.push(applyAlias(found, item));
249
249
  }
250
250
  // Silent skip on not-found. The spec leaves diagnostics to name
251
- // resolution (§26.13). In practice, users notice missing entities
251
+ // resolution (§27.13). In practice, users notice missing entities
252
252
  // because their references downstream become unresolved.
253
253
  }
254
254
  return out;
@@ -276,6 +276,8 @@ function extractImports(spec, sourceDoc) {
276
276
  * ViewDeclaration with matching name; supports dotted path.
277
277
  * - 'tablegroup':
278
278
  * TableGroupDeclaration with matching name (top-level only).
279
+ * - 'supertypegroup':
280
+ * SupertypeGroupDeclaration with matching name (top-level only, v0.5).
279
281
  * - 'tablepartial':
280
282
  * TablePartialDeclaration with matching name (top-level only).
281
283
  * - 'note':
@@ -344,6 +346,12 @@ function findImportTarget(item, doc) {
344
346
  if (item.elementType === 'tablegroup') {
345
347
  return doc.statements.find((s) => s.kind === 'TableGroupDeclaration' && s.name === path);
346
348
  }
349
+ // SupertypeGroup (spec §12, v0.5): top-level only, bare name. The group
350
+ // comes with its membership; its entities resolve in the importing
351
+ // document, by import or declaration, like TableGroup members.
352
+ if (item.elementType === 'supertypegroup') {
353
+ return doc.statements.find((s) => s.kind === 'SupertypeGroupDeclaration' && s.name === path);
354
+ }
347
355
  if (item.elementType === 'tablepartial') {
348
356
  return doc.statements.find((s) => s.kind === 'TablePartialDeclaration' && s.name === path);
349
357
  }
@@ -403,7 +411,7 @@ function findImportTarget(item, doc) {
403
411
  * object types to find a FieldDeclaration in a referenced source document.
404
412
  * Returns undefined when any segment fails to resolve.
405
413
  *
406
- * Path shapes accepted (per spec §26.8):
414
+ * Path shapes accepted (per spec §27.8):
407
415
  * - `entity.field` -- top-level entity
408
416
  * - `container.entity.field` -- container-qualified entity
409
417
  * - `entity.field.sub` -- nested via ObjectType
@@ -594,6 +602,8 @@ function applyAlias(stmt, item) {
594
602
  return { ...stmt, name: item.alias };
595
603
  case 'TableGroupDeclaration':
596
604
  return { ...stmt, name: item.alias };
605
+ case 'SupertypeGroupDeclaration':
606
+ return { ...stmt, name: item.alias };
597
607
  case 'TablePartialDeclaration':
598
608
  return { ...stmt, name: item.alias };
599
609
  case 'NoteDeclaration':
@@ -605,7 +615,7 @@ function applyAlias(stmt, item) {
605
615
  }
606
616
  }
607
617
  /* -------------------------------------------------------------------------
608
- * Module source classification (spec §26.14, "Remote module sources")
618
+ * Module source classification (spec §27.14, "Remote module sources")
609
619
  *
610
620
  * A `from` source is recognized purely by its scheme. A source beginning
611
621
  * with 'https://' is a remote (URL) source; anything else is a relative
@@ -617,7 +627,7 @@ function applyAlias(stmt, item) {
617
627
  * This is pure, synchronous classification. The actual network fetch is
618
628
  * delegated to ParseOptions.readFile (the host's resolver). The obligations
619
629
  * on a fetcher (SSRF defenses, https-only redirects, size and time limits)
620
- * live with that resolver, not here; see spec §26.14.5.
630
+ * live with that resolver, not here; see spec §27.14.5.
621
631
  * ----------------------------------------------------------------------- */
622
632
  /** Raised when a `from` source string is structurally disallowed. */
623
633
  export class ModuleSourceError extends Error {
@@ -687,7 +697,7 @@ export function classifyModuleSource(from) {
687
697
  * - A remote (https) source resolves to its normalized href. No '.xdbml'
688
698
  * is appended (a raw-content URL may carry a query string).
689
699
  * - A relative source whose importer is itself a remote module resolves
690
- * against the importer's base URL per RFC 3986 (spec §26.14.1). A remote
700
+ * against the importer's base URL per RFC 3986 (spec §27.14.1). A remote
691
701
  * module therefore can never reach the local filesystem.
692
702
  * - A relative source with a local importer resolves on the filesystem,
693
703
  * exactly as in v0.2.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Name resolution pass (spec §26.10 / §26.15, parser batch P6).
2
+ * Name resolution pass (spec §27.10 / §27.15, parser batch P6).
3
3
  *
4
4
  * `resolveNames(doc)` walks an xDBML document (the flattened view; clone
5
5
  * blocks have been merged) and produces:
@@ -67,7 +67,7 @@ export interface SymbolEntry {
67
67
  * Stable diagnostic code. Tooling can match on these to filter or style
68
68
  * messages without parsing the human-readable text.
69
69
  */
70
- export type DiagnosticCode = 'duplicate-declaration' | 'unresolved-type' | 'unresolved-entity' | 'unresolved-field' | 'unresolved-partial' | 'unresolved-tablegroup-member' | 'unresolved-records-entity' | 'unresolved-records-column' | 'empty-import' | 'invalid-nested-path' | 'foreign-master-composite' | 'foreign-master-duplicate-child' | 'foreign-master-without-ref' | 'construct-requires-version' | 'ambiguous-ref-endpoint' | 'invalid-constraint-type' | 'constraint-type-on-foreign-master' | 'invalid-undirected' | 'entity-level-many-to-many';
70
+ export type DiagnosticCode = 'duplicate-declaration' | 'unresolved-type' | 'unresolved-entity' | 'unresolved-field' | 'unresolved-partial' | 'unresolved-tablegroup-member' | 'unresolved-records-entity' | 'unresolved-records-column' | 'empty-import' | 'invalid-nested-path' | 'foreign-master-composite' | 'foreign-master-duplicate-child' | 'foreign-master-without-ref' | 'construct-requires-version' | 'ambiguous-ref-endpoint' | 'invalid-constraint-type' | 'constraint-type-on-foreign-master' | 'invalid-undirected' | 'entity-level-many-to-many' | 'missing-supertype' | 'unresolved-supertype-group-member' | 'invalid-supertype-group-value' | 'duplicate-subtype' | 'supertype-is-subtype' | 'subtype-in-multiple-groups' | 'supertype-cycle' | 'supertype-attribute-redeclared' | 'discriminator-on-overlapping-group' | 'merge-without-roll-up' | 'empty-supertype-group';
71
71
  /**
72
72
  * A single resolution diagnostic. Severity is currently always `error`,
73
73
  * but the field is included to leave room for future warnings (e.g.,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Name resolution pass (spec §26.10 / §26.15, parser batch P6).
2
+ * Name resolution pass (spec §27.10 / §27.15, parser batch P6).
3
3
  *
4
4
  * `resolveNames(doc)` walks an xDBML document (the flattened view; clone
5
5
  * blocks have been merged) and produces:
@@ -41,6 +41,7 @@
41
41
  import { SCALAR_TYPES, BSON_TYPES } from "./keywords.js";
42
42
  import { flatten } from "./module-resolver.js";
43
43
  import { checkRelationships } from "./relationships.js";
44
+ import { checkSupertypeGroups } from "./supertypes.js";
44
45
  /**
45
46
  * Read-only handle on the collected symbol table.
46
47
  *
@@ -137,6 +138,8 @@ export function resolveNames(doc) {
137
138
  resolveReferences(flat, symbols, diagnostics);
138
139
  // Pass 3: relationship rules that the grammar cannot express (spec 11.11).
139
140
  diagnostics.push(...checkRelationships(flat));
141
+ // Pass 4: supertype group rules (spec 12.8).
142
+ diagnostics.push(...checkSupertypeGroups(flat));
140
143
  return { diagnostics, symbols };
141
144
  }
142
145
  /* -------------------------------------------------------------------------
package/dist/parser.d.ts CHANGED
@@ -13,8 +13,22 @@ import type { ParseOptions, Position, XDbmlDocument } from './ast.ts';
13
13
  import type { Token } from './lexer.ts';
14
14
  export declare class ParseError extends Error {
15
15
  position: Position;
16
- constructor(message: string, position: Position);
16
+ /**
17
+ * Optional machine-readable reason. Set for the errors a caller may want
18
+ * to tell apart from a plain syntax error: `unsupported-version` when a
19
+ * document declares a newer version than this parser supports (spec 4.1).
20
+ */
21
+ code?: string;
22
+ constructor(message: string, position: Position, code?: string);
17
23
  }
24
+ /**
25
+ * The newest specification version this parser implements. A document
26
+ * declaring a later version is refused (spec 4.1) rather than parsed with
27
+ * semantics it does not have.
28
+ */
29
+ export declare const SUPPORTED_XDBML_VERSION = "0.5";
30
+ /** Compare dotted version strings numerically: -1, 0 or 1. */
31
+ export declare function compareVersions(a: string, b: string): number;
18
32
  export declare class Parser {
19
33
  private tokens;
20
34
  private idx;
@@ -30,7 +44,7 @@ export declare class Parser {
30
44
  * The set of file paths currently being parsed in the resolution chain.
31
45
  * Used for cycle detection: when resolving a directive whose `from` path
32
46
  * is already in this set, the parser produces an empty clone for that
33
- * directive rather than recursing (matching spec §26.15: cycles are
47
+ * directive rather than recursing (matching spec §27.15: cycles are
34
48
  * allowed; name resolution handles them). The set is passed by reference
35
49
  * across recursive parse() calls so all transitive levels see it.
36
50
  *
@@ -83,13 +97,13 @@ export declare class Parser {
83
97
  private parseEntityBody;
84
98
  private parsePartialInjection;
85
99
  /**
86
- * Parse a `records { ... }` block inside an entity body (§25.1, implicit
100
+ * Parse a `records { ... }` block inside an entity body (§26.1, implicit
87
101
  * column list). Values are stored as SettingValue cells; row boundaries
88
102
  * are determined by source line (see `parseRecordRow`).
89
103
  */
90
104
  private parseRecordsBlock;
91
105
  /**
92
- * Top-level records declaration (§25.2, new in v0.2):
106
+ * Top-level records declaration (§26.2, new in v0.2):
93
107
  *
94
108
  * records users (id, name, email) { ... }
95
109
  * records core.users (id, name, email) { ... }
@@ -151,12 +165,12 @@ export declare class Parser {
151
165
  * that match the import items by name and element type (matching is
152
166
  * downstream-consumer's job; the parser is permissive).
153
167
  *
154
- * Per spec §26.6, clone content uses the importing file's vocabulary
168
+ * Per spec §27.6, clone content uses the importing file's vocabulary
155
169
  * (aliases already applied) and is parsed under the importing file's
156
170
  * xdbml version directive.
157
171
  *
158
172
  * Most clone-block content uses TopLevelStatement shapes (Entity, Type,
159
- * Container, etc.). The exception is field imports (§26.8): when the
173
+ * Container, etc.). The exception is field imports (§27.8): when the
160
174
  * directive imports one or more fields via `field <path>` items, the
161
175
  * clone block holds each field as a bare FieldDeclaration with no entity
162
176
  * wrapper. The dispatch below checks whether the next token starts a
@@ -278,7 +292,7 @@ export declare class Parser {
278
292
  private parseCardinalityOperator;
279
293
  private parseRefEndpoint;
280
294
  /**
281
- * Parse a dotted path with the §18 segment vocabulary:
295
+ * Parse a dotted path with the §20 segment vocabulary:
282
296
  *
283
297
  * IDENTIFIER -- a field segment
284
298
  * .IDENTIFIER -- field
@@ -297,6 +311,16 @@ export declare class Parser {
297
311
  private parsePathSegments;
298
312
  private parseTablePartial;
299
313
  private parseTableGroup;
314
+ /**
315
+ * `SupertypeGroup <name> [supertype: X, ...] { Sub1 Sub2 [strategy: y] }`.
316
+ * Members are separated like TableGroup members: newline, comma or
317
+ * semicolon (spec §3.9). A name is required (§12.1); a writer exporting a
318
+ * group that has none emits `undefinedGroup1`, `undefinedGroup2`, ... so
319
+ * the parser never supplies one. Values are validated after parsing, by
320
+ * `checkSupertypeGroups()`, so an unknown value gets a located diagnostic
321
+ * rather than stopping the parse.
322
+ */
323
+ private parseSupertypeGroup;
300
324
  private parseIndexes;
301
325
  private parseIndexEntry;
302
326
  private parseIndexComponent;