@hitachivantara/app-shell-vite-plugin 0.12.0 → 0.13.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 +0 -15
- package/dist/automatic-utils.d.ts +6 -0
- package/dist/automatic-utils.d.ts.map +1 -0
- package/dist/automatic-utils.js +105 -0
- package/dist/automatic-utils.js.map +1 -0
- package/dist/config-utils.d.ts +34 -0
- package/dist/config-utils.d.ts.map +1 -0
- package/dist/config-utils.js +126 -0
- package/dist/config-utils.js.map +1 -0
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shared-dependencies.d.ts +8 -0
- package/dist/shared-dependencies.d.ts.map +1 -0
- package/dist/shared-dependencies.js +87 -0
- package/dist/shared-dependencies.js.map +1 -0
- package/dist/virtual-entrypoints.d.ts +5 -0
- package/dist/virtual-entrypoints.d.ts.map +1 -0
- package/dist/virtual-entrypoints.js +37 -0
- package/dist/virtual-entrypoints.js.map +1 -0
- package/dist/vite-configuration-processor-plugin.d.ts +14 -0
- package/dist/vite-configuration-processor-plugin.d.ts.map +1 -0
- package/dist/vite-configuration-processor-plugin.js +161 -0
- package/dist/vite-configuration-processor-plugin.js.map +1 -0
- package/dist/vite-generate-base-plugin.d.ts +8 -0
- package/dist/vite-generate-base-plugin.d.ts.map +1 -0
- package/dist/vite-generate-base-plugin.js +32 -0
- package/dist/vite-generate-base-plugin.js.map +1 -0
- package/dist/vite-generate-bash-script-plugin.d.ts +3 -0
- package/dist/vite-generate-bash-script-plugin.d.ts.map +1 -0
- package/dist/vite-generate-bash-script-plugin.js +122 -0
- package/dist/vite-generate-bash-script-plugin.js.map +1 -0
- package/dist/vite-importmap-plugin.d.ts +2 -2
- package/dist/vite-importmap-plugin.d.ts.map +1 -1
- package/dist/vite-importmap-plugin.js +15 -4
- package/dist/vite-importmap-plugin.js.map +1 -1
- package/dist/vite-metadata-plugin.d.ts.map +1 -1
- package/dist/vite-metadata-plugin.js.map +1 -1
- package/dist/vite-plugin.d.ts +36 -13
- package/dist/vite-plugin.d.ts.map +1 -1
- package/dist/vite-plugin.js +49 -525
- package/dist/vite-plugin.js.map +1 -1
- package/dist/vite-watch-config-plugin.d.ts +4 -0
- package/dist/vite-watch-config-plugin.d.ts.map +1 -0
- package/dist/vite-watch-config-plugin.js +41 -0
- package/dist/vite-watch-config-plugin.js.map +1 -0
- package/package.json +3 -3
package/dist/vite-plugin.js
CHANGED
|
@@ -1,449 +1,53 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { register, createEsmHooks } from "ts-node";
|
|
4
3
|
import virtual from "@rollup/plugin-virtual";
|
|
5
4
|
import { viteStaticCopy } from "vite-plugin-static-copy";
|
|
6
5
|
import generateImportmap from "./vite-importmap-plugin.js";
|
|
6
|
+
import processConfiguration from "./vite-configuration-processor-plugin.js";
|
|
7
|
+
import generateBaseTag from "./vite-generate-base-plugin.js";
|
|
7
8
|
import injectMetadata from "./vite-metadata-plugin.js";
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Return the main app (identified by @self)
|
|
17
|
-
* @param appShellConfig The App shell configuration
|
|
18
|
-
*/
|
|
19
|
-
const getMainApp = (appShellConfig) => {
|
|
20
|
-
return appShellConfig.apps?.filter(app => app.id === "@self")[0];
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Return the public path to be use by vite to launch the application.
|
|
24
|
-
* Value is obtained by returning the baseUrl value of the main app {@link #getMainApp}
|
|
25
|
-
* @param appShellConfig The App shell configuration
|
|
26
|
-
*/
|
|
27
|
-
const getPublicPath = (appShellConfig) => {
|
|
28
|
-
const mainApp = getMainApp(appShellConfig);
|
|
29
|
-
if (!mainApp) {
|
|
30
|
-
return "/";
|
|
31
|
-
}
|
|
32
|
-
const url = mainApp.baseUrl;
|
|
33
|
-
try {
|
|
34
|
-
return new URL(url).pathname;
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return url;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
9
|
+
import serveAppShellConfig from "./vite-watch-config-plugin.js";
|
|
10
|
+
import generateBashScript from "./vite-generate-bash-script-plugin.js";
|
|
11
|
+
import { findAppShellConfigFile, loadConfigFile } from "./config-utils.js";
|
|
12
|
+
import { resolveModule, getModulePath } from "./nodeModule.js";
|
|
13
|
+
import { applyAutomaticMenu, applyAutomaticViewsAndRoutes } from "./automatic-utils.js";
|
|
14
|
+
import getVirtualEntrypoints from "./virtual-entrypoints.js";
|
|
15
|
+
import SHARED_DEPENDENCIES from "./shared-dependencies.js";
|
|
40
16
|
var ViteBuildMode;
|
|
41
17
|
(function (ViteBuildMode) {
|
|
42
18
|
ViteBuildMode["PRODUCTION"] = "production";
|
|
43
19
|
ViteBuildMode["DEVELOPMENT"] = "development";
|
|
44
20
|
})(ViteBuildMode || (ViteBuildMode = {}));
|
|
45
|
-
var ViteCommand;
|
|
46
|
-
(function (ViteCommand) {
|
|
47
|
-
ViteCommand["BUILD"] = "build";
|
|
48
|
-
ViteCommand["SERVE"] = "serve";
|
|
49
|
-
})(ViteCommand || (ViteCommand = {}));
|
|
50
|
-
/**
|
|
51
|
-
* Returns the modules to be created by the build of the app.
|
|
52
|
-
* The list of modules is defined by the app-shell-config.json file routes ( limited to the @self app)
|
|
53
|
-
* The bundles will be created following the original directories structure ( having the src folder path removed)
|
|
54
|
-
*
|
|
55
|
-
* @param root Project root directory.
|
|
56
|
-
* @param appShellConfig The App Shell configuration.
|
|
57
|
-
* @param selfAppName The name of the application bundle being built.
|
|
58
|
-
*/
|
|
59
|
-
function getAppModules(root, appShellConfig, selfAppName) {
|
|
60
|
-
const appModules = {};
|
|
61
|
-
const selfApp = getMainApp(appShellConfig);
|
|
62
|
-
if (selfApp != null) {
|
|
63
|
-
const selfViews = selfApp.views?.map(view => {
|
|
64
|
-
const bundleName = view.bundle.replace(/^src\//, "");
|
|
65
|
-
return {
|
|
66
|
-
...view,
|
|
67
|
-
bundleName
|
|
68
|
-
};
|
|
69
|
-
}) ?? [];
|
|
70
|
-
selfViews.forEach(view => {
|
|
71
|
-
appModules[view.bundleName] = path.resolve(root, view.bundle);
|
|
72
|
-
});
|
|
73
|
-
const selfModules = selfApp.modules?.map(module => {
|
|
74
|
-
const bundleName = module.bundle.replace(/^src\//, "");
|
|
75
|
-
return {
|
|
76
|
-
...module,
|
|
77
|
-
bundleName
|
|
78
|
-
};
|
|
79
|
-
}) ?? [];
|
|
80
|
-
selfModules.forEach(module => {
|
|
81
|
-
appModules[module.bundleName] = path.resolve(root, module.bundle);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
const implicitThemeModules = appShellConfig?.theming?.themes?.map(theme => {
|
|
85
|
-
if (theme.startsWith("/src/") ||
|
|
86
|
-
theme.startsWith("@self/") ||
|
|
87
|
-
theme.startsWith(selfAppName)) {
|
|
88
|
-
const bundle = theme
|
|
89
|
-
.replace(/^@self\//, "")
|
|
90
|
-
.replace(new RegExp(`^${selfAppName}/`), "");
|
|
91
|
-
const bundleName = bundle.replace(/^(\/?)src\//, "");
|
|
92
|
-
return {
|
|
93
|
-
bundle,
|
|
94
|
-
bundleName
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
}) ?? [];
|
|
99
|
-
implicitThemeModules.forEach(module => {
|
|
100
|
-
if (module != null && appModules[module.bundleName] == null) {
|
|
101
|
-
appModules[module.bundleName] = path.resolve(root, module.bundle);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
console.info("Modules exported by the application bundle:", appModules);
|
|
105
|
-
return appModules;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Process configuration, executing several tasks:
|
|
109
|
-
* - Create rollup configuration to support module creation
|
|
110
|
-
* - Generates final transformed configuration json
|
|
111
|
-
* - "base" value is always "./" for build, and main app baseUrl for preview or dev
|
|
112
|
-
* - Injects the APP_BASE_PATH env prop, to be used by the apps (if required)
|
|
113
|
-
* @param root Project root directory.
|
|
114
|
-
* @param appShellConfig The original App Shell configuration json.
|
|
115
|
-
* @param selfAppName The name of the application bundle being built.
|
|
116
|
-
* @param buildEntryPoint If true, the index.html entry point will be added to the bundle.
|
|
117
|
-
*/
|
|
118
|
-
function processConfiguration(root, appShellConfig, selfAppName, buildEntryPoint) {
|
|
119
|
-
const selfApp = getMainApp(appShellConfig);
|
|
120
|
-
return {
|
|
121
|
-
name: "vite-plugin-appShell-configuration-processor",
|
|
122
|
-
config(config, { command }) {
|
|
123
|
-
const projectRoot = root ?? config.root;
|
|
124
|
-
const publicPath = getPublicPath(appShellConfig);
|
|
125
|
-
return {
|
|
126
|
-
build: {
|
|
127
|
-
rollupOptions: {
|
|
128
|
-
preserveEntrySignatures: "strict",
|
|
129
|
-
input: {
|
|
130
|
-
...(buildEntryPoint &&
|
|
131
|
-
fs.existsSync(path.resolve(projectRoot, "index.html"))
|
|
132
|
-
? { main: path.resolve(projectRoot, "index.html") }
|
|
133
|
-
: {}),
|
|
134
|
-
...getAppModules(projectRoot, appShellConfig, selfAppName)
|
|
135
|
-
},
|
|
136
|
-
output: {
|
|
137
|
-
entryFileNames: "[name].js"
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
// if serve (preview/dev) it uses the baseUrl. Otherwise(build), use ./
|
|
142
|
-
base: command === ViteCommand.SERVE ? publicPath : "./",
|
|
143
|
-
define: {
|
|
144
|
-
...config.define,
|
|
145
|
-
APP_BASE_PATH: JSON.stringify(publicPath)
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
},
|
|
149
|
-
/**
|
|
150
|
-
* Rollup hook with the info for bundle generation
|
|
151
|
-
* It will be used to create a new configuration with:
|
|
152
|
-
* - bundles replace with the final location (e.g. -> "bundle": "src/pages/Main" transformed to "bundle": "pages/Main.js",
|
|
153
|
-
* @param options build options
|
|
154
|
-
* @param bundle bundles information
|
|
155
|
-
*/
|
|
156
|
-
async generateBundle(options, bundle) {
|
|
157
|
-
// obtain the directory (dist) where the new config file will be placed
|
|
158
|
-
let targetDir;
|
|
159
|
-
if (options.dir) {
|
|
160
|
-
targetDir = options.dir;
|
|
161
|
-
}
|
|
162
|
-
else if (options.file) {
|
|
163
|
-
targetDir = path.dirname(options.file);
|
|
164
|
-
}
|
|
165
|
-
if (!targetDir) {
|
|
166
|
-
throw new Error("Please set outputPath, so we can know where to place the json file");
|
|
167
|
-
}
|
|
168
|
-
// create the targetDir if it does not exist
|
|
169
|
-
if (!fs.existsSync(targetDir)) {
|
|
170
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Creating a map with each chunk and the final name. Only the bundles with type=chunck are important
|
|
174
|
-
* Filename do not include the src path at the value
|
|
175
|
-
*/
|
|
176
|
-
const chunks = {};
|
|
177
|
-
Object.keys(bundle).forEach(key => {
|
|
178
|
-
const chunk = bundle[key];
|
|
179
|
-
if (chunk.type === "chunk") {
|
|
180
|
-
const outputChunk = chunk;
|
|
181
|
-
if (outputChunk.isEntry) {
|
|
182
|
-
const { fileName } = outputChunk;
|
|
183
|
-
const { name } = outputChunk;
|
|
184
|
-
chunks[name] = fileName;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
if (selfApp) {
|
|
189
|
-
selfApp.views = selfApp.views?.map(view => {
|
|
190
|
-
const bundleName = view.bundle
|
|
191
|
-
.replace(/^src\//, "")
|
|
192
|
-
.replaceAll(/\$/g, "_");
|
|
193
|
-
return {
|
|
194
|
-
...view,
|
|
195
|
-
bundle: chunks[bundleName]
|
|
196
|
-
};
|
|
197
|
-
});
|
|
198
|
-
selfApp.modules = selfApp.modules?.map(module => {
|
|
199
|
-
const bundleName = module.bundle.replace(/^src\//, "");
|
|
200
|
-
return {
|
|
201
|
-
...module,
|
|
202
|
-
bundle: chunks[bundleName]
|
|
203
|
-
};
|
|
204
|
-
});
|
|
205
|
-
// replace references to @self with the name of this application bundle
|
|
206
|
-
selfApp.id = selfAppName;
|
|
207
|
-
// also replace implicit references to selfApp in other parts of the configuration
|
|
208
|
-
const { theming } = appShellConfig;
|
|
209
|
-
if (theming != null) {
|
|
210
|
-
theming.themes = theming.themes?.map(theme => {
|
|
211
|
-
if (theme.startsWith("@self/") ||
|
|
212
|
-
theme.startsWith(selfAppName) ||
|
|
213
|
-
theme.startsWith("/src/")) {
|
|
214
|
-
const bundleName = theme
|
|
215
|
-
.replace(/^@self\//, "")
|
|
216
|
-
.replace(new RegExp(`^${selfAppName}/`), "")
|
|
217
|
-
.replace(/^(\/?)src\//, "");
|
|
218
|
-
return `${selfAppName}/${chunks[bundleName]}`;
|
|
219
|
-
}
|
|
220
|
-
return theme;
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const finalAppShellConfig = buildEntryPoint
|
|
225
|
-
? { ...appShellConfig }
|
|
226
|
-
: {
|
|
227
|
-
name: appShellConfig.name,
|
|
228
|
-
apps: selfApp != null ? [selfApp] : undefined
|
|
229
|
-
};
|
|
230
|
-
fs.writeFileSync(path.resolve(targetDir, "app-shell.config.json"), JSON.stringify(finalAppShellConfig));
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Add the <BASE> tag at index.html file. Tag value is obtained by the main app ({@link #getMainApp}) baseUrl ({@link #getPublicPath})‘
|
|
236
|
-
* @param appShellConfig The app shell configuration.
|
|
237
|
-
*/
|
|
238
|
-
const generateBaseTag = (appShellConfig) => {
|
|
239
|
-
const publicPath = getPublicPath(appShellConfig);
|
|
240
|
-
return {
|
|
241
|
-
name: "vite-plugin-generate-base",
|
|
242
|
-
enforce: "pre",
|
|
243
|
-
transformIndexHtml: {
|
|
244
|
-
enforce: "post",
|
|
245
|
-
transform: (html) => ({
|
|
246
|
-
html,
|
|
247
|
-
tags: [
|
|
248
|
-
{
|
|
249
|
-
tag: "base",
|
|
250
|
-
attrs: { href: publicPath },
|
|
251
|
-
injectTo: "head-prepend"
|
|
252
|
-
}
|
|
253
|
-
]
|
|
254
|
-
})
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
};
|
|
258
|
-
function serveAppShellConfig(appShellConfig, root, appShellConfigFile, automaticViewsFolder) {
|
|
259
|
-
return {
|
|
260
|
-
name: "vite-plugin-watch-app-shell-config",
|
|
261
|
-
configureServer(server) {
|
|
262
|
-
const restartServer = (file) => {
|
|
263
|
-
if (appShellConfigFile != null && file.endsWith(appShellConfigFile)) {
|
|
264
|
-
console.info("App Shell configuration file changed. Reloading...");
|
|
265
|
-
delete require.cache[require.resolve(path.resolve(root, appShellConfigFile))];
|
|
266
|
-
server
|
|
267
|
-
.restart()
|
|
268
|
-
.catch(e => console.error(`Restart failed with: ${e}`));
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
const restartServer2 = (file) => {
|
|
272
|
-
if (automaticViewsFolder != null && file.match(/\/index\.[tj]sx?$/)) {
|
|
273
|
-
console.info("Automatic views folder changed. Reloading...");
|
|
274
|
-
server
|
|
275
|
-
.restart()
|
|
276
|
-
.catch(e => console.error(`Restart failed with: ${e}`));
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
if (appShellConfigFile != null) {
|
|
280
|
-
server.watcher.add(path.resolve(root, appShellConfigFile));
|
|
281
|
-
server.watcher.on("change", restartServer);
|
|
282
|
-
}
|
|
283
|
-
if (automaticViewsFolder != null) {
|
|
284
|
-
server.watcher.add(path.resolve(root, automaticViewsFolder));
|
|
285
|
-
server.watcher.on("unlink", restartServer2);
|
|
286
|
-
server.watcher.on("add", restartServer2);
|
|
287
|
-
}
|
|
288
|
-
const publicPath = getPublicPath(appShellConfig);
|
|
289
|
-
server.middlewares.use(`${publicPath}app-shell.config.json`, async (req, res) => {
|
|
290
|
-
res.end(JSON.stringify(appShellConfig));
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
21
|
export var ApplicationBundleType;
|
|
296
22
|
(function (ApplicationBundleType) {
|
|
297
23
|
ApplicationBundleType["APP"] = "app";
|
|
298
24
|
ApplicationBundleType["BUNDLE"] = "bundle";
|
|
299
25
|
})(ApplicationBundleType || (ApplicationBundleType = {}));
|
|
300
|
-
const DEFAULT_CONFIG_FILES = [
|
|
301
|
-
"app-shell.config.ts",
|
|
302
|
-
"app-shell.config.js",
|
|
303
|
-
"app-shell.config.json"
|
|
304
|
-
];
|
|
305
|
-
function findIndexFiles(dir) {
|
|
306
|
-
const files = [];
|
|
307
|
-
fs.readdirSync(dir).forEach(file => {
|
|
308
|
-
const filePath = path.join(dir, file);
|
|
309
|
-
const stat = fs.statSync(filePath);
|
|
310
|
-
if (stat.isDirectory()) {
|
|
311
|
-
files.push(...findIndexFiles(filePath));
|
|
312
|
-
}
|
|
313
|
-
else if (file.match(/^index\.[tj]sx?$/)) {
|
|
314
|
-
files.push(filePath);
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
return files;
|
|
318
|
-
}
|
|
319
|
-
function mapIndexFilesToRoutes(files, folder) {
|
|
320
|
-
const routes = [];
|
|
321
|
-
files.forEach(filePath => {
|
|
322
|
-
const bundle = filePath.substring(filePath.lastIndexOf(`/${folder.replace(/^\/|\/$/g, "")}/`) + 1, filePath.lastIndexOf("/"));
|
|
323
|
-
const route = bundle
|
|
324
|
-
.replace(new RegExp(`^${folder}`), "")
|
|
325
|
-
.replace(/index\.[t|j]sx?$/, "")
|
|
326
|
-
.replaceAll(/\$/g, ":")
|
|
327
|
-
.toLowerCase();
|
|
328
|
-
routes.push({ bundle, route });
|
|
329
|
-
});
|
|
330
|
-
return routes;
|
|
331
|
-
}
|
|
332
26
|
/**
|
|
333
27
|
* Vite plugin to support App Shell apps setup
|
|
334
28
|
* @param opts Plugin options
|
|
335
29
|
*/
|
|
336
30
|
export function appShellVitePlugin(opts = {}, env = {}) {
|
|
337
|
-
const { root = process.cwd(), mode = ViteBuildMode.PRODUCTION, externalImportMap = false, type = ApplicationBundleType.APP, viewsFolder = "src/pages", autoViewsAndRoutes = false, autoDevMenu = false } = opts;
|
|
338
|
-
const buildEntryPoint = type !== ApplicationBundleType.BUNDLE;
|
|
31
|
+
const { root = process.cwd(), mode = ViteBuildMode.PRODUCTION, externalImportMap = false, type = ApplicationBundleType.APP, viewsFolder = "src/pages", autoViewsAndRoutes = false, autoDevMenu = false, inlineConfig = opts.generateEmptyShell ?? false, generateEmptyShell = false } = opts;
|
|
339
32
|
console.info(`Vite running in mode: ${mode}`);
|
|
340
33
|
const devMode = mode === ViteBuildMode.DEVELOPMENT;
|
|
34
|
+
const buildEntryPoint = type !== ApplicationBundleType.BUNDLE;
|
|
341
35
|
const packageJsonRaw = fs.readFileSync(path.resolve(root, "package.json"), "utf-8");
|
|
342
36
|
const packageJson = JSON.parse(packageJsonRaw);
|
|
343
|
-
const appShellConfigFile =
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
appShellConfigRaw = appShellConfigRaw.replaceAll(`@@${item.token}@@`, item.value);
|
|
351
|
-
});
|
|
352
|
-
appShellConfiguration = JSON.parse(appShellConfigRaw);
|
|
353
|
-
}
|
|
354
|
-
else {
|
|
355
|
-
// using require instead of import to avoid using --experimental-loader ts-node/esm
|
|
356
|
-
// eslint-disable-next-line import/no-dynamic-require
|
|
357
|
-
const loadedAppShellConfig = require(path.resolve(root, appShellConfigFile)).default;
|
|
358
|
-
if (typeof loadedAppShellConfig === "function") {
|
|
359
|
-
appShellConfiguration = loadedAppShellConfig(opts, env);
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
appShellConfiguration = loadedAppShellConfig;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
// an empty configuration is actually valid
|
|
368
|
-
// and with the automatic views option, it can even make sense
|
|
369
|
-
appShellConfiguration = {};
|
|
370
|
-
}
|
|
371
|
-
let selfApp = getMainApp(appShellConfiguration);
|
|
372
|
-
if (autoViewsAndRoutes != null) {
|
|
373
|
-
const folder = path.resolve(root, viewsFolder);
|
|
374
|
-
if (fs.existsSync(folder)) {
|
|
375
|
-
const views = mapIndexFilesToRoutes(findIndexFiles(folder), viewsFolder);
|
|
376
|
-
if (views.length > 0) {
|
|
377
|
-
if (selfApp == null) {
|
|
378
|
-
selfApp = {
|
|
379
|
-
id: "@self",
|
|
380
|
-
baseUrl: "/"
|
|
381
|
-
};
|
|
382
|
-
if (appShellConfiguration.apps == null) {
|
|
383
|
-
appShellConfiguration.apps = [];
|
|
384
|
-
}
|
|
385
|
-
appShellConfiguration.apps.push(selfApp);
|
|
386
|
-
}
|
|
387
|
-
if (selfApp.views != null && selfApp.views.length > 0) {
|
|
388
|
-
const nowOverlappingViews = views.filter(view => {
|
|
389
|
-
const exists = selfApp.views.some(existingView => existingView.bundle === view.bundle ||
|
|
390
|
-
existingView.route === view.route);
|
|
391
|
-
return !exists;
|
|
392
|
-
});
|
|
393
|
-
selfApp.views.push(...nowOverlappingViews);
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
selfApp.views = views;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
37
|
+
const appShellConfigFile = !generateEmptyShell
|
|
38
|
+
? findAppShellConfigFile(root)
|
|
39
|
+
: undefined;
|
|
40
|
+
const appShellConfiguration = loadConfigFile(appShellConfigFile, opts, env);
|
|
41
|
+
if (!generateEmptyShell) {
|
|
42
|
+
if (autoViewsAndRoutes) {
|
|
43
|
+
applyAutomaticViewsAndRoutes(appShellConfiguration, root, viewsFolder);
|
|
399
44
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (appShellConfiguration.menu == null ||
|
|
403
|
-
appShellConfiguration.menu.length === 0) {
|
|
404
|
-
if (selfApp?.views != null && selfApp.views.length > 0) {
|
|
405
|
-
const menu = [];
|
|
406
|
-
for (let i = 0; i !== selfApp.views.length; i += 1) {
|
|
407
|
-
const view = selfApp.views[i];
|
|
408
|
-
// skip dynamic routes (e.g. /list/:id))
|
|
409
|
-
if (view.route.indexOf(":") === -1) {
|
|
410
|
-
let currentMenu = menu;
|
|
411
|
-
const bundleParts = view.bundle.split("/");
|
|
412
|
-
const numberOfParts = view.route
|
|
413
|
-
.split("/")
|
|
414
|
-
.filter(part => part !== "").length;
|
|
415
|
-
const srcFolderParts = bundleParts.length - numberOfParts;
|
|
416
|
-
if (bundleParts.length > srcFolderParts) {
|
|
417
|
-
for (let j = srcFolderParts; j !== bundleParts.length - 1; j += 1) {
|
|
418
|
-
const part = bundleParts[j];
|
|
419
|
-
let submenu = currentMenu.find(item => item.label === part);
|
|
420
|
-
if (submenu == null) {
|
|
421
|
-
submenu = {
|
|
422
|
-
label: part,
|
|
423
|
-
submenus: []
|
|
424
|
-
};
|
|
425
|
-
currentMenu.push(submenu);
|
|
426
|
-
}
|
|
427
|
-
currentMenu = submenu.submenus;
|
|
428
|
-
}
|
|
429
|
-
const label = bundleParts[bundleParts.length - 1];
|
|
430
|
-
let menuitem = currentMenu.find(item => item.label === label);
|
|
431
|
-
if (menuitem == null) {
|
|
432
|
-
menuitem = {
|
|
433
|
-
label
|
|
434
|
-
};
|
|
435
|
-
currentMenu.push(menuitem);
|
|
436
|
-
}
|
|
437
|
-
menuitem.target = view.route;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
appShellConfiguration.menu = menu;
|
|
442
|
-
}
|
|
45
|
+
if (devMode && autoDevMenu) {
|
|
46
|
+
applyAutomaticMenu(appShellConfiguration);
|
|
443
47
|
}
|
|
444
48
|
}
|
|
445
49
|
return [
|
|
446
|
-
//
|
|
50
|
+
// copy the shared dependencies js bundles to the "bundles" folder
|
|
447
51
|
(buildEntryPoint || devMode) &&
|
|
448
52
|
viteStaticCopy({
|
|
449
53
|
targets: [
|
|
@@ -454,110 +58,30 @@ export function appShellVitePlugin(opts = {}, env = {}) {
|
|
|
454
58
|
...(!devMode && buildEntryPoint
|
|
455
59
|
? [
|
|
456
60
|
{
|
|
457
|
-
src: [
|
|
458
|
-
resolveModule(
|
|
459
|
-
resolveModule(
|
|
460
|
-
|
|
461
|
-
resolveModule("./esm-externals/react-dom.production.min.js.map"),
|
|
462
|
-
resolveModule("./esm-externals/react-router-dom.production.min.js"),
|
|
463
|
-
resolveModule("./esm-externals/react-router-dom.production.min.js.map"),
|
|
464
|
-
resolveModule("./esm-externals/emotion-react.production.min.js"),
|
|
465
|
-
resolveModule("./esm-externals/emotion-react.production.min.js.map"),
|
|
466
|
-
resolveModule("./esm-externals/emotion-cache.production.min.js"),
|
|
467
|
-
resolveModule("./esm-externals/emotion-cache.production.min.js.map"),
|
|
468
|
-
resolveModule("@hitachivantara/app-shell-shared/bundles/app-shell-shared.esm.js"),
|
|
469
|
-
resolveModule("@hitachivantara/app-shell-shared/bundles/app-shell-shared.esm.js.map"),
|
|
470
|
-
resolveModule("@hitachivantara/uikit-react-shared/bundles/uikit-react-shared.esm.js"),
|
|
471
|
-
resolveModule("@hitachivantara/uikit-react-shared/bundles/uikit-react-shared.esm.js.map")
|
|
472
|
-
],
|
|
61
|
+
src: SHARED_DEPENDENCIES.flatMap(dep => [
|
|
62
|
+
resolveModule(dep.bundleSrc),
|
|
63
|
+
resolveModule(`${dep.bundleSrc}.map`)
|
|
64
|
+
]),
|
|
473
65
|
dest: "bundles"
|
|
474
66
|
}
|
|
475
67
|
]
|
|
476
68
|
: [])
|
|
477
69
|
]
|
|
478
70
|
}),
|
|
479
|
-
// create virtual endpoints
|
|
71
|
+
// create virtual endpoints for shell code and for shared dependencies
|
|
480
72
|
virtual({
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
root.render(React.createElement(
|
|
488
|
-
Suspense,
|
|
489
|
-
{ fallback: true },
|
|
490
|
-
React.createElement(App, null)
|
|
491
|
-
));`,
|
|
492
|
-
"virtual:App.tsx": `import React from "react";
|
|
493
|
-
import { HvAppShell } from "@hitachivantara/app-shell";
|
|
494
|
-
|
|
495
|
-
const App = () => {
|
|
496
|
-
return React.createElement(HvAppShell, {
|
|
497
|
-
configUrl: window.location.origin + APP_BASE_PATH + "app-shell.config.json"
|
|
498
|
-
});
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
export default App;`,
|
|
502
|
-
"/bundles/react.production.min.js": `import * as React from "react";
|
|
503
|
-
export default React;
|
|
504
|
-
|
|
505
|
-
export {
|
|
506
|
-
Fragment,
|
|
507
|
-
StrictMode,
|
|
508
|
-
Profiler,
|
|
509
|
-
Suspense,
|
|
510
|
-
Children,
|
|
511
|
-
Component,
|
|
512
|
-
PureComponent,
|
|
513
|
-
cloneElement,
|
|
514
|
-
createContext,
|
|
515
|
-
createElement,
|
|
516
|
-
createFactory,
|
|
517
|
-
createRef,
|
|
518
|
-
forwardRef,
|
|
519
|
-
isValidElement,
|
|
520
|
-
lazy,
|
|
521
|
-
memo,
|
|
522
|
-
useCallback,
|
|
523
|
-
useContext,
|
|
524
|
-
useDebugValue,
|
|
525
|
-
useEffect,
|
|
526
|
-
useImperativeHandle,
|
|
527
|
-
useLayoutEffect,
|
|
528
|
-
useMemo,
|
|
529
|
-
useReducer,
|
|
530
|
-
useRef,
|
|
531
|
-
useState,
|
|
532
|
-
version,
|
|
533
|
-
} from "react";`,
|
|
534
|
-
"/bundles/react-dom.production.min.js": `export {
|
|
535
|
-
default,
|
|
536
|
-
flushSync,
|
|
537
|
-
createPortal,
|
|
538
|
-
findDOMNode,
|
|
539
|
-
hydrate,
|
|
540
|
-
render,
|
|
541
|
-
unmountComponentAtNode,
|
|
542
|
-
unstable_batchedUpdates,
|
|
543
|
-
unstable_renderSubtreeIntoContainer,
|
|
544
|
-
version,
|
|
545
|
-
} from "react-dom";`,
|
|
546
|
-
"/bundles/react-router-dom.production.min.js": `export * from "react-router-dom";`,
|
|
547
|
-
"/bundles/emotion-react.production.min.js": `export * from "@emotion/react";`,
|
|
548
|
-
"/bundles/emotion-cache.production.min.js": `import createCache from "@emotion/cache"; export default createCache;`,
|
|
549
|
-
"/bundles/app-shell-shared.esm.js": `export * from "@hitachivantara/app-shell-shared";`,
|
|
550
|
-
"/bundles/uikit-react-shared.esm.js": `export * from "@hitachivantara/uikit-react-shared";`
|
|
73
|
+
...getVirtualEntrypoints(inlineConfig),
|
|
74
|
+
...SHARED_DEPENDENCIES.reduce((acc, dep) => {
|
|
75
|
+
acc[`/bundles/${dep.bundle}`] = dep.virtualSrc;
|
|
76
|
+
return acc;
|
|
77
|
+
}, {})
|
|
551
78
|
}),
|
|
552
|
-
//
|
|
79
|
+
// generate the importmap for shared dependencies and for apps referenced in the config file
|
|
553
80
|
generateImportmap({
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
"@emotion/react": "./bundles/emotion-react.production.min.js",
|
|
559
|
-
"@emotion/cache": "./bundles/emotion-cache.production.min.js",
|
|
560
|
-
"@hitachivantara/uikit-react-shared": "./bundles/uikit-react-shared.esm.js",
|
|
81
|
+
...SHARED_DEPENDENCIES.reduce((acc, dep) => {
|
|
82
|
+
acc[dep.moduleId] = `./bundles/${dep.bundle}`;
|
|
83
|
+
return acc;
|
|
84
|
+
}, {}),
|
|
561
85
|
...appShellConfiguration?.apps?.reduce((acc, app) => {
|
|
562
86
|
if (app.id === "@self") {
|
|
563
87
|
acc[`${packageJson.name}/`] = app.baseUrl;
|
|
@@ -571,21 +95,21 @@ export function appShellVitePlugin(opts = {}, env = {}) {
|
|
|
571
95
|
return acc;
|
|
572
96
|
}, {})
|
|
573
97
|
}, [
|
|
574
|
-
|
|
575
|
-
"react-dom",
|
|
576
|
-
"react-router-dom",
|
|
577
|
-
"@hitachivantara/app-shell-shared",
|
|
578
|
-
"@hitachivantara/uikit-react-shared",
|
|
579
|
-
"@emotion/react",
|
|
580
|
-
"@emotion/cache",
|
|
98
|
+
...SHARED_DEPENDENCIES.map(dep => dep.moduleId),
|
|
581
99
|
"@self",
|
|
582
100
|
packageJson.name
|
|
583
|
-
], externalImportMap && buildEntryPoint),
|
|
584
|
-
|
|
585
|
-
buildEntryPoint &&
|
|
586
|
-
//
|
|
587
|
-
|
|
588
|
-
|
|
101
|
+
], externalImportMap && buildEntryPoint, generateEmptyShell),
|
|
102
|
+
// inject version metadata in the index.html
|
|
103
|
+
buildEntryPoint && injectMetadata(),
|
|
104
|
+
// set the base tag and replace the title in the index.html
|
|
105
|
+
buildEntryPoint &&
|
|
106
|
+
generateBaseTag(appShellConfiguration, generateEmptyShell),
|
|
107
|
+
// configure the build process based on the config file
|
|
108
|
+
processConfiguration(root, appShellConfiguration, packageJson.name, buildEntryPoint, inlineConfig, generateEmptyShell),
|
|
109
|
+
// serve the app shell config file as json and watch for changes
|
|
110
|
+
serveAppShellConfig(appShellConfiguration, root, appShellConfigFile, autoViewsAndRoutes ? viewsFolder : undefined),
|
|
111
|
+
// generate the shell script to replace the placeholders in the index.html
|
|
112
|
+
generateEmptyShell && generateBashScript(externalImportMap, inlineConfig)
|
|
589
113
|
];
|
|
590
114
|
}
|
|
591
115
|
export default appShellVitePlugin;
|