@xdbml/parse 0.1.0-poc.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/dist/ast.d.ts +565 -0
- package/dist/ast.js +10 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +33 -0
- package/dist/keywords.d.ts +45 -0
- package/dist/keywords.js +277 -0
- package/dist/lexer.d.ts +91 -0
- package/dist/lexer.js +549 -0
- package/dist/module-resolver.d.ts +115 -0
- package/dist/module-resolver.js +771 -0
- package/dist/monarch.d.ts +64 -0
- package/dist/monarch.js +205 -0
- package/dist/name-resolver.d.ts +135 -0
- package/dist/name-resolver.js +854 -0
- package/dist/parser.d.ts +331 -0
- package/dist/parser.js +2083 -0
- package/package.json +33 -0
package/dist/ast.d.ts
ADDED
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xDBML AST node types.
|
|
3
|
+
*
|
|
4
|
+
* The AST is intentionally narrow: each node carries only what's needed
|
|
5
|
+
* to round-trip xDBML source and to feed a downstream lowering pass
|
|
6
|
+
* (DDL emitters, JSON Schema emitters, etc.). Generic open-vocabulary
|
|
7
|
+
* settings are kept as Setting nodes rather than promoted to typed
|
|
8
|
+
* fields, because the spec leaves the settings vocabulary open.
|
|
9
|
+
*/
|
|
10
|
+
export interface Position {
|
|
11
|
+
/** 1-indexed line number */
|
|
12
|
+
line: number;
|
|
13
|
+
/** 1-indexed column number */
|
|
14
|
+
column: number;
|
|
15
|
+
/** 0-indexed byte offset into the source */
|
|
16
|
+
offset: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Span {
|
|
19
|
+
start: Position;
|
|
20
|
+
end: Position;
|
|
21
|
+
}
|
|
22
|
+
export interface XDbmlDocument {
|
|
23
|
+
kind: 'XDbmlDocument';
|
|
24
|
+
/** Present when the document opens with `xdbml: 0.1`. DBML-compat documents have this undefined. */
|
|
25
|
+
version?: VersionDeclaration;
|
|
26
|
+
experimental?: ExperimentalDeclaration;
|
|
27
|
+
statements: TopLevelStatement[];
|
|
28
|
+
span: Span;
|
|
29
|
+
}
|
|
30
|
+
export interface VersionDeclaration {
|
|
31
|
+
kind: 'VersionDeclaration';
|
|
32
|
+
/** The literal source text, e.g. "0.1" or "0.1.0". Semver shape validated at parse. */
|
|
33
|
+
version: string;
|
|
34
|
+
span: Span;
|
|
35
|
+
}
|
|
36
|
+
export interface ExperimentalDeclaration {
|
|
37
|
+
kind: 'ExperimentalDeclaration';
|
|
38
|
+
features: string[];
|
|
39
|
+
span: Span;
|
|
40
|
+
}
|
|
41
|
+
export type TopLevelStatement = ProjectDeclaration | ContainerDeclaration | EntityDeclaration | TypeDeclaration | EdgeDeclaration | ViewDeclaration | EnumDeclaration | RefDeclaration | TablePartialDeclaration | TableGroupDeclaration | NoteDeclaration | TopLevelRecordsDeclaration | ModuleImportDirective;
|
|
42
|
+
export interface ProjectDeclaration {
|
|
43
|
+
kind: 'ProjectDeclaration';
|
|
44
|
+
name: string;
|
|
45
|
+
body: ProjectBodyItem[];
|
|
46
|
+
span: Span;
|
|
47
|
+
}
|
|
48
|
+
export type ProjectBodyItem = Setting | NoteBlock;
|
|
49
|
+
export interface ContainerDeclaration {
|
|
50
|
+
kind: 'ContainerDeclaration';
|
|
51
|
+
keyword: ContainerKeyword;
|
|
52
|
+
name: string;
|
|
53
|
+
settings: Setting[];
|
|
54
|
+
body: ContainerBodyItem[];
|
|
55
|
+
span: Span;
|
|
56
|
+
}
|
|
57
|
+
export type ContainerKeyword = 'Container' | 'Schema' | 'Database' | 'Keyspace' | 'Namespace' | 'Dataset' | 'Bucket';
|
|
58
|
+
export type ContainerBodyItem = EntityDeclaration | EdgeDeclaration | ViewDeclaration | EnumDeclaration | NoteBlock | ModuleImportDirective;
|
|
59
|
+
export interface EntityDeclaration {
|
|
60
|
+
kind: 'EntityDeclaration';
|
|
61
|
+
keyword: EntityKeyword;
|
|
62
|
+
/** May be `container.entity` form when declared schema-qualified */
|
|
63
|
+
name: string;
|
|
64
|
+
/** Optional `as Alias` */
|
|
65
|
+
alias?: string;
|
|
66
|
+
settings: Setting[];
|
|
67
|
+
body: EntityBodyItem[];
|
|
68
|
+
span: Span;
|
|
69
|
+
}
|
|
70
|
+
export type EntityKeyword = 'Table' | 'Entity' | 'Collection' | 'Record';
|
|
71
|
+
export type EntityBodyItem = FieldDeclaration | IndexesBlock | ChecksBlock | NoteBlock | PartialInjection | RecordsBlock;
|
|
72
|
+
export interface FieldDeclaration {
|
|
73
|
+
kind: 'FieldDeclaration';
|
|
74
|
+
name: string;
|
|
75
|
+
/** True when the name came from a quoted identifier ("first name") */
|
|
76
|
+
nameQuoted: boolean;
|
|
77
|
+
type: TypeExpression;
|
|
78
|
+
settings: Setting[];
|
|
79
|
+
span: Span;
|
|
80
|
+
}
|
|
81
|
+
export type TypeExpression = ScalarType | ObjectType | ArrayType | TupleType | MapType | SetType | UnionType | OneOfType | AnyOfType | AllOfType | JsonType | NamedTypeReference;
|
|
82
|
+
export interface ScalarType {
|
|
83
|
+
kind: 'ScalarType';
|
|
84
|
+
/** The base name: `int`, `varchar`, `decimal`, `objectId`, `Decimal128`, etc. */
|
|
85
|
+
name: string;
|
|
86
|
+
/** `(p, s)` parameters, e.g. for `decimal(19, 4)`. Numbers preserved as strings to keep round-trip fidelity. */
|
|
87
|
+
params?: string[];
|
|
88
|
+
span: Span;
|
|
89
|
+
}
|
|
90
|
+
export interface NamedTypeReference {
|
|
91
|
+
kind: 'NamedTypeReference';
|
|
92
|
+
name: string;
|
|
93
|
+
span: Span;
|
|
94
|
+
}
|
|
95
|
+
export interface ObjectType {
|
|
96
|
+
kind: 'ObjectType';
|
|
97
|
+
/** Captures whether the source used `object`, `struct`, or `record` */
|
|
98
|
+
keyword: 'object' | 'struct' | 'record';
|
|
99
|
+
fields: (FieldDeclaration | NoteBlock | PartialInjection)[];
|
|
100
|
+
span: Span;
|
|
101
|
+
}
|
|
102
|
+
export interface ArrayType {
|
|
103
|
+
kind: 'ArrayType';
|
|
104
|
+
keyword: 'array' | 'list';
|
|
105
|
+
/** The element type when the array is homogeneous (`array [varchar]`). */
|
|
106
|
+
elementType?: TypeExpression;
|
|
107
|
+
/** When the array body uses `name type` form, e.g. `array [line_item object {...}]`, this carries the element name. */
|
|
108
|
+
elementName?: string;
|
|
109
|
+
/** Optional settings applied to the element type itself (rare). */
|
|
110
|
+
elementSettings?: Setting[];
|
|
111
|
+
span: Span;
|
|
112
|
+
}
|
|
113
|
+
export interface TupleType {
|
|
114
|
+
kind: 'TupleType';
|
|
115
|
+
/** Positional elements with `[N] name type` */
|
|
116
|
+
elements: TupleElement[];
|
|
117
|
+
span: Span;
|
|
118
|
+
}
|
|
119
|
+
export interface TupleElement {
|
|
120
|
+
kind: 'TupleElement';
|
|
121
|
+
position: number;
|
|
122
|
+
name: string;
|
|
123
|
+
type: TypeExpression;
|
|
124
|
+
settings: Setting[];
|
|
125
|
+
span: Span;
|
|
126
|
+
}
|
|
127
|
+
export interface MapType {
|
|
128
|
+
kind: 'MapType';
|
|
129
|
+
keyword: 'map' | 'dict' | 'dictionary';
|
|
130
|
+
keyType: TypeExpression;
|
|
131
|
+
valueType: TypeExpression;
|
|
132
|
+
span: Span;
|
|
133
|
+
}
|
|
134
|
+
export interface SetType {
|
|
135
|
+
kind: 'SetType';
|
|
136
|
+
elementType: TypeExpression;
|
|
137
|
+
span: Span;
|
|
138
|
+
}
|
|
139
|
+
export interface UnionType {
|
|
140
|
+
kind: 'UnionType';
|
|
141
|
+
members: (ScalarType | NamedTypeReference | NullTypeLiteral)[];
|
|
142
|
+
span: Span;
|
|
143
|
+
}
|
|
144
|
+
export interface NullTypeLiteral {
|
|
145
|
+
kind: 'NullTypeLiteral';
|
|
146
|
+
span: Span;
|
|
147
|
+
}
|
|
148
|
+
export interface OneOfType {
|
|
149
|
+
kind: 'OneOfType';
|
|
150
|
+
alternatives: PolymorphicAlternative[];
|
|
151
|
+
settings: Setting[];
|
|
152
|
+
span: Span;
|
|
153
|
+
}
|
|
154
|
+
export interface AnyOfType {
|
|
155
|
+
kind: 'AnyOfType';
|
|
156
|
+
alternatives: PolymorphicAlternative[];
|
|
157
|
+
settings: Setting[];
|
|
158
|
+
span: Span;
|
|
159
|
+
}
|
|
160
|
+
export interface AllOfType {
|
|
161
|
+
kind: 'AllOfType';
|
|
162
|
+
alternatives: PolymorphicAlternative[];
|
|
163
|
+
settings: Setting[];
|
|
164
|
+
span: Span;
|
|
165
|
+
}
|
|
166
|
+
export interface PolymorphicAlternative {
|
|
167
|
+
kind: 'PolymorphicAlternative';
|
|
168
|
+
name: string;
|
|
169
|
+
type: TypeExpression;
|
|
170
|
+
settings: Setting[];
|
|
171
|
+
span: Span;
|
|
172
|
+
}
|
|
173
|
+
export interface JsonType {
|
|
174
|
+
kind: 'JsonType';
|
|
175
|
+
/** `json`, `jsonb`, or `variant` */
|
|
176
|
+
keyword: 'json' | 'jsonb' | 'variant';
|
|
177
|
+
/** Optional schema block; absence = opaque JSON column */
|
|
178
|
+
fields?: (FieldDeclaration | NoteBlock | PartialInjection)[];
|
|
179
|
+
span: Span;
|
|
180
|
+
}
|
|
181
|
+
export interface TypeDeclaration {
|
|
182
|
+
kind: 'TypeDeclaration';
|
|
183
|
+
name: string;
|
|
184
|
+
/**
|
|
185
|
+
* v0.2 scalar form (spec §14.7): when present, this Type is an alias
|
|
186
|
+
* for the given type expression rather than an object-shaped record.
|
|
187
|
+
* Examples:
|
|
188
|
+
*
|
|
189
|
+
* Type Email varchar [pattern: '...', tags: ['pii']]
|
|
190
|
+
* Type Percentage decimal(5,2) [minimum: 0, maximum: 100]
|
|
191
|
+
*
|
|
192
|
+
* When `scalarBase` is set, `body` is empty and `settings` carries the
|
|
193
|
+
* full field-level validation surface (pattern, length bounds, range
|
|
194
|
+
* bounds, AI-readiness tags, notes, x_* custom properties).
|
|
195
|
+
*
|
|
196
|
+
* When `scalarBase` is undefined, the Type uses the v0.1 object form
|
|
197
|
+
* (`Type Name { ...fields }`) and `body` carries the field declarations.
|
|
198
|
+
*
|
|
199
|
+
* Both forms can be used in the same file. Consumers that care about
|
|
200
|
+
* which form was used look at this field.
|
|
201
|
+
*/
|
|
202
|
+
scalarBase?: TypeExpression;
|
|
203
|
+
settings: Setting[];
|
|
204
|
+
body: (FieldDeclaration | NoteBlock | PartialInjection)[];
|
|
205
|
+
span: Span;
|
|
206
|
+
}
|
|
207
|
+
export interface EdgeDeclaration {
|
|
208
|
+
kind: 'EdgeDeclaration';
|
|
209
|
+
name: string;
|
|
210
|
+
settings: Setting[];
|
|
211
|
+
body: EntityBodyItem[];
|
|
212
|
+
span: Span;
|
|
213
|
+
}
|
|
214
|
+
export interface ViewDeclaration {
|
|
215
|
+
kind: 'ViewDeclaration';
|
|
216
|
+
name: string;
|
|
217
|
+
settings: Setting[];
|
|
218
|
+
body: ViewBodyItem[];
|
|
219
|
+
span: Span;
|
|
220
|
+
}
|
|
221
|
+
export type ViewBodyItem = FieldDeclaration | NoteBlock | SourceQueryItem;
|
|
222
|
+
export interface SourceQueryItem {
|
|
223
|
+
kind: 'SourceQueryItem';
|
|
224
|
+
/** The raw query string. Opaque to the parser. */
|
|
225
|
+
query: string;
|
|
226
|
+
span: Span;
|
|
227
|
+
}
|
|
228
|
+
export interface EnumDeclaration {
|
|
229
|
+
kind: 'EnumDeclaration';
|
|
230
|
+
/** Source casing of `enum` or `Enum`; both are valid. */
|
|
231
|
+
keywordCasing: string;
|
|
232
|
+
name: string;
|
|
233
|
+
values: EnumValue[];
|
|
234
|
+
span: Span;
|
|
235
|
+
}
|
|
236
|
+
export interface EnumValue {
|
|
237
|
+
kind: 'EnumValue';
|
|
238
|
+
name: string;
|
|
239
|
+
nameQuoted: boolean;
|
|
240
|
+
settings: Setting[];
|
|
241
|
+
span: Span;
|
|
242
|
+
}
|
|
243
|
+
export interface RefDeclaration {
|
|
244
|
+
kind: 'RefDeclaration';
|
|
245
|
+
/** Optional named ref */
|
|
246
|
+
name?: string;
|
|
247
|
+
spec: RefSpec;
|
|
248
|
+
settings: Setting[];
|
|
249
|
+
span: Span;
|
|
250
|
+
}
|
|
251
|
+
export interface RefSpec {
|
|
252
|
+
kind: 'RefSpec';
|
|
253
|
+
source: RefEndpoint;
|
|
254
|
+
operator: CardinalityOperator;
|
|
255
|
+
target: RefEndpoint;
|
|
256
|
+
span: Span;
|
|
257
|
+
}
|
|
258
|
+
export type CardinalityOperator = '<' | '>' | '-' | '<>';
|
|
259
|
+
export interface RefEndpoint {
|
|
260
|
+
kind: 'RefEndpoint';
|
|
261
|
+
/**
|
|
262
|
+
* The dotted path. Composite FK form `customers.(id, country_code)` is
|
|
263
|
+
* captured by `compositeFields` being non-empty.
|
|
264
|
+
*/
|
|
265
|
+
path: PathSegment[];
|
|
266
|
+
compositeFields?: string[];
|
|
267
|
+
span: Span;
|
|
268
|
+
}
|
|
269
|
+
export type PathSegment = PathField | PathArrayIndex | PathArrayWildcard | PathMapKey;
|
|
270
|
+
export interface PathField {
|
|
271
|
+
kind: 'PathField';
|
|
272
|
+
name: string;
|
|
273
|
+
/** True for `.alternative_name` selectors through polymorphism */
|
|
274
|
+
isAlternativeSelector?: boolean;
|
|
275
|
+
span: Span;
|
|
276
|
+
}
|
|
277
|
+
export interface PathArrayIndex {
|
|
278
|
+
kind: 'PathArrayIndex';
|
|
279
|
+
index: number;
|
|
280
|
+
span: Span;
|
|
281
|
+
}
|
|
282
|
+
export interface PathArrayWildcard {
|
|
283
|
+
kind: 'PathArrayWildcard';
|
|
284
|
+
span: Span;
|
|
285
|
+
}
|
|
286
|
+
export interface PathMapKey {
|
|
287
|
+
kind: 'PathMapKey';
|
|
288
|
+
key: string;
|
|
289
|
+
span: Span;
|
|
290
|
+
}
|
|
291
|
+
export interface IndexesBlock {
|
|
292
|
+
kind: 'IndexesBlock';
|
|
293
|
+
entries: IndexEntry[];
|
|
294
|
+
span: Span;
|
|
295
|
+
}
|
|
296
|
+
export interface IndexEntry {
|
|
297
|
+
kind: 'IndexEntry';
|
|
298
|
+
/** When this is a composite index, multiple components; otherwise one. */
|
|
299
|
+
components: IndexComponent[];
|
|
300
|
+
settings: Setting[];
|
|
301
|
+
span: Span;
|
|
302
|
+
}
|
|
303
|
+
export type IndexComponent = IndexPathComponent | IndexExpressionComponent;
|
|
304
|
+
export interface IndexPathComponent {
|
|
305
|
+
kind: 'IndexPathComponent';
|
|
306
|
+
path: PathSegment[];
|
|
307
|
+
span: Span;
|
|
308
|
+
}
|
|
309
|
+
export interface IndexExpressionComponent {
|
|
310
|
+
kind: 'IndexExpressionComponent';
|
|
311
|
+
/** Source text inside the backticks, no surrounding backticks */
|
|
312
|
+
expression: string;
|
|
313
|
+
span: Span;
|
|
314
|
+
}
|
|
315
|
+
export interface ChecksBlock {
|
|
316
|
+
kind: 'ChecksBlock';
|
|
317
|
+
entries: CheckEntry[];
|
|
318
|
+
span: Span;
|
|
319
|
+
}
|
|
320
|
+
export interface CheckEntry {
|
|
321
|
+
kind: 'CheckEntry';
|
|
322
|
+
/** Source text inside the backticks, no surrounding backticks. */
|
|
323
|
+
expression: string;
|
|
324
|
+
/** Optional settings -- typically `name:` and/or `note:`. */
|
|
325
|
+
settings: Setting[];
|
|
326
|
+
span: Span;
|
|
327
|
+
}
|
|
328
|
+
export interface TablePartialDeclaration {
|
|
329
|
+
kind: 'TablePartialDeclaration';
|
|
330
|
+
name: string;
|
|
331
|
+
settings: Setting[];
|
|
332
|
+
body: EntityBodyItem[];
|
|
333
|
+
span: Span;
|
|
334
|
+
}
|
|
335
|
+
export interface TableGroupDeclaration {
|
|
336
|
+
kind: 'TableGroupDeclaration';
|
|
337
|
+
name: string;
|
|
338
|
+
settings: Setting[];
|
|
339
|
+
members: string[];
|
|
340
|
+
span: Span;
|
|
341
|
+
}
|
|
342
|
+
export interface PartialInjection {
|
|
343
|
+
kind: 'PartialInjection';
|
|
344
|
+
/** Identifier after the `~`. */
|
|
345
|
+
partialName: string;
|
|
346
|
+
span: Span;
|
|
347
|
+
}
|
|
348
|
+
export interface RecordsBlock {
|
|
349
|
+
kind: 'RecordsBlock';
|
|
350
|
+
rows: RecordRow[];
|
|
351
|
+
span: Span;
|
|
352
|
+
}
|
|
353
|
+
export interface RecordRow {
|
|
354
|
+
kind: 'RecordRow';
|
|
355
|
+
values: SettingValue[];
|
|
356
|
+
span: Span;
|
|
357
|
+
}
|
|
358
|
+
export interface TopLevelRecordsDeclaration {
|
|
359
|
+
kind: 'TopLevelRecordsDeclaration';
|
|
360
|
+
/**
|
|
361
|
+
* The entity being populated. Dotted form for cross-container references
|
|
362
|
+
* such as `core.users`. Stored as the source-text dotted path; no
|
|
363
|
+
* resolution is performed at parse time.
|
|
364
|
+
*/
|
|
365
|
+
entityRef: string;
|
|
366
|
+
/** The explicit column list. Required for the top-level form. */
|
|
367
|
+
columns: string[];
|
|
368
|
+
rows: RecordRow[];
|
|
369
|
+
span: Span;
|
|
370
|
+
}
|
|
371
|
+
export interface NoteDeclaration {
|
|
372
|
+
kind: 'NoteDeclaration';
|
|
373
|
+
name?: string;
|
|
374
|
+
body: string;
|
|
375
|
+
span: Span;
|
|
376
|
+
}
|
|
377
|
+
/** Inline `Note: '...'` or `Note { '''...''' }` form */
|
|
378
|
+
export interface NoteBlock {
|
|
379
|
+
kind: 'NoteBlock';
|
|
380
|
+
body: string;
|
|
381
|
+
span: Span;
|
|
382
|
+
}
|
|
383
|
+
export interface ModuleImportDirective {
|
|
384
|
+
kind: 'ModuleImportDirective';
|
|
385
|
+
/**
|
|
386
|
+
* Directive mode:
|
|
387
|
+
* - `'reuse'`: transitive (visible to files that further import this file).
|
|
388
|
+
* The recommended default per spec §26.4.
|
|
389
|
+
* - `'use'`: non-transitive (private to this file).
|
|
390
|
+
*/
|
|
391
|
+
mode: 'use' | 'reuse';
|
|
392
|
+
/** What to import: everything (`*`) or a selective list. */
|
|
393
|
+
spec: ImportSpec;
|
|
394
|
+
/**
|
|
395
|
+
* The relative path string from the `from` clause, with quotes stripped.
|
|
396
|
+
* Stored as-is; path resolution happens at name-resolution time (P5+).
|
|
397
|
+
*/
|
|
398
|
+
from: string;
|
|
399
|
+
/**
|
|
400
|
+
* Optional metadata settings appearing between `from '...'` and the
|
|
401
|
+
* clone block. In v0.2 phase 1, only `cloned_at` is defined; the parser
|
|
402
|
+
* is permissive and stores any settings here.
|
|
403
|
+
*/
|
|
404
|
+
settings: Setting[];
|
|
405
|
+
/**
|
|
406
|
+
* The embedded clone block. When present, this is the authoritative
|
|
407
|
+
* content for the import. When absent (reference-only directive), the
|
|
408
|
+
* parser must resolve the `from` path at parse time (P5+).
|
|
409
|
+
*/
|
|
410
|
+
clone?: CloneBlock;
|
|
411
|
+
span: Span;
|
|
412
|
+
}
|
|
413
|
+
/** Selective vs import-all distinction. */
|
|
414
|
+
export type ImportSpec = {
|
|
415
|
+
kind: 'ImportAll';
|
|
416
|
+
} | {
|
|
417
|
+
kind: 'ImportList';
|
|
418
|
+
items: ImportItem[];
|
|
419
|
+
};
|
|
420
|
+
/**
|
|
421
|
+
* A single import item in a selective `{ ... }` list:
|
|
422
|
+
*
|
|
423
|
+
* entity core.dim_customer
|
|
424
|
+
* type Email as PII_Email
|
|
425
|
+
* field core.dim_customer.email
|
|
426
|
+
*
|
|
427
|
+
* The element type is one of the keywords from §26.3 (table, entity,
|
|
428
|
+
* collection, record, enum, tablepartial, note, schema, container,
|
|
429
|
+
* tablegroup, type, edge, view, diagramview, field). Stored lowercased.
|
|
430
|
+
*
|
|
431
|
+
* The source path follows xDBML's standard dotted form. Container.Entity
|
|
432
|
+
* for an entity inside a Container; Container.Entity.Field for a field.
|
|
433
|
+
*/
|
|
434
|
+
export interface ImportItem {
|
|
435
|
+
kind: 'ImportItem';
|
|
436
|
+
/** Lowercased element type keyword. */
|
|
437
|
+
elementType: string;
|
|
438
|
+
/** Dotted source path. */
|
|
439
|
+
sourcePath: string;
|
|
440
|
+
/** Optional rename in the current file's namespace. */
|
|
441
|
+
alias?: string;
|
|
442
|
+
span: Span;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* A clone block embedding the imported declarations directly. For non-field
|
|
446
|
+
* imports the clone contains TopLevelStatement nodes (the natural shape of
|
|
447
|
+
* an entity, type, container, etc. clone). Field imports are not supported
|
|
448
|
+
* in P4 -- when they land, this type may grow to a wider union.
|
|
449
|
+
*
|
|
450
|
+
* Per spec §26.6, the clone contains exactly the imported declaration(s),
|
|
451
|
+
* without surrounding wrappers from the source file. For an entity clone
|
|
452
|
+
* the content is the EntityDeclaration alone (no container wrapper); for a
|
|
453
|
+
* container clone the content is the ContainerDeclaration including its
|
|
454
|
+
* intrinsic entities.
|
|
455
|
+
*/
|
|
456
|
+
export interface CloneBlock {
|
|
457
|
+
kind: 'CloneBlock';
|
|
458
|
+
/**
|
|
459
|
+
* Statements that the importing file pulls in from the source. Most are
|
|
460
|
+
* top-level shapes (Entity, Type, Enum, Container, etc.). The one
|
|
461
|
+
* exception is `FieldDeclaration`: when the parent directive imports
|
|
462
|
+
* one or more fields via `field <path>` items (spec §26.8), each field
|
|
463
|
+
* appears here as a bare FieldDeclaration with no entity wrapper.
|
|
464
|
+
* The `flatten()` pass lifts each bare field into a synthetic
|
|
465
|
+
* TypeDeclaration at file scope so downstream consumers see a normal
|
|
466
|
+
* Named Type.
|
|
467
|
+
*/
|
|
468
|
+
statements: (TopLevelStatement | FieldDeclaration)[];
|
|
469
|
+
span: Span;
|
|
470
|
+
}
|
|
471
|
+
export interface Setting {
|
|
472
|
+
kind: 'Setting';
|
|
473
|
+
/** Setting name, lowercased for canonical comparison. Source casing is preserved in `nameSource`. */
|
|
474
|
+
name: string;
|
|
475
|
+
nameSource: string;
|
|
476
|
+
/** Value, if any. A pure flag like `pk` has `value: null`. */
|
|
477
|
+
value: SettingValue | null;
|
|
478
|
+
span: Span;
|
|
479
|
+
}
|
|
480
|
+
export type SettingValue = StringValue | NumberValue | BooleanValue | NullValue | IdentifierValue | ExpressionValue | ListValue | RefValue;
|
|
481
|
+
export interface StringValue {
|
|
482
|
+
kind: 'StringValue';
|
|
483
|
+
/** The string content with surrounding quotes already stripped */
|
|
484
|
+
value: string;
|
|
485
|
+
/** Triple-quoted multi-line string */
|
|
486
|
+
multiline: boolean;
|
|
487
|
+
span: Span;
|
|
488
|
+
}
|
|
489
|
+
export interface NumberValue {
|
|
490
|
+
kind: 'NumberValue';
|
|
491
|
+
value: string;
|
|
492
|
+
span: Span;
|
|
493
|
+
}
|
|
494
|
+
export interface BooleanValue {
|
|
495
|
+
kind: 'BooleanValue';
|
|
496
|
+
value: boolean;
|
|
497
|
+
span: Span;
|
|
498
|
+
}
|
|
499
|
+
export interface NullValue {
|
|
500
|
+
kind: 'NullValue';
|
|
501
|
+
span: Span;
|
|
502
|
+
}
|
|
503
|
+
export interface IdentifierValue {
|
|
504
|
+
kind: 'IdentifierValue';
|
|
505
|
+
/** A bare or dotted identifier used as a value, e.g. `Oracle`, `cascade`, `set null`. */
|
|
506
|
+
value: string;
|
|
507
|
+
span: Span;
|
|
508
|
+
}
|
|
509
|
+
export interface ExpressionValue {
|
|
510
|
+
kind: 'ExpressionValue';
|
|
511
|
+
/** Source text inside backticks, no surrounding backticks */
|
|
512
|
+
expression: string;
|
|
513
|
+
span: Span;
|
|
514
|
+
}
|
|
515
|
+
export interface ListValue {
|
|
516
|
+
kind: 'ListValue';
|
|
517
|
+
items: SettingValue[];
|
|
518
|
+
span: Span;
|
|
519
|
+
}
|
|
520
|
+
/** An inline `ref: > target.field` setting carries a small ref spec. */
|
|
521
|
+
export interface RefValue {
|
|
522
|
+
kind: 'RefValue';
|
|
523
|
+
operator: CardinalityOperator;
|
|
524
|
+
target: RefEndpoint;
|
|
525
|
+
span: Span;
|
|
526
|
+
}
|
|
527
|
+
export interface ParseOptions {
|
|
528
|
+
/**
|
|
529
|
+
* The absolute or canonical path of the file being parsed. Used as the
|
|
530
|
+
* base directory for relative `from './...'` paths in `use`/`reuse`
|
|
531
|
+
* directives. If undefined, relative paths in directives can only be
|
|
532
|
+
* resolved when they're already absolute (rare). For files loaded via
|
|
533
|
+
* `readFile`, the parser passes the resolved path automatically.
|
|
534
|
+
*/
|
|
535
|
+
filePath?: string;
|
|
536
|
+
/**
|
|
537
|
+
* Synchronous file reader. Called by the parser when it needs to resolve
|
|
538
|
+
* a reference-only module directive. The argument is a resolved, stable
|
|
539
|
+
* key: an absolute path for local sources, or a normalized `https://` URL
|
|
540
|
+
* for remote (v0.3) sources (when a directive's `from` is a URL, or a
|
|
541
|
+
* relative reference inside a remote module resolves to one). The function
|
|
542
|
+
* should return the source text for that key, or throw if it is missing
|
|
543
|
+
* or unreadable.
|
|
544
|
+
*
|
|
545
|
+
* Because this reader is synchronous, a host that supports remote sources
|
|
546
|
+
* must return the fetched text from a cache it populated beforehand. The
|
|
547
|
+
* network fetch, and its SSRF / redirect / size / timeout obligations
|
|
548
|
+
* (spec §26.14.5), live in the host's resolver, not in the parser.
|
|
549
|
+
*
|
|
550
|
+
* If absent, reference-only directives fall back to the P4 rejection
|
|
551
|
+
* with a clear "no resolver available" message. Clone-block-bearing
|
|
552
|
+
* directives still work without a resolver because their content is
|
|
553
|
+
* embedded in the importing file.
|
|
554
|
+
*/
|
|
555
|
+
readFile?: (pathOrUrl: string) => string;
|
|
556
|
+
/**
|
|
557
|
+
* Maximum recursion depth when resolving directives. Each `from` traversal
|
|
558
|
+
* deepens the stack by one; circular imports trigger the cycle-detection
|
|
559
|
+
* path BEFORE this counter increases (cycles produce a parsed directive
|
|
560
|
+
* with an empty clone, not a depth-limit error). The default (8) is
|
|
561
|
+
* generous for realistic module graphs and small enough to keep the
|
|
562
|
+
* stack bounded under pathological inputs.
|
|
563
|
+
*/
|
|
564
|
+
maxDepth?: number;
|
|
565
|
+
}
|
package/dist/ast.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xDBML AST node types.
|
|
3
|
+
*
|
|
4
|
+
* The AST is intentionally narrow: each node carries only what's needed
|
|
5
|
+
* to round-trip xDBML source and to feed a downstream lowering pass
|
|
6
|
+
* (DDL emitters, JSON Schema emitters, etc.). Generic open-vocabulary
|
|
7
|
+
* settings are kept as Setting nodes rather than promoted to typed
|
|
8
|
+
* fields, because the spec leaves the settings vocabulary open.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xdbml/parse -- proof-of-concept parser for xDBML v0.1 and v0.2.
|
|
3
|
+
*
|
|
4
|
+
* Public API:
|
|
5
|
+
*
|
|
6
|
+
* parse(source, options?): XDbmlDocument
|
|
7
|
+
* Parse an xDBML document. Returns a fully-typed AST. Passing
|
|
8
|
+
* `options.readFile` enables cross-file `use`/`reuse` resolution
|
|
9
|
+
* (see ParseOptions for details).
|
|
10
|
+
*
|
|
11
|
+
* tokenize(source): Token[]
|
|
12
|
+
* Tokenize the source without parsing. Useful for syntax highlighting.
|
|
13
|
+
*
|
|
14
|
+
* flatten(doc): XDbmlDocument
|
|
15
|
+
* Produce a flattened view of a document where ModuleImportDirective
|
|
16
|
+
* nodes have been replaced by their clone-block content. Useful for
|
|
17
|
+
* downstream consumers that don't care about module provenance.
|
|
18
|
+
*
|
|
19
|
+
* resolveNames(doc): ResolutionResult
|
|
20
|
+
* Run the name-resolution pass. Returns a symbol table for queries
|
|
21
|
+
* and a list of diagnostics (unresolved references, name conflicts).
|
|
22
|
+
* The AST is not mutated. Flattens the input internally.
|
|
23
|
+
*
|
|
24
|
+
* The parser is DBML-3.13.6 compatible: a document without an `xdbml: ...`
|
|
25
|
+
* version header still parses, and DBML constructs are preserved.
|
|
26
|
+
*/
|
|
27
|
+
export * from './ast.ts';
|
|
28
|
+
export { tokenize, TokenKind, LexError } from './lexer.ts';
|
|
29
|
+
export type { Token } from './lexer.ts';
|
|
30
|
+
export { parse, Parser, ParseError } from './parser.ts';
|
|
31
|
+
export { flatten } from './module-resolver.ts';
|
|
32
|
+
export { classifyModuleSource, isUrlKey, ModuleSourceError, } from './module-resolver.ts';
|
|
33
|
+
export type { ModuleSource } from './module-resolver.ts';
|
|
34
|
+
export { resolveNames, SymbolTable } from './name-resolver.ts';
|
|
35
|
+
export type { Diagnostic, DiagnosticCode, ResolutionResult, SymbolEntry, SymbolKind, } from './name-resolver.ts';
|
|
36
|
+
export { xdbmlLanguageConfig, xdbmlMonarchTokensProvider, } from './monarch.ts';
|
|
37
|
+
export type { XDbmlLanguageConfiguration, XDbmlMonarchLanguage, } from './monarch.ts';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xdbml/parse -- proof-of-concept parser for xDBML v0.1 and v0.2.
|
|
3
|
+
*
|
|
4
|
+
* Public API:
|
|
5
|
+
*
|
|
6
|
+
* parse(source, options?): XDbmlDocument
|
|
7
|
+
* Parse an xDBML document. Returns a fully-typed AST. Passing
|
|
8
|
+
* `options.readFile` enables cross-file `use`/`reuse` resolution
|
|
9
|
+
* (see ParseOptions for details).
|
|
10
|
+
*
|
|
11
|
+
* tokenize(source): Token[]
|
|
12
|
+
* Tokenize the source without parsing. Useful for syntax highlighting.
|
|
13
|
+
*
|
|
14
|
+
* flatten(doc): XDbmlDocument
|
|
15
|
+
* Produce a flattened view of a document where ModuleImportDirective
|
|
16
|
+
* nodes have been replaced by their clone-block content. Useful for
|
|
17
|
+
* downstream consumers that don't care about module provenance.
|
|
18
|
+
*
|
|
19
|
+
* resolveNames(doc): ResolutionResult
|
|
20
|
+
* Run the name-resolution pass. Returns a symbol table for queries
|
|
21
|
+
* and a list of diagnostics (unresolved references, name conflicts).
|
|
22
|
+
* The AST is not mutated. Flattens the input internally.
|
|
23
|
+
*
|
|
24
|
+
* The parser is DBML-3.13.6 compatible: a document without an `xdbml: ...`
|
|
25
|
+
* version header still parses, and DBML constructs are preserved.
|
|
26
|
+
*/
|
|
27
|
+
export * from "./ast.js";
|
|
28
|
+
export { tokenize, TokenKind, LexError } from "./lexer.js";
|
|
29
|
+
export { parse, Parser, ParseError } from "./parser.js";
|
|
30
|
+
export { flatten } from "./module-resolver.js";
|
|
31
|
+
export { classifyModuleSource, isUrlKey, ModuleSourceError, } from "./module-resolver.js";
|
|
32
|
+
export { resolveNames, SymbolTable } from "./name-resolver.js";
|
|
33
|
+
export { xdbmlLanguageConfig, xdbmlMonarchTokensProvider, } from "./monarch.js";
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared keyword vocabulary for xDBML tokenizers and highlighters.
|
|
3
|
+
*
|
|
4
|
+
* This module is the single source of truth for the keyword lists
|
|
5
|
+
* that drive syntax highlighting across multiple surfaces:
|
|
6
|
+
*
|
|
7
|
+
* - parser/src/monarch.ts the playground's in-editor highlighter
|
|
8
|
+
* - tools/textmate/... the TextMate grammar for VS Code,
|
|
9
|
+
* Shiki (xdbml.org code blocks, Claude
|
|
10
|
+
* chat code blocks, etc.), and GitHub
|
|
11
|
+
*
|
|
12
|
+
* The grammar in grammar/xDBML.g4 is the language's canonical
|
|
13
|
+
* specification; this file mirrors its keyword vocabulary in a form
|
|
14
|
+
* convenient for consumers. A keyword-consistency test (in
|
|
15
|
+
* parser/test/) asserts that every keyword listed here is recognized
|
|
16
|
+
* by the parser.
|
|
17
|
+
*
|
|
18
|
+
* When adding a keyword to xDBML:
|
|
19
|
+
* 1. Update the grammar in grammar/xDBML.g4
|
|
20
|
+
* 2. Update parser/src/parser.ts if the parser needs to recognize it
|
|
21
|
+
* 3. Add it to the right array below
|
|
22
|
+
* 4. Re-run the TextMate grammar build script
|
|
23
|
+
* (tools/textmate/scripts/build.mjs)
|
|
24
|
+
* 5. Run `npm test` in the parser package to verify all three
|
|
25
|
+
* consumers see the keyword
|
|
26
|
+
*
|
|
27
|
+
* All keywords here are case-insensitive in xDBML. Stored in
|
|
28
|
+
* lower-case as the canonical form; matchers should be case-insensitive.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CONTAINER_KEYWORDS: readonly ["container", "schema", "database", "keyspace", "namespace", "dataset", "bucket"];
|
|
31
|
+
export declare const ENTITY_KEYWORDS: readonly ["table", "entity", "collection", "record"];
|
|
32
|
+
/**
|
|
33
|
+
* The full set of declaration keywords. Includes containers,
|
|
34
|
+
* entities, and other top-level constructs.
|
|
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"];
|
|
37
|
+
export declare const STRUCTURAL_TYPE_KEYWORDS: readonly ["object", "struct", "array", "list", "map", "dict", "dictionary", "set", "json", "jsonb", "variant"];
|
|
38
|
+
export declare const POLYMORPHISM_KEYWORDS: readonly ["union", "oneof", "anyof", "allof"];
|
|
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
|
+
export declare const BSON_TYPES: readonly ["objectid", "decimal128", "bindata", "minkey", "maxkey", "symbol", "regex", "long", "double"];
|
|
41
|
+
export declare const SETTING_FLAGS: readonly ["pk", "primary", "key", "unique", "null", "not", "required", "increment", "inactive"];
|
|
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", "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"];
|
|
43
|
+
export declare const GRANULARITY_VALUES: readonly ["year", "quarter", "month", "week", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"];
|
|
44
|
+
export declare const DIRECTIVE_KEYWORDS: readonly ["xdbml", "experimental"];
|
|
45
|
+
export declare const MODULE_KEYWORDS: readonly ["use", "reuse", "from", "as"];
|