@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.
- package/dist/apps/app-document.d.ts +3 -1
- package/dist/apps/app-document.d.ts.map +1 -1
- package/dist/apps/app-document.js +26 -11
- package/dist/apps/app-document.js.map +1 -1
- package/dist/apps/dashboard-document.d.ts +5 -0
- package/dist/apps/dashboard-document.d.ts.map +1 -1
- package/dist/apps/dashboard-document.js +4 -0
- package/dist/apps/dashboard-document.js.map +1 -1
- package/dist/apps/index.d.ts +2 -0
- package/dist/apps/index.d.ts.map +1 -1
- package/dist/apps/index.js +1 -0
- package/dist/apps/index.js.map +1 -1
- package/dist/apps/product-domain-context.d.ts +23 -0
- package/dist/apps/product-domain-context.d.ts.map +1 -0
- package/dist/apps/product-domain-context.js +25 -0
- package/dist/apps/product-domain-context.js.map +1 -0
- package/dist/artifacts/dql-artifact.d.ts +13 -0
- package/dist/artifacts/dql-artifact.d.ts.map +1 -1
- package/dist/artifacts/dql-artifact.js +69 -0
- package/dist/artifacts/dql-artifact.js.map +1 -1
- package/dist/artifacts/index.d.ts +1 -1
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/ast/index.d.ts +1 -1
- package/dist/ast/index.d.ts.map +1 -1
- package/dist/ast/index.js.map +1 -1
- package/dist/ast/nodes.d.ts +19 -1
- package/dist/ast/nodes.d.ts.map +1 -1
- package/dist/ast/printer.js +24 -0
- package/dist/ast/printer.js.map +1 -1
- package/dist/blocks/index.d.ts +2 -0
- package/dist/blocks/index.d.ts.map +1 -0
- package/dist/blocks/index.js +2 -0
- package/dist/blocks/index.js.map +1 -0
- package/dist/blocks/parameters.d.ts +55 -0
- package/dist/blocks/parameters.d.ts.map +1 -0
- package/dist/blocks/parameters.js +160 -0
- package/dist/blocks/parameters.js.map +1 -0
- package/dist/contracts/types.d.ts +6 -0
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js.map +1 -1
- package/dist/format/diff.d.ts.map +1 -1
- package/dist/format/diff.js +19 -11
- package/dist/format/diff.js.map +1 -1
- package/dist/format/notebook.d.ts +1 -1
- package/dist/format/notebook.js +2 -2
- package/dist/formatter/formatter.js +23 -1
- package/dist/formatter/formatter.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lineage/index.d.ts +1 -1
- package/dist/lineage/index.d.ts.map +1 -1
- package/dist/lineage/index.js.map +1 -1
- package/dist/lineage/sql-parser.d.ts +19 -0
- package/dist/lineage/sql-parser.d.ts.map +1 -1
- package/dist/lineage/sql-parser.js +90 -0
- package/dist/lineage/sql-parser.js.map +1 -1
- package/dist/manifest/builder.d.ts +5 -0
- package/dist/manifest/builder.d.ts.map +1 -1
- package/dist/manifest/builder.js +186 -8
- package/dist/manifest/builder.js.map +1 -1
- package/dist/manifest/datalex-migration.d.ts +68 -0
- package/dist/manifest/datalex-migration.d.ts.map +1 -0
- package/dist/manifest/datalex-migration.js +369 -0
- package/dist/manifest/datalex-migration.js.map +1 -0
- package/dist/manifest/dbt-first-authoring.d.ts +210 -0
- package/dist/manifest/dbt-first-authoring.d.ts.map +1 -0
- package/dist/manifest/dbt-first-authoring.js +510 -0
- package/dist/manifest/dbt-first-authoring.js.map +1 -0
- package/dist/manifest/dbt-first-modeling.d.ts +34 -0
- package/dist/manifest/dbt-first-modeling.d.ts.map +1 -0
- package/dist/manifest/dbt-first-modeling.js +931 -0
- package/dist/manifest/dbt-first-modeling.js.map +1 -0
- package/dist/manifest/domain-discovery.d.ts +98 -0
- package/dist/manifest/domain-discovery.d.ts.map +1 -0
- package/dist/manifest/domain-discovery.js +503 -0
- package/dist/manifest/domain-discovery.js.map +1 -0
- package/dist/manifest/domain-package-registry.d.ts +20 -0
- package/dist/manifest/domain-package-registry.d.ts.map +1 -0
- package/dist/manifest/domain-package-registry.js +265 -0
- package/dist/manifest/domain-package-registry.js.map +1 -0
- package/dist/manifest/domain-writer.d.ts +18 -0
- package/dist/manifest/domain-writer.d.ts.map +1 -1
- package/dist/manifest/domain-writer.js +52 -3
- package/dist/manifest/domain-writer.js.map +1 -1
- package/dist/manifest/index.d.ts +7 -1
- package/dist/manifest/index.d.ts.map +1 -1
- package/dist/manifest/index.js +6 -0
- package/dist/manifest/index.js.map +1 -1
- package/dist/manifest/project-snapshot.d.ts +30 -0
- package/dist/manifest/project-snapshot.d.ts.map +1 -0
- package/dist/manifest/project-snapshot.js +68 -0
- package/dist/manifest/project-snapshot.js.map +1 -0
- package/dist/manifest/types.d.ts +297 -3
- package/dist/manifest/types.d.ts.map +1 -1
- package/dist/parser/parser.d.ts.map +1 -1
- package/dist/parser/parser.js +88 -6
- package/dist/parser/parser.js.map +1 -1
- package/dist/semantic/analyzer.js +1 -1
- package/dist/semantic/analyzer.js.map +1 -1
- package/dist/semantic/index.d.ts +1 -1
- package/dist/semantic/index.d.ts.map +1 -1
- package/dist/semantic/index.js +1 -1
- package/dist/semantic/index.js.map +1 -1
- package/dist/semantic/providers/dbt-provider.d.ts +63 -0
- package/dist/semantic/providers/dbt-provider.d.ts.map +1 -1
- package/dist/semantic/providers/dbt-provider.js +43 -16
- package/dist/semantic/providers/dbt-provider.js.map +1 -1
- package/dist/semantic/semantic-layer.d.ts +11 -0
- package/dist/semantic/semantic-layer.d.ts.map +1 -1
- package/dist/semantic/semantic-layer.js +378 -27
- package/dist/semantic/semantic-layer.js.map +1 -1
- package/dist/semantic/sql-dialect.d.ts +8 -0
- package/dist/semantic/sql-dialect.d.ts.map +1 -1
- package/dist/semantic/sql-dialect.js +22 -0
- package/dist/semantic/sql-dialect.js.map +1 -1
- package/package.json +1 -1
package/dist/manifest/builder.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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) {
|