@bleedingdev/modern-js-server-runtime-extensions 0.0.0-trusted-publisher-bootstrap
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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/cjs/contractGateAutopilot.js +162 -0
- package/dist/cjs/contractGateSnapshotStore.js +253 -0
- package/dist/cjs/env.js +58 -0
- package/dist/cjs/index.js +162 -0
- package/dist/cjs/mfCache.js +106 -0
- package/dist/cjs/moduleFederationCss.js +285 -0
- package/dist/cjs/runtimeFallbackSignal.js +311 -0
- package/dist/cjs/telemetry.js +373 -0
- package/dist/cjs/telemetryCore.js +819 -0
- package/dist/esm/contractGateAutopilot.mjs +124 -0
- package/dist/esm/contractGateSnapshotStore.mjs +190 -0
- package/dist/esm/env.mjs +17 -0
- package/dist/esm/index.mjs +6 -0
- package/dist/esm/mfCache.mjs +55 -0
- package/dist/esm/moduleFederationCss.mjs +225 -0
- package/dist/esm/runtimeFallbackSignal.mjs +222 -0
- package/dist/esm/telemetry.mjs +275 -0
- package/dist/esm/telemetryCore.mjs +759 -0
- package/dist/esm-node/contractGateAutopilot.mjs +125 -0
- package/dist/esm-node/contractGateSnapshotStore.mjs +192 -0
- package/dist/esm-node/env.mjs +18 -0
- package/dist/esm-node/index.mjs +7 -0
- package/dist/esm-node/mfCache.mjs +56 -0
- package/dist/esm-node/moduleFederationCss.mjs +226 -0
- package/dist/esm-node/runtimeFallbackSignal.mjs +223 -0
- package/dist/esm-node/telemetry.mjs +276 -0
- package/dist/esm-node/telemetryCore.mjs +760 -0
- package/dist/types/contractGateAutopilot.d.ts +35 -0
- package/dist/types/contractGateSnapshotStore.d.ts +57 -0
- package/dist/types/env.d.ts +40 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/mfCache.d.ts +27 -0
- package/dist/types/moduleFederationCss.d.ts +87 -0
- package/dist/types/runtimeFallbackSignal.d.ts +94 -0
- package/dist/types/telemetry.d.ts +12 -0
- package/dist/types/telemetryCore.d.ts +257 -0
- package/package.json +69 -0
- package/rslib.config.mts +4 -0
- package/rstest.config.mts +7 -0
- package/src/contractGateAutopilot.ts +247 -0
- package/src/contractGateSnapshotStore.ts +420 -0
- package/src/env.ts +63 -0
- package/src/index.ts +84 -0
- package/src/mfCache.ts +119 -0
- package/src/moduleFederationCss.ts +473 -0
- package/src/runtimeFallbackSignal.ts +584 -0
- package/src/telemetry.ts +554 -0
- package/src/telemetryCore.ts +1332 -0
- package/tests/contractGateAutopilot.test.ts +203 -0
- package/tests/contractGateSnapshotStore.test.ts +223 -0
- package/tests/env.test.ts +73 -0
- package/tests/helpers.ts +19 -0
- package/tests/mfCache.test.ts +150 -0
- package/tests/moduleFederationCss.test.ts +392 -0
- package/tests/registration.test.ts +112 -0
- package/tests/telemetry.test.ts +360 -0
- package/tests/telemetryAutopilot.test.ts +993 -0
- package/tests/telemetryCanaryOrchestrator.test.ts +140 -0
- package/tests/telemetryLifecycle.test.ts +168 -0
- package/tests/telemetryTraceparent.test.ts +167 -0
- package/tests/tsconfig.json +11 -0
- package/tsconfig.json +10 -0
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bleedingdev/modern-js-server-runtime-extensions",
|
|
3
|
+
"description": "Fork-owned ultramodern.js server runtime extensions: telemetry pipeline, contract-gate canary autopilot and module federation runtime helpers. Bootstrap-only package record for npm trusted publishing setup.",
|
|
4
|
+
"homepage": "https://github.com/BleedingDev/ultramodern.js#readme",
|
|
5
|
+
"bugs": {
|
|
6
|
+
"url": "https://github.com/BleedingDev/ultramodern.js/issues"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/BleedingDev/ultramodern.js.git",
|
|
11
|
+
"directory": "packages/server/runtime-extensions"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"framework",
|
|
17
|
+
"modern",
|
|
18
|
+
"modern.js"
|
|
19
|
+
],
|
|
20
|
+
"version": "0.0.0-trusted-publisher-bootstrap",
|
|
21
|
+
"types": "./dist/types/index.d.ts",
|
|
22
|
+
"main": "./dist/cjs/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/types/index.d.ts",
|
|
26
|
+
"modern:source": "./src/index.ts",
|
|
27
|
+
"node": {
|
|
28
|
+
"import": "./dist/esm-node/index.mjs",
|
|
29
|
+
"require": "./dist/cjs/index.js"
|
|
30
|
+
},
|
|
31
|
+
"default": "./dist/cjs/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"typesVersions": {
|
|
35
|
+
"*": {
|
|
36
|
+
".": [
|
|
37
|
+
"./dist/types/index.d.ts",
|
|
38
|
+
"./src/index.ts"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@swc/helpers": "^0.5.23",
|
|
47
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.2.0-ultramodern.121",
|
|
48
|
+
"@modern-js/create-request": "npm:@bleedingdev/modern-js-create-request@3.2.0-ultramodern.121",
|
|
49
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.2.0-ultramodern.121",
|
|
50
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.2.0-ultramodern.121"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@rslib/core": "0.22.0",
|
|
54
|
+
"@types/node": "^25.9.3",
|
|
55
|
+
"@typescript/native-preview": "7.0.0-dev.20260610.1",
|
|
56
|
+
"@scripts/rstest-config": "2.66.0",
|
|
57
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.2.0-ultramodern.121"
|
|
58
|
+
},
|
|
59
|
+
"sideEffects": false,
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"registry": "https://registry.npmjs.org/",
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"dev": "rslib build --watch",
|
|
66
|
+
"build": "rslib build && pnpm -w tsgo:dts \"$PWD\"",
|
|
67
|
+
"test": "rstest --passWithNoTests"
|
|
68
|
+
}
|
|
69
|
+
}
|
package/rslib.config.mts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ContractGateSnapshotStore,
|
|
3
|
+
createFileContractGateSnapshotStore,
|
|
4
|
+
type GateSnapshot,
|
|
5
|
+
type GateSnapshotGateValue,
|
|
6
|
+
} from './contractGateSnapshotStore';
|
|
7
|
+
import type { TelemetryCanaryOrchestrator } from './telemetryCore';
|
|
8
|
+
|
|
9
|
+
const DEFAULT_POLL_INTERVAL_MS = 15_000;
|
|
10
|
+
const DEFAULT_GATE_STALE_AFTER_MS = 10 * 60_000;
|
|
11
|
+
|
|
12
|
+
type LoggerLike = {
|
|
13
|
+
info?: (message: string) => void;
|
|
14
|
+
warn?: (message: string) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type ContractGateAutopilotOptions = {
|
|
18
|
+
orchestrator: TelemetryCanaryOrchestrator;
|
|
19
|
+
gateSnapshotPath?: string;
|
|
20
|
+
gateSnapshotStore?: ContractGateSnapshotStore;
|
|
21
|
+
pollIntervalMs?: number;
|
|
22
|
+
gateStaleAfterMs?: number;
|
|
23
|
+
logger?: LoggerLike;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type NormalizedGate = {
|
|
27
|
+
name: string;
|
|
28
|
+
passed: boolean;
|
|
29
|
+
reason?: string;
|
|
30
|
+
updatedAt: number;
|
|
31
|
+
expiresAt?: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export class ContractGateAutopilot {
|
|
35
|
+
private readonly orchestrator: TelemetryCanaryOrchestrator;
|
|
36
|
+
private readonly gateSnapshotStore: ContractGateSnapshotStore;
|
|
37
|
+
private readonly gateSnapshotPath?: string;
|
|
38
|
+
private readonly pollIntervalMs: number;
|
|
39
|
+
private readonly gateStaleAfterMs: number;
|
|
40
|
+
private readonly logger?: LoggerLike;
|
|
41
|
+
private poller?: ReturnType<typeof setInterval>;
|
|
42
|
+
private lastSnapshotFingerprint?: string;
|
|
43
|
+
private readonly appliedGateFingerprints = new Map<string, string>();
|
|
44
|
+
|
|
45
|
+
constructor(options: ContractGateAutopilotOptions) {
|
|
46
|
+
this.orchestrator = options.orchestrator;
|
|
47
|
+
if (!options.gateSnapshotStore && !options.gateSnapshotPath) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'ContractGateAutopilot requires gateSnapshotPath or gateSnapshotStore',
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
this.gateSnapshotPath = options.gateSnapshotPath;
|
|
53
|
+
this.gateSnapshotStore =
|
|
54
|
+
options.gateSnapshotStore ||
|
|
55
|
+
createFileContractGateSnapshotStore(options.gateSnapshotPath!);
|
|
56
|
+
this.pollIntervalMs = Math.max(
|
|
57
|
+
250,
|
|
58
|
+
options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
59
|
+
);
|
|
60
|
+
this.gateStaleAfterMs = Math.max(
|
|
61
|
+
0,
|
|
62
|
+
options.gateStaleAfterMs ?? DEFAULT_GATE_STALE_AFTER_MS,
|
|
63
|
+
);
|
|
64
|
+
this.logger = options.logger;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async start() {
|
|
68
|
+
await this.syncOnce();
|
|
69
|
+
|
|
70
|
+
if (this.poller) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.poller = setInterval(() => {
|
|
75
|
+
void this.syncOnce();
|
|
76
|
+
}, this.pollIntervalMs);
|
|
77
|
+
if (typeof (this.poller as NodeJS.Timeout).unref === 'function') {
|
|
78
|
+
(this.poller as NodeJS.Timeout).unref();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
stop() {
|
|
83
|
+
if (this.poller) {
|
|
84
|
+
clearInterval(this.poller);
|
|
85
|
+
this.poller = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async syncOnce() {
|
|
90
|
+
const snapshot = await this.loadSnapshot();
|
|
91
|
+
if (!snapshot) {
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const gates = this.normalizeSnapshot(snapshot);
|
|
96
|
+
let updatedCount = 0;
|
|
97
|
+
for (const gate of gates) {
|
|
98
|
+
this.orchestrator.addRequiredContractGate(gate.name);
|
|
99
|
+
const fingerprint = `${gate.passed ? '1' : '0'}:${gate.reason || ''}`;
|
|
100
|
+
if (this.appliedGateFingerprints.get(gate.name) === fingerprint) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
this.orchestrator.setContractGate(gate.name, gate.passed, gate.reason);
|
|
105
|
+
this.appliedGateFingerprints.set(gate.name, fingerprint);
|
|
106
|
+
updatedCount += 1;
|
|
107
|
+
this.logger?.info?.(
|
|
108
|
+
`[telemetry.canary.autopilot] gate=${gate.name} passed=${String(gate.passed)} reason=${gate.reason || 'none'}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return updatedCount;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async loadSnapshot() {
|
|
116
|
+
try {
|
|
117
|
+
const snapshot = await this.gateSnapshotStore.readSnapshot();
|
|
118
|
+
if (!snapshot) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const fingerprint = JSON.stringify(snapshot);
|
|
123
|
+
if (fingerprint === this.lastSnapshotFingerprint) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
this.lastSnapshotFingerprint = fingerprint;
|
|
127
|
+
|
|
128
|
+
return snapshot;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const source =
|
|
131
|
+
this.gateSnapshotPath || this.gateSnapshotStore.name || 'stateStore';
|
|
132
|
+
this.logger?.warn?.(
|
|
133
|
+
`[telemetry.canary.autopilot] failed to load gate snapshot ${source}: ${error instanceof Error ? error.message : String(error)}`,
|
|
134
|
+
);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private normalizeSnapshot(snapshot: GateSnapshot) {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
const output: NormalizedGate[] = [];
|
|
142
|
+
const gates = snapshot.gates;
|
|
143
|
+
if (!gates || typeof gates !== 'object') {
|
|
144
|
+
return output;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const [name, value] of Object.entries(gates)) {
|
|
148
|
+
const normalizedName = name.trim();
|
|
149
|
+
if (!normalizedName) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const gate = this.normalizeGateValue(value, snapshot.updatedAt, now);
|
|
154
|
+
if (!gate) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
typeof gate.expiresAt === 'number' &&
|
|
160
|
+
Number.isFinite(gate.expiresAt) &&
|
|
161
|
+
gate.expiresAt > 0 &&
|
|
162
|
+
now >= gate.expiresAt
|
|
163
|
+
) {
|
|
164
|
+
output.push({
|
|
165
|
+
name: normalizedName,
|
|
166
|
+
passed: true,
|
|
167
|
+
reason: undefined,
|
|
168
|
+
updatedAt: gate.updatedAt,
|
|
169
|
+
expiresAt: gate.expiresAt,
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const isStale =
|
|
175
|
+
this.gateStaleAfterMs > 0 &&
|
|
176
|
+
now - gate.updatedAt > this.gateStaleAfterMs;
|
|
177
|
+
if (isStale) {
|
|
178
|
+
output.push({
|
|
179
|
+
name: normalizedName,
|
|
180
|
+
passed: false,
|
|
181
|
+
reason: gate.reason || 'Gate snapshot is stale',
|
|
182
|
+
updatedAt: gate.updatedAt,
|
|
183
|
+
});
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
output.push({
|
|
188
|
+
name: normalizedName,
|
|
189
|
+
passed: gate.passed,
|
|
190
|
+
reason: gate.reason,
|
|
191
|
+
updatedAt: gate.updatedAt,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return output;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private normalizeGateValue(
|
|
199
|
+
value: GateSnapshotGateValue,
|
|
200
|
+
snapshotUpdatedAt: number | undefined,
|
|
201
|
+
now: number,
|
|
202
|
+
) {
|
|
203
|
+
if (typeof value === 'boolean') {
|
|
204
|
+
return {
|
|
205
|
+
passed: value,
|
|
206
|
+
updatedAt: this.normalizeUpdatedAt(snapshotUpdatedAt, now),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!value || typeof value !== 'object') {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const hasPassed = typeof value.passed === 'boolean';
|
|
215
|
+
const passed = value.passed === true;
|
|
216
|
+
let reason =
|
|
217
|
+
typeof value.reason === 'string' && value.reason.trim().length > 0
|
|
218
|
+
? value.reason
|
|
219
|
+
: undefined;
|
|
220
|
+
if (!hasPassed) {
|
|
221
|
+
reason = reason || 'Gate snapshot record is missing "passed" boolean';
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
passed,
|
|
225
|
+
reason,
|
|
226
|
+
updatedAt: this.normalizeUpdatedAt(
|
|
227
|
+
value.updatedAt ?? snapshotUpdatedAt,
|
|
228
|
+
now,
|
|
229
|
+
),
|
|
230
|
+
expiresAt: this.normalizeExpiresAt(value.expiresAt),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private normalizeUpdatedAt(value: number | undefined, fallback: number) {
|
|
235
|
+
if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
return fallback;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private normalizeExpiresAt(value: number | undefined) {
|
|
242
|
+
if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
|
|
243
|
+
return value;
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
}
|