@duckcodeailabs/dql-core 1.6.33 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/apps/app-document.d.ts +3 -1
  2. package/dist/apps/app-document.d.ts.map +1 -1
  3. package/dist/apps/app-document.js +26 -11
  4. package/dist/apps/app-document.js.map +1 -1
  5. package/dist/apps/dashboard-document.d.ts +5 -0
  6. package/dist/apps/dashboard-document.d.ts.map +1 -1
  7. package/dist/apps/dashboard-document.js +4 -0
  8. package/dist/apps/dashboard-document.js.map +1 -1
  9. package/dist/apps/index.d.ts +2 -0
  10. package/dist/apps/index.d.ts.map +1 -1
  11. package/dist/apps/index.js +1 -0
  12. package/dist/apps/index.js.map +1 -1
  13. package/dist/apps/product-domain-context.d.ts +23 -0
  14. package/dist/apps/product-domain-context.d.ts.map +1 -0
  15. package/dist/apps/product-domain-context.js +25 -0
  16. package/dist/apps/product-domain-context.js.map +1 -0
  17. package/dist/artifacts/dql-artifact.d.ts +13 -0
  18. package/dist/artifacts/dql-artifact.d.ts.map +1 -1
  19. package/dist/artifacts/dql-artifact.js +69 -0
  20. package/dist/artifacts/dql-artifact.js.map +1 -1
  21. package/dist/artifacts/index.d.ts +1 -1
  22. package/dist/artifacts/index.d.ts.map +1 -1
  23. package/dist/ast/index.d.ts +1 -1
  24. package/dist/ast/index.d.ts.map +1 -1
  25. package/dist/ast/index.js.map +1 -1
  26. package/dist/ast/nodes.d.ts +19 -1
  27. package/dist/ast/nodes.d.ts.map +1 -1
  28. package/dist/ast/printer.js +24 -0
  29. package/dist/ast/printer.js.map +1 -1
  30. package/dist/blocks/index.d.ts +2 -0
  31. package/dist/blocks/index.d.ts.map +1 -0
  32. package/dist/blocks/index.js +2 -0
  33. package/dist/blocks/index.js.map +1 -0
  34. package/dist/blocks/parameters.d.ts +55 -0
  35. package/dist/blocks/parameters.d.ts.map +1 -0
  36. package/dist/blocks/parameters.js +160 -0
  37. package/dist/blocks/parameters.js.map +1 -0
  38. package/dist/contracts/types.d.ts +6 -0
  39. package/dist/contracts/types.d.ts.map +1 -1
  40. package/dist/contracts/types.js.map +1 -1
  41. package/dist/format/diff.d.ts.map +1 -1
  42. package/dist/format/diff.js +19 -11
  43. package/dist/format/diff.js.map +1 -1
  44. package/dist/format/notebook.d.ts +1 -1
  45. package/dist/format/notebook.js +2 -2
  46. package/dist/formatter/formatter.js +23 -1
  47. package/dist/formatter/formatter.js.map +1 -1
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/lineage/index.d.ts +1 -1
  53. package/dist/lineage/index.d.ts.map +1 -1
  54. package/dist/lineage/index.js.map +1 -1
  55. package/dist/lineage/sql-parser.d.ts +19 -0
  56. package/dist/lineage/sql-parser.d.ts.map +1 -1
  57. package/dist/lineage/sql-parser.js +90 -0
  58. package/dist/lineage/sql-parser.js.map +1 -1
  59. package/dist/manifest/builder.d.ts +5 -0
  60. package/dist/manifest/builder.d.ts.map +1 -1
  61. package/dist/manifest/builder.js +186 -8
  62. package/dist/manifest/builder.js.map +1 -1
  63. package/dist/manifest/datalex-migration.d.ts +68 -0
  64. package/dist/manifest/datalex-migration.d.ts.map +1 -0
  65. package/dist/manifest/datalex-migration.js +369 -0
  66. package/dist/manifest/datalex-migration.js.map +1 -0
  67. package/dist/manifest/dbt-first-authoring.d.ts +210 -0
  68. package/dist/manifest/dbt-first-authoring.d.ts.map +1 -0
  69. package/dist/manifest/dbt-first-authoring.js +510 -0
  70. package/dist/manifest/dbt-first-authoring.js.map +1 -0
  71. package/dist/manifest/dbt-first-modeling.d.ts +34 -0
  72. package/dist/manifest/dbt-first-modeling.d.ts.map +1 -0
  73. package/dist/manifest/dbt-first-modeling.js +931 -0
  74. package/dist/manifest/dbt-first-modeling.js.map +1 -0
  75. package/dist/manifest/domain-discovery.d.ts +98 -0
  76. package/dist/manifest/domain-discovery.d.ts.map +1 -0
  77. package/dist/manifest/domain-discovery.js +503 -0
  78. package/dist/manifest/domain-discovery.js.map +1 -0
  79. package/dist/manifest/domain-package-registry.d.ts +20 -0
  80. package/dist/manifest/domain-package-registry.d.ts.map +1 -0
  81. package/dist/manifest/domain-package-registry.js +265 -0
  82. package/dist/manifest/domain-package-registry.js.map +1 -0
  83. package/dist/manifest/domain-writer.d.ts +18 -0
  84. package/dist/manifest/domain-writer.d.ts.map +1 -1
  85. package/dist/manifest/domain-writer.js +52 -3
  86. package/dist/manifest/domain-writer.js.map +1 -1
  87. package/dist/manifest/index.d.ts +7 -1
  88. package/dist/manifest/index.d.ts.map +1 -1
  89. package/dist/manifest/index.js +6 -0
  90. package/dist/manifest/index.js.map +1 -1
  91. package/dist/manifest/project-snapshot.d.ts +30 -0
  92. package/dist/manifest/project-snapshot.d.ts.map +1 -0
  93. package/dist/manifest/project-snapshot.js +68 -0
  94. package/dist/manifest/project-snapshot.js.map +1 -0
  95. package/dist/manifest/types.d.ts +297 -3
  96. package/dist/manifest/types.d.ts.map +1 -1
  97. package/dist/parser/parser.d.ts.map +1 -1
  98. package/dist/parser/parser.js +88 -6
  99. package/dist/parser/parser.js.map +1 -1
  100. package/dist/semantic/analyzer.js +1 -1
  101. package/dist/semantic/analyzer.js.map +1 -1
  102. package/dist/semantic/index.d.ts +1 -1
  103. package/dist/semantic/index.d.ts.map +1 -1
  104. package/dist/semantic/index.js +1 -1
  105. package/dist/semantic/index.js.map +1 -1
  106. package/dist/semantic/providers/dbt-provider.d.ts +63 -0
  107. package/dist/semantic/providers/dbt-provider.d.ts.map +1 -1
  108. package/dist/semantic/providers/dbt-provider.js +43 -16
  109. package/dist/semantic/providers/dbt-provider.js.map +1 -1
  110. package/dist/semantic/semantic-layer.d.ts +11 -0
  111. package/dist/semantic/semantic-layer.d.ts.map +1 -1
  112. package/dist/semantic/semantic-layer.js +378 -27
  113. package/dist/semantic/semantic-layer.js.map +1 -1
  114. package/dist/semantic/sql-dialect.d.ts +8 -0
  115. package/dist/semantic/sql-dialect.d.ts.map +1 -1
  116. package/dist/semantic/sql-dialect.js +22 -0
  117. package/dist/semantic/sql-dialect.js.map +1 -1
  118. package/package.json +1 -1
@@ -16,8 +16,12 @@ import { buildLineageGraph } from '../lineage/builder.js';
16
16
  import { detectDomainFlows, getDomainTrustOverview } from '../lineage/domain-lineage.js';
17
17
  import { loadSemanticLayerFromDir } from '../semantic/index.js';
18
18
  import { DataLexContractRegistry } from '../contracts/index.js';
19
- import { loadAppDocument, findAppDocuments, findDashboardsForApp, loadDashboardDocument, extractDashboardBlockRefs, appFolderRelPath, } from '../apps/index.js';
19
+ import { loadAppDocument, findAppDocuments, findDashboardsForApp, loadDashboardDocument, extractDashboardBlockRefs, appFolderRelPath, normalizeProductDomainContext, } from '../apps/index.js';
20
20
  import { loadDbtRunState, applyBlockDataState } from './dbt-freshness.js';
21
+ import { blockParameterDefinitions } from '../blocks/parameters.js';
22
+ import { loadDbtFirstModeling, siblingDbtArtifact } from './dbt-first-modeling.js';
23
+ import { domainFolderSlug } from './domain-writer.js';
24
+ import { loadDomainPackageRegistry } from './domain-package-registry.js';
21
25
  /**
22
26
  * Enumerate every file whose contents could change the manifest output.
23
27
  *
@@ -53,7 +57,7 @@ export function collectInputFiles(options) {
53
57
  for (const f of scanFilesRecursive(join(projectRoot, dir), ['.dql']))
54
58
  files.add(f);
55
59
  }
56
- const notebookDirs = ['notebooks', 'blocks', 'dashboards', 'workbooks', ...(options.extraNotebookDirs ?? [])];
60
+ const notebookDirs = ['notebooks', 'domains', 'blocks', 'dashboards', 'workbooks', ...(options.extraNotebookDirs ?? [])];
57
61
  for (const dir of notebookDirs) {
58
62
  for (const f of scanFilesRecursive(join(projectRoot, dir), ['.dqlnb']))
59
63
  files.add(f);
@@ -65,6 +69,16 @@ export function collectInputFiles(options) {
65
69
  }
66
70
  if (options.dbtManifestPath && existsSync(options.dbtManifestPath)) {
67
71
  files.add(options.dbtManifestPath);
72
+ const catalogPath = siblingDbtArtifact(options.dbtManifestPath, 'catalog.json');
73
+ const semanticManifestPath = siblingDbtArtifact(options.dbtManifestPath, 'semantic_manifest.json');
74
+ if (catalogPath)
75
+ files.add(catalogPath);
76
+ if (semanticManifestPath)
77
+ files.add(semanticManifestPath);
78
+ }
79
+ if (config.manifestVersion === 3 && config.modeling?.mode === 'dbt-first') {
80
+ for (const f of scanFilesRecursive(join(projectRoot, 'domains'), ['.yaml', '.yml']))
81
+ files.add(f);
68
82
  }
69
83
  // Apps & dashboards. Manifests live at apps/<id>/dql.app.json; dashboards
70
84
  // live under apps/<id>/dashboards/*.dqld.
@@ -82,6 +96,14 @@ export function buildManifest(options) {
82
96
  // Load project config
83
97
  const config = loadProjectConfig(projectRoot);
84
98
  const projectName = config.project ?? 'dql-project';
99
+ const dbtFirstV3 = config.manifestVersion === 3 && config.modeling?.mode === 'dbt-first';
100
+ if ((config.manifestVersion === 3 || config.modeling?.mode === 'dbt-first') && !dbtFirstV3) {
101
+ diagnostics.push({
102
+ kind: 'config',
103
+ severity: 'error',
104
+ message: 'manifest v3 requires both `manifestVersion: 3` and `modeling.mode: "dbt-first"`; compiling with manifest v2 compatibility defaults',
105
+ });
106
+ }
85
107
  const datalexManifestPath = resolveDataLexManifestPath(projectRoot, options.datalexManifestPath, config);
86
108
  const datalexRegistry = datalexManifestPath
87
109
  ? new DataLexContractRegistry({ manifestPath: datalexManifestPath })
@@ -96,7 +118,12 @@ export function buildManifest(options) {
96
118
  }
97
119
  // Scan first-class business domains
98
120
  const domainDirs = ['domains', 'blocks', 'terms', 'business-views', ...(options.extraBlockDirs ?? [])];
99
- const domains = scanDomains(projectRoot, domainDirs, diagnostics);
121
+ const packageRegistry = dbtFirstV3 ? loadDomainPackageRegistry(projectRoot) : undefined;
122
+ const domains = packageRegistry
123
+ ? Object.fromEntries(packageRegistry.values().map((pkg) => [pkg.id, pkg.domain]))
124
+ : scanDomains(projectRoot, domainDirs, diagnostics);
125
+ if (!packageRegistry)
126
+ validateDomainHierarchy(domains, diagnostics);
100
127
  // Scan blocks
101
128
  const blockDirs = ['blocks', 'domains', 'dashboards', 'workbooks', ...(options.extraBlockDirs ?? [])];
102
129
  const blocks = scanBlocks(projectRoot, blockDirs, diagnostics, datalexRegistry);
@@ -172,15 +199,33 @@ export function buildManifest(options) {
172
199
  // `dataState` via its transitive dbt upstreams.
173
200
  applyBlockDataState(blocks, sources, dbtImport.dbtDag, runState);
174
201
  }
202
+ let dbtFirstModeling;
203
+ if (dbtFirstV3) {
204
+ if (!options.dbtManifestPath || !existsSync(options.dbtManifestPath)) {
205
+ diagnostics.push({
206
+ kind: 'config',
207
+ severity: 'error',
208
+ message: 'manifest v3 dbt-first modeling requires a readable dbt manifest.json',
209
+ });
210
+ }
211
+ else {
212
+ dbtFirstModeling = loadDbtFirstModeling(projectRoot, options.dbtManifestPath);
213
+ diagnostics.push(...dbtFirstModeling.diagnostics);
214
+ }
215
+ }
175
216
  // Apps & dashboards (consumption layer). Scanned after blocks/notebooks
176
217
  // because dashboard refs are resolved against the block path → name map.
177
218
  const { apps, dashboards } = scanAppsAndDashboards(projectRoot, blocks, diagnostics);
178
219
  // Build lineage
179
- const lineage = buildManifestLineage(domains, blocks, metrics, dimensions, notebooks, dbtImport, apps, dashboards, businessViews, terms);
220
+ const lineage = buildManifestLineage(domains, blocks, metrics, dimensions, notebooks, dbtFirstV3 ? stripDbtImportDetails(dbtImport) : dbtImport, apps, dashboards, businessViews, terms);
221
+ if (dbtFirstModeling)
222
+ appendDbtFirstModelingLineage(lineage, dbtFirstModeling.modeling);
180
223
  return {
181
- manifestVersion: 2,
224
+ manifestVersion: dbtFirstV3 ? 3 : 2,
182
225
  dqlVersion,
183
- generatedAt: new Date().toISOString(),
226
+ // v3 is a reproducible policy artifact. Runtime build time lives in the
227
+ // local cache, not in the canonical manifest content.
228
+ generatedAt: dbtFirstV3 ? new Date(0).toISOString() : new Date().toISOString(),
184
229
  project: projectName,
185
230
  projectRoot,
186
231
  domains,
@@ -190,11 +235,13 @@ export function buildManifest(options) {
190
235
  notebooks,
191
236
  metrics,
192
237
  dimensions,
193
- sources,
238
+ sources: dbtFirstV3 ? stripDbtOwnedSourceDetails(sources) : sources,
194
239
  apps: Object.keys(apps).length > 0 ? apps : undefined,
195
240
  dashboards: Object.keys(dashboards).length > 0 ? dashboards : undefined,
196
241
  lineage,
197
- dbtImport,
242
+ dbtImport: dbtFirstV3 ? undefined : dbtImport,
243
+ dbtProvenance: dbtFirstModeling?.provenance,
244
+ modeling: dbtFirstModeling?.modeling,
198
245
  diagnostics,
199
246
  };
200
247
  }
@@ -264,6 +311,75 @@ export function resolveDataLexManifestPath(projectRoot, explicit, loadedConfig)
264
311
  function isAbsPath(p) {
265
312
  return p.startsWith('/') || /^[A-Za-z]:[\\/]/.test(p);
266
313
  }
314
+ /** Remove physical dbt payloads before serializing a v3 lineage graph. */
315
+ function stripDbtImportDetails(dbtImport) {
316
+ if (!dbtImport?.dbtDag)
317
+ return dbtImport;
318
+ return {
319
+ ...dbtImport,
320
+ dbtDag: {
321
+ edges: dbtImport.dbtDag.edges,
322
+ models: dbtImport.dbtDag.models.map(({ columns: _columns, description: _description, ...model }) => model),
323
+ },
324
+ };
325
+ }
326
+ /** Keep source names/usage but never serialize dbt-owned schema content in v3. */
327
+ function stripDbtOwnedSourceDetails(sources) {
328
+ return Object.fromEntries(Object.entries(sources).map(([name, source]) => {
329
+ const { dbtModel: _dbtModel, ...sparseSource } = source;
330
+ return [name, sparseSource];
331
+ }));
332
+ }
333
+ /**
334
+ * Add DQL-owned analytical bindings and relationship proof to lineage without
335
+ * mutating or reclassifying dbt transformation edges. A relationship edge is
336
+ * intentionally distinct from dbt `depends_on`: it is a reviewed analytical
337
+ * join policy, not inferred DAG evidence.
338
+ */
339
+ function appendDbtFirstModelingLineage(lineage, modeling) {
340
+ const existingNodeIds = new Set(lineage.nodes.map((node) => node.id));
341
+ const existingEdges = new Set(lineage.edges.map((edge) => `${edge.source}:${edge.target}:${edge.type}`));
342
+ const dbtNodeByUniqueId = new Map();
343
+ for (const node of lineage.nodes) {
344
+ const uniqueId = typeof node.metadata?.uniqueId === 'string' ? node.metadata.uniqueId : undefined;
345
+ if (uniqueId)
346
+ dbtNodeByUniqueId.set(uniqueId, node.id);
347
+ }
348
+ const addEdge = (source, target, type) => {
349
+ const key = `${source}:${target}:${type}`;
350
+ if (!existingEdges.has(key)) {
351
+ lineage.edges.push({ source, target, type });
352
+ existingEdges.add(key);
353
+ }
354
+ };
355
+ for (const entity of Object.values(modeling.entities)) {
356
+ const entityId = `dql_entity:${entity.id}`;
357
+ if (!existingNodeIds.has(entityId)) {
358
+ lineage.nodes.push({
359
+ id: entityId,
360
+ type: 'dql_entity',
361
+ name: entity.id,
362
+ layer: 'answer',
363
+ domain: entity.domain,
364
+ filePath: entity.sourcePath,
365
+ metadata: {
366
+ dbtUniqueId: entity.dbtUniqueId,
367
+ grain: entity.grain,
368
+ keys: entity.keys,
369
+ identityFingerprint: entity.identityFingerprint,
370
+ provenance: 'dql sparse overlay',
371
+ },
372
+ });
373
+ existingNodeIds.add(entityId);
374
+ }
375
+ const dbtNode = dbtNodeByUniqueId.get(entity.dbtUniqueId);
376
+ if (dbtNode)
377
+ addEdge(dbtNode, entityId, 'binds_dbt_model');
378
+ }
379
+ for (const relationship of Object.values(modeling.relationships)) {
380
+ addEdge(`dql_entity:${relationship.from}`, `dql_entity:${relationship.to}`, 'governed_relationship');
381
+ }
382
+ }
267
383
  function resolveSemanticPath(projectRoot, config) {
268
384
  const customPath = config.semanticLayer?.path;
269
385
  if (customPath)
@@ -337,6 +453,41 @@ function scanDomains(projectRoot, dirs, diagnostics) {
337
453
  }
338
454
  return domains;
339
455
  }
456
+ /** Validate parent references without changing legacy flat-domain semantics. */
457
+ function validateDomainHierarchy(domains, diagnostics) {
458
+ const keyFor = (value) => domainAliasKey(value);
459
+ const byKey = new Map(Object.values(domains).map((domain) => [keyFor(domain.name), domain]));
460
+ for (const domain of Object.values(domains)) {
461
+ if (!domain.parent)
462
+ continue;
463
+ const parent = byKey.get(keyFor(domain.parent));
464
+ if (!parent) {
465
+ diagnostics.push({
466
+ kind: 'resolve',
467
+ filePath: domain.filePath,
468
+ severity: 'error',
469
+ message: `domain "${domain.name}" references missing parent "${domain.parent}"`,
470
+ });
471
+ continue;
472
+ }
473
+ const visited = new Set([keyFor(domain.name)]);
474
+ let current = parent;
475
+ while (current?.parent) {
476
+ const currentKey = keyFor(current.name);
477
+ if (visited.has(currentKey)) {
478
+ diagnostics.push({
479
+ kind: 'resolve',
480
+ filePath: domain.filePath,
481
+ severity: 'error',
482
+ message: `domain hierarchy contains a cycle involving "${domain.name}"`,
483
+ });
484
+ break;
485
+ }
486
+ visited.add(currentKey);
487
+ current = byKey.get(keyFor(current.parent));
488
+ }
489
+ }
490
+ }
340
491
  function scanBlocks(projectRoot, dirs, diagnostics, datalexRegistry) {
341
492
  const blocks = {};
342
493
  for (const dir of dirs) {
@@ -846,9 +997,11 @@ function scanNotebooks(projectRoot, dirs, diagnostics, datalexRegistry) {
846
997
  });
847
998
  }
848
999
  if (cells.length > 0) {
1000
+ const productContext = normalizeProductDomainContext(doc.metadata ?? {}, stringOrUndefined(doc.metadata?.domain));
849
1001
  notebooks[relPath] = {
850
1002
  title: doc.metadata?.title ?? doc.title ?? relPath,
851
1003
  filePath: relPath,
1004
+ ...productContext,
852
1005
  cells,
853
1006
  };
854
1007
  }
@@ -866,6 +1019,15 @@ function scanNotebooks(projectRoot, dirs, diagnostics, datalexRegistry) {
866
1019
  }
867
1020
  return notebooks;
868
1021
  }
1022
+ function stringOrUndefined(value) {
1023
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
1024
+ }
1025
+ function stringArrayValue(value) {
1026
+ if (!Array.isArray(value))
1027
+ return undefined;
1028
+ const items = [...new Set(value.filter((item) => typeof item === 'string').map((item) => item.trim()).filter(Boolean))];
1029
+ return items.length > 0 ? items : undefined;
1030
+ }
869
1031
  /** Extract blocks declared inside notebook DQL cells into the blocks map. */
870
1032
  function extractNotebookBlocks(notebooks) {
871
1033
  const blocks = {};
@@ -1505,6 +1667,11 @@ function appDocumentToManifest(app, filePath, dashboardIds) {
1505
1667
  businessRules: app.businessRules,
1506
1668
  caveats: app.caveats,
1507
1669
  domain: app.domain,
1670
+ ownerDomain: app.ownerDomain ?? app.domain,
1671
+ usesDomains: app.usesDomains,
1672
+ purpose: app.purpose,
1673
+ requiredExports: app.requiredExports,
1674
+ classification: app.classification,
1508
1675
  subdomain: app.subdomain,
1509
1676
  groups: app.groups ?? [],
1510
1677
  audience: app.audience,
@@ -1860,6 +2027,7 @@ function blockDeclToManifestBlock(block, filePath) {
1860
2027
  policy: entry.policy,
1861
2028
  }))
1862
2029
  : undefined,
2030
+ parameters: blockParameterDefinitions(block),
1863
2031
  filterBindings: Array.isArray(block.filterBindings)
1864
2032
  ? block.filterBindings.map((entry) => ({
1865
2033
  filter: entry.filter,
@@ -1948,8 +2116,10 @@ function buildOutputContract(declaredOutputs, columnLineage) {
1948
2116
  }
1949
2117
  function domainDeclToManifestDomain(domain, filePath) {
1950
2118
  return {
2119
+ id: typeof domain.id === 'string' ? domain.id : domainFolderSlug(domain.name),
1951
2120
  name: domain.name,
1952
2121
  filePath,
2122
+ parent: typeof domain.parent === 'string' ? domain.parent : undefined,
1953
2123
  owner: typeof domain.owner === 'string' ? domain.owner : undefined,
1954
2124
  businessOwner: typeof domain.businessOwner === 'string' ? domain.businessOwner : undefined,
1955
2125
  boundedContext: typeof domain.boundedContext === 'string' ? domain.boundedContext : undefined,
@@ -1959,6 +2129,14 @@ function domainDeclToManifestDomain(domain, filePath) {
1959
2129
  tags: Array.isArray(domain.tags) ? domain.tags : undefined,
1960
2130
  businessOutcome: typeof domain.businessOutcome === 'string' ? domain.businessOutcome : undefined,
1961
2131
  description: typeof domain.description === 'string' ? domain.description : undefined,
2132
+ inScope: Array.isArray(domain.inScope) ? domain.inScope : undefined,
2133
+ outOfScope: Array.isArray(domain.outOfScope) ? domain.outOfScope : undefined,
2134
+ dbtGroups: Array.isArray(domain.dbtGroups) ? domain.dbtGroups : undefined,
2135
+ dbtPaths: Array.isArray(domain.dbtPaths) ? domain.dbtPaths : undefined,
2136
+ dbtTags: Array.isArray(domain.dbtTags) ? domain.dbtTags : undefined,
2137
+ semanticDomains: Array.isArray(domain.semanticDomains) ? domain.semanticDomains : undefined,
2138
+ semanticTags: Array.isArray(domain.semanticTags) ? domain.semanticTags : undefined,
2139
+ exports: Array.isArray(domain.exports) ? domain.exports : undefined,
1962
2140
  };
1963
2141
  }
1964
2142
  function termDeclToManifestTerm(term, filePath) {