@trackunit/iris-app-build-utilities 1.9.22 → 1.10.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## 1.10.1 (2026-01-12)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated iris-app-api to 1.13.1
6
+
7
+ ## 1.10.0 (2026-01-12)
8
+
9
+ ### 🚀 Features
10
+
11
+ - enhance module loading and HTML generation for remote entries ([b1084798ae0](https://github.com/Trackunit/manager/commit/b1084798ae0))
12
+ - update HTML generation for remote script type ([f19cf84f02f](https://github.com/Trackunit/manager/commit/f19cf84f02f))
13
+ - enhance module federation support and loading mechanism ([75c9d14690f](https://github.com/Trackunit/manager/commit/75c9d14690f))
14
+ - enhance asset management in project.json ([dd52b03a22b](https://github.com/Trackunit/manager/commit/dd52b03a22b))
15
+ - add rollup-plugin-visualizer for bundle analysis ([6db228d8f14](https://github.com/Trackunit/manager/commit/6db228d8f14))
16
+ - add extensionType variable to HTML generation and improve TypeScript config loading ([add881c7ef7](https://github.com/Trackunit/manager/commit/add881c7ef7))
17
+
18
+ ### 🩹 Fixes
19
+
20
+ - allow local development by toggling extension loader URL based on environment variable ([dfda5509ef6](https://github.com/Trackunit/manager/commit/dfda5509ef6))
21
+
22
+ ### 🧱 Updated Dependencies
23
+
24
+ - Updated iris-app-api to 1.13.0
25
+
26
+ ### ❤️ Thank You
27
+
28
+ - Mikkel Thorbjørn Andersen
29
+
1
30
  ## 1.9.22 (2026-01-09)
2
31
 
3
32
  ### 🧱 Updated Dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app-build-utilities",
3
- "version": "1.9.22",
3
+ "version": "1.10.1",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "repository": "https://github.com/Trackunit/manager",
6
6
  "engines": {
@@ -14,9 +14,10 @@
14
14
  "tailwindcss": "3.4.3",
15
15
  "@tailwindcss/container-queries": "^0.1.1",
16
16
  "webpack-dev-server": "5.2.1",
17
+ "tslib": "^2.6.2",
18
+ "csp-header": "^5.2.1",
17
19
  "@rspack/core": "1.6.7",
18
- "@trackunit/iris-app-api": "1.12.22",
19
- "tslib": "^2.6.2"
20
+ "@trackunit/iris-app-api": "1.13.1"
20
21
  },
21
22
  "types": "./src/index.d.ts",
22
23
  "main": "./src/index.js",
@@ -1,5 +1,6 @@
1
1
  interface TSConfigOptions {
2
2
  projectRootDir: string;
3
+ workspaceRoot?: string;
3
4
  }
4
5
  /**
5
6
  * This enables typescript file to load projects from the path section in tsconfig file.
@@ -23,9 +23,9 @@ const enableTsConfigPath = (options) => {
23
23
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
24
  m._compile(outputText, filename);
25
25
  };
26
- const loadedConf = (0, tsconfig_paths_1.loadConfig)(options.projectRootDir);
26
+ const loadedConf = (0, tsconfig_paths_1.loadConfig)(options.workspaceRoot ? (0, path_1.join)(options.workspaceRoot, "tsconfig.base.json") : options.projectRootDir);
27
27
  (0, tsconfig_paths_1.register)({
28
- baseUrl: (0, path_1.join)(options.projectRootDir, loadedConf.baseUrl || ""),
28
+ baseUrl: options.workspaceRoot || (0, path_1.join)(options.projectRootDir, loadedConf.baseUrl || ""),
29
29
  paths: loadedConf.paths,
30
30
  });
31
31
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"enableTsConfigPath.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/enableTsConfigPath.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAClC,+BAA4B;AAC5B,mDAAiF;AAMjF,IAAI,QAAqC,CAAC;AAE1C;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,CAAC,OAAwB,EAAE,EAAE;IAC7D,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAA,WAAI,EAAC,OAAO,CAAC,cAAc,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrH,MAAM,MAAM,GAAG,QAAQ,CAAC,0BAA0B,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAE5G,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,EAAE,QAAQ;QAC/C,MAAM,KAAK,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE9C,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE;YACrD,eAAe,EAAE,UAAU,CAAC,MAAM;SACnC,CAAC,CAAC;QAEH,8DAA8D;QAC7D,CAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,IAAA,2BAAU,EAAC,OAAO,CAAC,cAAc,CAA8B,CAAC;IACnF,IAAA,yBAAQ,EAAC;QACP,OAAO,EAAE,IAAA,WAAI,EAAC,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC;QAC/D,KAAK,EAAE,UAAU,CAAC,KAAK;KACxB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AArBW,QAAA,kBAAkB,sBAqB7B","sourcesContent":["import { readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { ConfigLoaderSuccessResult, loadConfig, register } from \"tsconfig-paths\";\n\ninterface TSConfigOptions {\n projectRootDir: string;\n}\n\nlet tsModule: typeof import(\"typescript\");\n\n/**\n * This enables typescript file to load projects from the path section in tsconfig file.\n *\n * @param options - The options to enable tsconfig path\n * @returns {import(\"typescript\").ParsedCommandLine} - Returns the parsed command line\n */\nexport const enableTsConfigPath = (options: TSConfigOptions) => {\n tsModule = require(\"typescript\");\n const readResult = tsModule.readConfigFile(join(options.projectRootDir, \"tsconfig.app.json\"), tsModule.sys.readFile);\n const result = tsModule.parseJsonConfigFileContent(readResult.config, tsModule.sys, options.projectRootDir);\n\n require.extensions[\".ts\"] = function (m, filename) {\n const input = readFileSync(filename, \"utf-8\");\n\n const { outputText } = tsModule.transpileModule(input, {\n compilerOptions: readResult.config,\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (m as any)._compile(outputText, filename);\n };\n const loadedConf = loadConfig(options.projectRootDir) as ConfigLoaderSuccessResult;\n register({\n baseUrl: join(options.projectRootDir, loadedConf.baseUrl || \"\"),\n paths: loadedConf.paths,\n });\n return result;\n};\n"]}
1
+ {"version":3,"file":"enableTsConfigPath.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/enableTsConfigPath.ts"],"names":[],"mappings":";;;AAAA,2BAAkC;AAClC,+BAA4B;AAC5B,mDAAiF;AAOjF,IAAI,QAAqC,CAAC;AAE1C;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,CAAC,OAAwB,EAAE,EAAE;IAC7D,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAA,WAAI,EAAC,OAAO,CAAC,cAAc,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrH,MAAM,MAAM,GAAG,QAAQ,CAAC,0BAA0B,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAE5G,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,EAAE,QAAQ;QAC/C,MAAM,KAAK,GAAG,IAAA,iBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE9C,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,EAAE;YACrD,eAAe,EAAE,UAAU,CAAC,MAAM;SACnC,CAAC,CAAC;QAEH,8DAA8D;QAC7D,CAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,IAAA,2BAAU,EAC3B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,IAAA,WAAI,EAAC,OAAO,CAAC,aAAa,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CACtE,CAAC;IAC/B,IAAA,yBAAQ,EAAC;QACP,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,IAAA,WAAI,EAAC,OAAO,CAAC,cAAc,EAAE,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC;QACxF,KAAK,EAAE,UAAU,CAAC,KAAK;KACxB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAvBW,QAAA,kBAAkB,sBAuB7B","sourcesContent":["import { readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { ConfigLoaderSuccessResult, loadConfig, register } from \"tsconfig-paths\";\n\ninterface TSConfigOptions {\n projectRootDir: string;\n workspaceRoot?: string;\n}\n\nlet tsModule: typeof import(\"typescript\");\n\n/**\n * This enables typescript file to load projects from the path section in tsconfig file.\n *\n * @param options - The options to enable tsconfig path\n * @returns {import(\"typescript\").ParsedCommandLine} - Returns the parsed command line\n */\nexport const enableTsConfigPath = (options: TSConfigOptions) => {\n tsModule = require(\"typescript\");\n const readResult = tsModule.readConfigFile(join(options.projectRootDir, \"tsconfig.app.json\"), tsModule.sys.readFile);\n const result = tsModule.parseJsonConfigFileContent(readResult.config, tsModule.sys, options.projectRootDir);\n\n require.extensions[\".ts\"] = function (m, filename) {\n const input = readFileSync(filename, \"utf-8\");\n\n const { outputText } = tsModule.transpileModule(input, {\n compilerOptions: readResult.config,\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (m as any)._compile(outputText, filename);\n };\n const loadedConf = loadConfig(\n options.workspaceRoot ? join(options.workspaceRoot, \"tsconfig.base.json\") : options.projectRootDir\n ) as ConfigLoaderSuccessResult;\n register({\n baseUrl: options.workspaceRoot || join(options.projectRootDir, loadedConf.baseUrl || \"\"),\n paths: loadedConf.paths,\n });\n return result;\n};\n"]}
@@ -0,0 +1,49 @@
1
+ import { IrisAppManifest } from "@trackunit/iris-app-api";
2
+ /**
3
+ * Represents a copy pattern for CopyWebpackPlugin/CopyRspackPlugin/vite-plugin-static-copy
4
+ */
5
+ export interface CopyPattern {
6
+ /** Source path (with forward slashes for glob compatibility) */
7
+ from: string;
8
+ /** Destination path */
9
+ to: string;
10
+ }
11
+ interface GetCopyPatternsOptions {
12
+ /** The root of the nx workspace */
13
+ nxRootDir: string;
14
+ /** The app directory */
15
+ appDir: string;
16
+ /** The Iris app manifest */
17
+ manifest: IrisAppManifest;
18
+ /** Build mode - serverside extensions are only copied in production */
19
+ mode: "production" | "development";
20
+ }
21
+ /**
22
+ * Gets all copy patterns for an Iris app build.
23
+ *
24
+ * This utility consolidates the copy patterns logic used by webpack, rspack, and vite builds.
25
+ * It generates patterns for:
26
+ * - Serverside extensions (only in production mode)
27
+ * - Assets folder
28
+ * - Extension icons (fleet menu icons and widget icons)
29
+ *
30
+ * @param options - Configuration options for generating copy patterns
31
+ * @returns {Array<CopyPattern>} Array of copy patterns with `from` and `to` paths
32
+ * @example
33
+ * ```ts
34
+ * const patterns = getCopyPatterns({
35
+ * nxRootDir: '/path/to/workspace',
36
+ * appDir: '/path/to/workspace/apps/my-app',
37
+ * manifest: irisAppManifest,
38
+ * mode: 'production',
39
+ * });
40
+ *
41
+ * // Use with CopyWebpackPlugin
42
+ * new CopyWebpackPlugin({ patterns });
43
+ *
44
+ * // Use with CopyRspackPlugin
45
+ * new CopyRspackPlugin({ patterns });
46
+ * ```
47
+ */
48
+ export declare const getCopyPatterns: (options: GetCopyPatternsOptions) => Array<CopyPattern>;
49
+ export {};
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCopyPatterns = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const iris_app_api_1 = require("@trackunit/iris-app-api");
6
+ const path = tslib_1.__importStar(require("path"));
7
+ /**
8
+ * Extracts icon paths from FLEET_EXTENSION menu items.
9
+ * These are SVG icons that need to be copied to the output directory.
10
+ */
11
+ const getFleetExtensionIconPaths = (manifest) => {
12
+ return manifest.extensions
13
+ .filter(extension => {
14
+ return extension.type === "FLEET_EXTENSION" && extension.menuItem.image && (0, iris_app_api_1.isIconByPath)(extension.menuItem.image);
15
+ })
16
+ .map(extension => {
17
+ if (extension.type !== "FLEET_EXTENSION" ||
18
+ !extension.menuItem.image ||
19
+ !(0, iris_app_api_1.isIconByPath)(extension.menuItem.image)) {
20
+ throw new Error("Unexpected extension type after filter");
21
+ }
22
+ return {
23
+ extensionId: extension.id,
24
+ path: extension.menuItem.image.path,
25
+ sourceRoot: extension.sourceRoot,
26
+ };
27
+ });
28
+ };
29
+ /**
30
+ * Extracts icon paths from WIDGET_EXTENSION headers and footers.
31
+ * Widgets can have both a header image and a footer poweredByImage.
32
+ */
33
+ const getWidgetExtensionIconPaths = (manifest) => {
34
+ return manifest.extensions.flatMap(extension => {
35
+ const paths = [];
36
+ if (extension.type === "WIDGET_EXTENSION" &&
37
+ extension.footer?.poweredByImage &&
38
+ (0, iris_app_api_1.isImageByPath)(extension.footer.poweredByImage)) {
39
+ paths.push({
40
+ extensionId: extension.id,
41
+ path: extension.footer.poweredByImage.path,
42
+ sourceRoot: extension.sourceRoot,
43
+ });
44
+ }
45
+ if (extension.type === "WIDGET_EXTENSION" && extension.header.image && (0, iris_app_api_1.isIconByPath)(extension.header.image)) {
46
+ paths.push({
47
+ extensionId: extension.id,
48
+ path: extension.header.image.path,
49
+ sourceRoot: extension.sourceRoot,
50
+ });
51
+ }
52
+ return paths;
53
+ });
54
+ };
55
+ /**
56
+ * Generates copy patterns for serverside extensions (LIFECYCLE_EXTENSION, SERVERLESS_FUNCTION_EXTENSION, AI_AGENT_EXTENSION).
57
+ * These are only copied in production mode.
58
+ */
59
+ const getServersideExtensionPatterns = (options) => {
60
+ const { nxRootDir, appDir, manifest, mode } = options;
61
+ const relativeAppDir = appDir.split(nxRootDir)[1] || "<unknown appdir>";
62
+ // Only copy serverside extensions in production
63
+ if (mode !== "production") {
64
+ return [];
65
+ }
66
+ return manifest.extensions
67
+ .filter(extension => iris_app_api_1.serverSideExtensionTypes.includes(extension.type))
68
+ .flatMap(extension => {
69
+ const patterns = [
70
+ {
71
+ // globs must use / in path to be valid
72
+ from: path.resolve(nxRootDir, extension.sourceRoot.replace(/\\/g, "/")),
73
+ to: path.join(nxRootDir, "dist", relativeAppDir, "serverside", extension.id),
74
+ },
75
+ ];
76
+ // Check if extension has dependencyDefinitionFile and add it to patterns if it exists
77
+ if ("dependencyDefinitionFile" in extension && extension.dependencyDefinitionFile) {
78
+ patterns.push({
79
+ // globs must use / in path to be valid
80
+ from: path.resolve(nxRootDir, extension.dependencyDefinitionFile.replace(/\\/g, "/")),
81
+ to: path.join(nxRootDir, "dist", relativeAppDir, "serverside", extension.id),
82
+ });
83
+ }
84
+ return patterns;
85
+ });
86
+ };
87
+ /**
88
+ * Generates the copy pattern for the assets folder.
89
+ */
90
+ const getAssetsPattern = (options) => {
91
+ const { nxRootDir, appDir } = options;
92
+ const relativeAppDir = appDir.split(nxRootDir)[1] || "<unknown appdir>";
93
+ return {
94
+ // globs must use / in path to be valid
95
+ from: path.join(appDir, "assets/").replace(/\\/g, "/"),
96
+ to: path.join(nxRootDir, "dist", relativeAppDir, "assets"),
97
+ };
98
+ };
99
+ /**
100
+ * Generates copy patterns for extension icons (fleet menu icons and widget icons).
101
+ */
102
+ const getIconPatterns = (options) => {
103
+ const { nxRootDir, appDir, manifest } = options;
104
+ const relativeAppDir = appDir.split(nxRootDir)[1] || "<unknown appdir>";
105
+ const fleetIconPaths = getFleetExtensionIconPaths(manifest);
106
+ const widgetIconPaths = getWidgetExtensionIconPaths(manifest);
107
+ const allIconPaths = [...fleetIconPaths, ...widgetIconPaths];
108
+ return allIconPaths.map(iconPath => ({
109
+ // globs must use / in path to be valid
110
+ from: path.join(nxRootDir, iconPath.sourceRoot, iconPath.path).replace(/\\/g, "/"),
111
+ to: path.join(nxRootDir, "dist", relativeAppDir, iconPath.extensionId, iconPath.path),
112
+ }));
113
+ };
114
+ /**
115
+ * Gets all copy patterns for an Iris app build.
116
+ *
117
+ * This utility consolidates the copy patterns logic used by webpack, rspack, and vite builds.
118
+ * It generates patterns for:
119
+ * - Serverside extensions (only in production mode)
120
+ * - Assets folder
121
+ * - Extension icons (fleet menu icons and widget icons)
122
+ *
123
+ * @param options - Configuration options for generating copy patterns
124
+ * @returns {Array<CopyPattern>} Array of copy patterns with `from` and `to` paths
125
+ * @example
126
+ * ```ts
127
+ * const patterns = getCopyPatterns({
128
+ * nxRootDir: '/path/to/workspace',
129
+ * appDir: '/path/to/workspace/apps/my-app',
130
+ * manifest: irisAppManifest,
131
+ * mode: 'production',
132
+ * });
133
+ *
134
+ * // Use with CopyWebpackPlugin
135
+ * new CopyWebpackPlugin({ patterns });
136
+ *
137
+ * // Use with CopyRspackPlugin
138
+ * new CopyRspackPlugin({ patterns });
139
+ * ```
140
+ */
141
+ const getCopyPatterns = (options) => {
142
+ return [...getServersideExtensionPatterns(options), getAssetsPattern(options), ...getIconPatterns(options)];
143
+ };
144
+ exports.getCopyPatterns = getCopyPatterns;
145
+ //# sourceMappingURL=getCopyPatterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCopyPatterns.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getCopyPatterns.ts"],"names":[],"mappings":";;;;AAAA,0DAAiH;AACjH,mDAA6B;AAgC7B;;;GAGG;AACH,MAAM,0BAA0B,GAAG,CAAC,QAAyB,EAAmB,EAAE;IAChF,OAAO,QAAQ,CAAC,UAAU;SACvB,MAAM,CAAC,SAAS,CAAC,EAAE;QAClB,OAAO,SAAS,CAAC,IAAI,KAAK,iBAAiB,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAA,2BAAY,EAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpH,CAAC,CAAC;SACD,GAAG,CAAC,SAAS,CAAC,EAAE;QACf,IACE,SAAS,CAAC,IAAI,KAAK,iBAAiB;YACpC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK;YACzB,CAAC,IAAA,2BAAY,EAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EACvC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO;YACL,WAAW,EAAE,SAAS,CAAC,EAAE;YACzB,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;YACnC,UAAU,EAAE,SAAS,CAAC,UAAU;SACjC,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,2BAA2B,GAAG,CAAC,QAAyB,EAAmB,EAAE;IACjF,OAAO,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC7C,MAAM,KAAK,GAAoB,EAAE,CAAC;QAElC,IACE,SAAS,CAAC,IAAI,KAAK,kBAAkB;YACrC,SAAS,CAAC,MAAM,EAAE,cAAc;YAChC,IAAA,4BAAa,EAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,EAC9C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC;gBACT,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI;gBAC1C,UAAU,EAAE,SAAS,CAAC,UAAU;aACjC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,SAAS,CAAC,IAAI,KAAK,kBAAkB,IAAI,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,IAAA,2BAAY,EAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5G,KAAK,CAAC,IAAI,CAAC;gBACT,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;gBACjC,UAAU,EAAE,SAAS,CAAC,UAAU;aACjC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,8BAA8B,GAAG,CAAC,OAA+B,EAAsB,EAAE;IAC7F,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACtD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC;IAExE,gDAAgD;IAChD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,QAAQ,CAAC,UAAU;SACvB,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,uCAAwB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;SACtE,OAAO,CAAC,SAAS,CAAC,EAAE;QACnB,MAAM,QAAQ,GAAuB;YACnC;gBACE,uCAAuC;gBACvC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACvE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;aAC7E;SACF,CAAC;QAEF,sFAAsF;QACtF,IAAI,0BAA0B,IAAI,SAAS,IAAI,SAAS,CAAC,wBAAwB,EAAE,CAAC;YAClF,QAAQ,CAAC,IAAI,CAAC;gBACZ,uCAAuC;gBACvC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACrF,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;aAC7E,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,gBAAgB,GAAG,CAAC,OAA+B,EAAe,EAAE;IACxE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACtC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC;IAExE,OAAO;QACL,uCAAuC;QACvC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QACtD,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC;KAC3D,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,OAA+B,EAAsB,EAAE;IAC9E,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC;IAExE,MAAM,cAAc,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,eAAe,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,eAAe,CAAC,CAAC;IAE7D,OAAO,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnC,uCAAuC;QACvC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QAClF,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC;KACtF,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACI,MAAM,eAAe,GAAG,CAAC,OAA+B,EAAsB,EAAE;IACrF,OAAO,CAAC,GAAG,8BAA8B,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9G,CAAC,CAAC;AAFW,QAAA,eAAe,mBAE1B","sourcesContent":["import { IrisAppManifest, isIconByPath, isImageByPath, serverSideExtensionTypes } from \"@trackunit/iris-app-api\";\nimport * as path from \"path\";\n\n/**\n * Represents a copy pattern for CopyWebpackPlugin/CopyRspackPlugin/vite-plugin-static-copy\n */\nexport interface CopyPattern {\n /** Source path (with forward slashes for glob compatibility) */\n from: string;\n /** Destination path */\n to: string;\n}\n\n/**\n * Represents an icon path extracted from the manifest\n */\ninterface IconPath {\n extensionId: string;\n path: string;\n sourceRoot: string;\n}\n\ninterface GetCopyPatternsOptions {\n /** The root of the nx workspace */\n nxRootDir: string;\n /** The app directory */\n appDir: string;\n /** The Iris app manifest */\n manifest: IrisAppManifest;\n /** Build mode - serverside extensions are only copied in production */\n mode: \"production\" | \"development\";\n}\n\n/**\n * Extracts icon paths from FLEET_EXTENSION menu items.\n * These are SVG icons that need to be copied to the output directory.\n */\nconst getFleetExtensionIconPaths = (manifest: IrisAppManifest): Array<IconPath> => {\n return manifest.extensions\n .filter(extension => {\n return extension.type === \"FLEET_EXTENSION\" && extension.menuItem.image && isIconByPath(extension.menuItem.image);\n })\n .map(extension => {\n if (\n extension.type !== \"FLEET_EXTENSION\" ||\n !extension.menuItem.image ||\n !isIconByPath(extension.menuItem.image)\n ) {\n throw new Error(\"Unexpected extension type after filter\");\n }\n return {\n extensionId: extension.id,\n path: extension.menuItem.image.path,\n sourceRoot: extension.sourceRoot,\n };\n });\n};\n\n/**\n * Extracts icon paths from WIDGET_EXTENSION headers and footers.\n * Widgets can have both a header image and a footer poweredByImage.\n */\nconst getWidgetExtensionIconPaths = (manifest: IrisAppManifest): Array<IconPath> => {\n return manifest.extensions.flatMap(extension => {\n const paths: Array<IconPath> = [];\n\n if (\n extension.type === \"WIDGET_EXTENSION\" &&\n extension.footer?.poweredByImage &&\n isImageByPath(extension.footer.poweredByImage)\n ) {\n paths.push({\n extensionId: extension.id,\n path: extension.footer.poweredByImage.path,\n sourceRoot: extension.sourceRoot,\n });\n }\n\n if (extension.type === \"WIDGET_EXTENSION\" && extension.header.image && isIconByPath(extension.header.image)) {\n paths.push({\n extensionId: extension.id,\n path: extension.header.image.path,\n sourceRoot: extension.sourceRoot,\n });\n }\n\n return paths;\n });\n};\n\n/**\n * Generates copy patterns for serverside extensions (LIFECYCLE_EXTENSION, SERVERLESS_FUNCTION_EXTENSION, AI_AGENT_EXTENSION).\n * These are only copied in production mode.\n */\nconst getServersideExtensionPatterns = (options: GetCopyPatternsOptions): Array<CopyPattern> => {\n const { nxRootDir, appDir, manifest, mode } = options;\n const relativeAppDir = appDir.split(nxRootDir)[1] || \"<unknown appdir>\";\n\n // Only copy serverside extensions in production\n if (mode !== \"production\") {\n return [];\n }\n\n return manifest.extensions\n .filter(extension => serverSideExtensionTypes.includes(extension.type))\n .flatMap(extension => {\n const patterns: Array<CopyPattern> = [\n {\n // globs must use / in path to be valid\n from: path.resolve(nxRootDir, extension.sourceRoot.replace(/\\\\/g, \"/\")),\n to: path.join(nxRootDir, \"dist\", relativeAppDir, \"serverside\", extension.id),\n },\n ];\n\n // Check if extension has dependencyDefinitionFile and add it to patterns if it exists\n if (\"dependencyDefinitionFile\" in extension && extension.dependencyDefinitionFile) {\n patterns.push({\n // globs must use / in path to be valid\n from: path.resolve(nxRootDir, extension.dependencyDefinitionFile.replace(/\\\\/g, \"/\")),\n to: path.join(nxRootDir, \"dist\", relativeAppDir, \"serverside\", extension.id),\n });\n }\n\n return patterns;\n });\n};\n\n/**\n * Generates the copy pattern for the assets folder.\n */\nconst getAssetsPattern = (options: GetCopyPatternsOptions): CopyPattern => {\n const { nxRootDir, appDir } = options;\n const relativeAppDir = appDir.split(nxRootDir)[1] || \"<unknown appdir>\";\n\n return {\n // globs must use / in path to be valid\n from: path.join(appDir, \"assets/\").replace(/\\\\/g, \"/\"),\n to: path.join(nxRootDir, \"dist\", relativeAppDir, \"assets\"),\n };\n};\n\n/**\n * Generates copy patterns for extension icons (fleet menu icons and widget icons).\n */\nconst getIconPatterns = (options: GetCopyPatternsOptions): Array<CopyPattern> => {\n const { nxRootDir, appDir, manifest } = options;\n const relativeAppDir = appDir.split(nxRootDir)[1] || \"<unknown appdir>\";\n\n const fleetIconPaths = getFleetExtensionIconPaths(manifest);\n const widgetIconPaths = getWidgetExtensionIconPaths(manifest);\n const allIconPaths = [...fleetIconPaths, ...widgetIconPaths];\n\n return allIconPaths.map(iconPath => ({\n // globs must use / in path to be valid\n from: path.join(nxRootDir, iconPath.sourceRoot, iconPath.path).replace(/\\\\/g, \"/\"),\n to: path.join(nxRootDir, \"dist\", relativeAppDir, iconPath.extensionId, iconPath.path),\n }));\n};\n\n/**\n * Gets all copy patterns for an Iris app build.\n *\n * This utility consolidates the copy patterns logic used by webpack, rspack, and vite builds.\n * It generates patterns for:\n * - Serverside extensions (only in production mode)\n * - Assets folder\n * - Extension icons (fleet menu icons and widget icons)\n *\n * @param options - Configuration options for generating copy patterns\n * @returns {Array<CopyPattern>} Array of copy patterns with `from` and `to` paths\n * @example\n * ```ts\n * const patterns = getCopyPatterns({\n * nxRootDir: '/path/to/workspace',\n * appDir: '/path/to/workspace/apps/my-app',\n * manifest: irisAppManifest,\n * mode: 'production',\n * });\n *\n * // Use with CopyWebpackPlugin\n * new CopyWebpackPlugin({ patterns });\n *\n * // Use with CopyRspackPlugin\n * new CopyRspackPlugin({ patterns });\n * ```\n */\nexport const getCopyPatterns = (options: GetCopyPatternsOptions): Array<CopyPattern> => {\n return [...getServersideExtensionPatterns(options), getAssetsPattern(options), ...getIconPatterns(options)];\n};\n"]}
@@ -57,9 +57,11 @@ const createIrisAppDevServerConfig = async (port) => ({
57
57
  response.header("Access-Control-Allow-Origin", request.headers.origin || "https://dev.manager.trackunit.com");
58
58
  response.header("Access-Control-Allow-Headers", "X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion");
59
59
  try {
60
- // To test extensionloader locally build the iris-app-loader and flip these 2 lines.
61
- // const resp = await fetch("http://localhost:3000/extensionloader.js");
62
- const resp = await fetch("https://iris.trackunit.app/extensionloader.js");
60
+ let url = "https://iris.trackunit.app/extensionloader.js";
61
+ if (process.env.LOCAL === "true") {
62
+ url = "http://localhost:3000/extensionloader.js";
63
+ }
64
+ const resp = await fetch(url);
63
65
  const body = await resp.text();
64
66
  response.send(body);
65
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getIrisAppDevServer.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getIrisAppDevServer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DevServer as RspackDevServer } from \"@rspack/core\";\nimport type { Configuration as WebpackDevServerConfiguration } from \"webpack-dev-server\";\nimport { getAvailablePort } from \"./getAvailablePort\";\n\n/**\n * Creates the base Iris App dev server configuration.\n *\n * Returns the config without explicit typing because webpack-dev-server's Configuration\n * and rspack's DevServer are nominally different types despite being structurally identical.\n * The rspack team acknowledges this type incompatibility in their own codebase with @ts-ignore.\n *\n * @see https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n */\nconst createIrisAppDevServerConfig = async (port: number) => ({\n port,\n historyApiFallback: true,\n headers: {\n \"Access-Control-Allow-Credentials\": \"true\",\n \"Access-Control-Max-Age\": \"3600\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\":\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\",\n },\n onListening: () => {},\n setupMiddlewares: (\n middlewares: Array<{ name?: string; path?: string; middleware: unknown }>,\n devServer: { app?: { use: (path: string, handler: unknown) => void } }\n ) => {\n middlewares.push({\n name: \"cors-preflight\",\n path: \"/\",\n middleware: (\n req: { method?: string },\n res: { send?: (body: unknown) => void; end?: (body: string) => void },\n next: () => void\n ) => {\n if (req.method === \"GET\") {\n next();\n } else {\n res.end?.(\"GET, HEAD\");\n }\n },\n });\n devServer.app?.use(\n \"/\",\n (\n request: { headers: { origin?: string } },\n response: { header: (name: string, value: string) => void },\n next: () => void\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n next();\n }\n );\n devServer.app?.use(\n \"/manifestAndToken\",\n async (\n request: { headers: { origin?: string } },\n response: {\n header: (name: string, value: string) => void;\n send: (body: unknown) => void;\n status: (code: number) => void;\n }\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n response.header(\n \"Access-Control-Allow-Headers\",\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\"\n );\n try {\n const resp = await fetch(`http://localhost:${port}/manifest.json`);\n const body = await resp.json();\n response.send({ manifest: body });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\"ERROR: \", e);\n response.status(500);\n response.send(e);\n }\n }\n );\n devServer.app?.use(\n \"/extensionloader.js\",\n async (\n request: { headers: { origin?: string } },\n response: {\n header: (name: string, value: string) => void;\n send: (body: unknown) => void;\n status: (code: number) => void;\n }\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n response.header(\n \"Access-Control-Allow-Headers\",\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\"\n );\n try {\n // To test extensionloader locally build the iris-app-loader and flip these 2 lines.\n // const resp = await fetch(\"http://localhost:3000/extensionloader.js\");\n const resp = await fetch(\"https://iris.trackunit.app/extensionloader.js\");\n const body = await resp.text();\n response.send(body);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\"ERROR: \", e);\n response.status(500);\n response.send(e);\n }\n }\n );\n return middlewares;\n },\n});\n\n/**\n * Generates a dev server configuration for webpack configuration.\n *\n * @param webpackDevServerConfiguration The configuration to extend.\n * @returns {WebpackDevServerConfiguration} The dev server for webpack.\n */\nexport const getIrisAppWebpackDevServer = async (\n webpackDevServerConfiguration: WebpackDevServerConfiguration = {}\n): Promise<WebpackDevServerConfiguration> => {\n const port = await getAvailablePort(22220, 22229);\n const baseConfig = await createIrisAppDevServerConfig(port);\n\n // Type assertion required: webpack-dev-server and rspack have nominally different but\n // structurally identical DevServer types. This is a known limitation acknowledged by\n // the rspack team. See: https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n // eslint-disable-next-line local-rules/no-typescript-assertion\n return { ...baseConfig, ...webpackDevServerConfiguration } as unknown as WebpackDevServerConfiguration;\n};\n\n/**\n * Generates a dev server configuration for rspack configuration.\n *\n * @param rspackDevServerConfiguration The configuration to extend.\n * @returns {RspackDevServer} The dev server for rspack.\n */\nexport const getIrisAppRspackDevServer = async (\n rspackDevServerConfiguration: RspackDevServer = {}\n): Promise<RspackDevServer> => {\n const port = await getAvailablePort(22220, 22229);\n const baseConfig = await createIrisAppDevServerConfig(port);\n\n // Type assertion required: webpack-dev-server and rspack have nominally different but\n // structurally identical DevServer types. This is a known limitation acknowledged by\n // the rspack team. See: https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n // eslint-disable-next-line local-rules/no-typescript-assertion\n return { ...baseConfig, ...rspackDevServerConfiguration } as unknown as RspackDevServer;\n};\n"]}
1
+ {"version":3,"file":"getIrisAppDevServer.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getIrisAppDevServer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DevServer as RspackDevServer } from \"@rspack/core\";\nimport type { Configuration as WebpackDevServerConfiguration } from \"webpack-dev-server\";\nimport { getAvailablePort } from \"./getAvailablePort\";\n\n/**\n * Creates the base Iris App dev server configuration.\n *\n * Returns the config without explicit typing because webpack-dev-server's Configuration\n * and rspack's DevServer are nominally different types despite being structurally identical.\n * The rspack team acknowledges this type incompatibility in their own codebase with @ts-ignore.\n *\n * @see https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n */\nconst createIrisAppDevServerConfig = async (port: number) => ({\n port,\n historyApiFallback: true,\n headers: {\n \"Access-Control-Allow-Credentials\": \"true\",\n \"Access-Control-Max-Age\": \"3600\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\":\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\",\n },\n onListening: () => {},\n setupMiddlewares: (\n middlewares: Array<{ name?: string; path?: string; middleware: unknown }>,\n devServer: { app?: { use: (path: string, handler: unknown) => void } }\n ) => {\n middlewares.push({\n name: \"cors-preflight\",\n path: \"/\",\n middleware: (\n req: { method?: string },\n res: { send?: (body: unknown) => void; end?: (body: string) => void },\n next: () => void\n ) => {\n if (req.method === \"GET\") {\n next();\n } else {\n res.end?.(\"GET, HEAD\");\n }\n },\n });\n devServer.app?.use(\n \"/\",\n (\n request: { headers: { origin?: string } },\n response: { header: (name: string, value: string) => void },\n next: () => void\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n next();\n }\n );\n devServer.app?.use(\n \"/manifestAndToken\",\n async (\n request: { headers: { origin?: string } },\n response: {\n header: (name: string, value: string) => void;\n send: (body: unknown) => void;\n status: (code: number) => void;\n }\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n response.header(\n \"Access-Control-Allow-Headers\",\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\"\n );\n try {\n const resp = await fetch(`http://localhost:${port}/manifest.json`);\n const body = await resp.json();\n response.send({ manifest: body });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\"ERROR: \", e);\n response.status(500);\n response.send(e);\n }\n }\n );\n devServer.app?.use(\n \"/extensionloader.js\",\n async (\n request: { headers: { origin?: string } },\n response: {\n header: (name: string, value: string) => void;\n send: (body: unknown) => void;\n status: (code: number) => void;\n }\n ) => {\n response.header(\"Access-Control-Allow-Origin\", request.headers.origin || \"https://dev.manager.trackunit.com\");\n response.header(\n \"Access-Control-Allow-Headers\",\n \"X-Requested-With, baggage, content-type, Authorization, sentry-trace, session-id, commit-number, x-trackunitappversion\"\n );\n try {\n let url = \"https://iris.trackunit.app/extensionloader.js\";\n if (process.env.LOCAL === \"true\") {\n url = \"http://localhost:3000/extensionloader.js\";\n }\n const resp = await fetch(url);\n const body = await resp.text();\n response.send(body);\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error(\"ERROR: \", e);\n response.status(500);\n response.send(e);\n }\n }\n );\n return middlewares;\n },\n});\n\n/**\n * Generates a dev server configuration for webpack configuration.\n *\n * @param webpackDevServerConfiguration The configuration to extend.\n * @returns {WebpackDevServerConfiguration} The dev server for webpack.\n */\nexport const getIrisAppWebpackDevServer = async (\n webpackDevServerConfiguration: WebpackDevServerConfiguration = {}\n): Promise<WebpackDevServerConfiguration> => {\n const port = await getAvailablePort(22220, 22229);\n const baseConfig = await createIrisAppDevServerConfig(port);\n\n // Type assertion required: webpack-dev-server and rspack have nominally different but\n // structurally identical DevServer types. This is a known limitation acknowledged by\n // the rspack team. See: https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n // eslint-disable-next-line local-rules/no-typescript-assertion\n return { ...baseConfig, ...webpackDevServerConfiguration } as unknown as WebpackDevServerConfiguration;\n};\n\n/**\n * Generates a dev server configuration for rspack configuration.\n *\n * @param rspackDevServerConfiguration The configuration to extend.\n * @returns {RspackDevServer} The dev server for rspack.\n */\nexport const getIrisAppRspackDevServer = async (\n rspackDevServerConfiguration: RspackDevServer = {}\n): Promise<RspackDevServer> => {\n const port = await getAvailablePort(22220, 22229);\n const baseConfig = await createIrisAppDevServerConfig(port);\n\n // Type assertion required: webpack-dev-server and rspack have nominally different but\n // structurally identical DevServer types. This is a known limitation acknowledged by\n // the rspack team. See: https://github.com/web-infra-dev/rspack/blob/main/packages/rspack-dev-server/src/server.ts\n // eslint-disable-next-line local-rules/no-typescript-assertion\n return { ...baseConfig, ...rspackDevServerConfiguration } as unknown as RspackDevServer;\n};\n"]}
package/src/index.d.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  export * from "./enableTsConfigPath";
2
2
  export * from "./getAliasesFromTsConfig";
3
+ export * from "./getAvailablePort";
4
+ export * from "./getCopyPatterns";
3
5
  export * from "./getExposedExtensions";
4
6
  export * from "./getGraphqlCodeGenConfig";
5
7
  export * from "./getIrisAppDevServer";
6
8
  export * from "./getSharedDependencies";
7
9
  export * from "./getTailwindContentForApp";
10
+ export * from "./plugin-shared/consoleUtils";
11
+ export * from "./plugin-shared/customFieldUtil";
12
+ export * from "./plugin-shared/extensionUtil";
13
+ export * from "./plugin-shared/indexHtmlUtil";
package/src/index.js CHANGED
@@ -3,9 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./enableTsConfigPath"), exports);
5
5
  tslib_1.__exportStar(require("./getAliasesFromTsConfig"), exports);
6
+ tslib_1.__exportStar(require("./getAvailablePort"), exports);
7
+ tslib_1.__exportStar(require("./getCopyPatterns"), exports);
6
8
  tslib_1.__exportStar(require("./getExposedExtensions"), exports);
7
9
  tslib_1.__exportStar(require("./getGraphqlCodeGenConfig"), exports);
8
10
  tslib_1.__exportStar(require("./getIrisAppDevServer"), exports);
9
11
  tslib_1.__exportStar(require("./getSharedDependencies"), exports);
10
12
  tslib_1.__exportStar(require("./getTailwindContentForApp"), exports);
13
+ tslib_1.__exportStar(require("./plugin-shared/consoleUtils"), exports);
14
+ tslib_1.__exportStar(require("./plugin-shared/customFieldUtil"), exports);
15
+ tslib_1.__exportStar(require("./plugin-shared/extensionUtil"), exports);
16
+ tslib_1.__exportStar(require("./plugin-shared/indexHtmlUtil"), exports);
11
17
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,mEAAyC;AACzC,iEAAuC;AACvC,oEAA0C;AAC1C,gEAAsC;AACtC,kEAAwC;AACxC,qEAA2C","sourcesContent":["export * from \"./enableTsConfigPath\";\nexport * from \"./getAliasesFromTsConfig\";\nexport * from \"./getExposedExtensions\";\nexport * from \"./getGraphqlCodeGenConfig\";\nexport * from \"./getIrisAppDevServer\";\nexport * from \"./getSharedDependencies\";\nexport * from \"./getTailwindContentForApp\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,mEAAyC;AACzC,6DAAmC;AACnC,4DAAkC;AAClC,iEAAuC;AACvC,oEAA0C;AAC1C,gEAAsC;AACtC,kEAAwC;AACxC,qEAA2C;AAC3C,uEAA6C;AAC7C,0EAAgD;AAChD,wEAA8C;AAC9C,wEAA8C","sourcesContent":["export * from \"./enableTsConfigPath\";\nexport * from \"./getAliasesFromTsConfig\";\nexport * from \"./getAvailablePort\";\nexport * from \"./getCopyPatterns\";\nexport * from \"./getExposedExtensions\";\nexport * from \"./getGraphqlCodeGenConfig\";\nexport * from \"./getIrisAppDevServer\";\nexport * from \"./getSharedDependencies\";\nexport * from \"./getTailwindContentForApp\";\nexport * from \"./plugin-shared/consoleUtils\";\nexport * from \"./plugin-shared/customFieldUtil\";\nexport * from \"./plugin-shared/extensionUtil\";\nexport * from \"./plugin-shared/indexHtmlUtil\";\n"]}
@@ -0,0 +1,16 @@
1
+ export declare const RESET = "\u001B[0m";
2
+ export declare const GREEN = "\u001B[32m";
3
+ export declare const RED = "\u001B[31m";
4
+ export declare const YELLOW = "\u001B[33m";
5
+ /**
6
+ * Logs an error message and exits the program with a non-zero exit code.
7
+ */
8
+ export declare const logError: (message: string) => void;
9
+ /**
10
+ * Logs a warning message.
11
+ */
12
+ export declare const logWarning: (message: string) => void;
13
+ /**
14
+ * Logs an info message.
15
+ */
16
+ export declare const logInfo: (message: string) => void;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logInfo = exports.logWarning = exports.logError = exports.YELLOW = exports.RED = exports.GREEN = exports.RESET = void 0;
4
+ exports.RESET = "\x1b[0m";
5
+ exports.GREEN = "\x1b[32m";
6
+ exports.RED = "\x1b[31m";
7
+ exports.YELLOW = "\x1b[33m";
8
+ /**
9
+ * Logs an error message and exits the program with a non-zero exit code.
10
+ */
11
+ const logError = (message) => {
12
+ // eslint-disable-next-line no-console
13
+ console.error(exports.RED, message, exports.RESET);
14
+ };
15
+ exports.logError = logError;
16
+ /**
17
+ * Logs a warning message.
18
+ */
19
+ const logWarning = (message) => {
20
+ // eslint-disable-next-line no-console
21
+ console.warn(exports.YELLOW, message, exports.RESET);
22
+ };
23
+ exports.logWarning = logWarning;
24
+ /**
25
+ * Logs an info message.
26
+ */
27
+ const logInfo = (message) => {
28
+ // eslint-disable-next-line no-console
29
+ console.info(exports.GREEN, message, exports.RESET);
30
+ };
31
+ exports.logInfo = logInfo;
32
+ //# sourceMappingURL=consoleUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consoleUtils.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/consoleUtils.ts"],"names":[],"mappings":";;;AAAa,QAAA,KAAK,GAAG,SAAS,CAAC;AAClB,QAAA,KAAK,GAAG,UAAU,CAAC;AACnB,QAAA,GAAG,GAAG,UAAU,CAAC;AACjB,QAAA,MAAM,GAAG,UAAU,CAAC;AAEjC;;GAEG;AACI,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE;IAC1C,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAC,WAAG,EAAE,OAAO,EAAE,aAAK,CAAC,CAAC;AACrC,CAAC,CAAC;AAHW,QAAA,QAAQ,YAGnB;AAEF;;GAEG;AACI,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC5C,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAAC,cAAM,EAAE,OAAO,EAAE,aAAK,CAAC,CAAC;AACvC,CAAC,CAAC;AAHW,QAAA,UAAU,cAGrB;AAEF;;GAEG;AACI,MAAM,OAAO,GAAG,CAAC,OAAe,EAAE,EAAE;IACzC,sCAAsC;IACtC,OAAO,CAAC,IAAI,CAAC,aAAK,EAAE,OAAO,EAAE,aAAK,CAAC,CAAC;AACtC,CAAC,CAAC;AAHW,QAAA,OAAO,WAGlB","sourcesContent":["export const RESET = \"\\x1b[0m\";\nexport const GREEN = \"\\x1b[32m\";\nexport const RED = \"\\x1b[31m\";\nexport const YELLOW = \"\\x1b[33m\";\n\n/**\n * Logs an error message and exits the program with a non-zero exit code.\n */\nexport const logError = (message: string) => {\n // eslint-disable-next-line no-console\n console.error(RED, message, RESET);\n};\n\n/**\n * Logs a warning message.\n */\nexport const logWarning = (message: string) => {\n // eslint-disable-next-line no-console\n console.warn(YELLOW, message, RESET);\n};\n\n/**\n * Logs an info message.\n */\nexport const logInfo = (message: string) => {\n // eslint-disable-next-line no-console\n console.info(GREEN, message, RESET);\n};\n"]}
@@ -0,0 +1,9 @@
1
+ import { CustomFieldDefinition } from "@trackunit/iris-app-api";
2
+ /**
3
+ * Updates the custom field definitions with the given app source directory.
4
+ * If the custom field definitions are not provided, it returns an empty array.
5
+ * If the app source directory is not provided, it returns the custom field definitions.
6
+ *
7
+ * @returns {CustomFieldDefinition[]} the updated custom field definitions array
8
+ */
9
+ export declare const updateCustomFields: (customFieldDefinitions?: Array<CustomFieldDefinition>, appSrc?: string) => Array<CustomFieldDefinition>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateCustomFields = void 0;
4
+ const iris_app_api_1 = require("@trackunit/iris-app-api");
5
+ const process_1 = require("process");
6
+ const consoleUtils_1 = require("./consoleUtils");
7
+ const irisAppTranslationUtils_1 = require("./irisAppTranslationUtils");
8
+ /**
9
+ * Updates the custom field definitions with the given app source directory.
10
+ * If the custom field definitions are not provided, it returns an empty array.
11
+ * If the app source directory is not provided, it returns the custom field definitions.
12
+ *
13
+ * @returns {CustomFieldDefinition[]} the updated custom field definitions array
14
+ */
15
+ const updateCustomFields = (customFieldDefinitions, appSrc) => {
16
+ if (!customFieldDefinitions || !appSrc) {
17
+ return [];
18
+ }
19
+ customFieldDefinitions.forEach(customFieldDefinition => {
20
+ if ((0, iris_app_api_1.isCustomFieldTranslationArray)(customFieldDefinition.translations)) {
21
+ const foundEn = customFieldDefinition.translations.find(translation => translation.language === "en");
22
+ if (!foundEn) {
23
+ (0, consoleUtils_1.logError)(` ✨ Translation not found for language "en" you must supply the english translation for custom field: ${customFieldDefinition.key}`);
24
+ (0, process_1.exit)(1);
25
+ }
26
+ }
27
+ else {
28
+ const titles = (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(customFieldDefinition.translations.title, appSrc);
29
+ const descriptions = (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(customFieldDefinition.translations.description, appSrc);
30
+ if (!titles || !descriptions) {
31
+ (0, consoleUtils_1.logError)(` ✨ Translation not found for language "en" you must supply the english translation for custom field: ${customFieldDefinition.key}`);
32
+ (0, process_1.exit)(1);
33
+ }
34
+ const titleKeys = (0, irisAppTranslationUtils_1.isTranslationsObject)(titles)
35
+ ? Object.keys(titles).filter((key) => key in titles)
36
+ : null;
37
+ if (titleKeys !== null && titleKeys.indexOf("en") === -1) {
38
+ (0, consoleUtils_1.logError)(` ✨ Translation not found 'title' for language "en" you must supply the english translation for custom field: ${customFieldDefinition.key}`);
39
+ (0, process_1.exit)(1);
40
+ }
41
+ const descriptionKeys = (0, irisAppTranslationUtils_1.isTranslationsObject)(descriptions)
42
+ ? Object.keys(descriptions).filter((key) => key in descriptions)
43
+ : null;
44
+ if (descriptionKeys !== null && descriptionKeys.indexOf("en") === -1) {
45
+ (0, consoleUtils_1.logError)(` ✨ Translation not found 'description' for language "en" you must supply the english translation for custom field: ${customFieldDefinition.key}`);
46
+ (0, process_1.exit)(1);
47
+ }
48
+ const keys = new Set([...(titleKeys || []), ...(descriptionKeys || [])]);
49
+ const translations = [
50
+ {
51
+ language: "en",
52
+ title: (0, irisAppTranslationUtils_1.isTranslationsObject)(titles) ? titles.en : titles,
53
+ description: (0, irisAppTranslationUtils_1.isTranslationsObject)(descriptions) ? descriptions.en : descriptions,
54
+ },
55
+ ];
56
+ keys.forEach(language => {
57
+ if (language !== "en") {
58
+ translations.push({
59
+ language,
60
+ title: (0, irisAppTranslationUtils_1.isTranslationsObject)(titles) ? titles[language] : titles,
61
+ description: (0, irisAppTranslationUtils_1.isTranslationsObject)(descriptions) ? descriptions[language] : descriptions,
62
+ });
63
+ }
64
+ });
65
+ customFieldDefinition.translations = translations;
66
+ }
67
+ });
68
+ return customFieldDefinitions;
69
+ };
70
+ exports.updateCustomFields = updateCustomFields;
71
+ //# sourceMappingURL=customFieldUtil.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customFieldUtil.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/customFieldUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CustomFieldDefinition,\n CustomFieldTranslationArray,\n isCustomFieldTranslationArray,\n TranslationLanguageKeys,\n} from \"@trackunit/iris-app-api\";\nimport { exit } from \"process\";\nimport { logError } from \"./consoleUtils\";\nimport { convertTranslationKeyIfNeeded, isTranslationsObject } from \"./irisAppTranslationUtils\";\n\n/**\n * Updates the custom field definitions with the given app source directory.\n * If the custom field definitions are not provided, it returns an empty array.\n * If the app source directory is not provided, it returns the custom field definitions.\n *\n * @returns {CustomFieldDefinition[]} the updated custom field definitions array\n */\nexport const updateCustomFields = (\n customFieldDefinitions?: Array<CustomFieldDefinition>,\n appSrc?: string\n): Array<CustomFieldDefinition> => {\n if (!customFieldDefinitions || !appSrc) {\n return [];\n }\n customFieldDefinitions.forEach(customFieldDefinition => {\n if (isCustomFieldTranslationArray(customFieldDefinition.translations)) {\n const foundEn = customFieldDefinition.translations.find(translation => translation.language === \"en\");\n if (!foundEn) {\n logError(\n ` ✨ Translation not found for language \"en\" you must supply the english translation for custom field: ${customFieldDefinition.key}`\n );\n exit(1);\n }\n } else {\n const titles = convertTranslationKeyIfNeeded(customFieldDefinition.translations.title, appSrc);\n const descriptions = convertTranslationKeyIfNeeded(customFieldDefinition.translations.description, appSrc);\n\n if (!titles || !descriptions) {\n logError(\n ` ✨ Translation not found for language \"en\" you must supply the english translation for custom field: ${customFieldDefinition.key}`\n );\n exit(1);\n }\n const titleKeys = isTranslationsObject(titles)\n ? Object.keys(titles).filter((key): key is TranslationLanguageKeys => key in titles)\n : null;\n\n if (titleKeys !== null && titleKeys.indexOf(\"en\") === -1) {\n logError(\n ` ✨ Translation not found 'title' for language \"en\" you must supply the english translation for custom field: ${customFieldDefinition.key}`\n );\n exit(1);\n }\n\n const descriptionKeys = isTranslationsObject(descriptions)\n ? Object.keys(descriptions).filter((key): key is TranslationLanguageKeys => key in descriptions)\n : null;\n\n if (descriptionKeys !== null && descriptionKeys.indexOf(\"en\") === -1) {\n logError(\n ` ✨ Translation not found 'description' for language \"en\" you must supply the english translation for custom field: ${customFieldDefinition.key}`\n );\n exit(1);\n }\n\n const keys = new Set([...(titleKeys || []), ...(descriptionKeys || [])]);\n const translations: CustomFieldTranslationArray = [\n {\n language: \"en\",\n title: isTranslationsObject(titles) ? titles.en : titles,\n description: isTranslationsObject(descriptions) ? descriptions.en : descriptions,\n },\n ];\n\n keys.forEach(language => {\n if (language !== \"en\") {\n translations.push({\n language,\n\n title: isTranslationsObject(titles) ? titles[language]! : titles,\n description: isTranslationsObject(descriptions) ? descriptions[language] : descriptions,\n });\n }\n });\n customFieldDefinition.translations = translations;\n }\n });\n return customFieldDefinitions;\n};\n"]}
@@ -0,0 +1,14 @@
1
+ import { AssetHomeExtensionManifest, FleetExtensionManifest, IrisAppExtension } from "@trackunit/iris-app-api";
2
+ /**
3
+ * Updates the extensions with the correct translation keys and paths
4
+ *
5
+ * @param extensions - The extensions to update
6
+ * @returns { IrisAppExtension[]} The updated extensions
7
+ */
8
+ export declare const updateExtensions: (extensions: Array<IrisAppExtension>) => Array<IrisAppExtension>;
9
+ /**
10
+ * Updates the conditions of the extension
11
+ *
12
+ * @param extension - The extension to update
13
+ */
14
+ export declare const updateConditions: (extension: AssetHomeExtensionManifest | FleetExtensionManifest) => void;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateConditions = exports.updateExtensions = void 0;
4
+ const iris_app_api_1 = require("@trackunit/iris-app-api");
5
+ const irisAppTranslationUtils_1 = require("./irisAppTranslationUtils");
6
+ const fixUrl = (image, extensionId) => {
7
+ if ((0, iris_app_api_1.isIconByPath)(image) || (0, iris_app_api_1.isImageByPath)(image)) {
8
+ if (image.path.toString().startsWith("/")) {
9
+ image.path = (extensionId + image.path.toString());
10
+ }
11
+ else {
12
+ image.path = (extensionId + "/" + image.path.toString());
13
+ }
14
+ }
15
+ };
16
+ /**
17
+ * Updates the extensions with the correct translation keys and paths
18
+ *
19
+ * @param extensions - The extensions to update
20
+ * @returns { IrisAppExtension[]} The updated extensions
21
+ */
22
+ const updateExtensions = (extensions) => {
23
+ extensions.forEach(extension => {
24
+ if (extension.type !== "IRIS_APP_SETTINGS_EXTENSION" &&
25
+ extension.type !== "WIDGET_EXTENSION" &&
26
+ extension.type !== "LIFECYCLE_EXTENSION" &&
27
+ extension.type !== "SERVERLESS_FUNCTION_EXTENSION" &&
28
+ extension.type !== "AI_AGENT_EXTENSION" &&
29
+ extension.menuItem.name) {
30
+ extension.menuItem.name =
31
+ (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(extension.menuItem.name, extension.sourceRoot) || "Unknown";
32
+ }
33
+ if (extension.type === "WIDGET_EXTENSION" && extension.header.name) {
34
+ if ((0, iris_app_api_1.isIconByPath)(extension.header.image) && !extension.header.image.path.startsWith(extension.id)) {
35
+ fixUrl(extension.header.image, extension.id);
36
+ }
37
+ if (extension.footer &&
38
+ ((0, iris_app_api_1.isIconByPath)(extension.footer.poweredByImage) || (0, iris_app_api_1.isImageByPath)(extension.footer.poweredByImage)) &&
39
+ !extension.footer.poweredByImage.path.startsWith(extension.id)) {
40
+ fixUrl(extension.footer.poweredByImage, extension.id);
41
+ }
42
+ if (extension.footer &&
43
+ (0, iris_app_api_1.isFooterWithLink)(extension.footer) &&
44
+ (0, irisAppTranslationUtils_1.isTranslationKey)(extension.footer.linkDescription)) {
45
+ extension.footer.linkDescription = (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(extension.footer.linkDescription, extension.sourceRoot);
46
+ }
47
+ extension.header.name = (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(extension.header.name, extension.sourceRoot) || "Unknown";
48
+ }
49
+ if (extension.type === "REPORT_EXTENSION" && (0, irisAppTranslationUtils_1.isTranslationKey)(extension.menuItem.description)) {
50
+ extension.menuItem.description =
51
+ (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(extension.menuItem.description, extension.sourceRoot) || "Unknown";
52
+ }
53
+ if (extension.type === "ASSET_HOME_EXTENSION" || extension.type === "FLEET_EXTENSION") {
54
+ (0, exports.updateConditions)(extension);
55
+ }
56
+ if (extension.type === "FLEET_EXTENSION") {
57
+ if ((0, iris_app_api_1.isIconByPath)(extension.menuItem.image) && !extension.menuItem.image.path.startsWith(extension.id)) {
58
+ fixUrl(extension.menuItem.image, extension.id);
59
+ }
60
+ if (extension.menuItem.description) {
61
+ extension.menuItem.description = (0, irisAppTranslationUtils_1.convertTranslationKeyIfNeeded)(extension.menuItem.description, extension.sourceRoot);
62
+ }
63
+ }
64
+ });
65
+ return extensions;
66
+ };
67
+ exports.updateExtensions = updateExtensions;
68
+ /**
69
+ * Updates the conditions of the extension
70
+ *
71
+ * @param extension - The extension to update
72
+ */
73
+ const updateConditions = (extension) => {
74
+ if (extension.conditions?.brand) {
75
+ if (Array.isArray(extension.conditions.brand)) {
76
+ extension.conditions.brand.forEach(brand => {
77
+ if (typeof brand !== "string") {
78
+ brand.pattern = brand.pattern.toString();
79
+ }
80
+ });
81
+ }
82
+ else if (typeof extension.conditions.brand !== "string") {
83
+ extension.conditions.brand.pattern = extension.conditions.brand.pattern.toString();
84
+ }
85
+ }
86
+ if (extension.conditions?.model) {
87
+ if (Array.isArray(extension.conditions.model)) {
88
+ extension.conditions.model.forEach(model => {
89
+ if (typeof model !== "string") {
90
+ model.pattern = model.pattern.toString();
91
+ }
92
+ });
93
+ }
94
+ else if (typeof extension.conditions.model !== "string") {
95
+ extension.conditions.model.pattern = extension.conditions.model.pattern.toString();
96
+ }
97
+ }
98
+ if (extension.type === "ASSET_HOME_EXTENSION") {
99
+ const dtCondition = extension.conditions?.telematicsDeviceType;
100
+ if (dtCondition) {
101
+ if (Array.isArray(dtCondition)) {
102
+ dtCondition.forEach(dt => {
103
+ if (typeof dt !== "string") {
104
+ dt.pattern = dt.pattern.toString();
105
+ }
106
+ });
107
+ }
108
+ else if (typeof dtCondition !== "string") {
109
+ dtCondition.pattern = dtCondition.pattern.toString();
110
+ }
111
+ }
112
+ }
113
+ };
114
+ exports.updateConditions = updateConditions;
115
+ //# sourceMappingURL=extensionUtil.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensionUtil.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/extensionUtil.ts"],"names":[],"mappings":";;;AAAA,0DAWiC;AACjC,uEAA4F;AAE5F,MAAM,MAAM,GAAG,CAAC,KAAqD,EAAE,WAAmB,EAAE,EAAE;IAC5F,IAAI,IAAA,2BAAY,EAAC,KAAK,CAAC,IAAI,IAAA,4BAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAiB,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,GAAG,CAAC,WAAW,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAiB,CAAC;QAC3E,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF;;;;;GAKG;AACI,MAAM,gBAAgB,GAAG,CAAC,UAAmC,EAA2B,EAAE;IAC/F,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC7B,IACE,SAAS,CAAC,IAAI,KAAK,6BAA6B;YAChD,SAAS,CAAC,IAAI,KAAK,kBAAkB;YACrC,SAAS,CAAC,IAAI,KAAK,qBAAqB;YACxC,SAAS,CAAC,IAAI,KAAK,+BAA+B;YAClD,SAAS,CAAC,IAAI,KAAK,oBAAoB;YACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,EACvB,CAAC;YACD,SAAS,CAAC,QAAQ,CAAC,IAAI;gBACrB,IAAA,uDAA6B,EAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;QAC9F,CAAC;QAED,IAAI,SAAS,CAAC,IAAI,KAAK,kBAAkB,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACnE,IAAI,IAAA,2BAAY,EAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;gBAClG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;YAC/C,CAAC;YAED,IACE,SAAS,CAAC,MAAM;gBAChB,CAAC,IAAA,2BAAY,EAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,IAAA,4BAAa,EAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gBACjG,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,EAC9D,CAAC;gBACD,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,IACE,SAAS,CAAC,MAAM;gBAChB,IAAA,+BAAgB,EAAC,SAAS,CAAC,MAAM,CAAC;gBAClC,IAAA,0CAAgB,EAAC,SAAS,CAAC,MAAM,CAAC,eAAe,CAAC,EAClD,CAAC;gBACD,SAAS,CAAC,MAAM,CAAC,eAAe,GAAG,IAAA,uDAA6B,EAC9D,SAAS,CAAC,MAAM,CAAC,eAAe,EAChC,SAAS,CAAC,UAAU,CACrB,CAAC;YACJ,CAAC;YACD,SAAS,CAAC,MAAM,CAAC,IAAI,GAAG,IAAA,uDAA6B,EAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;QAClH,CAAC;QAED,IAAI,SAAS,CAAC,IAAI,KAAK,kBAAkB,IAAI,IAAA,0CAAgB,EAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9F,SAAS,CAAC,QAAQ,CAAC,WAAW;gBAC5B,IAAA,uDAA6B,EAAC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;QACrG,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAsB,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACtF,IAAA,wBAAgB,EAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;YACzC,IAAI,IAAA,2BAAY,EAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;gBACtG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,IAAI,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACnC,SAAS,CAAC,QAAQ,CAAC,WAAW,GAAG,IAAA,uDAA6B,EAC5D,SAAS,CAAC,QAAQ,CAAC,WAAW,EAC9B,SAAS,CAAC,UAAU,CACrB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AA3DW,QAAA,gBAAgB,oBA2D3B;AAEF;;;;GAIG;AACI,MAAM,gBAAgB,GAAG,CAAC,SAA8D,EAAE,EAAE;IACjG,IAAI,SAAS,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC3C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC1D,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC;QAChC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBAC3C,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC1D,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;QAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,UAAU,EAAE,oBAAoB,CAAC;QAC/D,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC/B,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;oBACvB,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;wBAC3B,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACrC,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;gBAC3C,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AArCW,QAAA,gBAAgB,oBAqC3B","sourcesContent":["import {\n AssetHomeExtensionManifest,\n FleetExtensionManifest,\n IconByName,\n IconByPath,\n ImageByPath,\n IrisAppExtension,\n isFooterWithLink,\n isIconByPath,\n isImageByPath,\n SvgImagePath,\n} from \"@trackunit/iris-app-api\";\nimport { convertTranslationKeyIfNeeded, isTranslationKey } from \"./irisAppTranslationUtils\";\n\nconst fixUrl = (image: IconByName | IconByPath | ImageByPath | string, extensionId: string) => {\n if (isIconByPath(image) || isImageByPath(image)) {\n if (image.path.toString().startsWith(\"/\")) {\n image.path = (extensionId + image.path.toString()) as SvgImagePath;\n } else {\n image.path = (extensionId + \"/\" + image.path.toString()) as SvgImagePath;\n }\n }\n};\n\n/**\n * Updates the extensions with the correct translation keys and paths\n *\n * @param extensions - The extensions to update\n * @returns { IrisAppExtension[]} The updated extensions\n */\nexport const updateExtensions = (extensions: Array<IrisAppExtension>): Array<IrisAppExtension> => {\n extensions.forEach(extension => {\n if (\n extension.type !== \"IRIS_APP_SETTINGS_EXTENSION\" &&\n extension.type !== \"WIDGET_EXTENSION\" &&\n extension.type !== \"LIFECYCLE_EXTENSION\" &&\n extension.type !== \"SERVERLESS_FUNCTION_EXTENSION\" &&\n extension.type !== \"AI_AGENT_EXTENSION\" &&\n extension.menuItem.name\n ) {\n extension.menuItem.name =\n convertTranslationKeyIfNeeded(extension.menuItem.name, extension.sourceRoot) || \"Unknown\";\n }\n\n if (extension.type === \"WIDGET_EXTENSION\" && extension.header.name) {\n if (isIconByPath(extension.header.image) && !extension.header.image.path.startsWith(extension.id)) {\n fixUrl(extension.header.image, extension.id);\n }\n\n if (\n extension.footer &&\n (isIconByPath(extension.footer.poweredByImage) || isImageByPath(extension.footer.poweredByImage)) &&\n !extension.footer.poweredByImage.path.startsWith(extension.id)\n ) {\n fixUrl(extension.footer.poweredByImage, extension.id);\n }\n if (\n extension.footer &&\n isFooterWithLink(extension.footer) &&\n isTranslationKey(extension.footer.linkDescription)\n ) {\n extension.footer.linkDescription = convertTranslationKeyIfNeeded(\n extension.footer.linkDescription,\n extension.sourceRoot\n );\n }\n extension.header.name = convertTranslationKeyIfNeeded(extension.header.name, extension.sourceRoot) || \"Unknown\";\n }\n\n if (extension.type === \"REPORT_EXTENSION\" && isTranslationKey(extension.menuItem.description)) {\n extension.menuItem.description =\n convertTranslationKeyIfNeeded(extension.menuItem.description, extension.sourceRoot) || \"Unknown\";\n }\n if (extension.type === \"ASSET_HOME_EXTENSION\" || extension.type === \"FLEET_EXTENSION\") {\n updateConditions(extension);\n }\n if (extension.type === \"FLEET_EXTENSION\") {\n if (isIconByPath(extension.menuItem.image) && !extension.menuItem.image.path.startsWith(extension.id)) {\n fixUrl(extension.menuItem.image, extension.id);\n }\n if (extension.menuItem.description) {\n extension.menuItem.description = convertTranslationKeyIfNeeded(\n extension.menuItem.description,\n extension.sourceRoot\n );\n }\n }\n });\n return extensions;\n};\n\n/**\n * Updates the conditions of the extension\n *\n * @param extension - The extension to update\n */\nexport const updateConditions = (extension: AssetHomeExtensionManifest | FleetExtensionManifest) => {\n if (extension.conditions?.brand) {\n if (Array.isArray(extension.conditions.brand)) {\n extension.conditions.brand.forEach(brand => {\n if (typeof brand !== \"string\") {\n brand.pattern = brand.pattern.toString();\n }\n });\n } else if (typeof extension.conditions.brand !== \"string\") {\n extension.conditions.brand.pattern = extension.conditions.brand.pattern.toString();\n }\n }\n if (extension.conditions?.model) {\n if (Array.isArray(extension.conditions.model)) {\n extension.conditions.model.forEach(model => {\n if (typeof model !== \"string\") {\n model.pattern = model.pattern.toString();\n }\n });\n } else if (typeof extension.conditions.model !== \"string\") {\n extension.conditions.model.pattern = extension.conditions.model.pattern.toString();\n }\n }\n if (extension.type === \"ASSET_HOME_EXTENSION\") {\n const dtCondition = extension.conditions?.telematicsDeviceType;\n if (dtCondition) {\n if (Array.isArray(dtCondition)) {\n dtCondition.forEach(dt => {\n if (typeof dt !== \"string\") {\n dt.pattern = dt.pattern.toString();\n }\n });\n } else if (typeof dtCondition !== \"string\") {\n dtCondition.pattern = dtCondition.pattern.toString();\n }\n }\n }\n};\n"]}
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html>
2
+ <html class="notranslate" translate="no" style="height:100dvh;">
3
+ <head>
4
+ <base id="baseHref" href="/" />
5
+ <script defer src="/extensionloader.js"></script>
6
+ <script nonce="{{nonce}}">
7
+ module = location.pathname.split('/')[1];
8
+ scope = "{{scope}}";
9
+ manifestScopes = {{manifestScopes}};
10
+ remoteEntryModuleFormat = "{{remoteEntryModuleFormat}}";
11
+ </script>
12
+ <meta http-equiv="Content-Security-Policy" content="{{cspContent}}" />
13
+ <meta name="referrer" content="strict-origin">
14
+ {{devTools}}
15
+ </head>
16
+ <body class="@container" style="height:100dvh;">
17
+ <div id="single-spa-application:app"></div>
18
+ </body>
19
+ </html>
@@ -0,0 +1,9 @@
1
+ import { IrisAppManifest } from "@trackunit/iris-app-api";
2
+ /**
3
+ * Updates the index.html file with the given manifest and package.json file.
4
+ */
5
+ export declare const updateIndexHtml: ({ manifest, packageJson, devtools, }: {
6
+ manifest: IrisAppManifest;
7
+ packageJson: string;
8
+ devtools?: string;
9
+ }) => string;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateIndexHtml = void 0;
4
+ const iris_app_api_1 = require("@trackunit/iris-app-api");
5
+ const crypto_1 = require("crypto");
6
+ const csp_header_1 = require("csp-header");
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ /**
10
+ * Updates the index.html file with the given manifest and package.json file.
11
+ */
12
+ const updateIndexHtml = ({ manifest, packageJson, devtools, }) => {
13
+ // Try to use the existing updateIndexHtml utility
14
+ const indexHtmlPath = (0, path_1.join)(__dirname, "index.html");
15
+ const indexContents = (0, fs_1.readFileSync)(indexHtmlPath, "utf8");
16
+ const scopeAndModuleNonce = (0, crypto_1.randomBytes)(16).toString("base64");
17
+ const csp = (0, csp_header_1.getCSP)({
18
+ // eslint-disable-next-line local-rules/no-typescript-assertion
19
+ directives: (0, iris_app_api_1.irisAppCspInput)(manifest.validDomains, manifest.cspHeader),
20
+ presets: {
21
+ irisAppDefaultCsp: iris_app_api_1.irisAppDefaultCsp,
22
+ localDev: { "connect-src": ["ws://localhost:8097/"], "script-src": [`'nonce-${scopeAndModuleNonce}'`] },
23
+ },
24
+ });
25
+ const cspWithoutSandbox = csp
26
+ .split(";")
27
+ .filter(substring => !substring.trim().startsWith("sandbox"))
28
+ .join(";");
29
+ let html = indexContents.replace("{{cspContent}}", cspWithoutSandbox);
30
+ html = html.replaceAll("{{devTools}}", devtools ? devtools : "");
31
+ html = html.replaceAll("{{scope}}", JSON.parse(packageJson).name);
32
+ html = html.replaceAll("{{remoteEntryModuleFormat}}", manifest.moduleFormat ?? "cjs");
33
+ if (manifest.scopes) {
34
+ html = html.replaceAll("{{manifestScopes}}", JSON.stringify(manifest.scopes));
35
+ }
36
+ else {
37
+ html = html.replaceAll("{{manifestScopes}}", "undefined");
38
+ }
39
+ // nonce last if anything above injects script tags
40
+ html = html.replaceAll("{{nonce}}", scopeAndModuleNonce);
41
+ return html;
42
+ };
43
+ exports.updateIndexHtml = updateIndexHtml;
44
+ //# sourceMappingURL=indexHtmlUtil.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexHtmlUtil.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/indexHtmlUtil.ts"],"names":[],"mappings":";;;AAAA,0DAA8F;AAC9F,mCAAqC;AACrC,2CAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAE5B;;GAEG;AACI,MAAM,eAAe,GAAG,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,GAKT,EAAE,EAAE;IACH,kDAAkD;IAClD,MAAM,aAAa,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,IAAA,iBAAY,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC1D,MAAM,mBAAmB,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,IAAA,mBAAM,EAAC;QACjB,+DAA+D;QAC/D,UAAU,EAAE,IAAA,8BAAe,EAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,SAAS,CAAuC;QAC5G,OAAO,EAAE;YACP,iBAAiB,EAAjB,gCAAiB;YACjB,QAAQ,EAAE,EAAE,aAAa,EAAE,CAAC,sBAAsB,CAAC,EAAE,YAAY,EAAE,CAAC,UAAU,mBAAmB,GAAG,CAAC,EAAE;SACxG;KACF,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,GAAG;SAC1B,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;SAC5D,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CAAC;IAEtE,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjE,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC;IAClE,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,6BAA6B,EAAE,QAAQ,CAAC,YAAY,IAAI,KAAK,CAAC,CAAC;IACtF,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAChF,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC;IACD,mDAAmD;IACnD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAxCW,QAAA,eAAe,mBAwC1B","sourcesContent":["import { irisAppCspInput, irisAppDefaultCsp, IrisAppManifest } from \"@trackunit/iris-app-api\";\nimport { randomBytes } from \"crypto\";\nimport { getCSP } from \"csp-header\";\nimport { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\n/**\n * Updates the index.html file with the given manifest and package.json file.\n */\nexport const updateIndexHtml = ({\n manifest,\n packageJson,\n devtools,\n}: {\n manifest: IrisAppManifest;\n packageJson: string;\n devtools?: string;\n}) => {\n // Try to use the existing updateIndexHtml utility\n const indexHtmlPath = join(__dirname, \"index.html\");\n const indexContents = readFileSync(indexHtmlPath, \"utf8\");\n const scopeAndModuleNonce = randomBytes(16).toString(\"base64\");\n\n const csp = getCSP({\n // eslint-disable-next-line local-rules/no-typescript-assertion\n directives: irisAppCspInput(manifest.validDomains, manifest.cspHeader) as import(\"csp-header\").CSPDirectives,\n presets: {\n irisAppDefaultCsp,\n localDev: { \"connect-src\": [\"ws://localhost:8097/\"], \"script-src\": [`'nonce-${scopeAndModuleNonce}'`] },\n },\n });\n\n const cspWithoutSandbox = csp\n .split(\";\")\n .filter(substring => !substring.trim().startsWith(\"sandbox\"))\n .join(\";\");\n let html = indexContents.replace(\"{{cspContent}}\", cspWithoutSandbox);\n\n html = html.replaceAll(\"{{devTools}}\", devtools ? devtools : \"\");\n html = html.replaceAll(\"{{scope}}\", JSON.parse(packageJson).name);\n html = html.replaceAll(\"{{remoteEntryModuleFormat}}\", manifest.moduleFormat ?? \"cjs\");\n if (manifest.scopes) {\n html = html.replaceAll(\"{{manifestScopes}}\", JSON.stringify(manifest.scopes));\n } else {\n html = html.replaceAll(\"{{manifestScopes}}\", \"undefined\");\n }\n // nonce last if anything above injects script tags\n html = html.replaceAll(\"{{nonce}}\", scopeAndModuleNonce);\n return html;\n};\n"]}
@@ -0,0 +1,34 @@
1
+ import { TranslationKey, Translations } from "@trackunit/iris-app-api";
2
+ /**
3
+ * Convert translation key if needed
4
+ *
5
+ * @param translationObj - The translation object to convert
6
+ * @param srcDir - The source directory
7
+ */
8
+ export declare const convertTranslationKeyIfNeeded: (translationObj: string | Translations | TranslationKey | null | undefined, srcDir: string) => Translations | string | undefined;
9
+ /**
10
+ * Check if the object is a translation key
11
+ *
12
+ * @param object - The object to check
13
+ * @returns {boolean} if the object is a translation key, false otherwise
14
+ * @example
15
+ * const translationKey: TranslationKey = {
16
+ * key: "hello",
17
+ * };
18
+ * console.log(isTranslationKey(translationKey)); // true
19
+ */
20
+ export declare const isTranslationKey: (object: string | Translations | TranslationKey | undefined | null) => object is TranslationKey;
21
+ /**
22
+ * Check if the object is a translations object
23
+ *
24
+ * @param object - The object to check
25
+ * @returns {boolean} if the object is a translations object, false otherwise
26
+ * @example
27
+ * const translations: Translations = {
28
+ * en: "Hello",
29
+ * da: "Hej",
30
+ * };
31
+ * console.log(isTranslationsObject(translations)); // true
32
+ * console.log(isTranslationsObject({ edn: "Hello" })); // false
33
+ */
34
+ export declare const isTranslationsObject: (object: string | Translations | TranslationKey | undefined | null) => object is Translations;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTranslationsObject = exports.isTranslationKey = exports.convertTranslationKeyIfNeeded = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const iris_app_api_1 = require("@trackunit/iris-app-api");
6
+ const fs = tslib_1.__importStar(require("fs"));
7
+ const path = tslib_1.__importStar(require("path"));
8
+ const process_1 = require("process");
9
+ const consoleUtils_1 = require("./consoleUtils");
10
+ /**
11
+ * Convert translation key if needed
12
+ *
13
+ * @param translationObj - The translation object to convert
14
+ * @param srcDir - The source directory
15
+ */
16
+ const convertTranslationKeyIfNeeded = (translationObj, srcDir) => {
17
+ const result = translationObj;
18
+ if ((0, exports.isTranslationKey)(result)) {
19
+ const translationKey = result.key;
20
+ const enTranslationFilePath = path.join(srcDir, "locales", "en", "translation.json");
21
+ if (!fs.existsSync(enTranslationFilePath)) {
22
+ (0, consoleUtils_1.logError)(` ✨ Translation file not found for: "${result.key}" looked here: ${enTranslationFilePath}`);
23
+ (0, process_1.exit)(1);
24
+ }
25
+ const enTranslations = JSON.parse(fs.readFileSync(enTranslationFilePath, "utf8"));
26
+ if (!enTranslations[translationKey]) {
27
+ (0, consoleUtils_1.logError)(` ✨ Translation not found for: "${result.key}" looked here: ${enTranslationFilePath}`);
28
+ (0, process_1.exit)(1);
29
+ }
30
+ const translations = {
31
+ en: enTranslations[translationKey],
32
+ };
33
+ iris_app_api_1.languageKeys.forEach(languageCode => {
34
+ const translationFilePath = path.join(srcDir, "locales", languageCode, "translation.json");
35
+ if (fs.existsSync(translationFilePath)) {
36
+ const lngTranslations = JSON.parse(fs.readFileSync(translationFilePath, "utf8"));
37
+ translations[languageCode] = lngTranslations[translationKey];
38
+ }
39
+ else {
40
+ (0, consoleUtils_1.logWarning)(` ✨ Warning translation file not found for: "${result.key}" looked here: ${translationFilePath}`);
41
+ }
42
+ });
43
+ return translations;
44
+ }
45
+ return result || undefined;
46
+ };
47
+ exports.convertTranslationKeyIfNeeded = convertTranslationKeyIfNeeded;
48
+ /**
49
+ * Check if the object is a translation key
50
+ *
51
+ * @param object - The object to check
52
+ * @returns {boolean} if the object is a translation key, false otherwise
53
+ * @example
54
+ * const translationKey: TranslationKey = {
55
+ * key: "hello",
56
+ * };
57
+ * console.log(isTranslationKey(translationKey)); // true
58
+ */
59
+ const isTranslationKey = (object) => {
60
+ return typeof object === "object" && object !== null && "key" in object;
61
+ };
62
+ exports.isTranslationKey = isTranslationKey;
63
+ /**
64
+ * Check if the object is a translations object
65
+ *
66
+ * @param object - The object to check
67
+ * @returns {boolean} if the object is a translations object, false otherwise
68
+ * @example
69
+ * const translations: Translations = {
70
+ * en: "Hello",
71
+ * da: "Hej",
72
+ * };
73
+ * console.log(isTranslationsObject(translations)); // true
74
+ * console.log(isTranslationsObject({ edn: "Hello" })); // false
75
+ */
76
+ const isTranslationsObject = (object) => {
77
+ return typeof object === "object" && object !== null && "en" in object;
78
+ };
79
+ exports.isTranslationsObject = isTranslationsObject;
80
+ //# sourceMappingURL=irisAppTranslationUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"irisAppTranslationUtils.js","sourceRoot":"","sources":["../../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/plugin-shared/irisAppTranslationUtils.ts"],"names":[],"mappings":";;;;AAAA,0DAAqF;AACrF,+CAAyB;AACzB,mDAA6B;AAC7B,qCAA+B;AAC/B,iDAAsD;AAEtD;;;;;GAKG;AACI,MAAM,6BAA6B,GAAG,CAC3C,cAAyE,EACzE,MAAc,EACqB,EAAE;IACrC,MAAM,MAAM,GAAG,cAAc,CAAC;IAE9B,IAAI,IAAA,wBAAgB,EAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC;QAElC,MAAM,qBAAqB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACrF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;YAC1C,IAAA,uBAAQ,EAAC,uCAAuC,MAAM,CAAC,GAAG,kBAAkB,qBAAqB,EAAE,CAAC,CAAC;YACrG,IAAA,cAAI,EAAC,CAAC,CAAC,CAAC;QACV,CAAC;QACD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC;YACpC,IAAA,uBAAQ,EAAC,kCAAkC,MAAM,CAAC,GAAG,kBAAkB,qBAAqB,EAAE,CAAC,CAAC;YAChG,IAAA,cAAI,EAAC,CAAC,CAAC,CAAC;QACV,CAAC;QAED,MAAM,YAAY,GAAiB;YACjC,EAAE,EAAE,cAAc,CAAC,cAAc,CAAC;SACnC,CAAC;QAEF,2BAAY,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YAClC,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC;YAC3F,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBACvC,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjF,YAAY,CAAC,YAAY,CAAC,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,IAAA,yBAAU,EAAC,+CAA+C,MAAM,CAAC,GAAG,kBAAkB,mBAAmB,EAAE,CAAC,CAAC;YAC/G,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,MAAM,IAAI,SAAS,CAAC;AAC7B,CAAC,CAAC;AApCW,QAAA,6BAA6B,iCAoCxC;AAEF;;;;;;;;;;GAUG;AACI,MAAM,gBAAgB,GAAG,CAC9B,MAAiE,EACvC,EAAE;IAC5B,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,IAAI,MAAM,CAAC;AAC1E,CAAC,CAAC;AAJW,QAAA,gBAAgB,oBAI3B;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,oBAAoB,GAAG,CAClC,MAAiE,EACzC,EAAE;IAC1B,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC;AACzE,CAAC,CAAC;AAJW,QAAA,oBAAoB,wBAI/B","sourcesContent":["import { languageKeys, TranslationKey, Translations } from \"@trackunit/iris-app-api\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { exit } from \"process\";\nimport { logError, logWarning } from \"./consoleUtils\";\n\n/**\n * Convert translation key if needed\n *\n * @param translationObj - The translation object to convert\n * @param srcDir - The source directory\n */\nexport const convertTranslationKeyIfNeeded = (\n translationObj: string | Translations | TranslationKey | null | undefined,\n srcDir: string\n): Translations | string | undefined => {\n const result = translationObj;\n\n if (isTranslationKey(result)) {\n const translationKey = result.key;\n\n const enTranslationFilePath = path.join(srcDir, \"locales\", \"en\", \"translation.json\");\n if (!fs.existsSync(enTranslationFilePath)) {\n logError(` ✨ Translation file not found for: \"${result.key}\" looked here: ${enTranslationFilePath}`);\n exit(1);\n }\n const enTranslations = JSON.parse(fs.readFileSync(enTranslationFilePath, \"utf8\"));\n if (!enTranslations[translationKey]) {\n logError(` ✨ Translation not found for: \"${result.key}\" looked here: ${enTranslationFilePath}`);\n exit(1);\n }\n\n const translations: Translations = {\n en: enTranslations[translationKey],\n };\n\n languageKeys.forEach(languageCode => {\n const translationFilePath = path.join(srcDir, \"locales\", languageCode, \"translation.json\");\n if (fs.existsSync(translationFilePath)) {\n const lngTranslations = JSON.parse(fs.readFileSync(translationFilePath, \"utf8\"));\n translations[languageCode] = lngTranslations[translationKey];\n } else {\n logWarning(` ✨ Warning translation file not found for: \"${result.key}\" looked here: ${translationFilePath}`);\n }\n });\n return translations;\n }\n return result || undefined;\n};\n\n/**\n * Check if the object is a translation key\n *\n * @param object - The object to check\n * @returns {boolean} if the object is a translation key, false otherwise\n * @example\n * const translationKey: TranslationKey = {\n * key: \"hello\",\n * };\n * console.log(isTranslationKey(translationKey)); // true\n */\nexport const isTranslationKey = (\n object: string | Translations | TranslationKey | undefined | null\n): object is TranslationKey => {\n return typeof object === \"object\" && object !== null && \"key\" in object;\n};\n\n/**\n * Check if the object is a translations object\n *\n * @param object - The object to check\n * @returns {boolean} if the object is a translations object, false otherwise\n * @example\n * const translations: Translations = {\n * en: \"Hello\",\n * da: \"Hej\",\n * };\n * console.log(isTranslationsObject(translations)); // true\n * console.log(isTranslationsObject({ edn: \"Hello\" })); // false\n */\nexport const isTranslationsObject = (\n object: string | Translations | TranslationKey | undefined | null\n): object is Translations => {\n return typeof object === \"object\" && object !== null && \"en\" in object;\n};\n"]}