@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 +45 -4
- package/dist/src/app.js +47 -15
- package/dist/src/emit.js +1463 -200
- package/dist/src/layout.js +9 -3
- package/dist/src/project.js +3 -3
- package/package.json +1 -1
- package/spec/AnQst-Spec-DSL.d.ts +22 -24
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 `
|
|
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:
|
|
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.
|
|
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(`
|
|
95
|
-
messageLines.push(`
|
|
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
|
|
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
|
|
221
|
-
if (
|
|
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 (
|
|
234
|
-
throw new errors_1.VerifyError("Unable to embed
|
|
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
|
|
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.
|
|
264
|
-
detailLines.push(` - Types output: ${(0, layout_1.toProjectRelative)(cwd, node_path_1.default.join(layout.
|
|
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
|
|
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.
|
|
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)),
|