@hitachivantara/app-shell-vite-plugin 2.3.0 → 2.5.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.
Files changed (32) hide show
  1. package/LICENSE +201 -0
  2. package/dist/automatic-utils.js +7 -3
  3. package/dist/esm-externals/react-router-dom.production.min.js +7 -7
  4. package/dist/esm-externals/react-router-dom.production.min.js.map +1 -1
  5. package/dist/locales-utils.d.ts +0 -9
  6. package/dist/locales-utils.js +2 -34
  7. package/dist/nodeModule.d.ts +1 -1
  8. package/dist/shared-dependencies.js +2 -1
  9. package/dist/utils.d.ts +9 -0
  10. package/dist/utils.js +34 -0
  11. package/dist/vite-plugin-configuration-processor.d.ts +30 -0
  12. package/dist/{vite-configuration-processor-plugin.js → vite-plugin-configuration-processor.js} +11 -12
  13. package/dist/{vite-crossorigin-fix-plugin.d.ts → vite-plugin-crossorigin-fix.d.ts} +1 -2
  14. package/dist/{vite-crossorigin-fix-plugin.js → vite-plugin-crossorigin-fix.js} +4 -5
  15. package/dist/vite-plugin-dist-package-json.d.ts +5 -0
  16. package/dist/vite-plugin-dist-package-json.js +271 -0
  17. package/dist/{vite-generate-base-plugin.d.ts → vite-plugin-generate-base.d.ts} +1 -1
  18. package/dist/{vite-generate-bash-script-plugin.js → vite-plugin-generate-bash-script.js} +1 -1
  19. package/dist/{vite-locales-plugin.js → vite-plugin-locales.js} +3 -2
  20. package/dist/{vite-metadata-plugin.d.ts → vite-plugin-metadata.d.ts} +1 -2
  21. package/dist/{vite-metadata-plugin.js → vite-plugin-metadata.js} +5 -8
  22. package/dist/{vite-watch-config-plugin.js → vite-plugin-watch-config.js} +3 -1
  23. package/dist/vite-plugin.d.ts +36 -0
  24. package/dist/vite-plugin.js +25 -13
  25. package/package.json +24 -19
  26. package/dist/vite-configuration-processor-plugin.d.ts +0 -16
  27. /package/dist/{vite-generate-base-plugin.js → vite-plugin-generate-base.js} +0 -0
  28. /package/dist/{vite-generate-bash-script-plugin.d.ts → vite-plugin-generate-bash-script.d.ts} +0 -0
  29. /package/dist/{vite-importmap-plugin.d.ts → vite-plugin-importmap.d.ts} +0 -0
  30. /package/dist/{vite-importmap-plugin.js → vite-plugin-importmap.js} +0 -0
  31. /package/dist/{vite-locales-plugin.d.ts → vite-plugin-locales.d.ts} +0 -0
  32. /package/dist/{vite-watch-config-plugin.d.ts → vite-plugin-watch-config.d.ts} +0 -0
@@ -1,8 +1,4 @@
1
1
  export declare const SUPPORTED_LOCALES_FILE = "supported-locales.json";
2
- /**
3
- * Deep merge two objects. `override` keys take priority over `base`.
4
- */
5
- export declare function deepMerge(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown>;
6
2
  /**
7
3
  * Reads a `supported-locales.json` file and returns its contents as an array
8
4
  * of locale strings. Returns an empty array if the file doesn't exist or
@@ -31,11 +27,6 @@ export declare function discoverLanguageDirs(localesDir: string): string[];
31
27
  * @param appLocalesDir - The app's locales directory (downstream / local).
32
28
  */
33
29
  export declare function computeSupportedLocales(shellLocalesDir: string | undefined, appLocalesDir: string | undefined): string[];
34
- /**
35
- * Parses a JSON file, wrapping parse errors with the file path for
36
- * actionable diagnostics.
37
- */
38
- export declare function readJsonFile(filePath: string): unknown;
39
30
  /**
40
31
  * Recursively merges source directory into destination.
41
32
  * JSON files are deep-merged with destination keys taking priority.
@@ -1,26 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { deepMerge, readJsonFile } from "./utils.js";
3
4
  export const SUPPORTED_LOCALES_FILE = "supported-locales.json";
4
- /**
5
- * Deep merge two objects. `override` keys take priority over `base`.
6
- */
7
- export function deepMerge(base, override) {
8
- const result = { ...base };
9
- for (const [key, value] of Object.entries(override)) {
10
- if (value != null &&
11
- typeof value === "object" &&
12
- !Array.isArray(value) &&
13
- result[key] != null &&
14
- typeof result[key] === "object" &&
15
- !Array.isArray(result[key])) {
16
- result[key] = deepMerge(result[key], value);
17
- }
18
- else {
19
- result[key] = value;
20
- }
21
- }
22
- return result;
23
- }
24
5
  /**
25
6
  * Reads a `supported-locales.json` file and returns its contents as an array
26
7
  * of locale strings. Returns an empty array if the file doesn't exist or
@@ -30,7 +11,7 @@ export function readSupportedLocales(filePath) {
30
11
  if (!fs.existsSync(filePath))
31
12
  return [];
32
13
  try {
33
- const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
14
+ const data = readJsonFile(filePath);
34
15
  if (Array.isArray(data) && data.every((item) => typeof item === "string")) {
35
16
  return data;
36
17
  }
@@ -107,19 +88,6 @@ export function computeSupportedLocales(shellLocalesDir, appLocalesDir) {
107
88
  }
108
89
  return result.toSorted();
109
90
  }
110
- /**
111
- * Parses a JSON file, wrapping parse errors with the file path for
112
- * actionable diagnostics.
113
- */
114
- export function readJsonFile(filePath) {
115
- const raw = fs.readFileSync(filePath, "utf-8");
116
- try {
117
- return JSON.parse(raw);
118
- }
119
- catch (cause) {
120
- throw new Error(`[app-shell-locales] Failed to parse ${filePath}: ${cause instanceof Error ? cause.message : cause}`, { cause });
121
- }
122
- }
123
91
  /**
124
92
  * Recursively merges source directory into destination.
125
93
  * JSON files are deep-merged with destination keys taking priority.
@@ -6,4 +6,4 @@ export declare const require: NodeJS.Require;
6
6
  * @param suffix to be added after the module path
7
7
  * @returns The module path normalized
8
8
  */
9
- export declare function resolveModule(moduleName: string, suffix?: string): string;
9
+ export declare function resolveModule(moduleName: string, suffix?: string): any;
@@ -87,7 +87,8 @@ export default [
87
87
  moduleId: "@hitachivantara/app-shell-services",
88
88
  bundle: "app-shell-services.esm.js",
89
89
  bundleSrc: "@hitachivantara/app-shell-services/bundles/app-shell-services.esm.js",
90
- virtualSrc: `export * from "@hitachivantara/app-shell-services";`,
90
+ virtualSrc: `export { default } from "@hitachivantara/app-shell-services";
91
+ export * from "@hitachivantara/app-shell-services";`,
91
92
  },
92
93
  {
93
94
  moduleId: "@hitachivantara/uikit-react-shared",
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Deep merge two objects. `override` keys take priority over `base`.
3
+ */
4
+ export declare function deepMerge(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown>;
5
+ /**
6
+ * Parses a JSON file, wrapping parse errors with the file path for
7
+ * actionable diagnostics.
8
+ */
9
+ export declare function readJsonFile(filePath: string): any;
package/dist/utils.js ADDED
@@ -0,0 +1,34 @@
1
+ import { readFileSync } from "node:fs";
2
+ /**
3
+ * Deep merge two objects. `override` keys take priority over `base`.
4
+ */
5
+ export function deepMerge(base, override) {
6
+ const result = { ...base };
7
+ for (const [key, value] of Object.entries(override)) {
8
+ if (value != null &&
9
+ typeof value === "object" &&
10
+ !Array.isArray(value) &&
11
+ result[key] != null &&
12
+ typeof result[key] === "object" &&
13
+ !Array.isArray(result[key])) {
14
+ result[key] = deepMerge(result[key], value);
15
+ }
16
+ else {
17
+ result[key] = value;
18
+ }
19
+ }
20
+ return result;
21
+ }
22
+ /**
23
+ * Parses a JSON file, wrapping parse errors with the file path for
24
+ * actionable diagnostics.
25
+ */
26
+ export function readJsonFile(filePath) {
27
+ const raw = readFileSync(filePath, "utf-8");
28
+ try {
29
+ return JSON.parse(raw);
30
+ }
31
+ catch (cause) {
32
+ throw new Error(`Failed to parse ${filePath}: ${cause instanceof Error ? cause.message : cause}`, { cause });
33
+ }
34
+ }
@@ -0,0 +1,30 @@
1
+ import type { PluginOption } from "vite";
2
+ import type { HvAppShellConfig } from "@hitachivantara/app-shell-shared";
3
+ /**
4
+ * Options for the configuration processor plugin.
5
+ */
6
+ export interface ProcessConfigurationOptions {
7
+ /** Project root directory. */
8
+ root: string;
9
+ /** The original App Shell configuration json. */
10
+ appShellConfig: HvAppShellConfig;
11
+ /** The name of the application bundle being built. */
12
+ selfAppName: string;
13
+ /** The set of modules to be created by the rollup. */
14
+ modules: string[];
15
+ /** If true, the index.html entry point will be added to the bundle. */
16
+ buildEntryPoint: boolean;
17
+ /** Flag to control if config is included at index.html. */
18
+ inlineConfig: boolean;
19
+ /** Flag to control if we are creating an empty AppShell instance. */
20
+ generateEmptyShell: boolean;
21
+ /** If true, always writes app-shell.config.json to dist for dual-use packages. */
22
+ experimentalNewPackageLayout: boolean;
23
+ }
24
+ /**
25
+ * Process configuration, executing several tasks:
26
+ * - Create rollup configuration to support module creation
27
+ * - Generates final transformed configuration json
28
+ * - "base" value is always "./" for build, and main app baseUrl for preview or dev
29
+ */
30
+ export default function processConfiguration(options: ProcessConfigurationOptions): PluginOption;
@@ -7,19 +7,13 @@ import sharedDependencies from "./shared-dependencies.js";
7
7
  * - Create rollup configuration to support module creation
8
8
  * - Generates final transformed configuration json
9
9
  * - "base" value is always "./" for build, and main app baseUrl for preview or dev
10
- * @param root Project root directory.
11
- * @param appShellConfig The original App Shell configuration json.
12
- * @param selfAppName The name of the application bundle being built.
13
- * @param buildEntryPoint If true, the index.html entry point will be added to the bundle.
14
- * @param inlineConfig flag to control if config is included at index.html
15
- * @param generateEmptyShell flag to control if we are creating an empty AppShell instance
16
- * @param modules the set of modules to be created by the rollup
17
10
  */
18
- export default function processConfiguration(root, appShellConfig, selfAppName, buildEntryPoint, inlineConfig, generateEmptyShell, modules = []) {
11
+ export default function processConfiguration(options) {
12
+ const { root, appShellConfig, selfAppName, modules, buildEntryPoint, inlineConfig, generateEmptyShell, experimentalNewPackageLayout, } = options;
19
13
  let finalAppShellConfig;
20
14
  let basePath;
21
15
  return {
22
- name: "vite-plugin-appShell-configuration-processor",
16
+ name: "vite-plugin-appShell-config-processor",
23
17
  config(config, { command }) {
24
18
  const projectRoot = root ?? config.root;
25
19
  let appModules = {};
@@ -58,7 +52,7 @@ export default function processConfiguration(root, appShellConfig, selfAppName,
58
52
  * @param options build options
59
53
  */
60
54
  async generateBundle(options) {
61
- if (generateEmptyShell || !buildEntryPoint) {
55
+ if (generateEmptyShell) {
62
56
  return;
63
57
  }
64
58
  // obtain the directory (dist) where the new config file will be placed
@@ -82,11 +76,16 @@ export default function processConfiguration(root, appShellConfig, selfAppName,
82
76
  finalAppShellConfig.baseUrl = basePath;
83
77
  }
84
78
  finalAppShellConfig.apps = undefined;
85
- // Replace all @self references using simple string replacement
79
+ // Replace all $app and @self (deprecated) references using simple string replacement.
86
80
  let configString = JSON.stringify(finalAppShellConfig);
81
+ configString = configString.replaceAll(`"$app/`, `"${selfAppName}/`);
82
+ // TODO(major): remove @self/ support in favour of $app/
87
83
  configString = configString.replaceAll(`"@self/`, `"${selfAppName}/`);
88
84
  finalAppShellConfig = JSON.parse(configString);
89
- if (!inlineConfig) {
85
+ // Write app-shell.config.json to dist when:
86
+ // - inlineConfig is false (standard flow), OR
87
+ // - experimentalNewPackageLayout is true (ensures dual-use: app shell or app bundle)
88
+ if (!inlineConfig || experimentalNewPackageLayout) {
90
89
  fs.writeFileSync(path.resolve(targetDir, "app-shell.config.json"), JSON.stringify(finalAppShellConfig));
91
90
  }
92
91
  },
@@ -5,5 +5,4 @@ export declare const isExternalUrl: (url: string) => boolean;
5
5
  export declare const dataUrlRE: RegExp;
6
6
  export declare const isDataUrl: (url: string) => boolean;
7
7
  export declare function checkCrossOrigin(html: string): any[];
8
- declare const fixCrossOrigin: () => PluginOption;
9
- export default fixCrossOrigin;
8
+ export default function fixCrossOrigin(): PluginOption;
@@ -48,11 +48,11 @@ export function checkCrossOrigin(html) {
48
48
  }
49
49
  return withCredentials;
50
50
  }
51
- const fixCrossOrigin = () => {
51
+ export default function fixCrossOrigin() {
52
52
  const withCredentials = {};
53
53
  return [
54
54
  {
55
- name: "vite-crossorigin-fix-collect-info-plugin",
55
+ name: "vite-plugin-crossorigin-fix-collect-info",
56
56
  transformIndexHtml: {
57
57
  order: "pre",
58
58
  handler(html, info) {
@@ -61,7 +61,7 @@ const fixCrossOrigin = () => {
61
61
  },
62
62
  },
63
63
  {
64
- name: "vite-crossorigin-fix-replace-plugin",
64
+ name: "vite-plugin-crossorigin-fix-replace",
65
65
  transformIndexHtml: {
66
66
  order: "post",
67
67
  handler(html, context) {
@@ -79,5 +79,4 @@ const fixCrossOrigin = () => {
79
79
  },
80
80
  },
81
81
  ];
82
- };
83
- export default fixCrossOrigin;
82
+ }
@@ -0,0 +1,5 @@
1
+ import type { Plugin } from "vite";
2
+ /**
3
+ * Generates a cleaned dist/package.json during Vite builds.
4
+ */
5
+ export default function distPackageJsonPlugin(root?: string, sourceCondition?: string): Plugin;
@@ -0,0 +1,271 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ // ─── Constants ───────────────────────────────────────────────────────────────
4
+ /**
5
+ * Default custom export condition used internally by workspace packages
6
+ * to resolve TypeScript source during development.
7
+ *
8
+ * This condition must never leak into published artifacts because external
9
+ * consumers would not be able to resolve it.
10
+ */
11
+ const DEFAULT_SOURCE_CONDITION = "@pentaho-apps:source";
12
+ /**
13
+ * Runtime-relevant package.json fields copied into dist output.
14
+ *
15
+ * All other fields are intentionally excluded.
16
+ */
17
+ const INCLUDED_FIELDS = [
18
+ "name",
19
+ "version",
20
+ "type",
21
+ "license",
22
+ "description",
23
+ "dependencies",
24
+ "peerDependencies",
25
+ "peerDependenciesMeta",
26
+ "optionalDependencies",
27
+ ];
28
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
29
+ /**
30
+ * Reads and parses a JSON file.
31
+ *
32
+ * Returns `undefined` if the file does not exist or cannot be parsed.
33
+ */
34
+ function readJsonFile(filePath) {
35
+ try {
36
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ /**
43
+ * Extracts the package name from a module specifier.
44
+ *
45
+ * Examples:
46
+ * react-dom/client → react-dom
47
+ * @emotion/react/jsx-dev → @emotion/react
48
+ */
49
+ function toPackageName(specifier) {
50
+ if (specifier.startsWith("@")) {
51
+ const segments = specifier.split("/");
52
+ return segments.length >= 2 ? `${segments[0]}/${segments[1]}` : segments[0];
53
+ }
54
+ return specifier.split("/")[0];
55
+ }
56
+ /**
57
+ * Removes the build output prefix from an export path.
58
+ *
59
+ * Example:
60
+ * ./dist/index.js → ./index.js
61
+ */
62
+ function stripDistPrefix(prefix, value) {
63
+ return value.startsWith(prefix) ? `./${value.slice(prefix.length)}` : value;
64
+ }
65
+ /**
66
+ * Transforms a package export target for dist/package.json.
67
+ *
68
+ * Processing rules:
69
+ *
70
+ * Strings:
71
+ * - Must resolve inside build.outDir
72
+ * - build.outDir prefix is stripped
73
+ *
74
+ * Objects:
75
+ * - Removes dev-only source condition
76
+ * - Recursively transforms nested targets
77
+ * - Removed if empty after transformation
78
+ *
79
+ * Arrays:
80
+ * - Node fallback arrays are eagerly collapsed to the first
81
+ * valid non-null target because import maps do not support
82
+ * Node conditional fallback resolution semantics.
83
+ *
84
+ * null:
85
+ * - Preserved as explicit export exclusion
86
+ *
87
+ * undefined:
88
+ * - Internal sentinel meaning "omit this entry"
89
+ */
90
+ function transformExportTargetForDist(target, distPrefix, sourceCondition) {
91
+ // Explicit export exclusion must be preserved
92
+ if (target === null) {
93
+ return null;
94
+ }
95
+ // Direct export path
96
+ if (typeof target === "string") {
97
+ const stripped = stripDistPrefix(distPrefix, target);
98
+ // Ignore paths outside dist output
99
+ return stripped === target ? undefined : stripped;
100
+ }
101
+ // Fallback array
102
+ if (Array.isArray(target)) {
103
+ for (const entry of target) {
104
+ const resolved = transformExportTargetForDist(entry, distPrefix, sourceCondition);
105
+ if (resolved !== undefined && resolved !== null) {
106
+ return resolved;
107
+ }
108
+ }
109
+ return undefined;
110
+ }
111
+ // Conditional exports object
112
+ const result = {};
113
+ for (const [condition, value] of Object.entries(target)) {
114
+ // Remove workspace-only source condition
115
+ if (condition === sourceCondition) {
116
+ continue;
117
+ }
118
+ const transformed = transformExportTargetForDist(value, distPrefix, sourceCondition);
119
+ // Omitted targets disappear entirely
120
+ if (transformed === undefined) {
121
+ continue;
122
+ }
123
+ result[condition] = transformed;
124
+ }
125
+ return Object.keys(result).length === 0 ? undefined : result;
126
+ }
127
+ /**
128
+ * Normalizes package exports into canonical subpath map form.
129
+ *
130
+ * Converts:
131
+ *
132
+ * "exports": "./index.js"
133
+ * → { ".": "./index.js" }
134
+ *
135
+ * "exports": { "import": "./index.js" }
136
+ * → { ".": { "import": "./index.js" } }
137
+ *
138
+ * Leaves already-normalized subpath maps untouched.
139
+ */
140
+ function normalizeExportsToSubpathMap(exportsField) {
141
+ if (exportsField == null) {
142
+ throw new Error(`[App Shell]: package.json is missing "exports".`);
143
+ }
144
+ // Sugar form:
145
+ // "exports": "./index.js"
146
+ // "exports": ["./a.js", "./b.js"]
147
+ if (typeof exportsField === "string" || Array.isArray(exportsField)) {
148
+ return { ".": exportsField };
149
+ }
150
+ const keys = Object.keys(exportsField);
151
+ // Already a subpath map
152
+ if (keys.every((key) => key.startsWith("."))) {
153
+ return exportsField;
154
+ }
155
+ // Root conditional exports sugar
156
+ return { ".": exportsField };
157
+ }
158
+ /**
159
+ * Appends standard metadata exports required at runtime.
160
+ */
161
+ function appendStandardExports(exportsMap, outDir) {
162
+ exportsMap["./package.json"] = "./package.json";
163
+ exportsMap["./app-shell.config.json"] = "./app-shell.config.json";
164
+ if (fs.existsSync(path.join(outDir, "locales"))) {
165
+ exportsMap["./locales/*"] = "./locales/*";
166
+ }
167
+ }
168
+ // ─── Dist package.json generation ────────────────────────────────────────────
169
+ /**
170
+ * Generates dist/package.json from the source package.
171
+ *
172
+ * The generated package:
173
+ * - strips dev-only export conditions
174
+ * - rewrites export paths relative to dist/
175
+ * - preserves explicit null exclusions
176
+ * - supports nested conditional exports
177
+ */
178
+ function generateDistPackageJson(root, outDir, buildOutDir, sourceCondition, externalizedPackages) {
179
+ const pkgPath = path.join(root, "package.json");
180
+ const pkg = readJsonFile(pkgPath);
181
+ if (!pkg || !fs.existsSync(outDir)) {
182
+ return false;
183
+ }
184
+ const rawExports = pkg.exports;
185
+ const distPrefix = `./${buildOutDir}/`;
186
+ const transformedExports = transformExportTargetForDist(normalizeExportsToSubpathMap(rawExports), distPrefix, sourceCondition);
187
+ /**
188
+ * The entire exports tree may collapse after removing dev-only
189
+ * conditions and invalid dist targets.
190
+ */
191
+ if (transformedExports === undefined) {
192
+ throw new Error(`[App Shell] ${pkg.name}: exports resolved to empty after transformation.`);
193
+ }
194
+ appendStandardExports(transformedExports, outDir);
195
+ const distPkg = {};
196
+ // Copy runtime-relevant fields. The "dependencies" and "optionalDependencies"
197
+ // fields are narrowed to only the modules that Rollup actually externalized,
198
+ // so the published package declares exactly the runtime modules it expects the
199
+ // host to provide.
200
+ for (const field of INCLUDED_FIELDS) {
201
+ if (pkg[field] == null) {
202
+ continue;
203
+ }
204
+ if (field === "dependencies" || field === "optionalDependencies") {
205
+ const filtered = filterExternalizedDependencies(pkg[field], externalizedPackages);
206
+ if (Object.keys(filtered).length > 0) {
207
+ distPkg[field] = filtered;
208
+ }
209
+ continue;
210
+ }
211
+ distPkg[field] = pkg[field];
212
+ }
213
+ distPkg.exports = transformedExports;
214
+ fs.writeFileSync(path.join(outDir, "package.json"), JSON.stringify(distPkg, null, 2) + "\n");
215
+ console.info(`[App Shell] Generated ${buildOutDir}/package.json for ${pkg.name}`);
216
+ return true;
217
+ }
218
+ /**
219
+ * Keeps only the declared dependencies whose package was externalized by the
220
+ * bundle (i.e. expected to be resolved by the host at runtime).
221
+ */
222
+ function filterExternalizedDependencies(dependencies, externalizedPackages) {
223
+ const filtered = {};
224
+ for (const [name, range] of Object.entries(dependencies)) {
225
+ if (externalizedPackages.has(name)) {
226
+ filtered[name] = range;
227
+ }
228
+ }
229
+ return filtered;
230
+ }
231
+ // ─── Plugin ──────────────────────────────────────────────────────────────────
232
+ /**
233
+ * Generates a cleaned dist/package.json during Vite builds.
234
+ */
235
+ export default function distPackageJsonPlugin(root, sourceCondition = DEFAULT_SOURCE_CONDITION) {
236
+ let config;
237
+ const externalizedPackages = new Set();
238
+ return {
239
+ name: "vite-plugin-dist-package-json",
240
+ apply: "build",
241
+ configResolved(resolved) {
242
+ config = resolved;
243
+ },
244
+ buildStart() {
245
+ // Reset per build so stale externalized packages from a previous build
246
+ // (e.g. in watch mode, where the plugin instance is reused) don't leak
247
+ // into the next dist/package.json.
248
+ externalizedPackages.clear();
249
+ },
250
+ generateBundle(_options, bundle) {
251
+ const emittedFiles = new Set(Object.keys(bundle));
252
+ for (const file of Object.values(bundle)) {
253
+ if (file.type !== "chunk") {
254
+ continue;
255
+ }
256
+ // Imports that do not point to an emitted file are external modules
257
+ // that Rollup left for the host runtime to resolve.
258
+ for (const imported of [...file.imports, ...file.dynamicImports]) {
259
+ if (!emittedFiles.has(imported)) {
260
+ externalizedPackages.add(toPackageName(imported));
261
+ }
262
+ }
263
+ }
264
+ },
265
+ closeBundle() {
266
+ const packageRoot = root ?? config.root;
267
+ const outDir = path.resolve(packageRoot, config.build.outDir);
268
+ generateDistPackageJson(packageRoot, outDir, config.build.outDir, sourceCondition, externalizedPackages);
269
+ },
270
+ };
271
+ }
@@ -8,7 +8,7 @@ import type { HvAppShellConfig } from "@hitachivantara/app-shell-shared";
8
8
  * @param appShellConfig App shell config values
9
9
  * @returns The app title
10
10
  */
11
- export declare const getAppTitle: (generateEmptyShell: boolean, appShellConfig: HvAppShellConfig) => any;
11
+ export declare const getAppTitle: (generateEmptyShell: boolean, appShellConfig: HvAppShellConfig) => string;
12
12
  /**
13
13
  * Add the <BASE> tag and icons preload in the index.html file.
14
14
  * @param appShellConfig The app shell configuration.
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import SHARED_DEPENDENCIES from "./shared-dependencies.js";
4
- import { getExtraDependenciesString } from "./vite-importmap-plugin.js";
4
+ import { getExtraDependenciesString } from "./vite-plugin-importmap.js";
5
5
  export default function generateBashScript(externalImportMap, inlineConfig) {
6
6
  let config;
7
7
  let targetDir;
@@ -1,7 +1,8 @@
1
1
  import fs from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import path from "node:path";
4
- import { computeSupportedLocales, deepMerge, mergeDirs, readJsonFile, SUPPORTED_LOCALES_FILE, } from "./locales-utils.js";
4
+ import { computeSupportedLocales, mergeDirs, SUPPORTED_LOCALES_FILE, } from "./locales-utils.js";
5
+ import { deepMerge, readJsonFile } from "./utils.js";
5
6
  /**
6
7
  * Resolves the app-shell-ui's locales directory path via its `./locales/*` export.
7
8
  */
@@ -63,7 +64,7 @@ export default function copyAppShellLocales(mergeUpstream = true) {
63
64
  let resolvedOutDir;
64
65
  let isBuild = false;
65
66
  return {
66
- name: "vite-plugin-appshell-copy-locales",
67
+ name: "vite-plugin-copy-appShell-locales",
67
68
  // Capture the resolved output directory from Vite's config
68
69
  configResolved(config) {
69
70
  resolvedOutDir = path.resolve(config.root, config.build.outDir);
@@ -4,5 +4,4 @@ import type { PluginOption } from "vite";
4
4
  * The metadata is used to help any troubleshoot activity by referencing
5
5
  * the version of the app-shell-vite-plugin and app-shell-ui packages used by the app.
6
6
  */
7
- declare const injectMetadata: () => PluginOption;
8
- export default injectMetadata;
7
+ export default function injectMetadata(): PluginOption;
@@ -1,20 +1,18 @@
1
- import fs from "node:fs";
2
1
  import { resolveModule } from "./nodeModule.js";
2
+ import { readJsonFile } from "./utils.js";
3
3
  const extractVersion = (packageJsonFile) => {
4
- const packageJson = fs.readFileSync(packageJsonFile, "utf8");
5
- const packageObject = JSON.parse(packageJson);
6
- return packageObject.version;
4
+ return readJsonFile(packageJsonFile).version;
7
5
  };
8
6
  /**
9
7
  * This plugin injects metadata into the index.html file.
10
8
  * The metadata is used to help any troubleshoot activity by referencing
11
9
  * the version of the app-shell-vite-plugin and app-shell-ui packages used by the app.
12
10
  */
13
- const injectMetadata = () => {
11
+ export default function injectMetadata() {
14
12
  const appShellUIVersion = extractVersion(resolveModule("@hitachivantara/app-shell-ui/package.json"));
15
13
  const appShellVitePluginVersion = extractVersion(resolveModule("@hitachivantara/app-shell-vite-plugin/package.json"));
16
14
  return {
17
- name: "vite-metadata-plugin",
15
+ name: "vite-plugin-metadata",
18
16
  transformIndexHtml() {
19
17
  return [
20
18
  {
@@ -34,5 +32,4 @@ const injectMetadata = () => {
34
32
  ];
35
33
  },
36
34
  };
37
- };
38
- export default injectMetadata;
35
+ }
@@ -1,12 +1,14 @@
1
1
  import path from "node:path";
2
2
  const prepareConfigForDevMode = (config, selfAppName) => {
3
3
  let configString = JSON.stringify(config);
4
+ configString = configString.replaceAll(`"$app/`, `"${selfAppName}/`);
5
+ // TODO(major): remove @self/ support in favour of $app/
4
6
  configString = configString.replaceAll(`"@self/`, `"${selfAppName}/`);
5
7
  return JSON.parse(configString);
6
8
  };
7
9
  export default function serveAppShellConfig(appShellConfig, root, selfAppName, appShellConfigFile, automaticViewsFolder) {
8
10
  return {
9
- name: "vite-plugin-watch-app-shell-config",
11
+ name: "vite-plugin-watch-appShell-config",
10
12
  apply: "serve",
11
13
  configureServer(server) {
12
14
  const restartServer = (file) => {