@softarc/native-federation 4.1.2 → 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 (197) 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/{src → dist}/lib/domain/config/federation-config.contract.d.ts +6 -2
  55. package/dist/lib/domain/config/federation-config.contract.js +0 -0
  56. package/dist/lib/domain/config/index.js +0 -0
  57. package/dist/lib/domain/config/skip-list.contract.js +0 -0
  58. package/dist/lib/domain/core/build-adapter.contract.js +0 -0
  59. package/dist/lib/domain/core/build-notification-options.contract.js +9 -0
  60. package/dist/lib/domain/core/chunk.js +12 -0
  61. package/dist/lib/domain/core/federation-cache.contract.js +0 -0
  62. package/{src → dist}/lib/domain/core/federation-info.contract.d.ts +1 -0
  63. package/dist/lib/domain/core/federation-info.contract.js +0 -0
  64. package/dist/lib/domain/core/federation-options.contract.js +0 -0
  65. package/{src → dist}/lib/domain/core/index.d.ts +1 -0
  66. package/dist/lib/domain/core/index.js +9 -0
  67. package/dist/lib/domain/core/manifest.contract.d.ts +5 -0
  68. package/dist/lib/domain/core/manifest.contract.js +0 -0
  69. package/dist/lib/domain/utils/file-watcher.contract.js +0 -0
  70. package/dist/lib/domain/utils/io-port.contract.d.ts +45 -0
  71. package/dist/lib/domain/utils/io-port.contract.js +0 -0
  72. package/dist/lib/domain/utils/keyvaluepair.contract.js +0 -0
  73. package/dist/lib/domain/utils/mapped-path.contract.js +0 -0
  74. package/dist/lib/domain/utils/package-json.contract.d.ts +27 -0
  75. package/dist/lib/domain/utils/package-json.contract.js +0 -0
  76. package/dist/lib/domain/utils/used-dependencies.contract.js +0 -0
  77. package/dist/lib/utils/errors.js +10 -0
  78. package/{src → dist}/lib/utils/file-watcher.d.ts +2 -0
  79. package/dist/lib/utils/file-watcher.js +51 -0
  80. package/dist/lib/utils/hash-file.d.ts +7 -0
  81. package/dist/lib/utils/hash-file.js +15 -0
  82. package/dist/lib/utils/io/node-io-adapter.d.ts +2 -0
  83. package/dist/lib/utils/io/node-io-adapter.js +68 -0
  84. package/dist/lib/utils/io/package-json-repository.d.ts +5 -0
  85. package/dist/lib/utils/io/package-json-repository.js +79 -0
  86. package/dist/lib/utils/logger.js +29 -0
  87. package/dist/lib/utils/normalize.js +22 -0
  88. package/dist/lib/utils/package/entry-point-resolver.d.ts +2 -0
  89. package/dist/lib/utils/package/entry-point-resolver.js +78 -0
  90. package/dist/lib/utils/package/esm-detection.d.ts +5 -0
  91. package/dist/lib/utils/package/esm-detection.js +10 -0
  92. package/dist/lib/utils/package/exports-resolver.d.ts +13 -0
  93. package/dist/lib/utils/package/exports-resolver.js +55 -0
  94. package/dist/lib/utils/package/package-info.d.ts +7 -0
  95. package/dist/lib/utils/package/package-info.js +31 -0
  96. package/dist/lib/utils/package/resolve-wildcard-keys.d.ts +3 -0
  97. package/dist/lib/utils/package/resolve-wildcard-keys.js +22 -0
  98. package/dist/lib/utils/package/version-maps.d.ts +3 -0
  99. package/dist/lib/utils/package/version-maps.js +8 -0
  100. package/dist/lib/utils/path-patterns.d.ts +14 -0
  101. package/dist/lib/utils/path-patterns.js +28 -0
  102. package/package.json +45 -22
  103. package/src/config.js +0 -4
  104. package/src/domain.js +0 -2
  105. package/src/index.d.ts +0 -10
  106. package/src/index.js +0 -10
  107. package/src/internal.js +0 -11
  108. package/src/lib/config/configuration-context.js +0 -10
  109. package/src/lib/config/default-skip-list.js +0 -31
  110. package/src/lib/config/remove-unused-deps.js +0 -10
  111. package/src/lib/config/share-utils.d.ts +0 -10
  112. package/src/lib/config/share-utils.js +0 -302
  113. package/src/lib/config/with-native-federation.js +0 -71
  114. package/src/lib/core/build-adapter.js +0 -12
  115. package/src/lib/core/build-for-federation.d.ts +0 -4
  116. package/src/lib/core/build-for-federation.js +0 -173
  117. package/src/lib/core/bundle-exposed-and-mappings.d.ts +0 -7
  118. package/src/lib/core/bundle-exposed-and-mappings.js +0 -174
  119. package/src/lib/core/bundle-shared.d.ts +0 -13
  120. package/src/lib/core/bundle-shared.js +0 -222
  121. package/src/lib/core/default-external-list.js +0 -29
  122. package/src/lib/core/federation-builder.js +0 -45
  123. package/src/lib/core/federation-cache.js +0 -16
  124. package/src/lib/core/get-externals.d.ts +0 -2
  125. package/src/lib/core/get-externals.js +0 -6
  126. package/src/lib/core/normalize-options.js +0 -58
  127. package/src/lib/core/rebuild-for-federation.d.ts +0 -4
  128. package/src/lib/core/rebuild-for-federation.js +0 -43
  129. package/src/lib/core/write-federation-info.d.ts +0 -3
  130. package/src/lib/core/write-federation-info.js +0 -6
  131. package/src/lib/core/write-import-map.d.ts +0 -6
  132. package/src/lib/core/write-import-map.js +0 -33
  133. package/src/lib/domain/config/external-config.contract.js +0 -1
  134. package/src/lib/domain/config/federation-config.contract.js +0 -1
  135. package/src/lib/domain/config/index.js +0 -1
  136. package/src/lib/domain/config/skip-list.contract.js +0 -1
  137. package/src/lib/domain/config/with-native-federation.contract.d.ts +0 -2
  138. package/src/lib/domain/config/with-native-federation.contract.js +0 -1
  139. package/src/lib/domain/core/build-adapter.contract.js +0 -1
  140. package/src/lib/domain/core/build-notification-options.contract.js +0 -6
  141. package/src/lib/domain/core/chunk.js +0 -8
  142. package/src/lib/domain/core/federation-cache.contract.js +0 -1
  143. package/src/lib/domain/core/federation-info.contract.js +0 -1
  144. package/src/lib/domain/core/federation-options.contract.js +0 -1
  145. package/src/lib/domain/core/index.js +0 -2
  146. package/src/lib/domain/utils/file-watcher.contract.js +0 -1
  147. package/src/lib/domain/utils/index.d.ts +0 -2
  148. package/src/lib/domain/utils/index.js +0 -1
  149. package/src/lib/domain/utils/keyvaluepair.contract.js +0 -1
  150. package/src/lib/domain/utils/mapped-path.contract.js +0 -5
  151. package/src/lib/domain/utils/used-dependencies.contract.js +0 -1
  152. package/src/lib/utils/build-result-map.js +0 -29
  153. package/src/lib/utils/cache-persistence.d.ts +0 -19
  154. package/src/lib/utils/cache-persistence.js +0 -66
  155. package/src/lib/utils/errors.js +0 -7
  156. package/src/lib/utils/file-watcher.js +0 -51
  157. package/src/lib/utils/get-external-imports.d.ts +0 -1
  158. package/src/lib/utils/get-external-imports.js +0 -80
  159. package/src/lib/utils/get-used-dependencies.d.ts +0 -7
  160. package/src/lib/utils/get-used-dependencies.js +0 -123
  161. package/src/lib/utils/hash-file.d.ts +0 -3
  162. package/src/lib/utils/hash-file.js +0 -13
  163. package/src/lib/utils/logger.js +0 -27
  164. package/src/lib/utils/mapped-paths.js +0 -33
  165. package/src/lib/utils/normalize.js +0 -17
  166. package/src/lib/utils/package-info.d.ts +0 -30
  167. package/src/lib/utils/package-info.js +0 -268
  168. package/src/lib/utils/rebuild-queue.js +0 -63
  169. package/src/lib/utils/resolve-glob.d.ts +0 -1
  170. package/src/lib/utils/resolve-glob.js +0 -29
  171. package/src/lib/utils/resolve-wildcard-keys.d.ts +0 -29
  172. package/src/lib/utils/resolve-wildcard-keys.js +0 -126
  173. package/src/lib/utils/rewrite-chunk-imports.d.ts +0 -2
  174. package/src/lib/utils/rewrite-chunk-imports.js +0 -48
  175. /package/{src → dist}/config.d.ts +0 -0
  176. /package/{src → dist}/domain.d.ts +0 -0
  177. /package/{src → dist}/lib/config/configuration-context.d.ts +0 -0
  178. /package/{src → dist}/lib/config/default-skip-list.d.ts +0 -0
  179. /package/{src → dist}/lib/config/remove-unused-deps.d.ts +0 -0
  180. /package/{src → dist}/lib/config/with-native-federation.d.ts +0 -0
  181. /package/{src/lib/core → dist/lib/core/build}/default-external-list.d.ts +0 -0
  182. /package/{src → dist}/lib/core/federation-builder.d.ts +0 -0
  183. /package/{src/lib/utils → dist/lib/core}/rebuild-queue.d.ts +0 -0
  184. /package/{src → dist}/lib/domain/config/index.d.ts +0 -0
  185. /package/{src → dist}/lib/domain/config/skip-list.contract.d.ts +0 -0
  186. /package/{src → dist}/lib/domain/core/build-adapter.contract.d.ts +0 -0
  187. /package/{src → dist}/lib/domain/core/build-notification-options.contract.d.ts +0 -0
  188. /package/{src → dist}/lib/domain/core/chunk.d.ts +0 -0
  189. /package/{src → dist}/lib/domain/core/federation-cache.contract.d.ts +0 -0
  190. /package/{src → dist}/lib/domain/core/federation-options.contract.d.ts +0 -0
  191. /package/{src → dist}/lib/domain/utils/file-watcher.contract.d.ts +0 -0
  192. /package/{src → dist}/lib/domain/utils/keyvaluepair.contract.d.ts +0 -0
  193. /package/{src → dist}/lib/domain/utils/mapped-path.contract.d.ts +0 -0
  194. /package/{src → dist}/lib/domain/utils/used-dependencies.contract.d.ts +0 -0
  195. /package/{src → dist}/lib/utils/errors.d.ts +0 -0
  196. /package/{src → dist}/lib/utils/logger.d.ts +0 -0
  197. /package/{src → dist}/lib/utils/normalize.d.ts +0 -0
@@ -1,173 +0,0 @@
1
- import { bundleExposedAndMappings, describeExposed, describeSharedMappings, } from './bundle-exposed-and-mappings.js';
2
- import { bundleShared } from './bundle-shared.js';
3
- import { writeFederationInfo } from './write-federation-info.js';
4
- import { writeImportMap } from './write-import-map.js';
5
- import { logger } from '../utils/logger.js';
6
- import { normalizePackageName } from '../utils/normalize.js';
7
- import { AbortedError } from '../utils/errors.js';
8
- import { addExternalsToCache } from './federation-cache.js';
9
- import path from 'path';
10
- export async function buildForFederation(config, fedOptions, externals, signal) {
11
- // 1. Setup
12
- fedOptions.federationCache.cachePath = path.join(fedOptions.federationCache.cachePath, fedOptions.projectName);
13
- logger.info('Building federation artifacts');
14
- logger.notice("Skip packages you don't want to share in your federation config");
15
- // 2. Externals
16
- if (fedOptions.federationCache.externals.length > 0) {
17
- logger.info('Checksum matched, re-using cached externals.');
18
- }
19
- if (fedOptions.federationCache.externals.length === 0) {
20
- const { sharedBrowser, sharedServer, separateBrowser, separateServer } = splitShared(config.shared);
21
- if (Object.keys(sharedBrowser).length > 0) {
22
- logger.info(`Bundling external npm packages with bundle type 'browser-shared'`);
23
- const start = process.hrtime();
24
- const sharedPackageInfoBrowser = await bundleShared(sharedBrowser, config, fedOptions, externals, { platform: 'browser', bundleName: 'browser-shared', chunks: config.chunks });
25
- logger.measure(start, 'Step 2.1) Bundling all shared browser externals');
26
- addExternalsToCache(fedOptions.federationCache, sharedPackageInfoBrowser);
27
- if (signal?.aborted)
28
- throw new AbortedError('[buildForFederation] After shared-browser bundle');
29
- }
30
- if (Object.keys(sharedServer).length > 0) {
31
- logger.info(`Bundling external npm packages with bundle type 'server-shared'`);
32
- const start = process.hrtime();
33
- const sharedPackageInfoServer = await bundleShared(sharedServer, config, fedOptions, externals, { platform: 'node', bundleName: 'node-shared', chunks: config.chunks });
34
- logger.measure(start, 'Step 2.1) Bundling all shared node externals');
35
- addExternalsToCache(fedOptions.federationCache, sharedPackageInfoServer);
36
- if (signal?.aborted)
37
- throw new AbortedError('[buildForFederation] After shared-node bundle');
38
- }
39
- if (Object.keys(separateBrowser).length > 0) {
40
- logger.info(`Bundling external npm packages with bundle type 'browser-separate'`);
41
- const start = process.hrtime();
42
- const separatePackageInfoBrowser = await bundleSeparatePackages(separateBrowser, externals, config, fedOptions, { platform: 'browser' });
43
- logger.measure(start, 'Step 2.2) Bundling all separate browser external packages');
44
- addExternalsToCache(fedOptions.federationCache, separatePackageInfoBrowser);
45
- if (signal?.aborted)
46
- throw new AbortedError('[buildForFederation] After separate-browser bundle');
47
- }
48
- if (Object.keys(separateServer).length > 0) {
49
- logger.info(`Bundling external npm packages with bundle type 'node-separate'`);
50
- const start = process.hrtime();
51
- const separatePackageInfoServer = await bundleSeparatePackages(separateServer, externals, config, fedOptions, { platform: 'node' });
52
- logger.measure(start, 'Step 2.2) Bundling all separate node external packages');
53
- addExternalsToCache(fedOptions.federationCache, separatePackageInfoServer);
54
- }
55
- if (signal?.aborted)
56
- throw new AbortedError('[buildForFederation] After separate-node bundle');
57
- }
58
- // 2. Shared mappings and exposed modules
59
- const start = process.hrtime();
60
- const artifactInfo = await bundleExposedAndMappings(config, fedOptions, externals, undefined, signal);
61
- logger.measure(start, 'Step 3) Bundling all internal libraries and exposed modules.');
62
- if (signal?.aborted)
63
- throw new AbortedError('[buildForFederation] After exposed-and-mappings bundle');
64
- const exposedInfo = !artifactInfo ? describeExposed(config, fedOptions) : artifactInfo.exposes;
65
- const sharedMappingInfo = !artifactInfo
66
- ? describeSharedMappings(config, fedOptions)
67
- : artifactInfo.mappings;
68
- const sharedExternals = [...fedOptions.federationCache.externals, ...sharedMappingInfo];
69
- if (config?.shareScope) {
70
- Object.values(sharedExternals).forEach(external => {
71
- if (!external.shareScope)
72
- external.shareScope = config.shareScope;
73
- });
74
- }
75
- const buildNotificationsEndpoint = fedOptions.buildNotifications?.enable && fedOptions.dev
76
- ? fedOptions.buildNotifications?.endpoint
77
- : undefined;
78
- const federationInfo = {
79
- name: config.name,
80
- shared: sharedExternals,
81
- exposes: exposedInfo,
82
- buildNotificationsEndpoint,
83
- };
84
- if (fedOptions.federationCache.chunks) {
85
- federationInfo.chunks = fedOptions.federationCache.chunks;
86
- }
87
- if (artifactInfo?.chunks) {
88
- federationInfo.chunks = { ...(federationInfo.chunks ?? {}), ...artifactInfo?.chunks };
89
- }
90
- if (config.features.integrityHashes) {
91
- federationInfo.integrity = {
92
- ...(fedOptions.federationCache.integrity ?? {}),
93
- ...(artifactInfo?.integrity ?? {}),
94
- };
95
- }
96
- writeFederationInfo(federationInfo, fedOptions);
97
- writeImportMap(fedOptions.federationCache, fedOptions, federationInfo.integrity);
98
- return federationInfo;
99
- }
100
- function inferPackageFromSecondary(secondary) {
101
- const parts = secondary.split('/');
102
- if (secondary.startsWith('@') && parts.length >= 2) {
103
- return parts[0] + '/' + parts[1];
104
- }
105
- return parts[0];
106
- }
107
- async function bundleSeparatePackages(separateBrowser, externals, config, fedOptions, buildOptions) {
108
- const groupedByPackage = {};
109
- for (const [key, shared] of Object.entries(separateBrowser)) {
110
- const packageName = shared.build === 'separate' ? key : inferPackageFromSecondary(key);
111
- if (!groupedByPackage[packageName]) {
112
- groupedByPackage[packageName] = {
113
- chunks: shared.chunks,
114
- entries: {},
115
- };
116
- }
117
- groupedByPackage[packageName].entries[key] = shared;
118
- }
119
- const bundlePromises = Object.entries(groupedByPackage).map(async ([packageName, packageConfig]) => {
120
- return bundleShared(packageConfig.entries, config, fedOptions, externals.filter(e => !e.startsWith(packageName)), {
121
- platform: buildOptions.platform,
122
- chunks: packageConfig.chunks,
123
- bundleName: `${buildOptions.platform}-${normalizePackageName(packageName)}`,
124
- });
125
- });
126
- const buildResults = await Promise.all(bundlePromises);
127
- return buildResults.reduce((acc, r) => {
128
- let chunks = acc.chunks;
129
- if (r.chunks) {
130
- chunks = { ...(acc.chunks ?? {}), ...r.chunks };
131
- }
132
- let integrity = acc.integrity;
133
- if (r.integrity) {
134
- integrity = { ...(acc.integrity ?? {}), ...r.integrity };
135
- }
136
- return {
137
- externals: [...acc.externals, ...r.externals],
138
- chunks,
139
- integrity,
140
- };
141
- }, { externals: [] });
142
- }
143
- function splitShared(shared) {
144
- const sharedServer = {};
145
- const sharedBrowser = {};
146
- const separateBrowser = {};
147
- const separateServer = {};
148
- for (const key in shared) {
149
- const obj = shared[key];
150
- if (obj?.platform === 'node') {
151
- if (obj.build === 'default') {
152
- sharedServer[key] = obj;
153
- }
154
- else {
155
- separateServer[key] = obj;
156
- }
157
- }
158
- else if (obj?.platform === 'browser') {
159
- if (obj.build === 'default') {
160
- sharedBrowser[key] = obj;
161
- }
162
- else {
163
- separateBrowser[key] = obj;
164
- }
165
- }
166
- }
167
- return {
168
- sharedBrowser,
169
- sharedServer,
170
- separateBrowser,
171
- separateServer,
172
- };
173
- }
@@ -1,7 +0,0 @@
1
- import type { ArtifactInfo, ExposesInfo, SharedInfo } from '../domain/core/federation-info.contract.js';
2
- import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
3
- import { type NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
4
- export declare function bundleExposedAndMappings(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], modifiedFiles?: string[], signal?: AbortSignal): Promise<ArtifactInfo>;
5
- export declare function describeExposed(config: NormalizedFederationConfig, options: NormalizedFederationOptions): Array<ExposesInfo>;
6
- export declare function describeSharedMappings(config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions): Array<SharedInfo>;
7
- export declare function getMappingVersion(fileName: string, workspaceRoot: string): string;
@@ -1,174 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { integrityForFile } from '../utils/hash-file.js';
4
- import { createBuildResultMap, popFromResultMap } from '../utils/build-result-map.js';
5
- import { logger } from '../utils/logger.js';
6
- import { normalize } from '../utils/normalize.js';
7
- import { AbortedError } from '../utils/errors.js';
8
- import { rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
9
- import { getBuildAdapter } from './build-adapter.js';
10
- export async function bundleExposedAndMappings(config, fedOptions, externals, modifiedFiles, signal) {
11
- if (signal?.aborted) {
12
- throw new AbortedError('[bundle-exposed-and-mappings] Aborted before bundling');
13
- }
14
- const shared = Object.entries(config.sharedMappings).map(([entryPoint, mappedImport]) => {
15
- return {
16
- fileName: entryPoint,
17
- outName: mappedImport.replace(/[^A-Za-z0-9]/g, '_') + '.js',
18
- key: mappedImport,
19
- };
20
- });
21
- const exposes = Object.entries(config.exposes).map(([key, entry]) => {
22
- const outFilePath = key + '.js';
23
- return { fileName: entry, outName: outFilePath, key };
24
- });
25
- const entryPoints = [...shared, ...exposes];
26
- const hash = !fedOptions.dev;
27
- let result;
28
- try {
29
- if (!modifiedFiles) {
30
- await getBuildAdapter().setup('mapping-or-exposed', {
31
- entryPoints,
32
- outdir: fedOptions.outputPath,
33
- tsConfigPath: fedOptions.tsConfig,
34
- external: externals,
35
- dev: !!fedOptions.dev,
36
- watch: fedOptions.watch,
37
- mappedPaths: config.sharedMappings,
38
- chunks: config.chunks,
39
- hash,
40
- optimizedMappings: config.features.ignoreUnusedDeps,
41
- isMappingOrExposed: true,
42
- cache: fedOptions.federationCache,
43
- });
44
- }
45
- result = await getBuildAdapter().build('mapping-or-exposed', {
46
- signal,
47
- modifiedFiles,
48
- });
49
- if (signal?.aborted) {
50
- throw new AbortedError('[bundle-exposed-and-mappings] Aborted after bundle');
51
- }
52
- }
53
- catch (error) {
54
- if (!(error instanceof AbortedError)) {
55
- logger.error('Error building federation artifacts');
56
- }
57
- throw error;
58
- }
59
- const resultMap = createBuildResultMap(result, hash, [
60
- ...shared.map(s => s.outName),
61
- ...exposes.map(e => e.outName),
62
- ]);
63
- const sharedResult = [];
64
- const entryFiles = [];
65
- // Pick shared-mappings
66
- for (const item of shared) {
67
- const distEntryFile = popFromResultMap(resultMap, item.outName);
68
- sharedResult.push(toSharedMappingInfo(item.fileName, item.key, path.basename(distEntryFile), config, fedOptions));
69
- entryFiles.push(distEntryFile);
70
- }
71
- const exposedResult = [];
72
- // Pick exposed-modules
73
- for (const item of exposes) {
74
- const distEntryFile = popFromResultMap(resultMap, item.outName);
75
- exposedResult.push({
76
- key: item.key,
77
- outFileName: path.basename(distEntryFile),
78
- dev: !fedOptions.dev
79
- ? undefined
80
- : {
81
- entryPoint: normalize(path.join(fedOptions.workspaceRoot, item.fileName)),
82
- },
83
- });
84
- entryFiles.push(distEntryFile);
85
- }
86
- // Remove .map files
87
- Object.keys(resultMap)
88
- .filter(f => f.endsWith('.map'))
89
- .forEach(f => popFromResultMap(resultMap, f));
90
- // Process remaining chunks and lazy loaded internal modules
91
- let exportedChunks = undefined;
92
- const chunkPaths = [];
93
- if (config.chunks && config.features.denseChunking) {
94
- for (const entryFile of entryFiles)
95
- rewriteChunkImports(entryFile);
96
- chunkPaths.push(...Object.values(resultMap));
97
- exportedChunks = {
98
- ['mapping-or-exposed']: chunkPaths.map(chunk => path.basename(chunk)),
99
- };
100
- }
101
- // Must run after rewriteChunkImports so SRI matches the final on-disk bytes.
102
- let integrity;
103
- if (config.features.integrityHashes) {
104
- integrity = {};
105
- for (const filePath of [...entryFiles, ...chunkPaths]) {
106
- if (!fs.existsSync(filePath))
107
- continue;
108
- integrity[path.basename(filePath)] = integrityForFile(filePath);
109
- }
110
- }
111
- return { mappings: sharedResult, exposes: exposedResult, chunks: exportedChunks, integrity };
112
- }
113
- export function describeExposed(config, options) {
114
- const result = [];
115
- for (const key in config.exposes) {
116
- const localPath = normalize(path.normalize(path.join(options.workspaceRoot, config.exposes[key])));
117
- result.push({
118
- key,
119
- outFileName: '',
120
- dev: !options.dev
121
- ? undefined
122
- : {
123
- entryPoint: localPath,
124
- },
125
- });
126
- }
127
- return result;
128
- }
129
- export function describeSharedMappings(config, fedOptions) {
130
- const result = [];
131
- for (const [mappedPath, mappedImport] of Object.entries(config.sharedMappings)) {
132
- result.push(toSharedMappingInfo(mappedPath, mappedImport, '', config, fedOptions));
133
- }
134
- return result;
135
- }
136
- function toSharedMappingInfo(mappedPath, mappedImport, outFileName, config, fedOptions) {
137
- const mappingVersion = config.features.mappingVersion
138
- ? getMappingVersion(mappedPath, fedOptions.workspaceRoot)
139
- : '';
140
- return {
141
- packageName: mappedImport,
142
- outFileName,
143
- requiredVersion: mappingVersion.length > 0 ? '~' + mappingVersion : '',
144
- singleton: true,
145
- strictVersion: config.features.mappingVersion,
146
- version: mappingVersion,
147
- dev: !fedOptions.dev
148
- ? undefined
149
- : {
150
- entryPoint: normalize(path.normalize(mappedPath)),
151
- },
152
- };
153
- }
154
- export function getMappingVersion(fileName, workspaceRoot) {
155
- const resolvedRoot = path.resolve(workspaceRoot);
156
- let dir = path.dirname(path.resolve(fileName));
157
- while (true) {
158
- const candidate = path.join(dir, 'package.json');
159
- try {
160
- const json = JSON.parse(fs.readFileSync(candidate, 'utf-8'));
161
- if (typeof json.version === 'string' && json.version)
162
- return json.version;
163
- }
164
- catch (err) {
165
- if (err.code !== 'ENOENT') {
166
- logger.warn(`[getMappingVersion] Failed to parse ${candidate}: ${err.message}`);
167
- }
168
- }
169
- const parent = path.dirname(dir);
170
- if (dir === resolvedRoot || parent === dir)
171
- return '';
172
- dir = parent;
173
- }
174
- }
@@ -1,13 +0,0 @@
1
- import type { NormalizedFederationConfig } from '../domain/config/federation-config.contract.js';
2
- import type { IntegrityMap, SharedInfo } from '../domain/core/federation-info.contract.js';
3
- import { type NormalizedFederationOptions } from '../domain/core/federation-options.contract.js';
4
- import type { NormalizedExternalConfig } from '../domain/config/external-config.contract.js';
5
- export declare function bundleShared(sharedBundles: Record<string, NormalizedExternalConfig>, config: NormalizedFederationConfig, fedOptions: NormalizedFederationOptions, externals: string[], buildOptions: {
6
- platform: 'browser' | 'node';
7
- bundleName: string;
8
- chunks: boolean;
9
- }): Promise<{
10
- externals: SharedInfo[];
11
- chunks?: Record<string, string[]>;
12
- integrity?: IntegrityMap;
13
- }>;
@@ -1,222 +0,0 @@
1
- import * as path from 'path';
2
- import * as fs from 'fs';
3
- import { getPackageInfo } from '../utils/package-info.js';
4
- import { logger } from '../utils/logger.js';
5
- import crypto from 'crypto';
6
- import { DEFAULT_EXTERNAL_LIST } from './default-external-list.js';
7
- import { isSourceFile, rewriteChunkImports } from '../utils/rewrite-chunk-imports.js';
8
- import { toChunkImport } from '../domain/core/chunk.js';
9
- import { cacheEntry, getChecksum, getFilename } from '../utils/cache-persistence.js';
10
- import { fileURLToPath } from 'url';
11
- import { getBuildAdapter } from './build-adapter.js';
12
- import { integrityForFile } from '../utils/hash-file.js';
13
- export async function bundleShared(sharedBundles, config, fedOptions, externals, buildOptions) {
14
- const checksum = getChecksum(sharedBundles, fedOptions.dev ? '1' : '0');
15
- const folder = fedOptions.packageJson
16
- ? path.dirname(fedOptions.packageJson)
17
- : fedOptions.workspaceRoot;
18
- const bundleCache = cacheEntry(fedOptions.federationCache.cachePath, getFilename(buildOptions.bundleName, fedOptions.dev));
19
- if (fedOptions?.cacheExternalArtifacts) {
20
- const cacheMetadata = bundleCache.getMetadata(checksum);
21
- if (cacheMetadata) {
22
- logger.debug(`Checksum of ${buildOptions.bundleName} matched, Skipped artifact bundling`);
23
- bundleCache.copyFiles(path.join(fedOptions.workspaceRoot, fedOptions.outputPath));
24
- let integrity = cacheMetadata.integrity;
25
- if (config.features.integrityHashes && !integrity) {
26
- integrity = computeIntegrityForFiles(cacheMetadata.files, fedOptions.federationCache.cachePath);
27
- }
28
- return {
29
- externals: cacheMetadata.externals,
30
- chunks: cacheMetadata.chunks,
31
- integrity,
32
- };
33
- }
34
- }
35
- bundleCache.clear();
36
- const inferredPackageInfos = Object.keys(sharedBundles)
37
- .filter(packageName => !sharedBundles[packageName]?.packageInfo)
38
- .map(packageName => getPackageInfo(packageName, folder))
39
- .filter(pi => !!pi);
40
- const configuredPackageInfos = Object.keys(sharedBundles)
41
- .filter(packageName => !!sharedBundles[packageName]?.packageInfo)
42
- .map(packageName => ({
43
- packageName,
44
- ...sharedBundles[packageName]?.packageInfo,
45
- }));
46
- const packageInfos = [...inferredPackageInfos, ...configuredPackageInfos];
47
- const __filename = fileURLToPath(import.meta.url);
48
- const configState = 'BUNDLER_CHUNKS' + // TODO: Replace this with lib version
49
- fs.readFileSync(path.join(path.dirname(__filename), '../../../package.json')) +
50
- JSON.stringify(config);
51
- const allEntryPoints = packageInfos.map(pi => {
52
- const encName = pi.packageName.replace(/[^A-Za-z0-9]/g, '_');
53
- const outName = createOutName(pi, configState, fedOptions, encName);
54
- return { fileName: pi.entryPoint, outName };
55
- });
56
- const fullOutputPath = path.join(fedOptions.workspaceRoot, fedOptions.outputPath);
57
- const expectedResults = allEntryPoints.map(ep => path.join(fullOutputPath, ep.outName));
58
- const entryPoints = allEntryPoints.filter(ep => !fs.existsSync(path.join(fedOptions.federationCache.cachePath, ep.outName)));
59
- // If we build for the browser and don't remote unused deps from the shared config,
60
- // we need to exclude typical node libs to avoid compilation issues
61
- const useDefaultExternalList = buildOptions.platform === 'browser' && !config.features.ignoreUnusedDeps;
62
- const additionalExternals = useDefaultExternalList ? DEFAULT_EXTERNAL_LIST : [];
63
- let bundleResult = null;
64
- try {
65
- await getBuildAdapter().setup(buildOptions.bundleName, {
66
- entryPoints,
67
- tsConfigPath: fedOptions.tsConfig,
68
- external: [...additionalExternals, ...externals],
69
- outdir: fedOptions.federationCache.cachePath,
70
- mappedPaths: config.sharedMappings,
71
- dev: fedOptions.dev,
72
- isMappingOrExposed: false,
73
- hash: false,
74
- chunks: buildOptions.chunks,
75
- platform: buildOptions.platform,
76
- optimizedMappings: config.features.ignoreUnusedDeps,
77
- cache: fedOptions.federationCache,
78
- });
79
- bundleResult = await getBuildAdapter().build(buildOptions.bundleName);
80
- await getBuildAdapter().dispose(buildOptions.bundleName);
81
- const cachedFiles = bundleResult.map(br => path.basename(br.fileName));
82
- rewriteImports(cachedFiles, fedOptions.federationCache.cachePath);
83
- }
84
- catch (e) {
85
- logger.error('Error bundling shared npm package ');
86
- if (e instanceof Error) {
87
- logger.error(e.message);
88
- }
89
- logger.error('For more information, run in verbose mode');
90
- logger.notice('');
91
- logger.notice('');
92
- logger.notice('** Important Information: ***');
93
- logger.notice('The error message above shows an issue with bundling a node_module.');
94
- logger.notice('In most cases this is because you (indirectly) shared a Node.js package,');
95
- logger.notice('while Native Federation builds for the browser.');
96
- logger.notice('You can move such packages into devDependencies or skip them in your federation.config.js.');
97
- logger.notice('');
98
- logger.notice('More Details: https://bit.ly/nf-issue');
99
- logger.notice('');
100
- logger.notice('');
101
- logger.verbose(e);
102
- throw e;
103
- }
104
- const outFileNames = [...expectedResults];
105
- const result = buildResult(packageInfos, sharedBundles, outFileNames);
106
- const chunks = bundleResult.filter(br => !br.fileName.endsWith('.map') &&
107
- !result.find(r => r.outFileName === path.basename(br.fileName)));
108
- /**
109
- * Chunking
110
- */
111
- let exportedChunks = undefined;
112
- if (buildOptions.chunks && config.features.denseChunking) {
113
- result.forEach(external => {
114
- external.bundle = buildOptions.bundleName;
115
- });
116
- if (chunks.length > 0) {
117
- exportedChunks = { [buildOptions.bundleName]: getChunkFileNames(chunks) };
118
- }
119
- }
120
- else {
121
- addChunksToResult(chunks, result);
122
- }
123
- const persistedFiles = bundleResult.map(r => r.fileName.split(path.sep).pop() ?? r.fileName);
124
- // Must run after rewriteImports so SRI matches the bytes copied to dist.
125
- const integrity = config.features.integrityHashes
126
- ? computeIntegrityForFiles(persistedFiles, fedOptions.federationCache.cachePath)
127
- : undefined;
128
- bundleCache.persist({
129
- checksum,
130
- externals: result,
131
- files: persistedFiles,
132
- chunks: exportedChunks,
133
- integrity,
134
- });
135
- bundleCache.copyFiles(path.join(fedOptions.workspaceRoot, fedOptions.outputPath));
136
- return { externals: result, chunks: exportedChunks, integrity };
137
- }
138
- function computeIntegrityForFiles(files, baseDir) {
139
- const integrity = {};
140
- for (const file of files) {
141
- if (file.endsWith('.map'))
142
- continue;
143
- const fullPath = path.join(baseDir, file);
144
- if (!fs.existsSync(fullPath))
145
- continue;
146
- integrity[path.basename(file)] = integrityForFile(fullPath);
147
- }
148
- return integrity;
149
- }
150
- function rewriteImports(cachedFiles, cachePath) {
151
- const newSourceFiles = cachedFiles.filter(cf => isSourceFile(cf));
152
- for (const sourceFile of newSourceFiles) {
153
- const sourceFilePath = path.join(cachePath, sourceFile);
154
- rewriteChunkImports(sourceFilePath);
155
- }
156
- }
157
- function createOutName(pi, configState, fedOptions, encName) {
158
- const hashBase = pi.version + '_' + pi.entryPoint + '_' + configState;
159
- const hash = calcHash(hashBase);
160
- const outName = fedOptions.dev ? `${encName}.${hash}-dev.js` : `${encName}.${hash}.js`;
161
- return outName;
162
- }
163
- function buildResult(packageInfos, sharedBundles, outFileNames) {
164
- return packageInfos.map(pi => {
165
- const shared = sharedBundles[pi.packageName];
166
- return {
167
- packageName: pi.packageName,
168
- outFileName: path.basename(outFileNames.shift() || ''),
169
- requiredVersion: shared?.requiredVersion,
170
- singleton: shared?.singleton,
171
- strictVersion: shared?.strictVersion,
172
- version: pi.version,
173
- ...(shared?.shareScope && { shareScope: shared.shareScope }),
174
- // TODO: Decide whether/when we need debug infos
175
- // dev: !fedOptions.dev
176
- // ? undefined
177
- // : {
178
- // entryPoint: normalize(pi.entryPoint),
179
- // },
180
- };
181
- });
182
- }
183
- function getChunkFileNames(chunks) {
184
- return chunks.map(chunk => path.basename(chunk.fileName));
185
- }
186
- function addChunksToResult(chunks, result) {
187
- for (const item of chunks) {
188
- const fileName = path.basename(item.fileName);
189
- result.push({
190
- singleton: false,
191
- strictVersion: false,
192
- // Here, the version does not matter because
193
- // a) a chunk split off by the bundler does
194
- // not have a version and b) it gets a hash
195
- // code as part of the file name to be unique
196
- // when requested via a _versioned_ package.
197
- //
198
- // For the same reason, we don't need to
199
- // take care of singleton and strictVersion.
200
- version: '0.0.0',
201
- requiredVersion: '0.0.0',
202
- packageName: toChunkImport(fileName),
203
- outFileName: fileName,
204
- // dev: dev
205
- // ? undefined
206
- // : {
207
- // entryPoint: normalize(fileName),
208
- // },
209
- });
210
- }
211
- }
212
- function calcHash(hashBase) {
213
- const hash = crypto
214
- .createHash('sha256')
215
- .update(hashBase)
216
- .digest('base64')
217
- .replace(/\//g, '_')
218
- .replace(/\+/g, '-')
219
- .replace(/=/g, '')
220
- .substring(0, 10);
221
- return hash;
222
- }
@@ -1,29 +0,0 @@
1
- const NODE_PACKAGES = [
2
- 'assert',
3
- 'buffer',
4
- 'child_process',
5
- 'cluster',
6
- 'crypto',
7
- 'dgram',
8
- 'dns',
9
- 'events',
10
- 'fs',
11
- 'http',
12
- 'https',
13
- 'module',
14
- 'net',
15
- 'os',
16
- 'path',
17
- 'querystring',
18
- 'readline',
19
- 'stream',
20
- 'timers',
21
- 'tls',
22
- 'tty',
23
- 'url',
24
- 'util',
25
- 'v8',
26
- 'vm',
27
- 'zlib',
28
- ];
29
- export const DEFAULT_EXTERNAL_LIST = NODE_PACKAGES.flatMap(p => [p, 'node:' + p]);
@@ -1,45 +0,0 @@
1
- import { getConfigContext, usePackageJson, useWorkspace } from '../config/configuration-context.js';
2
- import { getBuildAdapter, setBuildAdapter } from './build-adapter.js';
3
- import { buildForFederation } from './build-for-federation.js';
4
- import { getExternals } from './get-externals.js';
5
- import { normalizeFederationOptions } from './normalize-options.js';
6
- import { rebuildForFederation } from './rebuild-for-federation.js';
7
- let externals = [];
8
- let config;
9
- let options;
10
- let fedInfo;
11
- async function init(params) {
12
- setBuildAdapter(params.adapter);
13
- useWorkspace(params.options.workspaceRoot);
14
- usePackageJson(params.options.packageJson);
15
- params.options.workspaceRoot = getConfigContext().workspaceRoot ?? params.options.workspaceRoot;
16
- const normalized = await normalizeFederationOptions(params.options);
17
- options = normalized.options;
18
- config = normalized.config;
19
- externals = getExternals(config);
20
- }
21
- async function build(opts = {}) {
22
- if (!fedInfo) {
23
- fedInfo = await buildForFederation(config, options, externals, opts.signal);
24
- }
25
- else {
26
- fedInfo = await rebuildForFederation(config, options, externals, opts.modifiedFiles ?? [], opts.signal);
27
- }
28
- }
29
- async function close() {
30
- return getBuildAdapter().dispose();
31
- }
32
- export const federationBuilder = {
33
- init,
34
- build,
35
- close,
36
- get federationInfo() {
37
- return fedInfo;
38
- },
39
- get externals() {
40
- return externals;
41
- },
42
- get config() {
43
- return config;
44
- },
45
- };