@depup/module-federation__manifest 2.2.2-depup.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,446 @@
1
+ import { composeKeyWithSeparator } from "@module-federation/sdk";
2
+ import path from "path";
3
+ import { ContainerManager, RemoteManager, SharedManager } from "@module-federation/managers";
4
+ import { getFileNameWithOutExt } from "./utils.mjs";
5
+
6
+ ;// CONCATENATED MODULE: external "@module-federation/sdk"
7
+
8
+ ;// CONCATENATED MODULE: external "path"
9
+
10
+ ;// CONCATENATED MODULE: external "@module-federation/managers"
11
+
12
+ ;// CONCATENATED MODULE: external "./utils.mjs"
13
+
14
+ ;// CONCATENATED MODULE: ./src/ModuleHandler.ts
15
+
16
+
17
+
18
+
19
+ const isNonEmptyString = (value)=>{
20
+ return typeof value === 'string' && value.trim().length > 0;
21
+ };
22
+ const normalizeExposeValue = (exposeValue)=>{
23
+ if (!exposeValue) {
24
+ return undefined;
25
+ }
26
+ const toImportArray = (value)=>{
27
+ if (isNonEmptyString(value)) {
28
+ return [
29
+ value
30
+ ];
31
+ }
32
+ if (Array.isArray(value)) {
33
+ const normalized = value.filter(isNonEmptyString);
34
+ return normalized.length ? normalized : undefined;
35
+ }
36
+ return undefined;
37
+ };
38
+ if (typeof exposeValue === 'object') {
39
+ if ('import' in exposeValue) {
40
+ const { import: rawImport, name } = exposeValue;
41
+ const normalizedImport = toImportArray(rawImport);
42
+ if (!(normalizedImport === null || normalizedImport === void 0 ? void 0 : normalizedImport.length)) {
43
+ return undefined;
44
+ }
45
+ return {
46
+ import: normalizedImport,
47
+ ...isNonEmptyString(name) ? {
48
+ name
49
+ } : {}
50
+ };
51
+ }
52
+ return undefined;
53
+ }
54
+ const normalizedImport = toImportArray(exposeValue);
55
+ if (!(normalizedImport === null || normalizedImport === void 0 ? void 0 : normalizedImport.length)) {
56
+ return undefined;
57
+ }
58
+ return {
59
+ import: normalizedImport
60
+ };
61
+ };
62
+ const parseContainerExposeEntries = (identifier)=>{
63
+ const startIndex = identifier.indexOf('[');
64
+ if (startIndex < 0) {
65
+ return undefined;
66
+ }
67
+ let depth = 0;
68
+ let inString = false;
69
+ let isEscaped = false;
70
+ for(let cursor = startIndex; cursor < identifier.length; cursor++){
71
+ const char = identifier[cursor];
72
+ if (isEscaped) {
73
+ isEscaped = false;
74
+ continue;
75
+ }
76
+ if (char === '\\') {
77
+ isEscaped = true;
78
+ continue;
79
+ }
80
+ if (char === '"') {
81
+ inString = !inString;
82
+ continue;
83
+ }
84
+ if (inString) {
85
+ continue;
86
+ }
87
+ if (char === '[') {
88
+ depth++;
89
+ } else if (char === ']') {
90
+ depth--;
91
+ if (depth === 0) {
92
+ const serialized = identifier.slice(startIndex, cursor + 1);
93
+ try {
94
+ return JSON.parse(serialized);
95
+ } catch {
96
+ return undefined;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ return undefined;
102
+ };
103
+ const getExposeName = (exposeKey)=>{
104
+ return exposeKey.replace('./', '');
105
+ };
106
+ function getExposeItem({ exposeKey, name, file }) {
107
+ const exposeModuleName = getExposeName(exposeKey);
108
+ return {
109
+ path: exposeKey,
110
+ id: composeKeyWithSeparator(name, exposeModuleName),
111
+ name: exposeModuleName,
112
+ // @ts-ignore to deduplicate
113
+ requires: [],
114
+ file: path.relative(process.cwd(), file.import[0]),
115
+ assets: {
116
+ js: {
117
+ async: [],
118
+ sync: []
119
+ },
120
+ css: {
121
+ async: [],
122
+ sync: []
123
+ }
124
+ }
125
+ };
126
+ }
127
+ const getShareItem = ({ pkgName, normalizedShareOptions, pkgVersion, hostName })=>{
128
+ return {
129
+ ...normalizedShareOptions,
130
+ id: `${hostName}:${pkgName}`,
131
+ requiredVersion: (normalizedShareOptions === null || normalizedShareOptions === void 0 ? void 0 : normalizedShareOptions.requiredVersion) || `^${pkgVersion}`,
132
+ name: pkgName,
133
+ version: pkgVersion,
134
+ assets: {
135
+ js: {
136
+ async: [],
137
+ sync: []
138
+ },
139
+ css: {
140
+ async: [],
141
+ sync: []
142
+ }
143
+ },
144
+ // @ts-ignore to deduplicate
145
+ usedIn: new Set(),
146
+ usedExports: [],
147
+ fallback: ''
148
+ };
149
+ };
150
+ class ModuleHandler {
151
+ get isRspack() {
152
+ return this._bundler === 'rspack';
153
+ }
154
+ _handleSharedModule(mod, sharedMap, exposesMap) {
155
+ const { identifier, moduleType } = mod;
156
+ if (!identifier) {
157
+ return;
158
+ }
159
+ const sharedManagerNormalizedOptions = this._sharedManager.normalizedOptions;
160
+ const initShared = (pkgName, pkgVersion)=>{
161
+ if (sharedMap[pkgName]) {
162
+ return;
163
+ }
164
+ sharedMap[pkgName] = getShareItem({
165
+ pkgName,
166
+ pkgVersion,
167
+ normalizedShareOptions: sharedManagerNormalizedOptions[pkgName],
168
+ hostName: this._options.name
169
+ });
170
+ };
171
+ const collectRelationshipMap = (mod, pkgName)=>{
172
+ const { issuerName, reasons } = mod;
173
+ if (issuerName) {
174
+ if (exposesMap[getFileNameWithOutExt(issuerName)]) {
175
+ const expose = exposesMap[getFileNameWithOutExt(issuerName)];
176
+ // @ts-ignore use Set to deduplicate
177
+ expose.requires.push(pkgName);
178
+ // @ts-ignore use Set to deduplicate
179
+ sharedMap[pkgName].usedIn.add(expose.path);
180
+ }
181
+ }
182
+ if (reasons) {
183
+ reasons.forEach(({ resolvedModule, moduleName })=>{
184
+ let exposeModName = this.isRspack ? moduleName : resolvedModule;
185
+ // filters out entrypoints
186
+ if (exposeModName) {
187
+ if (exposesMap[getFileNameWithOutExt(exposeModName)]) {
188
+ const expose = exposesMap[getFileNameWithOutExt(exposeModName)];
189
+ // @ts-ignore to deduplicate
190
+ expose.requires.push(pkgName);
191
+ // @ts-ignore to deduplicate
192
+ sharedMap[pkgName].usedIn.add(expose.path);
193
+ }
194
+ }
195
+ });
196
+ }
197
+ };
198
+ const parseResolvedIdentifier = (nameAndVersion)=>{
199
+ let name = '';
200
+ let version = '';
201
+ if (nameAndVersion.startsWith('@')) {
202
+ const splitInfo = nameAndVersion.split('@');
203
+ splitInfo[0] = '@';
204
+ name = splitInfo[0] + splitInfo[1];
205
+ version = splitInfo[2];
206
+ } else if (nameAndVersion.includes('@')) {
207
+ [name, version] = nameAndVersion.split('@');
208
+ version = version.replace(/[\^~>|>=]/g, '');
209
+ }
210
+ return {
211
+ name,
212
+ version
213
+ };
214
+ };
215
+ if (moduleType === 'provide-module') {
216
+ // identifier(rspack) = provide shared module (default) react@18.2.0 = /temp/node_modules/.pnpm/react@18.2.0/node_modules/react/index.js
217
+ // identifier(webpack) = provide module (default) react@18.2.0 = /temp/node_modules/.pnpm/react@18.2.0/node_modules/react/index.js
218
+ const data = identifier.split(' ');
219
+ const nameAndVersion = this.isRspack ? data[4] : data[3];
220
+ const { name, version } = parseResolvedIdentifier(nameAndVersion);
221
+ if (name && version) {
222
+ initShared(name, version);
223
+ collectRelationshipMap(mod, name);
224
+ }
225
+ }
226
+ if (moduleType === 'consume-shared-module') {
227
+ // identifier(rspack) = consume shared module (default) lodash/get@^4.17.21 (strict) (fallback: /temp/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/get.js)
228
+ // identifier(webpack) = consume-shared-module|default|react-dom|!=1.8...2...0|false|/temp/node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/index.js|true|false
229
+ const SEPARATOR = this.isRspack ? ' ' : '|';
230
+ const data = identifier.split(SEPARATOR);
231
+ let pkgName = '';
232
+ let pkgVersion = '';
233
+ if (this.isRspack) {
234
+ const nameAndVersion = data[4];
235
+ const res = parseResolvedIdentifier(nameAndVersion);
236
+ pkgName = res.name;
237
+ pkgVersion = res.version;
238
+ } else {
239
+ pkgName = data[2];
240
+ const pkgVersionRange = data[3];
241
+ pkgVersion = '';
242
+ if (pkgVersionRange.startsWith('=')) {
243
+ pkgVersion = data[3].replace('=', '');
244
+ } else {
245
+ if (sharedManagerNormalizedOptions[pkgName]) {
246
+ pkgVersion = sharedManagerNormalizedOptions[pkgName].version;
247
+ } else {
248
+ const fullPkgName = pkgName.split('/').slice(0, -1).join('/');
249
+ // pkgName: react-dom/
250
+ if (sharedManagerNormalizedOptions[`${fullPkgName}/`]) {
251
+ if (sharedManagerNormalizedOptions[fullPkgName]) {
252
+ pkgVersion = sharedManagerNormalizedOptions[fullPkgName].version;
253
+ } else {
254
+ pkgVersion = sharedManagerNormalizedOptions[`${fullPkgName}/`].version;
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ if (pkgName && pkgVersion) {
261
+ initShared(pkgName, pkgVersion);
262
+ collectRelationshipMap(mod, pkgName);
263
+ }
264
+ }
265
+ }
266
+ _handleRemoteModule(mod, remotes, remotesConsumerMap) {
267
+ const { identifier, reasons, nameForCondition } = mod;
268
+ if (!identifier) {
269
+ return;
270
+ }
271
+ const remoteManagerNormalizedOptions = this._remoteManager.normalizedOptions;
272
+ // identifier = remote (default) webpack/container/reference/app2 ./Button
273
+ const data = identifier.split(' ');
274
+ if (data.length === 4) {
275
+ const moduleName = data[3].replace('./', '');
276
+ const remoteAlias = data[2].replace('webpack/container/reference/', '');
277
+ const normalizedRemote = remoteManagerNormalizedOptions[remoteAlias];
278
+ const basicRemote = {
279
+ alias: normalizedRemote.alias,
280
+ consumingFederationContainerName: this._options.name || '',
281
+ federationContainerName: remoteManagerNormalizedOptions[remoteAlias].name,
282
+ moduleName,
283
+ // @ts-ignore to deduplicate
284
+ usedIn: new Set()
285
+ };
286
+ if (!nameForCondition) {
287
+ return;
288
+ }
289
+ let remote;
290
+ if ('version' in normalizedRemote) {
291
+ remote = {
292
+ ...basicRemote,
293
+ version: normalizedRemote.version
294
+ };
295
+ } else {
296
+ remote = {
297
+ ...basicRemote,
298
+ entry: normalizedRemote.entry
299
+ };
300
+ }
301
+ remotes.push(remote);
302
+ remotesConsumerMap[nameForCondition] = remote;
303
+ }
304
+ if (reasons) {
305
+ reasons.forEach(({ userRequest, resolvedModule, moduleName })=>{
306
+ let exposeModName = this.isRspack ? moduleName : resolvedModule;
307
+ if (userRequest && exposeModName && remotesConsumerMap[userRequest]) {
308
+ // @ts-ignore to deduplicate
309
+ remotesConsumerMap[userRequest].usedIn.add(exposeModName.replace('./', ''));
310
+ }
311
+ });
312
+ }
313
+ }
314
+ _handleContainerModule(mod, exposesMap) {
315
+ const { identifier } = mod;
316
+ if (!identifier) {
317
+ return;
318
+ }
319
+ // identifier: container entry (default) [[".",{"import":["./src/routes/page.tsx"],"name":"__federation_expose_default_export"}]]'
320
+ const entries = parseContainerExposeEntries(identifier) ?? this._getContainerExposeEntriesFromOptions();
321
+ if (!entries) {
322
+ return;
323
+ }
324
+ entries.forEach(([prefixedName, file])=>{
325
+ // TODO: support multiple import
326
+ exposesMap[getFileNameWithOutExt(file.import[0])] = getExposeItem({
327
+ exposeKey: prefixedName,
328
+ name: this._options.name,
329
+ file
330
+ });
331
+ });
332
+ }
333
+ _getContainerExposeEntriesFromOptions() {
334
+ const exposes = this._containerManager.containerPluginExposesOptions;
335
+ const normalizedEntries = Object.entries(exposes).reduce((acc, [exposeKey, exposeOptions])=>{
336
+ const normalizedExpose = normalizeExposeValue(exposeOptions);
337
+ if (!(normalizedExpose === null || normalizedExpose === void 0 ? void 0 : normalizedExpose.import.length)) {
338
+ return acc;
339
+ }
340
+ acc.push([
341
+ exposeKey,
342
+ normalizedExpose
343
+ ]);
344
+ return acc;
345
+ }, []);
346
+ if (normalizedEntries.length) {
347
+ return normalizedEntries;
348
+ }
349
+ const rawExposes = this._options.exposes;
350
+ if (!rawExposes || Array.isArray(rawExposes)) {
351
+ return undefined;
352
+ }
353
+ const normalizedFromOptions = Object.entries(rawExposes).reduce((acc, [exposeKey, exposeOptions])=>{
354
+ const normalizedExpose = normalizeExposeValue(exposeOptions);
355
+ if (!(normalizedExpose === null || normalizedExpose === void 0 ? void 0 : normalizedExpose.import.length)) {
356
+ return acc;
357
+ }
358
+ acc.push([
359
+ exposeKey,
360
+ normalizedExpose
361
+ ]);
362
+ return acc;
363
+ }, []);
364
+ return normalizedFromOptions.length ? normalizedFromOptions : undefined;
365
+ }
366
+ _initializeExposesFromOptions(exposesMap) {
367
+ if (!this._options.name || !this._containerManager.enable) {
368
+ return;
369
+ }
370
+ const exposes = this._containerManager.containerPluginExposesOptions;
371
+ Object.entries(exposes).forEach(([exposeKey, exposeOptions])=>{
372
+ var _exposeOptions_import;
373
+ if (!((_exposeOptions_import = exposeOptions.import) === null || _exposeOptions_import === void 0 ? void 0 : _exposeOptions_import.length)) {
374
+ return;
375
+ }
376
+ const [exposeImport] = exposeOptions.import;
377
+ if (!exposeImport) {
378
+ return;
379
+ }
380
+ const exposeMapKey = getFileNameWithOutExt(exposeImport);
381
+ if (!exposesMap[exposeMapKey]) {
382
+ exposesMap[exposeMapKey] = getExposeItem({
383
+ exposeKey,
384
+ name: this._options.name,
385
+ file: exposeOptions
386
+ });
387
+ }
388
+ });
389
+ }
390
+ collect() {
391
+ const remotes = [];
392
+ const remotesConsumerMap = {};
393
+ const exposesMap = {};
394
+ const sharedMap = {};
395
+ this._initializeExposesFromOptions(exposesMap);
396
+ const isSharedModule = (moduleType)=>{
397
+ return Boolean(moduleType && [
398
+ 'provide-module',
399
+ 'consume-shared-module'
400
+ ].includes(moduleType));
401
+ };
402
+ const isContainerModule = (identifier)=>{
403
+ return identifier.startsWith('container entry');
404
+ };
405
+ const isRemoteModule = (identifier)=>{
406
+ return identifier.startsWith('remote ');
407
+ };
408
+ // handle remote/expose
409
+ this._modules.forEach((mod)=>{
410
+ const { identifier, reasons, nameForCondition, moduleType } = mod;
411
+ if (!identifier) {
412
+ return;
413
+ }
414
+ if (isSharedModule(moduleType)) {
415
+ this._handleSharedModule(mod, sharedMap, exposesMap);
416
+ }
417
+ if (isRemoteModule(identifier)) {
418
+ this._handleRemoteModule(mod, remotes, remotesConsumerMap);
419
+ } else if (isContainerModule(identifier)) {
420
+ this._handleContainerModule(mod, exposesMap);
421
+ }
422
+ });
423
+ return {
424
+ remotes,
425
+ exposesMap,
426
+ sharedMap
427
+ };
428
+ }
429
+ constructor(options, modules, { bundler }){
430
+ this._bundler = 'webpack';
431
+ this._remoteManager = new RemoteManager();
432
+ this._sharedManager = new SharedManager();
433
+ this._options = options;
434
+ this._modules = modules;
435
+ this._bundler = bundler;
436
+ this._containerManager = new ContainerManager();
437
+ this._containerManager.init(options);
438
+ this._remoteManager = new RemoteManager();
439
+ this._remoteManager.init(options);
440
+ this._sharedManager = new SharedManager();
441
+ this._sharedManager.init(options);
442
+ }
443
+ }
444
+
445
+
446
+ export { ModuleHandler, getExposeItem, getExposeName, getShareItem };
@@ -0,0 +1,29 @@
1
+ import { BasicStatsMetaData, StatsMetaData, Stats, moduleFederationPlugin } from '@module-federation/sdk';
2
+ import { Compilation, Compiler } from 'webpack';
3
+ declare class StatsManager {
4
+ private _options;
5
+ private _publicPath?;
6
+ private _pluginVersion?;
7
+ private _bundler;
8
+ private _containerManager;
9
+ private _remoteManager;
10
+ private _sharedManager;
11
+ private _pkgJsonManager;
12
+ private getBuildInfo;
13
+ get fileName(): string;
14
+ setMetaDataPublicPath(metaData: BasicStatsMetaData, compiler: Compiler): StatsMetaData;
15
+ private _getMetaData;
16
+ private _getFilteredModules;
17
+ private _getModuleAssets;
18
+ private _getProvideSharedAssets;
19
+ private _generateStats;
20
+ getPublicPath(compiler: Compiler): string;
21
+ init(options: moduleFederationPlugin.ModuleFederationPluginOptions, { pluginVersion, bundler, }: {
22
+ pluginVersion: string;
23
+ bundler: 'webpack' | 'rspack';
24
+ }): void;
25
+ updateStats(stats: Stats, compiler: Compiler): Stats;
26
+ generateStats(compiler: Compiler, compilation: Compilation): Promise<Stats>;
27
+ validate(compiler: Compiler): boolean;
28
+ }
29
+ export { StatsManager };