@duckcodeailabs/dql-cli 1.4.3 → 1.5.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 (283) hide show
  1. package/LICENSE +123 -0
  2. package/README.md +72 -0
  3. package/dist/apps-api.d.ts +79 -0
  4. package/dist/apps-api.d.ts.map +1 -0
  5. package/dist/apps-api.js +934 -0
  6. package/dist/apps-api.js.map +1 -0
  7. package/dist/apps-api.test.d.ts +2 -0
  8. package/dist/apps-api.test.d.ts.map +1 -0
  9. package/dist/apps-api.test.js +111 -0
  10. package/dist/apps-api.test.js.map +1 -0
  11. package/dist/args.d.ts +30 -0
  12. package/dist/args.d.ts.map +1 -0
  13. package/dist/args.js +105 -0
  14. package/dist/args.js.map +1 -0
  15. package/dist/args.test.d.ts +2 -0
  16. package/dist/args.test.d.ts.map +1 -0
  17. package/dist/args.test.js +41 -0
  18. package/dist/args.test.js.map +1 -0
  19. package/dist/assets/dql-notebook/assets/codemirror-DJYUkPr1.js +11 -0
  20. package/dist/assets/dql-notebook/assets/index-R3UrqjLQ.css +1 -0
  21. package/dist/assets/dql-notebook/assets/index-mlfOQ2me.js +857 -0
  22. package/dist/assets/dql-notebook/assets/react-CRB3T2We.js +32 -0
  23. package/dist/assets/dql-notebook/index.html +18 -0
  24. package/dist/assets/notebook-browser/app.js +548 -0
  25. package/dist/assets/notebook-browser/index.html +83 -0
  26. package/dist/assets/notebook-browser/styles.css +336 -0
  27. package/dist/block-studio-import.d.ts +58 -0
  28. package/dist/block-studio-import.d.ts.map +1 -0
  29. package/dist/block-studio-import.js +390 -0
  30. package/dist/block-studio-import.js.map +1 -0
  31. package/dist/block-studio-import.test.d.ts +2 -0
  32. package/dist/block-studio-import.test.d.ts.map +1 -0
  33. package/dist/block-studio-import.test.js +106 -0
  34. package/dist/block-studio-import.test.js.map +1 -0
  35. package/dist/block-templates.d.ts +8 -0
  36. package/dist/block-templates.d.ts.map +1 -0
  37. package/dist/block-templates.js +60 -0
  38. package/dist/block-templates.js.map +1 -0
  39. package/dist/commands/agent.d.ts +19 -0
  40. package/dist/commands/agent.d.ts.map +1 -0
  41. package/dist/commands/agent.js +258 -0
  42. package/dist/commands/agent.js.map +1 -0
  43. package/dist/commands/app.d.ts +32 -0
  44. package/dist/commands/app.d.ts.map +1 -0
  45. package/dist/commands/app.js +307 -0
  46. package/dist/commands/app.js.map +1 -0
  47. package/dist/commands/build.d.ts +3 -0
  48. package/dist/commands/build.d.ts.map +1 -0
  49. package/dist/commands/build.js +69 -0
  50. package/dist/commands/build.js.map +1 -0
  51. package/dist/commands/build.test.d.ts +2 -0
  52. package/dist/commands/build.test.d.ts.map +1 -0
  53. package/dist/commands/build.test.js +44 -0
  54. package/dist/commands/build.test.js.map +1 -0
  55. package/dist/commands/certify.d.ts +3 -0
  56. package/dist/commands/certify.d.ts.map +1 -0
  57. package/dist/commands/certify.js +228 -0
  58. package/dist/commands/certify.js.map +1 -0
  59. package/dist/commands/compile.d.ts +21 -0
  60. package/dist/commands/compile.d.ts.map +1 -0
  61. package/dist/commands/compile.js +198 -0
  62. package/dist/commands/compile.js.map +1 -0
  63. package/dist/commands/compile.test.d.ts +2 -0
  64. package/dist/commands/compile.test.d.ts.map +1 -0
  65. package/dist/commands/compile.test.js +115 -0
  66. package/dist/commands/compile.test.js.map +1 -0
  67. package/dist/commands/diff.d.ts +3 -0
  68. package/dist/commands/diff.d.ts.map +1 -0
  69. package/dist/commands/diff.js +52 -0
  70. package/dist/commands/diff.js.map +1 -0
  71. package/dist/commands/doctor.d.ts +3 -0
  72. package/dist/commands/doctor.d.ts.map +1 -0
  73. package/dist/commands/doctor.js +191 -0
  74. package/dist/commands/doctor.js.map +1 -0
  75. package/dist/commands/doctor.test.d.ts +2 -0
  76. package/dist/commands/doctor.test.d.ts.map +1 -0
  77. package/dist/commands/doctor.test.js +43 -0
  78. package/dist/commands/doctor.test.js.map +1 -0
  79. package/dist/commands/fmt.d.ts +3 -0
  80. package/dist/commands/fmt.d.ts.map +1 -0
  81. package/dist/commands/fmt.js +53 -0
  82. package/dist/commands/fmt.js.map +1 -0
  83. package/dist/commands/import.d.ts +3 -0
  84. package/dist/commands/import.d.ts.map +1 -0
  85. package/dist/commands/import.js +50 -0
  86. package/dist/commands/import.js.map +1 -0
  87. package/dist/commands/info.d.ts +3 -0
  88. package/dist/commands/info.d.ts.map +1 -0
  89. package/dist/commands/info.js +56 -0
  90. package/dist/commands/info.js.map +1 -0
  91. package/dist/commands/init.d.ts +3 -0
  92. package/dist/commands/init.d.ts.map +1 -0
  93. package/dist/commands/init.js +250 -0
  94. package/dist/commands/init.js.map +1 -0
  95. package/dist/commands/init.test.d.ts +2 -0
  96. package/dist/commands/init.test.d.ts.map +1 -0
  97. package/dist/commands/init.test.js +118 -0
  98. package/dist/commands/init.test.js.map +1 -0
  99. package/dist/commands/lineage.d.ts +24 -0
  100. package/dist/commands/lineage.d.ts.map +1 -0
  101. package/dist/commands/lineage.js +634 -0
  102. package/dist/commands/lineage.js.map +1 -0
  103. package/dist/commands/mcp.d.ts +7 -0
  104. package/dist/commands/mcp.d.ts.map +1 -0
  105. package/dist/commands/mcp.js +16 -0
  106. package/dist/commands/mcp.js.map +1 -0
  107. package/dist/commands/migrate.d.ts +12 -0
  108. package/dist/commands/migrate.d.ts.map +1 -0
  109. package/dist/commands/migrate.js +197 -0
  110. package/dist/commands/migrate.js.map +1 -0
  111. package/dist/commands/new.d.ts +3 -0
  112. package/dist/commands/new.d.ts.map +1 -0
  113. package/dist/commands/new.js +490 -0
  114. package/dist/commands/new.js.map +1 -0
  115. package/dist/commands/new.test.d.ts +2 -0
  116. package/dist/commands/new.test.d.ts.map +1 -0
  117. package/dist/commands/new.test.js +191 -0
  118. package/dist/commands/new.test.js.map +1 -0
  119. package/dist/commands/notebook.d.ts +3 -0
  120. package/dist/commands/notebook.d.ts.map +1 -0
  121. package/dist/commands/notebook.js +46 -0
  122. package/dist/commands/notebook.js.map +1 -0
  123. package/dist/commands/parse.d.ts +3 -0
  124. package/dist/commands/parse.d.ts.map +1 -0
  125. package/dist/commands/parse.js +63 -0
  126. package/dist/commands/parse.js.map +1 -0
  127. package/dist/commands/preview.d.ts +3 -0
  128. package/dist/commands/preview.d.ts.map +1 -0
  129. package/dist/commands/preview.js +42 -0
  130. package/dist/commands/preview.js.map +1 -0
  131. package/dist/commands/schedule.d.ts +3 -0
  132. package/dist/commands/schedule.d.ts.map +1 -0
  133. package/dist/commands/schedule.js +215 -0
  134. package/dist/commands/schedule.js.map +1 -0
  135. package/dist/commands/semantic.d.ts +12 -0
  136. package/dist/commands/semantic.d.ts.map +1 -0
  137. package/dist/commands/semantic.js +356 -0
  138. package/dist/commands/semantic.js.map +1 -0
  139. package/dist/commands/serve.d.ts +3 -0
  140. package/dist/commands/serve.d.ts.map +1 -0
  141. package/dist/commands/serve.js +30 -0
  142. package/dist/commands/serve.js.map +1 -0
  143. package/dist/commands/slack.d.ts +13 -0
  144. package/dist/commands/slack.d.ts.map +1 -0
  145. package/dist/commands/slack.js +53 -0
  146. package/dist/commands/slack.js.map +1 -0
  147. package/dist/commands/sync.d.ts +3 -0
  148. package/dist/commands/sync.d.ts.map +1 -0
  149. package/dist/commands/sync.js +192 -0
  150. package/dist/commands/sync.js.map +1 -0
  151. package/dist/commands/sync.test.d.ts +2 -0
  152. package/dist/commands/sync.test.d.ts.map +1 -0
  153. package/dist/commands/sync.test.js +147 -0
  154. package/dist/commands/sync.test.js.map +1 -0
  155. package/dist/commands/test.d.ts +3 -0
  156. package/dist/commands/test.d.ts.map +1 -0
  157. package/dist/commands/test.js +167 -0
  158. package/dist/commands/test.js.map +1 -0
  159. package/dist/commands/validate.d.ts +3 -0
  160. package/dist/commands/validate.d.ts.map +1 -0
  161. package/dist/commands/validate.js +163 -0
  162. package/dist/commands/validate.js.map +1 -0
  163. package/dist/commands/validate.test.d.ts +2 -0
  164. package/dist/commands/validate.test.d.ts.map +1 -0
  165. package/dist/commands/validate.test.js +55 -0
  166. package/dist/commands/validate.test.js.map +1 -0
  167. package/dist/commands/verify.d.ts +11 -0
  168. package/dist/commands/verify.d.ts.map +1 -0
  169. package/dist/commands/verify.js +74 -0
  170. package/dist/commands/verify.js.map +1 -0
  171. package/dist/digest.d.ts +10 -0
  172. package/dist/digest.d.ts.map +1 -0
  173. package/dist/digest.js +83 -0
  174. package/dist/digest.js.map +1 -0
  175. package/dist/git-service.d.ts +17 -0
  176. package/dist/git-service.d.ts.map +1 -0
  177. package/dist/git-service.js +54 -0
  178. package/dist/git-service.js.map +1 -0
  179. package/dist/governance-runtime.d.ts +15 -0
  180. package/dist/governance-runtime.d.ts.map +1 -0
  181. package/dist/governance-runtime.js +50 -0
  182. package/dist/governance-runtime.js.map +1 -0
  183. package/dist/index.d.ts +3 -0
  184. package/dist/index.d.ts.map +1 -0
  185. package/{index.js → dist/index.js} +5 -0
  186. package/dist/index.js.map +1 -0
  187. package/dist/llm/index.d.ts +4 -0
  188. package/dist/llm/index.d.ts.map +1 -0
  189. package/dist/llm/index.js +20 -0
  190. package/dist/llm/index.js.map +1 -0
  191. package/dist/llm/providers/claude-agent-sdk.d.ts +3 -0
  192. package/dist/llm/providers/claude-agent-sdk.d.ts.map +1 -0
  193. package/dist/llm/providers/claude-agent-sdk.js +174 -0
  194. package/dist/llm/providers/claude-agent-sdk.js.map +1 -0
  195. package/dist/llm/providers/claude-code.d.ts +8 -0
  196. package/dist/llm/providers/claude-code.d.ts.map +1 -0
  197. package/dist/llm/providers/claude-code.js +171 -0
  198. package/dist/llm/providers/claude-code.js.map +1 -0
  199. package/dist/llm/providers/dql-agent-provider.d.ts +5 -0
  200. package/dist/llm/providers/dql-agent-provider.d.ts.map +1 -0
  201. package/dist/llm/providers/dql-agent-provider.js +287 -0
  202. package/dist/llm/providers/dql-agent-provider.js.map +1 -0
  203. package/dist/llm/tools.d.ts +9 -0
  204. package/dist/llm/tools.d.ts.map +1 -0
  205. package/dist/llm/tools.js +112 -0
  206. package/dist/llm/tools.js.map +1 -0
  207. package/dist/llm/types.d.ts +72 -0
  208. package/dist/llm/types.d.ts.map +1 -0
  209. package/dist/llm/types.js +2 -0
  210. package/dist/llm/types.js.map +1 -0
  211. package/dist/local-runtime.d.ts +142 -0
  212. package/dist/local-runtime.d.ts.map +1 -0
  213. package/dist/local-runtime.js +4859 -0
  214. package/dist/local-runtime.js.map +1 -0
  215. package/dist/local-runtime.test.d.ts +2 -0
  216. package/dist/local-runtime.test.d.ts.map +1 -0
  217. package/dist/local-runtime.test.js +241 -0
  218. package/dist/local-runtime.test.js.map +1 -0
  219. package/dist/metricflow.d.ts +35 -0
  220. package/dist/metricflow.d.ts.map +1 -0
  221. package/dist/metricflow.js +122 -0
  222. package/dist/metricflow.js.map +1 -0
  223. package/dist/metricflow.test.d.ts +2 -0
  224. package/dist/metricflow.test.d.ts.map +1 -0
  225. package/dist/metricflow.test.js +54 -0
  226. package/dist/metricflow.test.js.map +1 -0
  227. package/dist/open-browser.d.ts +2 -0
  228. package/dist/open-browser.d.ts.map +1 -0
  229. package/dist/open-browser.js +29 -0
  230. package/dist/open-browser.js.map +1 -0
  231. package/dist/schedule/alerts.d.ts +5 -0
  232. package/dist/schedule/alerts.d.ts.map +1 -0
  233. package/dist/schedule/alerts.js +54 -0
  234. package/dist/schedule/alerts.js.map +1 -0
  235. package/dist/schedule/discovery.d.ts +4 -0
  236. package/dist/schedule/discovery.d.ts.map +1 -0
  237. package/dist/schedule/discovery.js +36 -0
  238. package/dist/schedule/discovery.js.map +1 -0
  239. package/dist/schedule/notifiers/email.d.ts +3 -0
  240. package/dist/schedule/notifiers/email.d.ts.map +1 -0
  241. package/dist/schedule/notifiers/email.js +76 -0
  242. package/dist/schedule/notifiers/email.js.map +1 -0
  243. package/dist/schedule/notifiers/file.d.ts +3 -0
  244. package/dist/schedule/notifiers/file.d.ts.map +1 -0
  245. package/dist/schedule/notifiers/file.js +50 -0
  246. package/dist/schedule/notifiers/file.js.map +1 -0
  247. package/dist/schedule/notifiers/index.d.ts +10 -0
  248. package/dist/schedule/notifiers/index.d.ts.map +1 -0
  249. package/dist/schedule/notifiers/index.js +33 -0
  250. package/dist/schedule/notifiers/index.js.map +1 -0
  251. package/dist/schedule/notifiers/slack.d.ts +3 -0
  252. package/dist/schedule/notifiers/slack.d.ts.map +1 -0
  253. package/dist/schedule/notifiers/slack.js +58 -0
  254. package/dist/schedule/notifiers/slack.js.map +1 -0
  255. package/dist/schedule/runner.d.ts +14 -0
  256. package/dist/schedule/runner.d.ts.map +1 -0
  257. package/dist/schedule/runner.js +225 -0
  258. package/dist/schedule/runner.js.map +1 -0
  259. package/dist/schedule/runs.d.ts +5 -0
  260. package/dist/schedule/runs.d.ts.map +1 -0
  261. package/dist/schedule/runs.js +41 -0
  262. package/dist/schedule/runs.js.map +1 -0
  263. package/dist/schedule/service.d.ts +13 -0
  264. package/dist/schedule/service.d.ts.map +1 -0
  265. package/dist/schedule/service.js +87 -0
  266. package/dist/schedule/service.js.map +1 -0
  267. package/dist/schedule/types.d.ts +70 -0
  268. package/dist/schedule/types.d.ts.map +1 -0
  269. package/dist/schedule/types.js +2 -0
  270. package/dist/schedule/types.js.map +1 -0
  271. package/dist/semantic-import.d.ts +135 -0
  272. package/dist/semantic-import.d.ts.map +1 -0
  273. package/dist/semantic-import.js +979 -0
  274. package/dist/semantic-import.js.map +1 -0
  275. package/dist/semantic-import.test.d.ts +2 -0
  276. package/dist/semantic-import.test.d.ts.map +1 -0
  277. package/dist/semantic-import.test.js +95 -0
  278. package/dist/semantic-import.test.js.map +1 -0
  279. package/dist/settings/provider-settings.d.ts +33 -0
  280. package/dist/settings/provider-settings.d.ts.map +1 -0
  281. package/dist/settings/provider-settings.js +91 -0
  282. package/dist/settings/provider-settings.js.map +1 -0
  283. package/package.json +29 -21
@@ -0,0 +1,163 @@
1
+ import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
2
+ import { dirname, extname, join, relative, resolve } from 'node:path';
3
+ import { Parser, analyze, loadSemanticLayerFromDir } from '@duckcodeailabs/dql-core';
4
+ function normalizePath(path) {
5
+ return path.replaceAll('\\', '/');
6
+ }
7
+ function findProjectRoot(startPath) {
8
+ let current = existsSync(startPath) && statSync(startPath).isFile() ? dirname(startPath) : startPath;
9
+ while (true) {
10
+ if (existsSync(join(current, 'dql.config.json')) || existsSync(join(current, 'blocks')) || existsSync(join(current, 'semantic-layer'))) {
11
+ return current;
12
+ }
13
+ const parent = dirname(current);
14
+ if (parent === current)
15
+ return startPath;
16
+ current = parent;
17
+ }
18
+ }
19
+ function collectDqlFilesFromDir(dirPath, projectRoot) {
20
+ if (!existsSync(dirPath))
21
+ return [];
22
+ const files = [];
23
+ for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
24
+ const entryPath = join(dirPath, entry.name);
25
+ if (entry.isDirectory()) {
26
+ files.push(...collectDqlFilesFromDir(entryPath, projectRoot));
27
+ }
28
+ else if (entry.isFile() && extname(entry.name) === '.dql') {
29
+ files.push({
30
+ filePath: entryPath,
31
+ relativePath: normalizePath(relative(projectRoot, entryPath)),
32
+ });
33
+ }
34
+ }
35
+ return files;
36
+ }
37
+ function collectValidationFiles(targetPath) {
38
+ const target = resolve(targetPath ?? '.');
39
+ const projectRoot = findProjectRoot(target);
40
+ if (existsSync(target)) {
41
+ const targetStat = statSync(target);
42
+ if (targetStat.isFile()) {
43
+ return {
44
+ projectRoot,
45
+ files: extname(target) === '.dql'
46
+ ? [{ filePath: target, relativePath: normalizePath(relative(projectRoot, target)) }]
47
+ : [],
48
+ };
49
+ }
50
+ if (targetStat.isDirectory() && target !== projectRoot) {
51
+ return {
52
+ projectRoot,
53
+ files: collectDqlFilesFromDir(target, projectRoot),
54
+ };
55
+ }
56
+ }
57
+ const dirs = ['blocks', 'dashboards', 'workbooks'];
58
+ return {
59
+ projectRoot,
60
+ files: dirs.flatMap((dir) => collectDqlFilesFromDir(join(projectRoot, dir), projectRoot)),
61
+ };
62
+ }
63
+ export async function runValidate(path, flags) {
64
+ const { projectRoot, files } = collectValidationFiles(path);
65
+ const diagnostics = [];
66
+ // Load semantic layer if present
67
+ let semanticLayer;
68
+ const semanticDir = join(projectRoot, 'semantic-layer');
69
+ if (existsSync(semanticDir)) {
70
+ try {
71
+ semanticLayer = loadSemanticLayerFromDir(semanticDir);
72
+ }
73
+ catch (err) {
74
+ diagnostics.push({
75
+ file: 'semantic-layer/',
76
+ severity: 'error',
77
+ message: `Failed to load semantic layer: ${err instanceof Error ? err.message : String(err)}`,
78
+ });
79
+ }
80
+ }
81
+ for (const { filePath, relativePath } of files) {
82
+ try {
83
+ const source = readFileSync(filePath, 'utf-8');
84
+ const parser = new Parser(source, relativePath);
85
+ const ast = parser.parse();
86
+ // Run semantic analysis
87
+ try {
88
+ const diags = analyze(ast);
89
+ for (const diag of diags) {
90
+ diagnostics.push({
91
+ file: relativePath,
92
+ severity: diag.severity === 'error' ? 'error' : 'warning',
93
+ message: diag.message,
94
+ line: diag.span?.start?.line,
95
+ });
96
+ }
97
+ }
98
+ catch {
99
+ // analyze may throw on some inputs
100
+ }
101
+ // Check semantic block metric references
102
+ for (const stmt of ast.statements) {
103
+ if (stmt.kind !== 'BlockDecl')
104
+ continue;
105
+ const block = stmt;
106
+ if (block.blockType === 'semantic' && block.metricRef) {
107
+ if (semanticLayer) {
108
+ const composed = semanticLayer.composeQuery({
109
+ metrics: [block.metricRef],
110
+ dimensions: [],
111
+ });
112
+ if (!composed) {
113
+ diagnostics.push({
114
+ file: relativePath,
115
+ severity: 'error',
116
+ message: `Metric "${block.metricRef}" referenced in block "${block.name}" not found in semantic layer`,
117
+ });
118
+ }
119
+ }
120
+ else {
121
+ diagnostics.push({
122
+ file: relativePath,
123
+ severity: 'warning',
124
+ message: `Semantic block "${block.name}" references metric "${block.metricRef}" but no semantic-layer/ directory exists`,
125
+ });
126
+ }
127
+ }
128
+ }
129
+ }
130
+ catch (err) {
131
+ diagnostics.push({
132
+ file: relativePath,
133
+ severity: 'error',
134
+ message: `Parse error: ${err instanceof Error ? err.message : String(err)}`,
135
+ });
136
+ }
137
+ }
138
+ const fileCount = files.length;
139
+ // Output
140
+ const errors = diagnostics.filter((d) => d.severity === 'error');
141
+ const warnings = diagnostics.filter((d) => d.severity === 'warning');
142
+ if (flags.format === 'json') {
143
+ console.log(JSON.stringify({ files: fileCount, diagnostics }, null, 2));
144
+ }
145
+ else {
146
+ console.log(`\n Validated ${fileCount} DQL file(s)\n`);
147
+ if (diagnostics.length === 0) {
148
+ console.log(' All files are valid.\n');
149
+ }
150
+ else {
151
+ for (const d of diagnostics) {
152
+ const loc = d.line ? `:${d.line}` : '';
153
+ const icon = d.severity === 'error' ? 'ERROR' : 'WARN';
154
+ console.log(` ${icon} ${d.file}${loc}: ${d.message}`);
155
+ }
156
+ console.log(`\n ${errors.length} error(s), ${warnings.length} warning(s)\n`);
157
+ }
158
+ }
159
+ if (errors.length > 0) {
160
+ process.exitCode = 1;
161
+ }
162
+ }
163
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../src/commands/validate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+ import { runValidate } from './validate.js';
6
+ const tempDirs = [];
7
+ afterEach(() => {
8
+ vi.restoreAllMocks();
9
+ process.exitCode = undefined;
10
+ while (tempDirs.length > 0) {
11
+ const dir = tempDirs.pop();
12
+ if (dir)
13
+ rmSync(dir, { recursive: true, force: true });
14
+ }
15
+ });
16
+ function tempProject() {
17
+ const dir = mkdtempSync(join(tmpdir(), 'dql-validate-'));
18
+ tempDirs.push(dir);
19
+ writeFileSync(join(dir, 'dql.config.json'), JSON.stringify({ version: 1, name: 'validate-test' }));
20
+ return dir;
21
+ }
22
+ function writeValidBlock(path) {
23
+ writeFileSync(path, `block "Monthly Revenue" {
24
+ domain = "finance"
25
+ type = "custom"
26
+ status = "certified"
27
+ query = """
28
+ SELECT 1 AS revenue
29
+ """
30
+ }
31
+ `);
32
+ }
33
+ describe('runValidate', () => {
34
+ it('recursively validates domain-scoped DQL files in a project folder', async () => {
35
+ const root = tempProject();
36
+ mkdirSync(join(root, 'blocks', 'finance'), { recursive: true });
37
+ writeValidBlock(join(root, 'blocks', 'finance', 'monthly_revenue.dql'));
38
+ const log = vi.spyOn(console, 'log').mockImplementation(() => { });
39
+ await runValidate(root, { format: 'text' });
40
+ expect(log.mock.calls.map((call) => call.join(' ')).join('\n')).toContain('Validated 1 DQL file(s)');
41
+ expect(process.exitCode).toBeUndefined();
42
+ });
43
+ it('validates a nested single file while loading project-level context', async () => {
44
+ const root = tempProject();
45
+ mkdirSync(join(root, 'blocks', 'finance'), { recursive: true });
46
+ const blockPath = join(root, 'blocks', 'finance', 'monthly_revenue.dql');
47
+ writeValidBlock(blockPath);
48
+ const log = vi.spyOn(console, 'log').mockImplementation(() => { });
49
+ await runValidate(blockPath, { format: 'json' });
50
+ const payload = JSON.parse(String(log.mock.calls.at(-1)?.[0]));
51
+ expect(payload.files).toBe(1);
52
+ expect(payload.diagnostics).toEqual([]);
53
+ });
54
+ });
55
+ //# sourceMappingURL=validate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../src/commands/validate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `dql verify` — prove the on-disk manifest is reproducible from source.
3
+ *
4
+ * Recompiles the manifest in-memory and diffs it against `dql-manifest.json`.
5
+ * Returns a non-zero exit code (and prints a diff summary) on drift. Used by
6
+ * CI to ensure programmable artifacts (Apps, dashboards, blocks, RLS rules,
7
+ * schedules) stay in lock-step with their source files.
8
+ */
9
+ import type { CLIFlags } from '../args.js';
10
+ export declare function runVerify(_rest: string[], flags: CLIFlags): Promise<void>;
11
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B/E"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `dql verify` — prove the on-disk manifest is reproducible from source.
3
+ *
4
+ * Recompiles the manifest in-memory and diffs it against `dql-manifest.json`.
5
+ * Returns a non-zero exit code (and prints a diff summary) on drift. Used by
6
+ * CI to ensure programmable artifacts (Apps, dashboards, blocks, RLS rules,
7
+ * schedules) stay in lock-step with their source files.
8
+ */
9
+ import { existsSync, readFileSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { buildManifest } from '@duckcodeailabs/dql-core';
12
+ import { findProjectRoot } from '../local-runtime.js';
13
+ export async function runVerify(_rest, flags) {
14
+ const projectRoot = findProjectRoot(process.cwd());
15
+ const manifestPath = join(projectRoot, 'dql-manifest.json');
16
+ if (!existsSync(manifestPath)) {
17
+ throw new Error(`dql-manifest.json not found at ${manifestPath}. Run \`dql compile\` first.`);
18
+ }
19
+ const onDisk = JSON.parse(readFileSync(manifestPath, 'utf-8'));
20
+ const fresh = buildManifest({ projectRoot });
21
+ const drift = diffManifest(onDisk, fresh);
22
+ const json = flags.format === 'json';
23
+ if (drift.length === 0) {
24
+ if (json) {
25
+ console.log(JSON.stringify({ ok: true }));
26
+ }
27
+ else {
28
+ console.log(' ✓ Manifest verified — no drift between source tree and dql-manifest.json.');
29
+ }
30
+ return;
31
+ }
32
+ if (json) {
33
+ console.log(JSON.stringify({ ok: false, drift }, null, 2));
34
+ }
35
+ else {
36
+ console.error(` ✗ Manifest drift detected:`);
37
+ for (const item of drift)
38
+ console.error(` - ${item}`);
39
+ console.error('\n Run `dql compile` to regenerate, then commit.');
40
+ }
41
+ process.exit(1);
42
+ }
43
+ function diffManifest(a, b) {
44
+ const drift = [];
45
+ diffMap('blocks', new Set(Object.keys(a.blocks)), new Set(Object.keys(b.blocks)), drift);
46
+ diffMap('notebooks', new Set(Object.keys(a.notebooks)), new Set(Object.keys(b.notebooks)), drift);
47
+ diffMap('apps', new Set(Object.keys(a.apps ?? {})), new Set(Object.keys(b.apps ?? {})), drift);
48
+ diffMap('dashboards', new Set(Object.keys(a.dashboards ?? {})), new Set(Object.keys(b.dashboards ?? {})), drift);
49
+ diffMap('metrics', new Set(Object.keys(a.metrics)), new Set(Object.keys(b.metrics)), drift);
50
+ diffMap('dimensions', new Set(Object.keys(a.dimensions)), new Set(Object.keys(b.dimensions)), drift);
51
+ diffMap('sources', new Set(Object.keys(a.sources)), new Set(Object.keys(b.sources)), drift);
52
+ // Block-level drift: shape changes that matter for downstream readers.
53
+ for (const [name, block] of Object.entries(a.blocks)) {
54
+ const other = b.blocks[name];
55
+ if (!other)
56
+ continue;
57
+ if (block.sql !== other.sql)
58
+ drift.push(`blocks/${name}: SQL drift`);
59
+ if ((block.status ?? '') !== (other.status ?? ''))
60
+ drift.push(`blocks/${name}: status drift (${block.status} → ${other.status})`);
61
+ if ((block.domain ?? '') !== (other.domain ?? ''))
62
+ drift.push(`blocks/${name}: domain drift`);
63
+ }
64
+ return drift;
65
+ }
66
+ function diffMap(label, a, b, into) {
67
+ for (const k of a)
68
+ if (!b.has(k))
69
+ into.push(`${label}: removed "${k}"`);
70
+ for (const k of b)
71
+ if (!a.has(k))
72
+ into.push(`${label}: added "${k}"`);
73
+ }
74
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Digest build helper — resolves block sources + SHAs and drives digest-emitter.
3
+ *
4
+ * Runs outside compile() so the narrative (potentially LLM-backed) stays an
5
+ * async post-process step and doesn't push async up through the core compiler.
6
+ */
7
+ import { type CompilationOutput, type DigestBuildResult, type DigestLLMProvider } from '@duckcodeailabs/dql-compiler';
8
+ export declare function isDigestOutput(output: CompilationOutput): boolean;
9
+ export declare function runDigestBuild(output: CompilationOutput, projectRoot: string, llm?: DigestLLMProvider): Promise<DigestBuildResult>;
10
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AAEtC,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAEjE;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,iBAAiB,EACzB,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,iBAAiB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CAsB5B"}
package/dist/digest.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Digest build helper — resolves block sources + SHAs and drives digest-emitter.
3
+ *
4
+ * Runs outside compile() so the narrative (potentially LLM-backed) stays an
5
+ * async post-process step and doesn't push async up through the core compiler.
6
+ */
7
+ import { execSync } from 'node:child_process';
8
+ import { existsSync, readFileSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { buildManifest } from '@duckcodeailabs/dql-core';
11
+ import { buildDigest, } from '@duckcodeailabs/dql-compiler';
12
+ export function isDigestOutput(output) {
13
+ return Boolean(output.metadata?.narrative);
14
+ }
15
+ export async function runDigestBuild(output, projectRoot, llm) {
16
+ const narrative = output.metadata?.narrative;
17
+ if (!narrative) {
18
+ throw new Error('runDigestBuild called on non-digest output');
19
+ }
20
+ const sources = loadBlockSources(projectRoot, narrative.sources);
21
+ const digestIR = {
22
+ title: output.metadata.title,
23
+ narrative,
24
+ // The digest-emitter only needs `title` + `narrative` + `sources` for
25
+ // narrative composition; the dashboard HTML is threaded in separately.
26
+ charts: [],
27
+ filters: [],
28
+ params: [],
29
+ notifications: output.metadata.notifications ?? [],
30
+ alerts: output.metadata.alerts ?? [],
31
+ layout: { type: 'grid', columns: 12, items: [] },
32
+ variables: {},
33
+ };
34
+ return buildDigest(digestIR, output.html, sources, llm);
35
+ }
36
+ function loadBlockSources(projectRoot, sourceNames) {
37
+ const manifest = loadOrBuildManifest(projectRoot);
38
+ const sources = new Map();
39
+ for (const name of sourceNames) {
40
+ const block = manifest?.blocks?.[name];
41
+ if (!block) {
42
+ sources.set(name, { path: name, description: undefined });
43
+ continue;
44
+ }
45
+ sources.set(name, {
46
+ path: block.filePath,
47
+ description: block.description,
48
+ gitCommitSha: resolveGitSha(projectRoot, block.filePath),
49
+ });
50
+ }
51
+ return sources;
52
+ }
53
+ function loadOrBuildManifest(projectRoot) {
54
+ const cached = join(projectRoot, 'dql-manifest.json');
55
+ if (existsSync(cached)) {
56
+ try {
57
+ return JSON.parse(readFileSync(cached, 'utf-8'));
58
+ }
59
+ catch {
60
+ // fall through to fresh build
61
+ }
62
+ }
63
+ try {
64
+ return buildManifest({ projectRoot, dqlVersion: '0.0.0' });
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ function resolveGitSha(projectRoot, filePath) {
71
+ try {
72
+ const sha = execSync(`git log -1 --format=%H -- "${filePath}"`, {
73
+ cwd: projectRoot,
74
+ encoding: 'utf-8',
75
+ stdio: ['ignore', 'pipe', 'ignore'],
76
+ }).trim();
77
+ return sha.length > 0 ? sha : undefined;
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ }
83
+ //# sourceMappingURL=digest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.js","sourceRoot":"","sources":["../src/digest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface RepoContext {
2
+ /** Absolute path to the repository root (where `.git` lives). */
3
+ dir: string;
4
+ /** Relative path of the requested file from the repo root, POSIX-separated. */
5
+ relpath: string;
6
+ }
7
+ /**
8
+ * Locate the git repository containing `absPath`. Walks upward looking
9
+ * for a `.git` directory. Returns `null` when no repository is found.
10
+ */
11
+ export declare function findRepoContext(absPath: string): RepoContext | null;
12
+ /**
13
+ * Read the HEAD-committed contents of `relpath` as a UTF-8 string. Returns
14
+ * `null` if HEAD has no such file (newly added in the working copy).
15
+ */
16
+ export declare function readHeadBlob(ctx: RepoContext): Promise<string | null>;
17
+ //# sourceMappingURL=git-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-service.d.ts","sourceRoot":"","sources":["../src/git-service.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAcnE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc3E"}
@@ -0,0 +1,54 @@
1
+ // Thin isomorphic-git wrapper used by `dql diff <path>` to resolve the
2
+ // HEAD blob for a file inside a git repo.
3
+ import { statSync } from 'node:fs';
4
+ import { join, relative, resolve } from 'node:path';
5
+ import git from 'isomorphic-git';
6
+ import * as fs from 'node:fs';
7
+ /**
8
+ * Locate the git repository containing `absPath`. Walks upward looking
9
+ * for a `.git` directory. Returns `null` when no repository is found.
10
+ */
11
+ export function findRepoContext(absPath) {
12
+ let dir = resolve(absPath);
13
+ if (!statSync(dir, { throwIfNoEntry: false })?.isDirectory()) {
14
+ dir = resolve(dir, '..');
15
+ }
16
+ while (true) {
17
+ if (statSync(join(dir, '.git'), { throwIfNoEntry: false })) {
18
+ const rel = relative(dir, absPath).split(/[\\/]/).join('/');
19
+ return { dir, relpath: rel };
20
+ }
21
+ const parent = resolve(dir, '..');
22
+ if (parent === dir)
23
+ return null;
24
+ dir = parent;
25
+ }
26
+ }
27
+ /**
28
+ * Read the HEAD-committed contents of `relpath` as a UTF-8 string. Returns
29
+ * `null` if HEAD has no such file (newly added in the working copy).
30
+ */
31
+ export async function readHeadBlob(ctx) {
32
+ try {
33
+ const commitSha = await git.resolveRef({ fs, dir: ctx.dir, ref: 'HEAD' });
34
+ const { blob } = await git.readBlob({
35
+ fs,
36
+ dir: ctx.dir,
37
+ oid: commitSha,
38
+ filepath: ctx.relpath,
39
+ });
40
+ return new TextDecoder('utf-8').decode(blob);
41
+ }
42
+ catch (error) {
43
+ if (isNotFoundError(error))
44
+ return null;
45
+ throw error;
46
+ }
47
+ }
48
+ function isNotFoundError(error) {
49
+ if (!error || typeof error !== 'object')
50
+ return false;
51
+ const code = error.code;
52
+ return code === 'NotFoundError' || code === 'ENOENT';
53
+ }
54
+ //# sourceMappingURL=git-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-service.js","sourceRoot":"","sources":["../src/git-service.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,0CAA0C;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,GAAG,MAAM,gBAAgB,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAS9B;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC;QAC7D,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAC3D,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5D,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC/B,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAgB;IACjD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC;YAClC,EAAE;YACF,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,SAAS;YACd,QAAQ,EAAE,GAAG,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,IAAI,GAAI,KAA2B,CAAC,IAAI,CAAC;IAC/C,OAAO,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,QAAQ,CAAC;AACvD,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type AppDocument } from '@duckcodeailabs/dql-core';
2
+ import { type AccessLevel, type DataClassification } from '@duckcodeailabs/dql-governance';
3
+ export declare class DQLAccessDeniedError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export declare function runtimeVariables(base: Record<string, unknown> | undefined): Record<string, unknown>;
7
+ export declare function activePersonaAppId(): string | undefined;
8
+ export declare function loadRuntimeApp(projectRoot: string, appId: string | undefined | null): AppDocument | null;
9
+ export declare function assertAppAccess(opts: {
10
+ app: AppDocument | null;
11
+ domain?: string | null;
12
+ classification?: DataClassification | null;
13
+ level?: AccessLevel;
14
+ }): void;
15
+ //# sourceMappingURL=governance-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance-runtime.d.ts","sourceRoot":"","sources":["../src/governance-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAgB,KAAK,WAAW,EAAqB,KAAK,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAM5H,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEnG;AAED,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAEvD;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CAOxG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC3C,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,IAAI,CAcP"}
@@ -0,0 +1,50 @@
1
+ import { loadAppDocument, findAppDocuments, } from '@duckcodeailabs/dql-core';
2
+ import { PolicyEngine } from '@duckcodeailabs/dql-governance';
3
+ import { defaultPersonaRegistry, mergePersonaVariables, } from '@duckcodeailabs/dql-project';
4
+ export class DQLAccessDeniedError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = 'DQLAccessDeniedError';
8
+ }
9
+ }
10
+ export function runtimeVariables(base) {
11
+ return mergePersonaVariables(base ?? {}, defaultPersonaRegistry.active);
12
+ }
13
+ export function activePersonaAppId() {
14
+ return defaultPersonaRegistry.active?.appId;
15
+ }
16
+ export function loadRuntimeApp(projectRoot, appId) {
17
+ if (!appId)
18
+ return null;
19
+ for (const p of findAppDocuments(projectRoot)) {
20
+ const { document } = loadAppDocument(p);
21
+ if (document?.id === appId)
22
+ return document;
23
+ }
24
+ return null;
25
+ }
26
+ export function assertAppAccess(opts) {
27
+ const app = opts.app;
28
+ if (!app)
29
+ return;
30
+ const user = defaultPersonaRegistry.toUserContext();
31
+ const engine = new PolicyEngine(app.policies.map(toAccessPolicy));
32
+ const result = engine.checkAccess(user, opts.domain ?? app.domain, opts.classification ?? 'internal', opts.level ?? 'execute');
33
+ if (!result.allowed) {
34
+ throw new DQLAccessDeniedError(result.reason ?? 'Not authorized');
35
+ }
36
+ }
37
+ function toAccessPolicy(policy) {
38
+ return {
39
+ id: policy.id,
40
+ name: policy.id,
41
+ description: policy.description ?? policy.id,
42
+ domain: policy.domain,
43
+ minClassification: policy.minClassification,
44
+ allowedRoles: policy.allowedRoles,
45
+ allowedUsers: policy.allowedUsers ?? [],
46
+ accessLevel: policy.accessLevel,
47
+ enabled: policy.enabled !== false,
48
+ };
49
+ }
50
+ //# sourceMappingURL=governance-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance-runtime.js","sourceRoot":"","sources":["../src/governance-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,gBAAgB,GAEjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAgE,MAAM,gCAAgC,CAAC;AAC5H,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAErC,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAyC;IACxE,OAAO,qBAAqB,CAAC,IAAI,IAAI,EAAE,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,KAAgC;IAClF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,KAAK,MAAM,CAAC,IAAI,gBAAgB,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,QAAQ,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,EAAE,KAAK,KAAK;YAAE,OAAO,QAAQ,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAK/B;IACC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,MAAM,IAAI,GAAG,sBAAsB,CAAC,aAAa,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,IAAI,EACJ,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,EACzB,IAAI,CAAC,cAAc,IAAI,UAAU,EACjC,IAAI,CAAC,KAAK,IAAI,SAAS,CACxB,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,oBAAoB,CAAC,MAAM,CAAC,MAAM,IAAI,gBAAgB,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAuC;IAC7D,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,IAAI,EAAE,MAAM,CAAC,EAAE;QACf,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE;QAC5C,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;QACvC,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,KAAK;KAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -28,6 +28,7 @@ import { runSchedule } from './commands/schedule.js';
28
28
  import { runAgent } from './commands/agent.js';
29
29
  import { runSlack } from './commands/slack.js';
30
30
  import { runVerify } from './commands/verify.js';
31
+ import { runImport } from './commands/import.js';
31
32
  const HELP = `
32
33
  dql — DQL CLI
33
34
 
@@ -45,6 +46,7 @@ const HELP = `
45
46
  dql info <file.dql> Show block metadata
46
47
  dql migrate <source> Scaffold migration from looker/tableau/dbt/metabase/raw-sql
47
48
  dql migrate format [--check] Upgrade all .dql/.dqlnb files to canonical format
49
+ dql import sql <path> Preview SQL files/folders as draft Block Studio import candidates
48
50
  dql fmt <file.dql|.dqlnb> Format DQL/notebook file in place
49
51
  dql diff <path> Diff a .dql/.dqlnb file vs HEAD
50
52
  dql diff <before> <after> Semantic diff between two files
@@ -139,6 +141,9 @@ async function main() {
139
141
  case 'migrate':
140
142
  await runMigrate(file, flags);
141
143
  break;
144
+ case 'import':
145
+ await runImport(file, rest, flags);
146
+ break;
142
147
  case 'fmt':
143
148
  await runFmt(file, flags);
144
149
  break;