@duckcodeailabs/dql-cli 1.0.2 → 1.0.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-DhWFlKju.js → index-BJbWzCsK.js} +79 -80
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/local-runtime.d.ts +22 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +93 -6
- package/dist/local-runtime.js.map +1 -1
- package/package.json +8 -8
- package/dist/package.json +0 -46
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-BJbWzCsK.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/react-CRB3T2We.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/codemirror-BqWuFwtC.js">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="/assets/index-BZV40eAE.css">
|
package/dist/local-runtime.d.ts
CHANGED
|
@@ -28,6 +28,20 @@ export declare function prepareLocalExecution(sql: string, connection: Connectio
|
|
|
28
28
|
sql: string;
|
|
29
29
|
connection: ConnectionConfig;
|
|
30
30
|
};
|
|
31
|
+
export interface PreparedSemanticSql {
|
|
32
|
+
sql: string;
|
|
33
|
+
semanticRefs: {
|
|
34
|
+
metrics: string[];
|
|
35
|
+
dimensions: string[];
|
|
36
|
+
};
|
|
37
|
+
unresolvedRefs: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Shared resolver for `@metric(name)` / `@dim(name)` refs in raw SQL.
|
|
41
|
+
* Used by notebook SQL execution and Block Studio validation so both paths
|
|
42
|
+
* behave identically. If the SQL has no refs, returns it unchanged.
|
|
43
|
+
*/
|
|
44
|
+
export declare function prepareSemanticSql(sql: string, semanticLayer: SemanticLayer | undefined): PreparedSemanticSql;
|
|
31
45
|
export declare function normalizeProjectConnection(connection: ConnectionConfig, projectRoot: string): ConnectionConfig;
|
|
32
46
|
export declare function resolveProjectRelativeSqlPaths(sql: string, projectRoot: string, dataDir?: string): string;
|
|
33
47
|
type BlockStudioDiagnostic = {
|
|
@@ -52,14 +66,22 @@ export declare function validateBlockStudioSource(source: string, semanticLayer?
|
|
|
52
66
|
};
|
|
53
67
|
executableSql?: string | null;
|
|
54
68
|
};
|
|
69
|
+
export interface BlockGitMetadata {
|
|
70
|
+
commitSha: string;
|
|
71
|
+
repo: string | null;
|
|
72
|
+
branch: string | null;
|
|
73
|
+
}
|
|
74
|
+
export declare function readGitMetadata(projectRoot: string): BlockGitMetadata | null;
|
|
55
75
|
export declare function createBlockArtifacts(projectRoot: string, options: {
|
|
56
76
|
name: string;
|
|
57
77
|
domain?: string;
|
|
78
|
+
owner?: string;
|
|
58
79
|
content?: string;
|
|
59
80
|
description?: string;
|
|
60
81
|
tags?: string[];
|
|
61
82
|
metricRefs?: string[];
|
|
62
83
|
template?: string;
|
|
84
|
+
gitMetadata?: BlockGitMetadata | null;
|
|
63
85
|
}): {
|
|
64
86
|
path: string;
|
|
65
87
|
content: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-runtime.d.ts","sourceRoot":"","sources":["../src/local-runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-runtime.d.ts","sourceRoot":"","sources":["../src/local-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/local-runtime.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { createServer } from 'node:http';
|
|
2
3
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, watch, writeFileSync } from 'node:fs';
|
|
3
4
|
import { dirname, extname, join, normalize, relative, resolve } from 'node:path';
|
|
@@ -339,20 +340,37 @@ export async function startLocalServer(opts) {
|
|
|
339
340
|
if (req.method === 'POST' && path === '/api/blocks/save-from-cell') {
|
|
340
341
|
try {
|
|
341
342
|
const body = await readJSON(req);
|
|
342
|
-
const { name, domain, content, description, tags, metricRefs, template, } = body;
|
|
343
|
+
const { name, domain, owner, content, description, tags, metricRefs, template, } = body;
|
|
343
344
|
if (!name || typeof name !== 'string' || !content || typeof content !== 'string') {
|
|
344
345
|
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
345
346
|
res.end(serializeJSON({ error: 'name and content are required' }));
|
|
346
347
|
return;
|
|
347
348
|
}
|
|
349
|
+
const missing = [];
|
|
350
|
+
if (!owner || !owner.trim())
|
|
351
|
+
missing.push('owner');
|
|
352
|
+
if (!domain || !domain.trim())
|
|
353
|
+
missing.push('domain');
|
|
354
|
+
if (!description || !description.trim())
|
|
355
|
+
missing.push('description');
|
|
356
|
+
if (missing.length > 0) {
|
|
357
|
+
res.writeHead(422, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
358
|
+
res.end(serializeJSON({
|
|
359
|
+
error: `Block is missing required governance fields: ${missing.join(', ')}`,
|
|
360
|
+
missing,
|
|
361
|
+
}));
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
348
364
|
const created = createBlockArtifacts(projectRoot, {
|
|
349
365
|
name,
|
|
350
366
|
domain,
|
|
367
|
+
owner,
|
|
351
368
|
content,
|
|
352
369
|
description,
|
|
353
370
|
tags,
|
|
354
371
|
metricRefs,
|
|
355
372
|
template,
|
|
373
|
+
gitMetadata: readGitMetadata(projectRoot),
|
|
356
374
|
});
|
|
357
375
|
res.writeHead(201, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
358
376
|
res.end(serializeJSON(created));
|
|
@@ -1279,9 +1297,21 @@ export async function startLocalServer(opts) {
|
|
|
1279
1297
|
res.end(serializeJSON({ columns: [], rows: [], error: 'Missing SQL in request body.' }));
|
|
1280
1298
|
return;
|
|
1281
1299
|
}
|
|
1282
|
-
const
|
|
1300
|
+
const semantic = prepareSemanticSql(body.sql, semanticLayer);
|
|
1301
|
+
if (semantic.unresolvedRefs.length > 0) {
|
|
1302
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1303
|
+
res.end(serializeJSON({
|
|
1304
|
+
columns: [],
|
|
1305
|
+
rows: [],
|
|
1306
|
+
error: `Unknown semantic reference${semantic.unresolvedRefs.length > 1 ? 's' : ''}: ${semantic.unresolvedRefs.join(', ')}`,
|
|
1307
|
+
code: 'semantic_ref',
|
|
1308
|
+
unresolvedRefs: semantic.unresolvedRefs,
|
|
1309
|
+
}));
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
const prepared = prepareLocalExecution(semantic.sql, isConnectionConfig(body.connection) ? body.connection : connection, projectRoot, projectConfig);
|
|
1283
1313
|
const result = await executor.executeQuery(prepared.sql, Array.isArray(body.sqlParams) ? body.sqlParams : [], body.variables && typeof body.variables === 'object' ? body.variables : {}, prepared.connection);
|
|
1284
|
-
const payload = serializeJSON(normalizeQueryResult(result));
|
|
1314
|
+
const payload = serializeJSON(normalizeQueryResult(result, semantic.semanticRefs));
|
|
1285
1315
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1286
1316
|
res.end(payload);
|
|
1287
1317
|
}
|
|
@@ -1848,9 +1878,10 @@ export function formatLocalQueryRuntimeError(connection, error) {
|
|
|
1848
1878
|
* Connector returns columns as ColumnMeta[] ({name,type,driverType}).
|
|
1849
1879
|
* The notebook SPA expects columns as string[] (just names).
|
|
1850
1880
|
*/
|
|
1851
|
-
function normalizeQueryResult(result) {
|
|
1881
|
+
function normalizeQueryResult(result, semanticRefs) {
|
|
1852
1882
|
const rawCols = Array.isArray(result?.columns) ? result.columns : [];
|
|
1853
1883
|
const columns = rawCols.map((c) => typeof c === 'string' ? c : typeof c?.name === 'string' ? c.name : String(c));
|
|
1884
|
+
const hasRefs = semanticRefs && (semanticRefs.metrics.length > 0 || semanticRefs.dimensions.length > 0);
|
|
1854
1885
|
return {
|
|
1855
1886
|
columns,
|
|
1856
1887
|
rows: Array.isArray(result?.rows) ? result.rows : [],
|
|
@@ -1860,6 +1891,7 @@ function normalizeQueryResult(result) {
|
|
|
1860
1891
|
: typeof result?.executionTime === 'number'
|
|
1861
1892
|
? result.executionTime
|
|
1862
1893
|
: 0,
|
|
1894
|
+
...(hasRefs ? { semanticRefs } : {}),
|
|
1863
1895
|
};
|
|
1864
1896
|
}
|
|
1865
1897
|
export function serializeJSON(value) {
|
|
@@ -1941,6 +1973,25 @@ export function prepareLocalExecution(sql, connection, projectRoot, projectConfi
|
|
|
1941
1973
|
connection: normalizedConnection,
|
|
1942
1974
|
};
|
|
1943
1975
|
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Shared resolver for `@metric(name)` / `@dim(name)` refs in raw SQL.
|
|
1978
|
+
* Used by notebook SQL execution and Block Studio validation so both paths
|
|
1979
|
+
* behave identically. If the SQL has no refs, returns it unchanged.
|
|
1980
|
+
*/
|
|
1981
|
+
export function prepareSemanticSql(sql, semanticLayer) {
|
|
1982
|
+
if (!hasSemanticRefs(sql)) {
|
|
1983
|
+
return { sql, semanticRefs: { metrics: [], dimensions: [] }, unresolvedRefs: [] };
|
|
1984
|
+
}
|
|
1985
|
+
const resolution = resolveSemanticRefs(sql, semanticLayer);
|
|
1986
|
+
return {
|
|
1987
|
+
sql: resolution.resolvedSql,
|
|
1988
|
+
semanticRefs: {
|
|
1989
|
+
metrics: resolution.resolvedMetrics,
|
|
1990
|
+
dimensions: resolution.resolvedDimensions,
|
|
1991
|
+
},
|
|
1992
|
+
unresolvedRefs: resolution.unresolvedRefs,
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1944
1995
|
export function normalizeProjectConnection(connection, projectRoot) {
|
|
1945
1996
|
const normalized = { ...connection };
|
|
1946
1997
|
if ((normalized.driver === 'file' || normalized.driver === 'duckdb') && normalized.filepath && normalized.filepath !== ':memory:' && !isAbsoluteLikePath(normalized.filepath)) {
|
|
@@ -2720,6 +2771,26 @@ function canonicalizeSafe(source) {
|
|
|
2720
2771
|
return source;
|
|
2721
2772
|
}
|
|
2722
2773
|
}
|
|
2774
|
+
export function readGitMetadata(projectRoot) {
|
|
2775
|
+
const run = (cmd) => execSync(cmd, { cwd: projectRoot, encoding: 'utf-8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
2776
|
+
try {
|
|
2777
|
+
const commitSha = run('git rev-parse HEAD');
|
|
2778
|
+
let repo = null;
|
|
2779
|
+
let branch = null;
|
|
2780
|
+
try {
|
|
2781
|
+
repo = run('git config --get remote.origin.url') || null;
|
|
2782
|
+
}
|
|
2783
|
+
catch { /* no remote */ }
|
|
2784
|
+
try {
|
|
2785
|
+
branch = run('git rev-parse --abbrev-ref HEAD') || null;
|
|
2786
|
+
}
|
|
2787
|
+
catch { /* detached */ }
|
|
2788
|
+
return { commitSha, repo, branch };
|
|
2789
|
+
}
|
|
2790
|
+
catch {
|
|
2791
|
+
return null;
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2723
2794
|
export function createBlockArtifacts(projectRoot, options) {
|
|
2724
2795
|
const slug = options.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'block';
|
|
2725
2796
|
const safeDomain = (options.domain ?? '')
|
|
@@ -2736,23 +2807,27 @@ export function createBlockArtifacts(projectRoot, options) {
|
|
|
2736
2807
|
const templateContent = options.template
|
|
2737
2808
|
? listBlockTemplates().find((template) => template.id === options.template)?.content
|
|
2738
2809
|
: undefined;
|
|
2810
|
+
const relativePath = safeDomain ? `blocks/${safeDomain}/${slug}.dql` : `blocks/${slug}.dql`;
|
|
2739
2811
|
const fileContent = canonicalizeSafe(normalizeBlockStudioContent({
|
|
2740
2812
|
name: options.name,
|
|
2741
2813
|
domain: safeDomain || 'uncategorized',
|
|
2814
|
+
owner: options.owner,
|
|
2742
2815
|
description: options.description,
|
|
2743
2816
|
tags: options.tags,
|
|
2744
2817
|
content: options.content?.trim() || templateContent,
|
|
2745
2818
|
}));
|
|
2746
2819
|
writeFileSync(blockPath, fileContent, 'utf-8');
|
|
2747
|
-
const relativePath = safeDomain ? `blocks/${safeDomain}/${slug}.dql` : `blocks/${slug}.dql`;
|
|
2748
2820
|
const companionPath = writeBlockCompanionFile(projectRoot, {
|
|
2749
2821
|
slug,
|
|
2750
2822
|
name: options.name,
|
|
2751
2823
|
domain: safeDomain || 'uncategorized',
|
|
2824
|
+
owner: options.owner,
|
|
2752
2825
|
description: options.description,
|
|
2753
2826
|
tags: options.tags,
|
|
2754
2827
|
provider: 'dql',
|
|
2755
2828
|
content: fileContent,
|
|
2829
|
+
gitMetadata: options.gitMetadata,
|
|
2830
|
+
gitPath: relativePath,
|
|
2756
2831
|
});
|
|
2757
2832
|
return {
|
|
2758
2833
|
path: relativePath,
|
|
@@ -2928,6 +3003,17 @@ function writeBlockCompanionFile(projectRoot, options) {
|
|
|
2928
3003
|
for (const table of options.lineage)
|
|
2929
3004
|
lines.push(` - ${yamlScalar(table)}`);
|
|
2930
3005
|
}
|
|
3006
|
+
if (options.gitMetadata || options.gitPath) {
|
|
3007
|
+
lines.push('git:');
|
|
3008
|
+
if (options.gitMetadata?.commitSha)
|
|
3009
|
+
lines.push(` commitSha: ${yamlScalar(options.gitMetadata.commitSha)}`);
|
|
3010
|
+
if (options.gitMetadata?.repo)
|
|
3011
|
+
lines.push(` repo: ${yamlScalar(options.gitMetadata.repo)}`);
|
|
3012
|
+
if (options.gitMetadata?.branch)
|
|
3013
|
+
lines.push(` branch: ${yamlScalar(options.gitMetadata.branch)}`);
|
|
3014
|
+
if (options.gitPath)
|
|
3015
|
+
lines.push(` path: ${yamlScalar(options.gitPath)}`);
|
|
3016
|
+
}
|
|
2931
3017
|
lines.push('reviewStatus: draft');
|
|
2932
3018
|
writeFileSync(companionPath, lines.join('\n') + '\n', 'utf-8');
|
|
2933
3019
|
return relative(projectRoot, companionPath).replaceAll('\\', '/');
|
|
@@ -2968,6 +3054,7 @@ function normalizeBlockStudioContent(options) {
|
|
|
2968
3054
|
return buildBlankBlockContent({
|
|
2969
3055
|
name: options.name,
|
|
2970
3056
|
domain: options.domain,
|
|
3057
|
+
owner: options.owner,
|
|
2971
3058
|
description: options.description,
|
|
2972
3059
|
tags: options.tags,
|
|
2973
3060
|
sql: content || 'SELECT 1 AS value',
|
|
@@ -2979,7 +3066,7 @@ function buildBlankBlockContent(options) {
|
|
|
2979
3066
|
` domain = "${escapeDqlString(options.domain)}"`,
|
|
2980
3067
|
' type = "custom"',
|
|
2981
3068
|
` description = "${escapeDqlString(options.description?.trim() || options.name)}"`,
|
|
2982
|
-
|
|
3069
|
+
` owner = "${escapeDqlString(options.owner?.trim() ?? '')}"`,
|
|
2983
3070
|
];
|
|
2984
3071
|
lines.push(` tags = [${(options.tags ?? []).map((tag) => `"${escapeDqlString(tag)}"`).join(', ')}]`);
|
|
2985
3072
|
lines.push('');
|