@softarc/native-federation-orchestrator 4.1.1 → 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.
@@ -0,0 +1,92 @@
1
+ // src/node-loader.ts
2
+ var EMPTY_MAP = Object.freeze({ imports: {}, scopes: {} });
3
+ var baseURL = (() => {
4
+ const cwd = process.cwd();
5
+ const url = new URL("file://");
6
+ url.pathname = cwd.endsWith("/") ? cwd : cwd + "/";
7
+ return url.href.endsWith("/") ? url.href : url.href + "/";
8
+ })();
9
+ var activeMap = EMPTY_MAP;
10
+ function initialize(data = {}) {
11
+ if (data.initialImportMap) {
12
+ activeMap = normalize(data.initialImportMap);
13
+ }
14
+ if (data.port) {
15
+ data.port.on("message", (msg) => {
16
+ if (msg && msg.type === "set-import-map") {
17
+ activeMap = normalize(msg.map);
18
+ data.port.postMessage({ type: "import-map-applied" });
19
+ }
20
+ });
21
+ data.port.unref?.();
22
+ }
23
+ }
24
+ async function resolve(specifier, context, nextResolve) {
25
+ const mapped = resolveSpecifier(activeMap, specifier, context.parentURL);
26
+ return nextResolve(mapped ?? specifier, context);
27
+ }
28
+ async function load(url, context, nextLoad) {
29
+ if (url.startsWith("http://") || url.startsWith("https://")) {
30
+ const res = await fetch(url);
31
+ if (!res.ok) {
32
+ throw new Error(`Failed to fetch module from ${url}: ${res.status} ${res.statusText}`);
33
+ }
34
+ const source = await res.text();
35
+ return { shortCircuit: true, format: "module", source };
36
+ }
37
+ if (!url.startsWith("node:")) {
38
+ context.format = "module";
39
+ }
40
+ return nextLoad(url, context);
41
+ }
42
+ function resolveSpecifier(map, specifier, parentURL) {
43
+ const currentBaseURL = parentURL ? parentURL.slice(0, parentURL.lastIndexOf("/") + 1) : baseURL;
44
+ const normalizedSpecifier = parseURLLikeSpecifier(specifier, currentBaseURL) ?? specifier;
45
+ if (map.scopes) {
46
+ for (const scopePrefix in map.scopes) {
47
+ if (scopePrefix === currentBaseURL || scopePrefix.endsWith("/") && currentBaseURL.startsWith(scopePrefix)) {
48
+ const match = resolveImportsMatch(normalizedSpecifier, map.scopes[scopePrefix]);
49
+ if (match) return match;
50
+ }
51
+ }
52
+ }
53
+ return resolveImportsMatch(normalizedSpecifier, map.imports);
54
+ }
55
+ function resolveImportsMatch(normalizedSpecifier, specifierMap) {
56
+ for (const specifierKey in specifierMap) {
57
+ const resolutionResult = specifierMap[specifierKey];
58
+ if (resolutionResult === void 0) continue;
59
+ if (specifierKey === normalizedSpecifier) return resolutionResult;
60
+ if (specifierKey.endsWith("/") && normalizedSpecifier.startsWith(specifierKey)) {
61
+ const afterPrefix = normalizedSpecifier.slice(specifierKey.length);
62
+ try {
63
+ return new URL(afterPrefix, resolutionResult).href;
64
+ } catch {
65
+ throw new TypeError(
66
+ `import-map resolution of '${specifierKey}' failed due to URL parse failure`
67
+ );
68
+ }
69
+ }
70
+ }
71
+ return null;
72
+ }
73
+ function parseURLLikeSpecifier(specifier, base) {
74
+ const useBase = specifier.startsWith("/") || specifier.startsWith("./") || specifier.startsWith("../");
75
+ try {
76
+ return new URL(specifier, useBase ? base : void 0).href;
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+ function normalize(parsed) {
82
+ return {
83
+ imports: parsed.imports ?? {},
84
+ scopes: parsed.scopes ?? {}
85
+ };
86
+ }
87
+ export {
88
+ initialize,
89
+ load,
90
+ resolve
91
+ };
92
+ //# sourceMappingURL=loader.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/node-loader.ts"],
4
+ "sourcesContent": ["/**\n * Node.js module customization hooks for native-federation.\n *\n * Registered via `module.register(<this file>, import.meta.url, { data: { port }, transferList: [port] })`\n * from the orchestrator. The main thread posts the resolved import map over the\n * MessagePort whenever it changes; this loader rewrites `import` specifiers\n * accordingly and fetches http(s) modules into the loader as source text.\n */\n\nimport type { MessagePort } from 'node:worker_threads';\n\ntype Imports = Record<string, string>;\ntype Scopes = Record<string, Imports>;\ntype ImportMap = { imports: Imports; scopes?: Scopes };\n\ntype InitData = {\n port?: MessagePort;\n initialImportMap?: ImportMap;\n};\n\nconst EMPTY_MAP: ImportMap = Object.freeze({ imports: {}, scopes: {} });\n\nconst baseURL = (() => {\n const cwd = process.cwd();\n const url = new URL('file://');\n url.pathname = cwd.endsWith('/') ? cwd : cwd + '/';\n return url.href.endsWith('/') ? url.href : url.href + '/';\n})();\n\nlet activeMap: ImportMap = EMPTY_MAP;\n\nexport function initialize(data: InitData = {}): void {\n if (data.initialImportMap) {\n activeMap = normalize(data.initialImportMap);\n }\n if (data.port) {\n data.port.on('message', (msg: { type: 'set-import-map'; map: ImportMap }) => {\n if (msg && msg.type === 'set-import-map') {\n activeMap = normalize(msg.map);\n data.port!.postMessage({ type: 'import-map-applied' });\n }\n });\n data.port.unref?.();\n }\n}\n\ntype ResolveContext = { parentURL?: string };\ntype ResolveResult = { url: string; format?: string | null; shortCircuit?: boolean };\ntype NextResolve = (specifier: string, context?: ResolveContext) => Promise<ResolveResult>;\n\nexport async function resolve(\n specifier: string,\n context: ResolveContext,\n nextResolve: NextResolve\n): Promise<ResolveResult> {\n const mapped = resolveSpecifier(activeMap, specifier, context.parentURL);\n return nextResolve(mapped ?? specifier, context);\n}\n\ntype LoadContext = { format?: string | null };\ntype LoadResult = {\n format: string;\n source?: string | ArrayBuffer | Uint8Array;\n shortCircuit?: boolean;\n};\ntype NextLoad = (url: string, context?: LoadContext) => Promise<LoadResult>;\n\nexport async function load(\n url: string,\n context: LoadContext,\n nextLoad: NextLoad\n): Promise<LoadResult> {\n if (url.startsWith('http://') || url.startsWith('https://')) {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`Failed to fetch module from ${url}: ${res.status} ${res.statusText}`);\n }\n const source = await res.text();\n return { shortCircuit: true, format: 'module', source };\n }\n if (!url.startsWith('node:')) {\n context.format = 'module';\n }\n return nextLoad(url, context);\n}\n\n// --- WICG import-map resolve algorithm ------------------------------------\n// https://wicg.github.io/import-maps/#new-resolve-algorithm\n\nfunction resolveSpecifier(map: ImportMap, specifier: string, parentURL?: string): string | null {\n const currentBaseURL = parentURL ? parentURL.slice(0, parentURL.lastIndexOf('/') + 1) : baseURL;\n const normalizedSpecifier = parseURLLikeSpecifier(specifier, currentBaseURL) ?? specifier;\n\n if (map.scopes) {\n for (const scopePrefix in map.scopes) {\n if (\n scopePrefix === currentBaseURL ||\n (scopePrefix.endsWith('/') && currentBaseURL.startsWith(scopePrefix))\n ) {\n const match = resolveImportsMatch(normalizedSpecifier, map.scopes[scopePrefix]!);\n if (match) return match;\n }\n }\n }\n\n return resolveImportsMatch(normalizedSpecifier, map.imports);\n}\n\nfunction resolveImportsMatch(normalizedSpecifier: string, specifierMap: Imports): string | null {\n for (const specifierKey in specifierMap) {\n const resolutionResult = specifierMap[specifierKey];\n if (resolutionResult === undefined) continue;\n\n if (specifierKey === normalizedSpecifier) return resolutionResult;\n\n if (specifierKey.endsWith('/') && normalizedSpecifier.startsWith(specifierKey)) {\n const afterPrefix = normalizedSpecifier.slice(specifierKey.length);\n try {\n return new URL(afterPrefix, resolutionResult).href;\n } catch {\n throw new TypeError(\n `import-map resolution of '${specifierKey}' failed due to URL parse failure`\n );\n }\n }\n }\n return null;\n}\n\nfunction parseURLLikeSpecifier(specifier: string, base: string): string | null {\n const useBase =\n specifier.startsWith('/') || specifier.startsWith('./') || specifier.startsWith('../');\n try {\n return new URL(specifier, useBase ? base : undefined).href;\n } catch {\n return null;\n }\n}\n\nfunction normalize(parsed: ImportMap): ImportMap {\n return {\n imports: parsed.imports ?? {},\n scopes: parsed.scopes ?? {},\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.1.1",
2
+ "version": "4.2.0",
3
3
  "name": "@softarc/native-federation-orchestrator",
4
4
  "author": "Aukevanoost",
5
5
  "keywords": [
@@ -12,11 +12,12 @@
12
12
  "url": "https://github.com/native-federation/orchestrator.git"
13
13
  },
14
14
  "pnpm": {
15
- "overrides": {
16
- "js-yaml": ">=4.1.1"
17
- }
15
+ "overrides": {}
18
16
  },
19
17
  "license": "MIT",
18
+ "engines": {
19
+ "node": ">=20.6.0"
20
+ },
20
21
  "sideEffects": false,
21
22
  "dependencies": {
22
23
  "semver": "^7.7.1"
@@ -50,6 +51,13 @@
50
51
  "./audit": {
51
52
  "types": "./types/lib/audit.index.d.ts",
52
53
  "default": "./fesm2022/audit.mjs"
54
+ },
55
+ "./node": {
56
+ "types": "./types/lib/node.index.d.ts",
57
+ "default": "./fesm2022/node.mjs"
58
+ },
59
+ "./node-loader/loader.mjs": {
60
+ "default": "./node-loader/loader.mjs"
53
61
  }
54
62
  },
55
63
  "typings": "./types/lib/index.d.ts",