everything-dev 1.27.0 → 1.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/cli/infra.cjs +1 -1
  2. package/dist/cli/infra.mjs +1 -1
  3. package/dist/cli/init.cjs +34 -9
  4. package/dist/cli/init.cjs.map +1 -1
  5. package/dist/cli/init.d.cts +2 -1
  6. package/dist/cli/init.d.cts.map +1 -1
  7. package/dist/cli/init.d.mts +2 -1
  8. package/dist/cli/init.d.mts.map +1 -1
  9. package/dist/cli/init.mjs +34 -9
  10. package/dist/cli/init.mjs.map +1 -1
  11. package/dist/cli/prompts.cjs +28 -24
  12. package/dist/cli/prompts.cjs.map +1 -1
  13. package/dist/cli/prompts.mjs +27 -24
  14. package/dist/cli/prompts.mjs.map +1 -1
  15. package/dist/cli/sync.cjs +40 -3
  16. package/dist/cli/sync.cjs.map +1 -1
  17. package/dist/cli/sync.mjs +40 -3
  18. package/dist/cli/sync.mjs.map +1 -1
  19. package/dist/cli.cjs +187 -12
  20. package/dist/cli.cjs.map +1 -1
  21. package/dist/cli.mjs +186 -11
  22. package/dist/cli.mjs.map +1 -1
  23. package/dist/config.cjs +1 -0
  24. package/dist/config.cjs.map +1 -1
  25. package/dist/config.d.cts.map +1 -1
  26. package/dist/config.d.mts.map +1 -1
  27. package/dist/config.mjs +1 -0
  28. package/dist/config.mjs.map +1 -1
  29. package/dist/contract.cjs +1 -1
  30. package/dist/contract.cjs.map +1 -1
  31. package/dist/contract.d.cts +38 -34
  32. package/dist/contract.d.cts.map +1 -1
  33. package/dist/contract.d.mts +38 -34
  34. package/dist/contract.d.mts.map +1 -1
  35. package/dist/contract.mjs +1 -0
  36. package/dist/contract.mjs.map +1 -1
  37. package/dist/dev-session.cjs +0 -1
  38. package/dist/dev-session.mjs +1 -1
  39. package/dist/index.cjs +0 -2
  40. package/dist/index.d.cts +2 -2
  41. package/dist/index.d.mts +2 -2
  42. package/dist/index.mjs +0 -1
  43. package/dist/near-cli.cjs +1 -1
  44. package/dist/near-cli.mjs +1 -1
  45. package/dist/orchestrator.cjs +1 -1
  46. package/dist/orchestrator.mjs +1 -1
  47. package/dist/plugin.cjs +183 -151
  48. package/dist/plugin.cjs.map +1 -1
  49. package/dist/plugin.d.cts +67 -34
  50. package/dist/plugin.d.cts.map +1 -1
  51. package/dist/plugin.d.mts +66 -34
  52. package/dist/plugin.d.mts.map +1 -1
  53. package/dist/plugin.mjs +173 -142
  54. package/dist/plugin.mjs.map +1 -1
  55. package/dist/service-descriptor.d.cts +34 -0
  56. package/dist/service-descriptor.d.cts.map +1 -0
  57. package/dist/service-descriptor.d.mts +36 -0
  58. package/dist/service-descriptor.d.mts.map +1 -0
  59. package/dist/types.d.cts +2 -2
  60. package/dist/types.d.mts +2 -2
  61. package/dist/utils/run.cjs +9 -20
  62. package/dist/utils/run.cjs.map +1 -1
  63. package/dist/utils/run.mjs +9 -20
  64. package/dist/utils/run.mjs.map +1 -1
  65. package/package.json +2 -2
  66. package/src/api-contract.ts +0 -623
  67. package/src/app.ts +0 -193
  68. package/src/cli/catalog.ts +0 -49
  69. package/src/cli/framework-version.ts +0 -61
  70. package/src/cli/help.ts +0 -13
  71. package/src/cli/infra.ts +0 -190
  72. package/src/cli/init.ts +0 -1145
  73. package/src/cli/parse.ts +0 -147
  74. package/src/cli/prompts.ts +0 -135
  75. package/src/cli/snapshot.ts +0 -46
  76. package/src/cli/status.ts +0 -99
  77. package/src/cli/sync.ts +0 -429
  78. package/src/cli/timing.ts +0 -63
  79. package/src/cli/upgrade.ts +0 -869
  80. package/src/cli.ts +0 -516
  81. package/src/components/dev-view.tsx +0 -352
  82. package/src/components/streaming-view.ts +0 -177
  83. package/src/config.ts +0 -893
  84. package/src/contract.meta.ts +0 -140
  85. package/src/contract.ts +0 -326
  86. package/src/dev-logs.ts +0 -92
  87. package/src/dev-session.ts +0 -283
  88. package/src/fastkv.ts +0 -181
  89. package/src/index.ts +0 -8
  90. package/src/integrity.ts +0 -138
  91. package/src/internal/manifest-normalizer.ts +0 -290
  92. package/src/merge.ts +0 -187
  93. package/src/mf.ts +0 -147
  94. package/src/near-cli.ts +0 -259
  95. package/src/network.ts +0 -3
  96. package/src/orchestrator.ts +0 -493
  97. package/src/plugin.ts +0 -1799
  98. package/src/sdk.ts +0 -14
  99. package/src/service-descriptor.ts +0 -281
  100. package/src/shared.ts +0 -249
  101. package/src/sidebar.ts +0 -140
  102. package/src/types.ts +0 -330
  103. package/src/ui/head.ts +0 -83
  104. package/src/ui/index.ts +0 -5
  105. package/src/ui/metadata.ts +0 -95
  106. package/src/ui/router.ts +0 -88
  107. package/src/ui/runtime.ts +0 -42
  108. package/src/ui/types.ts +0 -65
  109. package/src/utils/banner.ts +0 -21
  110. package/src/utils/linkify.ts +0 -11
  111. package/src/utils/path-match.ts +0 -16
  112. package/src/utils/run.ts +0 -31
  113. package/src/utils/save-config.ts +0 -20
  114. package/src/utils/theme.ts +0 -39
@@ -1,290 +0,0 @@
1
- import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
- import { dirname, join, relative, sep } from "node:path";
3
- import { glob } from "glob";
4
-
5
- const FRAMEWORK_PACKAGES = ["every-plugin", "everything-dev"] as const;
6
-
7
- const CATALOG_TOOL_PACKAGES = [
8
- "@rspack/core",
9
- "@rspack/cli",
10
- "@rsbuild/core",
11
- "@rsbuild/plugin-react",
12
- "@module-federation/enhanced",
13
- "@module-federation/node",
14
- "@module-federation/rsbuild-plugin",
15
- "@module-federation/runtime-core",
16
- "@module-federation/sdk",
17
- "@module-federation/dts-plugin",
18
- ] as const;
19
-
20
- type PackageJson = Record<string, unknown>;
21
-
22
- type NormalizationSpec = {
23
- rootCatalog: Record<string, string>;
24
- frameworkVersions: Record<string, string>;
25
- };
26
-
27
- type NormalizeManifestOptions = {
28
- resolveCatalogRefs: boolean;
29
- preserveCatalogRefs?: boolean;
30
- excludeFrameworkWorkspaces?: boolean;
31
- removeWorkspaceDeps?: string[];
32
- removeWorkspaces?: boolean;
33
- removePublishScripts?: boolean;
34
- };
35
-
36
- export type NormalizeTreeOptions = NormalizeManifestOptions & {
37
- sourceRootDir: string;
38
- targetDir: string;
39
- };
40
-
41
- function readJson<T>(filePath: string): T {
42
- return JSON.parse(readFileSync(filePath, "utf-8")) as T;
43
- }
44
-
45
- function extractExactVersion(input: string | undefined): string | null {
46
- if (!input) return null;
47
- const match = input.match(/\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/);
48
- return match ? match[0] : null;
49
- }
50
-
51
- function writeJson(filePath: string, value: PackageJson) {
52
- writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`);
53
- }
54
-
55
- export function loadManifestNormalizationSpec(sourceRootDir: string): NormalizationSpec {
56
- const rootPackage = readJson<PackageJson>(join(sourceRootDir, "package.json"));
57
- const rootCatalog = {
58
- ...(((rootPackage.workspaces as { catalog?: Record<string, string> } | undefined)?.catalog ??
59
- {}) as Record<string, string>),
60
- };
61
- const frameworkVersions: Record<string, string> = {};
62
-
63
- for (const packageName of FRAMEWORK_PACKAGES) {
64
- const sourcePackagePath = join(sourceRootDir, "packages", packageName, "package.json");
65
- const localPackagePath = join(import.meta.dirname, "..", "..", packageName, "package.json");
66
- const packageVersion = existsSync(localPackagePath)
67
- ? readJson<{ version: string }>(localPackagePath).version
68
- : existsSync(sourcePackagePath)
69
- ? readJson<{ version: string }>(sourcePackagePath).version
70
- : extractExactVersion(rootCatalog[packageName]);
71
-
72
- if (!packageVersion) {
73
- throw new Error(`Could not resolve version for ${packageName}`);
74
- }
75
-
76
- frameworkVersions[packageName] = packageVersion;
77
- rootCatalog[packageName] = `^${packageVersion}`;
78
- }
79
-
80
- return { rootCatalog, frameworkVersions };
81
- }
82
-
83
- function normalizeDependencyMap(
84
- map: Record<string, string>,
85
- spec: NormalizationSpec,
86
- options: NormalizeManifestOptions,
87
- ) {
88
- const catalogPackages = new Set<string>([...FRAMEWORK_PACKAGES, ...CATALOG_TOOL_PACKAGES]);
89
-
90
- let modified = false;
91
-
92
- for (const [name, version] of Object.entries(map)) {
93
- if (options.preserveCatalogRefs && catalogPackages.has(name)) {
94
- if (version !== "catalog:") {
95
- map[name] = "catalog:";
96
- modified = true;
97
- }
98
- continue;
99
- }
100
-
101
- if (version === "workspace:*") {
102
- const frameworkVersion = spec.frameworkVersions[name];
103
- if (frameworkVersion) {
104
- map[name] = `^${frameworkVersion}`;
105
- modified = true;
106
- continue;
107
- }
108
-
109
- if (options.removeWorkspaceDeps?.includes(name)) {
110
- delete map[name];
111
- modified = true;
112
- }
113
- continue;
114
- }
115
-
116
- if (options.resolveCatalogRefs && version.startsWith("catalog:")) {
117
- const resolved = spec.rootCatalog[name];
118
- if (resolved) {
119
- map[name] = resolved;
120
- modified = true;
121
- }
122
- }
123
- }
124
-
125
- return modified;
126
- }
127
-
128
- export function normalizePackageManifest(
129
- pkg: PackageJson,
130
- spec: NormalizationSpec,
131
- options: NormalizeManifestOptions,
132
- ) {
133
- let modified = false;
134
-
135
- for (const depField of ["dependencies", "devDependencies", "peerDependencies"]) {
136
- const deps = pkg[depField];
137
- if (!deps || typeof deps !== "object") continue;
138
- if (normalizeDependencyMap(deps as Record<string, string>, spec, options)) {
139
- modified = true;
140
- }
141
- }
142
-
143
- if (pkg.workspaces && typeof pkg.workspaces === "object") {
144
- const workspaces = pkg.workspaces as {
145
- packages?: string[];
146
- catalog?: Record<string, string>;
147
- };
148
-
149
- if (options.excludeFrameworkWorkspaces && Array.isArray(workspaces.packages)) {
150
- const nextPackages = workspaces.packages.filter(
151
- (entry) => !FRAMEWORK_PACKAGES.some((name) => entry === `packages/${name}`),
152
- );
153
- if (nextPackages.length !== workspaces.packages.length) {
154
- workspaces.packages = nextPackages;
155
- modified = true;
156
- }
157
- }
158
-
159
- if (workspaces.catalog && typeof workspaces.catalog === "object") {
160
- for (const [name, version] of Object.entries(workspaces.catalog)) {
161
- const resolved = spec.rootCatalog[name];
162
- if (resolved && resolved !== version) {
163
- workspaces.catalog[name] = resolved;
164
- modified = true;
165
- continue;
166
- }
167
-
168
- if (version === "workspace:*" && spec.frameworkVersions[name]) {
169
- workspaces.catalog[name] = `^${spec.frameworkVersions[name]}`;
170
- modified = true;
171
- }
172
- }
173
- }
174
- }
175
-
176
- if (options.removeWorkspaces && "workspaces" in pkg) {
177
- delete pkg.workspaces;
178
- modified = true;
179
- }
180
-
181
- if (options.removePublishScripts && pkg.scripts && typeof pkg.scripts === "object") {
182
- const scripts = pkg.scripts as Record<string, string>;
183
- let scriptsModified = false;
184
- for (const key of ["prepublishOnly", "prepack", "prepare", "postpack"]) {
185
- if (key in scripts) {
186
- delete scripts[key];
187
- scriptsModified = true;
188
- }
189
- }
190
- if (scriptsModified) {
191
- modified = true;
192
- if (Object.keys(scripts).length === 0) {
193
- delete pkg.scripts;
194
- }
195
- }
196
- }
197
-
198
- return modified;
199
- }
200
-
201
- export async function normalizePackageManifestsInTree(opts: NormalizeTreeOptions) {
202
- const spec = loadManifestNormalizationSpec(opts.sourceRootDir);
203
- const files = await glob("**/package.json", {
204
- cwd: opts.targetDir,
205
- nodir: true,
206
- dot: false,
207
- absolute: true,
208
- ignore: ["**/node_modules/**"],
209
- });
210
-
211
- const updatedFiles: string[] = [];
212
-
213
- for (const filePath of files) {
214
- const pkg = readJson<PackageJson>(filePath);
215
- if (normalizePackageManifest(pkg, spec, opts)) {
216
- writeJson(filePath, pkg);
217
- updatedFiles.push(filePath);
218
- }
219
- }
220
-
221
- return updatedFiles;
222
- }
223
-
224
- function shouldCopyPackageFile(sourceDir: string, filePath: string) {
225
- const relPath = relative(sourceDir, filePath);
226
- if (!relPath) return true;
227
- const segments = relPath.split(sep);
228
- return !segments.includes("node_modules") && !segments.includes("tests");
229
- }
230
-
231
- function stripDevelopmentExports(pkg: PackageJson) {
232
- const exports = pkg.exports;
233
- if (!exports || typeof exports !== "object") return;
234
-
235
- for (const key of Object.keys(exports as Record<string, unknown>)) {
236
- const entry = (exports as Record<string, unknown>)[key];
237
- if (entry && typeof entry === "object") {
238
- delete (entry as Record<string, unknown>).development;
239
- }
240
- }
241
- }
242
-
243
- export function stageReleasePackage(opts: {
244
- repoRoot: string;
245
- packageName: string;
246
- outDir: string;
247
- }) {
248
- const sourceDir = join(opts.repoRoot, "packages", opts.packageName);
249
-
250
- rmSync(opts.outDir, { recursive: true, force: true });
251
- mkdirSync(dirname(opts.outDir), { recursive: true });
252
- cpSync(sourceDir, opts.outDir, {
253
- recursive: true,
254
- filter: (filePath) => shouldCopyPackageFile(sourceDir, filePath),
255
- });
256
- rmSync(join(opts.outDir, "tests"), { recursive: true, force: true });
257
-
258
- const packageJsonPath = join(opts.outDir, "package.json");
259
- const spec = loadManifestNormalizationSpec(opts.repoRoot);
260
- const pkg = readJson<PackageJson>(packageJsonPath);
261
-
262
- normalizePackageManifest(pkg, spec, {
263
- resolveCatalogRefs: true,
264
- preserveCatalogRefs: false,
265
- removeWorkspaces: true,
266
- removePublishScripts: true,
267
- });
268
-
269
- stripDevelopmentExports(pkg);
270
-
271
- writeJson(packageJsonPath, pkg);
272
- }
273
-
274
- export function stageReleasePackages(opts: {
275
- repoRoot: string;
276
- outDir: string;
277
- packageNames?: string[];
278
- }) {
279
- const packageNames = opts.packageNames ?? [...FRAMEWORK_PACKAGES];
280
- rmSync(opts.outDir, { recursive: true, force: true });
281
- mkdirSync(opts.outDir, { recursive: true });
282
-
283
- for (const packageName of packageNames) {
284
- stageReleasePackage({
285
- repoRoot: opts.repoRoot,
286
- packageName,
287
- outDir: join(opts.outDir, packageName),
288
- });
289
- }
290
- }
package/src/merge.ts DELETED
@@ -1,187 +0,0 @@
1
- import { createDefu } from "defu";
2
- import type { BosConfigInput, ExtendsConfig } from "./types";
3
-
4
- export const BOS_CONFIG_ORDER = [
5
- "extends",
6
- "account",
7
- "domain",
8
- "title",
9
- "description",
10
- "testnet",
11
- "staging",
12
- "repository",
13
- "app",
14
- "plugins",
15
- "shared",
16
- ] as const;
17
-
18
- export type BosConfigFieldName = (typeof BOS_CONFIG_ORDER)[number];
19
-
20
- export type BosEnv = "development" | "production" | "staging";
21
-
22
- export interface ResolvedConfigMeta {
23
- env: BosEnv;
24
- resolvedAt: string;
25
- extendsChain: string[];
26
- source?: string;
27
- }
28
-
29
- const ARRAY_UNION_KEYS = new Set(["secrets"]);
30
-
31
- export function isPlainObject(value: unknown): value is Record<string, unknown> {
32
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
33
- }
34
-
35
- function unionArrays(a: unknown, b: unknown): unknown[] | undefined {
36
- const aArr = Array.isArray(a) ? a : [];
37
- const bArr = Array.isArray(b) ? b : [];
38
- if (aArr.length === 0 && bArr.length === 0) return undefined;
39
- const seen = new Set<string>();
40
- const result: unknown[] = [];
41
- for (const item of [...aArr, ...bArr]) {
42
- if (typeof item === "string") {
43
- if (seen.has(item)) continue;
44
- seen.add(item);
45
- }
46
- result.push(item);
47
- }
48
- return result;
49
- }
50
-
51
- function cleanNullSentinels(obj: Record<string, unknown>): Record<string, unknown> {
52
- const out: Record<string, unknown> = {};
53
- for (const [key, value] of Object.entries(obj)) {
54
- if (value === null || value === undefined) continue;
55
- if (isPlainObject(value)) {
56
- const cleaned = cleanNullSentinels(value);
57
- if (Object.keys(cleaned).length > 0) {
58
- out[key] = cleaned;
59
- }
60
- } else {
61
- out[key] = value;
62
- }
63
- }
64
- return out;
65
- }
66
-
67
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
- const bosConfigMerger = createDefu((obj: any, key: any, value: any): boolean | undefined => {
69
- if (obj[key] === null) return true;
70
- if (value === null) {
71
- obj[key] = null;
72
- return true;
73
- }
74
- if (Array.isArray(obj[key]) && Array.isArray(value)) {
75
- if (ARRAY_UNION_KEYS.has(key)) {
76
- obj[key] = unionArrays(obj[key], value);
77
- } else {
78
- obj[key] = value;
79
- }
80
- return true;
81
- }
82
- return false;
83
- });
84
-
85
- export function resolveExtendsRef(
86
- extendsField: string | ExtendsConfig | undefined,
87
- env: BosEnv,
88
- ): string | undefined {
89
- if (!extendsField) return undefined;
90
- if (typeof extendsField === "string") return extendsField;
91
- return extendsField[env] ?? extendsField.production ?? Object.values(extendsField).find(Boolean);
92
- }
93
-
94
- export function mergeBosConfigWithExtends(
95
- parent: BosConfigInput,
96
- child: BosConfigInput,
97
- ): BosConfigInput {
98
- const { plugins: _ignoredParentPlugins, ...parentWithoutPlugins } = parent;
99
- const merged = bosConfigMerger(child, parentWithoutPlugins) as BosConfigInput;
100
-
101
- if (child.plugins !== undefined && isPlainObject(child.plugins)) {
102
- (merged as Record<string, unknown>).plugins = cleanNullSentinels(
103
- child.plugins as Record<string, unknown>,
104
- );
105
- } else {
106
- delete (merged as Record<string, unknown>).plugins;
107
- }
108
-
109
- const mergedRecord = merged as Record<string, unknown>;
110
-
111
- if (isPlainObject(mergedRecord.app)) {
112
- for (const entryVal of Object.values(mergedRecord.app as Record<string, unknown>)) {
113
- if (!isPlainObject(entryVal)) continue;
114
- for (const secretKey of ARRAY_UNION_KEYS) {
115
- if (Array.isArray(entryVal[secretKey])) {
116
- entryVal[secretKey] =
117
- (unionArrays(entryVal[secretKey] as unknown[], []) as string[] | undefined)?.filter(
118
- Boolean,
119
- ) ?? entryVal[secretKey];
120
- }
121
- }
122
- }
123
- }
124
-
125
- if (isPlainObject(mergedRecord.plugins)) {
126
- for (const pluginVal of Object.values(mergedRecord.plugins as Record<string, unknown>)) {
127
- if (!isPlainObject(pluginVal)) continue;
128
- for (const secretKey of ARRAY_UNION_KEYS) {
129
- if (Array.isArray(pluginVal[secretKey])) {
130
- pluginVal[secretKey] =
131
- (unionArrays(pluginVal[secretKey] as unknown[], []) as string[] | undefined)?.filter(
132
- Boolean,
133
- ) ?? pluginVal[secretKey];
134
- }
135
- }
136
- }
137
- }
138
-
139
- return rebuildOrderedConfig(mergedRecord) as BosConfigInput;
140
- }
141
-
142
- export function mergeBosConfigWithTemplate(
143
- local: BosConfigInput,
144
- template: BosConfigInput,
145
- ): BosConfigInput {
146
- const merged = mergeJsonValuesPreservingLocalOrder(local, template) as BosConfigInput;
147
- return rebuildOrderedConfig(merged as Record<string, unknown>) as BosConfigInput;
148
- }
149
-
150
- function mergeJsonValuesPreservingLocalOrder(local: unknown, template: unknown): unknown {
151
- if (isPlainObject(local) && isPlainObject(template)) {
152
- const merged: Record<string, unknown> = {};
153
- for (const key of Object.keys(local)) {
154
- merged[key] = mergeJsonValuesPreservingLocalOrder(
155
- local[key],
156
- (template as Record<string, unknown>)[key],
157
- );
158
- }
159
- for (const key of Object.keys(template as Record<string, unknown>)) {
160
- if (!(key in merged)) {
161
- merged[key] = (template as Record<string, unknown>)[key];
162
- }
163
- }
164
- return merged;
165
- }
166
- return local ?? template;
167
- }
168
-
169
- export function rebuildOrderedConfig<T extends Record<string, unknown>>(config: T): T {
170
- const ordered: Record<string, unknown> = {};
171
-
172
- for (const key of BOS_CONFIG_ORDER) {
173
- if (key in config) {
174
- ordered[key] = config[key];
175
- }
176
- }
177
-
178
- for (const key of Object.keys(config)) {
179
- if (!BOS_CONFIG_ORDER.includes(key as BosConfigFieldName)) {
180
- ordered[key] = config[key];
181
- }
182
- }
183
-
184
- return ordered as T;
185
- }
186
-
187
- export { bosConfigMerger };
package/src/mf.ts DELETED
@@ -1,147 +0,0 @@
1
- import { createInstance, getInstance } from "@module-federation/enhanced/runtime";
2
- import { setGlobalFederationInstance } from "@module-federation/runtime-core";
3
- import { computeSriHash, type IntegrityRegistry } from "./integrity";
4
-
5
- type FederationInstance = ReturnType<typeof createInstance>;
6
-
7
- let mfInstance: FederationInstance | null = null;
8
-
9
- export function patchManifestFetchForSsrPublicPath(mf: FederationInstance): void {
10
- if (!mf || !(mf as any).loaderHook?.lifecycle?.fetch?.on) return;
11
- if ((mf as any).__everythingDevPatchedManifestFetch === true) return;
12
- (mf as any).__everythingDevPatchedManifestFetch = true;
13
-
14
- (mf as any).loaderHook.lifecycle.fetch.on((url: unknown, init: unknown) => {
15
- if (typeof url !== "string" || !url.endsWith("/mf-manifest.json")) {
16
- return;
17
- }
18
- return fetch(url, init as any)
19
- .then((res) => res.json())
20
- .then((json: any) => {
21
- json.metaData = json.metaData ?? {};
22
- json.metaData.ssrPublicPath =
23
- json.metaData.ssrPublicPath ?? url.replace(/\/mf-manifest\.json$/, "/");
24
- return new Response(JSON.stringify(json), {
25
- headers: { "content-type": "application/json" },
26
- });
27
- });
28
- });
29
- }
30
-
31
- export function installIntegrityFetchHook(
32
- mf: FederationInstance,
33
- registry: IntegrityRegistry,
34
- ): void {
35
- if (!mf || !(mf as any).loaderHook?.lifecycle?.fetch?.on) {
36
- console.warn("[SRI] MF lifecycle fetch hook not available, skipping integrity-in-pipeline");
37
- return;
38
- }
39
- if ((mf as any).__everythingDevIntegrityHook === true) return;
40
- (mf as any).__everythingDevIntegrityHook = true;
41
-
42
- (mf as any).loaderHook.lifecycle.fetch.on((url: unknown, init: unknown) => {
43
- if (typeof url !== "string") return;
44
-
45
- const expectedHash = registry.get(url);
46
- if (!expectedHash) return;
47
-
48
- return fetch(url, init as any).then(async (res) => {
49
- const buffer = Buffer.from(await res.arrayBuffer());
50
- const computed = computeSriHash(buffer);
51
-
52
- if (computed !== expectedHash) {
53
- console.error(
54
- `[SRI] Integrity check failed in MF fetch pipeline for ${url}\n Expected: ${expectedHash}\n Computed: ${computed}`,
55
- );
56
- return new Response(`Integrity check failed for ${url}`, {
57
- status: 500,
58
- statusText: "Integrity Check Failed",
59
- });
60
- }
61
-
62
- console.log(`[SRI] Integrity verified in pipeline for ${url}`);
63
- return new Response(buffer, {
64
- status: res.status,
65
- statusText: res.statusText,
66
- headers: res.headers,
67
- });
68
- });
69
- });
70
- }
71
-
72
- export function getFederationInstance(): FederationInstance {
73
- if (mfInstance) return mfInstance;
74
-
75
- const existing = getInstance();
76
- if (existing) {
77
- mfInstance = existing as FederationInstance;
78
- setGlobalFederationInstance(mfInstance as any);
79
- patchManifestFetchForSsrPublicPath(mfInstance);
80
- return mfInstance;
81
- }
82
-
83
- mfInstance = createInstance({
84
- name: "host",
85
- remotes: [],
86
- }) as FederationInstance;
87
- setGlobalFederationInstance(mfInstance as any);
88
- patchManifestFetchForSsrPublicPath(mfInstance);
89
- return mfInstance;
90
- }
91
-
92
- export async function registerRemote(opts: {
93
- name: string;
94
- entry: string;
95
- type?: "manifest" | "script";
96
- }): Promise<void> {
97
- const instance = getFederationInstance();
98
-
99
- const inferType = (): "manifest" | "script" => {
100
- if (opts.type) return opts.type;
101
- if (opts.entry.endsWith("/mf-manifest.json")) return "manifest";
102
- if (opts.entry.endsWith("/remoteEntry.js")) return "script";
103
- return typeof window === "undefined" ? "script" : "manifest";
104
- };
105
-
106
- const remoteType = inferType();
107
-
108
- instance.registerRemotes([
109
- {
110
- name: opts.name,
111
- entry: opts.entry,
112
- type: remoteType,
113
- },
114
- ]);
115
- }
116
-
117
- export async function loadRemoteModule<T>(
118
- specifier: string,
119
- options?: { loadFactory?: boolean; from?: "build" | "runtime" },
120
- ): Promise<T> {
121
- const instance = getFederationInstance();
122
-
123
- const isServer = typeof window === "undefined";
124
- if (isServer) {
125
- await (instance as any).initializeSharing?.("default");
126
- }
127
-
128
- const mod = await instance.loadRemote<T>(specifier, options as any);
129
- if (!mod) {
130
- throw new Error(`Failed to load remote module: ${specifier}`);
131
- }
132
- return mod;
133
- }
134
-
135
- export async function ensureNodeRuntimePlugin(): Promise<void> {
136
- const instance = getFederationInstance();
137
- if (typeof window !== "undefined") return;
138
- if ((instance as any).__nodeRuntimePluginLoaded) return;
139
-
140
- const mod: any = await import("@module-federation/node/runtimePlugin");
141
- const factory = mod?.default ?? mod;
142
- const plugin = typeof factory === "function" ? factory() : null;
143
- if (plugin) {
144
- instance.registerPlugins([plugin]);
145
- }
146
- (instance as any).__nodeRuntimePluginLoaded = true;
147
- }