@dbml/parse 10.4.0-alpha.2 → 11.0.0-alpha.2

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 (36) hide show
  1. package/LICENSE +0 -0
  2. package/dist/dbml-parse.js +38 -28
  3. package/dist/dbml-parse.mjs +5991 -4945
  4. package/dist/src/compiler/index.d.ts +40 -8
  5. package/dist/src/compiler/projectLayout/layout.d.ts +0 -7
  6. package/dist/src/compiler/queries/files/fileKind.d.ts +18 -0
  7. package/dist/src/compiler/queries/transform/index.d.ts +2 -1
  8. package/dist/src/compiler/queries/transform/renameElement.d.ts +13 -0
  9. package/dist/src/compiler/queries/transform/types.d.ts +10 -1
  10. package/dist/src/compiler/queries/transform/utils/arch.d.ts +6 -0
  11. package/dist/src/core/arch/icons.d.ts +5 -0
  12. package/dist/src/core/arch/read.d.ts +51 -0
  13. package/dist/src/core/arch/vocabulary.d.ts +11 -0
  14. package/dist/src/core/global_modules/arch/index.d.ts +2 -0
  15. package/dist/src/core/global_modules/arch/interpret.d.ts +11 -0
  16. package/dist/src/core/global_modules/arch/utils.d.ts +7 -0
  17. package/dist/src/core/global_modules/index.d.ts +15 -1
  18. package/dist/src/core/global_modules/metadata/utils.d.ts +3 -1
  19. package/dist/src/core/global_modules/program/bind.d.ts +1 -0
  20. package/dist/src/core/global_modules/program/interpret.d.ts +2 -0
  21. package/dist/src/core/lexer/lexer.d.ts +23 -1
  22. package/dist/src/core/local_modules/arch/index.d.ts +2 -0
  23. package/dist/src/core/local_modules/index.d.ts +1 -0
  24. package/dist/src/core/parser/parser.d.ts +18 -1
  25. package/dist/src/core/types/errors.d.ts +17 -1
  26. package/dist/src/core/types/filepath.d.ts +1 -3
  27. package/dist/src/core/types/nodes.d.ts +1 -0
  28. package/dist/src/core/types/schemaJson/types.d.ts +63 -1
  29. package/dist/src/core/types/symbol/metadata.d.ts +12 -1
  30. package/dist/src/core/types/symbol/symbols.d.ts +18 -0
  31. package/dist/src/core/types/tokens.d.ts +2 -0
  32. package/dist/src/index.d.ts +19 -4
  33. package/dist/src/services/definition/provider.d.ts +0 -1
  34. package/dist/src/services/suggestions/provider.d.ts +1 -3
  35. package/dist/src/services/suggestions/use.d.ts +1 -4
  36. package/package.json +3 -3
@@ -1,9 +1,22 @@
1
+ import { GlobalModule } from '../core/global_modules/types';
2
+ import { ParserOptions } from '../core/parser/parser';
3
+ import { LexerOptions } from '../core/lexer/lexer';
4
+ import { SyntaxToken } from '../core/types/tokens';
5
+ import { FileKind, FileScan } from './queries/files/fileKind';
1
6
  import { Filepath } from '../core/types/filepath';
2
7
  import { SyntaxNode, SyntaxNodeIdGenerator } from '../core/types/nodes';
3
8
  import { NodeSymbolIdGenerator, SymbolFactory } from '../core/types/symbol';
4
9
  import { DBMLCodeActionProvider, DBMLCompletionItemProvider, DBMLDefinitionProvider, DBMLDiagnosticsProvider, DBMLReferencesProvider } from '../services/index';
5
10
  import { DbmlProjectLayout } from './projectLayout';
6
11
  import { addDoubleQuoteIfNeeded, escapeString, formatRecordValue, isValidIdentifier, normalizeQualifiedName, splitQualifiedIdentifier, unescapeString } from './queries/utils';
12
+ /**
13
+ * Grammar switches a dialect asks for, gathered in one place so the Compiler does not grow a
14
+ * parameter per stage. Every switch inside is off by default, so DBML is exactly what it was.
15
+ */
16
+ export interface DialectOptions {
17
+ lexer?: LexerOptions;
18
+ parser?: ParserOptions;
19
+ }
7
20
  export { ScopeKind } from './types';
8
21
  export type { TextEdit } from './queries/transform';
9
22
  export { addDoubleQuoteIfNeeded, escapeString, formatRecordValue, isValidIdentifier, normalizeQualifiedName, splitQualifiedIdentifier, unescapeString, };
@@ -12,8 +25,27 @@ export default class Compiler {
12
25
  readonly nodeIdGenerator: SyntaxNodeIdGenerator;
13
26
  readonly symbolIdGenerator: NodeSymbolIdGenerator;
14
27
  readonly symbolFactory: SymbolFactory;
15
- constructor(layout: DbmlProjectLayout);
28
+ readonly explicitModules: GlobalModule[] | undefined;
29
+ private readonly explicitDialect;
30
+ readonly dialect: DialectOptions;
31
+ /**
32
+ * @param layout the structure of the DbmlProject
33
+ * @param modules the element vocabulary for every file. When omitted, each file uses the
34
+ * modules of its own kind (DBML or architecture).
35
+ * @param dialect grammar switches for every file. When omitted, each file gets its kind's switches.
36
+ */
37
+ constructor(layout: DbmlProjectLayout, modules?: GlobalModule[], dialect?: DialectOptions);
16
38
  getSource(filepath: Filepath): string | undefined;
39
+ lexerOptions(): LexerOptions;
40
+ parserOptions(kind: FileKind): ParserOptions;
41
+ private fileScans;
42
+ private fileKinds;
43
+ scanFile(filepath: Filepath, tokens?: readonly SyntaxToken[]): FileScan;
44
+ fileKind(filepath: Filepath): FileKind;
45
+ fileKindForParse(filepath: Filepath, tokens?: readonly SyntaxToken[]): FileKind;
46
+ parsedFileKind(filepath: Filepath): FileKind;
47
+ private decideKind;
48
+ private refreshFileKind;
17
49
  private sourceSnapshot;
18
50
  private cleanStaleLocalCache;
19
51
  private entrypointsSnapshot;
@@ -70,8 +102,9 @@ export default class Compiler {
70
102
  }[];
71
103
  };
72
104
  }>;
73
- nodeAtPosition: (filepath: Filepath, offset: number) => SyntaxNode | import('..').SyntaxToken | undefined;
105
+ nodeAtPosition: (filepath: Filepath, offset: number) => SyntaxNode | SyntaxToken | undefined;
74
106
  renameTable: (filepath: Filepath, oldName: string | import('..').TableIdentifier, newName: string | import('..').TableIdentifier) => Map<string, string>;
107
+ renameElement: (filepath: Filepath, oldHandle: string, newName: string) => Map<string, string>;
75
108
  updateElementSetting: (filepath: Filepath, target: import('..').ElementIdentifier, settingName: string, value: string | null | undefined) => string;
76
109
  updateElementSettingEdit: (filepath: Filepath, target: import('..').ElementIdentifier, settingName: string, value: string | null | undefined) => import('.').TextEdit[];
77
110
  syncDiagramView: (filepath: Filepath, operations: import('..').DiagramViewSyncOperation[], blocks?: import('..').DiagramViewBlock[] | undefined) => {
@@ -83,22 +116,22 @@ export default class Compiler {
83
116
  edits: import('.').TextEdit[];
84
117
  };
85
118
  readonly token: {
86
- invalidStream: (filepath: Filepath) => readonly import('..').SyntaxToken[];
87
- flatStream: (filepath: Filepath) => readonly import('..').SyntaxToken[];
119
+ invalidStream: (filepath: Filepath) => readonly SyntaxToken[];
120
+ flatStream: (filepath: Filepath) => readonly SyntaxToken[];
88
121
  };
89
122
  readonly parse: {
90
123
  source: (filepath: Filepath) => string;
91
124
  ast: (filepath?: Filepath) => Readonly<import('../core/types/nodes').ProgramNode>;
92
125
  errors: (filepath?: Filepath) => readonly Readonly<import('..').CompileError>[];
93
- warnings: (filepath?: Filepath) => readonly Readonly<import('..').CompileWarning>[];
94
- tokens: (filepath?: Filepath) => readonly Readonly<import('..').SyntaxToken>[];
126
+ warnings: (filepath?: Filepath) => readonly Readonly<import('../core/types').CompileWarning>[];
127
+ tokens: (filepath?: Filepath) => readonly Readonly<SyntaxToken>[];
95
128
  rawDb: (filepath?: Filepath) => Readonly<import('..').Database> | undefined;
96
129
  publicSymbolTable: (filepath?: Filepath) => readonly Readonly<import('../core/types/symbol').NodeSymbol>[] | undefined;
97
130
  };
98
131
  readonly container: {
99
132
  stack: (filepath: Filepath, offset: number) => readonly Readonly<SyntaxNode>[];
100
133
  token: (filepath: Filepath, offset: number) => {
101
- token: import('..').SyntaxToken;
134
+ token: SyntaxToken;
102
135
  index: number;
103
136
  } | {
104
137
  token: undefined;
@@ -111,7 +144,6 @@ export default class Compiler {
111
144
  initMonacoServices(options?: {
112
145
  autocompletion?: {
113
146
  triggerCharacters?: string[];
114
- fileListDepth?: number;
115
147
  };
116
148
  }): {
117
149
  definitionProvider: DBMLDefinitionProvider;
@@ -1,12 +1,6 @@
1
1
  import { Filepath } from '../../core/types/filepath';
2
- export interface FileSpecifierInfo {
3
- specifier: string;
4
- label?: string;
5
- detail?: string;
6
- }
7
2
  export interface DbmlProjectLayout {
8
3
  resolveFileSpecifier(currentFilepath: Filepath, specifier: string): Filepath | undefined;
9
- getFileSpecifierInfo(currentFilepath: Filepath, targetFilepath: Filepath): FileSpecifierInfo | undefined;
10
4
  getSource(filePath: Filepath): string | undefined;
11
5
  exists(filePath: Filepath): boolean;
12
6
  isFile(filePath: Filepath): boolean;
@@ -18,7 +12,6 @@ export declare class MemoryProjectLayout implements DbmlProjectLayout {
18
12
  private readonly files;
19
13
  constructor(files?: Map<string, string> | Record<string, string>);
20
14
  resolveFileSpecifier(currentFilepath: Filepath, relativePath: string): Filepath | undefined;
21
- getFileSpecifierInfo(currentFilepath: Filepath, targetFilepath: Filepath): FileSpecifierInfo | undefined;
22
15
  setSource(filePath: Filepath, content: string): void;
23
16
  getSource(filePath: Filepath): string | undefined;
24
17
  deleteSource(filePath: Filepath): void;
@@ -0,0 +1,18 @@
1
+ import { SyntaxToken } from '../../../core/types/tokens';
2
+ export type FileKind = 'dbml' | 'arch';
3
+ export declare const ARCH_DIAGRAM_TYPES: Set<string>;
4
+ export declare const isArchDiagramType: (type: string | null | undefined) => boolean;
5
+ export interface FileScan {
6
+ frontMatter: Record<string, string>;
7
+ topWords: string[];
8
+ kindNames: string[];
9
+ usePaths: string[];
10
+ }
11
+ export declare function readFrontMatter(block: string): Record<string, string>;
12
+ export declare function frontMatterToken(tokens: readonly SyntaxToken[]): SyntaxToken | undefined;
13
+ export declare function scanTokens(tokens: readonly SyntaxToken[]): FileScan;
14
+ export interface FileKindResult {
15
+ kind: FileKind;
16
+ dependsOnImports: boolean;
17
+ }
18
+ export declare function decideFileKind(scan: FileScan, importedScans: () => FileScan[]): FileKindResult;
@@ -1,6 +1,7 @@
1
1
  export { renameTable } from './renameTable';
2
+ export { renameElement } from './renameElement';
2
3
  export { updateElementSetting, updateElementSettingEdit } from './updateElementSetting';
3
4
  export { syncDiagramView, findDiagramViewBlocks, type DiagramViewSyncOperation, type DiagramViewBlock, } from './syncDiagramView';
4
5
  export { syncDep, generateDepBlock, type DepSyncOperation, type DepSyncEdge, type DepEndpointRef, } from './syncDep';
5
6
  export { applyTextEdits, type TextEdit } from './applyTextEdits';
6
- export type { ElementIdentifier, SchemaIdentifier, TableIdentifier, ColumnIdentifier, EnumIdentifier, EndpointRef, RefIdentifier, DepIdentifier, NoteIdentifier, TableGroupIdentifier, } from './types';
7
+ export type { ElementIdentifier, SchemaIdentifier, TableIdentifier, ColumnIdentifier, EnumIdentifier, EndpointRef, RefIdentifier, DepIdentifier, NoteIdentifier, TableGroupIdentifier, ArchElementIdentifier, ArchLinkIdentifier, } from './types';
@@ -0,0 +1,13 @@
1
+ import { Filepath } from '../../../core/types/filepath';
2
+ import { default as Compiler } from '../../index';
3
+ /**
4
+ * Renames an architecture element (node, group or note box) in `filepath`.
5
+ *
6
+ * With an `as` alias, links, groups and metadata name the element by its alias, so only the
7
+ * name changes. Without one the name is the handle, so every link endpoint, group member and
8
+ * metadata target in the same file that names it is renamed too.
9
+ *
10
+ * Returns a map of absolute file paths to new source content. An empty map indicates a no-op
11
+ * (lookup miss or name collision).
12
+ */
13
+ export declare function renameElement(this: Compiler, filepath: Filepath, oldHandle: string, newName: string): Map<string, string>;
@@ -1,6 +1,6 @@
1
1
  import { SymbolKind } from '../../../core/types/symbol';
2
2
  import { MetadataKind } from '../../../core/types/symbol/metadata';
3
- export type ElementIdentifier = (SchemaIdentifier | TableIdentifier | ColumnIdentifier | EnumIdentifier | RefIdentifier | DepIdentifier | NoteIdentifier | TableGroupIdentifier) & {
3
+ export type ElementIdentifier = (SchemaIdentifier | TableIdentifier | ColumnIdentifier | EnumIdentifier | RefIdentifier | DepIdentifier | NoteIdentifier | TableGroupIdentifier | ArchElementIdentifier | ArchLinkIdentifier) & {
4
4
  kind: string;
5
5
  };
6
6
  export interface SchemaIdentifier {
@@ -46,3 +46,12 @@ export interface TableGroupIdentifier {
46
46
  schema?: string;
47
47
  name: string;
48
48
  }
49
+ export interface ArchElementIdentifier {
50
+ kind?: typeof SymbolKind.Element;
51
+ name: string;
52
+ }
53
+ export interface ArchLinkIdentifier {
54
+ kind?: 'Link';
55
+ from: string;
56
+ to: string;
57
+ }
@@ -0,0 +1,6 @@
1
+ import { Filepath } from '../../../../core/types/filepath';
2
+ import { ElementDeclarationNode } from '../../../../core/types/nodes';
3
+ import { default as Compiler } from '../../../index';
4
+ export declare function archDeclarations(compiler: Compiler, filepath: Filepath): ElementDeclarationNode[];
5
+ export declare function findArchElement(compiler: Compiler, filepath: Filepath, handle: string): ElementDeclarationNode | undefined;
6
+ export declare function findArchLink(compiler: Compiler, filepath: Filepath, from: string, to: string): ElementDeclarationNode | undefined;
@@ -0,0 +1,5 @@
1
+ export declare const ICON_NAMES: string[];
2
+ /** what people actually type; an alias costs one line and saves a diagnostic */
3
+ export declare const ICON_ALIAS: Record<string, string>;
4
+ export declare const resolveIcon: (name: string) => string;
5
+ export declare const isIconName: (name: string) => boolean;
@@ -0,0 +1,51 @@
1
+ import { ElementDeclarationNode, ListExpressionNode, SyntaxNode } from '../types/nodes';
2
+ import { ArchSettingValue, ArchSettings } from '../types/schemaJson';
3
+ export type ArchSort = 'node' | 'group' | 'note' | 'kind' | 'link' | 'metadata' | 'project';
4
+ export declare const declarationWord: (node: ElementDeclarationNode) => string | undefined;
5
+ export declare function isTopLevel(node: SyntaxNode): node is ElementDeclarationNode;
6
+ export declare function archSort(node: SyntaxNode): ArchSort | undefined;
7
+ export declare function topLevelDeclaration(node: SyntaxNode): ElementDeclarationNode | undefined;
8
+ export declare function nameOf(node?: SyntaxNode): string | undefined;
9
+ export declare const handleOf: (node: ElementDeclarationNode) => string | undefined;
10
+ export declare function numberOf(node?: SyntaxNode): number | null;
11
+ export declare function valueOf(node: SyntaxNode): ArchSettingValue | undefined;
12
+ export declare function settingsOf(list?: ListExpressionNode): ArchSettings;
13
+ export declare function bodyOf(node: ElementDeclarationNode): SyntaxNode[];
14
+ export interface Row {
15
+ callee: SyntaxNode | undefined;
16
+ args: SyntaxNode[];
17
+ settings: ListExpressionNode | undefined;
18
+ }
19
+ export declare function rowOf(node: SyntaxNode | undefined): Row | undefined;
20
+ export interface Infix {
21
+ left: SyntaxNode;
22
+ op: string;
23
+ right: SyntaxNode;
24
+ }
25
+ export declare function infixOf(node?: SyntaxNode): Infix | undefined;
26
+ export declare function endpointNode(node: SyntaxNode): SyntaxNode;
27
+ export declare const LINK_OPS: Set<string>;
28
+ export interface LinkParts {
29
+ row: Row | undefined;
30
+ infix: Infix;
31
+ }
32
+ export declare function linkPartsOf(declaration: ElementDeclarationNode): LinkParts | undefined;
33
+ export interface Property {
34
+ key: string;
35
+ value: ArchSettingValue | undefined;
36
+ }
37
+ export declare function propertyOf(node: SyntaxNode): Property | undefined;
38
+ export declare function noteDeclarationOf(declaration: ElementDeclarationNode): ElementDeclarationNode | undefined;
39
+ export declare function noteTextOf(note: ElementDeclarationNode): string;
40
+ export declare function noteBoxTextOf(declaration: ElementDeclarationNode): string;
41
+ export declare const IMAGE_URL: RegExp;
42
+ export declare const IMAGE_REFUSED = "A picture must be an https: URL or a data:image/ URI.";
43
+ export interface BodyRead {
44
+ settings: ArchSettings;
45
+ problems: {
46
+ code: 'bad' | 'duplicate';
47
+ message: string;
48
+ node: SyntaxNode;
49
+ }[];
50
+ }
51
+ export declare function readBody(declaration: ElementDeclarationNode, settings: ArchSettings, bareWordIsAFlag: boolean): BodyRead;
@@ -0,0 +1,11 @@
1
+ export type Category = 'compute' | 'data' | 'net' | 'edge' | 'people' | 'ops' | 'custom';
2
+ export interface KindSpec {
3
+ icon: string;
4
+ category: Category;
5
+ }
6
+ export declare const BUILTIN_KINDS: Record<string, KindSpec>;
7
+ export declare const builtinKindName: (typed: string) => string | undefined;
8
+ export declare function suggestKind(typed: string): string;
9
+ export declare const RESERVED: Set<string>;
10
+ export declare const isReserved: (word: string) => boolean;
11
+ export declare function suggestIcon(typed: string): string;
@@ -0,0 +1,2 @@
1
+ import { GlobalModule } from '../types';
2
+ export declare const archModule: GlobalModule;
@@ -0,0 +1,11 @@
1
+ import { default as Compiler } from '../../../compiler';
2
+ import { Filepath } from '../../types/filepath';
3
+ import { default as Report } from '../../types/report';
4
+ import { ArchSettings, Group, Kind, Link, Node, NoteBox } from '../../types/schemaJson';
5
+ import { ElementSymbol, KindSymbol } from '../../types/symbol';
6
+ import { ArchMetadataElementMetadata, LinkMetadata } from '../../types/symbol/metadata';
7
+ export declare function interpretElement(compiler: Compiler, symbol: ElementSymbol, filepath: Filepath): Report<Node | Group | NoteBox | undefined>;
8
+ export declare function interpretKind(symbol: KindSymbol): Report<Kind | undefined>;
9
+ export declare function builtinKinds(): Kind[];
10
+ export declare function interpretLink(compiler: Compiler, metadata: LinkMetadata): Report<Link | undefined>;
11
+ export declare function interpretArchMetadata(metadata: ArchMetadataElementMetadata): Report<ArchSettings>;
@@ -0,0 +1,7 @@
1
+ import { default as Compiler } from '../../../compiler';
2
+ import { Filepath } from '../../types/filepath';
3
+ import { NodeSymbol, SymbolKind } from '../../types/symbol';
4
+ export declare function lookupVisible(compiler: Compiler, filepath: Filepath, kind: SymbolKind, name: string): NodeSymbol | undefined;
5
+ export declare function visibleKinds(compiler: Compiler, filepath: Filepath): Map<string, NodeSymbol>;
6
+ export declare function resolveRole(compiler: Compiler, filepath: Filepath, word: string): string | undefined;
7
+ export declare function originalHandle(symbol: NodeSymbol): string | undefined;
@@ -7,7 +7,21 @@ import { NodeMetadata } from '../types/symbol/metadata';
7
7
  import { SchemaElement } from '../types/schemaJson';
8
8
  import { NodeSymbol } from '../types/symbol';
9
9
  import { GlobalModule } from './types';
10
- export declare const modules: GlobalModule[];
10
+ /**
11
+ * The DBML vocabulary: the modules a Compiler uses when nobody says otherwise.
12
+ *
13
+ * The dispatcher tries each in order until one claims the node, so order is meaningful. Each
14
+ * time you add a new DBML element, register its module here.
15
+ *
16
+ * A Compiler may also be built with a different list (see `Compiler`'s second argument). The
17
+ * lexer and the parser do not know this vocabulary at all: `parser.ts` has one generic
18
+ * `elementDeclaration()` and never mentions `ElementKind`, so another dialect is a different
19
+ * array, not a different grammar. Pass a different list and the same front end binds a
20
+ * different language, which is how the architecture dialect reuses all of this without forking
21
+ * it or widening DBML's own vocabulary by a single word.
22
+ */
23
+ export declare const dbmlModules: GlobalModule[];
24
+ export declare const archModules: GlobalModule[];
11
25
  export declare function nodeSymbol(this: Compiler, node: SyntaxNode): Report<NodeSymbol> | Report<Unhandled>;
12
26
  export declare function symbolMembers(this: Compiler, symbol: NodeSymbol): Report<NodeSymbol[]> | Report<Unhandled>;
13
27
  export declare function nodeReferee(this: Compiler, node: SyntaxNode): Report<NodeSymbol | undefined> | Report<Unhandled>;
@@ -1,5 +1,5 @@
1
1
  import { default as Compiler } from '../../../compiler/index';
2
- import { Filepath, SettingName } from '../../types';
2
+ import { Filepath, FilepathId, SettingName } from '../../types';
3
3
  import { Column, Note, Table, TableGroup, TokenPosition } from '../../types/schemaJson';
4
4
  import { ElementDeclarationNode, SyntaxNode } from '../../types/nodes';
5
5
  import { NodeSymbol, SymbolKind, MetadataTargetKind } from '../../types/symbol';
@@ -24,6 +24,8 @@ type NameWithSymbolKind = {
24
24
  /** @internal Exported for testing only. */
25
25
  export declare function mapNamePartToSymbolKind(nameParts: string[], targetKind: MetadataTargetKind): NameWithSymbolKind[];
26
26
  export declare function resolveMetadataTarget(compiler: Compiler, metadataNode: ElementDeclarationNode): NodeSymbol | undefined;
27
+ /** Get precedence score of files in import tree, lower score means lower precedence */
28
+ export declare function metadataFilePrecedence(compiler: Compiler, root: Filepath): Map<FilepathId, number>;
27
29
  /** Merge every custom-metadata block, reachable from the current program, targeting element to it's `metadata` and other builtin (note/headercolor/...) fields */
28
30
  export declare function attachCustomMetadata<T extends MetadataTarget>(compiler: Compiler, targetElement: Partial<T>, targetSymbol: NodeSymbol, fieldsRegistry: MetadataFieldRegistry<T, any>, filepath: Filepath): void;
29
31
  export {};
@@ -6,6 +6,7 @@ export default class Binder {
6
6
  private compiler;
7
7
  constructor(ast: ProgramNode, compiler: Compiler);
8
8
  resolve(): Report<void>;
9
+ private isArchFile;
9
10
  private checkDuplicateRefs;
10
11
  private checkStandaloneRefs;
11
12
  private checkInlineRefs;
@@ -14,6 +14,8 @@ export default class ProgramInterpreter {
14
14
  private db;
15
15
  constructor(compiler: Compiler, symbol: ProgramSymbol, filepath: Filepath);
16
16
  interpret(): Report<SchemaElement | SchemaElement[] | undefined>;
17
+ private arch;
18
+ private finishArch;
17
19
  private interpretAllSymbols;
18
20
  private interpretUseSymbol;
19
21
  private interpretAllMetadata;
@@ -1,6 +1,19 @@
1
1
  import { Filepath } from '../types/filepath';
2
2
  import { default as Report } from '../types/report';
3
3
  import { SyntaxToken, SyntaxTokenKind } from '../types/tokens';
4
+ /**
5
+ * Grammar switches the lexer offers a dialect. Off by default, so DBML is untouched.
6
+ */
7
+ export interface LexerOptions {
8
+ /**
9
+ * Read a `---` fenced block at the very top of a file as one trivia token.
10
+ *
11
+ * It is Markdown's convention and people expect it for file-level metadata. DBML has no use
12
+ * for it, because `Project { ... }` already carries that and its interpreter files any
13
+ * unrecognised field as a free-form property. A dialect that wants both says so here.
14
+ */
15
+ allowFrontMatter?: boolean;
16
+ }
4
17
  export default class Lexer {
5
18
  private start;
6
19
  private current;
@@ -8,7 +21,16 @@ export default class Lexer {
8
21
  private filepath;
9
22
  private tokens;
10
23
  private errors;
11
- constructor(text: string, filepath: Filepath);
24
+ private readonly options;
25
+ constructor(text: string, filepath: Filepath, options?: LexerOptions);
26
+ /**
27
+ * Only at offset zero, and only up to the closing fence.
28
+ *
29
+ * It is consumed character by character like everything else, so `line` and `column` keep
30
+ * counting and every token after it still reports where it really is. Lifting the block out
31
+ * of the text instead would shift every diagnostic in the file by however many lines it had.
32
+ */
33
+ private scanFrontMatter;
12
34
  private isAtEnd;
13
35
  private advance;
14
36
  private peek;
@@ -0,0 +1,2 @@
1
+ import { LocalModule } from '../types';
2
+ export declare const archModule: LocalModule;
@@ -4,6 +4,7 @@ import { SyntaxNode } from '../types/nodes';
4
4
  import { default as Report } from '../types/report';
5
5
  import { LocalModule, Settings } from './types';
6
6
  export declare const modules: LocalModule[];
7
+ export declare const archModules: LocalModule[];
7
8
  export declare function validateNode(this: Compiler, node: SyntaxNode): Report<void> | Report<Unhandled>;
8
9
  export declare function nodeSettings(this: Compiler, node: SyntaxNode): Report<Settings> | Report<Unhandled>;
9
10
  export declare function nodeFullname(this: Compiler, node: SyntaxNode): Report<string[] | undefined> | Report<Unhandled>;
@@ -2,6 +2,22 @@ import { Filepath } from '../types/filepath';
2
2
  import { ProgramNode, SyntaxNodeIdGenerator } from '../types/nodes';
3
3
  import { default as Report } from '../types/report';
4
4
  import { SyntaxToken } from '../types/tokens';
5
+ /**
6
+ * Grammar switches a dialect may ask for. Every one of these is off by default, so the DBML
7
+ * grammar is exactly what it was; a dialect that wants a different shape says so, and the
8
+ * difference is one flag rather than a forked parser.
9
+ */
10
+ export interface ParserOptions {
11
+ /**
12
+ * Allow an element declaration with no body: `Database mongo1` as a complete statement.
13
+ *
14
+ * DBML has nothing that reads that way, because every DBML element carries something: a Table
15
+ * has columns, a Ref has endpoints. An architecture file is the opposite, mostly bare nouns
16
+ * with the occasional body, and writing `Database mongo1 { }` on every line to satisfy a
17
+ * grammar rule that exists for a different language would be the tail wagging the dog.
18
+ */
19
+ allowBodylessElement?: boolean;
20
+ }
5
21
  export default class Parser {
6
22
  private tokens;
7
23
  private current;
@@ -10,7 +26,8 @@ export default class Parser {
10
26
  private nodeFactory;
11
27
  private source;
12
28
  private filepath;
13
- constructor(source: string, tokens: SyntaxToken[], nodeIdGenerator: SyntaxNodeIdGenerator, filepath: Filepath);
29
+ private readonly options;
30
+ constructor(source: string, tokens: SyntaxToken[], nodeIdGenerator: SyntaxNodeIdGenerator, filepath: Filepath, options?: ParserOptions);
14
31
  private isAtEnd;
15
32
  private advance;
16
33
  private peek;
@@ -126,7 +126,23 @@ export declare enum CompileErrorCode {
126
126
  TABLE_REAPPEAR_IN_TABLEGROUP = 5009,
127
127
  INVALID_METADATA_TARGET_KIND = 5010,
128
128
  INVALID_METADATA_FIELD = 5011,
129
- DUPLICATE_METADATA_FIELD = 5012
129
+ DUPLICATE_METADATA_FIELD = 5012,
130
+ UNKNOWN_KIND = 6000,
131
+ MISSING_NAME = 6001,
132
+ RESERVED_KIND = 6002,
133
+ UNKNOWN_ENDPOINT = 6003,
134
+ EMPTY_LINK = 6004,
135
+ BAD_LINK = 6005,
136
+ UNKNOWN_METADATA_TARGET = 6006,
137
+ BAD_PROPERTY = 6007,
138
+ DUPLICATE_PROPERTY = 6008,
139
+ DIAGRAM_TYPE_NOT_HERE = 6009,
140
+ METADATA_KIND_MISMATCH = 6010,
141
+ UNKNOWN_TYPE = 6011,
142
+ UNKNOWN_ICON = 6012,
143
+ BAD_IMAGE = 6013,
144
+ DUPLICATE_LINK = 6014,
145
+ NESTED_ENDPOINTS = 6015
130
146
  }
131
147
  export interface RelatedLocation {
132
148
  nodeOrToken: SyntaxNode | SyntaxToken;
@@ -5,12 +5,10 @@ export type FilepathId = string & {
5
5
  };
6
6
  export declare class Filepath implements Internable<FilepathId> {
7
7
  private readonly protocol?;
8
- private readonly root;
9
- private readonly segments;
8
+ private readonly path;
10
9
  constructor(absolutePath: string, options?: {
11
10
  protocol?: string;
12
11
  });
13
- private get path();
14
12
  intern(): FilepathId;
15
13
  static from(absolutePath: string): Filepath;
16
14
  static resolve(fromDir: string, relativePath: string): Filepath;
@@ -95,6 +95,7 @@ export declare class UseSpecifierNode extends SyntaxNode {
95
95
  asKeyword?: SyntaxToken;
96
96
  alias?: NormalExpressionNode;
97
97
  }, id: SyntaxNodeId, filepath: Filepath);
98
+ archImport?: boolean;
98
99
  isKind(...importKinds: ImportKind[]): boolean;
99
100
  getSymbolKind(): SymbolKind | undefined;
100
101
  }
@@ -27,6 +27,10 @@ export interface DatabaseExternals {
27
27
  tableGroups: ElementRef[];
28
28
  tablePartials: ElementRef[];
29
29
  notes: ElementRef[];
30
+ nodes?: ElementRef[];
31
+ groups?: ElementRef[];
32
+ noteBoxes?: ElementRef[];
33
+ kinds?: ElementRef[];
30
34
  }
31
35
  /**
32
36
  * FilterConfig is a tri-state filter:
@@ -70,6 +74,64 @@ export interface Database {
70
74
  externals: DatabaseExternals;
71
75
  diagramViews: DiagramView[];
72
76
  token?: TokenPosition;
77
+ nodes?: Node[];
78
+ groups?: Group[];
79
+ noteBoxes?: NoteBox[];
80
+ links?: Link[];
81
+ kinds?: Kind[];
82
+ frontMatter?: Record<string, string>;
83
+ diagramType?: 'arch';
84
+ }
85
+ export type ArchSettingValue = string | number | boolean;
86
+ export type ArchSettings = Record<string, ArchSettingValue>;
87
+ export type KindCategory = 'compute' | 'data' | 'net' | 'edge' | 'people' | 'ops' | 'custom';
88
+ export interface Node {
89
+ name: string;
90
+ alias: string | null;
91
+ kind: string;
92
+ type: string | null;
93
+ image: string | null;
94
+ settings: ArchSettings;
95
+ note: {
96
+ value: string;
97
+ token: TokenPosition;
98
+ } | null;
99
+ token: TokenPosition;
100
+ }
101
+ export interface Group {
102
+ name: string;
103
+ alias: string | null;
104
+ children: string[];
105
+ settings: ArchSettings;
106
+ note: {
107
+ value: string;
108
+ token: TokenPosition;
109
+ } | null;
110
+ token: TokenPosition;
111
+ }
112
+ export interface NoteBox {
113
+ name: string;
114
+ alias: string | null;
115
+ content: string;
116
+ token: TokenPosition;
117
+ }
118
+ export type LinkOp = '>' | '<' | '<>' | '-';
119
+ export interface Link {
120
+ from: string;
121
+ to: string;
122
+ op: LinkOp;
123
+ settings: ArchSettings;
124
+ token: TokenPosition;
125
+ }
126
+ export interface Kind {
127
+ name: string;
128
+ icon: string;
129
+ glyph: string[] | null;
130
+ image: string | null;
131
+ category: KindCategory;
132
+ color: string | null;
133
+ builtin: boolean;
134
+ token: TokenPosition | null;
73
135
  }
74
136
  export interface MasterDatabase {
75
137
  files: Record<string, Database>;
@@ -297,4 +359,4 @@ export type Project = Record<string, never> | {
297
359
  token: TokenPosition;
298
360
  [index: string & Omit<any, 'name' | 'tables' | 'refs' | 'enums' | 'tableGroups' | 'note' | 'tablePartials' | 'records'>]: string;
299
361
  };
300
- export type SchemaElement = Database | Project | Table | Note | Column | ColumnType | Index | Check | InlineRef | InlineDep | Ref | RefEndpoint | Dep | DepEdge | DepEndpoint | Enum | EnumField | TableGroup | TableGroupField | Alias | TablePartial | TablePartialInjection | TableRecord | RecordValue | MetadataValues;
362
+ export type SchemaElement = Database | Project | Table | Note | Column | ColumnType | Index | Check | InlineRef | InlineDep | Ref | RefEndpoint | Dep | DepEdge | DepEndpoint | Enum | EnumField | TableGroup | TableGroupField | Alias | TablePartial | TablePartialInjection | TableRecord | RecordValue | MetadataValues | Node | Group | NoteBox | Link | Kind | ArchSettings;
@@ -12,7 +12,8 @@ export declare enum MetadataKind {
12
12
  Indexes = "indexes",
13
13
  Records = "records",
14
14
  Project = "project",
15
- MetadataElement = "metadata element"
15
+ MetadataElement = "metadata element",
16
+ Link = "link"
16
17
  }
17
18
  declare const __nodeMetadataBrand: unique symbol;
18
19
  export type NodeMetadataId = number & {
@@ -115,6 +116,16 @@ export declare class MetadataElementMetadata extends NodeMetadata {
115
116
  target(compiler: Compiler): NodeSymbol | undefined;
116
117
  owners(compiler: Compiler): NodeSymbol[];
117
118
  }
119
+ export declare class LinkMetadata extends NodeMetadata {
120
+ declaration: ElementDeclarationNode;
121
+ readonly kind = MetadataKind.Link;
122
+ constructor(declaration: ElementDeclarationNode);
123
+ endpoints(compiler: Compiler): [NodeSymbol | undefined, NodeSymbol | undefined];
124
+ owners(compiler: Compiler): NodeSymbol[];
125
+ }
126
+ export declare class ArchMetadataElementMetadata extends MetadataElementMetadata {
127
+ target(compiler: Compiler): NodeSymbol | undefined;
128
+ }
118
129
  export declare class ProjectMetadata extends NodeMetadata {
119
130
  readonly kind = MetadataKind.Project;
120
131
  constructor(declaration: SyntaxNode);
@@ -25,6 +25,8 @@ export declare enum SymbolKind {
25
25
  DiagramViewNote = "DiagramView note",
26
26
  DiagramViewSchema = "DiagramView schema",
27
27
  Metadata = "Metadata",
28
+ Element = "Element",
29
+ Kind = "Kind",
28
30
  Program = "Program"
29
31
  }
30
32
  export declare const ImportKind: {
@@ -203,6 +205,22 @@ export declare class TableGroupFieldSymbol extends NodeSymbol {
203
205
  get canBeImported(): boolean;
204
206
  get originalSymbol(): NodeSymbol;
205
207
  }
208
+ export declare class ElementSymbol extends NodeSymbol {
209
+ constructor({ declaration, name, }: {
210
+ declaration?: SyntaxNode;
211
+ name?: string;
212
+ }, id: NodeSymbolId, filepath: Filepath);
213
+ get canBeImported(): boolean;
214
+ get originalSymbol(): NodeSymbol;
215
+ }
216
+ export declare class KindSymbol extends NodeSymbol {
217
+ constructor({ declaration, name, }: {
218
+ declaration?: SyntaxNode;
219
+ name?: string;
220
+ }, id: NodeSymbolId, filepath: Filepath);
221
+ get canBeImported(): boolean;
222
+ get originalSymbol(): NodeSymbol;
223
+ }
206
224
  export declare class NoteSymbol extends NodeSymbol {
207
225
  constructor({ declaration, name, }: {
208
226
  declaration?: SyntaxNode;
@@ -25,6 +25,8 @@ export declare enum SyntaxTokenKind {
25
25
  COLON = "<colon>",
26
26
  SINGLE_LINE_COMMENT = "<single-line-comment>",
27
27
  MULTILINE_COMMENT = "<multiline-comment>",
28
+ /** a `---` fenced block at the very top of a file; only a dialect that asks for it gets one */
29
+ FRONT_MATTER = "<front-matter>",
28
30
  WILDCARD = "<wildcard>"
29
31
  }
30
32
  export declare function isTriviaToken(token: SyntaxToken): boolean;