@wavemaker/angular-codegen 11.15.6-rc.647667 → 11.16.0-rc.269

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 (39) hide show
  1. package/angular-app/build-scripts/build.js +18 -1
  2. package/angular-app/build-scripts/ng-circle-progress-patch.mjs +38 -0
  3. package/angular-app/build-scripts/ngx-bootstrap-patch.mjs +308 -0
  4. package/angular-app/dependency-report.html +1 -1
  5. package/angular-app/npm-shrinkwrap.json +14517 -16192
  6. package/angular-app/package-lock.json +14517 -16192
  7. package/angular-app/package.json +48 -44
  8. package/angular-app/src/assets/styles/css/wm-responsive.css +1 -1
  9. package/angular-app/src/assets/styles/css/wm-style.css +56 -1
  10. package/angular-app/src/framework/services/component-ref-provider.service.ts +8 -3
  11. package/angular-app/src/framework/services/lazy-component-ref-provider.service.ts +5 -8
  12. package/angular-app/src/setup-jest.js +26 -0
  13. package/angular-app/tsconfig.json +5 -2
  14. package/angular-app/tsconfig.web-app.json +11 -5
  15. package/build-angular-app.js +2 -2
  16. package/dependencies/custom-widgets-bundle.cjs.js +14 -37
  17. package/dependencies/expression-parser.cjs.js +81671 -27260
  18. package/dependencies/pipe-provider.cjs.js +206101 -196686
  19. package/dependencies/transpilation-web.cjs.js +60795 -80092
  20. package/npm-shrinkwrap.json +2154 -2399
  21. package/package-lock.json +2154 -2399
  22. package/package.json +15 -10
  23. package/src/codegen-args-cli.js +1 -1
  24. package/src/expr-parser-utils.js +1 -1
  25. package/src/gen-app-override-css.js +1 -1
  26. package/src/gen-app-skeleton.js +1 -1
  27. package/src/gen-components.js +1 -1
  28. package/src/gen-layouts.js +1 -1
  29. package/src/handlebar-helpers.js +1 -1
  30. package/src/pages-util.js +1 -1
  31. package/src/project-meta.js +1 -1
  32. package/src/update-angular-json.js +1 -1
  33. package/src/wm-utils.js +1 -1
  34. package/templates/app.config.ts.hbs +11 -6
  35. package/templates/customwidget/customwidget.component.ts.hbs +2 -1
  36. package/templates/layout/layout.component.ts.hbs +2 -1
  37. package/templates/page/page.component.ts.hbs +2 -1
  38. package/templates/partial/partial.component.ts.hbs +2 -1
  39. package/templates/prefab/prefab.component.ts.hbs +2 -1
@@ -1,4 +1,5 @@
1
1
  const { spawnSync } = require('child_process');
2
+ const fs = require('fs');
2
3
  const path = require('path');
3
4
 
4
5
  let processArgs = process.argv;
@@ -7,6 +8,21 @@ if (processArgs.findIndex(arg => arg.startsWith('--max-old-space-size')) !== -1)
7
8
  console.log("Setting node options: ", process.env.NODE_OPTIONS);
8
9
  }
9
10
 
11
+ // Patch lives only in build-scripts/ (next to this file), shipped in @wavemaker-ai/angular-app.
12
+ const patchPath = path.join(__dirname, 'ngx-bootstrap-patch.mjs');
13
+ if (!fs.existsSync(patchPath)) {
14
+ console.error('Cannot find ngx-bootstrap-patch.mjs at', patchPath);
15
+ process.exit(1);
16
+ }
17
+ console.log('Using ngx-bootstrap patch at:', patchPath);
18
+ console.log("\x1b[36m", "Patching ngx-bootstrap ESM files...\x1b[0m");
19
+ const patchProcess = spawnSync('node', [patchPath], { stdio: 'inherit' });
20
+
21
+ if (patchProcess.status !== 0) {
22
+ console.error('Error patching ngx-bootstrap:', patchProcess.error || patchProcess.stderr);
23
+ process.exit(1);
24
+ }
25
+
10
26
  const args = processArgs.slice(2);
11
27
  const ngBuildArgs = ['build', ...args];
12
28
  console.log("\x1b[33m", "Angular build params: ", ngBuildArgs);
@@ -23,7 +39,8 @@ if (ngBuildProcess.status === 0) {
23
39
  process.exit(1);
24
40
  }
25
41
 
26
- const ngPostBuildArgs = ['build-scripts/post-build.js', ...args];
42
+ const postBuildPath = path.join(__dirname, 'post-build.js');
43
+ const ngPostBuildArgs = [postBuildPath, ...args];
27
44
  console.log("Post build params - ", ngPostBuildArgs);
28
45
 
29
46
  const ngPostBuildProcess = spawnSync('node', ngPostBuildArgs, { stdio: 'inherit' });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ng-circle-progress patching for the UMD (JIT) bundle.
3
+ *
4
+ * ng-circle-progress 1.7.1 is compiled against Angular 14.2.12 and its partial declaration
5
+ * (ɵɵngDeclareComponent) has no `changeDetection` field. The UMD bundle is not run through the
6
+ * Angular linker, so the browser JIT-compiles that declaration — and Angular 22's JIT path
7
+ * (compileComponentDeclaration) defaults a missing `changeDetection` to OnPush regardless of the
8
+ * library's version (the AOT linker only does that for libraries built with Angular >= 22).
9
+ * As OnPush, <circle-progress> never re-renders when its rxjs animation timer assigns `svg`,
10
+ * so it renders as an empty `<circle-progress><!----></circle-progress>`.
11
+ *
12
+ * Fix: pin `changeDetection: Eager` in the declaration, matching the pre-22 behavior.
13
+ */
14
+
15
+ const DECLARATION = /(i0\.ɵɵngDeclareComponent\(\{[^}]*?type: CircleProgressComponent, )/;
16
+
17
+ export function ngCircleProgressPatchPlugin() {
18
+ return {
19
+ name: 'ng-circle-progress-patch',
20
+ transform(code, id) {
21
+ if (!id.includes('ng-circle-progress') || !code.includes('ɵɵngDeclareComponent')) {
22
+ return null;
23
+ }
24
+ if (/type: CircleProgressComponent, [^\n]*changeDetection:/.test(code)) {
25
+ return null;
26
+ }
27
+ if (!DECLARATION.test(code)) {
28
+ throw new Error('[ng-circle-progress-patch] CircleProgressComponent declaration not found — '
29
+ + 'ng-circle-progress output changed, re-check whether the Eager pin is still needed.');
30
+ }
31
+ console.log(' ✅ ng-circle-progress: pinned CircleProgressComponent changeDetection to Eager');
32
+ return {
33
+ code: code.replace(DECLARATION, '$1changeDetection: i0.ChangeDetectionStrategy.Eager, '),
34
+ map: null
35
+ };
36
+ }
37
+ };
38
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * ngx-bootstrap patching utilities.
3
+ * Canonical path: build-scripts/ next to build.js only (angular-app tarball → generated-app/build-scripts/).
4
+ * Do not rely on a separate copy under config/.
5
+ *
6
+ * Provides Rollup plugin for bundling and standalone function for patching ESM files.
7
+ * Patches: PositioningService (DestroyRef, reopen), ComponentLoader (subscriptions),
8
+ * Dropdown/Modal (ngx-bootstrap v20 compatibility).
9
+ *
10
+ * Copied from feature/angular-22-upgrade (WMS-32451, 21→22 hop on stage-classic) — that branch
11
+ * carries 4 patch categories (componentLoader, dropdown, modal, typeahead) this repo's own
12
+ * ngx-bootstrap-patch.mjs never had, tracing back to WMS-29275 (the original 18→20 upgrade).
13
+ * Confirmed the underlying bugs are real on stage-classic's own installed ngx-bootstrap 22.0.0
14
+ * before copying — see patterns/runtime.md §12 for per-patch verification evidence.
15
+ */
16
+
17
+ import fs from 'fs';
18
+ import path from 'path';
19
+
20
+ // ============================================
21
+ // Utilities
22
+ // ============================================
23
+
24
+ const matchesModule = (id, ...modules) =>
25
+ modules.some(mod => id.includes(`ngx-bootstrap-${mod}`) || id.includes(`ngx-bootstrap/${mod}`));
26
+
27
+ const applyReplacement = (code, pattern, replacement, logMsg) => {
28
+ const patched = code.replace(pattern, replacement);
29
+ const changed = patched !== code;
30
+ if (changed && logMsg) console.log(` ✅ ${logMsg}`);
31
+ return { code: patched, changed };
32
+ };
33
+
34
+ // ============================================
35
+ // Patch Definitions
36
+ // ============================================
37
+
38
+ const PATCHES = {
39
+ positioning: {
40
+ matcher: (id) => matchesModule(id, 'positioning'),
41
+ apply: (code) => {
42
+ let current = code;
43
+ let anyChanged = false;
44
+
45
+ // DestroyRef injection fix (ngx-bootstrap 21: takeUntilDestroyed(__destroyRef) without declaration)
46
+ if (
47
+ current.includes('takeUntilDestroyed(__destroyRef)') &&
48
+ !current.includes('const __destroyRef = i0.inject(i0.DestroyRef)')
49
+ ) {
50
+ const r1 = applyReplacement(
51
+ current,
52
+ /(constructor\s*\(\s*(?:ngZone\s*,\s*)?rendererFactory\s*,\s*platformId\s*\)\s*\{)/,
53
+ '$1\n const __destroyRef = i0.inject(i0.DestroyRef);',
54
+ 'Patched PositioningService: DestroyRef injection'
55
+ );
56
+ current = r1.code;
57
+ anyChanged = r1.changed || anyChanged;
58
+ } else if (
59
+ current.includes('takeUntilDestroyed()') &&
60
+ !current.includes('const __destroyRef = i0.inject(i0.DestroyRef)')
61
+ ) {
62
+ const r1 = applyReplacement(
63
+ current,
64
+ /(constructor\s*\(\s*(?:ngZone\s*,\s*)?rendererFactory\s*,\s*platformId\s*\)\s*\{)/,
65
+ '$1\n const __destroyRef = i0.inject(i0.DestroyRef);',
66
+ null
67
+ );
68
+ const r2 = applyReplacement(
69
+ r1.code,
70
+ /takeUntilDestroyed\(\)/g,
71
+ 'takeUntilDestroyed(__destroyRef)',
72
+ 'Patched PositioningService: DestroyRef injection'
73
+ );
74
+ current = r2.code;
75
+ anyChanged = r2.changed || anyChanged;
76
+ }
77
+
78
+ // Repair bad reopen line: a plain replacement string cannot contain literal $$ (see reopen fix below).
79
+ if (current.includes('this.update$.next')) {
80
+ const beforeRepair = current;
81
+ current = current.replace(/this\.update\$\.next\(null\);?/g, () => 'this.update$$.next(null);');
82
+ if (current !== beforeRepair) {
83
+ anyChanged = true;
84
+ console.log(' ✅ Patched PositioningService: Repair update$$.next reopen line');
85
+ }
86
+ }
87
+
88
+ // Reopen fix: pristine addPositionElement only calls set(); gate on that body (not global
89
+ // this.enable(); / calcPosition’s update$$) so the patch still applies after ngx-bootstrap edits.
90
+ const needsPositioningReopenFix =
91
+ /addPositionElement\(options\)\s*\{\s*\n\s*this\.positionElements\.set\(_getHtmlElement\(options\.element\),\s*options\);\s*\n\s*\}/m.test(
92
+ current
93
+ );
94
+ if (needsPositioningReopenFix) {
95
+ const result = applyReplacement(
96
+ current,
97
+ /this\.positionElements\.set\(_getHtmlElement\(options\.element\),\s*options\);/g,
98
+ 'this.positionElements.set(_getHtmlElement(options.element), options);\n this.enable();\n this.update$$$$.next(null);',
99
+ 'Patched PositioningService: Reopen fix'
100
+ );
101
+ current = result.code;
102
+ anyChanged = result.changed || anyChanged;
103
+ }
104
+
105
+ // BS5: computeAutoPlacement returns hyphenated keys (e.g. bottom-end) not in PlacementForBs5;
106
+ // lookup is undefined → dataPlacement.split throws during PositioningService Map.forEach (wm-libs).
107
+ if (!current.includes('PlacementForBs5[data.placement] ?? data.placement')) {
108
+ const r3 = applyReplacement(
109
+ current,
110
+ /const dataPlacement = getBsVer\(\)\.isBs5\s*\n\s*\?\s*PlacementForBs5\[data\.placement\]\s*\n\s*:\s*data\.placement;/,
111
+ `const dataPlacementRaw = getBsVer().isBs5
112
+ ? PlacementForBs5[data.placement] ?? data.placement
113
+ : data.placement;
114
+ const dataPlacement = dataPlacementRaw ?? '';`,
115
+ 'Patched updateContainerClass: BS5 placement fallback'
116
+ );
117
+ current = r3.code;
118
+ anyChanged = r3.changed || anyChanged;
119
+ }
120
+ if (!current.includes('String(dataPlacement).split(/[\\s-]/)[0]')) {
121
+ const safeReplaceLine =
122
+ 'containerClass = containerClass.replace(/left|right|top|bottom|end|start/g, `' +
123
+ '${(String(dataPlacement).split(/[\\s-]/)[0] || \'bottom\')}`' +
124
+ ');';
125
+ const r4 = applyReplacement(
126
+ current,
127
+ /containerClass = containerClass\.replace\(\/left\|right\|top\|bottom\|end\|start\/g, `\$\{dataPlacement\.split\(' '\)\[0\]\}`\);/,
128
+ safeReplaceLine,
129
+ 'Patched updateContainerClass: safe placement primary axis'
130
+ );
131
+ current = r4.code;
132
+ anyChanged = r4.changed || anyChanged;
133
+ }
134
+
135
+ return { code: current, wasPatched: anyChanged };
136
+ }
137
+ },
138
+
139
+ componentLoader: {
140
+ matcher: (id) => matchesModule(id, 'component-loader'),
141
+ apply: (code) => {
142
+ let current = code;
143
+ let anyChanged = false;
144
+
145
+ const patches = [
146
+ {
147
+ condition: !current.includes('this._onShownSubscription = this.onShown.subscribe'),
148
+ pattern: /this\.onShown\.subscribe\(\(\)\s*=>\s*\{/g,
149
+ replacement: 'this._onShownSubscription = this.onShown.subscribe(() => {',
150
+ msg: 'Patched ComponentLoader: Subscription tracking'
151
+ },
152
+ {
153
+ condition: !/hide\([^)]*\)\s*\{[\s\S]*?_unsubscribePositioning\(\)[\s\S]*?_posService\.deletePositionElement/.test(current),
154
+ pattern: /(hide\([^)]*\)\s*\{\s*\n\s*if\s*\(\s*!this\._componentRef\s*\)\s*\{\s*\n\s*return\s+this;\s*\n\s*\}\s*\n\s*)(this\._posService\.deletePositionElement)/,
155
+ replacement: '$1this._unsubscribePositioning();\n $2',
156
+ msg: 'Patched ComponentLoader: Hide cleanup'
157
+ },
158
+ {
159
+ condition: !current.includes('if (this._onShownSubscription)'),
160
+ pattern: /(_unsubscribePositioning\(\)\s*\{\s*\n\s*)(if\s*\(\s*!this\._zoneSubscription\s*\))/,
161
+ replacement: `$1if (this._onShownSubscription) {\n this._onShownSubscription.unsubscribe();\n this._onShownSubscription = void 0;\n }\n $2`,
162
+ msg: 'Patched ComponentLoader: Unsubscribe fix'
163
+ }
164
+ ];
165
+
166
+ for (const { condition, pattern, replacement, msg } of patches) {
167
+ if (condition) {
168
+ const result = applyReplacement(current, pattern, replacement, msg);
169
+ current = result.code;
170
+ anyChanged = result.changed || anyChanged;
171
+ }
172
+ }
173
+
174
+ return { code: current, wasPatched: anyChanged };
175
+ }
176
+ },
177
+
178
+ dropdown: {
179
+ matcher: (id) => matchesModule(id, 'dropdown'),
180
+ apply: (code) => {
181
+ // ngx-bootstrap 20 + Bootstrap 5: host `.show` toggles dropdown visibility. Removing it breaks
182
+ // datetime timepicker (dropdown menu) and similar `[dropdown]` hosts — restore if stripped.
183
+ if (
184
+ code.includes(
185
+ 'properties: { "class.dropup": "dropup", "class.open": "isOpen", "class.show": "isOpen" }'
186
+ )
187
+ ) {
188
+ return { code, wasPatched: false };
189
+ }
190
+ const result = applyReplacement(
191
+ code,
192
+ /properties: \{ "class\.dropup": "dropup", "class\.open": "isOpen" \}/,
193
+ 'properties: { "class.dropup": "dropup", "class.open": "isOpen", "class.show": "isOpen" }',
194
+ 'Patched Dropdown: Restore BS5 show class on directive host'
195
+ );
196
+ return { code: result.code, wasPatched: result.changed };
197
+ }
198
+ },
199
+
200
+ modal: {
201
+ matcher: (id) => matchesModule(id, 'modal'),
202
+ apply: (code) => {
203
+ if (!code.includes("SHOW: 'show'")) {
204
+ return { code, wasPatched: false };
205
+ }
206
+ const result = applyReplacement(
207
+ code,
208
+ /SHOW: 'show'/g,
209
+ "SHOW: 'in'",
210
+ 'Patched Modal: SHOW class to in'
211
+ );
212
+ return { code: result.code, wasPatched: result.changed };
213
+ }
214
+ },
215
+
216
+ typeahead: {
217
+ matcher: (id) => matchesModule(id, 'typeahead'),
218
+ apply: (code) => {
219
+ let current = code;
220
+ let anyChanged = false;
221
+
222
+ if (current.includes(':host.dropdown-menu,.dropdown-menu{overflow-y:auto;height:100px}')) {
223
+ const result = applyReplacement(
224
+ current,
225
+ /:host\.dropdown-menu,\.dropdown-menu\{overflow-y:auto;height:100px\}/g,
226
+ '',
227
+ 'Patched Typeahead: Remove overflow-y and height styles'
228
+ );
229
+ current = result.code;
230
+ anyChanged = result.changed || anyChanged;
231
+ }
232
+
233
+ return { code: current, wasPatched: anyChanged };
234
+ }
235
+ }
236
+ };
237
+
238
+ // ============================================
239
+ // Rollup Plugin
240
+ // ============================================
241
+
242
+ export function ngxBootstrapPatchPlugin() {
243
+ return {
244
+ name: 'ngx-bootstrap-patch',
245
+ transform(code, id) {
246
+ for (const patch of Object.values(PATCHES)) {
247
+ if (patch.matcher(id)) {
248
+ const result = patch.apply(code);
249
+ if (result.wasPatched || result.code !== code) {
250
+ return { code: result.code, map: null };
251
+ }
252
+ }
253
+ }
254
+ return null;
255
+ }
256
+ };
257
+ }
258
+ /**
259
+ * Files to patch in node_modules/ngx-bootstrap (fesm2022 only for Angular 17+)
260
+ */
261
+ const FILES_TO_PATCH = [
262
+ { path: 'positioning/fesm2022/ngx-bootstrap-positioning.mjs', patchKey: 'positioning' },
263
+ { path: 'component-loader/fesm2022/ngx-bootstrap-component-loader.mjs', patchKey: 'componentLoader' },
264
+ { path: 'dropdown/fesm2022/ngx-bootstrap-dropdown.mjs', patchKey: 'dropdown' },
265
+ { path: 'modal/fesm2022/ngx-bootstrap-modal.mjs', patchKey: 'modal' },
266
+ { path: 'typeahead/fesm2022/ngx-bootstrap-typeahead.mjs', patchKey: 'typeahead' }
267
+ ];
268
+
269
+ /**
270
+ * Patch ngx-bootstrap ESM files directly in node_modules.
271
+ * Call this from build.js before Angular build.
272
+ */
273
+ export function patchNgxBootstrapFiles(nodeModulesPath = 'node_modules') {
274
+ console.log('\n🔧 Patching ngx-bootstrap ESM files...\n');
275
+
276
+ const ngxPath = path.join(nodeModulesPath, 'ngx-bootstrap');
277
+ let totalPatched = 0;
278
+
279
+ for (const { path: filePath, patchKey } of FILES_TO_PATCH) {
280
+ const fullPath = path.join(ngxPath, filePath);
281
+
282
+ if (!fs.existsSync(fullPath)) continue;
283
+
284
+ const code = fs.readFileSync(fullPath, 'utf-8');
285
+ const patch = PATCHES[patchKey];
286
+
287
+ if (patch) {
288
+ const result = patch.apply(code);
289
+ if (result.wasPatched) {
290
+ fs.writeFileSync(fullPath, result.code, 'utf-8');
291
+ totalPatched++;
292
+ }
293
+ }
294
+ }
295
+
296
+ console.log(
297
+ totalPatched > 0
298
+ ? `\n✅ Patched ${totalPatched} ngx-bootstrap file(s)\n`
299
+ : '\n✓ ngx-bootstrap files already patched or no patches needed\n'
300
+ );
301
+
302
+ return totalPatched;
303
+ }
304
+
305
+ // CLI entry point
306
+ if (process.argv[1]?.includes('ngx-bootstrap-patch')) {
307
+ patchNgxBootstrapFiles();
308
+ }
@@ -69,7 +69,7 @@
69
69
  <body>
70
70
  <div class="header">
71
71
  <h1>Angular Project Dependencies Report</h1>
72
- <p class="timestamp">Generated on: 7/21/2026, 3:57:42 PM</p>
72
+ <p class="timestamp">Generated on: 10/17/2026, 2:33:44 PM</p>
73
73
  </div>
74
74
 
75
75
  <div class="section">