@dusted/anqst 1.5.1 → 1.6.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.
package/README.md CHANGED
@@ -43,7 +43,7 @@ Settings file (`./AnQst/<WidgetName>.settings.json`) owns project-local AnQst co
43
43
  "layoutVersion": 2,
44
44
  "widgetName": "<WidgetName>",
45
45
  "spec": "./AnQst/<WidgetName>.AnQst.d.ts",
46
- "generate": ["QWidget", "AngularService", "node_express_ws"],
46
+ "generate": ["QWidget", "AngularService", "VanillaTS", "VanillaJS", "node_express_ws"],
47
47
  "widgetCategory": "AnQst Widgets"
48
48
  }
49
49
  ```
@@ -63,6 +63,16 @@ Settings file (`./AnQst/<WidgetName>.settings.json`) owns project-local AnQst co
63
63
  - Updates `tsconfig.json` (when present):
64
64
  - `compilerOptions.paths["anqst-generated/*"] = ["AnQst/generated/frontend/<WidgetName>_Angular/*"]`
65
65
 
66
+ Available generate targets:
67
+
68
+ - Browser frontend targets:
69
+ - `AngularService`
70
+ - `VanillaTS`
71
+ - `VanillaJS`
72
+ - Backend targets:
73
+ - `QWidget`
74
+ - `node_express_ws`
75
+
66
76
  - `anqst test`
67
77
  - Loads settings from `package.json.AnQst`.
68
78
  - Verifies the configured spec.
@@ -72,9 +82,11 @@ Settings file (`./AnQst/<WidgetName>.settings.json`) owns project-local AnQst co
72
82
  - Verifies spec and regenerates selected targets.
73
83
  - Writes only under `./AnQst/generated`.
74
84
  - Removes selected target roots before regeneration (no stale generated files).
75
- - If `QWidget` is enabled and `angular.json` exists:
76
- - runs production Angular build
85
+ - If `QWidget` is enabled and a browser build output is present under project `dist/`:
77
86
  - embeds built web assets into generated Qt widget `webapp/`.
87
+ - If `QWidget` is enabled and `angular.json` exists:
88
+ - `anqst build` may invoke a production Angular build before embedding.
89
+ - Browser bundle discovery is frontend-profile-neutral: Angular and Vanilla browser outputs are both expected to produce a dist tree containing `index.html`.
78
90
  - Generated Qt integration CMake consumes the existing `./AnQst/generated` widget tree and fails fast if the required generated files are missing.
79
91
  - Downstream CMake no longer invokes `npm`, `npx`, or `anqst`; run `anqst build` first, then build C++ against the generated tree.
80
92
  - If `--designerplugin` is enabled:
@@ -106,6 +118,8 @@ Settings file (`./AnQst/<WidgetName>.settings.json`) owns project-local AnQst co
106
118
  generated/
107
119
  frontend/
108
120
  <WidgetName>_Angular/
121
+ <WidgetName>_VanillaTS/
122
+ <WidgetName>_VanillaJS/
109
123
  backend/
110
124
  node/
111
125
  express/
@@ -143,10 +157,37 @@ npx @dusted/anqst test
143
157
  npx @dusted/anqst build
144
158
  ```
145
159
 
160
+ ## Vanilla browser usage
161
+
162
+ Minimal browser-global usage for `VanillaJS`:
163
+
164
+ ```html
165
+ <script src="./AnQst/generated/frontend/BurgerConstructor_VanillaJS/index.js"></script>
166
+ <script>
167
+ (async () => {
168
+ const frontend = await window.AnQstGenerated.widgets.BurgerConstructor.createFrontend();
169
+ const ok = await frontend.services.BurgerService.validateDraft({ name: "Classic" });
170
+ console.log(ok);
171
+ })();
172
+ </script>
173
+ ```
174
+
175
+ TypeScript authors use the same runtime shape with typings from `VanillaTS`:
176
+
177
+ ```ts
178
+ /// <reference path="./AnQst/generated/frontend/BurgerConstructor_VanillaTS/index.d.ts" />
179
+
180
+ async function boot() {
181
+ const frontend = await window.AnQstGenerated.widgets.BurgerConstructor.createFrontend();
182
+ const ok = await frontend.services.BurgerService.validateDraft({ name: "Classic" });
183
+ console.log(frontend.diagnostics.state(), ok);
184
+ }
185
+ ```
186
+
146
187
  ## Two-stage workflow
147
188
 
148
189
  ```bash
149
- # Stage 1: Node/Angular/generation environment
190
+ # Stage 1: browser/backend/generation environment
150
191
  npx @dusted/anqst build
151
192
 
152
193
  # Stage 2: pure Qt/CMake environment, consuming the generated tree
package/dist/src/app.js CHANGED
@@ -65,7 +65,13 @@ function resetGeneratedTargets(cwd, widgetName, targets) {
65
65
  const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, widgetName);
66
66
  const roots = new Set();
67
67
  if (targets.emitAngularService) {
68
- roots.add(layout.frontendRoot);
68
+ roots.add(layout.angularFrontendRoot);
69
+ }
70
+ if (targets.emitVanillaTS) {
71
+ roots.add(layout.vanillaTsFrontendRoot);
72
+ }
73
+ if (targets.emitVanillaJS) {
74
+ roots.add(layout.vanillaJsFrontendRoot);
69
75
  }
70
76
  if (targets.emitNodeExpressWs) {
71
77
  roots.add(layout.nodeExpressRoot);
@@ -84,15 +90,19 @@ function resetGeneratedTargets(cwd, widgetName, targets) {
84
90
  function buildGenerateSummary(cwd, specPath, widgetName, generationTargets) {
85
91
  const layout = (0, layout_1.resolveGeneratedLayoutPaths)(cwd, widgetName);
86
92
  const relativeSpecFile = (0, layout_1.normalizeSlashes)(node_path_1.default.relative(cwd, specPath));
87
- const servicePath = (0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "services"));
88
- const typePath = (0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "types"));
89
93
  const widgetRootPath = (0, layout_1.toProjectRelative)(cwd, layout.cppQtWidgetRoot);
90
94
  const nodePath = (0, layout_1.toProjectRelative)(cwd, layout.nodeExpressRoot);
91
95
  const messageLines = [];
92
96
  messageLines.push(`AnQst spec ${relativeSpecFile} built.`);
93
97
  if (generationTargets.emitAngularService) {
94
- messageLines.push(` Services are available from ${servicePath}.`);
95
- messageLines.push(` Generated types are available from ${typePath}.`);
98
+ messageLines.push(` Angular services are available from ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.angularFrontendRoot, "services"))}.`);
99
+ messageLines.push(` Angular generated types are available from ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.angularFrontendRoot, "types"))}.`);
100
+ }
101
+ if (generationTargets.emitVanillaTS) {
102
+ messageLines.push(` VanillaTS browser bundle is available from ${(0, layout_1.toProjectRelative)(cwd, layout.vanillaTsFrontendRoot)}.`);
103
+ }
104
+ if (generationTargets.emitVanillaJS) {
105
+ messageLines.push(` VanillaJS browser bundle is available from ${(0, layout_1.toProjectRelative)(cwd, layout.vanillaJsFrontendRoot)}.`);
96
106
  }
97
107
  if (generationTargets.emitQWidget) {
98
108
  messageLines.push(` Widget library available in ${widgetRootPath}.`);
@@ -100,7 +110,11 @@ function buildGenerateSummary(cwd, specPath, widgetName, generationTargets) {
100
110
  if (generationTargets.emitNodeExpressWs) {
101
111
  messageLines.push(` Node Express WS module available in ${nodePath}.`);
102
112
  }
103
- if (!generationTargets.emitAngularService && !generationTargets.emitQWidget && !generationTargets.emitNodeExpressWs) {
113
+ if (!generationTargets.emitAngularService
114
+ && !generationTargets.emitVanillaTS
115
+ && !generationTargets.emitVanillaJS
116
+ && !generationTargets.emitQWidget
117
+ && !generationTargets.emitNodeExpressWs) {
104
118
  messageLines.push(" No outputs selected by AnQst.generate.");
105
119
  }
106
120
  return `\n${messageLines.join("\n")}\n`;
@@ -217,8 +231,8 @@ function runBuild(cwd, designerPlugin = false) {
217
231
  if (generationTargets.emitQWidget) {
218
232
  (0, emit_1.installQtIntegrationCMake)(cwd, parsed.widgetName);
219
233
  }
220
- const hasAngularProject = generationTargets.emitQWidget && node_fs_1.default.existsSync(node_path_1.default.join(cwd, "angular.json"));
221
- if (hasAngularProject) {
234
+ const shouldRunAngularBuild = generationTargets.emitQWidget && node_fs_1.default.existsSync(node_path_1.default.join(cwd, "angular.json"));
235
+ if (shouldRunAngularBuild) {
222
236
  const angularBuild = (0, node_child_process_1.spawnSync)("npx", ["ng", "build", "--configuration", "production"], {
223
237
  cwd,
224
238
  stdio: "inherit",
@@ -230,8 +244,8 @@ function runBuild(cwd, designerPlugin = false) {
230
244
  }
231
245
  if (generationTargets.emitQWidget) {
232
246
  const embedded = (0, emit_1.installEmbeddedWebBundle)(cwd, parsed.widgetName);
233
- if (hasAngularProject && !embedded) {
234
- throw new errors_1.VerifyError("Unable to embed Angular output. Ensure ng build produced a dist bundle with index.html.");
247
+ if (shouldRunAngularBuild && !embedded) {
248
+ throw new errors_1.VerifyError("Unable to embed browser output. Ensure the browser build produced a dist bundle with index.html.");
235
249
  }
236
250
  }
237
251
  let designerPluginBuilt = false;
@@ -246,7 +260,11 @@ function runBuild(cwd, designerPlugin = false) {
246
260
  designerPluginBuilt = true;
247
261
  }
248
262
  }
249
- if (!generationTargets.emitAngularService && !generationTargets.emitQWidget && !generationTargets.emitNodeExpressWs) {
263
+ if (!generationTargets.emitAngularService
264
+ && !generationTargets.emitVanillaTS
265
+ && !generationTargets.emitVanillaJS
266
+ && !generationTargets.emitQWidget
267
+ && !generationTargets.emitNodeExpressWs) {
250
268
  return {
251
269
  success: true,
252
270
  message: [
@@ -260,15 +278,25 @@ function runBuild(cwd, designerPlugin = false) {
260
278
  const detailLines = [];
261
279
  if (generationTargets.emitAngularService) {
262
280
  detailLines.push(" Target AngularService:");
263
- detailLines.push(` - Services output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "services"))}`);
264
- detailLines.push(` - Types output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.frontendRoot, "types"))}`);
281
+ detailLines.push(` - Services output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.angularFrontendRoot, "services"))}`);
282
+ detailLines.push(` - Types output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.angularFrontendRoot, "types"))}`);
283
+ }
284
+ if (generationTargets.emitVanillaTS) {
285
+ detailLines.push(" Target VanillaTS:");
286
+ detailLines.push(` - Browser bundle root: ${(0, layout_1.toProjectRelative)(cwd, layout.vanillaTsFrontendRoot)}`);
287
+ detailLines.push(` - Browser global: window.AnQstGenerated.widgets.${parsed.widgetName}`);
288
+ }
289
+ if (generationTargets.emitVanillaJS) {
290
+ detailLines.push(" Target VanillaJS:");
291
+ detailLines.push(` - Browser bundle root: ${(0, layout_1.toProjectRelative)(cwd, layout.vanillaJsFrontendRoot)}`);
292
+ detailLines.push(` - Browser global: window.AnQstGenerated.widgets.${parsed.widgetName}`);
265
293
  }
266
294
  if (generationTargets.emitQWidget) {
267
295
  detailLines.push(" Target QWidget:");
268
296
  detailLines.push(` - Qt integration CMake: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.cppCmakeRoot, "CMakeLists.txt"))}`);
269
297
  detailLines.push(` - Widget output root: ${(0, layout_1.toProjectRelative)(cwd, layout.cppQtWidgetRoot)}`);
270
298
  detailLines.push(" - C++ handoff: downstream CMake consumes this generated tree directly");
271
- detailLines.push(" - Embedded web assets refreshed from Angular build");
299
+ detailLines.push(" - Embedded web assets refreshed from detected browser dist output");
272
300
  }
273
301
  if (generationTargets.emitNodeExpressWs) {
274
302
  detailLines.push(" Target node_express_ws:");
@@ -436,6 +464,8 @@ function toGenerationTargets(targets) {
436
464
  return {
437
465
  emitQWidget: targets.includes("QWidget"),
438
466
  emitAngularService: targets.includes("AngularService"),
467
+ emitVanillaTS: targets.includes("VanillaTS"),
468
+ emitVanillaJS: targets.includes("VanillaJS"),
439
469
  emitNodeExpressWs: targets.includes("node_express_ws")
440
470
  };
441
471
  }
@@ -452,7 +482,9 @@ function runClean(pathArg, force) {
452
482
  const context = (0, project_1.resolveAnQstSettings)(targetRoot);
453
483
  const layout = (0, layout_1.resolveGeneratedLayoutPaths)(targetRoot, context.settings.widgetName);
454
484
  const widgetDirs = [
455
- (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.frontendRoot)),
485
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.angularFrontendRoot)),
486
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.vanillaTsFrontendRoot)),
487
+ (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.vanillaJsFrontendRoot)),
456
488
  (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.nodeExpressRoot)),
457
489
  (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.cppQtWidgetRoot)),
458
490
  (0, layout_1.normalizeSlashes)(node_path_1.default.relative(targetRoot, layout.cppCmakeRoot)),