@wavemaker-ai/angular-app 1.0.0-rc.309
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/.npmrc +1 -0
- package/angular.json +274 -0
- package/build-scripts/build.js +53 -0
- package/build-scripts/index-html-transform-ng-serve.ts +20 -0
- package/build-scripts/index-html-transform.js +28 -0
- package/build-scripts/ngx-bootstrap-patch.mjs +287 -0
- package/build-scripts/optimize-css.gulpfile.js +101 -0
- package/build-scripts/post-build.js +217 -0
- package/build-scripts/update-version.js +25 -0
- package/dependencies/app.component.html +40 -0
- package/dependencies/custom-widgets-bundle.cjs.js +421 -0
- package/dependencies/expression-parser.cjs.js +33229 -0
- package/dependencies/pipe-provider.cjs.js +220499 -0
- package/dependencies/transpilation-web.cjs.js +107428 -0
- package/dependency-report.html +124 -0
- package/generate-dependency-report.js +240 -0
- package/npm-shrinkwrap.json +25599 -0
- package/package-lock.json +25599 -0
- package/package.json +131 -0
- package/proxy.conf.js +14 -0
- package/pwa-assets/icons/icon-128x128.png +0 -0
- package/pwa-assets/icons/icon-144x144.png +0 -0
- package/pwa-assets/icons/icon-152x152.png +0 -0
- package/pwa-assets/icons/icon-192x192.png +0 -0
- package/pwa-assets/icons/icon-384x384.png +0 -0
- package/pwa-assets/icons/icon-512x512.png +0 -0
- package/pwa-assets/icons/icon-72x72.png +0 -0
- package/pwa-assets/icons/icon-96x96.png +0 -0
- package/pwa-assets/manifest.json +59 -0
- package/pwa-assets/ngsw-config.json +30 -0
- package/pwa-assets/wmsw-worker.js +24 -0
- package/src/.browserslistrc +12 -0
- package/src/app/app.component.css +0 -0
- package/src/app/app.component.script.js +3 -0
- package/src/app/app.component.variables.ts +3 -0
- package/src/app/app.routes.ts +5 -0
- package/src/app/lazy-load-scripts.resolve.ts +13 -0
- package/src/app/prefabs/prefab-config.js +2 -0
- package/src/app/wm-project-properties.ts +3 -0
- package/src/app/wmProperties.js +13 -0
- package/src/assets/.gitkeep +0 -0
- package/src/assets/print.css +32 -0
- package/src/environments/environment.dev.ts +3 -0
- package/src/environments/environment.prod.ts +3 -0
- package/src/environments/environment.ts +16 -0
- package/src/framework/services/app-extension.service.ts +20 -0
- package/src/framework/services/app-js-provider.service.ts +15 -0
- package/src/framework/services/app-variables-provider.service.ts +15 -0
- package/src/framework/services/component-ref-provider.service.ts +70 -0
- package/src/framework/services/customwidget-config-provider.service.ts +13 -0
- package/src/framework/services/lazy-component-ref-provider.service.ts +79 -0
- package/src/framework/services/prefab-config-provider.service.ts +13 -0
- package/src/framework/util/lazy-module-routes.ts +4 -0
- package/src/framework/util/page-util.ts +7 -0
- package/src/index.html +17 -0
- package/src/main.ts +70 -0
- package/src/polyfills.ts +53 -0
- package/src/setup-jest.js +121 -0
- package/src/styles.css +1 -0
- package/src/tsconfig.app.json +17 -0
- package/src/tslint.json +17 -0
- package/src/typings.d.ts +27 -0
- package/src/wm-namespace.js +13 -0
- package/tsconfig.json +94 -0
- package/tsconfig.web-app.json +81 -0
- package/wm-custom-webpack.config.js +51 -0
package/.npmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
legacy-peer-deps = true
|
package/angular.json
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"newProjectRoot": "projects",
|
|
5
|
+
"projects": {
|
|
6
|
+
"angular-app": {
|
|
7
|
+
"root": "",
|
|
8
|
+
"sourceRoot": "src",
|
|
9
|
+
"projectType": "application",
|
|
10
|
+
"prefix": "app",
|
|
11
|
+
"schematics": {},
|
|
12
|
+
"architect": {
|
|
13
|
+
"build": {
|
|
14
|
+
"builder": "@angular-builders/custom-webpack:browser",
|
|
15
|
+
"options": {
|
|
16
|
+
"main": "src/main.ts",
|
|
17
|
+
"polyfills": "src/polyfills.ts",
|
|
18
|
+
"tsConfig": "src/tsconfig.app.json",
|
|
19
|
+
"assets": [
|
|
20
|
+
"src/favicon.ico",
|
|
21
|
+
"src/favicon.png",
|
|
22
|
+
"src/assets",
|
|
23
|
+
{
|
|
24
|
+
"glob": "**/*",
|
|
25
|
+
"input": "libraries/locales/moment-timezone",
|
|
26
|
+
"output": "/locales/moment-timezone"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"glob": "**/*",
|
|
30
|
+
"input": "node_modules/@wavemaker-ai/app-ng-runtime/locales/moment-timezone",
|
|
31
|
+
"output": "/locales/moment-timezone"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"glob": "**/*",
|
|
35
|
+
"input": "src/servicedefs",
|
|
36
|
+
"output": "/servicedefs/"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"glob": "**/*",
|
|
40
|
+
"input": "resources",
|
|
41
|
+
"output": "/resources/",
|
|
42
|
+
"ignore": [
|
|
43
|
+
"**/*.txt"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"styles": [
|
|
48
|
+
"src/styles.css",
|
|
49
|
+
"src/assets/styles/css/wm-style.css",
|
|
50
|
+
"src/assets/styles/css/wm-responsive.css",
|
|
51
|
+
{
|
|
52
|
+
"input": "src/assets/themes/material/style.css",
|
|
53
|
+
"inject": false,
|
|
54
|
+
"bundleName": "wm-styles"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"input": "src/assets/app.css",
|
|
58
|
+
"inject": false,
|
|
59
|
+
"bundleName": "wm-styles"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"input": "src/assets/print.css",
|
|
63
|
+
"inject": false,
|
|
64
|
+
"bundleName": "print"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"scripts": [
|
|
68
|
+
"./node_modules/d3/dist/d3.min.js",
|
|
69
|
+
"./node_modules/@wavemaker/nvd3/build/nv.d3.min.js",
|
|
70
|
+
"./node_modules/jquery/dist/jquery.min.js",
|
|
71
|
+
"./node_modules/lodash/lodash.min.js",
|
|
72
|
+
"./node_modules/jquery-ui/ui/disable-selection.js",
|
|
73
|
+
"./node_modules/jquery-ui/ui/version.js",
|
|
74
|
+
"./node_modules/jquery-ui/ui/widget.js",
|
|
75
|
+
"./node_modules/jquery-ui/ui/scroll-parent.js",
|
|
76
|
+
"./node_modules/jquery-ui/ui/plugin.js",
|
|
77
|
+
"./node_modules/jquery-ui/ui/data.js",
|
|
78
|
+
"./node_modules/jquery-ui/ui/widgets/mouse.js",
|
|
79
|
+
"./node_modules/jquery-ui/ui/widgets/resizable.js",
|
|
80
|
+
"./node_modules/jquery-ui/ui/widgets/sortable.js",
|
|
81
|
+
"./node_modules/jquery-ui/ui/widgets/draggable.js",
|
|
82
|
+
"./node_modules/jquery-ui/ui/widgets/droppable.js",
|
|
83
|
+
"./node_modules/@wavemaker-ai/app-ng-runtime/scripts/datatable/datatable.js",
|
|
84
|
+
"./node_modules/@wavemaker-ai/app-ng-runtime/scripts/swipey/swipey.jquery.plugin.js",
|
|
85
|
+
"./node_modules/@wavemaker-ai/app-ng-runtime/scripts/jquery.ui.touch-punch/jquery.ui.touch-punch.min.js",
|
|
86
|
+
"./node_modules/summernote/dist/summernote-lite.min.js",
|
|
87
|
+
"./node_modules/iscroll/build/iscroll.js",
|
|
88
|
+
"./node_modules/jssha/dist/sha256.js",
|
|
89
|
+
"./node_modules/@ztree/ztree_v3/js/jquery.ztree.all.js",
|
|
90
|
+
"./node_modules/@wavemaker-ai/app-ng-runtime/scripts/tree-keyboard-navigation/keyboard-navigation.js"
|
|
91
|
+
],
|
|
92
|
+
"allowedCommonJsDependencies": [
|
|
93
|
+
"angular2-websocket/angular2-websocket",
|
|
94
|
+
"he",
|
|
95
|
+
"moment",
|
|
96
|
+
"moment-timezone",
|
|
97
|
+
"x2js"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"configurations": {
|
|
101
|
+
"production": {
|
|
102
|
+
"customWebpackConfig": {
|
|
103
|
+
"path": "./wm-custom-webpack.config.js"
|
|
104
|
+
},
|
|
105
|
+
"indexTransform": "./build-scripts/index-html-transform.js",
|
|
106
|
+
"deployUrl": "ng-bundle/",
|
|
107
|
+
"outputPath": "dist/ng-bundle",
|
|
108
|
+
"index": {
|
|
109
|
+
"input": "src/index.html",
|
|
110
|
+
"output": "../../index.html"
|
|
111
|
+
},
|
|
112
|
+
"fileReplacements": [
|
|
113
|
+
{
|
|
114
|
+
"replace": "src/environments/environment.ts",
|
|
115
|
+
"with": "src/environments/environment.prod.ts"
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"optimization": {
|
|
119
|
+
"scripts": true,
|
|
120
|
+
"styles": {
|
|
121
|
+
"minify": true,
|
|
122
|
+
"inlineCritical": false
|
|
123
|
+
},
|
|
124
|
+
"fonts": true
|
|
125
|
+
},
|
|
126
|
+
"outputHashing": "all",
|
|
127
|
+
"sourceMap": false,
|
|
128
|
+
"namedChunks": false,
|
|
129
|
+
"aot": true,
|
|
130
|
+
"extractLicenses": true,
|
|
131
|
+
"vendorChunk": false,
|
|
132
|
+
"buildOptimizer": true,
|
|
133
|
+
"budgets": [
|
|
134
|
+
{
|
|
135
|
+
"type": "initial",
|
|
136
|
+
"maximumWarning": "5mb"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
"development": {
|
|
141
|
+
"customWebpackConfig": {
|
|
142
|
+
"path": "./wm-custom-webpack.config.js"
|
|
143
|
+
},
|
|
144
|
+
"indexTransform": "./build-scripts/index-html-transform.js",
|
|
145
|
+
"deployUrl": "ng-bundle/",
|
|
146
|
+
"outputPath": "dist/ng-bundle",
|
|
147
|
+
"index": {
|
|
148
|
+
"input": "src/index.html",
|
|
149
|
+
"output": "../../index.html"
|
|
150
|
+
},
|
|
151
|
+
"fileReplacements": [
|
|
152
|
+
{
|
|
153
|
+
"replace": "src/environments/environment.ts",
|
|
154
|
+
"with": "src/environments/environment.dev.ts"
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"optimization": false,
|
|
158
|
+
"outputHashing": "none",
|
|
159
|
+
"sourceMap": true,
|
|
160
|
+
"namedChunks": true,
|
|
161
|
+
"aot": true,
|
|
162
|
+
"extractLicenses": false,
|
|
163
|
+
"vendorChunk": true,
|
|
164
|
+
"buildOptimizer": false,
|
|
165
|
+
"budgets": [
|
|
166
|
+
{
|
|
167
|
+
"type": "initial",
|
|
168
|
+
"maximumWarning": "2mb"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
"local": {
|
|
173
|
+
"customWebpackConfig": {
|
|
174
|
+
"path": "./wm-custom-webpack.config.js"
|
|
175
|
+
},
|
|
176
|
+
"indexTransform": "./build-scripts/index-html-transform.js",
|
|
177
|
+
"deployUrl": "ng-bundle/",
|
|
178
|
+
"outputPath": "dist/ng-bundle",
|
|
179
|
+
"index": {
|
|
180
|
+
"input": "src/index.html",
|
|
181
|
+
"output": "../../index.html"
|
|
182
|
+
},
|
|
183
|
+
"fileReplacements": [
|
|
184
|
+
{
|
|
185
|
+
"replace": "src/environments/environment.ts",
|
|
186
|
+
"with": "src/environments/environment.dev.ts"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"optimization": {
|
|
190
|
+
"scripts": false,
|
|
191
|
+
"styles": {
|
|
192
|
+
"minify": false,
|
|
193
|
+
"inlineCritical": false
|
|
194
|
+
},
|
|
195
|
+
"fonts": true
|
|
196
|
+
},
|
|
197
|
+
"outputHashing": "none",
|
|
198
|
+
"sourceMap": true,
|
|
199
|
+
"namedChunks": true,
|
|
200
|
+
"aot": true,
|
|
201
|
+
"extractLicenses": false,
|
|
202
|
+
"vendorChunk": false,
|
|
203
|
+
"buildOptimizer": true,
|
|
204
|
+
"budgets": [
|
|
205
|
+
{
|
|
206
|
+
"type": "initial",
|
|
207
|
+
"maximumWarning": "2mb"
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
"ng-serve": {
|
|
212
|
+
"indexTransform": "./build-scripts/index-html-transform-ng-serve.ts",
|
|
213
|
+
"deployUrl": "ng-bundle/",
|
|
214
|
+
"outputPath": "dist/ng-bundle",
|
|
215
|
+
"index": "src/index.html",
|
|
216
|
+
"fileReplacements": [
|
|
217
|
+
{
|
|
218
|
+
"replace": "src/environments/environment.ts",
|
|
219
|
+
"with": "src/environments/environment.dev.ts"
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
"optimization": false,
|
|
223
|
+
"outputHashing": "none",
|
|
224
|
+
"sourceMap": true,
|
|
225
|
+
"namedChunks": true,
|
|
226
|
+
"aot": true,
|
|
227
|
+
"extractLicenses": false,
|
|
228
|
+
"vendorChunk": true,
|
|
229
|
+
"buildOptimizer": false,
|
|
230
|
+
"budgets": [
|
|
231
|
+
{
|
|
232
|
+
"type": "initial",
|
|
233
|
+
"maximumWarning": "2mb"
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
"defaultConfiguration": "production"
|
|
239
|
+
},
|
|
240
|
+
"serve": {
|
|
241
|
+
"builder": "@angular-builders/custom-webpack:dev-server",
|
|
242
|
+
"configurations": {
|
|
243
|
+
"development": {
|
|
244
|
+
"buildTarget": "angular-app:build:ng-serve",
|
|
245
|
+
"proxyConfig": "proxy.conf.js"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"defaultConfiguration": "development"
|
|
249
|
+
},
|
|
250
|
+
"extract-i18n": {
|
|
251
|
+
"builder": "@angular-devkit/build-angular:extract-i18n",
|
|
252
|
+
"options": {
|
|
253
|
+
"buildTarget": "angular-app:build"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
"lint": {
|
|
257
|
+
"builder": "@angular-eslint/builder:lint",
|
|
258
|
+
"options": {
|
|
259
|
+
"lintFilePatterns": [
|
|
260
|
+
"src/**/*.ts",
|
|
261
|
+
"src/**/*.html"
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"cli": {
|
|
269
|
+
"analytics": "fe5e8f46-2dff-4044-b3b8-8a1307278ce6",
|
|
270
|
+
"schematicCollections": [
|
|
271
|
+
"@angular-eslint/schematics"
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const { spawnSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
let processArgs = process.argv;
|
|
6
|
+
if (processArgs.findIndex(arg => arg.startsWith('--max-old-space-size')) !== -1) {
|
|
7
|
+
process.env.NODE_OPTIONS = processArgs.pop();
|
|
8
|
+
console.log("Setting node options: ", process.env.NODE_OPTIONS);
|
|
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
|
+
|
|
26
|
+
const args = processArgs.slice(2);
|
|
27
|
+
const ngBuildArgs = ['build', ...args];
|
|
28
|
+
console.log("\x1b[33m", "Angular build params: ", ngBuildArgs);
|
|
29
|
+
|
|
30
|
+
//Trigger angular build with the passed params
|
|
31
|
+
const ngPath = path.resolve(process.cwd(), 'node_modules', '.bin', "ng");
|
|
32
|
+
const ngBuildProcess = spawnSync(ngPath, ngBuildArgs, { stdio: 'inherit', shell: true });
|
|
33
|
+
|
|
34
|
+
if (ngBuildProcess.status === 0) {
|
|
35
|
+
console.log('ng build completed successfully!');
|
|
36
|
+
} else {
|
|
37
|
+
// TODO: JS heap out of memory error handling
|
|
38
|
+
console.error('Error during ng build:', ngBuildProcess.error || ngBuildProcess.stderr);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const postBuildPath = path.join(__dirname, 'post-build.js');
|
|
43
|
+
const ngPostBuildArgs = [postBuildPath, ...args];
|
|
44
|
+
console.log("Post build params - ", ngPostBuildArgs);
|
|
45
|
+
|
|
46
|
+
const ngPostBuildProcess = spawnSync('node', ngPostBuildArgs, { stdio: 'inherit' });
|
|
47
|
+
|
|
48
|
+
if (ngPostBuildProcess.status === 0) {
|
|
49
|
+
console.log('ng post build completed successfully!');
|
|
50
|
+
} else {
|
|
51
|
+
console.error('Error during ng build:', ngPostBuildProcess.error || ngPostBuildProcess.stderr);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {TargetOptions} from '@angular-builders/custom-webpack';
|
|
2
|
+
|
|
3
|
+
export default function indexHtmlTransformNgServe(
|
|
4
|
+
targetOptions: TargetOptions,
|
|
5
|
+
indexHtml: string
|
|
6
|
+
): string {
|
|
7
|
+
const deployUrl = 'ng-bundle/';
|
|
8
|
+
const wmStylesHref = `${deployUrl}wm-styles.css`;
|
|
9
|
+
|
|
10
|
+
const metaDeployUrl = `<meta name="deployUrl" content="${deployUrl}">`;
|
|
11
|
+
const linkWmStyles = `<link rel="stylesheet" type="text/css" href="${wmStylesHref}">`;
|
|
12
|
+
|
|
13
|
+
const injectHtml = `${metaDeployUrl}
|
|
14
|
+
${linkWmStyles}`;
|
|
15
|
+
const headCloseIndex = indexHtml.indexOf('</head>');
|
|
16
|
+
|
|
17
|
+
return `${indexHtml.slice(0, headCloseIndex)}
|
|
18
|
+
${injectHtml}
|
|
19
|
+
${indexHtml.slice(headCloseIndex)}`;
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const node_path = require('path');
|
|
4
|
+
|
|
5
|
+
const validScript = (path,indexHtml)=>{
|
|
6
|
+
return !indexHtml.includes(path);
|
|
7
|
+
}
|
|
8
|
+
const getScriptTag = (path)=>{
|
|
9
|
+
return `<script src="ng-bundle/${path}"></script>`
|
|
10
|
+
}
|
|
11
|
+
module.exports = (targetOptions, indexHtml) =>{
|
|
12
|
+
const vendor_path = node_path.resolve(__dirname+`/../dist/ng-bundle`);
|
|
13
|
+
let vendorScripts = ``;
|
|
14
|
+
fs.readdirSync(vendor_path).forEach((file)=>{
|
|
15
|
+
if(file.indexOf('vendor-')===0){
|
|
16
|
+
if(!file.includes('.br.js') && !file.includes('.gzip.js') && validScript(file,indexHtml)){
|
|
17
|
+
vendorScripts+=getScriptTag(file);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const mainScriptStr = `<script src="ng-bundle/main`;
|
|
23
|
+
const mainIndex = indexHtml.indexOf(mainScriptStr);
|
|
24
|
+
|
|
25
|
+
return `${indexHtml.slice(0,mainIndex)}
|
|
26
|
+
${vendorScripts}
|
|
27
|
+
${indexHtml.slice(mainIndex)}`;
|
|
28
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
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
|
+
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
|
|
14
|
+
// ============================================
|
|
15
|
+
// Utilities
|
|
16
|
+
// ============================================
|
|
17
|
+
|
|
18
|
+
const matchesModule = (id, ...modules) =>
|
|
19
|
+
modules.some(mod => id.includes(`ngx-bootstrap-${mod}`) || id.includes(`ngx-bootstrap/${mod}`));
|
|
20
|
+
|
|
21
|
+
const applyReplacement = (code, pattern, replacement, logMsg) => {
|
|
22
|
+
const patched = code.replace(pattern, replacement);
|
|
23
|
+
const changed = patched !== code;
|
|
24
|
+
if (changed && logMsg) console.log(` ✅ ${logMsg}`);
|
|
25
|
+
return { code: patched, changed };
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ============================================
|
|
29
|
+
// Patch Definitions
|
|
30
|
+
// ============================================
|
|
31
|
+
|
|
32
|
+
const PATCHES = {
|
|
33
|
+
positioning: {
|
|
34
|
+
matcher: (id) => matchesModule(id, 'positioning'),
|
|
35
|
+
apply: (code) => {
|
|
36
|
+
let current = code;
|
|
37
|
+
let anyChanged = false;
|
|
38
|
+
|
|
39
|
+
// DestroyRef injection fix
|
|
40
|
+
if (current.includes('takeUntilDestroyed()') && !current.includes('const __destroyRef = i0.inject(i0.DestroyRef)')) {
|
|
41
|
+
const r1 = applyReplacement(
|
|
42
|
+
current,
|
|
43
|
+
/(constructor\s*\(\s*ngZone\s*,\s*rendererFactory\s*,\s*platformId\s*\)\s*\{)/,
|
|
44
|
+
'$1\n const __destroyRef = i0.inject(i0.DestroyRef);',
|
|
45
|
+
null
|
|
46
|
+
);
|
|
47
|
+
const r2 = applyReplacement(
|
|
48
|
+
r1.code,
|
|
49
|
+
/takeUntilDestroyed\(\)/g,
|
|
50
|
+
'takeUntilDestroyed(__destroyRef)',
|
|
51
|
+
'Patched PositioningService: DestroyRef injection'
|
|
52
|
+
);
|
|
53
|
+
current = r2.code;
|
|
54
|
+
anyChanged = r2.changed || anyChanged;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Repair bad reopen line: a plain replacement string cannot contain literal $$ (see reopen fix below).
|
|
58
|
+
if (current.includes('this.update$.next')) {
|
|
59
|
+
const beforeRepair = current;
|
|
60
|
+
current = current.replace(/this\.update\$\.next\(null\);?/g, () => 'this.update$$.next(null);');
|
|
61
|
+
if (current !== beforeRepair) {
|
|
62
|
+
anyChanged = true;
|
|
63
|
+
console.log(' ✅ Patched PositioningService: Repair update$$.next reopen line');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Reopen fix: pristine addPositionElement only calls set(); gate on that body (not global
|
|
68
|
+
// this.enable(); / calcPosition’s update$$) so the patch still applies after ngx-bootstrap edits.
|
|
69
|
+
const needsPositioningReopenFix =
|
|
70
|
+
/addPositionElement\(options\)\s*\{\s*\n\s*this\.positionElements\.set\(_getHtmlElement\(options\.element\),\s*options\);\s*\n\s*\}/m.test(
|
|
71
|
+
current
|
|
72
|
+
);
|
|
73
|
+
if (needsPositioningReopenFix) {
|
|
74
|
+
const result = applyReplacement(
|
|
75
|
+
current,
|
|
76
|
+
/this\.positionElements\.set\(_getHtmlElement\(options\.element\),\s*options\);/g,
|
|
77
|
+
'this.positionElements.set(_getHtmlElement(options.element), options);\n this.enable();\n this.update$$$$.next(null);',
|
|
78
|
+
'Patched PositioningService: Reopen fix'
|
|
79
|
+
);
|
|
80
|
+
current = result.code;
|
|
81
|
+
anyChanged = result.changed || anyChanged;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// BS5: computeAutoPlacement returns hyphenated keys (e.g. bottom-end) not in PlacementForBs5;
|
|
85
|
+
// lookup is undefined → dataPlacement.split throws during PositioningService Map.forEach (wm-libs).
|
|
86
|
+
if (!current.includes('PlacementForBs5[data.placement] ?? data.placement')) {
|
|
87
|
+
const r3 = applyReplacement(
|
|
88
|
+
current,
|
|
89
|
+
/const dataPlacement = getBsVer\(\)\.isBs5\s*\n\s*\?\s*PlacementForBs5\[data\.placement\]\s*\n\s*:\s*data\.placement;/,
|
|
90
|
+
`const dataPlacementRaw = getBsVer().isBs5
|
|
91
|
+
? PlacementForBs5[data.placement] ?? data.placement
|
|
92
|
+
: data.placement;
|
|
93
|
+
const dataPlacement = dataPlacementRaw ?? '';`,
|
|
94
|
+
'Patched updateContainerClass: BS5 placement fallback'
|
|
95
|
+
);
|
|
96
|
+
current = r3.code;
|
|
97
|
+
anyChanged = r3.changed || anyChanged;
|
|
98
|
+
}
|
|
99
|
+
if (!current.includes('String(dataPlacement).split(/[\\s-]/)[0]')) {
|
|
100
|
+
const safeReplaceLine =
|
|
101
|
+
'containerClass = containerClass.replace(/left|right|top|bottom|end|start/g, `' +
|
|
102
|
+
'${(String(dataPlacement).split(/[\\s-]/)[0] || \'bottom\')}`' +
|
|
103
|
+
');';
|
|
104
|
+
const r4 = applyReplacement(
|
|
105
|
+
current,
|
|
106
|
+
/containerClass = containerClass\.replace\(\/left\|right\|top\|bottom\|end\|start\/g, `\$\{dataPlacement\.split\(' '\)\[0\]\}`\);/,
|
|
107
|
+
safeReplaceLine,
|
|
108
|
+
'Patched updateContainerClass: safe placement primary axis'
|
|
109
|
+
);
|
|
110
|
+
current = r4.code;
|
|
111
|
+
anyChanged = r4.changed || anyChanged;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return { code: current, wasPatched: anyChanged };
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
componentLoader: {
|
|
119
|
+
matcher: (id) => matchesModule(id, 'component-loader'),
|
|
120
|
+
apply: (code) => {
|
|
121
|
+
let current = code;
|
|
122
|
+
let anyChanged = false;
|
|
123
|
+
|
|
124
|
+
const patches = [
|
|
125
|
+
{
|
|
126
|
+
condition: !current.includes('this._onShownSubscription = this.onShown.subscribe'),
|
|
127
|
+
pattern: /this\.onShown\.subscribe\(\(\)\s*=>\s*\{/g,
|
|
128
|
+
replacement: 'this._onShownSubscription = this.onShown.subscribe(() => {',
|
|
129
|
+
msg: 'Patched ComponentLoader: Subscription tracking'
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
condition: !/hide\([^)]*\)\s*\{[\s\S]*?_unsubscribePositioning\(\)[\s\S]*?_posService\.deletePositionElement/.test(current),
|
|
133
|
+
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)/,
|
|
134
|
+
replacement: '$1this._unsubscribePositioning();\n $2',
|
|
135
|
+
msg: 'Patched ComponentLoader: Hide cleanup'
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
condition: !current.includes('if (this._onShownSubscription)'),
|
|
139
|
+
pattern: /(_unsubscribePositioning\(\)\s*\{\s*\n\s*)(if\s*\(\s*!this\._zoneSubscription\s*\))/,
|
|
140
|
+
replacement: `$1if (this._onShownSubscription) {\n this._onShownSubscription.unsubscribe();\n this._onShownSubscription = void 0;\n }\n $2`,
|
|
141
|
+
msg: 'Patched ComponentLoader: Unsubscribe fix'
|
|
142
|
+
}
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
for (const { condition, pattern, replacement, msg } of patches) {
|
|
146
|
+
if (condition) {
|
|
147
|
+
const result = applyReplacement(current, pattern, replacement, msg);
|
|
148
|
+
current = result.code;
|
|
149
|
+
anyChanged = result.changed || anyChanged;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return { code: current, wasPatched: anyChanged };
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
dropdown: {
|
|
158
|
+
matcher: (id) => matchesModule(id, 'dropdown'),
|
|
159
|
+
apply: (code) => {
|
|
160
|
+
// ngx-bootstrap 20 + Bootstrap 5: host `.show` toggles dropdown visibility. Removing it breaks
|
|
161
|
+
// datetime timepicker (dropdown menu) and similar `[dropdown]` hosts — restore if stripped.
|
|
162
|
+
if (
|
|
163
|
+
code.includes(
|
|
164
|
+
'properties: { "class.dropup": "dropup", "class.open": "isOpen", "class.show": "isOpen" }'
|
|
165
|
+
)
|
|
166
|
+
) {
|
|
167
|
+
return { code, wasPatched: false };
|
|
168
|
+
}
|
|
169
|
+
const result = applyReplacement(
|
|
170
|
+
code,
|
|
171
|
+
/properties: \{ "class\.dropup": "dropup", "class\.open": "isOpen" \}/,
|
|
172
|
+
'properties: { "class.dropup": "dropup", "class.open": "isOpen", "class.show": "isOpen" }',
|
|
173
|
+
'Patched Dropdown: Restore BS5 show class on directive host'
|
|
174
|
+
);
|
|
175
|
+
return { code: result.code, wasPatched: result.changed };
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
modal: {
|
|
180
|
+
matcher: (id) => matchesModule(id, 'modal'),
|
|
181
|
+
apply: (code) => {
|
|
182
|
+
if (!code.includes("SHOW: 'show'")) {
|
|
183
|
+
return { code, wasPatched: false };
|
|
184
|
+
}
|
|
185
|
+
const result = applyReplacement(
|
|
186
|
+
code,
|
|
187
|
+
/SHOW: 'show'/g,
|
|
188
|
+
"SHOW: 'in'",
|
|
189
|
+
'Patched Modal: SHOW class to in'
|
|
190
|
+
);
|
|
191
|
+
return { code: result.code, wasPatched: result.changed };
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
typeahead: {
|
|
196
|
+
matcher: (id) => matchesModule(id, 'typeahead'),
|
|
197
|
+
apply: (code) => {
|
|
198
|
+
let current = code;
|
|
199
|
+
let anyChanged = false;
|
|
200
|
+
|
|
201
|
+
if (current.includes(':host.dropdown-menu,.dropdown-menu{overflow-y:auto;height:100px}')) {
|
|
202
|
+
const result = applyReplacement(
|
|
203
|
+
current,
|
|
204
|
+
/:host\.dropdown-menu,\.dropdown-menu\{overflow-y:auto;height:100px\}/g,
|
|
205
|
+
'',
|
|
206
|
+
'Patched Typeahead: Remove overflow-y and height styles'
|
|
207
|
+
);
|
|
208
|
+
current = result.code;
|
|
209
|
+
anyChanged = result.changed || anyChanged;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return { code: current, wasPatched: anyChanged };
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// ============================================
|
|
218
|
+
// Rollup Plugin
|
|
219
|
+
// ============================================
|
|
220
|
+
|
|
221
|
+
export function ngxBootstrapPatchPlugin() {
|
|
222
|
+
return {
|
|
223
|
+
name: 'ngx-bootstrap-patch',
|
|
224
|
+
transform(code, id) {
|
|
225
|
+
for (const patch of Object.values(PATCHES)) {
|
|
226
|
+
if (patch.matcher(id)) {
|
|
227
|
+
const result = patch.apply(code);
|
|
228
|
+
if (result.wasPatched || result.code !== code) {
|
|
229
|
+
return { code: result.code, map: null };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Files to patch in node_modules/ngx-bootstrap (fesm2022 only for Angular 17+)
|
|
239
|
+
*/
|
|
240
|
+
const FILES_TO_PATCH = [
|
|
241
|
+
{ path: 'positioning/fesm2022/ngx-bootstrap-positioning.mjs', patchKey: 'positioning' },
|
|
242
|
+
{ path: 'component-loader/fesm2022/ngx-bootstrap-component-loader.mjs', patchKey: 'componentLoader' },
|
|
243
|
+
{ path: 'dropdown/fesm2022/ngx-bootstrap-dropdown.mjs', patchKey: 'dropdown' },
|
|
244
|
+
{ path: 'modal/fesm2022/ngx-bootstrap-modal.mjs', patchKey: 'modal' },
|
|
245
|
+
{ path: 'typeahead/fesm2022/ngx-bootstrap-typeahead.mjs', patchKey: 'typeahead' }
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Patch ngx-bootstrap ESM files directly in node_modules.
|
|
250
|
+
* Call this from build.js before Angular build.
|
|
251
|
+
*/
|
|
252
|
+
export function patchNgxBootstrapFiles(nodeModulesPath = 'node_modules') {
|
|
253
|
+
console.log('\n🔧 Patching ngx-bootstrap ESM files...\n');
|
|
254
|
+
|
|
255
|
+
const ngxPath = path.join(nodeModulesPath, 'ngx-bootstrap');
|
|
256
|
+
let totalPatched = 0;
|
|
257
|
+
|
|
258
|
+
for (const { path: filePath, patchKey } of FILES_TO_PATCH) {
|
|
259
|
+
const fullPath = path.join(ngxPath, filePath);
|
|
260
|
+
|
|
261
|
+
if (!fs.existsSync(fullPath)) continue;
|
|
262
|
+
|
|
263
|
+
const code = fs.readFileSync(fullPath, 'utf-8');
|
|
264
|
+
const patch = PATCHES[patchKey];
|
|
265
|
+
|
|
266
|
+
if (patch) {
|
|
267
|
+
const result = patch.apply(code);
|
|
268
|
+
if (result.wasPatched) {
|
|
269
|
+
fs.writeFileSync(fullPath, result.code, 'utf-8');
|
|
270
|
+
totalPatched++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
console.log(
|
|
276
|
+
totalPatched > 0
|
|
277
|
+
? `\n✅ Patched ${totalPatched} ngx-bootstrap file(s)\n`
|
|
278
|
+
: '\n✓ ngx-bootstrap files already patched or no patches needed\n'
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
return totalPatched;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// CLI entry point
|
|
285
|
+
if (process.argv[1]?.includes('ngx-bootstrap-patch')) {
|
|
286
|
+
patchNgxBootstrapFiles();
|
|
287
|
+
}
|