@trackunit/iris-app-build-utilities 1.12.0 → 1.12.7

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,48 @@
1
+ ## 1.12.7 (2026-01-27)
2
+
3
+ ### 🧱 Updated Dependencies
4
+
5
+ - Updated iris-app-api to 1.14.7
6
+ - Updated shared-utils to 1.13.7
7
+
8
+ ## 1.12.6 (2026-01-27)
9
+
10
+ ### 🧱 Updated Dependencies
11
+
12
+ - Updated iris-app-api to 1.14.6
13
+ - Updated shared-utils to 1.13.6
14
+
15
+ ## 1.12.5 (2026-01-27)
16
+
17
+ ### 🧱 Updated Dependencies
18
+
19
+ - Updated iris-app-api to 1.14.5
20
+ - Updated shared-utils to 1.13.5
21
+
22
+ ## 1.12.4 (2026-01-26)
23
+
24
+ ### 🧱 Updated Dependencies
25
+
26
+ - Updated iris-app-api to 1.14.4
27
+
28
+ ## 1.12.3 (2026-01-26)
29
+
30
+ ### 🧱 Updated Dependencies
31
+
32
+ - Updated iris-app-api to 1.14.3
33
+
34
+ ## 1.12.2 (2026-01-26)
35
+
36
+ ### 🧱 Updated Dependencies
37
+
38
+ - Updated iris-app-api to 1.14.2
39
+
40
+ ## 1.12.1 (2026-01-26)
41
+
42
+ ### 🧱 Updated Dependencies
43
+
44
+ - Updated iris-app-api to 1.14.1
45
+
1
46
  ## 1.12.0 (2026-01-26)
2
47
 
3
48
  ### 🚀 Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/iris-app-build-utilities",
3
- "version": "1.12.0",
3
+ "version": "1.12.7",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "repository": "https://github.com/Trackunit/manager",
6
6
  "engines": {
@@ -17,7 +17,11 @@
17
17
  "tslib": "^2.6.2",
18
18
  "csp-header": "^5.2.1",
19
19
  "@rspack/core": "1.6.7",
20
- "@trackunit/iris-app-api": "1.14.0"
20
+ "@trackunit/iris-app-api": "1.14.7",
21
+ "@nx/devkit": "22.0.4",
22
+ "@trackunit/shared-utils": "1.13.7",
23
+ "pacote": "^21.0.4",
24
+ "semver": "7.5.4"
21
25
  },
22
26
  "types": "./src/index.d.ts",
23
27
  "main": "./src/index.js",
@@ -0,0 +1,30 @@
1
+ /**
2
+ *
3
+ * @param pkg package to look for.
4
+ * @param localRange local version of the package.
5
+ * @param range range
6
+ * @returns { boolean } true if its a valid version
7
+ */
8
+ export declare const versionCheck: (pkg: string, localRange: string, range: string, throwError?: boolean) => boolean;
9
+ /**
10
+ * Get the latest version of the package from the registry.
11
+ *
12
+ * @param pkg package to look for.
13
+ * @returns { Promise<string> } returns version
14
+ */
15
+ export declare const getLatestRemoteVersion: (pkg: string) => Promise<string>;
16
+ /**
17
+ * Check if the current version of the package is the same as the one in the manager.
18
+ *
19
+ * @param {string} managerNxVersion version of nx in the manager
20
+ * @returns { boolean} true if its a valid version
21
+ */
22
+ export declare function checkNxVersion(managerNxVersion: string, throwError?: boolean): Promise<boolean>;
23
+ /**
24
+ *
25
+ */
26
+ export declare function checkTrackunitPackages(dependencies: Record<string, string>, throwError?: boolean): Promise<boolean>;
27
+ /**
28
+ *
29
+ */
30
+ export declare function checkPackageVersion(throwError?: boolean): Promise<boolean>;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLatestRemoteVersion = exports.versionCheck = void 0;
4
+ exports.checkNxVersion = checkNxVersion;
5
+ exports.checkTrackunitPackages = checkTrackunitPackages;
6
+ exports.checkPackageVersion = checkPackageVersion;
7
+ const tslib_1 = require("tslib");
8
+ const devkit_1 = require("@nx/devkit");
9
+ const shared_utils_1 = require("@trackunit/shared-utils");
10
+ const child_process_1 = require("child_process");
11
+ const pacote = tslib_1.__importStar(require("pacote"));
12
+ const semver = tslib_1.__importStar(require("semver"));
13
+ /**
14
+ *
15
+ * @param pkg package to look for.
16
+ * @param localRange local version of the package.
17
+ * @param range range
18
+ * @returns { boolean } true if its a valid version
19
+ */
20
+ const versionCheck = (pkg, localRange, range, throwError = true) => {
21
+ const localVersion = semver.minVersion(localRange) ?? localRange; // ('^1.0.0') => '1.0.0'
22
+ const remoteVersion = semver.minVersion(range) ?? range; // Assume range is in a format that semver.minVersion can handle
23
+ if (!semver.satisfies(localVersion, range)) {
24
+ const msg = `Package "${pkg}" outdated. Remote Version: ${range} Local version: ${localRange}. 👈\n Update package using command: \n npm i ${pkg}@${range}\n ...or to update all trackunit dependencies: \n npx npm-check-updates "/@trackunit/" -u`;
25
+ if (semver.major(localVersion) < semver.major(remoteVersion) && throwError) {
26
+ throw new Error(msg);
27
+ }
28
+ else {
29
+ // eslint-disable-next-line no-console
30
+ console.warn("⚠️ " + msg + "\n");
31
+ return true;
32
+ }
33
+ }
34
+ return true;
35
+ };
36
+ exports.versionCheck = versionCheck;
37
+ /**
38
+ * Get the latest version of the package from the registry.
39
+ *
40
+ * @param pkg package to look for.
41
+ * @returns { Promise<string> } returns version
42
+ */
43
+ const getLatestRemoteVersion = async (pkg) => {
44
+ try {
45
+ const manifest = await pacote.manifest(pkg);
46
+ return manifest.version;
47
+ }
48
+ catch (error) {
49
+ throw new Error(`Error fetching manifest for package ${pkg}. This package might need to be published, or it has been included as a dependency by mistake.`);
50
+ }
51
+ };
52
+ exports.getLatestRemoteVersion = getLatestRemoteVersion;
53
+ /**
54
+ * Check if the current version of the package is the same as the one in the manager.
55
+ *
56
+ * @param {string} managerNxVersion version of nx in the manager
57
+ * @returns { boolean} true if its a valid version
58
+ */
59
+ async function checkNxVersion(managerNxVersion, throwError = true) {
60
+ const currentNxVersion = (0, child_process_1.execSync)("nx --version")
61
+ .toString("utf-8")
62
+ .replace(/\r?\n|\r/, ""); // regex removes any line breaks
63
+ return (0, exports.versionCheck)("nx", currentNxVersion, managerNxVersion, throwError);
64
+ }
65
+ /**
66
+ *
67
+ */
68
+ async function checkTrackunitPackages(dependencies, throwError = true) {
69
+ for (const key in dependencies) {
70
+ const remoteVersion = await (0, exports.getLatestRemoteVersion)(key);
71
+ if (remoteVersion) {
72
+ const localDependencyVersion = dependencies[key];
73
+ // If @trackunit dependencies are linked/added locally using "file:", skip the version check, used for E2E tests.
74
+ if (localDependencyVersion && !localDependencyVersion.includes("file:")) {
75
+ (0, exports.versionCheck)(key, localDependencyVersion, remoteVersion, throwError);
76
+ }
77
+ }
78
+ }
79
+ return true;
80
+ }
81
+ function getLibraries() {
82
+ const packageJsonLocal = (0, devkit_1.readJsonFile)("package.json");
83
+ const trackunitDependencies = (0, shared_utils_1.objectFromEntries)(Object.entries(packageJsonLocal.dependencies || {}).filter(([key]) => key.startsWith("@trackunit/")));
84
+ const trackunitDevDependencies = (0, shared_utils_1.objectFromEntries)(Object.entries(packageJsonLocal.devDependencies || {}).filter(([key]) => key.startsWith("@trackunit/")));
85
+ return { trackunitDependencies, trackunitDevDependencies };
86
+ }
87
+ /**
88
+ *
89
+ */
90
+ async function checkPackageVersion(throwError = true) {
91
+ const { trackunitDependencies, trackunitDevDependencies } = getLibraries();
92
+ // const managerNxVersion = version.managerNxVersion;
93
+ // await checkNxVersion(managerNxVersion, throwError);
94
+ await checkTrackunitPackages(trackunitDependencies, throwError);
95
+ await checkTrackunitPackages(trackunitDevDependencies, throwError);
96
+ return true;
97
+ }
98
+ //# sourceMappingURL=checkPackageVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkPackageVersion.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/checkPackageVersion.ts"],"names":[],"mappings":"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","sourcesContent":["import { readJsonFile } from \"@nx/devkit\";\nimport { objectFromEntries } from \"@trackunit/shared-utils\";\nimport { execSync } from \"child_process\";\nimport * as pacote from \"pacote\";\nimport * as semver from \"semver\";\n\n/**\n *\n * @param pkg package to look for.\n * @param localRange local version of the package.\n * @param range range\n * @returns { boolean } true if its a valid version\n */\nexport const versionCheck = (pkg: string, localRange: string, range: string, throwError = true) => {\n const localVersion = semver.minVersion(localRange) ?? localRange; // ('^1.0.0') => '1.0.0'\n const remoteVersion = semver.minVersion(range) ?? range; // Assume range is in a format that semver.minVersion can handle\n\n if (!semver.satisfies(localVersion, range)) {\n const msg = `Package \"${pkg}\" outdated. Remote Version: ${range} Local version: ${localRange}. 👈\\n Update package using command: \\n npm i ${pkg}@${range}\\n ...or to update all trackunit dependencies: \\n npx npm-check-updates \"/@trackunit/\" -u`;\n if (semver.major(localVersion) < semver.major(remoteVersion) && throwError) {\n throw new Error(msg);\n } else {\n // eslint-disable-next-line no-console\n console.warn(\"⚠️ \" + msg + \"\\n\");\n return true;\n }\n }\n return true;\n};\n\n/**\n * Get the latest version of the package from the registry.\n *\n * @param pkg package to look for.\n * @returns { Promise<string> } returns version\n */\nexport const getLatestRemoteVersion = async (pkg: string) => {\n try {\n const manifest = await pacote.manifest(pkg);\n return manifest.version;\n } catch (error) {\n throw new Error(\n `Error fetching manifest for package ${pkg}. This package might need to be published, or it has been included as a dependency by mistake.`\n );\n }\n};\n\n/**\n * Check if the current version of the package is the same as the one in the manager.\n *\n * @param {string} managerNxVersion version of nx in the manager\n * @returns { boolean} true if its a valid version\n */\nexport async function checkNxVersion(managerNxVersion: string, throwError = true) {\n const currentNxVersion = execSync(\"nx --version\")\n .toString(\"utf-8\")\n .replace(/\\r?\\n|\\r/, \"\"); // regex removes any line breaks\n return versionCheck(\"nx\", currentNxVersion, managerNxVersion, throwError);\n}\n\n/**\n *\n */\nexport async function checkTrackunitPackages(dependencies: Record<string, string>, throwError = true) {\n for (const key in dependencies) {\n const remoteVersion: string | undefined = await getLatestRemoteVersion(key);\n if (remoteVersion) {\n const localDependencyVersion: string | undefined = dependencies[key];\n // If @trackunit dependencies are linked/added locally using \"file:\", skip the version check, used for E2E tests.\n if (localDependencyVersion && !localDependencyVersion.includes(\"file:\")) {\n versionCheck(key, localDependencyVersion, remoteVersion, throwError);\n }\n }\n }\n return true;\n}\n\nfunction getLibraries() {\n const packageJsonLocal: Record<string, string | Record<string, string>> = readJsonFile(\"package.json\");\n const trackunitDependencies = objectFromEntries(\n Object.entries(packageJsonLocal.dependencies || {}).filter(([key]) => key.startsWith(\"@trackunit/\"))\n );\n const trackunitDevDependencies = objectFromEntries(\n Object.entries(packageJsonLocal.devDependencies || {}).filter(([key]) => key.startsWith(\"@trackunit/\"))\n );\n return { trackunitDependencies, trackunitDevDependencies };\n}\n\n/**\n *\n */\nexport async function checkPackageVersion(throwError = true) {\n const { trackunitDependencies, trackunitDevDependencies } = getLibraries();\n // const managerNxVersion = version.managerNxVersion;\n // await checkNxVersion(managerNxVersion, throwError);\n await checkTrackunitPackages(trackunitDependencies, throwError);\n await checkTrackunitPackages(trackunitDevDependencies, throwError);\n return true;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Gets the first available port in the specified range.
3
3
  *
4
- * @param minPort min port number inclusive
5
- * @param maxPort max port number inclusive
4
+ * @param minPort min port number inclusive (1024 to avoid reserved ports)
5
+ * @param maxPort max port number inclusive (65535 to avoid reserved ports)
6
6
  * @returns {number} the first available port in the range
7
7
  */
8
8
  export declare const getAvailablePort: (minPort: number, maxPort: number) => Promise<number>;
@@ -3,39 +3,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAvailablePort = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const net = tslib_1.__importStar(require("net"));
6
- const findPort = async (port) => {
6
+ /**
7
+ * Attempts to bind to a port on the specified host.
8
+ * Returns true if successful, false if the port is in use.
9
+ */
10
+ const canBindToPort = (port, host) => {
7
11
  return new Promise(resolve => {
8
12
  const server = net.createServer();
9
- server.once("error", (err) => {
10
- if (err.code === "EADDRINUSE") {
11
- resolve(false);
12
- }
13
- else {
14
- resolve(true);
15
- }
16
- });
17
- server.once("listening", () => {
18
- server.close(() => {
19
- resolve(true);
20
- });
21
- });
22
- server.listen(port);
13
+ server.once("error", () => resolve(false));
14
+ server.once("listening", () => server.close(() => resolve(true)));
15
+ server.listen(port, host);
23
16
  });
24
17
  };
18
+ /**
19
+ * Checks if a port is available on both localhost and all interfaces (0.0.0.0).
20
+ * Both must be available for the port to be considered free.
21
+ */
22
+ const isPortAvailable = async (port) => {
23
+ const availableOnLocalhost = await canBindToPort(port, "localhost");
24
+ if (!availableOnLocalhost) {
25
+ return false;
26
+ }
27
+ const availableOnAllInterfaces = await canBindToPort(port, "0.0.0.0");
28
+ return availableOnAllInterfaces;
29
+ };
25
30
  /**
26
31
  * Gets the first available port in the specified range.
27
32
  *
28
- * @param minPort min port number inclusive
29
- * @param maxPort max port number inclusive
33
+ * @param minPort min port number inclusive (1024 to avoid reserved ports)
34
+ * @param maxPort max port number inclusive (65535 to avoid reserved ports)
30
35
  * @returns {number} the first available port in the range
31
36
  */
32
37
  const getAvailablePort = async (minPort, maxPort) => {
33
- if (minPort < 1 || maxPort > 65535 || minPort > maxPort) {
38
+ if (minPort < 1023 || maxPort > 65535 || minPort > maxPort) {
34
39
  throw new Error("Invalid port range.");
35
40
  }
36
41
  for (let port = minPort; port <= maxPort; port++) {
37
- const isAvailable = await findPort(port);
38
- if (isAvailable) {
42
+ const available = await isPortAvailable(port);
43
+ if (available) {
39
44
  return port;
40
45
  }
41
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getAvailablePort.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getAvailablePort.ts"],"names":[],"mappings":";;;;AAAA,iDAA2B;AAE3B,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IACxD,OAAO,IAAI,OAAO,CAAU,OAAO,CAAC,EAAE;QACpC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAqB,EAAE,EAAE;YAC7C,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBAChB,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAe,EAAE,OAAe,EAAmB,EAAE;IAC1F,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,KAAK,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,IAAI,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;AAChE,CAAC,CAAC;AAbW,QAAA,gBAAgB,oBAa3B","sourcesContent":["import * as net from \"net\";\n\nconst findPort = async (port: number): Promise<boolean> => {\n return new Promise<boolean>(resolve => {\n const server = net.createServer();\n server.once(\"error\", (err: { code: string }) => {\n if (err.code === \"EADDRINUSE\") {\n resolve(false);\n } else {\n resolve(true);\n }\n });\n\n server.once(\"listening\", () => {\n server.close(() => {\n resolve(true);\n });\n });\n\n server.listen(port);\n });\n};\n\n/**\n * Gets the first available port in the specified range.\n *\n * @param minPort min port number inclusive\n * @param maxPort max port number inclusive\n * @returns {number} the first available port in the range\n */\nexport const getAvailablePort = async (minPort: number, maxPort: number): Promise<number> => {\n if (minPort < 1 || maxPort > 65535 || minPort > maxPort) {\n throw new Error(\"Invalid port range.\");\n }\n\n for (let port = minPort; port <= maxPort; port++) {\n const isAvailable = await findPort(port);\n if (isAvailable) {\n return port;\n }\n }\n\n throw new Error(\"No available ports in the specified range.\");\n};\n"]}
1
+ {"version":3,"file":"getAvailablePort.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getAvailablePort.ts"],"names":[],"mappings":";;;;AAAA,iDAA2B;AAE3B;;;GAGG;AACH,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,IAAY,EAAoB,EAAE;IACrE,OAAO,IAAI,OAAO,CAAU,OAAO,CAAC,EAAE;QACpC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAElE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,eAAe,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IAC/D,MAAM,oBAAoB,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACpE,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,wBAAwB,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACtE,OAAO,wBAAwB,CAAC;AAClC,CAAC,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAe,EAAE,OAAe,EAAmB,EAAE;IAC1F,IAAI,OAAO,GAAG,IAAI,IAAI,OAAO,GAAG,KAAK,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,IAAI,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;AAChE,CAAC,CAAC;AAbW,QAAA,gBAAgB,oBAa3B","sourcesContent":["import * as net from \"net\";\n\n/**\n * Attempts to bind to a port on the specified host.\n * Returns true if successful, false if the port is in use.\n */\nconst canBindToPort = (port: number, host: string): Promise<boolean> => {\n return new Promise<boolean>(resolve => {\n const server = net.createServer();\n\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => server.close(() => resolve(true)));\n\n server.listen(port, host);\n });\n};\n\n/**\n * Checks if a port is available on both localhost and all interfaces (0.0.0.0).\n * Both must be available for the port to be considered free.\n */\nconst isPortAvailable = async (port: number): Promise<boolean> => {\n const availableOnLocalhost = await canBindToPort(port, \"localhost\");\n if (!availableOnLocalhost) {\n return false;\n }\n\n const availableOnAllInterfaces = await canBindToPort(port, \"0.0.0.0\");\n return availableOnAllInterfaces;\n};\n\n/**\n * Gets the first available port in the specified range.\n *\n * @param minPort min port number inclusive (1024 to avoid reserved ports)\n * @param maxPort max port number inclusive (65535 to avoid reserved ports)\n * @returns {number} the first available port in the range\n */\nexport const getAvailablePort = async (minPort: number, maxPort: number): Promise<number> => {\n if (minPort < 1023 || maxPort > 65535 || minPort > maxPort) {\n throw new Error(\"Invalid port range.\");\n }\n\n for (let port = minPort; port <= maxPort; port++) {\n const available = await isPortAvailable(port);\n if (available) {\n return port;\n }\n }\n\n throw new Error(\"No available ports in the specified range.\");\n};\n"]}
@@ -75,10 +75,12 @@ const getServersideExtensionPatterns = (options) => {
75
75
  ];
76
76
  // Check if extension has dependencyDefinitionFile and add it to patterns if it exists
77
77
  if ("dependencyDefinitionFile" in extension && extension.dependencyDefinitionFile) {
78
+ const dependencyFileName = path.basename(extension.dependencyDefinitionFile);
78
79
  patterns.push({
79
80
  // globs must use / in path to be valid
80
81
  from: path.resolve(nxRootDir, extension.dependencyDefinitionFile.replace(/\\/g, "/")),
81
- to: path.join(nxRootDir, "dist", relativeAppDir, "serverside", extension.id),
82
+ // Must specify full file path (not just directory) for copyFileSync
83
+ to: path.join(nxRootDir, "dist", relativeAppDir, "serverside", extension.id, dependencyFileName),
82
84
  });
83
85
  }
84
86
  return patterns;
@@ -96,6 +98,20 @@ const getAssetsPattern = (options) => {
96
98
  to: path.join(nxRootDir, "dist", relativeAppDir, "assets"),
97
99
  };
98
100
  };
101
+ /**
102
+ * Strips the extensionId prefix from a path if present.
103
+ * The updateExtensions function in extensionUtil.ts modifies image.path to include
104
+ * the extensionId prefix for runtime loading, but we need the original path for copying.
105
+ */
106
+ const stripExtensionIdPrefix = (iconPath, extensionId) => {
107
+ if (iconPath.startsWith(extensionId + "/")) {
108
+ return iconPath.substring(extensionId.length + 1);
109
+ }
110
+ if (iconPath.startsWith(extensionId)) {
111
+ return iconPath.substring(extensionId.length);
112
+ }
113
+ return iconPath;
114
+ };
99
115
  /**
100
116
  * Generates copy patterns for extension icons (fleet menu icons and widget icons).
101
117
  */
@@ -105,11 +121,18 @@ const getIconPatterns = (options) => {
105
121
  const fleetIconPaths = getFleetExtensionIconPaths(manifest);
106
122
  const widgetIconPaths = getWidgetExtensionIconPaths(manifest);
107
123
  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
- }));
124
+ return allIconPaths.map(iconPath => {
125
+ // The path may have been modified to include extensionId prefix by updateExtensions.
126
+ // We need the original path (without prefix) for the source file location.
127
+ const originalPath = stripExtensionIdPrefix(iconPath.path, iconPath.extensionId);
128
+ return {
129
+ // Source file is at sourceRoot/originalPath (without extensionId prefix)
130
+ // globs must use / in path to be valid
131
+ from: path.join(nxRootDir, iconPath.sourceRoot, originalPath).replace(/\\/g, "/"),
132
+ // Destination is at dist/appDir/extensionId/originalPath
133
+ to: path.join(nxRootDir, "dist", relativeAppDir, iconPath.extensionId, originalPath),
134
+ };
135
+ });
113
136
  };
114
137
  /**
115
138
  * Gets all copy patterns for an Iris app build.
@@ -1 +1 @@
1
- {"version":3,"file":"getCopyPatterns.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getCopyPatterns.ts"],"names":[],"mappings":"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","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"]}
1
+ {"version":3,"file":"getCopyPatterns.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/getCopyPatterns.ts"],"names":[],"mappings":"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","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 const dependencyFileName = path.basename(extension.dependencyDefinitionFile);\n patterns.push({\n // globs must use / in path to be valid\n from: path.resolve(nxRootDir, extension.dependencyDefinitionFile.replace(/\\\\/g, \"/\")),\n // Must specify full file path (not just directory) for copyFileSync\n to: path.join(nxRootDir, \"dist\", relativeAppDir, \"serverside\", extension.id, dependencyFileName),\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 * Strips the extensionId prefix from a path if present.\n * The updateExtensions function in extensionUtil.ts modifies image.path to include\n * the extensionId prefix for runtime loading, but we need the original path for copying.\n */\nconst stripExtensionIdPrefix = (iconPath: string, extensionId: string): string => {\n if (iconPath.startsWith(extensionId + \"/\")) {\n return iconPath.substring(extensionId.length + 1);\n }\n if (iconPath.startsWith(extensionId)) {\n return iconPath.substring(extensionId.length);\n }\n return iconPath;\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 // The path may have been modified to include extensionId prefix by updateExtensions.\n // We need the original path (without prefix) for the source file location.\n const originalPath = stripExtensionIdPrefix(iconPath.path, iconPath.extensionId);\n\n return {\n // Source file is at sourceRoot/originalPath (without extensionId prefix)\n // globs must use / in path to be valid\n from: path.join(nxRootDir, iconPath.sourceRoot, originalPath).replace(/\\\\/g, \"/\"),\n // Destination is at dist/appDir/extensionId/originalPath\n to: path.join(nxRootDir, \"dist\", relativeAppDir, iconPath.extensionId, originalPath),\n };\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"]}
package/src/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./checkPackageVersion";
1
2
  export * from "./enableTsConfigPath";
2
3
  export * from "./getAliasesFromTsConfig";
3
4
  export * from "./getAvailablePort";
package/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./checkPackageVersion"), exports);
4
5
  tslib_1.__exportStar(require("./enableTsConfigPath"), exports);
5
6
  tslib_1.__exportStar(require("./getAliasesFromTsConfig"), exports);
6
7
  tslib_1.__exportStar(require("./getAvailablePort"), exports);
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,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"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,+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 \"./checkPackageVersion\";\nexport * 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,4 @@
1
+ export declare const version: {
2
+ managerNxVersion: string;
3
+ managerNodeVersion: string;
4
+ };
package/src/version.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.version = void 0;
4
+ // The major version of NX and Node specified here will be matched with corresponding versions in the iris app.
5
+ exports.version = {
6
+ managerNxVersion: "^19.8.3",
7
+ managerNodeVersion: "^22.14.0",
8
+ };
9
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../../../libs/iris-app-sdk/iris-app-build-utilities/src/version.ts"],"names":[],"mappings":";;;AAAA,+GAA+G;AAClG,QAAA,OAAO,GAAG;IACrB,gBAAgB,EAAE,SAAS;IAC3B,kBAAkB,EAAE,UAAU;CAC/B,CAAC","sourcesContent":["// The major version of NX and Node specified here will be matched with corresponding versions in the iris app.\nexport const version = {\n managerNxVersion: \"^19.8.3\",\n managerNodeVersion: \"^22.14.0\",\n};\n\n"]}