@datashow/super-visual-cli 0.1.0-rc.2 → 0.1.0-rc.4
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/package.json +5 -5
- package/src/main.mjs +33 -15
- package/src/project.mjs +2 -0
- package/templates/blank/package.json +1 -1
- package/templates/hello-world/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datashow/super-visual-cli",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.4",
|
|
4
4
|
"description": "CLI for validating, compiling, packaging, verifying, and deploying Super Visual projects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@datashow/super-visual-adapter-claude-dashboard": "0.1.0-rc.
|
|
29
|
-
"@datashow/super-visual-compiler": "0.1.0-rc.
|
|
30
|
-
"@datashow/super-visual-contracts": "0.1.0-rc.
|
|
31
|
-
"@datashow/super-visual-fabric": "0.1.0-rc.
|
|
28
|
+
"@datashow/super-visual-adapter-claude-dashboard": "0.1.0-rc.4",
|
|
29
|
+
"@datashow/super-visual-compiler": "0.1.0-rc.4",
|
|
30
|
+
"@datashow/super-visual-contracts": "0.1.0-rc.4",
|
|
31
|
+
"@datashow/super-visual-fabric": "0.1.0-rc.4",
|
|
32
32
|
"@fontsource/source-serif-4": "5.3.1",
|
|
33
33
|
"@nivo/bar": "0.99.0",
|
|
34
34
|
"@nivo/line": "0.99.0",
|
package/src/main.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cp, mkdir, mkdtemp, readFile, readdir, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { writeSync } from "node:fs";
|
|
2
3
|
import { execFile } from "node:child_process";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
@@ -15,11 +16,20 @@ import { resolveProjectTarget, targetUpdate, writeProjectTarget } from "./projec
|
|
|
15
16
|
import { runSemanticPreviewTest, startSemanticPreview } from "./semantic-preview.mjs";
|
|
16
17
|
|
|
17
18
|
const run = promisify(execFile);
|
|
18
|
-
const VERSION = "0.1.0-rc.
|
|
19
|
+
const VERSION = "0.1.0-rc.4";
|
|
19
20
|
const FABRIC_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
21
|
const SPINNER_FRAMES = ["|", "/", "-", "\\"];
|
|
22
|
+
const progressStream = process.stderr;
|
|
21
23
|
let activeProgress = null;
|
|
22
24
|
|
|
25
|
+
function writeProgress(value) {
|
|
26
|
+
try {
|
|
27
|
+
writeSync(2, value);
|
|
28
|
+
} catch {
|
|
29
|
+
progressStream.write(value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
23
33
|
export class CliUserError extends Error {
|
|
24
34
|
constructor(message, { summary, guidance } = {}) {
|
|
25
35
|
super(message);
|
|
@@ -51,28 +61,30 @@ function output(value, json) {
|
|
|
51
61
|
export function stopActiveProgress() {
|
|
52
62
|
if (!activeProgress) return;
|
|
53
63
|
clearInterval(activeProgress.timer);
|
|
54
|
-
|
|
64
|
+
writeProgress(`\r${" ".repeat(activeProgress.width)}\r`);
|
|
55
65
|
activeProgress = null;
|
|
56
66
|
}
|
|
57
67
|
|
|
58
|
-
function writeInitProgress(event) {
|
|
59
|
-
if (event.status === "running"
|
|
68
|
+
export function writeInitProgress(event) {
|
|
69
|
+
if (event.status === "running") {
|
|
60
70
|
stopActiveProgress();
|
|
71
|
+
writeProgress(`> ${event.message}\n`);
|
|
72
|
+
if (!progressStream.isTTY) return;
|
|
61
73
|
let frame = 0;
|
|
62
74
|
const render = () => {
|
|
63
|
-
const line = `${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]}
|
|
64
|
-
|
|
75
|
+
const line = `${SPINNER_FRAMES[frame % SPINNER_FRAMES.length]} Working...`;
|
|
76
|
+
writeProgress(`\r${line}`);
|
|
65
77
|
activeProgress.width = Math.max(activeProgress.width, line.length);
|
|
66
78
|
frame += 1;
|
|
67
79
|
};
|
|
68
|
-
activeProgress = { timer: null, width:
|
|
80
|
+
activeProgress = { timer: null, width: 12 };
|
|
69
81
|
render();
|
|
70
|
-
activeProgress.timer = setInterval(render,
|
|
82
|
+
activeProgress.timer = setInterval(render, 120);
|
|
71
83
|
return;
|
|
72
84
|
}
|
|
73
85
|
stopActiveProgress();
|
|
74
|
-
const marker = event.status === "passed" ? "✓" : "
|
|
75
|
-
|
|
86
|
+
const marker = event.status === "passed" ? "✓" : "!";
|
|
87
|
+
writeProgress(`${marker} ${event.message}\n`);
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
function semanticInventory(model) {
|
|
@@ -322,14 +334,19 @@ function createProgram() {
|
|
|
322
334
|
validateFabricId(options.workspaceId, "--workspace-id");
|
|
323
335
|
validateFabricId(options.semanticModelId, "--semantic-model-id");
|
|
324
336
|
const json = jsonEnabled(command);
|
|
325
|
-
if (!json)
|
|
337
|
+
if (!json) writeProgress(`\nSuper Visual init\n\n`);
|
|
326
338
|
let liveValidation = null;
|
|
327
339
|
if (options.workspaceId && options.semanticModelId && !options.skipLiveValidation) {
|
|
328
|
-
if (!json) writeInitProgress({ status: "running", message: "Verifying the Fabric workspace and Power BI semantic model (read-only)" });
|
|
329
340
|
let inspected;
|
|
330
341
|
try {
|
|
331
342
|
const client = new FabricHttpClient({ timeoutSeconds: Number(options.timeout) });
|
|
332
|
-
inspected = await inspectSemanticModel({
|
|
343
|
+
inspected = await inspectSemanticModel({
|
|
344
|
+
client,
|
|
345
|
+
workspaceId: options.workspaceId,
|
|
346
|
+
workspaceName: options.workspaceName,
|
|
347
|
+
semanticModelId: options.semanticModelId,
|
|
348
|
+
onProgress: json ? null : writeInitProgress,
|
|
349
|
+
});
|
|
333
350
|
} catch (error) {
|
|
334
351
|
throw new CliUserError(error instanceof Error ? error.message : String(error), {
|
|
335
352
|
summary: "Super Visual could not verify the Fabric workspace and semantic model.",
|
|
@@ -346,9 +363,9 @@ function createProgram() {
|
|
|
346
363
|
};
|
|
347
364
|
if (!json) writeInitProgress({ status: "passed", message: `Verified workspace ${inspected.workspace.displayName} and semantic model ${inspected.semanticModel.displayName}` });
|
|
348
365
|
} else if (!json && options.skipLiveValidation) {
|
|
349
|
-
|
|
366
|
+
writeProgress("! Live Fabric validation skipped by request\n");
|
|
350
367
|
} else if (!json) {
|
|
351
|
-
|
|
368
|
+
writeProgress("! No complete Fabric binding supplied; live validation was not run\n");
|
|
352
369
|
}
|
|
353
370
|
const result = await initializeProject({
|
|
354
371
|
directory,
|
|
@@ -360,6 +377,7 @@ function createProgram() {
|
|
|
360
377
|
onProgress: json ? null : writeInitProgress,
|
|
361
378
|
});
|
|
362
379
|
if (options.workspaceId) {
|
|
380
|
+
if (!json) writeInitProgress({ status: "running", message: "Saving the reusable Fabric project binding" });
|
|
363
381
|
const saved = await writeProjectTarget(result.directory, targetUpdate({
|
|
364
382
|
...options,
|
|
365
383
|
workspaceName: options.workspaceName ?? liveValidation?.workspace.displayName,
|
package/src/project.mjs
CHANGED
|
@@ -286,9 +286,11 @@ export async function initializeProject({ directory, template = "blank", name, t
|
|
|
286
286
|
await writeFile(path.join(target, "README.md"), blankReadme(projectTitle));
|
|
287
287
|
}
|
|
288
288
|
if (app) {
|
|
289
|
+
onProgress?.({ status: "running", step: "application", message: `Importing React application from ${path.resolve(app)}` });
|
|
289
290
|
await installApplication(target, app, projectTitle);
|
|
290
291
|
onProgress?.({ status: "passed", step: "application", message: `Imported React application from ${path.resolve(app)}` });
|
|
291
292
|
}
|
|
293
|
+
onProgress?.({ status: "running", step: "source", message: "Synchronizing React source and report-source contract" });
|
|
292
294
|
const style = await readFile(path.join(target, "source", "report-design.less"), "utf8");
|
|
293
295
|
const designHash = createHash("sha256").update(style).digest("hex");
|
|
294
296
|
await replaceTemplateTokens(target, { DESIGN_HASH: designHash });
|