@bleedingdev/modern-js-runtime-extensions 3.9.0-ultramodern.5 → 3.9.0-ultramodern.6
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/dist/cjs/routerProvider.js +9 -74
- package/dist/esm/routerProvider.mjs +8 -67
- package/dist/esm-node/routerProvider.mjs +8 -67
- package/dist/types/routerProvider.d.ts +2 -24
- package/dist/types/server-config/bffRuntime.d.ts +2 -2
- package/dist/types/server-config/serverTelemetry.d.ts +27 -27
- package/package.json +4 -4
- package/src/routerProvider.ts +14 -194
- package/src/server-config/bffRuntime.ts +2 -2
- package/src/server-config/serverTelemetry.ts +27 -27
- package/tests/routerProvider.test.ts +2 -11
|
@@ -30,10 +30,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
30
30
|
__webpack_require__.d(__webpack_exports__, {
|
|
31
31
|
createRouterPlugin: ()=>createRouterPlugin,
|
|
32
32
|
createRouterProviderRealm: ()=>createRouterProviderRealm,
|
|
33
|
-
registerRouterProvider: ()=>registerRouterProvider,
|
|
34
33
|
reportUnsupportedProviderRegistryHooks: ()=>reportUnsupportedProviderRegistryHooks,
|
|
35
|
-
resolveRouterProvider: ()=>resolveRouterProvider
|
|
36
|
-
unsafe_resetRouterProvidersForTesting: ()=>unsafe_resetRouterProvidersForTesting
|
|
34
|
+
resolveRouterProvider: ()=>resolveRouterProvider
|
|
37
35
|
});
|
|
38
36
|
const merge_namespaceObject = require("@modern-js/runtime-utils/merge");
|
|
39
37
|
function reportUnsupportedProviderRegistryHooks(providerPlugin, routerProviderRegistryHooks) {
|
|
@@ -62,74 +60,15 @@ function createRouterProviderRealm(registrations) {
|
|
|
62
60
|
names: ()=>providerNames
|
|
63
61
|
});
|
|
64
62
|
}
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
warnedDuplicates: new Set()
|
|
73
|
-
};
|
|
74
|
-
host[REGISTRY_SLOT].duplicateProviders ??= new Set();
|
|
75
|
-
host[REGISTRY_SLOT].warnedDuplicates ??= new Set();
|
|
76
|
-
return host[REGISTRY_SLOT];
|
|
77
|
-
}
|
|
78
|
-
function getLegacyV2Registry() {
|
|
79
|
-
const host = globalThis;
|
|
80
|
-
return host[LEGACY_V2_REGISTRY_SLOT];
|
|
81
|
-
}
|
|
82
|
-
function registerRouterProvider(name, factory, options = {}) {
|
|
83
|
-
const registry = getRegistry();
|
|
84
|
-
const existing = registry.providers.get(name);
|
|
85
|
-
if (void 0 !== existing) {
|
|
86
|
-
if (existing !== factory) registry.duplicateProviders.add(name);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (true === options.isDefault) registry.defaultProvider = name;
|
|
90
|
-
registry.providers.set(name, factory);
|
|
91
|
-
}
|
|
92
|
-
function resolveRouterProvider(framework, options = {}) {
|
|
93
|
-
if (void 0 !== options.realm) {
|
|
94
|
-
const name = framework || options.realm.defaultProvider;
|
|
95
|
-
const realmProviderNames = options.realm.names();
|
|
96
|
-
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
97
|
-
const factory = options.realm.get(name);
|
|
98
|
-
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}. Compatibility registry fallback is disabled for app-owned realms.`);
|
|
99
|
-
return factory;
|
|
100
|
-
}
|
|
101
|
-
const registry = getRegistry();
|
|
102
|
-
const legacyV2Registry = getLegacyV2Registry();
|
|
103
|
-
const name = framework || options.localDefault?.name || registry.defaultProvider || legacyV2Registry?.defaultProvider;
|
|
104
|
-
if (void 0 === name) throw new Error('[@modern-js/runtime] No default router provider is registered. This is a bug in the runtime setup.');
|
|
105
|
-
if (void 0 !== options.localDefault && name === options.localDefault.name) return options.localDefault.factory;
|
|
106
|
-
const factory = registry.providers.get(name);
|
|
107
|
-
if (void 0 !== factory) {
|
|
108
|
-
if (registry.duplicateProviders.has(name) && !registry.warnedDuplicates.has(name)) {
|
|
109
|
-
registry.warnedDuplicates.add(name);
|
|
110
|
-
console.warn(`[@modern-js/runtime] The router provider "${name}" was registered more than once with different module instances, and a router wrapper without an app-owned provider realm is resolving the mixed-version compatibility fallback. The fallback is keeping the first registration. Modern router wrappers isolate app-owned realms automatically. For an older wrapper, share the provider runtime between Module Federation host and remotes or upgrade every app to a realm-aware runtime.`);
|
|
111
|
-
}
|
|
112
|
-
return factory;
|
|
113
|
-
}
|
|
114
|
-
const legacyV2Factory = legacyV2Registry?.providers.get(name);
|
|
115
|
-
if (void 0 !== legacyV2Factory) return legacyV2Factory;
|
|
116
|
-
if ('tanstack' === name) throw new Error("[@modern-js/runtime] `runtime.router.framework` is set to \"tanstack\", but no TanStack router provider is registered. Install @modern-js/plugin-tanstack, add `tanstackRouterPlugin()` to the `plugins` array in modern.config.ts, and make sure '@modern-js/plugin-tanstack/runtime' is imported (e.g. in modern.runtime.ts).");
|
|
117
|
-
throw new Error(`[@modern-js/runtime] Unknown router framework "${name}". Registered providers: ${[
|
|
118
|
-
...new Set([
|
|
119
|
-
...registry.providers.keys(),
|
|
120
|
-
...legacyV2Registry?.providers.keys() ?? []
|
|
121
|
-
])
|
|
122
|
-
].join(', ') || '(none)'}. Install and register the plugin that provides this router framework.`);
|
|
123
|
-
}
|
|
124
|
-
function unsafe_resetRouterProvidersForTesting() {
|
|
125
|
-
const host = globalThis;
|
|
126
|
-
delete host[REGISTRY_SLOT];
|
|
127
|
-
delete host[LEGACY_V2_REGISTRY_SLOT];
|
|
63
|
+
function resolveRouterProvider(framework, options) {
|
|
64
|
+
const name = framework || options.realm.defaultProvider;
|
|
65
|
+
const realmProviderNames = options.realm.names();
|
|
66
|
+
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
67
|
+
const factory = options.realm.get(name);
|
|
68
|
+
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
69
|
+
return factory;
|
|
128
70
|
}
|
|
129
71
|
function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [] }) {
|
|
130
|
-
registerRouterProvider(defaultProvider.name, defaultProvider.factory, {
|
|
131
|
-
isDefault: true
|
|
132
|
-
});
|
|
133
72
|
const realm = createRouterProviderRealm([
|
|
134
73
|
{
|
|
135
74
|
...defaultProvider,
|
|
@@ -153,17 +92,13 @@ function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [
|
|
|
153
92
|
}
|
|
154
93
|
exports.createRouterPlugin = __webpack_exports__.createRouterPlugin;
|
|
155
94
|
exports.createRouterProviderRealm = __webpack_exports__.createRouterProviderRealm;
|
|
156
|
-
exports.registerRouterProvider = __webpack_exports__.registerRouterProvider;
|
|
157
95
|
exports.reportUnsupportedProviderRegistryHooks = __webpack_exports__.reportUnsupportedProviderRegistryHooks;
|
|
158
96
|
exports.resolveRouterProvider = __webpack_exports__.resolveRouterProvider;
|
|
159
|
-
exports.unsafe_resetRouterProvidersForTesting = __webpack_exports__.unsafe_resetRouterProvidersForTesting;
|
|
160
97
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
161
98
|
"createRouterPlugin",
|
|
162
99
|
"createRouterProviderRealm",
|
|
163
|
-
"registerRouterProvider",
|
|
164
100
|
"reportUnsupportedProviderRegistryHooks",
|
|
165
|
-
"resolveRouterProvider"
|
|
166
|
-
"unsafe_resetRouterProvidersForTesting"
|
|
101
|
+
"resolveRouterProvider"
|
|
167
102
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
168
103
|
Object.defineProperty(exports, '__esModule', {
|
|
169
104
|
value: true
|
|
@@ -25,74 +25,15 @@ function createRouterProviderRealm(registrations) {
|
|
|
25
25
|
names: ()=>providerNames
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
warnedDuplicates: new Set()
|
|
36
|
-
};
|
|
37
|
-
host[REGISTRY_SLOT].duplicateProviders ??= new Set();
|
|
38
|
-
host[REGISTRY_SLOT].warnedDuplicates ??= new Set();
|
|
39
|
-
return host[REGISTRY_SLOT];
|
|
40
|
-
}
|
|
41
|
-
function getLegacyV2Registry() {
|
|
42
|
-
const host = globalThis;
|
|
43
|
-
return host[LEGACY_V2_REGISTRY_SLOT];
|
|
44
|
-
}
|
|
45
|
-
function registerRouterProvider(name, factory, options = {}) {
|
|
46
|
-
const registry = getRegistry();
|
|
47
|
-
const existing = registry.providers.get(name);
|
|
48
|
-
if (void 0 !== existing) {
|
|
49
|
-
if (existing !== factory) registry.duplicateProviders.add(name);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (true === options.isDefault) registry.defaultProvider = name;
|
|
53
|
-
registry.providers.set(name, factory);
|
|
54
|
-
}
|
|
55
|
-
function resolveRouterProvider(framework, options = {}) {
|
|
56
|
-
if (void 0 !== options.realm) {
|
|
57
|
-
const name = framework || options.realm.defaultProvider;
|
|
58
|
-
const realmProviderNames = options.realm.names();
|
|
59
|
-
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
60
|
-
const factory = options.realm.get(name);
|
|
61
|
-
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}. Compatibility registry fallback is disabled for app-owned realms.`);
|
|
62
|
-
return factory;
|
|
63
|
-
}
|
|
64
|
-
const registry = getRegistry();
|
|
65
|
-
const legacyV2Registry = getLegacyV2Registry();
|
|
66
|
-
const name = framework || options.localDefault?.name || registry.defaultProvider || legacyV2Registry?.defaultProvider;
|
|
67
|
-
if (void 0 === name) throw new Error('[@modern-js/runtime] No default router provider is registered. This is a bug in the runtime setup.');
|
|
68
|
-
if (void 0 !== options.localDefault && name === options.localDefault.name) return options.localDefault.factory;
|
|
69
|
-
const factory = registry.providers.get(name);
|
|
70
|
-
if (void 0 !== factory) {
|
|
71
|
-
if (registry.duplicateProviders.has(name) && !registry.warnedDuplicates.has(name)) {
|
|
72
|
-
registry.warnedDuplicates.add(name);
|
|
73
|
-
console.warn(`[@modern-js/runtime] The router provider "${name}" was registered more than once with different module instances, and a router wrapper without an app-owned provider realm is resolving the mixed-version compatibility fallback. The fallback is keeping the first registration. Modern router wrappers isolate app-owned realms automatically. For an older wrapper, share the provider runtime between Module Federation host and remotes or upgrade every app to a realm-aware runtime.`);
|
|
74
|
-
}
|
|
75
|
-
return factory;
|
|
76
|
-
}
|
|
77
|
-
const legacyV2Factory = legacyV2Registry?.providers.get(name);
|
|
78
|
-
if (void 0 !== legacyV2Factory) return legacyV2Factory;
|
|
79
|
-
if ('tanstack' === name) throw new Error("[@modern-js/runtime] `runtime.router.framework` is set to \"tanstack\", but no TanStack router provider is registered. Install @modern-js/plugin-tanstack, add `tanstackRouterPlugin()` to the `plugins` array in modern.config.ts, and make sure '@modern-js/plugin-tanstack/runtime' is imported (e.g. in modern.runtime.ts).");
|
|
80
|
-
throw new Error(`[@modern-js/runtime] Unknown router framework "${name}". Registered providers: ${[
|
|
81
|
-
...new Set([
|
|
82
|
-
...registry.providers.keys(),
|
|
83
|
-
...legacyV2Registry?.providers.keys() ?? []
|
|
84
|
-
])
|
|
85
|
-
].join(', ') || '(none)'}. Install and register the plugin that provides this router framework.`);
|
|
86
|
-
}
|
|
87
|
-
function unsafe_resetRouterProvidersForTesting() {
|
|
88
|
-
const host = globalThis;
|
|
89
|
-
delete host[REGISTRY_SLOT];
|
|
90
|
-
delete host[LEGACY_V2_REGISTRY_SLOT];
|
|
28
|
+
function resolveRouterProvider(framework, options) {
|
|
29
|
+
const name = framework || options.realm.defaultProvider;
|
|
30
|
+
const realmProviderNames = options.realm.names();
|
|
31
|
+
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
32
|
+
const factory = options.realm.get(name);
|
|
33
|
+
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
34
|
+
return factory;
|
|
91
35
|
}
|
|
92
36
|
function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [] }) {
|
|
93
|
-
registerRouterProvider(defaultProvider.name, defaultProvider.factory, {
|
|
94
|
-
isDefault: true
|
|
95
|
-
});
|
|
96
37
|
const realm = createRouterProviderRealm([
|
|
97
38
|
{
|
|
98
39
|
...defaultProvider,
|
|
@@ -114,4 +55,4 @@ function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [
|
|
|
114
55
|
}
|
|
115
56
|
});
|
|
116
57
|
}
|
|
117
|
-
export { createRouterPlugin, createRouterProviderRealm,
|
|
58
|
+
export { createRouterPlugin, createRouterProviderRealm, reportUnsupportedProviderRegistryHooks, resolveRouterProvider };
|
|
@@ -26,74 +26,15 @@ function createRouterProviderRealm(registrations) {
|
|
|
26
26
|
names: ()=>providerNames
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
warnedDuplicates: new Set()
|
|
37
|
-
};
|
|
38
|
-
host[REGISTRY_SLOT].duplicateProviders ??= new Set();
|
|
39
|
-
host[REGISTRY_SLOT].warnedDuplicates ??= new Set();
|
|
40
|
-
return host[REGISTRY_SLOT];
|
|
41
|
-
}
|
|
42
|
-
function getLegacyV2Registry() {
|
|
43
|
-
const host = globalThis;
|
|
44
|
-
return host[LEGACY_V2_REGISTRY_SLOT];
|
|
45
|
-
}
|
|
46
|
-
function registerRouterProvider(name, factory, options = {}) {
|
|
47
|
-
const registry = getRegistry();
|
|
48
|
-
const existing = registry.providers.get(name);
|
|
49
|
-
if (void 0 !== existing) {
|
|
50
|
-
if (existing !== factory) registry.duplicateProviders.add(name);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (true === options.isDefault) registry.defaultProvider = name;
|
|
54
|
-
registry.providers.set(name, factory);
|
|
55
|
-
}
|
|
56
|
-
function resolveRouterProvider(framework, options = {}) {
|
|
57
|
-
if (void 0 !== options.realm) {
|
|
58
|
-
const name = framework || options.realm.defaultProvider;
|
|
59
|
-
const realmProviderNames = options.realm.names();
|
|
60
|
-
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
61
|
-
const factory = options.realm.get(name);
|
|
62
|
-
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}. Compatibility registry fallback is disabled for app-owned realms.`);
|
|
63
|
-
return factory;
|
|
64
|
-
}
|
|
65
|
-
const registry = getRegistry();
|
|
66
|
-
const legacyV2Registry = getLegacyV2Registry();
|
|
67
|
-
const name = framework || options.localDefault?.name || registry.defaultProvider || legacyV2Registry?.defaultProvider;
|
|
68
|
-
if (void 0 === name) throw new Error('[@modern-js/runtime] No default router provider is registered. This is a bug in the runtime setup.');
|
|
69
|
-
if (void 0 !== options.localDefault && name === options.localDefault.name) return options.localDefault.factory;
|
|
70
|
-
const factory = registry.providers.get(name);
|
|
71
|
-
if (void 0 !== factory) {
|
|
72
|
-
if (registry.duplicateProviders.has(name) && !registry.warnedDuplicates.has(name)) {
|
|
73
|
-
registry.warnedDuplicates.add(name);
|
|
74
|
-
console.warn(`[@modern-js/runtime] The router provider "${name}" was registered more than once with different module instances, and a router wrapper without an app-owned provider realm is resolving the mixed-version compatibility fallback. The fallback is keeping the first registration. Modern router wrappers isolate app-owned realms automatically. For an older wrapper, share the provider runtime between Module Federation host and remotes or upgrade every app to a realm-aware runtime.`);
|
|
75
|
-
}
|
|
76
|
-
return factory;
|
|
77
|
-
}
|
|
78
|
-
const legacyV2Factory = legacyV2Registry?.providers.get(name);
|
|
79
|
-
if (void 0 !== legacyV2Factory) return legacyV2Factory;
|
|
80
|
-
if ('tanstack' === name) throw new Error("[@modern-js/runtime] `runtime.router.framework` is set to \"tanstack\", but no TanStack router provider is registered. Install @modern-js/plugin-tanstack, add `tanstackRouterPlugin()` to the `plugins` array in modern.config.ts, and make sure '@modern-js/plugin-tanstack/runtime' is imported (e.g. in modern.runtime.ts).");
|
|
81
|
-
throw new Error(`[@modern-js/runtime] Unknown router framework "${name}". Registered providers: ${[
|
|
82
|
-
...new Set([
|
|
83
|
-
...registry.providers.keys(),
|
|
84
|
-
...legacyV2Registry?.providers.keys() ?? []
|
|
85
|
-
])
|
|
86
|
-
].join(', ') || '(none)'}. Install and register the plugin that provides this router framework.`);
|
|
87
|
-
}
|
|
88
|
-
function unsafe_resetRouterProvidersForTesting() {
|
|
89
|
-
const host = globalThis;
|
|
90
|
-
delete host[REGISTRY_SLOT];
|
|
91
|
-
delete host[LEGACY_V2_REGISTRY_SLOT];
|
|
29
|
+
function resolveRouterProvider(framework, options) {
|
|
30
|
+
const name = framework || options.realm.defaultProvider;
|
|
31
|
+
const realmProviderNames = options.realm.names();
|
|
32
|
+
if (void 0 === name) throw new Error(`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
33
|
+
const factory = options.realm.get(name);
|
|
34
|
+
if (void 0 === factory) throw new Error(`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. Available realm providers: ${realmProviderNames.join(', ') || '(none)'}.`);
|
|
35
|
+
return factory;
|
|
92
36
|
}
|
|
93
37
|
function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [] }) {
|
|
94
|
-
registerRouterProvider(defaultProvider.name, defaultProvider.factory, {
|
|
95
|
-
isDefault: true
|
|
96
|
-
});
|
|
97
38
|
const realm = createRouterProviderRealm([
|
|
98
39
|
{
|
|
99
40
|
...defaultProvider,
|
|
@@ -115,4 +56,4 @@ function createRouterPlugin({ defaultProvider, registryHooks, localProviders = [
|
|
|
115
56
|
}
|
|
116
57
|
});
|
|
117
58
|
}
|
|
118
|
-
export { createRouterPlugin, createRouterProviderRealm,
|
|
59
|
+
export { createRouterPlugin, createRouterProviderRealm, reportUnsupportedProviderRegistryHooks, resolveRouterProvider };
|
|
@@ -32,31 +32,9 @@ export type RouterProviderRealm = Readonly<{
|
|
|
32
32
|
names: () => readonly string[];
|
|
33
33
|
}>;
|
|
34
34
|
export declare function createRouterProviderRealm(registrations: readonly RouterProviderRegistration[]): RouterProviderRealm;
|
|
35
|
-
export declare function
|
|
36
|
-
|
|
37
|
-
}): void;
|
|
38
|
-
export declare function resolveRouterProvider(framework?: string, options?: {
|
|
39
|
-
/**
|
|
40
|
-
* Provider factories owned by the resolving app/runtime wrapper. A realm
|
|
41
|
-
* is the exclusive provider source when supplied because its factories
|
|
42
|
-
* close over the correct app module graph.
|
|
43
|
-
*/
|
|
44
|
-
realm?: RouterProviderRealm;
|
|
45
|
-
/**
|
|
46
|
-
* Legacy single-provider override retained for published wrappers. New
|
|
47
|
-
* integrations should pass an app-owned `realm`, which supports every
|
|
48
|
-
* provider rather than only the default.
|
|
49
|
-
*/
|
|
50
|
-
localDefault?: {
|
|
51
|
-
name: string;
|
|
52
|
-
factory: RouterProviderFactory;
|
|
53
|
-
};
|
|
35
|
+
export declare function resolveRouterProvider(framework: string | undefined, options: {
|
|
36
|
+
realm: RouterProviderRealm;
|
|
54
37
|
}): RouterProviderFactory;
|
|
55
|
-
/**
|
|
56
|
-
* Test-only escape hatch: compatibility registries live on `globalThis`, so
|
|
57
|
-
* unit tests need a way to restore a pristine state between cases.
|
|
58
|
-
*/
|
|
59
|
-
export declare function unsafe_resetRouterProvidersForTesting(): void;
|
|
60
38
|
/** Compose app-owned providers without importing the native runtime graph. */
|
|
61
39
|
export declare function createRouterPlugin<Hooks extends Record<string, unknown>>({ defaultProvider, registryHooks, localProviders, }: {
|
|
62
40
|
defaultProvider: {
|
|
@@ -109,10 +109,10 @@ export interface BffEffectUserConfig {
|
|
|
109
109
|
/**
|
|
110
110
|
* Enforce Effect-native API/runtime modules instead of raw request handlers.
|
|
111
111
|
*
|
|
112
|
-
*
|
|
112
|
+
* Effect API entries must export a `defineEffectBff(...)`
|
|
113
113
|
* definition or a `{ api, layer }` HttpApi module. Raw `handler` exports,
|
|
114
114
|
* default request handlers, and unbranded custom `createHandler` factories
|
|
115
|
-
* are
|
|
115
|
+
* are rejected.
|
|
116
116
|
*
|
|
117
117
|
* @default true
|
|
118
118
|
*/
|
|
@@ -27,17 +27,17 @@ export interface ServerTelemetrySloUserConfig {
|
|
|
27
27
|
*/
|
|
28
28
|
alertCooldownMs?: number;
|
|
29
29
|
}
|
|
30
|
-
export interface
|
|
30
|
+
export interface ServerTelemetryHealthContractGateUserConfig {
|
|
31
31
|
/**
|
|
32
32
|
* Whether this contract gate currently passes.
|
|
33
33
|
*/
|
|
34
34
|
passed: boolean;
|
|
35
35
|
/**
|
|
36
|
-
* Optional failure reason used for
|
|
36
|
+
* Optional failure reason used for health diagnostics.
|
|
37
37
|
*/
|
|
38
38
|
reason?: string;
|
|
39
39
|
}
|
|
40
|
-
export interface
|
|
40
|
+
export interface ServerTelemetrySnapshotObservationUserConfig {
|
|
41
41
|
/**
|
|
42
42
|
* Enable automatic contract gate synchronization from a gate snapshot file.
|
|
43
43
|
*
|
|
@@ -65,14 +65,14 @@ export interface ServerTelemetryCanaryAutopilotUserConfig {
|
|
|
65
65
|
/**
|
|
66
66
|
* Runtime MF fallback signal ingestion.
|
|
67
67
|
*/
|
|
68
|
-
runtimeFallbackSignal?:
|
|
68
|
+
runtimeFallbackSignal?: ServerTelemetryHealthRuntimeFallbackSignalUserConfig;
|
|
69
69
|
/**
|
|
70
70
|
* Optional pluggable state store backend for contract gate snapshots.
|
|
71
71
|
* When omitted, snapshots are read/written from gateSnapshotPath on local disk.
|
|
72
72
|
*/
|
|
73
|
-
stateStore?:
|
|
73
|
+
stateStore?: ServerTelemetrySnapshotObservationStateStoreUserConfig;
|
|
74
74
|
}
|
|
75
|
-
export interface
|
|
75
|
+
export interface ServerTelemetrySnapshotObservationStateStoreUserConfig {
|
|
76
76
|
/**
|
|
77
77
|
* Path or package name of a module that exports
|
|
78
78
|
* `createContractGateSnapshotStore(context)`.
|
|
@@ -83,7 +83,7 @@ export interface ServerTelemetryCanaryAutopilotStateStoreUserConfig {
|
|
|
83
83
|
*/
|
|
84
84
|
options?: Record<string, unknown>;
|
|
85
85
|
}
|
|
86
|
-
export interface
|
|
86
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalUserConfig {
|
|
87
87
|
/**
|
|
88
88
|
* Enable runtime MF fallback signal ingestion endpoint.
|
|
89
89
|
*
|
|
@@ -119,15 +119,15 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalUserConfig {
|
|
|
119
119
|
maxBodyBytes?: number;
|
|
120
120
|
/**
|
|
121
121
|
* Optional runtime trust policy for fallback signal ingestion.
|
|
122
|
-
* Use this to restrict who can mutate
|
|
122
|
+
* Use this to restrict who can mutate health contract gates.
|
|
123
123
|
*/
|
|
124
|
-
trustPolicy?:
|
|
124
|
+
trustPolicy?: ServerTelemetryHealthRuntimeFallbackSignalTrustPolicyUserConfig;
|
|
125
125
|
/**
|
|
126
126
|
* Optional request authentication for runtime fallback signal endpoint.
|
|
127
127
|
*/
|
|
128
|
-
auth?:
|
|
128
|
+
auth?: ServerTelemetryHealthRuntimeFallbackSignalAuthUserConfig;
|
|
129
129
|
}
|
|
130
|
-
export interface
|
|
130
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalAuthUserConfig {
|
|
131
131
|
/**
|
|
132
132
|
* Enable auth guard for runtime fallback signal endpoint.
|
|
133
133
|
*
|
|
@@ -149,7 +149,7 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalAuthUserConfig {
|
|
|
149
149
|
*/
|
|
150
150
|
expectedValueEnv?: string;
|
|
151
151
|
}
|
|
152
|
-
export interface
|
|
152
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalTrustPolicyUserConfig {
|
|
153
153
|
/**
|
|
154
154
|
* Allowlist of app names accepted by runtime fallback signal endpoint.
|
|
155
155
|
* Empty means no app-name allowlist check.
|
|
@@ -190,58 +190,58 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalTrustPolicyUserConfig
|
|
|
190
190
|
*/
|
|
191
191
|
dedupeWindowMs?: number;
|
|
192
192
|
}
|
|
193
|
-
export interface
|
|
193
|
+
export interface ServerTelemetryHealthUserConfig {
|
|
194
194
|
/**
|
|
195
|
-
* Enable
|
|
195
|
+
* Enable telemetry health observation.
|
|
196
196
|
*
|
|
197
197
|
* @default false
|
|
198
198
|
*/
|
|
199
199
|
enabled?: boolean;
|
|
200
200
|
/**
|
|
201
|
-
* Periodic
|
|
201
|
+
* Periodic health evaluation interval in milliseconds.
|
|
202
202
|
*
|
|
203
203
|
* @default 15000
|
|
204
204
|
*/
|
|
205
205
|
evaluationIntervalMs?: number;
|
|
206
206
|
/**
|
|
207
|
-
* Required consecutive healthy evaluations before
|
|
207
|
+
* Required consecutive healthy evaluations before reporting healthy.
|
|
208
208
|
*
|
|
209
209
|
* @default 3
|
|
210
210
|
*/
|
|
211
211
|
minConsecutiveHealthyEvaluations?: number;
|
|
212
212
|
/**
|
|
213
|
-
* Consecutive failing evaluations before
|
|
213
|
+
* Consecutive failing evaluations before reporting unhealthy.
|
|
214
214
|
*
|
|
215
215
|
* @default 2
|
|
216
216
|
*/
|
|
217
|
-
|
|
217
|
+
minConsecutiveFailedEvaluations?: number;
|
|
218
218
|
/**
|
|
219
|
-
* Maximum queue utilization ratio allowed
|
|
219
|
+
* Maximum queue utilization ratio allowed for healthy telemetry.
|
|
220
220
|
*
|
|
221
221
|
* @default 0.8
|
|
222
222
|
*/
|
|
223
223
|
maxQueueUtilization?: number;
|
|
224
224
|
/**
|
|
225
|
-
* Maximum allowed total dropped envelopes
|
|
225
|
+
* Maximum allowed total dropped envelopes for healthy telemetry.
|
|
226
226
|
*
|
|
227
227
|
* @default 0
|
|
228
228
|
*/
|
|
229
229
|
maxTotalDropped?: number;
|
|
230
230
|
/**
|
|
231
|
-
* Maximum allowed unhealthy exporters
|
|
231
|
+
* Maximum allowed unhealthy exporters for healthy telemetry.
|
|
232
232
|
*
|
|
233
233
|
* @default 0
|
|
234
234
|
*/
|
|
235
235
|
maxUnhealthyExporters?: number;
|
|
236
236
|
/**
|
|
237
|
-
* Contract gate map used in
|
|
237
|
+
* Contract gate map used in health evaluations.
|
|
238
238
|
* `true` means passing, `false` means failing.
|
|
239
239
|
*/
|
|
240
|
-
contractGates?: Record<string, boolean |
|
|
240
|
+
contractGates?: Record<string, boolean | ServerTelemetryHealthContractGateUserConfig>;
|
|
241
241
|
/**
|
|
242
|
-
* Contract-gate
|
|
242
|
+
* Contract-gate snapshot observation settings.
|
|
243
243
|
*/
|
|
244
|
-
|
|
244
|
+
snapshotObservation?: ServerTelemetrySnapshotObservationUserConfig;
|
|
245
245
|
}
|
|
246
246
|
export interface ServerTelemetryConfigExtension {
|
|
247
247
|
telemetry?: ServerTelemetryUserConfig;
|
|
@@ -306,9 +306,9 @@ export interface ServerTelemetryUserConfig {
|
|
|
306
306
|
*/
|
|
307
307
|
slo?: ServerTelemetrySloUserConfig;
|
|
308
308
|
/**
|
|
309
|
-
*
|
|
309
|
+
* Telemetry health observation policy.
|
|
310
310
|
*/
|
|
311
|
-
|
|
311
|
+
health?: ServerTelemetryHealthUserConfig;
|
|
312
312
|
exporters?: {
|
|
313
313
|
/**
|
|
314
314
|
* OpenTelemetry HTTP exporter.
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/runtime/runtime-extensions"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"version": "3.9.0-ultramodern.
|
|
14
|
+
"version": "3.9.0-ultramodern.6",
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=26.7.0"
|
|
17
17
|
},
|
|
@@ -274,7 +274,7 @@
|
|
|
274
274
|
},
|
|
275
275
|
"devDependencies": {
|
|
276
276
|
"@loadable/component": "5.16.7",
|
|
277
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.
|
|
277
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.6",
|
|
278
278
|
"@rsbuild/core": "2.2.3",
|
|
279
279
|
"@rslib/core": "1.0.0",
|
|
280
280
|
"@scripts/rstest-config": "2.66.0",
|
|
@@ -303,8 +303,8 @@
|
|
|
303
303
|
}
|
|
304
304
|
},
|
|
305
305
|
"dependencies": {
|
|
306
|
-
"@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.9.0-ultramodern.
|
|
307
|
-
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.
|
|
306
|
+
"@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.9.0-ultramodern.6",
|
|
307
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.6",
|
|
308
308
|
"react-helmet-async": "3.0.0"
|
|
309
309
|
},
|
|
310
310
|
"scripts": {
|
package/src/routerProvider.ts
CHANGED
|
@@ -97,209 +97,32 @@ export function createRouterProviderRealm(
|
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
type RouterProviderRegistry = {
|
|
101
|
-
providers: Map<string, RouterProviderFactory>;
|
|
102
|
-
defaultProvider?: string;
|
|
103
|
-
/** Names that were registered by more than one module instance. */
|
|
104
|
-
duplicateProviders: Set<string>;
|
|
105
|
-
/** Duplicate names already reported when the compatibility fallback won. */
|
|
106
|
-
warnedDuplicates: Set<string>;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Versioned compatibility-registry key. The unsuffixed key
|
|
111
|
-
* ('@modern-js/runtime:router-providers') is owned by older published copies
|
|
112
|
-
* of this module whose `registerRouterProvider` *throws* on a same-name
|
|
113
|
-
* re-registration. `:v2` added keep-first registration but also enforced one
|
|
114
|
-
* non-default provider across the whole JavaScript realm. `:v3` removes that
|
|
115
|
-
* page-global app invariant: explicit runtime realms own provider selection,
|
|
116
|
-
* while this registry remains only a mixed-version fallback. New copies read
|
|
117
|
-
* but never mutate the v2 slot so older published copies remain compatible.
|
|
118
|
-
*/
|
|
119
|
-
const REGISTRY_SLOT: unique symbol = Symbol.for(
|
|
120
|
-
'@modern-js/runtime:router-providers:v3',
|
|
121
|
-
);
|
|
122
|
-
const LEGACY_V2_REGISTRY_SLOT: unique symbol = Symbol.for(
|
|
123
|
-
'@modern-js/runtime:router-providers:v2',
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
function getRegistry(): RouterProviderRegistry {
|
|
127
|
-
const host = globalThis as { [REGISTRY_SLOT]?: RouterProviderRegistry };
|
|
128
|
-
host[REGISTRY_SLOT] ??= {
|
|
129
|
-
providers: new Map(),
|
|
130
|
-
duplicateProviders: new Set(),
|
|
131
|
-
warnedDuplicates: new Set(),
|
|
132
|
-
};
|
|
133
|
-
// Defense in depth within the v3 key: if a future v3-keyed copy of this
|
|
134
|
-
// module ever predates a later-added field (mixed v3 minors in a Module
|
|
135
|
-
// Federation setup), heal the shape instead of crashing on `undefined`.
|
|
136
|
-
host[REGISTRY_SLOT].duplicateProviders ??= new Set();
|
|
137
|
-
host[REGISTRY_SLOT].warnedDuplicates ??= new Set();
|
|
138
|
-
return host[REGISTRY_SLOT];
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function getLegacyV2Registry():
|
|
142
|
-
| Pick<RouterProviderRegistry, 'providers' | 'defaultProvider'>
|
|
143
|
-
| undefined {
|
|
144
|
-
const host = globalThis as {
|
|
145
|
-
[LEGACY_V2_REGISTRY_SLOT]?: Pick<
|
|
146
|
-
RouterProviderRegistry,
|
|
147
|
-
'providers' | 'defaultProvider'
|
|
148
|
-
>;
|
|
149
|
-
};
|
|
150
|
-
return host[LEGACY_V2_REGISTRY_SLOT];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export function registerRouterProvider(
|
|
154
|
-
name: string,
|
|
155
|
-
factory: RouterProviderFactory,
|
|
156
|
-
options: { isDefault?: boolean } = {},
|
|
157
|
-
): void {
|
|
158
|
-
const registry = getRegistry();
|
|
159
|
-
const existing = registry.providers.get(name);
|
|
160
|
-
|
|
161
|
-
if (existing !== undefined) {
|
|
162
|
-
// Keep-first semantics. A same-name re-registration with a *different*
|
|
163
|
-
// factory is almost always two bundled copies of the same provider
|
|
164
|
-
// module — e.g. a Module Federation remote that does not share
|
|
165
|
-
// '@modern-js/plugin-tanstack/runtime' evaluates its own copy, which
|
|
166
|
-
// creates a fresh factory function per evaluation. That must not crash
|
|
167
|
-
// the app; the first registration remains available for compatibility.
|
|
168
|
-
// Merely loading independent app-owned realms is valid, so defer the
|
|
169
|
-
// warning until a caller actually consumes this ambiguous fallback.
|
|
170
|
-
if (existing !== factory) {
|
|
171
|
-
registry.duplicateProviders.add(name);
|
|
172
|
-
}
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (options.isDefault === true) {
|
|
177
|
-
registry.defaultProvider = name;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
registry.providers.set(name, factory);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
100
|
export function resolveRouterProvider(
|
|
184
|
-
framework
|
|
185
|
-
options: {
|
|
186
|
-
/**
|
|
187
|
-
* Provider factories owned by the resolving app/runtime wrapper. A realm
|
|
188
|
-
* is the exclusive provider source when supplied because its factories
|
|
189
|
-
* close over the correct app module graph.
|
|
190
|
-
*/
|
|
191
|
-
realm?: RouterProviderRealm;
|
|
192
|
-
/**
|
|
193
|
-
* Legacy single-provider override retained for published wrappers. New
|
|
194
|
-
* integrations should pass an app-owned `realm`, which supports every
|
|
195
|
-
* provider rather than only the default.
|
|
196
|
-
*/
|
|
197
|
-
localDefault?: { name: string; factory: RouterProviderFactory };
|
|
198
|
-
} = {},
|
|
101
|
+
framework: string | undefined,
|
|
102
|
+
options: { realm: RouterProviderRealm },
|
|
199
103
|
): RouterProviderFactory {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const realmProviderNames = options.realm.names();
|
|
203
|
-
|
|
204
|
-
if (name === undefined) {
|
|
205
|
-
throw new Error(
|
|
206
|
-
`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${
|
|
207
|
-
realmProviderNames.join(', ') || '(none)'
|
|
208
|
-
}.`,
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const factory = options.realm.get(name);
|
|
213
|
-
if (factory === undefined) {
|
|
214
|
-
throw new Error(
|
|
215
|
-
`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. ` +
|
|
216
|
-
`Available realm providers: ${
|
|
217
|
-
realmProviderNames.join(', ') || '(none)'
|
|
218
|
-
}. Compatibility registry fallback is disabled for app-owned realms.`,
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return factory;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const registry = getRegistry();
|
|
226
|
-
const legacyV2Registry = getLegacyV2Registry();
|
|
227
|
-
// `||` on purpose: a falsy framework value (empty string from env
|
|
228
|
-
// templating, `false`, `undefined`) falls back to the default provider
|
|
229
|
-
// instead of erroring on an unknown framework "". Prefer the older
|
|
230
|
-
// localDefault contract before compatibility slots.
|
|
231
|
-
const name =
|
|
232
|
-
framework ||
|
|
233
|
-
options.localDefault?.name ||
|
|
234
|
-
registry.defaultProvider ||
|
|
235
|
-
legacyV2Registry?.defaultProvider;
|
|
104
|
+
const name = framework || options.realm.defaultProvider;
|
|
105
|
+
const realmProviderNames = options.realm.names();
|
|
236
106
|
|
|
237
107
|
if (name === undefined) {
|
|
238
108
|
throw new Error(
|
|
239
|
-
|
|
109
|
+
`[@modern-js/runtime] The app-owned router provider realm does not declare a default provider. Available realm providers: ${
|
|
110
|
+
realmProviderNames.join(', ') || '(none)'
|
|
111
|
+
}.`,
|
|
240
112
|
);
|
|
241
113
|
}
|
|
242
114
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
name === options.localDefault.name
|
|
246
|
-
) {
|
|
247
|
-
return options.localDefault.factory;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const factory = registry.providers.get(name);
|
|
251
|
-
if (factory !== undefined) {
|
|
252
|
-
if (
|
|
253
|
-
registry.duplicateProviders.has(name) &&
|
|
254
|
-
!registry.warnedDuplicates.has(name)
|
|
255
|
-
) {
|
|
256
|
-
registry.warnedDuplicates.add(name);
|
|
257
|
-
console.warn(
|
|
258
|
-
`[@modern-js/runtime] The router provider "${name}" was registered more than once with different module instances, and a router wrapper without an app-owned provider realm is resolving the mixed-version compatibility fallback. The fallback is keeping the first registration. ` +
|
|
259
|
-
'Modern router wrappers isolate app-owned realms automatically. ' +
|
|
260
|
-
'For an older wrapper, share the provider runtime between Module Federation host and remotes or upgrade every app to a realm-aware runtime.',
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
return factory;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const legacyV2Factory = legacyV2Registry?.providers.get(name);
|
|
267
|
-
if (legacyV2Factory !== undefined) {
|
|
268
|
-
return legacyV2Factory;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (name === 'tanstack') {
|
|
115
|
+
const factory = options.realm.get(name);
|
|
116
|
+
if (factory === undefined) {
|
|
272
117
|
throw new Error(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
118
|
+
`[@modern-js/runtime] Router provider "${name}" is not registered in the app-owned router provider realm. ` +
|
|
119
|
+
`Available realm providers: ${
|
|
120
|
+
realmProviderNames.join(', ') || '(none)'
|
|
121
|
+
}.`,
|
|
276
122
|
);
|
|
277
123
|
}
|
|
278
124
|
|
|
279
|
-
|
|
280
|
-
`[@modern-js/runtime] Unknown router framework "${name}". ` +
|
|
281
|
-
`Registered providers: ${
|
|
282
|
-
[
|
|
283
|
-
...new Set([
|
|
284
|
-
...registry.providers.keys(),
|
|
285
|
-
...(legacyV2Registry?.providers.keys() ?? []),
|
|
286
|
-
]),
|
|
287
|
-
].join(', ') || '(none)'
|
|
288
|
-
}. Install and register the plugin that provides this router framework.`,
|
|
289
|
-
);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Test-only escape hatch: compatibility registries live on `globalThis`, so
|
|
294
|
-
* unit tests need a way to restore a pristine state between cases.
|
|
295
|
-
*/
|
|
296
|
-
export function unsafe_resetRouterProvidersForTesting(): void {
|
|
297
|
-
const host = globalThis as {
|
|
298
|
-
[REGISTRY_SLOT]?: RouterProviderRegistry;
|
|
299
|
-
[LEGACY_V2_REGISTRY_SLOT]?: unknown;
|
|
300
|
-
};
|
|
301
|
-
delete host[REGISTRY_SLOT];
|
|
302
|
-
delete host[LEGACY_V2_REGISTRY_SLOT];
|
|
125
|
+
return factory;
|
|
303
126
|
}
|
|
304
127
|
|
|
305
128
|
/** Compose app-owned providers without importing the native runtime graph. */
|
|
@@ -312,9 +135,6 @@ export function createRouterPlugin<Hooks extends Record<string, unknown>>({
|
|
|
312
135
|
registryHooks: Hooks;
|
|
313
136
|
localProviders?: readonly Omit<RouterProviderRegistration, 'isDefault'>[];
|
|
314
137
|
}) {
|
|
315
|
-
registerRouterProvider(defaultProvider.name, defaultProvider.factory, {
|
|
316
|
-
isDefault: true,
|
|
317
|
-
});
|
|
318
138
|
const realm = createRouterProviderRealm([
|
|
319
139
|
{ ...defaultProvider, isDefault: true },
|
|
320
140
|
...localProviders,
|
|
@@ -123,10 +123,10 @@ export interface BffEffectUserConfig {
|
|
|
123
123
|
/**
|
|
124
124
|
* Enforce Effect-native API/runtime modules instead of raw request handlers.
|
|
125
125
|
*
|
|
126
|
-
*
|
|
126
|
+
* Effect API entries must export a `defineEffectBff(...)`
|
|
127
127
|
* definition or a `{ api, layer }` HttpApi module. Raw `handler` exports,
|
|
128
128
|
* default request handlers, and unbranded custom `createHandler` factories
|
|
129
|
-
* are
|
|
129
|
+
* are rejected.
|
|
130
130
|
*
|
|
131
131
|
* @default true
|
|
132
132
|
*/
|
|
@@ -31,18 +31,18 @@ export interface ServerTelemetrySloUserConfig {
|
|
|
31
31
|
alertCooldownMs?: number;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export interface
|
|
34
|
+
export interface ServerTelemetryHealthContractGateUserConfig {
|
|
35
35
|
/**
|
|
36
36
|
* Whether this contract gate currently passes.
|
|
37
37
|
*/
|
|
38
38
|
passed: boolean;
|
|
39
39
|
/**
|
|
40
|
-
* Optional failure reason used for
|
|
40
|
+
* Optional failure reason used for health diagnostics.
|
|
41
41
|
*/
|
|
42
42
|
reason?: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export interface
|
|
45
|
+
export interface ServerTelemetrySnapshotObservationUserConfig {
|
|
46
46
|
/**
|
|
47
47
|
* Enable automatic contract gate synchronization from a gate snapshot file.
|
|
48
48
|
*
|
|
@@ -70,15 +70,15 @@ export interface ServerTelemetryCanaryAutopilotUserConfig {
|
|
|
70
70
|
/**
|
|
71
71
|
* Runtime MF fallback signal ingestion.
|
|
72
72
|
*/
|
|
73
|
-
runtimeFallbackSignal?:
|
|
73
|
+
runtimeFallbackSignal?: ServerTelemetryHealthRuntimeFallbackSignalUserConfig;
|
|
74
74
|
/**
|
|
75
75
|
* Optional pluggable state store backend for contract gate snapshots.
|
|
76
76
|
* When omitted, snapshots are read/written from gateSnapshotPath on local disk.
|
|
77
77
|
*/
|
|
78
|
-
stateStore?:
|
|
78
|
+
stateStore?: ServerTelemetrySnapshotObservationStateStoreUserConfig;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export interface
|
|
81
|
+
export interface ServerTelemetrySnapshotObservationStateStoreUserConfig {
|
|
82
82
|
/**
|
|
83
83
|
* Path or package name of a module that exports
|
|
84
84
|
* `createContractGateSnapshotStore(context)`.
|
|
@@ -90,7 +90,7 @@ export interface ServerTelemetryCanaryAutopilotStateStoreUserConfig {
|
|
|
90
90
|
options?: Record<string, unknown>;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
export interface
|
|
93
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalUserConfig {
|
|
94
94
|
/**
|
|
95
95
|
* Enable runtime MF fallback signal ingestion endpoint.
|
|
96
96
|
*
|
|
@@ -126,16 +126,16 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalUserConfig {
|
|
|
126
126
|
maxBodyBytes?: number;
|
|
127
127
|
/**
|
|
128
128
|
* Optional runtime trust policy for fallback signal ingestion.
|
|
129
|
-
* Use this to restrict who can mutate
|
|
129
|
+
* Use this to restrict who can mutate health contract gates.
|
|
130
130
|
*/
|
|
131
|
-
trustPolicy?:
|
|
131
|
+
trustPolicy?: ServerTelemetryHealthRuntimeFallbackSignalTrustPolicyUserConfig;
|
|
132
132
|
/**
|
|
133
133
|
* Optional request authentication for runtime fallback signal endpoint.
|
|
134
134
|
*/
|
|
135
|
-
auth?:
|
|
135
|
+
auth?: ServerTelemetryHealthRuntimeFallbackSignalAuthUserConfig;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
export interface
|
|
138
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalAuthUserConfig {
|
|
139
139
|
/**
|
|
140
140
|
* Enable auth guard for runtime fallback signal endpoint.
|
|
141
141
|
*
|
|
@@ -158,7 +158,7 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalAuthUserConfig {
|
|
|
158
158
|
expectedValueEnv?: string;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
export interface
|
|
161
|
+
export interface ServerTelemetryHealthRuntimeFallbackSignalTrustPolicyUserConfig {
|
|
162
162
|
/**
|
|
163
163
|
* Allowlist of app names accepted by runtime fallback signal endpoint.
|
|
164
164
|
* Empty means no app-name allowlist check.
|
|
@@ -200,61 +200,61 @@ export interface ServerTelemetryCanaryRuntimeFallbackSignalTrustPolicyUserConfig
|
|
|
200
200
|
dedupeWindowMs?: number;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
export interface
|
|
203
|
+
export interface ServerTelemetryHealthUserConfig {
|
|
204
204
|
/**
|
|
205
|
-
* Enable
|
|
205
|
+
* Enable telemetry health observation.
|
|
206
206
|
*
|
|
207
207
|
* @default false
|
|
208
208
|
*/
|
|
209
209
|
enabled?: boolean;
|
|
210
210
|
/**
|
|
211
|
-
* Periodic
|
|
211
|
+
* Periodic health evaluation interval in milliseconds.
|
|
212
212
|
*
|
|
213
213
|
* @default 15000
|
|
214
214
|
*/
|
|
215
215
|
evaluationIntervalMs?: number;
|
|
216
216
|
/**
|
|
217
|
-
* Required consecutive healthy evaluations before
|
|
217
|
+
* Required consecutive healthy evaluations before reporting healthy.
|
|
218
218
|
*
|
|
219
219
|
* @default 3
|
|
220
220
|
*/
|
|
221
221
|
minConsecutiveHealthyEvaluations?: number;
|
|
222
222
|
/**
|
|
223
|
-
* Consecutive failing evaluations before
|
|
223
|
+
* Consecutive failing evaluations before reporting unhealthy.
|
|
224
224
|
*
|
|
225
225
|
* @default 2
|
|
226
226
|
*/
|
|
227
|
-
|
|
227
|
+
minConsecutiveFailedEvaluations?: number;
|
|
228
228
|
/**
|
|
229
|
-
* Maximum queue utilization ratio allowed
|
|
229
|
+
* Maximum queue utilization ratio allowed for healthy telemetry.
|
|
230
230
|
*
|
|
231
231
|
* @default 0.8
|
|
232
232
|
*/
|
|
233
233
|
maxQueueUtilization?: number;
|
|
234
234
|
/**
|
|
235
|
-
* Maximum allowed total dropped envelopes
|
|
235
|
+
* Maximum allowed total dropped envelopes for healthy telemetry.
|
|
236
236
|
*
|
|
237
237
|
* @default 0
|
|
238
238
|
*/
|
|
239
239
|
maxTotalDropped?: number;
|
|
240
240
|
/**
|
|
241
|
-
* Maximum allowed unhealthy exporters
|
|
241
|
+
* Maximum allowed unhealthy exporters for healthy telemetry.
|
|
242
242
|
*
|
|
243
243
|
* @default 0
|
|
244
244
|
*/
|
|
245
245
|
maxUnhealthyExporters?: number;
|
|
246
246
|
/**
|
|
247
|
-
* Contract gate map used in
|
|
247
|
+
* Contract gate map used in health evaluations.
|
|
248
248
|
* `true` means passing, `false` means failing.
|
|
249
249
|
*/
|
|
250
250
|
contractGates?: Record<
|
|
251
251
|
string,
|
|
252
|
-
boolean |
|
|
252
|
+
boolean | ServerTelemetryHealthContractGateUserConfig
|
|
253
253
|
>;
|
|
254
254
|
/**
|
|
255
|
-
* Contract-gate
|
|
255
|
+
* Contract-gate snapshot observation settings.
|
|
256
256
|
*/
|
|
257
|
-
|
|
257
|
+
snapshotObservation?: ServerTelemetrySnapshotObservationUserConfig;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
export interface ServerTelemetryConfigExtension {
|
|
@@ -321,9 +321,9 @@ export interface ServerTelemetryUserConfig {
|
|
|
321
321
|
*/
|
|
322
322
|
slo?: ServerTelemetrySloUserConfig;
|
|
323
323
|
/**
|
|
324
|
-
*
|
|
324
|
+
* Telemetry health observation policy.
|
|
325
325
|
*/
|
|
326
|
-
|
|
326
|
+
health?: ServerTelemetryHealthUserConfig;
|
|
327
327
|
exporters?: {
|
|
328
328
|
/**
|
|
329
329
|
* OpenTelemetry HTTP exporter.
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createRouterPlugin,
|
|
3
|
-
registerRouterProvider,
|
|
4
|
-
unsafe_resetRouterProvidersForTesting,
|
|
5
|
-
} from '../src/routerProvider';
|
|
6
|
-
|
|
7
|
-
afterEach(() => unsafe_resetRouterProvidersForTesting());
|
|
1
|
+
import { createRouterPlugin } from '../src/routerProvider';
|
|
8
2
|
|
|
9
3
|
test('selects the injected app-local factory from runtime config and preserves native hook objects', () => {
|
|
10
4
|
const registryHooks = { afterCreate: { call() {} } };
|
|
@@ -24,9 +18,7 @@ test('selects the injected app-local factory from runtime config and preserves n
|
|
|
24
18
|
expect(defaultFactory).not.toHaveBeenCalled();
|
|
25
19
|
});
|
|
26
20
|
|
|
27
|
-
test('
|
|
28
|
-
const foreign = rstest.fn(() => ({}));
|
|
29
|
-
registerRouterProvider('foreign', foreign);
|
|
21
|
+
test('rejects missing local providers', () => {
|
|
30
22
|
const factory = createRouterPlugin({
|
|
31
23
|
defaultProvider: { name: 'native', factory: () => ({}) },
|
|
32
24
|
registryHooks: {},
|
|
@@ -34,5 +26,4 @@ test('does not resolve missing local providers through the global compatibility
|
|
|
34
26
|
expect(() =>
|
|
35
27
|
factory({ framework: 'foreign' }).setup({ getRuntimeConfig: () => ({}) }),
|
|
36
28
|
).toThrow(/app-owned router provider realm/);
|
|
37
|
-
expect(foreign).not.toHaveBeenCalled();
|
|
38
29
|
});
|