@softarc/native-federation 4.1.3 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +638 -0
  3. package/dist/config.js +17 -0
  4. package/dist/domain.js +2 -0
  5. package/dist/index.d.ts +10 -0
  6. package/dist/index.js +21 -0
  7. package/{src → dist}/internal.d.ts +6 -7
  8. package/dist/internal.js +26 -0
  9. package/dist/lib/config/configuration-context.js +15 -0
  10. package/dist/lib/config/default-skip-list.js +36 -0
  11. package/dist/lib/config/get-external-imports.d.ts +2 -0
  12. package/dist/lib/config/get-external-imports.js +60 -0
  13. package/dist/lib/config/get-used-dependencies.d.ts +24 -0
  14. package/dist/lib/config/get-used-dependencies.js +126 -0
  15. package/{src/lib/utils → dist/lib/config}/mapped-paths.d.ts +2 -2
  16. package/dist/lib/config/mapped-paths.js +31 -0
  17. package/dist/lib/config/remove-unused-deps.js +11 -0
  18. package/dist/lib/config/share-utils.d.ts +20 -0
  19. package/dist/lib/config/share-utils.js +344 -0
  20. package/dist/lib/config/with-native-federation.js +80 -0
  21. package/{src/lib/core → dist/lib/core/build}/build-adapter.d.ts +1 -1
  22. package/dist/lib/core/build/build-adapter.js +16 -0
  23. package/dist/lib/core/build/build-for-federation.d.ts +4 -0
  24. package/dist/lib/core/build/build-for-federation.js +207 -0
  25. package/{src/lib/utils → dist/lib/core/build}/build-result-map.d.ts +1 -1
  26. package/dist/lib/core/build/build-result-map.js +39 -0
  27. package/dist/lib/core/build/bundle-exposed-and-mappings.d.ts +13 -0
  28. package/dist/lib/core/build/bundle-exposed-and-mappings.js +178 -0
  29. package/dist/lib/core/build/bundle-shared.d.ts +34 -0
  30. package/dist/lib/core/build/bundle-shared.js +261 -0
  31. package/dist/lib/core/build/compute-integrity.d.ts +11 -0
  32. package/dist/lib/core/build/compute-integrity.js +20 -0
  33. package/dist/lib/core/build/default-external-list.js +32 -0
  34. package/dist/lib/core/build/get-externals.d.ts +2 -0
  35. package/dist/lib/core/build/get-externals.js +9 -0
  36. package/dist/lib/core/build/rebuild-for-federation.d.ts +4 -0
  37. package/dist/lib/core/build/rebuild-for-federation.js +52 -0
  38. package/dist/lib/core/build/rewrite-chunk-imports.d.ts +5 -0
  39. package/dist/lib/core/build/rewrite-chunk-imports.js +74 -0
  40. package/dist/lib/core/cache/cache-persistence.d.ts +22 -0
  41. package/dist/lib/core/cache/cache-persistence.js +63 -0
  42. package/{src/lib/core → dist/lib/core/cache}/federation-cache.d.ts +2 -2
  43. package/dist/lib/core/cache/federation-cache.js +22 -0
  44. package/dist/lib/core/federation-builder.js +53 -0
  45. package/{src → dist}/lib/core/normalize-options.d.ts +13 -1
  46. package/dist/lib/core/normalize-options.js +67 -0
  47. package/dist/lib/core/output/write-federation-info.d.ts +5 -0
  48. package/dist/lib/core/output/write-federation-info.js +17 -0
  49. package/dist/lib/core/output/write-import-map.d.ts +11 -0
  50. package/dist/lib/core/output/write-import-map.js +42 -0
  51. package/dist/lib/core/rebuild-queue.js +61 -0
  52. package/{src → dist}/lib/domain/config/external-config.contract.d.ts +2 -2
  53. package/dist/lib/domain/config/external-config.contract.js +0 -0
  54. package/dist/lib/domain/config/federation-config.contract.js +0 -0
  55. package/dist/lib/domain/config/index.js +0 -0
  56. package/dist/lib/domain/config/skip-list.contract.js +0 -0
  57. package/dist/lib/domain/core/build-adapter.contract.js +0 -0
  58. package/dist/lib/domain/core/build-notification-options.contract.js +9 -0
  59. package/dist/lib/domain/core/chunk.js +12 -0
  60. package/dist/lib/domain/core/federation-cache.contract.js +0 -0
  61. package/dist/lib/domain/core/federation-info.contract.js +0 -0
  62. package/dist/lib/domain/core/federation-options.contract.js +0 -0
  63. package/dist/lib/domain/core/index.js +9 -0
  64. package/dist/lib/domain/core/manifest.contract.js +0 -0
  65. package/dist/lib/domain/utils/file-watcher.contract.js +0 -0
  66. package/dist/lib/domain/utils/io-port.contract.d.ts +45 -0
  67. package/dist/lib/domain/utils/io-port.contract.js +0 -0
  68. package/dist/lib/domain/utils/keyvaluepair.contract.js +0 -0
  69. package/dist/lib/domain/utils/mapped-path.contract.js +0 -0
  70. package/dist/lib/domain/utils/package-json.contract.d.ts +27 -0
  71. package/dist/lib/domain/utils/package-json.contract.js +0 -0
  72. package/dist/lib/domain/utils/used-dependencies.contract.js +0 -0
  73. package/dist/lib/utils/errors.js +10 -0
  74. package/{src → dist}/lib/utils/file-watcher.d.ts +2 -0
  75. package/dist/lib/utils/file-watcher.js +51 -0
  76. package/dist/lib/utils/hash-file.d.ts +7 -0
  77. package/dist/lib/utils/hash-file.js +15 -0
  78. package/dist/lib/utils/io/node-io-adapter.d.ts +2 -0
  79. package/dist/lib/utils/io/node-io-adapter.js +68 -0
  80. package/dist/lib/utils/io/package-json-repository.d.ts +5 -0
  81. package/dist/lib/utils/io/package-json-repository.js +79 -0
  82. package/dist/lib/utils/logger.js +29 -0
  83. package/dist/lib/utils/normalize.js +22 -0
  84. package/dist/lib/utils/package/entry-point-resolver.d.ts +2 -0
  85. package/dist/lib/utils/package/entry-point-resolver.js +78 -0
  86. package/dist/lib/utils/package/esm-detection.d.ts +5 -0
  87. package/dist/lib/utils/package/esm-detection.js +10 -0
  88. package/dist/lib/utils/package/exports-resolver.d.ts +13 -0
  89. package/dist/lib/utils/package/exports-resolver.js +55 -0
  90. package/dist/lib/utils/package/package-info.d.ts +7 -0
  91. package/dist/lib/utils/package/package-info.js +31 -0
  92. package/dist/lib/utils/package/resolve-wildcard-keys.d.ts +3 -0
  93. package/dist/lib/utils/package/resolve-wildcard-keys.js +22 -0
  94. package/dist/lib/utils/package/version-maps.d.ts +3 -0
  95. package/dist/lib/utils/package/version-maps.js +8 -0
  96. package/dist/lib/utils/path-patterns.d.ts +14 -0
  97. package/dist/lib/utils/path-patterns.js +28 -0
  98. package/package.json +45 -22
  99. package/src/config.js +0 -4
  100. package/src/domain.js +0 -2
  101. package/src/index.d.ts +0 -10
  102. package/src/index.js +0 -10
  103. package/src/internal.js +0 -11
  104. package/src/lib/config/configuration-context.js +0 -10
  105. package/src/lib/config/default-skip-list.js +0 -31
  106. package/src/lib/config/remove-unused-deps.js +0 -10
  107. package/src/lib/config/share-utils.d.ts +0 -10
  108. package/src/lib/config/share-utils.js +0 -302
  109. package/src/lib/config/with-native-federation.js +0 -79
  110. package/src/lib/core/build-adapter.js +0 -12
  111. package/src/lib/core/build-for-federation.d.ts +0 -4
  112. package/src/lib/core/build-for-federation.js +0 -173
  113. package/src/lib/core/bundle-exposed-and-mappings.d.ts +0 -7
  114. package/src/lib/core/bundle-exposed-and-mappings.js +0 -177
  115. package/src/lib/core/bundle-shared.d.ts +0 -13
  116. package/src/lib/core/bundle-shared.js +0 -222
  117. package/src/lib/core/default-external-list.js +0 -29
  118. package/src/lib/core/federation-builder.js +0 -45
  119. package/src/lib/core/federation-cache.js +0 -16
  120. package/src/lib/core/get-externals.d.ts +0 -2
  121. package/src/lib/core/get-externals.js +0 -6
  122. package/src/lib/core/normalize-options.js +0 -58
  123. package/src/lib/core/rebuild-for-federation.d.ts +0 -4
  124. package/src/lib/core/rebuild-for-federation.js +0 -43
  125. package/src/lib/core/write-federation-info.d.ts +0 -3
  126. package/src/lib/core/write-federation-info.js +0 -6
  127. package/src/lib/core/write-import-map.d.ts +0 -6
  128. package/src/lib/core/write-import-map.js +0 -33
  129. package/src/lib/domain/config/external-config.contract.js +0 -1
  130. package/src/lib/domain/config/federation-config.contract.js +0 -1
  131. package/src/lib/domain/config/index.js +0 -1
  132. package/src/lib/domain/config/skip-list.contract.js +0 -1
  133. package/src/lib/domain/config/with-native-federation.contract.d.ts +0 -2
  134. package/src/lib/domain/config/with-native-federation.contract.js +0 -1
  135. package/src/lib/domain/core/build-adapter.contract.js +0 -1
  136. package/src/lib/domain/core/build-notification-options.contract.js +0 -6
  137. package/src/lib/domain/core/chunk.js +0 -8
  138. package/src/lib/domain/core/federation-cache.contract.js +0 -1
  139. package/src/lib/domain/core/federation-info.contract.js +0 -1
  140. package/src/lib/domain/core/federation-options.contract.js +0 -1
  141. package/src/lib/domain/core/index.js +0 -2
  142. package/src/lib/domain/core/manifest.contract.js +0 -1
  143. package/src/lib/domain/utils/file-watcher.contract.js +0 -1
  144. package/src/lib/domain/utils/index.d.ts +0 -2
  145. package/src/lib/domain/utils/index.js +0 -1
  146. package/src/lib/domain/utils/keyvaluepair.contract.js +0 -1
  147. package/src/lib/domain/utils/mapped-path.contract.js +0 -5
  148. package/src/lib/domain/utils/used-dependencies.contract.js +0 -1
  149. package/src/lib/utils/build-result-map.js +0 -29
  150. package/src/lib/utils/cache-persistence.d.ts +0 -19
  151. package/src/lib/utils/cache-persistence.js +0 -66
  152. package/src/lib/utils/errors.js +0 -7
  153. package/src/lib/utils/file-watcher.js +0 -51
  154. package/src/lib/utils/get-external-imports.d.ts +0 -1
  155. package/src/lib/utils/get-external-imports.js +0 -80
  156. package/src/lib/utils/get-used-dependencies.d.ts +0 -8
  157. package/src/lib/utils/get-used-dependencies.js +0 -123
  158. package/src/lib/utils/hash-file.d.ts +0 -3
  159. package/src/lib/utils/hash-file.js +0 -13
  160. package/src/lib/utils/logger.js +0 -27
  161. package/src/lib/utils/mapped-paths.js +0 -33
  162. package/src/lib/utils/normalize.js +0 -17
  163. package/src/lib/utils/package-info.d.ts +0 -30
  164. package/src/lib/utils/package-info.js +0 -268
  165. package/src/lib/utils/rebuild-queue.js +0 -63
  166. package/src/lib/utils/resolve-glob.d.ts +0 -1
  167. package/src/lib/utils/resolve-glob.js +0 -29
  168. package/src/lib/utils/resolve-wildcard-keys.d.ts +0 -29
  169. package/src/lib/utils/resolve-wildcard-keys.js +0 -126
  170. package/src/lib/utils/rewrite-chunk-imports.d.ts +0 -2
  171. package/src/lib/utils/rewrite-chunk-imports.js +0 -48
  172. /package/{src → dist}/config.d.ts +0 -0
  173. /package/{src → dist}/domain.d.ts +0 -0
  174. /package/{src → dist}/lib/config/configuration-context.d.ts +0 -0
  175. /package/{src → dist}/lib/config/default-skip-list.d.ts +0 -0
  176. /package/{src → dist}/lib/config/remove-unused-deps.d.ts +0 -0
  177. /package/{src → dist}/lib/config/with-native-federation.d.ts +0 -0
  178. /package/{src/lib/core → dist/lib/core/build}/default-external-list.d.ts +0 -0
  179. /package/{src → dist}/lib/core/federation-builder.d.ts +0 -0
  180. /package/{src/lib/utils → dist/lib/core}/rebuild-queue.d.ts +0 -0
  181. /package/{src → dist}/lib/domain/config/federation-config.contract.d.ts +0 -0
  182. /package/{src → dist}/lib/domain/config/index.d.ts +0 -0
  183. /package/{src → dist}/lib/domain/config/skip-list.contract.d.ts +0 -0
  184. /package/{src → dist}/lib/domain/core/build-adapter.contract.d.ts +0 -0
  185. /package/{src → dist}/lib/domain/core/build-notification-options.contract.d.ts +0 -0
  186. /package/{src → dist}/lib/domain/core/chunk.d.ts +0 -0
  187. /package/{src → dist}/lib/domain/core/federation-cache.contract.d.ts +0 -0
  188. /package/{src → dist}/lib/domain/core/federation-info.contract.d.ts +0 -0
  189. /package/{src → dist}/lib/domain/core/federation-options.contract.d.ts +0 -0
  190. /package/{src → dist}/lib/domain/core/index.d.ts +0 -0
  191. /package/{src → dist}/lib/domain/core/manifest.contract.d.ts +0 -0
  192. /package/{src → dist}/lib/domain/utils/file-watcher.contract.d.ts +0 -0
  193. /package/{src → dist}/lib/domain/utils/keyvaluepair.contract.d.ts +0 -0
  194. /package/{src → dist}/lib/domain/utils/mapped-path.contract.d.ts +0 -0
  195. /package/{src → dist}/lib/domain/utils/used-dependencies.contract.d.ts +0 -0
  196. /package/{src → dist}/lib/utils/errors.d.ts +0 -0
  197. /package/{src → dist}/lib/utils/logger.d.ts +0 -0
  198. /package/{src → dist}/lib/utils/normalize.d.ts +0 -0
@@ -1,5 +1,7 @@
1
+ import type { WatchPort, FileReaderPort } from '../domain/utils/io-port.contract.js';
1
2
  import type { NfFileWatcher, NfFileWatcherOptions } from '../domain/utils/file-watcher.contract.js';
2
3
  export declare function createNfWatcher(options?: NfFileWatcherOptions): NfFileWatcher;
4
+ export declare function createNfWatcherCore(io: WatchPort & FileReaderPort, options?: NfFileWatcherOptions): NfFileWatcher;
3
5
  export declare function syncNfFileWatcher(watcher: NfFileWatcher, bundlerCache: {
4
6
  keys(): IterableIterator<string>;
5
7
  }): void;
@@ -0,0 +1,51 @@
1
+ import { join } from "path";
2
+ import { nodeIo } from "./io/node-io-adapter.js";
3
+ import { logger } from "./logger.js";
4
+ import { toPosix } from "./path-patterns.js";
5
+ function createNfWatcher(options = {}) {
6
+ return createNfWatcherCore(nodeIo, options);
7
+ }
8
+ function createNfWatcherCore(io, options = {}) {
9
+ const { onChange } = options;
10
+ const watchers = /* @__PURE__ */ new Map();
11
+ const dirtyPaths = /* @__PURE__ */ new Set();
12
+ const notify = (path) => {
13
+ if (onChange) onChange(path);
14
+ else dirtyPaths.add(path);
15
+ };
16
+ return {
17
+ addPaths(paths) {
18
+ const list = typeof paths === "string" ? [paths] : [...paths];
19
+ for (const p of list) {
20
+ if (watchers.has(p)) continue;
21
+ try {
22
+ const isDir = io.isDirectory(p);
23
+ const handle = isDir ? io.watch(p, { recursive: true }, (filename) => {
24
+ if (filename) notify(toPosix(join(p, filename)));
25
+ }) : io.watch(p, { recursive: false }, () => notify(toPosix(p)));
26
+ watchers.set(p, handle);
27
+ } catch {
28
+ logger.debug(`Could not watch path '${p}'.`);
29
+ }
30
+ }
31
+ },
32
+ get: () => dirtyPaths,
33
+ clear: () => dirtyPaths.clear(),
34
+ mutate: (fn) => fn(dirtyPaths),
35
+ async close() {
36
+ for (const handle of watchers.values()) {
37
+ handle.close();
38
+ }
39
+ watchers.clear();
40
+ }
41
+ };
42
+ }
43
+ function syncNfFileWatcher(watcher, bundlerCache) {
44
+ const files = [...bundlerCache.keys()].filter((k) => !k.includes("node_modules"));
45
+ if (files.length) watcher.addPaths(files);
46
+ }
47
+ export {
48
+ createNfWatcher,
49
+ createNfWatcherCore,
50
+ syncNfFileWatcher
51
+ };
@@ -0,0 +1,7 @@
1
+ import type { FileReaderPort, HashPort } from '../domain/utils/io-port.contract.js';
2
+ export type SriAlgorithm = 'sha256' | 'sha384' | 'sha512';
3
+ type HashDeps = FileReaderPort & HashPort;
4
+ export declare function hashFile(fileName: string): string;
5
+ export declare function hashFileCore(io: HashDeps, fileName: string): string;
6
+ export declare function integrityForFileCore(io: HashDeps, fileName: string, algorithm?: SriAlgorithm): string;
7
+ export {};
@@ -0,0 +1,15 @@
1
+ import { nodeIo } from "./io/node-io-adapter.js";
2
+ function hashFile(fileName) {
3
+ return hashFileCore(nodeIo, fileName);
4
+ }
5
+ function hashFileCore(io, fileName) {
6
+ return io.hash("md5", io.readBytes(fileName)).hex();
7
+ }
8
+ function integrityForFileCore(io, fileName, algorithm = "sha384") {
9
+ return `${algorithm}-${io.hash(algorithm, io.readBytes(fileName)).base64()}`;
10
+ }
11
+ export {
12
+ hashFile,
13
+ hashFileCore,
14
+ integrityForFileCore
15
+ };
@@ -0,0 +1,2 @@
1
+ import type { IoPort } from '../../domain/utils/io-port.contract.js';
2
+ export declare const nodeIo: IoPort;
@@ -0,0 +1,68 @@
1
+ import * as fs from "fs";
2
+ import * as crypto from "crypto";
3
+ import fg from "fast-glob";
4
+ const nodeIo = {
5
+ readText(path) {
6
+ return fs.readFileSync(path, "utf-8");
7
+ },
8
+ readBytes(path) {
9
+ return fs.readFileSync(path);
10
+ },
11
+ exists(path) {
12
+ return fs.existsSync(path);
13
+ },
14
+ isFile(path) {
15
+ try {
16
+ return fs.statSync(path).isFile();
17
+ } catch {
18
+ return false;
19
+ }
20
+ },
21
+ isDirectory(path) {
22
+ try {
23
+ return fs.statSync(path).isDirectory();
24
+ } catch {
25
+ return false;
26
+ }
27
+ },
28
+ readDir(path) {
29
+ try {
30
+ return fs.readdirSync(path);
31
+ } catch {
32
+ return [];
33
+ }
34
+ },
35
+ writeText(path, data) {
36
+ fs.writeFileSync(path, data, "utf-8");
37
+ },
38
+ mkdirp(path) {
39
+ fs.mkdirSync(path, { recursive: true });
40
+ },
41
+ copyFile(from, to) {
42
+ fs.copyFileSync(from, to);
43
+ },
44
+ remove(path) {
45
+ fs.unlinkSync(path);
46
+ },
47
+ globFiles(pattern, opts) {
48
+ return fg.sync(pattern, { cwd: opts.cwd, onlyFiles: true, deep: Infinity });
49
+ },
50
+ hash(algorithm, data) {
51
+ const sum = crypto.createHash(algorithm).update(data);
52
+ return {
53
+ hex: () => sum.digest("hex"),
54
+ base64: () => sum.digest("base64")
55
+ };
56
+ },
57
+ watch(path, opts, onEvent) {
58
+ const watcher = opts.recursive ? fs.watch(
59
+ path,
60
+ { recursive: true },
61
+ (_event, filename) => onEvent(filename ? filename.toString() : null)
62
+ ) : fs.watch(path, () => onEvent(path));
63
+ return { close: () => watcher.close() };
64
+ }
65
+ };
66
+ export {
67
+ nodeIo
68
+ };
@@ -0,0 +1,5 @@
1
+ import type { FileReaderPort } from '../../domain/utils/io-port.contract.js';
2
+ import type { PackageJsonRepository } from '../../domain/utils/package-json.contract.js';
3
+ export declare function getPkgFolder(packageName: string): string;
4
+ export declare function createPackageJsonRepository(io?: FileReaderPort): PackageJsonRepository;
5
+ export declare const sharedPackageJsonRepository: PackageJsonRepository;
@@ -0,0 +1,79 @@
1
+ import * as path from "path";
2
+ import { nodeIo } from "./node-io-adapter.js";
3
+ import { normalize } from "../normalize.js";
4
+ import { logger } from "../logger.js";
5
+ function getPkgFolder(packageName) {
6
+ const parts = packageName.split("/");
7
+ let folder = parts[0];
8
+ if (folder.startsWith("@")) {
9
+ folder += "/" + parts[1];
10
+ }
11
+ return folder;
12
+ }
13
+ function createPackageJsonRepository(io = nodeIo) {
14
+ const cache = /* @__PURE__ */ new Map();
15
+ const readJson = (filePath) => JSON.parse(io.readText(filePath));
16
+ function expandFolders(child, parent) {
17
+ const result = [];
18
+ parent = normalize(parent, true);
19
+ child = normalize(child, true);
20
+ if (!child.startsWith(parent)) {
21
+ throw new Error(
22
+ `Workspace folder ${parent} needs to be a parent of the project folder ${child}`
23
+ );
24
+ }
25
+ let current = child;
26
+ while (current !== parent) {
27
+ result.push(current);
28
+ const cand = normalize(path.dirname(current), true);
29
+ if (cand === current) break;
30
+ current = cand;
31
+ }
32
+ result.push(parent);
33
+ return result;
34
+ }
35
+ function findPackageJsonFiles(project, workspace) {
36
+ return expandFolders(project, workspace).map((f) => path.join(f, "package.json")).filter((f) => io.exists(f));
37
+ }
38
+ function getPackageJsonFiles(project, workspace) {
39
+ const cacheKey = `${project}**${workspace}`;
40
+ const cached = cache.get(cacheKey);
41
+ if (cached) return cached;
42
+ const maps = findPackageJsonFiles(project, workspace).map((f) => ({
43
+ content: readJson(f),
44
+ directory: normalize(path.dirname(f), true)
45
+ }));
46
+ cache.set(cacheKey, maps);
47
+ return maps;
48
+ }
49
+ function findDepPackageJson(packageName, projectRoot) {
50
+ const mainPkgName = getPkgFolder(packageName);
51
+ if (!mainPkgName) throw new Error(`Package.json "${packageName}" is missing`);
52
+ let directory = projectRoot;
53
+ let mainPkgJsonPath = path.join(directory, "node_modules", mainPkgName, "package.json");
54
+ while (path.dirname(directory) !== directory) {
55
+ if (io.exists(mainPkgJsonPath)) break;
56
+ directory = normalize(path.dirname(directory), true);
57
+ mainPkgJsonPath = path.join(directory, "node_modules", mainPkgName, "package.json");
58
+ }
59
+ if (!io.exists(mainPkgJsonPath)) {
60
+ logger.verbose(
61
+ "No package.json found for " + packageName + " in " + path.dirname(mainPkgJsonPath)
62
+ );
63
+ return null;
64
+ }
65
+ return mainPkgJsonPath;
66
+ }
67
+ return {
68
+ getPackageJsonFiles,
69
+ findDepPackageJson,
70
+ readJson,
71
+ exists: (filePath) => io.exists(filePath)
72
+ };
73
+ }
74
+ const sharedPackageJsonRepository = createPackageJsonRepository();
75
+ export {
76
+ createPackageJsonRepository,
77
+ getPkgFolder,
78
+ sharedPackageJsonRepository
79
+ };
@@ -0,0 +1,29 @@
1
+ import chalk from "chalk";
2
+ let verbose = false;
3
+ const debug = (msg) => verbose && console.log(chalk.bgGreen.ansi256(15)(" DBG! "), msg);
4
+ const logger = {
5
+ warn: (msg) => console.warn(chalk.bgYellow.ansi256(15)(" WARN "), msg),
6
+ error: (msg) => console.error(chalk.bgRed.ansi256(15)(" ERRR "), msg),
7
+ notice: (msg) => console.log(chalk.bgYellowBright.black(" NOTE "), msg),
8
+ info: (msg) => console.log(chalk.bgGreen.ansi256(15)(" INFO "), msg),
9
+ verbose: debug,
10
+ // public alias, kept for backwards compatibility
11
+ debug,
12
+ measure: (start, milestone) => {
13
+ if (!verbose) return;
14
+ const [totalSeconds, nanoseconds] = process.hrtime(start);
15
+ const minutes = Math.floor(totalSeconds / 60);
16
+ const seconds = totalSeconds % 60;
17
+ const milliseconds = nanoseconds / 1e6;
18
+ const msFormatted = milliseconds.toFixed(3);
19
+ const timeStr = `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}:${msFormatted.padStart(7, "0")}ms`;
20
+ console.log(chalk.bgGreen.ansi256(15)(" DBG! "), `${timeStr} - ${milestone}`);
21
+ }
22
+ };
23
+ const setLogLevel = (level) => {
24
+ verbose = level === "verbose";
25
+ };
26
+ export {
27
+ logger,
28
+ setLogLevel
29
+ };
@@ -0,0 +1,22 @@
1
+ import { toPosix } from "./path-patterns.js";
2
+ function normalize(path, trailingSlash) {
3
+ let cand = toPosix(path);
4
+ if (typeof trailingSlash === "undefined") {
5
+ return cand;
6
+ }
7
+ while (cand.endsWith("/")) {
8
+ cand = cand.substring(0, cand.length - 1);
9
+ }
10
+ if (trailingSlash) {
11
+ return cand + "/";
12
+ }
13
+ return cand;
14
+ }
15
+ function normalizePackageName(fileName) {
16
+ const sanitized = fileName.replace(/[^A-Za-z0-9]/g, "_");
17
+ return sanitized.startsWith("_") ? sanitized.slice(1) : sanitized;
18
+ }
19
+ export {
20
+ normalize,
21
+ normalizePackageName
22
+ };
@@ -0,0 +1,2 @@
1
+ import type { PackageInfo, PackageJsonRepository } from '../../domain/utils/package-json.contract.js';
2
+ export declare function resolvePackageInfo(repo: PackageJsonRepository, packageName: string, directory: string): PackageInfo | null;
@@ -0,0 +1,78 @@
1
+ import * as path from "path";
2
+ import { logger } from "../logger.js";
3
+ import { findOptimalExport, resolveExportsEntry } from "./exports-resolver.js";
4
+ import { getPkgFolder } from "../io/package-json-repository.js";
5
+ const base = (ctx, entryPoint, esm) => ({
6
+ entryPoint,
7
+ packageName: ctx.packageName,
8
+ version: ctx.version,
9
+ esm
10
+ });
11
+ const STRATEGIES = [
12
+ (ctx) => {
13
+ const entry = resolveExportsEntry(ctx.mainPkgJson?.exports, ctx.relSecondaryPath);
14
+ if (!entry) return null;
15
+ return findOptimalExport(entry, base(ctx, ctx.mainPkgPath, ctx.esm)) ?? null;
16
+ },
17
+ (ctx) => ctx.mainPkgJson["module"] && ctx.relSecondaryPath === "." ? base(ctx, path.join(ctx.mainPkgPath, ctx.mainPkgJson["module"]), true) : null,
18
+ (ctx) => ctx.secondaryPkgJson?.module ? base(ctx, path.join(ctx.secondaryPkgPath, ctx.secondaryPkgJson.module), true) : null,
19
+ (ctx) => {
20
+ const cand = path.join(ctx.secondaryPkgPath, "index.mjs");
21
+ return ctx.repo.exists(cand) ? base(ctx, cand, true) : null;
22
+ },
23
+ (ctx) => ctx.secondaryPkgJson?.main ? base(ctx, path.join(ctx.secondaryPkgPath, ctx.secondaryPkgJson.main), ctx.esm) : null,
24
+ (ctx) => {
25
+ const cand = path.join(ctx.secondaryPkgPath, "index.js");
26
+ return ctx.repo.exists(cand) ? base(ctx, cand, ctx.esm) : null;
27
+ },
28
+ (ctx) => {
29
+ const cand = ctx.secondaryPkgPath + ".js";
30
+ return ctx.repo.exists(cand) ? base(ctx, cand, ctx.esm) : null;
31
+ },
32
+ (ctx) => {
33
+ const cand = ctx.secondaryPkgPath + ".mjs";
34
+ return ctx.repo.exists(cand) ? base(ctx, cand, ctx.esm) : null;
35
+ }
36
+ ];
37
+ function resolvePackageInfo(repo, packageName, directory) {
38
+ const mainPkgName = getPkgFolder(packageName);
39
+ if (!mainPkgName) throw new Error(`Could not resolve "${packageName}" in "${directory}`);
40
+ const mainPkgJsonPath = repo.findDepPackageJson(packageName, directory);
41
+ if (!mainPkgJsonPath) return null;
42
+ const mainPkgPath = path.dirname(mainPkgJsonPath);
43
+ const mainPkgJson = repo.readJson(mainPkgJsonPath);
44
+ const version = mainPkgJson["version"];
45
+ const esm = mainPkgJson["type"] === "module";
46
+ if (!version) {
47
+ logger.warn("No version found for " + packageName);
48
+ return null;
49
+ }
50
+ const pathToSecondary = path.relative(mainPkgName, packageName);
51
+ const relSecondaryPath = !pathToSecondary ? "." : "./" + pathToSecondary.replace(/\\/g, "/");
52
+ const secondaryPkgPath = path.join(mainPkgPath, relSecondaryPath);
53
+ const secondaryPkgJsonPath = path.join(secondaryPkgPath, "package.json");
54
+ const secondaryPkgJson = repo.exists(secondaryPkgJsonPath) ? repo.readJson(secondaryPkgJsonPath) : null;
55
+ const ctx = {
56
+ packageName,
57
+ version,
58
+ esm,
59
+ mainPkgPath,
60
+ mainPkgJson,
61
+ relSecondaryPath,
62
+ secondaryPkgPath,
63
+ secondaryPkgJson,
64
+ repo
65
+ };
66
+ for (const strategy of STRATEGIES) {
67
+ const result = strategy(ctx);
68
+ if (result) return result;
69
+ }
70
+ logger.warn("No entry point found for " + packageName);
71
+ logger.warn(
72
+ "If you don't need this package, skip it in your federation.config.js or consider moving it into depDependencies in your package.json"
73
+ );
74
+ return null;
75
+ }
76
+ export {
77
+ resolvePackageInfo
78
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Classify a package.json `exports` condition key as ESM (`true`), CJS (`false`),
3
+ * or ambiguous (`undefined`).
4
+ */
5
+ export declare const isESMExport: (e: string) => boolean | undefined;
@@ -0,0 +1,10 @@
1
+ const isESMExport = (e) => {
2
+ if (e === "import" || e === "module-sync") return true;
3
+ if (e === "module" || e === "esm" || /^es20\d{2}$/.test(e)) return true;
4
+ if (e === "require") return false;
5
+ if (e === "cjs" || e === "commonjs") return false;
6
+ return void 0;
7
+ };
8
+ export {
9
+ isESMExport
10
+ };
@@ -0,0 +1,13 @@
1
+ import type { ExportEntry, PackageInfo } from '../../domain/utils/package-json.contract.js';
2
+ export declare function replaceGlob(target: ExportEntry, replacement: string): ExportEntry;
3
+ /**
4
+ * Walk an `exports` entry (string, conditions object, or array) to the single
5
+ * best target, preferring ESM. Returns a {@link PackageInfo} with `entryPoint`
6
+ * resolved relative to `info.entryPoint`, or `undefined` when nothing resolves.
7
+ */
8
+ export declare function findOptimalExport(target: ExportEntry, info: PackageInfo, isESM?: boolean | undefined): PackageInfo | undefined;
9
+ /**
10
+ * Find the `exports` field entry matching a secondary subpath (e.g. `./sub`),
11
+ * expanding subpath-pattern (`*`) entries. Returns `undefined` when no key matches.
12
+ */
13
+ export declare function resolveExportsEntry(exports: Record<string, ExportEntry> | undefined, relSecondaryPath: string): ExportEntry;
@@ -0,0 +1,55 @@
1
+ import * as path from "path";
2
+ import { isESMExport } from "./esm-detection.js";
3
+ function replaceGlob(target, replacement) {
4
+ if (!target) return void 0;
5
+ if (typeof target === "string") return target.replace("*", replacement);
6
+ return Object.entries(target).reduce(
7
+ (a, [k, v]) => ({
8
+ ...a,
9
+ [k]: replaceGlob(v, replacement)
10
+ }),
11
+ {}
12
+ );
13
+ }
14
+ function findOptimalExport(target, info, isESM = void 0) {
15
+ if (typeof target === "string") {
16
+ return {
17
+ ...info,
18
+ entryPoint: path.join(info.entryPoint, target),
19
+ esm: isESM ?? info.esm
20
+ };
21
+ }
22
+ if (!target) return void 0;
23
+ if (Array.isArray(target)) return findOptimalExport(target[0], info, isESM);
24
+ const exportTypes = Object.keys(target);
25
+ if (typeof isESM === "undefined") {
26
+ const esmExport = exportTypes.find((e) => isESMExport(e));
27
+ if (esmExport) {
28
+ return findOptimalExport(target[esmExport], info, true);
29
+ }
30
+ }
31
+ const secondBestEntry = "default" in target && target["default"] ? "default" : exportTypes.filter((e) => e !== "types")[0];
32
+ const secondBestExport = target[secondBestEntry];
33
+ return findOptimalExport(secondBestExport, info, isESM ?? isESMExport(secondBestEntry));
34
+ }
35
+ function resolveExportsEntry(exports, relSecondaryPath) {
36
+ const exportsKey = Object.keys(exports ?? {}).find((e) => {
37
+ if (e === relSecondaryPath) return true;
38
+ if (e === "./*") return true;
39
+ if (!e.endsWith("*")) return false;
40
+ const globPath = e.substring(0, e.length - 1);
41
+ return relSecondaryPath.startsWith(globPath);
42
+ });
43
+ if (!exportsKey || !exports) return void 0;
44
+ let entry = exports[exportsKey];
45
+ if (exportsKey.endsWith("*")) {
46
+ const replacement = relSecondaryPath.substring(exportsKey.length - 1);
47
+ entry = replaceGlob(entry, replacement);
48
+ }
49
+ return entry;
50
+ }
51
+ export {
52
+ findOptimalExport,
53
+ replaceGlob,
54
+ resolveExportsEntry
55
+ };
@@ -0,0 +1,7 @@
1
+ import type { PackageInfo, PackageJsonRepository, VersionMap } from '../../domain/utils/package-json.contract.js';
2
+ export { sharedPackageJsonRepository } from '../io/package-json-repository.js';
3
+ export type { PackageInfo, VersionMap, ExportCondition, ExportEntry, } from '../../domain/utils/package-json.contract.js';
4
+ export { isESMExport } from './esm-detection.js';
5
+ export declare function getPackageInfo(packageName: string, workspaceRoot: string, repo?: PackageJsonRepository): PackageInfo | null;
6
+ export declare function getVersionMaps(project: string, workspace: string, repo?: PackageJsonRepository): VersionMap[];
7
+ export declare function findDepPackageJson(packageName: string, projectRoot: string, repo?: PackageJsonRepository): string | null;
@@ -0,0 +1,31 @@
1
+ import { logger } from "../logger.js";
2
+ import { normalize } from "../normalize.js";
3
+ import { sharedPackageJsonRepository } from "../io/package-json-repository.js";
4
+ import { resolvePackageInfo } from "./entry-point-resolver.js";
5
+ import { getVersionMaps as getVersionMapsFromRepo } from "./version-maps.js";
6
+ import { sharedPackageJsonRepository as sharedPackageJsonRepository2 } from "../io/package-json-repository.js";
7
+ import { isESMExport } from "./esm-detection.js";
8
+ function getPackageInfo(packageName, workspaceRoot, repo = sharedPackageJsonRepository) {
9
+ workspaceRoot = normalize(workspaceRoot, true);
10
+ for (const info of repo.getPackageJsonFiles(workspaceRoot, workspaceRoot)) {
11
+ const cand = resolvePackageInfo(repo, packageName, info.directory);
12
+ if (cand) {
13
+ return cand;
14
+ }
15
+ }
16
+ logger.warn("No meta data found for shared lib " + packageName);
17
+ return null;
18
+ }
19
+ function getVersionMaps(project, workspace, repo = sharedPackageJsonRepository) {
20
+ return getVersionMapsFromRepo(repo, project, workspace);
21
+ }
22
+ function findDepPackageJson(packageName, projectRoot, repo = sharedPackageJsonRepository) {
23
+ return repo.findDepPackageJson(packageName, projectRoot);
24
+ }
25
+ export {
26
+ findDepPackageJson,
27
+ getPackageInfo,
28
+ getVersionMaps,
29
+ isESMExport,
30
+ sharedPackageJsonRepository2 as sharedPackageJsonRepository
31
+ };
@@ -0,0 +1,3 @@
1
+ import type { GlobPort } from '../../domain/utils/io-port.contract.js';
2
+ import type { KeyValuePair } from '../../domain/utils/keyvaluepair.contract.js';
3
+ export declare function resolvePackageJsonExportsWildcardCore(io: GlobPort, keyPattern: string, valuePattern: string, cwd: string): KeyValuePair[];
@@ -0,0 +1,22 @@
1
+ import { captureWildcard, parseWildcard, substituteWildcard, toPosix } from "../path-patterns.js";
2
+ function resolvePackageJsonExportsWildcardCore(io, keyPattern, valuePattern, cwd) {
3
+ const pattern = parseWildcard(valuePattern.replace(/^\.?\/+/, ""));
4
+ if (!pattern.hasWildcard) {
5
+ return [];
6
+ }
7
+ const files = io.globFiles(pattern.prefix + "**/*" + pattern.suffix, { cwd });
8
+ const keys = [];
9
+ for (const file of files) {
10
+ const relPath = toPosix(file).replace(/^\.\//, "");
11
+ const captured = captureWildcard(relPath, pattern);
12
+ if (captured === null) continue;
13
+ keys.push({
14
+ key: substituteWildcard(keyPattern, captured),
15
+ value: relPath
16
+ });
17
+ }
18
+ return keys;
19
+ }
20
+ export {
21
+ resolvePackageJsonExportsWildcardCore
22
+ };
@@ -0,0 +1,3 @@
1
+ import type { PackageJsonRepository, VersionMap } from '../../domain/utils/package-json.contract.js';
2
+ /** Extract a `{ name: version }` map from every package.json's `dependencies`. */
3
+ export declare function getVersionMaps(repo: PackageJsonRepository, project: string, workspace: string): VersionMap[];
@@ -0,0 +1,8 @@
1
+ function getVersionMaps(repo, project, workspace) {
2
+ return repo.getPackageJsonFiles(project, workspace).map((json) => ({
3
+ ...json.content["dependencies"]
4
+ }));
5
+ }
6
+ export {
7
+ getVersionMaps
8
+ };
@@ -0,0 +1,14 @@
1
+ export declare const toPosix: (p: string) => string;
2
+ export interface WildcardPattern {
3
+ prefix: string;
4
+ suffix: string;
5
+ hasWildcard: boolean;
6
+ }
7
+ export declare function parseWildcard(pattern: string): WildcardPattern;
8
+ export declare function matchesWildcard(value: string, pattern: string): boolean;
9
+ /**
10
+ * End-anchored capture of the substring matched by `*` (which may span path
11
+ * separators). Returns `null` when `value` does not fit the pattern.
12
+ */
13
+ export declare function captureWildcard(value: string, pattern: WildcardPattern): string | null;
14
+ export declare function substituteWildcard(template: string, captured: string): string;
@@ -0,0 +1,28 @@
1
+ const toPosix = (p) => p.replace(/\\/g, "/");
2
+ function parseWildcard(pattern) {
3
+ const i = pattern.indexOf("*");
4
+ if (i === -1) return { prefix: pattern, suffix: "", hasWildcard: false };
5
+ return { prefix: pattern.slice(0, i), suffix: pattern.slice(i + 1), hasWildcard: true };
6
+ }
7
+ function matchesWildcard(value, pattern) {
8
+ const { prefix, suffix, hasWildcard } = parseWildcard(pattern);
9
+ if (!hasWildcard) return value === pattern;
10
+ return value.startsWith(prefix) && (suffix === "" || value.endsWith(suffix));
11
+ }
12
+ function captureWildcard(value, pattern) {
13
+ const { prefix, suffix, hasWildcard } = pattern;
14
+ if (!hasWildcard) return value === prefix ? "" : null;
15
+ if (!value.startsWith(prefix)) return null;
16
+ if (suffix && !value.endsWith(suffix)) return null;
17
+ return suffix ? value.slice(prefix.length, value.length - suffix.length) : value.slice(prefix.length);
18
+ }
19
+ function substituteWildcard(template, captured) {
20
+ return template.replace("*", captured);
21
+ }
22
+ export {
23
+ captureWildcard,
24
+ matchesWildcard,
25
+ parseWildcard,
26
+ substituteWildcard,
27
+ toPosix
28
+ };