@module-federation/retry-plugin 2.5.1 → 2.7.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.
package/README.md CHANGED
@@ -93,18 +93,18 @@ export default () =>
93
93
 
94
94
  ### CommonRetryOptions
95
95
 
96
- | Option | Type | Default | Description |
97
- | ----------------- | --------------------- | ----------- | ---------------------------------------- |
98
- | `retryTimes` | `number` | `3` | Number of retry attempts |
99
- | `retryDelay` | `number` | `1000` | Delay between retries in milliseconds |
100
- | `successTimes` | `number` | `0` | Number of successful requests required |
101
- | `domains` | `string[]` | `[]` | Alternative domains for script resources |
102
- | `manifestDomains` | `string[]` | `[]` | Alternative domains for manifest files |
103
- | `addQuery` | `boolean \| function` | `false` | Add query parameters for cache busting |
104
- | `fetchOptions` | `RequestInit` | `{}` | Additional fetch options |
105
- | `onRetry` | `function` | `undefined` | Callback when retry occurs |
106
- | `onSuccess` | `function` | `undefined` | Callback when request succeeds |
107
- | `onError` | `function` | `undefined` | Callback when all retries fail |
96
+ | Option | Type | Default | Description |
97
+ | ----------------- | --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------ |
98
+ | `retryTimes` | `number` | `3` | Number of retry attempts |
99
+ | `retryDelay` | `number \| (attempt: number) => number` | `1000` | Delay between retries in milliseconds, or a function returning delay per 1-indexed retry attempt |
100
+ | `successTimes` | `number` | `0` | Number of successful requests required |
101
+ | `domains` | `string[]` | `[]` | Alternative domains for script resources |
102
+ | `manifestDomains` | `string[]` | `[]` | Alternative domains for manifest files |
103
+ | `addQuery` | `boolean \| function` | `false` | Add query parameters for cache busting |
104
+ | `fetchOptions` | `RequestInit` | `{}` | Additional fetch options |
105
+ | `onRetry` | `function` | `undefined` | Callback when retry occurs |
106
+ | `onSuccess` | `function` | `undefined` | Callback when request succeeds |
107
+ | `onError` | `function` | `undefined` | Callback when all retries fail |
108
108
 
109
109
  ### addQuery Function
110
110
 
@@ -142,7 +142,7 @@ onError: ({ domains, url, tagName }) => {
142
142
  ```ts
143
143
  RetryPlugin({
144
144
  retryTimes: 5,
145
- retryDelay: (attempt) => Math.pow(2, attempt) * 1000, // Exponential backoff
145
+ retryDelay: (attempt) => 1000 * 2 ** (attempt - 1), // Exponential backoff: 1s, 2s, 4s, ...
146
146
  domains: ['https://cdn1.example.com', 'https://cdn2.example.com', 'https://cdn3.example.com'],
147
147
  manifestDomains: ['https://api1.example.com', 'https://api2.example.com'],
148
148
  addQuery: ({ times, originalQuery }) => {
package/dist/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @module-federation/retry-plugin
2
2
 
3
+ ## 2.7.0
4
+
5
+ ### Patch Changes
6
+
7
+ - c103676: fix: externalize @module-federation/runtime and runtime-core from DTS bundle to prevent type incompatibility in consumers
8
+ - Updated dependencies [dcc640b]
9
+ - Updated dependencies [9958086]
10
+ - @module-federation/sdk@2.7.0
11
+ - @module-federation/runtime@2.7.0
12
+
13
+ ## 2.6.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 64719e2: Support function-based `retryDelay` for per-attempt delay strategies such as exponential backoff.
18
+
19
+ ### Patch Changes
20
+
21
+ - @module-federation/sdk@2.6.0
22
+
3
23
  ## 2.5.1
4
24
 
5
25
  ### Patch Changes
package/dist/README.md CHANGED
@@ -93,18 +93,18 @@ export default () =>
93
93
 
94
94
  ### CommonRetryOptions
95
95
 
96
- | Option | Type | Default | Description |
97
- | ----------------- | --------------------- | ----------- | ---------------------------------------- |
98
- | `retryTimes` | `number` | `3` | Number of retry attempts |
99
- | `retryDelay` | `number` | `1000` | Delay between retries in milliseconds |
100
- | `successTimes` | `number` | `0` | Number of successful requests required |
101
- | `domains` | `string[]` | `[]` | Alternative domains for script resources |
102
- | `manifestDomains` | `string[]` | `[]` | Alternative domains for manifest files |
103
- | `addQuery` | `boolean \| function` | `false` | Add query parameters for cache busting |
104
- | `fetchOptions` | `RequestInit` | `{}` | Additional fetch options |
105
- | `onRetry` | `function` | `undefined` | Callback when retry occurs |
106
- | `onSuccess` | `function` | `undefined` | Callback when request succeeds |
107
- | `onError` | `function` | `undefined` | Callback when all retries fail |
96
+ | Option | Type | Default | Description |
97
+ | ----------------- | --------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------ |
98
+ | `retryTimes` | `number` | `3` | Number of retry attempts |
99
+ | `retryDelay` | `number \| (attempt: number) => number` | `1000` | Delay between retries in milliseconds, or a function returning delay per 1-indexed retry attempt |
100
+ | `successTimes` | `number` | `0` | Number of successful requests required |
101
+ | `domains` | `string[]` | `[]` | Alternative domains for script resources |
102
+ | `manifestDomains` | `string[]` | `[]` | Alternative domains for manifest files |
103
+ | `addQuery` | `boolean \| function` | `false` | Add query parameters for cache busting |
104
+ | `fetchOptions` | `RequestInit` | `{}` | Additional fetch options |
105
+ | `onRetry` | `function` | `undefined` | Callback when retry occurs |
106
+ | `onSuccess` | `function` | `undefined` | Callback when request succeeds |
107
+ | `onError` | `function` | `undefined` | Callback when all retries fail |
108
108
 
109
109
  ### addQuery Function
110
110
 
@@ -142,7 +142,7 @@ onError: ({ domains, url, tagName }) => {
142
142
  ```ts
143
143
  RetryPlugin({
144
144
  retryTimes: 5,
145
- retryDelay: (attempt) => Math.pow(2, attempt) * 1000, // Exponential backoff
145
+ retryDelay: (attempt) => 1000 * 2 ** (attempt - 1), // Exponential backoff: 1s, 2s, 4s, ...
146
146
  domains: ['https://cdn1.example.com', 'https://cdn2.example.com', 'https://cdn3.example.com'],
147
147
  manifestDomains: ['https://api1.example.com', 'https://api2.example.com'],
148
148
  addQuery: ({ times, originalQuery }) => {
package/dist/esm/index.js CHANGED
@@ -144,7 +144,11 @@ async function fetchRetry(params, lastRequestUrl, originalTotal) {
144
144
  queryKey: "retryCount"
145
145
  });
146
146
  try {
147
- if (!isFirstAttempt && retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
147
+ if (!isFirstAttempt) {
148
+ const attemptIndex = total - retryTimes;
149
+ const delay = typeof retryDelay === "function" ? retryDelay(attemptIndex) : retryDelay;
150
+ if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
151
+ }
148
152
  const response = await fetch(requestUrl, fetchOptions);
149
153
  const responseClone = response.clone();
150
154
  if (!response.ok) throw new Error(`${PLUGIN_IDENTIFIER}: Request failed: ${response.status} ${response.statusText || ""} | url: ${requestUrl}`);
@@ -204,7 +208,8 @@ function scriptRetry({ retryOptions, retryFn, beforeExecuteRetry = () => {} }) {
204
208
  const maxAttempts = retryTimes;
205
209
  while (attempts < maxAttempts) try {
206
210
  beforeExecuteRetry();
207
- if (retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
211
+ const delay = typeof retryDelay === "function" ? retryDelay(attempts + 1) : retryDelay;
212
+ if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
208
213
  const retryIndex = attempts + 1;
209
214
  retryWrapper = await retryFn({
210
215
  ...params,
package/dist/index.d.ts CHANGED
@@ -1,766 +1,5 @@
1
- import { CreateLinkHookReturnDom, CreateScriptHookReturn, GlobalModuleInfo, Manifest, Module, ModuleInfo, RemoteEntryType, RemoteWithEntry, RemoteWithVersion, TreeShakingStatus } from "@module-federation/sdk";
1
+ import { ModuleFederationRuntimePlugin } from "@module-federation/runtime";
2
2
 
3
- //#region ../runtime-core/dist/utils/hooks/syncHook.d.ts
4
- //#region src/utils/hooks/syncHook.d.ts
5
- type Callback<T, K> = (...args: ArgsType<T>) => K;
6
- type ArgsType<T> = T extends Array<any> ? T : Array<any>;
7
- declare class SyncHook<T, K> {
8
- type: string;
9
- listeners: Set<Callback<T, K>>;
10
- constructor(type?: string);
11
- on(fn: Callback<T, K>): void;
12
- once(fn: Callback<T, K>): void;
13
- emit(...data: ArgsType<T>): void | K | Promise<any>;
14
- remove(fn: Callback<T, K>): void;
15
- removeAll(): void;
16
- } //#endregion
17
- //#endregion
18
- //#region ../runtime-core/dist/utils/hooks/asyncHook.d.ts
19
- //#region src/utils/hooks/asyncHook.d.ts
20
- type CallbackReturnType$1 = void | false | Promise<void | false>;
21
- declare class AsyncHook<T, ExternalEmitReturnType = CallbackReturnType$1> extends SyncHook<T, ExternalEmitReturnType> {
22
- emit(...data: ArgsType<T>): Promise<void | false | ExternalEmitReturnType>;
23
- } //#endregion
24
- //#endregion
25
- //#region ../runtime-core/dist/utils/hooks/syncWaterfallHook.d.ts
26
- //#region src/utils/hooks/syncWaterfallHook.d.ts
27
- declare class SyncWaterfallHook<T extends Record<string, any>> extends SyncHook<[T], T | void> {
28
- onerror: (errMsg: string | Error | unknown) => void;
29
- constructor(type: string);
30
- emit(data: T): T;
31
- } //#endregion
32
- //#endregion
33
- //#region ../runtime-core/dist/utils/hooks/asyncWaterfallHooks.d.ts
34
- //#region src/utils/hooks/asyncWaterfallHooks.d.ts
35
- type CallbackReturnType<T> = T | void | Promise<T | void>;
36
- declare class AsyncWaterfallHook<T extends object> extends SyncHook<[T], CallbackReturnType<T>> {
37
- onerror: (errMsg: string | Error | unknown) => void;
38
- constructor(type: string);
39
- emit(data: T): Promise<T>;
40
- } //#endregion
41
- //#endregion
42
- //#region ../runtime-core/dist/utils/hooks/pluginSystem.d.ts
43
- //#region src/utils/hooks/pluginSystem.d.ts
44
- type Plugin<T extends Record<string, any>> = { [k in keyof T]?: Parameters<T[k]['on']>[0] } & {
45
- name: string;
46
- version?: string;
47
- apply?: (instance: ModuleFederation) => void;
48
- };
49
- declare class PluginSystem<T extends Record<string, any>> {
50
- lifecycle: T;
51
- lifecycleKeys: Array<keyof T>;
52
- registerPlugins: Record<string, Plugin<T>>;
53
- constructor(lifecycle: T);
54
- applyPlugin(plugin: Plugin<T>, instance: ModuleFederation): void;
55
- removePlugin(pluginName: string): void;
56
- } //#endregion
57
- //#endregion
58
- //#region ../runtime-core/dist/type/config.d.ts
59
- //#region src/type/config.d.ts
60
- type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
61
- interface RemoteInfoCommon {
62
- alias?: string;
63
- shareScope?: string | string[];
64
- type?: RemoteEntryType;
65
- entryGlobalName?: string;
66
- }
67
- type Remote = (RemoteWithEntry | RemoteWithVersion) & RemoteInfoCommon;
68
- interface RemoteInfo {
69
- alias?: string;
70
- name: string;
71
- version?: string;
72
- buildVersion?: string;
73
- entry: string;
74
- type: RemoteEntryType;
75
- entryGlobalName: string;
76
- shareScope: string | string[];
77
- }
78
- interface SharedConfig {
79
- singleton?: boolean;
80
- requiredVersion: false | string;
81
- eager?: boolean;
82
- strictVersion?: boolean;
83
- layer?: string | null;
84
- }
85
- type TreeShakingArgs = {
86
- usedExports?: string[];
87
- get?: SharedGetter;
88
- lib?: () => Module;
89
- status?: TreeShakingStatus;
90
- mode?: 'server-calc' | 'runtime-infer';
91
- loading?: null | Promise<any>;
92
- loaded?: boolean;
93
- useIn?: Array<string>;
94
- };
95
- type SharedBaseArgs = {
96
- version?: string;
97
- shareConfig?: SharedConfig;
98
- scope?: string | Array<string>;
99
- deps?: Array<string>;
100
- strategy?: 'version-first' | 'loaded-first';
101
- loaded?: boolean;
102
- treeShaking?: TreeShakingArgs;
103
- };
104
- type SharedGetter = (() => () => Module) | (() => Promise<() => Module>);
105
- type ShareArgs = (SharedBaseArgs & {
106
- get: SharedGetter;
107
- }) | (SharedBaseArgs & {
108
- lib: () => Module;
109
- }) | SharedBaseArgs;
110
- type ShareStrategy = 'version-first' | 'loaded-first';
111
- type Shared = {
112
- version: string;
113
- get: SharedGetter;
114
- shareConfig: SharedConfig;
115
- scope: Array<string>;
116
- useIn: Array<string>;
117
- from: string;
118
- deps: Array<string>;
119
- lib?: () => Module;
120
- loaded?: boolean;
121
- loading?: null | Promise<any>;
122
- eager?: boolean;
123
- /**
124
- * @deprecated set in initOptions.shareStrategy instead
125
- */
126
- strategy: ShareStrategy;
127
- treeShaking?: TreeShakingArgs;
128
- };
129
- type ShareScopeMap = {
130
- [scope: string]: {
131
- [pkgName: string]: {
132
- [sharedVersion: string]: Shared;
133
- };
134
- };
135
- };
136
- type GlobalShareScopeMap = {
137
- [instanceName: string]: ShareScopeMap;
138
- };
139
- type ShareInfos = {
140
- [pkgName: string]: Shared[];
141
- };
142
- interface Options {
143
- id?: string;
144
- name: string;
145
- version?: string;
146
- remotes: Array<Remote>;
147
- shared: ShareInfos;
148
- plugins: Array<ModuleFederationRuntimePlugin>;
149
- inBrowser: boolean;
150
- shareStrategy?: ShareStrategy;
151
- }
152
- type UserOptions = Omit<Optional<Options, 'plugins'>, 'shared' | 'inBrowser'> & {
153
- shared?: {
154
- [pkgName: string]: ShareArgs | ShareArgs[];
155
- };
156
- };
157
- type RemoteEntryInitOptions = {
158
- version: string;
159
- shareScopeMap?: ShareScopeMap;
160
- shareScopeKeys: string | string[];
161
- };
162
- type InitTokens = Record<string, Record<string, any>>;
163
- type InitScope = InitTokens[];
164
- type CallFrom = 'build' | 'runtime';
165
- type RemoteEntryExports = {
166
- get: (id: string) => () => Promise<Module>;
167
- init: (shareScope: ShareScopeMap[string], initScope?: InitScope, remoteEntryInitOPtions?: RemoteEntryInitOptions) => void | Promise<void>;
168
- }; //#endregion
169
- //#endregion
170
- //#region ../runtime-core/dist/type/preload.d.ts
171
- //#region src/type/preload.d.ts
172
- type depsPreloadArg = Omit<PreloadRemoteArgs, 'depsRemote'>;
173
- interface PreloadRemoteArgs {
174
- nameOrAlias: string;
175
- exposes?: Array<string>;
176
- resourceCategory?: 'all' | 'sync';
177
- share?: boolean;
178
- depsRemote?: boolean | Array<depsPreloadArg>;
179
- filter?: (assetUrl: string) => boolean;
180
- }
181
- type PreloadConfig = PreloadRemoteArgs;
182
- type PreloadOptions = Array<{
183
- remote: Remote;
184
- preloadConfig: PreloadConfig;
185
- }>;
186
- type ResourceLoadInitiator = 'loadRemote' | 'preloadRemote';
187
- type ResourceLoadType = 'manifest' | 'remoteEntry' | 'js' | 'css';
188
- interface ResourceLoadContext {
189
- initiator: ResourceLoadInitiator;
190
- id: string;
191
- resourceType: ResourceLoadType;
192
- url?: string;
193
- }
194
- type PreloadAssetStatus = 'success' | 'error' | 'timeout' | 'cached';
195
- interface PreloadAssetResult {
196
- url: string;
197
- status: PreloadAssetStatus;
198
- resourceType: ResourceLoadType;
199
- initiator: ResourceLoadInitiator;
200
- id: string;
201
- error?: unknown;
202
- }
203
- interface PreloadRemoteResult {
204
- remote: Remote;
205
- remoteInfo: RemoteInfo;
206
- preloadConfig: PreloadConfig;
207
- id: string;
208
- results: PreloadAssetResult[];
209
- }
210
- type EntryAssets = {
211
- name: string;
212
- url: string;
213
- moduleInfo: RemoteInfo;
214
- };
215
- interface PreloadAssets {
216
- cssAssets: Array<string>;
217
- jsAssetsWithoutEntry: Array<string>;
218
- entryAssets: Array<EntryAssets>;
219
- } //#endregion
220
- //#endregion
221
- //#region ../runtime-core/dist/remote/index.d.ts
222
- //#region src/remote/index.d.ts
223
- interface LoadRemoteMatch {
224
- id: string;
225
- pkgNameOrAlias: string;
226
- expose: string;
227
- remote: Remote;
228
- options: Options;
229
- origin: ModuleFederation;
230
- remoteInfo: RemoteInfo;
231
- remoteSnapshot?: ModuleInfo;
232
- }
233
- declare class RemoteHandler {
234
- host: ModuleFederation;
235
- idToRemoteMap: Record<string, {
236
- name: string;
237
- expose: string;
238
- }>;
239
- hooks: PluginSystem<{
240
- beforeRegisterRemote: SyncWaterfallHook<{
241
- remote: Remote;
242
- origin: ModuleFederation;
243
- }>;
244
- registerRemote: SyncWaterfallHook<{
245
- remote: Remote;
246
- origin: ModuleFederation;
247
- }>;
248
- beforeRequest: AsyncWaterfallHook<{
249
- id: string;
250
- options: Options;
251
- origin: ModuleFederation;
252
- }>;
253
- afterMatchRemote: AsyncHook<[{
254
- id: string;
255
- options: Options;
256
- remote?: Remote;
257
- expose?: string;
258
- remoteInfo?: RemoteInfo;
259
- error?: unknown;
260
- origin: ModuleFederation;
261
- }], void>;
262
- onLoad: AsyncHook<[{
263
- id: string;
264
- expose: string;
265
- pkgNameOrAlias: string;
266
- remote: Remote;
267
- options: ModuleOptions;
268
- origin: ModuleFederation;
269
- exposeModule: any;
270
- exposeModuleFactory: any;
271
- moduleInstance: Module$1;
272
- }], unknown>;
273
- afterLoadRemote: AsyncHook<[{
274
- id: string;
275
- expose?: string;
276
- remote?: RemoteInfo;
277
- options?: {
278
- loadFactory?: boolean;
279
- from?: CallFrom;
280
- };
281
- error?: unknown;
282
- recovered?: boolean;
283
- origin: ModuleFederation;
284
- }], void>;
285
- handlePreloadModule: SyncHook<[{
286
- id: string;
287
- name: string;
288
- remote: Remote;
289
- remoteSnapshot: ModuleInfo;
290
- preloadConfig: PreloadRemoteArgs;
291
- origin: ModuleFederation;
292
- }], void>;
293
- errorLoadRemote: AsyncHook<[{
294
- id: string;
295
- error: unknown;
296
- options?: any;
297
- from: CallFrom;
298
- lifecycle: "beforeRequest" | "beforeLoadShare" | "afterResolve" | "onLoad";
299
- remote?: RemoteInfo;
300
- expose?: string;
301
- origin: ModuleFederation;
302
- }], unknown>;
303
- beforePreloadRemote: AsyncHook<[{
304
- preloadOps: Array<PreloadRemoteArgs>;
305
- options: Options;
306
- origin: ModuleFederation;
307
- }], false | void | Promise<false | void>>;
308
- generatePreloadAssets: AsyncHook<[{
309
- origin: ModuleFederation;
310
- preloadOptions: PreloadOptions[number];
311
- remote: Remote;
312
- remoteInfo: RemoteInfo;
313
- remoteSnapshot: ModuleInfo;
314
- globalSnapshot: GlobalModuleInfo;
315
- }], Promise<PreloadAssets>>;
316
- afterPreloadRemote: AsyncHook<[{
317
- preloadOps: Array<PreloadRemoteArgs>;
318
- options: Options;
319
- origin: ModuleFederation;
320
- results: PreloadRemoteResult[];
321
- error?: unknown;
322
- }], false | void | Promise<false | void>>;
323
- loadEntry: AsyncHook<[{
324
- origin: ModuleFederation;
325
- loaderHook: ModuleFederation["loaderHook"];
326
- remoteInfo: RemoteInfo;
327
- remoteEntryExports?: RemoteEntryExports;
328
- }], void | RemoteEntryExports | Promise<void | RemoteEntryExports>>;
329
- }>;
330
- constructor(host: ModuleFederation);
331
- formatAndRegisterRemote(globalOptions: Options, userOptions: UserOptions): Remote[];
332
- setIdToRemoteMap(id: string, remoteMatchInfo: LoadRemoteMatch): void;
333
- loadRemote<T>(id: string, options?: {
334
- loadFactory?: boolean;
335
- from: CallFrom;
336
- }): Promise<T | null>;
337
- preloadRemote(preloadOptions: Array<PreloadRemoteArgs>): Promise<void>;
338
- registerRemotes(remotes: Remote[], options?: {
339
- force?: boolean;
340
- }): void;
341
- getRemoteModuleAndOptions(options: {
342
- id: string;
343
- }): Promise<{
344
- module: Module$1;
345
- moduleOptions: ModuleOptions;
346
- remoteMatchInfo: LoadRemoteMatch;
347
- }>;
348
- registerRemote(remote: Remote, targetRemotes: Remote[], options?: {
349
- force?: boolean;
350
- }): void;
351
- private removeRemote;
352
- } //#endregion
353
- //#endregion
354
- //#region ../runtime-core/dist/shared/index.d.ts
355
- //#region src/shared/index.d.ts
356
- declare class SharedHandler {
357
- host: ModuleFederation;
358
- shareScopeMap: ShareScopeMap;
359
- hooks: PluginSystem<{
360
- beforeRegisterShare: SyncWaterfallHook<{
361
- pkgName: string;
362
- shared: Shared;
363
- origin: ModuleFederation;
364
- }>;
365
- afterResolve: AsyncWaterfallHook<LoadRemoteMatch>;
366
- beforeLoadShare: AsyncWaterfallHook<{
367
- pkgName: string;
368
- shareInfo?: Shared;
369
- shared: Options["shared"];
370
- origin: ModuleFederation;
371
- }>;
372
- loadShare: AsyncHook<[ModuleFederation, string, ShareInfos], false | void | Promise<false | void>>;
373
- afterLoadShare: SyncHook<[{
374
- pkgName: string;
375
- shareInfo?: Partial<Shared>;
376
- selectedShared?: Partial<Shared>;
377
- shared: Options["shared"];
378
- shareScopeMap: ShareScopeMap;
379
- lifecycle: "loadShare" | "loadShareSync";
380
- origin: ModuleFederation;
381
- }], void>;
382
- errorLoadShare: SyncHook<[{
383
- pkgName: string;
384
- shareInfo?: Partial<Shared>;
385
- shared: Options["shared"];
386
- shareScopeMap: ShareScopeMap;
387
- lifecycle: "loadShare" | "loadShareSync";
388
- origin: ModuleFederation;
389
- error?: unknown;
390
- recovered?: boolean;
391
- }], void>;
392
- resolveShare: SyncWaterfallHook<{
393
- shareScopeMap: ShareScopeMap;
394
- scope: string;
395
- pkgName: string;
396
- version: string;
397
- shareInfo: Shared;
398
- GlobalFederation: Federation;
399
- resolver: () => {
400
- shared: Shared;
401
- useTreesShaking: boolean;
402
- } | undefined;
403
- }>;
404
- initContainerShareScopeMap: SyncWaterfallHook<{
405
- shareScope: ShareScopeMap[string];
406
- options: Options;
407
- origin: ModuleFederation;
408
- scopeName: string;
409
- hostShareScopeMap?: ShareScopeMap;
410
- }>;
411
- }>;
412
- initTokens: InitTokens;
413
- constructor(host: ModuleFederation);
414
- private emitAfterLoadShare;
415
- private emitErrorLoadShare;
416
- registerShared(globalOptions: Options, userOptions: UserOptions): {
417
- newShareInfos: ShareInfos;
418
- allShareInfos: {
419
- [pkgName: string]: Shared[];
420
- };
421
- };
422
- loadShare<T>(pkgName: string, extraOptions?: {
423
- customShareInfo?: Partial<Shared>;
424
- resolver?: (sharedOptions: ShareInfos[string]) => Shared;
425
- }): Promise<false | (() => T | undefined)>;
426
- /**
427
- * This function initializes the sharing sequence (executed only once per share scope).
428
- * It accepts one argument, the name of the share scope.
429
- * If the share scope does not exist, it creates one.
430
- */
431
- initializeSharing(shareScopeName?: string, extraOptions?: {
432
- initScope?: InitScope;
433
- from?: CallFrom;
434
- strategy?: ShareStrategy;
435
- }): Array<Promise<void>>;
436
- loadShareSync<T>(pkgName: string, extraOptions?: {
437
- from?: 'build' | 'runtime';
438
- customShareInfo?: Partial<Shared>;
439
- resolver?: (sharedOptions: ShareInfos[string]) => Shared;
440
- }): () => T | never;
441
- initShareScopeMap(scopeName: string, shareScope: ShareScopeMap[string], extraOptions?: {
442
- hostShareScopeMap?: ShareScopeMap;
443
- }): void;
444
- private setShared;
445
- private _setGlobalShareScopeMap;
446
- } //#endregion
447
- //#endregion
448
- //#region ../runtime-core/dist/type/plugin.d.ts
449
- //#region src/type/plugin.d.ts
450
- type CoreLifeCycle = ModuleFederation['hooks']['lifecycle'];
451
- type CoreLifeCyclePartial = Partial<{ [k in keyof CoreLifeCycle]: Parameters<CoreLifeCycle[k]['on']>[0] }>;
452
- type SnapshotLifeCycle = SnapshotHandler['hooks']['lifecycle'];
453
- type SnapshotLifeCycleCyclePartial = Partial<{ [k in keyof SnapshotLifeCycle]: Parameters<SnapshotLifeCycle[k]['on']>[0] }>;
454
- type ModuleLifeCycle = Module$1['host']['loaderHook']['lifecycle'];
455
- type ModuleLifeCycleCyclePartial = Partial<{ [k in keyof ModuleLifeCycle]: Parameters<ModuleLifeCycle[k]['on']>[0] }>;
456
- type ModuleBridgeLifeCycle = Module$1['host']['bridgeHook']['lifecycle'];
457
- type ModuleBridgeLifeCycleCyclePartial = Partial<{ [k in keyof ModuleBridgeLifeCycle]: Parameters<ModuleBridgeLifeCycle[k]['on']>[0] }>;
458
- type SharedLifeCycle = SharedHandler['hooks']['lifecycle'];
459
- type SharedLifeCycleCyclePartial = Partial<{ [k in keyof SharedLifeCycle]: Parameters<SharedLifeCycle[k]['on']>[0] }>;
460
- type RemoteLifeCycle = RemoteHandler['hooks']['lifecycle'];
461
- type RemoteLifeCycleCyclePartial = Partial<{ [k in keyof RemoteLifeCycle]: Parameters<RemoteLifeCycle[k]['on']>[0] }>;
462
- type ModuleFederationRuntimePlugin = CoreLifeCyclePartial & SnapshotLifeCycleCyclePartial & SharedLifeCycleCyclePartial & RemoteLifeCycleCyclePartial & ModuleLifeCycleCyclePartial & ModuleBridgeLifeCycleCyclePartial & {
463
- name: string;
464
- version?: string;
465
- apply?: (instance: ModuleFederation) => void;
466
- }; //#endregion
467
- //#endregion
468
- //#region ../runtime-core/dist/global.d.ts
469
- //#region src/global.d.ts
470
- interface Federation {
471
- __GLOBAL_PLUGIN__: Array<ModuleFederationRuntimePlugin>;
472
- __DEBUG_CONSTRUCTOR_VERSION__?: string;
473
- moduleInfo: GlobalModuleInfo;
474
- __DEBUG_CONSTRUCTOR__?: typeof ModuleFederation;
475
- __INSTANCES__: Array<ModuleFederation>;
476
- __SHARE__: GlobalShareScopeMap;
477
- __MANIFEST_LOADING__: Record<string, Promise<ModuleInfo>>;
478
- __PRELOADED_MAP__: Map<string, boolean>;
479
- }
480
- declare global {
481
- var __FEDERATION__: Federation, __VMOK__: Federation, __GLOBAL_LOADING_REMOTE_ENTRY__: Record<string, undefined | Promise<RemoteEntryExports | void>>;
482
- }
483
- declare const getGlobalSnapshot: () => GlobalModuleInfo;
484
- //#endregion
485
- //#region ../runtime-core/dist/plugins/snapshot/SnapshotHandler.d.ts
486
- //#region src/plugins/snapshot/SnapshotHandler.d.ts
487
- declare class SnapshotHandler {
488
- loadingHostSnapshot: Promise<GlobalModuleInfo | void> | null;
489
- HostInstance: ModuleFederation;
490
- manifestCache: Map<string, Manifest>;
491
- hooks: PluginSystem<{
492
- beforeLoadRemoteSnapshot: AsyncHook<[{
493
- options: Options;
494
- moduleInfo: Remote;
495
- origin: ModuleFederation;
496
- }], void>;
497
- loadSnapshot: AsyncWaterfallHook<{
498
- options: Options;
499
- moduleInfo: Remote;
500
- hostGlobalSnapshot: GlobalModuleInfo[string] | undefined;
501
- globalSnapshot: ReturnType<typeof getGlobalSnapshot>;
502
- remoteSnapshot?: GlobalModuleInfo[string] | undefined;
503
- }>;
504
- loadRemoteSnapshot: AsyncWaterfallHook<{
505
- options: Options;
506
- moduleInfo: Remote;
507
- manifestJson?: Manifest;
508
- manifestUrl?: string;
509
- remoteSnapshot: ModuleInfo;
510
- from: "global" | "manifest";
511
- }>;
512
- afterLoadSnapshot: AsyncWaterfallHook<{
513
- id?: string;
514
- host: ModuleFederation;
515
- options: Options;
516
- moduleInfo: Remote;
517
- remoteSnapshot: ModuleInfo;
518
- }>;
519
- }>;
520
- loaderHook: ModuleFederation['loaderHook'];
521
- manifestLoading: Record<string, Promise<ModuleInfo>>;
522
- constructor(HostInstance: ModuleFederation);
523
- loadRemoteSnapshotInfo({
524
- moduleInfo,
525
- id,
526
- initiator
527
- }: {
528
- moduleInfo: Remote;
529
- id?: string;
530
- initiator?: ResourceLoadInitiator;
531
- }): Promise<{
532
- remoteSnapshot: ModuleInfo;
533
- globalSnapshot: GlobalModuleInfo;
534
- }> | never;
535
- getGlobalRemoteInfo(moduleInfo: Remote): {
536
- hostGlobalSnapshot: ModuleInfo | undefined;
537
- globalSnapshot: ReturnType<typeof getGlobalSnapshot>;
538
- remoteSnapshot: GlobalModuleInfo[string] | undefined;
539
- };
540
- private getManifestJson;
541
- private loadManifestSnapshot;
542
- } //#endregion
543
- //#endregion
544
- //#region ../runtime-core/dist/utils/load.d.ts
545
- //#region src/utils/load.d.ts
546
- declare function getRemoteEntry(params: {
547
- origin: ModuleFederation;
548
- remoteInfo: RemoteInfo;
549
- remoteEntryExports?: RemoteEntryExports | undefined;
550
- getEntryUrl?: (url: string) => string;
551
- _inErrorHandling?: boolean;
552
- resourceContext?: ResourceLoadContext;
553
- }): Promise<RemoteEntryExports | false | void>;
554
- //#endregion
555
- //#region ../runtime-core/dist/core.d.ts
556
- //#region src/core.d.ts
557
- declare class ModuleFederation {
558
- options: Options;
559
- hooks: PluginSystem<{
560
- beforeInit: SyncWaterfallHook<{
561
- userOptions: UserOptions;
562
- options: Options;
563
- origin: ModuleFederation;
564
- /**
565
- * @deprecated shareInfo will be removed soon, please use userOptions directly!
566
- */
567
- shareInfo: ShareInfos;
568
- }>;
569
- init: SyncHook<[{
570
- options: Options;
571
- origin: ModuleFederation;
572
- }], void>;
573
- beforeInitContainer: AsyncWaterfallHook<{
574
- shareScope: ShareScopeMap[string];
575
- initScope: InitScope;
576
- remoteEntryInitOptions: RemoteEntryInitOptions;
577
- remoteInfo: RemoteInfo;
578
- origin: ModuleFederation;
579
- }>;
580
- initContainer: AsyncWaterfallHook<{
581
- shareScope: ShareScopeMap[string];
582
- initScope: InitScope;
583
- remoteEntryInitOptions: RemoteEntryInitOptions;
584
- remoteInfo: RemoteInfo;
585
- remoteEntryExports: RemoteEntryExports;
586
- origin: ModuleFederation;
587
- id?: string;
588
- remoteSnapshot?: ModuleInfo;
589
- }>;
590
- }>;
591
- version: string;
592
- name: string;
593
- moduleCache: Map<string, Module$1>;
594
- snapshotHandler: SnapshotHandler;
595
- sharedHandler: SharedHandler;
596
- remoteHandler: RemoteHandler;
597
- shareScopeMap: ShareScopeMap;
598
- loaderHook: PluginSystem<{
599
- getModuleInfo: SyncHook<[{
600
- target: Record<string, any>;
601
- key: any;
602
- }], void | {
603
- value: any | undefined;
604
- key: string;
605
- }>;
606
- createScript: SyncHook<[{
607
- url: string;
608
- attrs?: Record<string, any>;
609
- /**
610
- * The producer(remote) info bound to this resource.
611
- * Only present when the loader is invoked in a remote-related context
612
- * (e.g. preloadRemote / loading remoteEntry).
613
- */
614
- remoteInfo?: RemoteInfo;
615
- resourceContext?: ResourceLoadContext;
616
- }], CreateScriptHookReturn>;
617
- createLink: SyncHook<[{
618
- url: string;
619
- attrs?: Record<string, any>;
620
- /**
621
- * The producer(remote) info bound to this resource.
622
- * Only present when the loader is invoked in a remote-related context
623
- * (e.g. preloadRemote / loading remoteEntry).
624
- */
625
- remoteInfo?: RemoteInfo;
626
- resourceContext?: ResourceLoadContext;
627
- }], CreateLinkHookReturnDom>;
628
- fetch: AsyncHook<[string, RequestInit, (RemoteInfo | undefined)?, (ResourceLoadContext | undefined)?], false | void | Promise<Response>>;
629
- loadEntryError: AsyncHook<[{
630
- getRemoteEntry: typeof getRemoteEntry;
631
- origin: ModuleFederation;
632
- remoteInfo: RemoteInfo;
633
- remoteEntryExports?: RemoteEntryExports | undefined;
634
- globalLoading: Record<string, Promise<void | RemoteEntryExports> | undefined>;
635
- uniqueKey: string;
636
- }], Promise<Promise<RemoteEntryExports | undefined> | undefined>>;
637
- afterLoadEntry: AsyncHook<[{
638
- origin: ModuleFederation;
639
- remoteInfo: RemoteInfo;
640
- remoteEntryExports?: false | void | RemoteEntryExports | undefined;
641
- error?: unknown;
642
- recovered?: boolean;
643
- }], void>;
644
- beforeInitRemote: AsyncHook<[{
645
- id?: string;
646
- remoteInfo: RemoteInfo;
647
- remoteSnapshot?: ModuleInfo;
648
- origin: ModuleFederation;
649
- }], void>;
650
- afterInitRemote: AsyncHook<[{
651
- id?: string;
652
- remoteInfo: RemoteInfo;
653
- remoteSnapshot?: ModuleInfo;
654
- remoteEntryExports?: RemoteEntryExports;
655
- error?: unknown;
656
- cached?: boolean;
657
- origin: ModuleFederation;
658
- }], void>;
659
- beforeGetExpose: AsyncHook<[{
660
- id: string;
661
- expose: string;
662
- moduleInfo: RemoteInfo;
663
- remoteEntryExports: RemoteEntryExports;
664
- origin: ModuleFederation;
665
- }], void>;
666
- afterGetExpose: AsyncHook<[{
667
- id: string;
668
- expose: string;
669
- moduleInfo: RemoteInfo;
670
- remoteEntryExports: RemoteEntryExports;
671
- moduleFactory?: RemoteModuleFactory;
672
- error?: unknown;
673
- origin: ModuleFederation;
674
- }], void>;
675
- beforeExecuteFactory: AsyncHook<[{
676
- id: string;
677
- expose: string;
678
- moduleInfo: RemoteInfo;
679
- loadFactory: boolean;
680
- origin: ModuleFederation;
681
- }], void>;
682
- afterExecuteFactory: AsyncHook<[{
683
- id: string;
684
- expose: string;
685
- moduleInfo: RemoteInfo;
686
- loadFactory: boolean;
687
- exposeModule?: unknown;
688
- error?: unknown;
689
- origin: ModuleFederation;
690
- }], void>;
691
- getModuleFactory: AsyncHook<[{
692
- remoteEntryExports: RemoteEntryExports;
693
- expose: string;
694
- moduleInfo: RemoteInfo;
695
- }], RemoteModuleFactory | Promise<RemoteModuleFactory | undefined> | undefined>;
696
- }>;
697
- bridgeHook: PluginSystem<{
698
- beforeBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>;
699
- afterBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>;
700
- beforeBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>;
701
- afterBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>;
702
- }>;
703
- moduleInfo?: GlobalModuleInfo[string];
704
- constructor(userOptions: UserOptions);
705
- initOptions(userOptions: UserOptions): Options;
706
- loadShare<T>(pkgName: string, extraOptions?: {
707
- customShareInfo?: Partial<Shared>;
708
- resolver?: (sharedOptions: ShareInfos[string]) => Shared;
709
- }): Promise<false | (() => T | undefined)>;
710
- loadShareSync<T>(pkgName: string, extraOptions?: {
711
- customShareInfo?: Partial<Shared>;
712
- from?: 'build' | 'runtime';
713
- resolver?: (sharedOptions: ShareInfos[string]) => Shared;
714
- }): () => T | never;
715
- initializeSharing(shareScopeName?: string, extraOptions?: {
716
- initScope?: InitScope;
717
- from?: CallFrom;
718
- strategy?: Shared['strategy'];
719
- }): Array<Promise<void>>;
720
- initRawContainer(name: string, url: string, container: RemoteEntryExports): Module$1;
721
- loadRemote<T>(id: string, options?: {
722
- loadFactory?: boolean;
723
- from: CallFrom;
724
- }): Promise<T | null>;
725
- preloadRemote(preloadOptions: Array<PreloadRemoteArgs>): Promise<void>;
726
- initShareScopeMap(scopeName: string, shareScope: ShareScopeMap[string], extraOptions?: {
727
- hostShareScopeMap?: ShareScopeMap;
728
- }): void;
729
- formatOptions(globalOptions: Options, userOptions: UserOptions): Options;
730
- registerPlugins(plugins: UserOptions['plugins']): void;
731
- registerRemotes(remotes: Remote[], options?: {
732
- force?: boolean;
733
- }): void;
734
- registerShared(shared: UserOptions['shared']): void;
735
- } //#endregion
736
- //#endregion
737
- //#region ../runtime-core/dist/module/index.d.ts
738
- //#region src/module/index.d.ts
739
- type ModuleOptions = ConstructorParameters<typeof Module$1>[0];
740
- type RemoteModuleFactory = () => unknown | Promise<unknown>;
741
- declare class Module$1 {
742
- remoteInfo: RemoteInfo;
743
- inited: boolean;
744
- initing: boolean;
745
- initPromise?: Promise<void>;
746
- remoteEntryExports?: RemoteEntryExports;
747
- lib: RemoteEntryExports | undefined;
748
- host: ModuleFederation;
749
- constructor({
750
- remoteInfo,
751
- host
752
- }: {
753
- remoteInfo: RemoteInfo;
754
- host: ModuleFederation;
755
- });
756
- getEntry(expose?: string): Promise<RemoteEntryExports>;
757
- init(id?: string, remoteSnapshot?: ModuleInfo, rawInitScope?: InitScope, expose?: string): Promise<RemoteEntryExports>;
758
- get(id: string, expose: string, options?: {
759
- loadFactory?: boolean;
760
- }, remoteSnapshot?: ModuleInfo): Promise<unknown>;
761
- private wraperFactory;
762
- } //#endregion
763
- //#endregion
764
3
  //#region src/types.d.ts
765
4
  type CommonRetryOptions = {
766
5
  /**
@@ -776,9 +15,10 @@ type CommonRetryOptions = {
776
15
  */
777
16
  successTimes?: number;
778
17
  /**
779
- * retry delay
18
+ * retry delay in milliseconds, or a function that returns delay per attempt.
19
+ * When a function, `attempt` is 1-indexed (the nth retry, not the initial call).
780
20
  */
781
- retryDelay?: number;
21
+ retryDelay?: number | ((attempt: number) => number);
782
22
  /**
783
23
  * retry path
784
24
  */
package/dist/index.js CHANGED
@@ -145,7 +145,11 @@ async function fetchRetry(params, lastRequestUrl, originalTotal) {
145
145
  queryKey: "retryCount"
146
146
  });
147
147
  try {
148
- if (!isFirstAttempt && retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
148
+ if (!isFirstAttempt) {
149
+ const attemptIndex = total - retryTimes;
150
+ const delay = typeof retryDelay === "function" ? retryDelay(attemptIndex) : retryDelay;
151
+ if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
152
+ }
149
153
  const response = await fetch(requestUrl, fetchOptions);
150
154
  const responseClone = response.clone();
151
155
  if (!response.ok) throw new Error(`${PLUGIN_IDENTIFIER}: Request failed: ${response.status} ${response.statusText || ""} | url: ${requestUrl}`);
@@ -205,7 +209,8 @@ function scriptRetry({ retryOptions, retryFn, beforeExecuteRetry = () => {} }) {
205
209
  const maxAttempts = retryTimes;
206
210
  while (attempts < maxAttempts) try {
207
211
  beforeExecuteRetry();
208
- if (retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
212
+ const delay = typeof retryDelay === "function" ? retryDelay(attempts + 1) : retryDelay;
213
+ if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
209
214
  const retryIndex = attempts + 1;
210
215
  retryWrapper = await retryFn({
211
216
  ...params,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/retry-plugin",
3
- "version": "2.5.1",
3
+ "version": "2.7.0",
4
4
  "author": "danpeen <dapeen.feng@gmail.com>",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -32,15 +32,18 @@
32
32
  ]
33
33
  }
34
34
  },
35
+ "peerDependencies": {
36
+ "@module-federation/runtime": "*"
37
+ },
35
38
  "devDependencies": {
36
- "@module-federation/runtime": "2.5.1"
39
+ "@module-federation/runtime": "2.7.0"
37
40
  },
38
41
  "dependencies": {
39
- "@module-federation/sdk": "2.5.1"
42
+ "@module-federation/sdk": "2.7.0"
40
43
  },
41
44
  "scripts": {
42
45
  "build": "tsdown --config tsdown.config.ts && cp *.md dist",
43
- "test": "vitest run -u -c vitest.config.ts",
46
+ "test": "rstest -u",
44
47
  "lint": "ESLINT_USE_FLAT_CONFIG=false pnpm exec eslint --ignore-pattern node_modules \"**/*.ts\" \"package.json\"",
45
48
  "build-debug": "FEDERATION_DEBUG=true pnpm run build",
46
49
  "pre-release": "pnpm run test && pnpm run build"