@softarc/native-federation 4.2.0 → 4.3.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.
@@ -1,240 +1,48 @@
1
1
  import * as path from "path";
2
- import { cwd } from "process";
3
2
  import { DEFAULT_SKIP_LIST, isInSkipList, prepareSkipList } from "./default-skip-list.js";
4
3
  import {
5
4
  sharedPackageJsonRepository,
6
5
  findDepPackageJson,
7
6
  getVersionMaps
8
7
  } from "../utils/package/package-info.js";
9
- import { getConfigContext } from "./configuration-context.js";
10
8
  import { logger } from "../utils/logger.js";
11
9
  import { nodeIo } from "../utils/io/node-io-adapter.js";
12
- import { resolvePackageJsonExportsWildcardCore } from "../utils/package/resolve-wildcard-keys.js";
13
- let inferVersion = false;
14
- function findRootTsConfigJson() {
15
- return findRootTsConfigJsonCore(nodeIo);
16
- }
17
- function findRootTsConfigJsonCore(io) {
18
- const packageJson = findPackageJson(io, cwd());
19
- const projectRoot = path.dirname(packageJson);
20
- const tsConfigBaseJson = path.join(projectRoot, "tsconfig.base.json");
21
- const tsConfigJson = path.join(projectRoot, "tsconfig.json");
22
- if (io.exists(tsConfigBaseJson)) {
23
- return tsConfigBaseJson;
24
- } else if (io.exists(tsConfigJson)) {
25
- return tsConfigJson;
26
- }
27
- throw new Error("Neither a tsconfig.json nor a tsconfig.base.json was found");
28
- }
29
- function findPackageJson(io, folder) {
30
- while (!io.exists(path.join(folder, "package.json")) && path.dirname(folder) !== folder) {
31
- folder = path.dirname(folder);
32
- }
33
- const filePath = path.join(folder, "package.json");
34
- if (io.exists(filePath)) {
35
- return filePath;
36
- }
37
- throw new Error(
38
- "no package.json found. Searched the following folder and all parents: " + folder
39
- );
40
- }
41
- function lookupVersion(key, workspaceRoot, repo) {
42
- const versionMaps = getVersionMaps(workspaceRoot, workspaceRoot, repo);
43
- for (const versionMap of versionMaps) {
44
- const version = lookupVersionInMap(key, versionMap);
45
- if (version) {
46
- return version;
47
- }
48
- }
49
- throw new Error(
50
- `Shared Dependency ${key} has requiredVersion:'auto'. However, this dependency is not found in your package.json`
51
- );
52
- }
53
- function lookupVersionInMap(key, versions) {
54
- const parts = key.split("/");
55
- if (parts.length >= 2 && parts[0].startsWith("@")) {
56
- key = parts[0] + "/" + parts[1];
57
- } else {
58
- key = parts[0];
59
- }
60
- if (!versions[key]) {
61
- return null;
62
- }
63
- return versions[key];
64
- }
65
- function _findSecondaries(io, libPath, excludes, shareObject, acc, preparedSkipList) {
66
- const files = io.readDir(libPath);
67
- const secondaries = files.map((f) => path.join(libPath, f)).filter((f) => io.isDirectory(f) && !f.endsWith("node_modules"));
68
- for (const s of secondaries) {
69
- if (io.exists(path.join(s, "package.json"))) {
70
- const secondaryLibName = s.replace(/\\/g, "/").replace(/^.*node_modules[/]/, "");
71
- const inCustomSkipList = excludes.some(
72
- (e) => e === secondaryLibName || e.endsWith("*") && secondaryLibName.startsWith(e.slice(0, -1))
73
- );
74
- if (inCustomSkipList) continue;
75
- if (isInSkipList(secondaryLibName, preparedSkipList)) {
76
- continue;
77
- }
78
- acc[secondaryLibName] = { ...shareObject };
79
- }
80
- _findSecondaries(io, s, excludes, shareObject, acc, preparedSkipList);
81
- }
82
- }
83
- function findSecondaries(io, libPath, excludes, shareObject, preparedSkipList) {
84
- const acc = {};
85
- _findSecondaries(io, libPath, excludes, shareObject, acc, preparedSkipList);
86
- return acc;
87
- }
88
- function getSecondaries(io, includeSecondaries, libPath, key, shareObject, preparedSkipList) {
89
- let exclude = [];
90
- let resolveGlob = false;
91
- if (typeof includeSecondaries === "object") {
92
- if (includeSecondaries.skip) {
93
- if (Array.isArray(includeSecondaries.skip)) {
94
- exclude = includeSecondaries.skip;
95
- } else if (typeof includeSecondaries.skip === "string") {
96
- exclude = [includeSecondaries.skip];
97
- }
98
- }
99
- resolveGlob = !!includeSecondaries.resolveGlob;
100
- }
101
- if (!io.exists(libPath)) {
102
- return {};
103
- }
104
- const configured = readConfiguredSecondaries(
105
- io,
106
- key,
107
- libPath,
108
- exclude,
109
- shareObject,
110
- preparedSkipList,
111
- resolveGlob
112
- );
113
- if (configured) {
114
- return configured;
115
- }
116
- const secondaries = findSecondaries(io, libPath, exclude, shareObject, preparedSkipList);
117
- return secondaries;
118
- }
119
- function readConfiguredSecondaries(io, parent, libPath, exclude, shareObject, preparedSkipList, resolveGlob) {
120
- const libPackageJson = path.join(libPath, "package.json");
121
- if (!io.exists(libPackageJson)) {
122
- return null;
123
- }
124
- const packageJson = JSON.parse(io.readText(libPackageJson));
125
- const version = packageJson["version"];
126
- const esm = packageJson["type"] === "module";
127
- const exports = packageJson["exports"];
128
- if (!exports) {
129
- return null;
130
- }
131
- const keys = Object.keys(exports).filter(
132
- (key) => key !== "." && key !== "./package.json" && key.startsWith("./") && (exports[key]?.["default"] || exports[key]?.["import"] || typeof exports[key] === "string")
133
- );
134
- const result = {};
135
- const discoveredFiles = /* @__PURE__ */ new Set();
136
- for (const key of keys) {
137
- const secondaryName = path.join(parent, key).replace(/\\/g, "/");
138
- const inCustomSkipList = exclude.some(
139
- (e) => e === secondaryName || e.endsWith("*") && secondaryName.startsWith(e.slice(0, -1))
140
- );
141
- if (inCustomSkipList) continue;
142
- if (isInSkipList(secondaryName, preparedSkipList)) {
143
- continue;
144
- }
145
- const entry = getDefaultEntry(exports, key);
146
- if (typeof entry !== "string") {
147
- console.log("No entry point found for " + secondaryName);
148
- continue;
149
- }
150
- if (!key.includes("*") && !isJsFile(entry)) {
151
- continue;
152
- }
153
- const items = resolveGlobSecondaries(
154
- io,
155
- key,
156
- libPath,
157
- parent,
158
- secondaryName,
159
- entry,
160
- { discovered: discoveredFiles, skip: exclude },
161
- resolveGlob
162
- );
163
- items.forEach((e) => discoveredFiles.add(typeof e === "string" ? e : e.value));
164
- for (const item of items) {
165
- if (typeof item === "object") {
166
- result[item.key] = {
167
- ...shareObject,
168
- packageInfo: {
169
- entryPoint: item.value,
170
- version: shareObject.version ?? version,
171
- esm
172
- }
10
+ import { findPackageJson, inferProjectPath } from "./project-paths.js";
11
+ import { isInferVersion, lookupVersion } from "./version-lookup.js";
12
+ import { addSecondaries, getSecondaries } from "./secondaries.js";
13
+ const fromPackageJson = (baseCfg, projectPath) => {
14
+ const skipList = [...DEFAULT_SKIP_LIST];
15
+ let overrides = {};
16
+ const patchList = {};
17
+ const builder = {
18
+ skip(externals) {
19
+ skipList.push(...externals);
20
+ return builder;
21
+ },
22
+ override(externals) {
23
+ overrides = { ...overrides, ...externals };
24
+ return builder;
25
+ },
26
+ patch(externals, cfg) {
27
+ externals.forEach((external) => {
28
+ patchList[external] = {
29
+ ...patchList[external] ?? {},
30
+ ...cfg
173
31
  };
174
- } else {
175
- result[item] = {
176
- ...shareObject
177
- };
178
- }
179
- }
180
- }
181
- return result;
182
- }
183
- function resolveGlobSecondaries(io, key, libPath, parent, secondaryName, entry, excludes, resolveGlob) {
184
- let items = [];
185
- if (key.includes("*")) {
186
- if (!resolveGlob) return items;
187
- const expanded = resolvePackageJsonExportsWildcardCore(io, key, entry, libPath);
188
- items = expanded.map((e) => ({
189
- key: path.join(parent, e.key),
190
- value: path.join(libPath, e.value)
191
- })).filter((i) => {
192
- if (!isJsFile(i.value)) {
193
- return false;
194
- }
195
- if (excludes.skip.some(
196
- (e) => e.endsWith("*") ? i.key.startsWith(e.slice(0, -1)) : e === i.key
197
- )) {
198
- return false;
199
- }
200
- if (excludes.discovered.has(i.value)) {
201
- return false;
202
- }
203
- return true;
204
- });
205
- } else {
206
- items = [secondaryName];
207
- }
208
- return items;
209
- }
210
- function isJsFile(file) {
211
- return file.endsWith(".js") || file.endsWith(".mjs") || file.endsWith(".cjs");
212
- }
213
- function getDefaultEntry(exports, key) {
214
- let entry = "";
215
- if (typeof exports[key] === "string") {
216
- entry = exports[key];
217
- }
218
- if (!entry) {
219
- entry = exports[key]?.["default"];
220
- if (typeof entry === "object") {
221
- entry = entry["default"];
222
- }
223
- }
224
- if (!entry) {
225
- entry = exports[key]?.["import"];
226
- if (typeof entry === "object") {
227
- entry = entry["import"] ?? entry["default"];
228
- }
229
- }
230
- if (!entry) {
231
- entry = exports[key]?.["require"];
232
- if (typeof entry === "object") {
233
- entry = entry["require"] ?? entry["default"];
32
+ });
33
+ return builder;
34
+ },
35
+ get() {
36
+ return shareAllCore(nodeIo, baseCfg, {
37
+ skipList,
38
+ projectPath,
39
+ overrides,
40
+ patchList
41
+ });
234
42
  }
235
- }
236
- return entry;
237
- }
43
+ };
44
+ return builder;
45
+ };
238
46
  function shareAll(config, opts = {}) {
239
47
  return shareAllCore(nodeIo, config, opts);
240
48
  }
@@ -251,32 +59,35 @@ function shareAllCore(io, config, opts = {}, repo = sharedPackageJsonRepository)
251
59
  if (!!opts.overrides && Object.keys(opts.overrides).some((o) => key.startsWith(o))) {
252
60
  continue;
253
61
  }
254
- const inferVersion2 = !config.requiredVersion || config.requiredVersion === "auto";
255
- const requiredVersion = inferVersion2 ? versions[key] : config.requiredVersion;
62
+ const inferVersion = !config.requiredVersion || config.requiredVersion === "auto";
63
+ const requiredVersion = inferVersion ? versions[key] : config.requiredVersion;
256
64
  if (!sharedExternals[key]) {
257
65
  sharedExternals[key] = { ...config, requiredVersion };
258
66
  }
259
67
  }
260
68
  }
69
+ const finalExternalList = applyPatchList(sharedExternals, opts.patchList, opts.overrides);
261
70
  return {
262
- ...shareCore(io, sharedExternals, opts.projectPath, skipList, repo),
71
+ ...shareCore(io, finalExternalList, opts.projectPath, skipList, repo),
263
72
  ...!opts.overrides ? {} : shareCore(io, opts.overrides, opts.projectPath, skipList, repo)
264
73
  };
265
74
  }
266
- function inferProjectPath(projectPath) {
267
- if (!projectPath && getConfigContext().packageJson) {
268
- projectPath = path.dirname(getConfigContext().packageJson || "");
269
- }
270
- if (!projectPath && getConfigContext().workspaceRoot) {
271
- projectPath = getConfigContext().workspaceRoot || "";
75
+ function applyPatchList(sharedExternals, patchList, overrides) {
76
+ if (!patchList) {
77
+ return sharedExternals;
272
78
  }
273
- if (!projectPath) {
274
- projectPath = cwd();
79
+ const result = { ...sharedExternals };
80
+ for (const [external, cfg] of Object.entries(patchList)) {
81
+ if (!result[external]) {
82
+ const shadowedByOverride = !!overrides && Object.keys(overrides).some((o) => external.startsWith(o));
83
+ logger.warn(
84
+ shadowedByOverride ? `Ignoring patch for '${external}': it is already configured via 'overrides' ('patch' and 'overrides' are mutually exclusive per external).` : `Ignoring patch for '${external}': it is not a shared external (unknown dependency or skipped).`
85
+ );
86
+ continue;
87
+ }
88
+ result[external] = { ...result[external], ...cfg };
275
89
  }
276
- return projectPath;
277
- }
278
- function setInferVersion(infer) {
279
- inferVersion = infer;
90
+ return result;
280
91
  }
281
92
  function share(configuredShareObjects, projectPath = "", skipList = DEFAULT_SKIP_LIST) {
282
93
  return shareCore(nodeIo, configuredShareObjects, projectPath, skipList);
@@ -287,11 +98,10 @@ function shareCore(io, configuredShareObjects, projectPath = "", skipList = DEFA
287
98
  const preparedSkipList = prepareSkipList(skipList);
288
99
  const shareObjects = { ...configuredShareObjects };
289
100
  const result = {};
290
- let includeSecondaries;
291
101
  for (const key in shareObjects) {
292
- includeSecondaries = false;
102
+ let includeSecondaries = false;
293
103
  const shareObject = shareObjects[key];
294
- if (shareObject.requiredVersion === "auto" || inferVersion && typeof shareObject.requiredVersion === "undefined" || shareObject.requiredVersion?.length < 1) {
104
+ if (shareObject.requiredVersion === "auto" || isInferVersion() && typeof shareObject.requiredVersion === "undefined" || (shareObject.requiredVersion?.length ?? 1) < 1) {
295
105
  const version = lookupVersion(key, projectPath, repo);
296
106
  shareObject.requiredVersion = version;
297
107
  shareObject.version = version.replace(/^\D*/, "");
@@ -302,7 +112,9 @@ function shareCore(io, configuredShareObjects, projectPath = "", skipList = DEFA
302
112
  if (shareObject.includeSecondaries) {
303
113
  includeSecondaries = shareObject.includeSecondaries;
304
114
  delete shareObject.includeSecondaries;
305
- if (includeSecondaries?.keepAll) shareObject.includeSecondaries = true;
115
+ if (typeof includeSecondaries === "object" && includeSecondaries.keepAll) {
116
+ shareObject.includeSecondaries = true;
117
+ }
306
118
  }
307
119
  result[key] = shareObject;
308
120
  if (includeSecondaries) {
@@ -327,16 +139,8 @@ function shareCore(io, configuredShareObjects, projectPath = "", skipList = DEFA
327
139
  }
328
140
  return result;
329
141
  }
330
- function addSecondaries(secondaries, result) {
331
- for (const key in secondaries) {
332
- result[key] = secondaries[key];
333
- }
334
- }
335
142
  export {
336
- findRootTsConfigJson,
337
- findRootTsConfigJsonCore,
338
- getSecondaries,
339
- setInferVersion,
143
+ fromPackageJson,
340
144
  share,
341
145
  shareAll,
342
146
  shareAllCore,
@@ -0,0 +1,4 @@
1
+ import type { PackageJsonRepository } from '../domain/utils/package-json.contract.js';
2
+ export declare function setInferVersion(infer: boolean): void;
3
+ export declare function isInferVersion(): boolean;
4
+ export declare function lookupVersion(key: string, workspaceRoot: string, repo: PackageJsonRepository): string;
@@ -0,0 +1,37 @@
1
+ import { getVersionMaps } from "../utils/package/package-info.js";
2
+ let inferVersion = false;
3
+ function setInferVersion(infer) {
4
+ inferVersion = infer;
5
+ }
6
+ function isInferVersion() {
7
+ return inferVersion;
8
+ }
9
+ function lookupVersion(key, workspaceRoot, repo) {
10
+ const versionMaps = getVersionMaps(workspaceRoot, workspaceRoot, repo);
11
+ for (const versionMap of versionMaps) {
12
+ const version = lookupVersionInMap(key, versionMap);
13
+ if (version) {
14
+ return version;
15
+ }
16
+ }
17
+ throw new Error(
18
+ `Shared Dependency ${key} has requiredVersion:'auto'. However, this dependency is not found in your package.json`
19
+ );
20
+ }
21
+ function lookupVersionInMap(key, versions) {
22
+ const parts = key.split("/");
23
+ if (parts.length >= 2 && parts[0].startsWith("@")) {
24
+ key = parts[0] + "/" + parts[1];
25
+ } else {
26
+ key = parts[0];
27
+ }
28
+ if (!versions[key]) {
29
+ return null;
30
+ }
31
+ return versions[key];
32
+ }
33
+ export {
34
+ isInferVersion,
35
+ lookupVersion,
36
+ setInferVersion
37
+ };
@@ -1,5 +1,6 @@
1
1
  import { getRawMappedPaths } from "./mapped-paths.js";
2
- import { shareAll, findRootTsConfigJson } from "./share-utils.js";
2
+ import { fromPackageJson } from "./share-utils.js";
3
+ import { findRootTsConfigJson } from "./project-paths.js";
3
4
  import { isInSkipList, prepareSkipList } from "./default-skip-list.js";
4
5
  import { logger } from "../utils/logger.js";
5
6
  function withNativeFederation(config) {
@@ -18,6 +19,7 @@ function withNativeFederation(config) {
18
19
  mappingVersion: config.features?.mappingVersion ?? true,
19
20
  ignoreUnusedDeps: config.features?.ignoreUnusedDeps ?? true,
20
21
  denseChunking: config.features?.denseChunking ?? false,
22
+ denseExternals: config.features?.denseExternals ?? false,
21
23
  integrityHashes: config.features?.integrityHashes ?? false
22
24
  },
23
25
  ...config.shareScope && { shareScope: config.shareScope }
@@ -35,12 +37,12 @@ function normalizeExposes(exposes) {
35
37
  }
36
38
  function normalizeShared(config, skip, chunks) {
37
39
  let result = {};
38
- const shared = config.shared ?? shareAll({
40
+ const shared = config.shared ?? fromPackageJson({
39
41
  singleton: true,
40
42
  strictVersion: true,
41
43
  requiredVersion: "auto",
42
44
  platform: "browser"
43
- });
45
+ }).get();
44
46
  result = Object.keys(shared).reduce((acc, cur) => {
45
47
  const key = cur.replace(/\\/g, "/");
46
48
  const sharedConfig = shared[cur];
@@ -56,11 +58,12 @@ function normalizeShared(config, skip, chunks) {
56
58
  strictVersion: sharedConfig.strictVersion ?? false,
57
59
  version: sharedConfig.version,
58
60
  chunks: sharedConfig.chunks ?? chunks,
59
- includeSecondaries: sharedConfig.includeSecondaries,
61
+ includeSecondaries: typeof sharedConfig.includeSecondaries === "object" ? !!sharedConfig.includeSecondaries.keepAll : sharedConfig.includeSecondaries,
60
62
  packageInfo: sharedConfig.packageInfo,
61
63
  platform: sharedConfig.platform ?? config.platform ?? "browser",
62
64
  build: sharedConfig.build ?? "default",
63
- ...sharedConfig.shareScope && { shareScope: sharedConfig.shareScope }
65
+ ...sharedConfig.shareScope && { shareScope: sharedConfig.shareScope },
66
+ ...sharedConfig.pool && { pool: sharedConfig.pool }
64
67
  };
65
68
  return {
66
69
  ...acc,
@@ -4,10 +4,11 @@ import {
4
4
  describeSharedMappings
5
5
  } from "./bundle-exposed-and-mappings.js";
6
6
  import { bundleShared } from "./bundle-shared.js";
7
+ import { densifyExternals } from "../output/densify-externals.js";
7
8
  import { writeFederationInfo } from "../output/write-federation-info.js";
8
9
  import { writeImportMap } from "../output/write-import-map.js";
9
10
  import { logger } from "../../utils/logger.js";
10
- import { normalizePackageName } from "../../utils/normalize.js";
11
+ import { inferPackageFromSecondary, normalizePackageName } from "../../utils/normalize.js";
11
12
  import { AbortedError } from "../../utils/errors.js";
12
13
  import { addExternalsToCache } from "../cache/federation-cache.js";
13
14
  import path from "path";
@@ -97,10 +98,11 @@ async function buildForFederation(config, fedOptions, externals, signal) {
97
98
  if (!external.shareScope) external.shareScope = config.shareScope;
98
99
  });
99
100
  }
101
+ const shared = config.features.denseExternals ? densifyExternals(sharedExternals) : sharedExternals;
100
102
  const buildNotificationsEndpoint = fedOptions.buildNotifications?.enable && fedOptions.dev ? fedOptions.buildNotifications?.endpoint : void 0;
101
103
  const federationInfo = {
102
104
  name: config.name,
103
- shared: sharedExternals,
105
+ shared,
104
106
  exposes: exposedInfo,
105
107
  buildNotificationsEndpoint
106
108
  };
@@ -120,13 +122,6 @@ async function buildForFederation(config, fedOptions, externals, signal) {
120
122
  writeImportMap(fedOptions.federationCache, fedOptions, federationInfo.integrity);
121
123
  return federationInfo;
122
124
  }
123
- function inferPackageFromSecondary(secondary) {
124
- const parts = secondary.split("/");
125
- if (secondary.startsWith("@") && parts.length >= 2) {
126
- return parts[0] + "/" + parts[1];
127
- }
128
- return parts[0];
129
- }
130
125
  async function bundleSeparatePackages(separateBrowser, externals, config, fedOptions, buildOptions) {
131
126
  const groupedByPackage = {};
132
127
  for (const [key, shared] of Object.entries(separateBrowser)) {
@@ -193,13 +193,8 @@ function buildResult(packageInfos, sharedBundles, outFileNames) {
193
193
  singleton: shared?.singleton,
194
194
  strictVersion: shared?.strictVersion,
195
195
  version: pi.version,
196
- ...shared?.shareScope && { shareScope: shared.shareScope }
197
- // TODO: Decide whether/when we need debug infos
198
- // dev: !fedOptions.dev
199
- // ? undefined
200
- // : {
201
- // entryPoint: normalize(pi.entryPoint),
202
- // },
196
+ ...shared?.shareScope && { shareScope: shared.shareScope },
197
+ ...shared?.pool && { pool: shared.pool }
203
198
  };
204
199
  });
205
200
  }
@@ -212,14 +207,12 @@ function addChunksToResult(chunks, result) {
212
207
  result.push({
213
208
  singleton: false,
214
209
  strictVersion: false,
215
- // Here, the version does not matter because
210
+ // Here, the version, singleton and strictversion
211
+ // do not matter because
216
212
  // a) a chunk split off by the bundler does
217
213
  // not have a version and b) it gets a hash
218
214
  // code as part of the file name to be unique
219
215
  // when requested via a _versioned_ package.
220
- //
221
- // For the same reason, we don't need to
222
- // take care of singleton and strictVersion.
223
216
  version: "0.0.0",
224
217
  requiredVersion: "0.0.0",
225
218
  packageName: toChunkImport(fileName),
@@ -0,0 +1,8 @@
1
+ import type { SharedInfo, DenseSharedInfo } from '../../domain/core/federation-info.contract.js';
2
+ /**
3
+ * Groups a flat `shared` array into {@link DenseSharedInfo} objects: one per shared external,
4
+ * with an `entries` map from each import name to its output file. Entries sharing a parent
5
+ * package but with differing metadata split into separate groups. Bundler chunks and
6
+ * already-dense entries pass through unchanged.
7
+ */
8
+ export declare function densifyExternals(shared: Array<SharedInfo | DenseSharedInfo>): Array<SharedInfo | DenseSharedInfo>;
@@ -0,0 +1,49 @@
1
+ import { CHUNK_PREFIX } from "../../domain/core/chunk.js";
2
+ import { inferPackageFromSecondary } from "../../utils/normalize.js";
3
+ function isDense(entry) {
4
+ return "entries" in entry;
5
+ }
6
+ function isChunk(entry) {
7
+ return entry.packageName.startsWith(CHUNK_PREFIX + "/");
8
+ }
9
+ function densifyExternals(shared) {
10
+ const result = [];
11
+ const groupIndex = /* @__PURE__ */ new Map();
12
+ for (const entry of shared) {
13
+ if (isDense(entry) || isChunk(entry)) {
14
+ result.push(entry);
15
+ continue;
16
+ }
17
+ const parent = inferPackageFromSecondary(entry.packageName);
18
+ const sig = JSON.stringify({
19
+ singleton: entry.singleton,
20
+ strictVersion: entry.strictVersion,
21
+ requiredVersion: entry.requiredVersion,
22
+ version: entry.version,
23
+ shareScope: entry.shareScope
24
+ });
25
+ const key = parent + " " + sig;
26
+ const existing = groupIndex.get(key);
27
+ if (existing === void 0) {
28
+ const dense = {
29
+ singleton: entry.singleton,
30
+ strictVersion: entry.strictVersion,
31
+ requiredVersion: entry.requiredVersion,
32
+ packageName: parent,
33
+ entries: { [entry.packageName]: entry.outFileName }
34
+ };
35
+ if (entry.version !== void 0) dense.version = entry.version;
36
+ if (entry.shareScope !== void 0) dense.shareScope = entry.shareScope;
37
+ if (entry.bundle !== void 0) dense.bundle = entry.bundle;
38
+ if (entry.dev !== void 0) dense.dev = entry.dev;
39
+ groupIndex.set(key, result.length);
40
+ result.push(dense);
41
+ } else {
42
+ result[existing].entries[entry.packageName] = entry.outFileName;
43
+ }
44
+ }
45
+ return result;
46
+ }
47
+ export {
48
+ densifyExternals
49
+ };
@@ -1,11 +1,17 @@
1
+ export type IncludeSecondariesOptions = {
2
+ skip?: string | string[];
3
+ resolveGlob?: boolean;
4
+ keepAll?: boolean;
5
+ } | boolean;
1
6
  export interface ExternalConfig {
2
7
  singleton?: boolean;
3
8
  strictVersion?: boolean;
4
9
  requiredVersion?: string;
5
10
  version?: string;
6
- includeSecondaries?: boolean;
11
+ includeSecondaries?: IncludeSecondariesOptions;
7
12
  platform?: 'browser' | 'node';
8
13
  build?: 'separate' | 'package';
14
+ pool?: string;
9
15
  chunks?: boolean;
10
16
  shareScope?: string;
11
17
  packageInfo?: {
@@ -21,6 +27,7 @@ export interface NormalizedExternalConfig {
21
27
  version?: string;
22
28
  includeSecondaries?: boolean;
23
29
  shareScope?: string;
30
+ pool?: string;
24
31
  chunks: boolean;
25
32
  platform: 'browser' | 'node';
26
33
  build: 'default' | 'separate' | 'package';
@@ -30,14 +37,11 @@ export interface NormalizedExternalConfig {
30
37
  esm: boolean;
31
38
  };
32
39
  }
33
- export type IncludeSecondariesOptions = {
34
- skip?: string | string[];
35
- resolveGlob?: boolean;
36
- keepAll?: boolean;
37
- } | boolean;
38
40
  export type SharedExternalsConfig = Record<string, ExternalConfig>;
39
41
  export type NormalizedSharedExternalsConfig = Record<string, NormalizedExternalConfig>;
40
- export type ShareAllExternalsOptions = Omit<ExternalConfig, 'includeSecondaries'> & {
41
- includeSecondaries?: IncludeSecondariesOptions;
42
+ export type ShareAllExternalsOptions = ExternalConfig;
43
+ export type ShareExternalsOptions = SharedExternalsConfig;
44
+ export type ResolvedExternalConfig = Omit<ExternalConfig, 'includeSecondaries'> & {
45
+ includeSecondaries?: boolean;
42
46
  };
43
- export type ShareExternalsOptions = Record<string, ShareAllExternalsOptions>;
47
+ export type ResolvedSharedExternalsConfig = Record<string, ResolvedExternalConfig>;
@@ -19,6 +19,7 @@ export interface FederationConfig {
19
19
  mappingVersion?: boolean;
20
20
  ignoreUnusedDeps?: boolean;
21
21
  denseChunking?: boolean;
22
+ denseExternals?: boolean;
22
23
  integrityHashes?: boolean;
23
24
  };
24
25
  }
@@ -36,6 +37,7 @@ export interface NormalizedFederationConfig {
36
37
  mappingVersion: boolean;
37
38
  ignoreUnusedDeps: boolean;
38
39
  denseChunking: boolean;
40
+ denseExternals: boolean;
39
41
  integrityHashes: boolean;
40
42
  };
41
43
  }
@@ -1,3 +1,3 @@
1
- export type { ExternalConfig, IncludeSecondariesOptions, SharedExternalsConfig, ShareAllExternalsOptions, ShareExternalsOptions, } from './external-config.contract.js';
1
+ export type { ExternalConfig, IncludeSecondariesOptions, ResolvedExternalConfig, ResolvedSharedExternalsConfig, SharedExternalsConfig, ShareAllExternalsOptions, ShareExternalsOptions, } from './external-config.contract.js';
2
2
  export type { FederationConfig } from './federation-config.contract.js';
3
3
  export type { PreparedSkipList, SkipFn, SkipList, SkipListEntry } from './skip-list.contract.js';