@duckcodeailabs/dql-cli 1.6.2 → 1.6.3
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/assets/dql-notebook/assets/{index-60sOoPrg.js → index-CIMLd3Cb.js} +317 -627
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +16 -4
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +44 -0
- package/package.json +12 -12
- package/dist/apps-api.test.d.ts +0 -2
- package/dist/apps-api.test.d.ts.map +0 -1
- package/dist/apps-api.test.js +0 -196
- package/dist/apps-api.test.js.map +0 -1
- package/dist/args.test.d.ts +0 -2
- package/dist/args.test.d.ts.map +0 -1
- package/dist/args.test.js +0 -41
- package/dist/args.test.js.map +0 -1
- package/dist/block-studio-import.test.d.ts +0 -2
- package/dist/block-studio-import.test.d.ts.map +0 -1
- package/dist/block-studio-import.test.js +0 -168
- package/dist/block-studio-import.test.js.map +0 -1
- package/dist/commands/build.test.d.ts +0 -2
- package/dist/commands/build.test.d.ts.map +0 -1
- package/dist/commands/build.test.js +0 -44
- package/dist/commands/build.test.js.map +0 -1
- package/dist/commands/compile.test.d.ts +0 -2
- package/dist/commands/compile.test.d.ts.map +0 -1
- package/dist/commands/compile.test.js +0 -115
- package/dist/commands/compile.test.js.map +0 -1
- package/dist/commands/doctor.test.d.ts +0 -2
- package/dist/commands/doctor.test.d.ts.map +0 -1
- package/dist/commands/doctor.test.js +0 -44
- package/dist/commands/doctor.test.js.map +0 -1
- package/dist/commands/init.test.d.ts +0 -2
- package/dist/commands/init.test.d.ts.map +0 -1
- package/dist/commands/init.test.js +0 -182
- package/dist/commands/init.test.js.map +0 -1
- package/dist/commands/new.test.d.ts +0 -2
- package/dist/commands/new.test.d.ts.map +0 -1
- package/dist/commands/new.test.js +0 -297
- package/dist/commands/new.test.js.map +0 -1
- package/dist/commands/sync.test.d.ts +0 -2
- package/dist/commands/sync.test.d.ts.map +0 -1
- package/dist/commands/sync.test.js +0 -147
- package/dist/commands/sync.test.js.map +0 -1
- package/dist/commands/validate.test.d.ts +0 -2
- package/dist/commands/validate.test.d.ts.map +0 -1
- package/dist/commands/validate.test.js +0 -140
- package/dist/commands/validate.test.js.map +0 -1
- package/dist/local-runtime.test.d.ts +0 -2
- package/dist/local-runtime.test.d.ts.map +0 -1
- package/dist/local-runtime.test.js +0 -363
- package/dist/local-runtime.test.js.map +0 -1
- package/dist/metricflow.test.d.ts +0 -2
- package/dist/metricflow.test.d.ts.map +0 -1
- package/dist/metricflow.test.js +0 -54
- package/dist/metricflow.test.js.map +0 -1
- package/dist/promote-from-draft.test.d.ts +0 -2
- package/dist/promote-from-draft.test.d.ts.map +0 -1
- package/dist/promote-from-draft.test.js +0 -149
- package/dist/promote-from-draft.test.js.map +0 -1
- package/dist/semantic-import.test.d.ts +0 -2
- package/dist/semantic-import.test.d.ts.map +0 -1
- package/dist/semantic-import.test.js +0 -95
- package/dist/semantic-import.test.js.map +0 -1
- package/dist/template-adoption.test.d.ts +0 -2
- package/dist/template-adoption.test.d.ts.map +0 -1
- package/dist/template-adoption.test.js +0 -105
- package/dist/template-adoption.test.js.map +0 -1
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { buildAgentPreviewSql, buildDbtStatus, createBlockArtifacts, createSemanticBuilderBlock, discoverDbtProfileConnections, formatLocalQueryRuntimeError, normalizeProjectConnection, prepareLocalExecution, resolveProjectRelativeSqlPaths, serializeJSON, validateBlockStudioSource, } from './local-runtime.js';
|
|
3
|
-
import { afterEach } from 'vitest';
|
|
4
|
-
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import { tmpdir } from 'node:os';
|
|
7
|
-
import { SemanticLayer } from '@duckcodeailabs/dql-core';
|
|
8
|
-
const tempDirs = [];
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
while (tempDirs.length > 0) {
|
|
11
|
-
const dir = tempDirs.pop();
|
|
12
|
-
if (dir)
|
|
13
|
-
rmSync(dir, { recursive: true, force: true });
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
describe('formatLocalQueryRuntimeError', () => {
|
|
17
|
-
it('explains missing DuckDB native bindings with actionable guidance', () => {
|
|
18
|
-
const message = formatLocalQueryRuntimeError({ driver: 'file', filepath: ':memory:' }, new Error("Cannot find module '/tmp/duckdb/lib/binding/duckdb.node'"));
|
|
19
|
-
expect(message).toContain('DuckDB native bindings could not be loaded');
|
|
20
|
-
expect(message).toContain(`Current Node.js runtime: ${process.versions.node}`);
|
|
21
|
-
expect(message).toContain('Node 18, 20, or 22');
|
|
22
|
-
expect(message).toContain('pnpm install');
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
describe('serializeJSON', () => {
|
|
26
|
-
it('serializes safe bigint values as numbers', () => {
|
|
27
|
-
expect(serializeJSON({ revenue: 42n })).toBe('{"revenue":42}');
|
|
28
|
-
});
|
|
29
|
-
it('serializes unsafe bigint values as strings', () => {
|
|
30
|
-
const value = BigInt(Number.MAX_SAFE_INTEGER) + 1n;
|
|
31
|
-
expect(serializeJSON({ revenue: value })).toBe(`{"revenue":"${value.toString()}"}`);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
describe('resolveProjectRelativeSqlPaths', () => {
|
|
35
|
-
it('rewrites notebook sample file paths relative to the selected project', () => {
|
|
36
|
-
const sql = "SELECT * FROM read_csv_auto('./data/revenue.csv')";
|
|
37
|
-
const resolved = resolveProjectRelativeSqlPaths(sql, '/tmp/demo-project');
|
|
38
|
-
expect(resolved).toBe("SELECT * FROM read_csv_auto('/tmp/demo-project/data/revenue.csv')");
|
|
39
|
-
});
|
|
40
|
-
it('leaves unrelated string literals untouched', () => {
|
|
41
|
-
const sql = "SELECT './data/revenue.csv' AS label";
|
|
42
|
-
expect(resolveProjectRelativeSqlPaths(sql, '/tmp/demo-project')).toBe(sql);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
describe('normalizeProjectConnection', () => {
|
|
46
|
-
it('resolves relative local database paths against the project root', () => {
|
|
47
|
-
expect(normalizeProjectConnection({ driver: 'duckdb', filepath: './local/dev.duckdb' }, '/tmp/demo-project')).toEqual({ driver: 'duckdb', filepath: '/tmp/demo-project/local/dev.duckdb' });
|
|
48
|
-
});
|
|
49
|
-
it('expands environment placeholders when the value is available', () => {
|
|
50
|
-
const previous = process.env.DQL_TEST_DATABASE;
|
|
51
|
-
process.env.DQL_TEST_DATABASE = 'analytics';
|
|
52
|
-
try {
|
|
53
|
-
expect(normalizeProjectConnection({ driver: 'postgresql', host: 'localhost', database: '${DQL_TEST_DATABASE}', username: 'dql' }, '/tmp/demo-project')).toEqual({ driver: 'postgresql', host: 'localhost', database: 'analytics', username: 'dql' });
|
|
54
|
-
}
|
|
55
|
-
finally {
|
|
56
|
-
if (previous === undefined)
|
|
57
|
-
delete process.env.DQL_TEST_DATABASE;
|
|
58
|
-
else
|
|
59
|
-
process.env.DQL_TEST_DATABASE = previous;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
describe('discoverDbtProfileConnections', () => {
|
|
64
|
-
it('maps dbt profiles.yml targets into DQL connection drafts', () => {
|
|
65
|
-
const projectRoot = mkdtempSync(join(tmpdir(), 'dql-dbt-profiles-'));
|
|
66
|
-
tempDirs.push(projectRoot);
|
|
67
|
-
writeFileSync(join(projectRoot, 'dbt_project.yml'), 'name: banking\nprofile: banking\n', 'utf-8');
|
|
68
|
-
writeFileSync(join(projectRoot, 'profiles.yml'), [
|
|
69
|
-
'banking:',
|
|
70
|
-
' target: dev',
|
|
71
|
-
' outputs:',
|
|
72
|
-
' dev:',
|
|
73
|
-
' type: postgres',
|
|
74
|
-
' host: "{{ env_var(\'PGHOST\', \'localhost\') }}"',
|
|
75
|
-
' port: 5432',
|
|
76
|
-
' dbname: analytics',
|
|
77
|
-
' schema: marts',
|
|
78
|
-
' user: analyst',
|
|
79
|
-
' password: "{{ env_var(\'PGPASSWORD\') }}"',
|
|
80
|
-
'other:',
|
|
81
|
-
' outputs:',
|
|
82
|
-
' dev:',
|
|
83
|
-
' type: duckdb',
|
|
84
|
-
' path: other.duckdb',
|
|
85
|
-
].join('\n'), 'utf-8');
|
|
86
|
-
const profilePath = join(projectRoot, 'profiles.yml');
|
|
87
|
-
const candidates = discoverDbtProfileConnections(projectRoot, {});
|
|
88
|
-
const candidate = candidates.find((item) => item.path === profilePath && item.profileName === 'banking');
|
|
89
|
-
expect(candidate).toBeDefined();
|
|
90
|
-
expect(candidate?.targetName).toBe('dev');
|
|
91
|
-
expect(candidate?.connection).toMatchObject({
|
|
92
|
-
driver: 'postgresql',
|
|
93
|
-
host: 'localhost',
|
|
94
|
-
port: 5432,
|
|
95
|
-
database: 'analytics',
|
|
96
|
-
schema: 'marts',
|
|
97
|
-
username: 'analyst',
|
|
98
|
-
password: '${PGPASSWORD}',
|
|
99
|
-
});
|
|
100
|
-
expect(candidate?.missingFields).toContain('env:PGPASSWORD');
|
|
101
|
-
expect(candidates.some((item) => item.profileName === 'other')).toBe(false);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
describe('prepareLocalExecution', () => {
|
|
105
|
-
it('rewrites SQL paths for file-backed notebook queries', () => {
|
|
106
|
-
const prepared = prepareLocalExecution("SELECT * FROM read_csv_auto('./data/revenue.csv')", { driver: 'file', filepath: ':memory:' }, '/tmp/demo-project', { dataDir: './data' });
|
|
107
|
-
expect(prepared.connection).toEqual({ driver: 'file', filepath: ':memory:' });
|
|
108
|
-
expect(prepared.sql).toBe("SELECT * FROM read_csv_auto('/tmp/demo-project/data/revenue.csv')");
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
describe('buildAgentPreviewSql', () => {
|
|
112
|
-
it('wraps read-only generated SQL in a bounded preview', () => {
|
|
113
|
-
expect(buildAgentPreviewSql('SELECT status, COUNT(*) AS n FROM orders GROUP BY status;')).toBe('SELECT * FROM (\nSELECT status, COUNT(*) AS n FROM orders GROUP BY status\n) AS dql_agent_preview LIMIT 200');
|
|
114
|
-
});
|
|
115
|
-
it('rejects generated SQL that is not a single read-only statement', () => {
|
|
116
|
-
expect(() => buildAgentPreviewSql('SELECT 1; DROP TABLE orders')).toThrow('one statement');
|
|
117
|
-
expect(() => buildAgentPreviewSql('DELETE FROM orders')).toThrow('read-only SELECT or WITH');
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
describe('semantic block save artifacts', () => {
|
|
121
|
-
it('writes both the block file and semantic companion metadata for save-from-cell flows', () => {
|
|
122
|
-
const projectRoot = mkdtempSync(join(tmpdir(), 'dql-block-artifacts-'));
|
|
123
|
-
tempDirs.push(projectRoot);
|
|
124
|
-
writeFileSync(join(projectRoot, 'dql.config.json'), '{}\n');
|
|
125
|
-
const created = createBlockArtifacts(projectRoot, {
|
|
126
|
-
name: 'Revenue Summary',
|
|
127
|
-
domain: 'finance',
|
|
128
|
-
content: 'SELECT @metric(total_revenue), @dim(order_date);',
|
|
129
|
-
description: 'Finance summary block',
|
|
130
|
-
tags: ['finance', 'exec'],
|
|
131
|
-
});
|
|
132
|
-
expect(created.path).toBe('blocks/finance/revenue-summary.dql');
|
|
133
|
-
expect(created.companionPath).toBe('semantic-layer/blocks/finance/revenue-summary.yaml');
|
|
134
|
-
expect(readFileSync(join(projectRoot, created.path), 'utf-8')).toContain('@metric(total_revenue)');
|
|
135
|
-
const companion = readFileSync(join(projectRoot, created.companionPath), 'utf-8');
|
|
136
|
-
expect(companion).toContain('provider: dql');
|
|
137
|
-
expect(companion).toContain('semanticMetrics:');
|
|
138
|
-
expect(companion).toContain(' - total_revenue');
|
|
139
|
-
expect(companion).toContain('semanticDimensions:');
|
|
140
|
-
expect(companion).toContain(' - order_date');
|
|
141
|
-
expect(companion).toContain('reviewStatus: draft');
|
|
142
|
-
});
|
|
143
|
-
it('writes semantic builder blocks with lineage companion metadata', () => {
|
|
144
|
-
const projectRoot = mkdtempSync(join(tmpdir(), 'dql-builder-artifacts-'));
|
|
145
|
-
tempDirs.push(projectRoot);
|
|
146
|
-
writeFileSync(join(projectRoot, 'dql.config.json'), '{}\n');
|
|
147
|
-
const created = createSemanticBuilderBlock(projectRoot, {
|
|
148
|
-
name: 'Executive Revenue',
|
|
149
|
-
domain: 'finance',
|
|
150
|
-
description: 'Executive revenue cut',
|
|
151
|
-
owner: 'finance-analytics',
|
|
152
|
-
tags: ['finance'],
|
|
153
|
-
metrics: ['total_revenue'],
|
|
154
|
-
dimensions: ['sales_channel'],
|
|
155
|
-
timeDimension: { name: 'order_date', granularity: 'month' },
|
|
156
|
-
chart: 'line',
|
|
157
|
-
blockType: 'semantic',
|
|
158
|
-
sql: 'SELECT 1',
|
|
159
|
-
tables: ['analytics.orders'],
|
|
160
|
-
provider: 'dbt',
|
|
161
|
-
});
|
|
162
|
-
expect(created.path).toBe('blocks/finance/executive-revenue.dql');
|
|
163
|
-
expect(created.content).toContain('type = "semantic"');
|
|
164
|
-
expect(created.content).toContain('metric = "total_revenue"');
|
|
165
|
-
const companion = readFileSync(join(projectRoot, created.companionPath), 'utf-8');
|
|
166
|
-
expect(companion).toContain('provider: dbt');
|
|
167
|
-
expect(companion).toContain('lineage:');
|
|
168
|
-
expect(companion).toContain('analytics.orders');
|
|
169
|
-
expect(companion).toContain('semanticMetrics:');
|
|
170
|
-
expect(companion).toContain(' - total_revenue');
|
|
171
|
-
expect(companion).toContain('semanticDimensions:');
|
|
172
|
-
expect(companion).toContain(' - sales_channel');
|
|
173
|
-
expect(companion).toContain(' - order_date');
|
|
174
|
-
});
|
|
175
|
-
it('writes a blank semantic block when created from the Semantic Block path', () => {
|
|
176
|
-
const projectRoot = mkdtempSync(join(tmpdir(), 'dql-blank-semantic-block-'));
|
|
177
|
-
tempDirs.push(projectRoot);
|
|
178
|
-
writeFileSync(join(projectRoot, 'dql.config.json'), '{}\n');
|
|
179
|
-
const created = createBlockArtifacts(projectRoot, {
|
|
180
|
-
name: 'Approval Rate',
|
|
181
|
-
domain: 'cards',
|
|
182
|
-
blockType: 'semantic',
|
|
183
|
-
owner: 'cards-analytics',
|
|
184
|
-
description: 'Semantic metric starter',
|
|
185
|
-
tags: ['cards'],
|
|
186
|
-
});
|
|
187
|
-
expect(created.path).toBe('blocks/cards/approval-rate.dql');
|
|
188
|
-
expect(created.content).toContain('type = "semantic"');
|
|
189
|
-
expect(created.content).toContain('metric = ""');
|
|
190
|
-
expect(created.content).toContain('dimensions = []');
|
|
191
|
-
expect(created.content).not.toContain('query = """');
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
describe('buildDbtStatus', () => {
|
|
195
|
-
it('reports configured dbt artifacts and counts for the Block Studio start page', () => {
|
|
196
|
-
const projectRoot = mkdtempSync(join(tmpdir(), 'dql-dbt-status-'));
|
|
197
|
-
tempDirs.push(projectRoot);
|
|
198
|
-
const dbtRoot = join(projectRoot, 'dbt');
|
|
199
|
-
const targetDir = join(dbtRoot, 'target');
|
|
200
|
-
mkdirSync(targetDir, { recursive: true });
|
|
201
|
-
writeFileSync(join(dbtRoot, 'dbt_project.yml'), 'name: banking\nversion: 1.0\n', 'utf-8');
|
|
202
|
-
writeFileSync(join(targetDir, 'manifest.json'), JSON.stringify({
|
|
203
|
-
metadata: { project_name: 'banking', generated_at: '2026-04-30T12:00:00Z' },
|
|
204
|
-
nodes: {
|
|
205
|
-
'model.banking.fct_cards': { resource_type: 'model' },
|
|
206
|
-
'test.banking.not_null': { resource_type: 'test' },
|
|
207
|
-
},
|
|
208
|
-
sources: {
|
|
209
|
-
'source.banking.raw.cards': {},
|
|
210
|
-
},
|
|
211
|
-
}), 'utf-8');
|
|
212
|
-
writeFileSync(join(targetDir, 'semantic_manifest.json'), JSON.stringify({
|
|
213
|
-
metadata: { generated_at: '2026-04-30T12:01:00Z' },
|
|
214
|
-
metrics: [{ name: 'approval_rate' }],
|
|
215
|
-
semantic_models: [{ name: 'cards' }],
|
|
216
|
-
saved_queries: [{ name: 'daily_cards' }],
|
|
217
|
-
}), 'utf-8');
|
|
218
|
-
const status = buildDbtStatus(projectRoot, {
|
|
219
|
-
semanticLayer: { provider: 'dbt', projectPath: './dbt' },
|
|
220
|
-
dbt: { projectDir: './dbt', manifestPath: 'target/manifest.json' },
|
|
221
|
-
}, '2026-04-30T12:02:00Z');
|
|
222
|
-
expect(status.configured).toBe(true);
|
|
223
|
-
expect(status.projectName).toBe('banking');
|
|
224
|
-
expect(status.artifacts.manifest.exists).toBe(true);
|
|
225
|
-
expect(status.artifacts.semanticManifest.exists).toBe(true);
|
|
226
|
-
expect(status.counts.models).toBe(1);
|
|
227
|
-
expect(status.counts.sources).toBe(1);
|
|
228
|
-
expect(status.counts.metrics).toBe(1);
|
|
229
|
-
expect(status.counts.semanticModels).toBe(1);
|
|
230
|
-
expect(status.counts.savedQueries).toBe(1);
|
|
231
|
-
expect(status.lastSyncTime).toBe('2026-04-30T12:02:00Z');
|
|
232
|
-
expect(status.setupHint).toContain('dbt artifacts are ready');
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
describe('validateBlockStudioSource', () => {
|
|
236
|
-
const semanticLayer = new SemanticLayer({
|
|
237
|
-
metrics: [
|
|
238
|
-
{
|
|
239
|
-
name: 'total_revenue',
|
|
240
|
-
label: 'Total Revenue',
|
|
241
|
-
description: 'Revenue metric',
|
|
242
|
-
domain: 'finance',
|
|
243
|
-
sql: 'SUM(revenue)',
|
|
244
|
-
type: 'sum',
|
|
245
|
-
table: 'orders',
|
|
246
|
-
tags: [],
|
|
247
|
-
},
|
|
248
|
-
],
|
|
249
|
-
dimensions: [
|
|
250
|
-
{
|
|
251
|
-
name: 'customer_type',
|
|
252
|
-
label: 'Customer Type',
|
|
253
|
-
description: 'Customer type dimension',
|
|
254
|
-
domain: 'finance',
|
|
255
|
-
sql: 'customer_type',
|
|
256
|
-
type: 'string',
|
|
257
|
-
table: 'orders',
|
|
258
|
-
tags: [],
|
|
259
|
-
},
|
|
260
|
-
],
|
|
261
|
-
hierarchies: [],
|
|
262
|
-
});
|
|
263
|
-
it('composes executable SQL for semantic blocks with metric and dimensions', () => {
|
|
264
|
-
const source = `block "Revenue by Type" {
|
|
265
|
-
domain = "finance"
|
|
266
|
-
type = "semantic"
|
|
267
|
-
description = ""
|
|
268
|
-
owner = ""
|
|
269
|
-
tags = []
|
|
270
|
-
metric = "total_revenue"
|
|
271
|
-
dimensions = ["customer_type"]
|
|
272
|
-
}`;
|
|
273
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
274
|
-
expect(validation.valid).toBe(true);
|
|
275
|
-
expect(validation.executableSql).toContain('SUM(revenue) AS total_revenue');
|
|
276
|
-
expect(validation.executableSql).toContain('customer_type AS customer_type');
|
|
277
|
-
expect(validation.executableSql).toContain('GROUP BY customer_type');
|
|
278
|
-
});
|
|
279
|
-
it('returns an actionable diagnostic when a semantic block is missing a metric', () => {
|
|
280
|
-
const source = `block "Revenue by Type" {
|
|
281
|
-
domain = "finance"
|
|
282
|
-
type = "semantic"
|
|
283
|
-
description = ""
|
|
284
|
-
owner = ""
|
|
285
|
-
tags = []
|
|
286
|
-
dimensions = ["customer_type"]
|
|
287
|
-
}`;
|
|
288
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
289
|
-
expect(validation.valid).toBe(false);
|
|
290
|
-
expect(validation.executableSql).toBeNull();
|
|
291
|
-
expect(validation.diagnostics.some((item) => item.code === 'semantic_metric_missing')).toBe(true);
|
|
292
|
-
});
|
|
293
|
-
it('returns a semantic validation error for unknown dimensions', () => {
|
|
294
|
-
const source = `block "Revenue by Type" {
|
|
295
|
-
domain = "finance"
|
|
296
|
-
type = "semantic"
|
|
297
|
-
description = ""
|
|
298
|
-
owner = ""
|
|
299
|
-
tags = []
|
|
300
|
-
metric = "total_revenue"
|
|
301
|
-
dimensions = ["missing_dimension"]
|
|
302
|
-
}`;
|
|
303
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
304
|
-
expect(validation.valid).toBe(false);
|
|
305
|
-
expect(validation.diagnostics.some((item) => item.code === 'semantic_ref' && item.message.includes('missing_dimension'))).toBe(true);
|
|
306
|
-
});
|
|
307
|
-
it('keeps custom block validation behavior unchanged', () => {
|
|
308
|
-
const source = `block "Custom Revenue" {
|
|
309
|
-
domain = "finance"
|
|
310
|
-
type = "custom"
|
|
311
|
-
description = ""
|
|
312
|
-
owner = ""
|
|
313
|
-
tags = []
|
|
314
|
-
|
|
315
|
-
query = """
|
|
316
|
-
SELECT revenue
|
|
317
|
-
FROM orders
|
|
318
|
-
"""
|
|
319
|
-
}`;
|
|
320
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
321
|
-
expect(validation.valid).toBe(true);
|
|
322
|
-
expect(validation.executableSql).toContain('SELECT revenue');
|
|
323
|
-
});
|
|
324
|
-
it('resolves semantic refs inside custom block SQL before execution', () => {
|
|
325
|
-
const source = `block "Revenue Query" {
|
|
326
|
-
domain = "finance"
|
|
327
|
-
type = "custom"
|
|
328
|
-
description = ""
|
|
329
|
-
owner = ""
|
|
330
|
-
tags = []
|
|
331
|
-
|
|
332
|
-
query = """
|
|
333
|
-
SELECT
|
|
334
|
-
@metric(total_revenue),
|
|
335
|
-
@dim(customer_type)
|
|
336
|
-
FROM orders
|
|
337
|
-
GROUP BY @dim(customer_type)
|
|
338
|
-
"""
|
|
339
|
-
}`;
|
|
340
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
341
|
-
expect(validation.valid).toBe(true);
|
|
342
|
-
expect(validation.executableSql).toContain('SUM(revenue) AS total_revenue');
|
|
343
|
-
expect(validation.executableSql).toContain('customer_type AS customer_type');
|
|
344
|
-
expect(validation.executableSql).toContain('GROUP BY customer_type');
|
|
345
|
-
});
|
|
346
|
-
it('returns a semantic validation error for unresolved refs in custom SQL', () => {
|
|
347
|
-
const source = `block "Broken Revenue Query" {
|
|
348
|
-
domain = "finance"
|
|
349
|
-
type = "custom"
|
|
350
|
-
description = ""
|
|
351
|
-
owner = ""
|
|
352
|
-
tags = []
|
|
353
|
-
|
|
354
|
-
query = """
|
|
355
|
-
SELECT @metric(missing_metric)
|
|
356
|
-
"""
|
|
357
|
-
}`;
|
|
358
|
-
const validation = validateBlockStudioSource(source, semanticLayer);
|
|
359
|
-
expect(validation.valid).toBe(false);
|
|
360
|
-
expect(validation.diagnostics.some((item) => item.code === 'semantic_ref' && item.message.includes('missing_metric'))).toBe(true);
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
//# sourceMappingURL=local-runtime.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-runtime.test.js","sourceRoot":"","sources":["../src/local-runtime.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"metricflow.test.d.ts","sourceRoot":"","sources":["../src/metricflow.test.ts"],"names":[],"mappings":""}
|
package/dist/metricflow.test.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { compileMetricFlowQuery, MetricFlowUnavailableError } from './metricflow.js';
|
|
6
|
-
describe('MetricFlow compile wrapper', () => {
|
|
7
|
-
let tmpDir;
|
|
8
|
-
let previousBin;
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
tmpDir = mkdtempSync(join(tmpdir(), 'dql-mf-'));
|
|
11
|
-
previousBin = process.env.DQL_METRICFLOW_BIN;
|
|
12
|
-
});
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
if (previousBin === undefined) {
|
|
15
|
-
delete process.env.DQL_METRICFLOW_BIN;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
process.env.DQL_METRICFLOW_BIN = previousBin;
|
|
19
|
-
}
|
|
20
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
21
|
-
});
|
|
22
|
-
it('compiles through mf and extracts SQL from mixed stdout', () => {
|
|
23
|
-
mkdirSync(join(tmpDir, 'target'), { recursive: true });
|
|
24
|
-
writeFileSync(join(tmpDir, 'target', 'semantic_manifest.json'), '{}', 'utf-8');
|
|
25
|
-
const bin = join(tmpDir, 'mf');
|
|
26
|
-
writeFileSync(bin, [
|
|
27
|
-
'#!/bin/sh',
|
|
28
|
-
'printf "%s\\n" "$*" > args.txt',
|
|
29
|
-
'printf "%s\\n" "info: compiling"',
|
|
30
|
-
'printf "%s\\n" "SELECT metric_time, revenue FROM compiled_metric_sql"',
|
|
31
|
-
].join('\n'), 'utf-8');
|
|
32
|
-
chmodSync(bin, 0o755);
|
|
33
|
-
process.env.DQL_METRICFLOW_BIN = bin;
|
|
34
|
-
const result = compileMetricFlowQuery({
|
|
35
|
-
projectRoot: tmpDir,
|
|
36
|
-
metrics: ['revenue'],
|
|
37
|
-
dimensions: ['region'],
|
|
38
|
-
timeDimension: { name: 'metric_time', granularity: 'month' },
|
|
39
|
-
filters: [{ expression: "{{ Dimension('region') }} = 'NA'" }],
|
|
40
|
-
limit: 25,
|
|
41
|
-
});
|
|
42
|
-
expect(result.sql).toBe('SELECT metric_time, revenue FROM compiled_metric_sql');
|
|
43
|
-
expect(result.command).toContain('--compile');
|
|
44
|
-
expect(result.command).toContain('--metrics');
|
|
45
|
-
});
|
|
46
|
-
it('returns a setup error when semantic_manifest.json is missing', () => {
|
|
47
|
-
expect(() => compileMetricFlowQuery({
|
|
48
|
-
projectRoot: tmpDir,
|
|
49
|
-
metrics: ['revenue'],
|
|
50
|
-
dimensions: [],
|
|
51
|
-
})).toThrow(MetricFlowUnavailableError);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
//# sourceMappingURL=metricflow.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"metricflow.test.js","sourceRoot":"","sources":["../src/metricflow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"promote-from-draft.test.d.ts","sourceRoot":"","sources":["../src/promote-from-draft.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { promoteFromDraft } from './promote-from-draft.js';
|
|
6
|
-
function baseFlags(overrides = {}) {
|
|
7
|
-
return {
|
|
8
|
-
format: 'text',
|
|
9
|
-
verbose: false,
|
|
10
|
-
help: false,
|
|
11
|
-
version: false,
|
|
12
|
-
check: false,
|
|
13
|
-
open: null,
|
|
14
|
-
input: '',
|
|
15
|
-
outDir: '',
|
|
16
|
-
port: null,
|
|
17
|
-
host: null,
|
|
18
|
-
chart: '',
|
|
19
|
-
domain: '',
|
|
20
|
-
owner: '',
|
|
21
|
-
queryOnly: false,
|
|
22
|
-
template: '',
|
|
23
|
-
connection: '',
|
|
24
|
-
skipTests: false,
|
|
25
|
-
force: false,
|
|
26
|
-
http: false,
|
|
27
|
-
...overrides,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
function writeDraft(root, slug, body) {
|
|
31
|
-
const draftDir = join(root, 'blocks', '_drafts');
|
|
32
|
-
mkdirSync(draftDir, { recursive: true });
|
|
33
|
-
const domain = body?.domain ?? 'customer';
|
|
34
|
-
const id = body?.proposedContractId ?? 'commerce.Customer.monthly_active_customers';
|
|
35
|
-
const status = body?.status ?? 'draft';
|
|
36
|
-
writeFileSync(join(draftDir, `${slug}.dql`), `block "${slug}" {
|
|
37
|
-
domain = "${domain}"
|
|
38
|
-
type = "custom"
|
|
39
|
-
status = "${status}"
|
|
40
|
-
description = """How many active customers each month?"""
|
|
41
|
-
datalex_contract = ""
|
|
42
|
-
|
|
43
|
-
_proposed {
|
|
44
|
-
asked_times = 3
|
|
45
|
-
first_asked = "2026-04-01T00:00:00Z"
|
|
46
|
-
last_asked = "2026-05-01T12:00:00Z"
|
|
47
|
-
proposed_contract_id = "${id}"
|
|
48
|
-
proposed_domain = "${domain}"
|
|
49
|
-
proposed_entity = "Customer"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
query = """SELECT 1"""
|
|
53
|
-
}
|
|
54
|
-
`);
|
|
55
|
-
}
|
|
56
|
-
describe('promoteFromDraft (dql certify --from-draft)', () => {
|
|
57
|
-
let tmp;
|
|
58
|
-
beforeEach(() => {
|
|
59
|
-
tmp = mkdtempSync(join(tmpdir(), 'promote-'));
|
|
60
|
-
});
|
|
61
|
-
afterEach(() => {
|
|
62
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
63
|
-
});
|
|
64
|
-
it('returns ok=false when the draft path does not exist', () => {
|
|
65
|
-
const out = promoteFromDraft(tmp, baseFlags({ fromDraft: 'blocks/_drafts/nope.dql' }));
|
|
66
|
-
expect(out.ok).toBe(false);
|
|
67
|
-
expect(out.message).toMatch(/not found/i);
|
|
68
|
-
});
|
|
69
|
-
it('refuses to promote a file whose status is not draft', () => {
|
|
70
|
-
writeDraft(tmp, 'mau', { status: 'certified' });
|
|
71
|
-
const out = promoteFromDraft(tmp, baseFlags({ fromDraft: 'blocks/_drafts/mau.dql' }));
|
|
72
|
-
expect(out.ok).toBe(false);
|
|
73
|
-
expect(out.message).toMatch(/status="draft"/);
|
|
74
|
-
});
|
|
75
|
-
it('promotes a draft to blocks/<domain>/<slug>.dql, flips status, sets contract, drops _proposed', () => {
|
|
76
|
-
writeDraft(tmp, 'mau');
|
|
77
|
-
const out = promoteFromDraft(tmp, baseFlags({
|
|
78
|
-
fromDraft: 'blocks/_drafts/mau.dql',
|
|
79
|
-
domain: 'customer',
|
|
80
|
-
contract: 'commerce.Customer.monthly_active_customers@1',
|
|
81
|
-
owner: 'growth@example.com',
|
|
82
|
-
}));
|
|
83
|
-
expect(out.ok).toBe(true);
|
|
84
|
-
expect(out.certifiedPath).toBe('blocks/customer/mau.dql');
|
|
85
|
-
const certified = readFileSync(join(tmp, 'blocks/customer/mau.dql'), 'utf-8');
|
|
86
|
-
expect(certified).toContain('status = "certified"');
|
|
87
|
-
expect(certified).toContain('datalex_contract = "commerce.Customer.monthly_active_customers@1"');
|
|
88
|
-
expect(certified).toContain('owner = "growth@example.com"');
|
|
89
|
-
expect(certified).not.toContain('_proposed');
|
|
90
|
-
expect(certified).not.toContain('asked_times');
|
|
91
|
-
expect(existsSync(join(tmp, 'blocks/_drafts/mau.dql'))).toBe(false);
|
|
92
|
-
});
|
|
93
|
-
it('falls back to the proposed contract id with @1 when --contract is omitted', () => {
|
|
94
|
-
writeDraft(tmp, 'mau', {
|
|
95
|
-
proposedContractId: 'commerce.Customer.monthly_active_customers',
|
|
96
|
-
});
|
|
97
|
-
const out = promoteFromDraft(tmp, baseFlags({ fromDraft: 'blocks/_drafts/mau.dql', domain: 'customer' }));
|
|
98
|
-
expect(out.ok).toBe(true);
|
|
99
|
-
const certified = readFileSync(join(tmp, 'blocks/customer/mau.dql'), 'utf-8');
|
|
100
|
-
expect(certified).toContain('datalex_contract = "commerce.Customer.monthly_active_customers@1"');
|
|
101
|
-
});
|
|
102
|
-
it('errors when no --contract and no proposed_contract_id available', () => {
|
|
103
|
-
writeDraft(tmp, 'mau', { proposedContractId: '' });
|
|
104
|
-
const out = promoteFromDraft(tmp, baseFlags({ fromDraft: 'blocks/_drafts/mau.dql', domain: 'customer' }));
|
|
105
|
-
expect(out.ok).toBe(false);
|
|
106
|
-
expect(out.message).toMatch(/contract/i);
|
|
107
|
-
});
|
|
108
|
-
it('refuses to overwrite an existing certified file unless --force', () => {
|
|
109
|
-
writeDraft(tmp, 'mau');
|
|
110
|
-
mkdirSync(join(tmp, 'blocks', 'customer'), { recursive: true });
|
|
111
|
-
writeFileSync(join(tmp, 'blocks', 'customer', 'mau.dql'), 'already here');
|
|
112
|
-
const out = promoteFromDraft(tmp, baseFlags({
|
|
113
|
-
fromDraft: 'blocks/_drafts/mau.dql',
|
|
114
|
-
domain: 'customer',
|
|
115
|
-
contract: 'commerce.Customer.monthly_active_customers@1',
|
|
116
|
-
}));
|
|
117
|
-
expect(out.ok).toBe(false);
|
|
118
|
-
expect(out.message).toMatch(/already exists/);
|
|
119
|
-
});
|
|
120
|
-
it('overwrites with --force', () => {
|
|
121
|
-
writeDraft(tmp, 'mau');
|
|
122
|
-
mkdirSync(join(tmp, 'blocks', 'customer'), { recursive: true });
|
|
123
|
-
writeFileSync(join(tmp, 'blocks', 'customer', 'mau.dql'), 'old content');
|
|
124
|
-
const out = promoteFromDraft(tmp, baseFlags({
|
|
125
|
-
fromDraft: 'blocks/_drafts/mau.dql',
|
|
126
|
-
domain: 'customer',
|
|
127
|
-
contract: 'commerce.Customer.monthly_active_customers@1',
|
|
128
|
-
force: true,
|
|
129
|
-
}));
|
|
130
|
-
expect(out.ok).toBe(true);
|
|
131
|
-
const content = readFileSync(join(tmp, 'blocks/customer/mau.dql'), 'utf-8');
|
|
132
|
-
expect(content).not.toBe('old content');
|
|
133
|
-
expect(content).toContain('status = "certified"');
|
|
134
|
-
});
|
|
135
|
-
it('surfaces a datalex-manifest.json patch with the contract entry to add', () => {
|
|
136
|
-
writeDraft(tmp, 'mau');
|
|
137
|
-
const out = promoteFromDraft(tmp, baseFlags({
|
|
138
|
-
fromDraft: 'blocks/_drafts/mau.dql',
|
|
139
|
-
domain: 'customer',
|
|
140
|
-
contract: 'commerce.Customer.monthly_active_customers@1',
|
|
141
|
-
}));
|
|
142
|
-
expect(out.datalexManifestDiff).toBeDefined();
|
|
143
|
-
expect(out.datalexManifestDiff).toContain('commerce.Customer.monthly_active_customers');
|
|
144
|
-
expect(out.datalexManifestDiff).toContain('"version": 1');
|
|
145
|
-
expect(out.datalexManifestDiff).toContain('domains[name=commerce]');
|
|
146
|
-
expect(out.datalexManifestDiff).toContain('entities[name=Customer]');
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
//# sourceMappingURL=promote-from-draft.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"promote-from-draft.test.js","sourceRoot":"","sources":["../src/promote-from-draft.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"semantic-import.test.d.ts","sourceRoot":"","sources":["../src/semantic-import.test.ts"],"names":[],"mappings":""}
|