@dusted/anqst 0.1.1 → 0.1.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/src/app.js CHANGED
@@ -13,148 +13,135 @@ const node_path_1 = __importDefault(require("node:path"));
13
13
  const node_fs_1 = __importDefault(require("node:fs"));
14
14
  const node_child_process_1 = require("node:child_process");
15
15
  const errors_1 = require("./errors");
16
+ const debug_dump_1 = require("./debug-dump");
16
17
  const emit_1 = require("./emit");
17
18
  const project_1 = require("./project");
18
- const backend_1 = require("./backend");
19
- const ANQSTGEN_ACTIVE_STAMP_FILE = ".anqstgen-version-active.json";
20
- function generationTargetsForBackend(backendId, targets) {
21
- if (backendId !== "tsc")
22
- return targets;
23
- // tsc backend currently supports QWidget and node_express_ws emitters only.
24
- return {
25
- emitQWidget: targets.emitQWidget,
26
- emitAngularService: false,
27
- emitNodeExpressWs: targets.emitNodeExpressWs
28
- };
29
- }
19
+ const layout_1 = require("./layout");
20
+ const parser_1 = require("./parser");
21
+ const verify_1 = require("./verify");
22
+ const build_stamp_1 = require("./build-stamp");
30
23
  function renderHelp() {
24
+ const version = readActiveBuildStamp();
31
25
  return [
26
+ `anqst version ${version}`,
27
+ "",
32
28
  "Usage:",
33
29
  " anqst <command> [arguments] [options]",
34
30
  "",
35
31
  "Commands:",
36
32
  " instill <WidgetName> Initialize AnQst in current npm project",
37
- " test Verify package.json AnQst spec",
38
- " build [--backend <id>] [--designerplugin[=true|false]] Generate artifacts from package.json AnQst spec",
39
- " generate <specFile> [--backend <id>] Generate artifacts from explicit spec file",
40
- " verify <specFile> [--backend <id>] Verify explicit spec file only",
33
+ " test Verify AnQst spec from package settings",
34
+ " build [--designerplugin[=true|false]] Generate artifacts from package settings",
35
+ " generate <specFile> Generate artifacts from explicit spec file",
36
+ " verify <specFile> Verify explicit spec file only",
41
37
  " clean <path> [-f|--force] Remove generated artifacts under path",
42
38
  "",
43
39
  "Options:",
44
- " --backend <id> Backend for build/generate/verify: ast|tsc",
45
- " --designerplugin Build Qt Designer plugin (build command only, tsc + QWidget)",
46
- " -h, --help Show this help output"
40
+ " --designerplugin Build Qt Designer plugin (build command only, QWidget target required)",
41
+ " -h, --help Show this help output",
42
+ " -v, --version Print CLI version"
47
43
  ].join("\n");
48
44
  }
49
45
  function usageFor(command) {
50
46
  if (command === "instill")
51
47
  return "Usage: anqst instill <WidgetName>";
52
48
  if (command === "build")
53
- return "Usage: anqst build [--backend <id>] [--designerplugin[=true|false]]";
49
+ return "Usage: anqst build [--designerplugin[=true|false]]";
54
50
  if (command === "verify")
55
- return "Usage: anqst verify <specFile> [--backend <id>]";
51
+ return "Usage: anqst verify <specFile>";
56
52
  if (command === "generate")
57
- return "Usage: anqst generate <specFile> [--backend <id>]";
53
+ return "Usage: anqst generate <specFile>";
58
54
  if (command === "clean")
59
55
  return "Usage: anqst clean <path> [-f|--force]";
60
56
  return renderHelp();
61
57
  }
62
- function runVerify(specArg, backendId = "ast") {
63
- const specPath = node_path_1.default.resolve(process.cwd(), specArg);
64
- const backend = (0, backend_1.resolveBackend)(backendId);
65
- const parsed = backend.parseSpecFile(specPath);
66
- const verification = backend.verifySpec(parsed);
67
- return {
68
- success: true,
69
- message: verification.message
70
- };
71
- }
72
- function runGenerate(specArg, backendId = "ast") {
73
- const cwd = process.cwd();
74
- const specPath = node_path_1.default.resolve(cwd, specArg);
75
- const backend = (0, backend_1.resolveBackend)(backendId);
76
- const parsed = backend.parseSpecFile(specPath);
77
- const verification = backend.verifySpec(parsed);
78
- const generationTargets = generationTargetsForBackend(backend.id, resolveGenerationTargetsFromCwd(cwd));
79
- const outputs = backend.generateOutputs(parsed, generationTargets);
80
- if (backend.emitsArtifacts) {
81
- (0, emit_1.writeGeneratedOutputs)(cwd, outputs);
82
- if (generationTargets.emitAngularService) {
83
- (0, emit_1.installTypeScriptOutputs)(cwd);
84
- }
85
- if (generationTargets.emitQWidget) {
86
- (0, emit_1.installQtIntegrationCMake)(cwd, parsed.widgetName);
87
- }
58
+ function resetGeneratedTargets(cwd, widgetName, targets) {
59
+ const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, widgetName);
60
+ const roots = new Set();
61
+ if (targets.emitAngularService) {
62
+ roots.add(layout.frontendRoot);
88
63
  }
89
- else {
90
- const relativeSpecFile = normalizeSlashes(node_path_1.default.relative(cwd, specPath));
91
- return {
92
- success: true,
93
- verificationMessage: verification.message,
94
- message: `\nAnQst spec ${relativeSpecFile} built.\n Backend '${backend.id}' is a non-emitting skeleton. No artifacts were generated.\n`
95
- };
64
+ if (targets.emitNodeExpressWs) {
65
+ roots.add(layout.nodeExpressRoot);
66
+ }
67
+ if (targets.emitQWidget) {
68
+ roots.add(layout.cppQtWidgetRoot);
69
+ roots.add(layout.cppCmakeRoot);
70
+ }
71
+ if ((0, debug_dump_1.isDebugEnabled)()) {
72
+ roots.add(layout.debugIntermediateRoot);
73
+ }
74
+ for (const root of roots) {
75
+ node_fs_1.default.rmSync(root, { recursive: true, force: true });
96
76
  }
97
- const relativeSpecFile = normalizeSlashes(node_path_1.default.relative(cwd, specPath));
98
- const relativeTypeScriptInstallPath = normalizeSlashes(node_path_1.default.relative(cwd, node_path_1.default.join(cwd, "src", "anqst-generated")));
99
- const relativeCppLibraryPath = normalizeSlashes(node_path_1.default.relative(cwd, node_path_1.default.join(cwd, "generated_output", `${parsed.widgetName}_QtWidget`)));
100
- const relativeNodeModulePath = normalizeSlashes(node_path_1.default.relative(cwd, node_path_1.default.join(cwd, "generated_output", `${parsed.widgetName}_node_express_ws`)));
101
- const serviceList = parsed.services.map((s) => s.name).join(", ");
77
+ }
78
+ function buildGenerateSummary(cwd, specPath, widgetName, generationTargets) {
79
+ const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, widgetName);
80
+ const relativeSpecFile = (0, layout_1.normalizeSlashes)(node_path_1.default.relative(cwd, specPath));
81
+ const servicePath = (0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "services"));
82
+ const typePath = (0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "types"));
83
+ const widgetRootPath = (0, layout_1.toProjectRelative)(cwd, layout.cppQtWidgetRoot);
84
+ const nodePath = (0, layout_1.toProjectRelative)(cwd, layout.nodeExpressRoot);
102
85
  const messageLines = [];
103
86
  messageLines.push(`AnQst spec ${relativeSpecFile} built.`);
104
87
  if (generationTargets.emitAngularService) {
105
- messageLines.push(` Services ${serviceList} are available from ${relativeTypeScriptInstallPath}/services.`);
106
- messageLines.push(` Generated types are available from ${relativeTypeScriptInstallPath}/types.`);
88
+ messageLines.push(` Services are available from ${servicePath}.`);
89
+ messageLines.push(` Generated types are available from ${typePath}.`);
107
90
  }
108
91
  if (generationTargets.emitQWidget) {
109
- messageLines.push(` Widget library available in ${relativeCppLibraryPath}.`);
92
+ messageLines.push(` Widget library available in ${widgetRootPath}.`);
110
93
  }
111
94
  if (generationTargets.emitNodeExpressWs) {
112
- messageLines.push(` Node Express WS module available in ${relativeNodeModulePath}.`);
95
+ messageLines.push(` Node Express WS module available in ${nodePath}.`);
113
96
  }
114
97
  if (!generationTargets.emitAngularService && !generationTargets.emitQWidget && !generationTargets.emitNodeExpressWs) {
115
98
  messageLines.push(" No outputs selected by AnQst.generate.");
116
99
  }
100
+ return `\n${messageLines.join("\n")}\n`;
101
+ }
102
+ function runVerify(specArg) {
103
+ const specPath = node_path_1.default.resolve(process.cwd(), specArg);
104
+ const parsed = (0, parser_1.parseSpecFile)(specPath);
105
+ const verification = (0, verify_1.verifySpec)(parsed);
106
+ return {
107
+ success: true,
108
+ message: verification.message
109
+ };
110
+ }
111
+ function runGenerate(specArg) {
112
+ const cwd = process.cwd();
113
+ const specPath = node_path_1.default.resolve(cwd, specArg);
114
+ const parsed = (0, parser_1.parseSpecFile)(specPath);
115
+ const verification = (0, verify_1.verifySpec)(parsed);
116
+ const generationTargets = resolveGenerationTargetsFromCwd(cwd);
117
+ resetGeneratedTargets(cwd, parsed.widgetName, generationTargets);
118
+ const outputs = (0, emit_1.generateOutputs)(parsed, generationTargets);
119
+ (0, emit_1.writeGeneratedOutputs)(cwd, outputs);
120
+ if (generationTargets.emitQWidget) {
121
+ (0, emit_1.installQtIntegrationCMake)(cwd, parsed.widgetName);
122
+ }
117
123
  return {
118
124
  success: true,
119
125
  verificationMessage: verification.message,
120
- message: `\n${messageLines.join("\n")}\n`
126
+ message: buildGenerateSummary(cwd, specPath, parsed.widgetName, generationTargets)
121
127
  };
122
128
  }
123
129
  function runTest(cwd) {
124
130
  const specPath = (0, project_1.resolveAnQstSpecPath)(cwd);
125
- const backend = (0, backend_1.resolveBackend)("ast");
126
- const parsed = backend.parseSpecFile(specPath);
127
- const verification = backend.verifySpec(parsed);
131
+ const parsed = (0, parser_1.parseSpecFile)(specPath);
132
+ const verification = (0, verify_1.verifySpec)(parsed);
128
133
  return {
129
134
  success: true,
130
135
  message: verification.message
131
136
  };
132
137
  }
133
- function resolveAnQstGenRoot() {
134
- return node_path_1.default.resolve(__dirname, "..", "..");
135
- }
136
138
  function readActiveBuildStamp() {
137
- if (process.env.ANQST_BUILD_STAMP && process.env.ANQST_BUILD_STAMP.trim().length > 0) {
138
- return process.env.ANQST_BUILD_STAMP.trim();
139
- }
140
- const activePath = node_path_1.default.join(resolveAnQstGenRoot(), ANQSTGEN_ACTIVE_STAMP_FILE);
141
- if (!node_fs_1.default.existsSync(activePath)) {
142
- return "unknown_build_0";
143
- }
144
- try {
145
- const parsed = JSON.parse(node_fs_1.default.readFileSync(activePath, "utf8"));
146
- if (typeof parsed.active === "string" && parsed.active.trim().length > 0) {
147
- return parsed.active.trim();
148
- }
149
- }
150
- catch {
151
- // Fallback to deterministic unknown stamp.
152
- }
153
- return "unknown_build_0";
139
+ return build_stamp_1.ANQST_BUILD_STAMP;
154
140
  }
155
- function runDesignerPluginBuild(cwd) {
156
- const pluginSourceDir = node_path_1.default.join(cwd, "anqst-cmake", "designerplugin");
157
- const pluginBuildDir = node_path_1.default.join(cwd, "anqst-cmake", "build-designerplugin");
141
+ function runDesignerPluginBuild(cwd, widgetName) {
142
+ const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, widgetName);
143
+ const pluginSourceDir = layout.designerPluginRoot;
144
+ const pluginBuildDir = layout.designerPluginBuildRoot;
158
145
  const webBaseDir = process.env.ANQST_WEBBASE_DIR?.trim();
159
146
  if (!webBaseDir) {
160
147
  throw new errors_1.VerifyError("Missing ANQST_WEBBASE_DIR environment variable for --designerplugin build.");
@@ -187,181 +174,117 @@ function runDesignerPluginBuild(cwd) {
187
174
  throw new errors_1.VerifyError("CMake build failed while compiling Qt Designer plugin.");
188
175
  }
189
176
  }
190
- function runBuild(cwd, backendId = "ast", designerPlugin = false) {
177
+ function runBuild(cwd, designerPlugin = false) {
191
178
  const buildVersion = readActiveBuildStamp();
192
- process.env.ANQST_BUILD_STAMP = buildVersion;
193
- try {
194
- const backend = (0, backend_1.resolveBackend)(backendId);
195
- const specPath = (0, project_1.resolveAnQstSpecPath)(cwd);
196
- const generationTargets = generationTargetsForBackend(backend.id, resolveGenerationTargetsFromCwd(cwd, true));
197
- const parsed = backend.parseSpecFile(specPath);
198
- backend.verifySpec(parsed);
199
- const outputs = backend.generateOutputs(parsed, generationTargets);
200
- if (backend.emitsArtifacts) {
201
- (0, emit_1.writeGeneratedOutputs)(cwd, outputs);
202
- if (generationTargets.emitAngularService) {
203
- (0, emit_1.installTypeScriptOutputs)(cwd);
204
- }
205
- if (generationTargets.emitQWidget) {
206
- (0, emit_1.installQtIntegrationCMake)(cwd, parsed.widgetName);
207
- }
208
- }
209
- else {
210
- return {
211
- success: true,
212
- message: `Build completed: backend '${backend.id}' is a non-emitting skeleton; no artifacts were generated`
213
- };
214
- }
215
- const hasAngularProject = generationTargets.emitQWidget && node_fs_1.default.existsSync(node_path_1.default.join(cwd, "angular.json"));
216
- if (hasAngularProject && generationTargets.emitQWidget) {
217
- const angularBuild = (0, node_child_process_1.spawnSync)("npx", ["ng", "build", "--configuration", "production"], {
218
- cwd,
219
- stdio: "inherit",
220
- shell: process.platform === "win32"
221
- });
222
- if (angularBuild.status !== 0) {
223
- throw new errors_1.VerifyError("Angular build failed while preparing embedded widget assets.");
224
- }
225
- }
226
- if (generationTargets.emitQWidget) {
227
- const embedded = (0, emit_1.installEmbeddedWebBundle)(cwd, parsed.widgetName);
228
- if (hasAngularProject && !embedded) {
229
- throw new errors_1.VerifyError("Unable to embed Angular output. Ensure ng build produced a dist bundle with index.html.");
230
- }
231
- }
232
- let designerPluginBuilt = false;
233
- if (designerPlugin) {
234
- if (backend.id !== "tsc") {
235
- console.warn("[AnQst] --designerplugin is only supported with --backend tsc. Skipping designer plugin build.");
236
- }
237
- else if (!generationTargets.emitQWidget) {
238
- console.warn("[AnQst] --designerplugin requested but QWidget target is not enabled. Skipping designer plugin build.");
239
- }
240
- else {
241
- const widgetCategory = (0, project_1.resolveAnQstWidgetCategory)(cwd);
242
- (0, emit_1.installQtDesignerPluginCMake)(cwd, parsed.widgetName, { widgetCategory });
243
- runDesignerPluginBuild(cwd);
244
- designerPluginBuilt = true;
245
- }
246
- }
247
- if (!generationTargets.emitAngularService && !generationTargets.emitQWidget && !generationTargets.emitNodeExpressWs) {
248
- return {
249
- success: true,
250
- message: [
251
- "Build completed.",
252
- ` anqst version ${buildVersion}`,
253
- " No outputs selected by AnQst.generate."
254
- ].join("\n")
255
- };
256
- }
257
- const detailLines = [];
258
- if (generationTargets.emitAngularService) {
259
- detailLines.push(" Target AngularService:");
260
- detailLines.push(" - Services output: src/anqst-generated/services");
261
- detailLines.push(" - Types output: src/anqst-generated/types");
179
+ const specPath = (0, project_1.resolveAnQstSpecPath)(cwd);
180
+ const configuredWidgetName = (0, project_1.resolveAnQstWidgetName)(cwd);
181
+ const generationTargets = resolveGenerationTargetsFromCwd(cwd, true);
182
+ const parsed = (0, parser_1.parseSpecFile)(specPath);
183
+ (0, verify_1.verifySpec)(parsed);
184
+ if (parsed.widgetName !== configuredWidgetName) {
185
+ throw new errors_1.VerifyError(`Settings widgetName '${configuredWidgetName}' does not match spec namespace '${parsed.widgetName}'.`);
186
+ }
187
+ resetGeneratedTargets(cwd, parsed.widgetName, generationTargets);
188
+ const outputs = (0, emit_1.generateOutputs)(parsed, generationTargets);
189
+ (0, emit_1.writeGeneratedOutputs)(cwd, outputs);
190
+ if (generationTargets.emitQWidget) {
191
+ (0, emit_1.installQtIntegrationCMake)(cwd, parsed.widgetName);
192
+ }
193
+ const hasAngularProject = generationTargets.emitQWidget && node_fs_1.default.existsSync(node_path_1.default.join(cwd, "angular.json"));
194
+ if (hasAngularProject) {
195
+ const angularBuild = (0, node_child_process_1.spawnSync)("npx", ["ng", "build", "--configuration", "production"], {
196
+ cwd,
197
+ stdio: "inherit",
198
+ shell: process.platform === "win32"
199
+ });
200
+ if (angularBuild.status !== 0) {
201
+ throw new errors_1.VerifyError("Angular build failed while preparing embedded widget assets.");
262
202
  }
263
- if (generationTargets.emitQWidget) {
264
- detailLines.push(" Target QWidget:");
265
- detailLines.push(" - Qt integration CMake: anqst-cmake/CMakeLists.txt");
266
- detailLines.push(` - Widget output root: generated_output/${parsed.widgetName}_QtWidget`);
267
- detailLines.push(" - Embedded web assets refreshed from Angular build");
203
+ }
204
+ if (generationTargets.emitQWidget) {
205
+ const embedded = (0, emit_1.installEmbeddedWebBundle)(cwd, parsed.widgetName);
206
+ if (hasAngularProject && !embedded) {
207
+ throw new errors_1.VerifyError("Unable to embed Angular output. Ensure ng build produced a dist bundle with index.html.");
268
208
  }
269
- if (generationTargets.emitNodeExpressWs) {
270
- detailLines.push(" Target node_express_ws:");
271
- detailLines.push(` - Module output root: generated_output/${parsed.widgetName}_node_express_ws`);
209
+ }
210
+ let designerPluginBuilt = false;
211
+ if (designerPlugin) {
212
+ if (!generationTargets.emitQWidget) {
213
+ console.warn("[AnQst] --designerplugin requested but QWidget target is not enabled. Skipping designer plugin build.");
272
214
  }
273
- if (designerPluginBuilt) {
274
- const pluginBinaryPath = normalizeSlashes(node_path_1.default.join("anqst-cmake", "build-designerplugin", designerPluginBinaryName(parsed.widgetName)));
275
- detailLines.push(" Target QtDesignerPlugin:");
276
- detailLines.push(" - Build output: anqst-cmake/build-designerplugin");
277
- detailLines.push(` - Plugin binary: ${pluginBinaryPath}`);
278
- detailLines.push(" - Install target dir: <QT_INSTALL_PLUGINS>/designer");
279
- detailLines.push(" - Discover QT_INSTALL_PLUGINS: qmake -query QT_INSTALL_PLUGINS");
280
- detailLines.push(` - Example install: cp ${pluginBinaryPath} "$(qmake -query QT_INSTALL_PLUGINS)/designer/"`);
281
- detailLines.push(` - User-local install: mkdir -p "$HOME/.local/lib/qt5/plugins/designer" && cp ${pluginBinaryPath} "$HOME/.local/lib/qt5/plugins/designer/"`);
215
+ else {
216
+ const widgetCategory = (0, project_1.resolveAnQstWidgetCategory)(cwd);
217
+ (0, emit_1.installQtDesignerPluginCMake)(cwd, parsed.widgetName, { widgetCategory });
218
+ runDesignerPluginBuild(cwd, parsed.widgetName);
219
+ designerPluginBuilt = true;
282
220
  }
221
+ }
222
+ if (!generationTargets.emitAngularService && !generationTargets.emitQWidget && !generationTargets.emitNodeExpressWs) {
283
223
  return {
284
224
  success: true,
285
225
  message: [
286
226
  "Build completed.",
287
227
  ` anqst version ${buildVersion}`,
288
- ...detailLines
228
+ " No outputs selected by AnQst.generate."
289
229
  ].join("\n")
290
230
  };
291
231
  }
292
- finally {
293
- delete process.env.ANQST_BUILD_STAMP;
232
+ const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, parsed.widgetName);
233
+ const detailLines = [];
234
+ if (generationTargets.emitAngularService) {
235
+ detailLines.push(" Target AngularService:");
236
+ detailLines.push(` - Services output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "services"))}`);
237
+ detailLines.push(` - Types output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "types"))}`);
238
+ }
239
+ if (generationTargets.emitQWidget) {
240
+ detailLines.push(" Target QWidget:");
241
+ detailLines.push(` - Qt integration CMake: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.cppCmakeRoot, "CMakeLists.txt"))}`);
242
+ detailLines.push(` - Widget output root: ${(0, layout_1.toProjectRelative)(cwd, layout.cppQtWidgetRoot)}`);
243
+ detailLines.push(" - Embedded web assets refreshed from Angular build");
244
+ }
245
+ if (generationTargets.emitNodeExpressWs) {
246
+ detailLines.push(" Target node_express_ws:");
247
+ detailLines.push(` - Module output root: ${(0, layout_1.toProjectRelative)(cwd, layout.nodeExpressRoot)}`);
248
+ }
249
+ if (designerPluginBuilt) {
250
+ const pluginBinaryPath = (0, layout_1.normalizeSlashes)(node_path_1.default.join((0, layout_1.toProjectRelative)(cwd, layout.designerPluginBuildRoot), designerPluginBinaryName(parsed.widgetName)));
251
+ detailLines.push(" Target QtDesignerPlugin:");
252
+ detailLines.push(` - Build output: ${(0, layout_1.toProjectRelative)(cwd, layout.designerPluginBuildRoot)}`);
253
+ detailLines.push(` - Plugin binary: ${pluginBinaryPath}`);
254
+ detailLines.push(" - Install target dir: <QT_INSTALL_PLUGINS>/designer");
255
+ detailLines.push(" - Discover QT_INSTALL_PLUGINS: qmake -query QT_INSTALL_PLUGINS");
256
+ detailLines.push(` - Example install: cp ${pluginBinaryPath} \"$(qmake -query QT_INSTALL_PLUGINS)/designer/\"`);
257
+ detailLines.push(` - User-local install: mkdir -p \"$HOME/.local/lib/qt5/plugins/designer\" && cp ${pluginBinaryPath} \"$HOME/.local/lib/qt5/plugins/designer/\"`);
294
258
  }
259
+ return {
260
+ success: true,
261
+ message: [
262
+ "Build completed.",
263
+ ` anqst version ${buildVersion}`,
264
+ ...detailLines
265
+ ].join("\n")
266
+ };
295
267
  }
296
- function parseBackendCommandArgs(commandName, specArg, extraArgs, requireSpec) {
268
+ function parseSpecCommandArg(commandName, specArg, extraArgs) {
297
269
  const allArgs = [specArg, ...extraArgs].filter((arg) => typeof arg === "string" && arg.length > 0);
298
- let backendId = "ast";
299
270
  const positional = [];
300
- for (let i = 0; i < allArgs.length; i += 1) {
301
- const arg = allArgs[i];
302
- if (arg === "--backend") {
303
- const value = allArgs[i + 1];
304
- if (!value || value.startsWith("-")) {
305
- throw new Error(`Missing value for --backend. ${usageFor(commandName)}`);
306
- }
307
- if (!(0, backend_1.isBackendId)(value)) {
308
- throw new Error(`Unknown backend '${value}'. Allowed backends: ast, tsc.`);
309
- }
310
- backendId = value;
311
- i += 1;
312
- continue;
313
- }
314
- if (arg.startsWith("--backend=")) {
315
- const value = arg.slice("--backend=".length);
316
- if (!(0, backend_1.isBackendId)(value)) {
317
- throw new Error(`Unknown backend '${value}'. Allowed backends: ast, tsc.`);
318
- }
319
- backendId = value;
320
- continue;
321
- }
271
+ for (const arg of allArgs) {
322
272
  if (arg.startsWith("-")) {
323
273
  throw new Error(`Unknown ${commandName} flag '${arg}'. ${usageFor(commandName)}`);
324
274
  }
325
275
  positional.push(arg);
326
276
  }
327
- if (requireSpec) {
328
- if (positional.length !== 1) {
329
- throw new Error(usageFor(commandName));
330
- }
331
- return { backendId, specArg: positional[0] };
277
+ if (positional.length !== 1) {
278
+ throw new Error(usageFor(commandName));
332
279
  }
333
- if (positional.length > 0) {
334
- throw new Error(`Unexpected extra argument '${positional[0]}'. ${usageFor(commandName)}`);
335
- }
336
- return { backendId };
280
+ return positional[0];
337
281
  }
338
282
  function parseBuildCommandArgs(specArg, extraArgs) {
339
283
  const allArgs = [specArg, ...extraArgs].filter((arg) => typeof arg === "string" && arg.length > 0);
340
- let backendId = "ast";
341
284
  let designerPlugin = false;
342
285
  const positional = [];
343
286
  for (let i = 0; i < allArgs.length; i += 1) {
344
287
  const arg = allArgs[i];
345
- if (arg === "--backend") {
346
- const value = allArgs[i + 1];
347
- if (!value || value.startsWith("-")) {
348
- throw new Error(`Missing value for --backend. ${usageFor("build")}`);
349
- }
350
- if (!(0, backend_1.isBackendId)(value)) {
351
- throw new Error(`Unknown backend '${value}'. Allowed backends: ast, tsc.`);
352
- }
353
- backendId = value;
354
- i += 1;
355
- continue;
356
- }
357
- if (arg.startsWith("--backend=")) {
358
- const value = arg.slice("--backend=".length);
359
- if (!(0, backend_1.isBackendId)(value)) {
360
- throw new Error(`Unknown backend '${value}'. Allowed backends: ast, tsc.`);
361
- }
362
- backendId = value;
363
- continue;
364
- }
365
288
  if (arg === "--designerplugin") {
366
289
  const value = allArgs[i + 1];
367
290
  if (value && !value.startsWith("-")) {
@@ -386,7 +309,7 @@ function parseBuildCommandArgs(specArg, extraArgs) {
386
309
  if (positional.length > 0) {
387
310
  throw new Error(`Unexpected extra argument '${positional[0]}'. ${usageFor("build")}`);
388
311
  }
389
- return { backendId, designerPlugin };
312
+ return { designerPlugin };
390
313
  }
391
314
  function parseCleanCommandArgs(specArg, extraArgs) {
392
315
  const allArgs = [specArg, ...extraArgs].filter((arg) => typeof arg === "string" && arg.length > 0);
@@ -442,7 +365,7 @@ function formatCleanResult(targetRoot, rows) {
442
365
  const notFound = rows.filter((row) => row.status === "not_found");
443
366
  const failed = rows.filter((row) => row.status === "failed");
444
367
  const lines = [];
445
- lines.push(`[AnQst] Clean summary for ${normalizeSlashes(targetRoot)}`);
368
+ lines.push(`[AnQst] Clean summary for ${(0, layout_1.normalizeSlashes)(targetRoot)}`);
446
369
  if (deleted.length > 0) {
447
370
  lines.push(` Deleted (${deleted.length})`);
448
371
  for (const row of deleted)
@@ -464,14 +387,14 @@ function resolveGenerationTargetsFromCwd(cwd, requirePackageAnQst = false) {
464
387
  const packagePath = node_path_1.default.join(cwd, "package.json");
465
388
  if (!node_fs_1.default.existsSync(packagePath)) {
466
389
  if (requirePackageAnQst) {
467
- throw new errors_1.VerifyError("No package.json: Can only build AnQst inside an npm project.");
390
+ throw new errors_1.VerifyError("No package.json: AnQst commands must run inside an npm project.");
468
391
  }
469
392
  return toGenerationTargets([...project_1.DEFAULT_ANQST_GENERATE_TARGETS]);
470
393
  }
471
394
  const packageJson = JSON.parse(node_fs_1.default.readFileSync(packagePath, "utf8"));
472
395
  if (packageJson.AnQst === undefined) {
473
396
  if (requirePackageAnQst) {
474
- throw new errors_1.VerifyError("Missing package.json key 'AnQst.spec'. Run 'anqst instill <WidgetName>' first.");
397
+ throw new errors_1.VerifyError("Missing package.json key 'AnQst'. Run 'anqst instill <WidgetName>' first.");
475
398
  }
476
399
  return toGenerationTargets([...project_1.DEFAULT_ANQST_GENERATE_TARGETS]);
477
400
  }
@@ -484,40 +407,24 @@ function toGenerationTargets(targets) {
484
407
  emitNodeExpressWs: targets.includes("node_express_ws")
485
408
  };
486
409
  }
487
- function resolveAnQstSpecFromPackage(targetRoot) {
488
- const packagePath = node_path_1.default.join(targetRoot, "package.json");
489
- if (!node_fs_1.default.existsSync(packagePath)) {
490
- throw new Error(`No package.json with an AnQst key found at '${normalizeSlashes(targetRoot)}'. Use 'anqst clean ${normalizeSlashes(targetRoot)} --force' to clean anyway.`);
491
- }
492
- const packageJson = JSON.parse(node_fs_1.default.readFileSync(packagePath, "utf8"));
493
- const spec = packageJson.AnQst?.spec;
494
- if (!spec || spec.trim().length === 0) {
495
- throw new Error(`No package.json with an AnQst key found at '${normalizeSlashes(targetRoot)}'. Use 'anqst clean ${normalizeSlashes(targetRoot)} --force' to clean anyway.`);
496
- }
497
- return node_path_1.default.resolve(targetRoot, spec);
498
- }
499
410
  function runClean(pathArg, force) {
500
411
  const targetRoot = node_path_1.default.resolve(process.cwd(), pathArg);
501
- const broadDirs = [
502
- "generated_output",
503
- node_path_1.default.join("src", "anqst-generated"),
504
- "anqst-cmake"
505
- ];
506
412
  if (force) {
507
- const rows = runCleanup(targetRoot, broadDirs);
413
+ const rows = runCleanup(targetRoot, [(0, layout_1.normalizeSlashes)(node_path_1.default.join("AnQst", "generated"))]);
508
414
  return {
509
415
  success: true,
510
416
  message: formatCleanResult(targetRoot, rows),
511
417
  hadFailures: rows.some((row) => row.status === "failed")
512
418
  };
513
419
  }
514
- const specPath = resolveAnQstSpecFromPackage(targetRoot);
515
- const parsed = (0, backend_1.resolveBackend)("ast").parseSpecFile(specPath);
420
+ const context = (0, project_1.resolveAnQstSettings)(targetRoot);
421
+ const layout = (0, layout_1.resolveGeneratedLayoutPaths)(targetRoot, context.settings.widgetName);
516
422
  const widgetDirs = [
517
- node_path_1.default.join("generated_output", `${parsed.widgetName}_QtWidget`),
518
- node_path_1.default.join("generated_output", `${parsed.widgetName}_node_express_ws`),
519
- node_path_1.default.join("src", "anqst-generated"),
520
- "anqst-cmake"
423
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.frontendRoot)),
424
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.nodeExpressRoot)),
425
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.cppQtWidgetRoot)),
426
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.cppCmakeRoot)),
427
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.debugIntermediateRoot))
521
428
  ];
522
429
  const rows = runCleanup(targetRoot, widgetDirs);
523
430
  return {
@@ -526,9 +433,6 @@ function runClean(pathArg, force) {
526
433
  hadFailures: rows.some((row) => row.status === "failed")
527
434
  };
528
435
  }
529
- function normalizeSlashes(inputPath) {
530
- return inputPath.split(node_path_1.default.sep).join("/");
531
- }
532
436
  function designerPluginBinaryName(widgetName) {
533
437
  const targetName = `${widgetName}DesignerPlugin`;
534
438
  if (process.platform === "win32") {
@@ -556,6 +460,10 @@ function runCommand(command, specArg, extraArgs = []) {
556
460
  console.log(renderHelp());
557
461
  return 0;
558
462
  }
463
+ if (command === "-v" || command === "--version" || command === "version") {
464
+ console.log(`anqst version ${readActiveBuildStamp()}`);
465
+ return 0;
466
+ }
559
467
  const normalizedCommand = command === "install" ? "instill" : command;
560
468
  if (command === "install") {
561
469
  console.log(renderInstallAliasMessage());
@@ -576,19 +484,19 @@ function runCommand(command, specArg, extraArgs = []) {
576
484
  }
577
485
  if (normalizedCommand === "build") {
578
486
  const parsedArgs = parseBuildCommandArgs(specArg, extraArgs);
579
- const res = runBuild(process.cwd(), parsedArgs.backendId, parsedArgs.designerPlugin);
487
+ const res = runBuild(process.cwd(), parsedArgs.designerPlugin);
580
488
  console.log(res.message);
581
489
  return 0;
582
490
  }
583
491
  if (normalizedCommand === "verify") {
584
- const parsedArgs = parseBackendCommandArgs("verify", specArg, extraArgs, true);
585
- const res = runVerify(parsedArgs.specArg, parsedArgs.backendId);
492
+ const specArgParsed = parseSpecCommandArg("verify", specArg, extraArgs);
493
+ const res = runVerify(specArgParsed);
586
494
  console.log(res.message);
587
495
  return 0;
588
496
  }
589
497
  if (normalizedCommand === "generate") {
590
- const parsedArgs = parseBackendCommandArgs("generate", specArg, extraArgs, true);
591
- const res = runGenerate(parsedArgs.specArg, parsedArgs.backendId);
498
+ const specArgParsed = parseSpecCommandArg("generate", specArg, extraArgs);
499
+ const res = runGenerate(specArgParsed);
592
500
  if (res.verificationMessage) {
593
501
  console.log(res.verificationMessage);
594
502
  }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ANQST_BUILD_STAMP = void 0;
4
+ // Generated by scripts/build-with-stamp.js. Do not edit by hand.
5
+ exports.ANQST_BUILD_STAMP = "0.1.3/da5d2ee_clean_build_1/2026-03-11";
@@ -9,11 +9,12 @@ exports.inspectText = inspectText;
9
9
  const node_fs_1 = __importDefault(require("node:fs"));
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
11
  const node_util_1 = __importDefault(require("node:util"));
12
+ const layout_1 = require("./layout");
12
13
  function isDebugEnabled() {
13
14
  return process.env.ANQST_DEBUG === "true";
14
15
  }
15
16
  function baseIntermediateDir(cwd) {
16
- return node_path_1.default.join(cwd, "generated_output", "intermediate");
17
+ return (0, layout_1.anqstDebugIntermediateRootDir)(cwd);
17
18
  }
18
19
  function writeDebugFile(cwd, relativePath, content) {
19
20
  if (!isDebugEnabled())