@vercel/microfrontends 0.17.2 → 0.17.4

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +48 -89
  3. package/dist/bin/cli.cjs +298 -200
  4. package/dist/config.cjs +19 -43
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.d.ts +4 -4
  7. package/dist/config.js +19 -43
  8. package/dist/config.js.map +1 -1
  9. package/dist/{types-a29d224a.d.ts → index-5fcf0863.d.ts} +2 -2
  10. package/dist/{index-09caaa28.d.ts → index-f094deb1.d.ts} +3 -3
  11. package/dist/microfrontends/server.cjs +65 -73
  12. package/dist/microfrontends/server.cjs.map +1 -1
  13. package/dist/microfrontends/server.d.ts +4 -4
  14. package/dist/microfrontends/server.js +65 -73
  15. package/dist/microfrontends/server.js.map +1 -1
  16. package/dist/microfrontends.cjs +21 -46
  17. package/dist/microfrontends.cjs.map +1 -1
  18. package/dist/microfrontends.d.ts +4 -4
  19. package/dist/microfrontends.js +21 -46
  20. package/dist/microfrontends.js.map +1 -1
  21. package/dist/next/client.cjs +1 -1
  22. package/dist/next/client.cjs.map +1 -1
  23. package/dist/next/client.js +1 -1
  24. package/dist/next/client.js.map +1 -1
  25. package/dist/next/config.cjs +83 -99
  26. package/dist/next/config.cjs.map +1 -1
  27. package/dist/next/config.js +83 -99
  28. package/dist/next/config.js.map +1 -1
  29. package/dist/next/endpoints.cjs +1 -1
  30. package/dist/next/endpoints.cjs.map +1 -1
  31. package/dist/next/endpoints.d.ts +2 -2
  32. package/dist/next/endpoints.js +1 -1
  33. package/dist/next/endpoints.js.map +1 -1
  34. package/dist/next/middleware.cjs +29 -61
  35. package/dist/next/middleware.cjs.map +1 -1
  36. package/dist/next/middleware.js +29 -61
  37. package/dist/next/middleware.js.map +1 -1
  38. package/dist/next/testing.cjs +24 -52
  39. package/dist/next/testing.cjs.map +1 -1
  40. package/dist/next/testing.d.ts +4 -4
  41. package/dist/next/testing.js +24 -52
  42. package/dist/next/testing.js.map +1 -1
  43. package/dist/overrides.cjs +1 -2
  44. package/dist/overrides.cjs.map +1 -1
  45. package/dist/overrides.d.ts +3 -3
  46. package/dist/overrides.js +1 -2
  47. package/dist/overrides.js.map +1 -1
  48. package/dist/schema.cjs.map +1 -1
  49. package/dist/schema.d.ts +1 -1
  50. package/dist/{types-fc30696d.d.ts → types-5900be7c.d.ts} +1 -1
  51. package/dist/{types-cfe3308b.d.ts → types-ecd7b91b.d.ts} +1 -1
  52. package/dist/utils/mfe-port.cjs +65 -73
  53. package/dist/utils/mfe-port.cjs.map +1 -1
  54. package/dist/utils/mfe-port.js +65 -73
  55. package/dist/utils/mfe-port.js.map +1 -1
  56. package/dist/validation.cjs +46 -17
  57. package/dist/validation.cjs.map +1 -1
  58. package/dist/validation.d.ts +1 -1
  59. package/dist/validation.js +46 -17
  60. package/dist/validation.js.map +1 -1
  61. package/package.json +20 -24
  62. package/schema/schema.json +15 -8
package/dist/bin/cli.cjs CHANGED
@@ -29,7 +29,7 @@ var import_commander = require("commander");
29
29
  // package.json
30
30
  var package_default = {
31
31
  name: "@vercel/microfrontends",
32
- version: "0.17.2",
32
+ version: "0.17.4",
33
33
  private: false,
34
34
  description: "Defines configuration and utilities for micro-frontend development",
35
35
  repository: {
@@ -39,12 +39,8 @@ var package_default = {
39
39
  },
40
40
  sideEffects: false,
41
41
  type: "module",
42
- bin: {
43
- microfrontends: "./cli/index.cjs",
44
- "micro-frontends": "./cli/index.cjs"
45
- },
46
42
  exports: {
47
- "./schema.json": "./schema/schema-v2.json",
43
+ "./schema.json": "./schema/schema.json",
48
44
  "./validation": {
49
45
  import: "./dist/validation.js",
50
46
  require: "./dist/validation.cjs"
@@ -104,35 +100,68 @@ var package_default = {
104
100
  },
105
101
  typesVersions: {
106
102
  "*": {
107
- validation: ["./dist/validation.d.ts"],
108
- config: ["./dist/config.d.ts"],
109
- microfrontends: ["./dist/microfrontends.d.ts"],
110
- overrides: ["./dist/overrides.d.ts"],
111
- routing: ["./dist/routing.d.ts"],
112
- "microfrontends/server": ["./dist/microfrontends/server.d.ts"],
113
- "microfrontends/utils": ["./dist/microfrontends/utils.d.ts"],
114
- schema: ["./dist/schema.d.ts"],
115
- "next/config": ["./dist/next/config.d.ts"],
116
- "next/middleware": ["./dist/next/middleware.d.ts"],
117
- "next/endpoints": ["./dist/next/endpoints.d.ts"],
118
- "next/testing": ["./dist/next/testing.d.ts"],
119
- "next/client": ["./dist/next/client.d.ts"],
120
- "utils/mfe-port": ["./dist/utils/mfe-port.d.ts"]
103
+ validation: [
104
+ "./dist/validation.d.ts"
105
+ ],
106
+ config: [
107
+ "./dist/config.d.ts"
108
+ ],
109
+ microfrontends: [
110
+ "./dist/microfrontends.d.ts"
111
+ ],
112
+ overrides: [
113
+ "./dist/overrides.d.ts"
114
+ ],
115
+ routing: [
116
+ "./dist/routing.d.ts"
117
+ ],
118
+ "microfrontends/server": [
119
+ "./dist/microfrontends/server.d.ts"
120
+ ],
121
+ "microfrontends/utils": [
122
+ "./dist/microfrontends/utils.d.ts"
123
+ ],
124
+ schema: [
125
+ "./dist/schema.d.ts"
126
+ ],
127
+ "next/config": [
128
+ "./dist/next/config.d.ts"
129
+ ],
130
+ "next/middleware": [
131
+ "./dist/next/middleware.d.ts"
132
+ ],
133
+ "next/endpoints": [
134
+ "./dist/next/endpoints.d.ts"
135
+ ],
136
+ "next/testing": [
137
+ "./dist/next/testing.d.ts"
138
+ ],
139
+ "next/client": [
140
+ "./dist/next/client.d.ts"
141
+ ],
142
+ "utils/mfe-port": [
143
+ "./dist/utils/mfe-port.d.ts"
144
+ ]
121
145
  }
122
146
  },
123
- files: ["dist", "schema"],
147
+ bin: {
148
+ microfrontends: "./cli/index.cjs"
149
+ },
150
+ files: [
151
+ "dist",
152
+ "schema"
153
+ ],
124
154
  scripts: {
125
155
  build: "tsup",
126
156
  postbuild: "pnpm generate:exports",
127
- "generate:schema": "tsx scripts/generate-json-schema.ts",
128
157
  "generate:exports": "tsx scripts/generate-exports/index.ts",
129
- conformance: "vercel conformance",
130
- eslint: "eslint-runner",
131
- "eslint-fix": "eslint-runner --fix",
158
+ "generate:schema": "tsx scripts/generate-json-schema.ts",
159
+ lint: "eslint .",
160
+ "lint-fix": "eslint . --fix",
132
161
  prepublishOnly: "pnpm build && pnpm generate:exports && pnpm generate:schema",
133
- "type-check": "tsc --noEmit",
134
- "unit-test": "cross-env TZ=UTC jest",
135
- proxy: "tsx src/proxy/index.ts"
162
+ proxy: "tsx src/proxy/index.ts",
163
+ test: "cross-env TZ=UTC jest",
164
+ typecheck: "tsc --noEmit"
136
165
  },
137
166
  dependencies: {
138
167
  ajv: "^8.17.1",
@@ -144,9 +173,8 @@ var package_default = {
144
173
  "path-to-regexp": "6.2.1"
145
174
  },
146
175
  devDependencies: {
176
+ "@edge-runtime/jest-environment": "^4.0.0",
147
177
  "@edge-runtime/types": "^3.0.2",
148
- "@pyra/eslint-config": "workspace:*",
149
- "@pyra/typescript-config": "workspace:*",
150
178
  "@testing-library/react": "^15.0.7",
151
179
  "@types/cookie": "0.5.1",
152
180
  "@types/http-proxy": "^1.17.15",
@@ -155,31 +183,31 @@ var package_default = {
155
183
  "@types/node": "20.11.30",
156
184
  "@types/react": "18.3.1",
157
185
  "@types/react-dom": "18.3.0",
158
- "@vercel-private/conformance": "^1.12.2-canary.0",
186
+ "eslint-config-custom": "workspace:*",
159
187
  jest: "^29.7.0",
160
188
  "jest-environment-jsdom": "29.2.2",
161
- next: "15.2.0-canary.28",
189
+ next: "15.2.0-canary.32",
162
190
  react: "19.0.0",
163
191
  "react-dom": "19.0.0",
192
+ "ts-config": "workspace:*",
164
193
  "ts-json-schema-generator": "^1.1.2",
194
+ "ts-node": "~10.9.2",
165
195
  tsup: "^6.6.2",
166
196
  tsx: "^4.6.2",
167
- typescript: "5.6.3",
197
+ typescript: "5.7.3",
168
198
  webpack: "5"
169
199
  },
170
200
  peerDependencies: {
171
- next: "15.2.0-canary.28",
172
- react: "19.0.0",
173
- "react-dom": "19.0.0"
174
- },
175
- publishConfig: {
176
- access: "restricted"
201
+ next: ">=13",
202
+ react: ">=17.0.0",
203
+ "react-dom": ">=17.0.0"
177
204
  }
178
205
  };
179
206
 
180
207
  // src/bin/local-proxy.ts
181
208
  var http = __toESM(require("http"), 1);
182
209
  var https = __toESM(require("https"), 1);
210
+ var import_node_url = require("url");
183
211
  var import_cookie = require("cookie");
184
212
  var import_path_to_regexp3 = require("path-to-regexp");
185
213
  var import_http_proxy = __toESM(require("http-proxy"), 1);
@@ -194,9 +222,9 @@ var MicrofrontendError = class extends Error {
194
222
  constructor(message, opts) {
195
223
  super(message);
196
224
  this.name = "MicrofrontendsError";
197
- this.source = (opts == null ? void 0 : opts.source) ?? "@vercel/microfrontends";
198
- this.type = (opts == null ? void 0 : opts.type) ?? "unknown";
199
- this.subtype = opts == null ? void 0 : opts.subtype;
225
+ this.source = opts?.source ?? "@vercel/microfrontends";
226
+ this.type = opts?.type ?? "unknown";
227
+ this.subtype = opts?.subtype;
200
228
  Error.captureStackTrace(this, MicrofrontendError);
201
229
  }
202
230
  isKnown() {
@@ -211,7 +239,7 @@ var MicrofrontendError = class extends Error {
211
239
  * @returns The converted MicrofrontendsError.
212
240
  */
213
241
  static convert(original, opts) {
214
- if (opts == null ? void 0 : opts.fileName) {
242
+ if (opts?.fileName) {
215
243
  const err = MicrofrontendError.convertFSError(original, opts.fileName);
216
244
  if (err) {
217
245
  return err;
@@ -283,17 +311,6 @@ var MicrofrontendError = class extends Error {
283
311
 
284
312
  // src/config/microfrontends-config/isomorphic/validation.ts
285
313
  var import_path_to_regexp = require("path-to-regexp");
286
- var SUPPORTED_VERSIONS = ["2"];
287
- var validateConfigVersion = (version) => {
288
- if (!SUPPORTED_VERSIONS.includes(version)) {
289
- throw new MicrofrontendError(
290
- `Unsupported version: ${version}. Supported versions are: ${SUPPORTED_VERSIONS.join(
291
- ", "
292
- )}`,
293
- { type: "config", subtype: "unsupported_version" }
294
- );
295
- }
296
- };
297
314
  var validateConfigPaths = (applicationConfigsById) => {
298
315
  if (!applicationConfigsById) {
299
316
  return;
@@ -469,7 +486,7 @@ var Host = class {
469
486
  this.protocol = protocol;
470
487
  this.host = host;
471
488
  this.port = Host.getPort({ port, protocol: this.protocol });
472
- this.local = options == null ? void 0 : options.isLocal;
489
+ this.local = options?.isLocal;
473
490
  }
474
491
  isLocal() {
475
492
  return this.local || this.host === "localhost" || this.host === "127.0.0.1";
@@ -518,18 +535,17 @@ var Application = class {
518
535
  overrides,
519
536
  isDefault
520
537
  }) {
521
- var _a, _b;
522
538
  this.name = name;
523
539
  this.development = {
524
540
  local: new LocalHost({
525
541
  appName: name,
526
- ...(_a = app.development) == null ? void 0 : _a.local
542
+ ...app.development?.local
527
543
  }),
528
- fallback: ((_b = app.development) == null ? void 0 : _b.fallback) ? new Host(app.development.fallback) : void 0
544
+ fallback: app.development?.fallback ? new Host(app.development.fallback) : void 0
529
545
  };
530
546
  this.production = app.production ? new Host(app.production) : void 0;
531
547
  this.vercel = app.vercel;
532
- this.overrides = (overrides == null ? void 0 : overrides.environment) ? {
548
+ this.overrides = overrides?.environment ? {
533
549
  environment: new Host(overrides.environment)
534
550
  } : void 0;
535
551
  this.default = isDefault ?? false;
@@ -607,7 +623,7 @@ var MicrofrontendConfigClient = class {
607
623
  constructor(config, opts) {
608
624
  this.pathCache = {};
609
625
  this.serialized = config;
610
- if (opts == null ? void 0 : opts.removeFlaggedPaths) {
626
+ if (opts?.removeFlaggedPaths) {
611
627
  for (const app of Object.values(config.applications)) {
612
628
  if (app.routing) {
613
629
  app.routing = app.routing.filter((match) => !match.flag);
@@ -673,8 +689,7 @@ var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
673
689
 
674
690
  // src/config/overrides/is-override-cookie.ts
675
691
  function isOverrideCookie(cookie) {
676
- var _a;
677
- return Boolean((_a = cookie.name) == null ? void 0 : _a.startsWith(OVERRIDES_COOKIE_PREFIX));
692
+ return Boolean(cookie.name?.startsWith(OVERRIDES_COOKIE_PREFIX));
678
693
  }
679
694
 
680
695
  // src/config/overrides/get-override-from-cookie.ts
@@ -713,14 +728,13 @@ var MicrofrontendConfigIsomorphic = class {
713
728
  opts
714
729
  }) {
715
730
  this.childApplications = {};
716
- var _a, _b, _c, _d;
717
731
  MicrofrontendConfigIsomorphic.validate(config, opts);
718
- const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
732
+ const disableOverrides = config.options?.vercel?.disableOverrides ?? false;
719
733
  this.overrides = overrides && !disableOverrides ? overrides : void 0;
720
734
  this.isMainConfig = isMainConfig(config);
721
735
  if (isMainConfig(config)) {
722
736
  for (const [appId, appConfig] of Object.entries(config.applications)) {
723
- const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
737
+ const appOverrides = !disableOverrides ? this.overrides?.applications[appId] : void 0;
724
738
  if (isDefaultApp(appConfig)) {
725
739
  this.defaultApplication = new DefaultApplication(appId, {
726
740
  app: appConfig,
@@ -735,7 +749,7 @@ var MicrofrontendConfigIsomorphic = class {
735
749
  }
736
750
  } else {
737
751
  this.partOf = config.partOf;
738
- const appOverrides = !disableOverrides ? (_d = this.overrides) == null ? void 0 : _d.applications[meta.fromApp] : void 0;
752
+ const appOverrides = !disableOverrides ? this.overrides?.applications[meta.fromApp] : void 0;
739
753
  this.childApplications[meta.fromApp] = new ChildApplication(
740
754
  meta.fromApp,
741
755
  {
@@ -763,12 +777,9 @@ var MicrofrontendConfigIsomorphic = class {
763
777
  };
764
778
  }
765
779
  static validate(config, opts) {
766
- const skipValidation = (opts == null ? void 0 : opts.skipValidation) ?? [];
780
+ const skipValidation = opts?.skipValidation ?? [];
767
781
  const c = typeof config === "string" ? (0, import_jsonc_parser.parse)(config) : config;
768
782
  if (isMainConfig(c)) {
769
- if (!skipValidation.includes("version")) {
770
- validateConfigVersion(c.version);
771
- }
772
783
  if (!skipValidation.includes("paths")) {
773
784
  validateConfigPaths(c.applications);
774
785
  }
@@ -789,8 +800,7 @@ var MicrofrontendConfigIsomorphic = class {
789
800
  });
790
801
  }
791
802
  isOverridesDisabled() {
792
- var _a, _b;
793
- return ((_b = (_a = this.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
803
+ return this.options?.vercel?.disableOverrides ?? false;
794
804
  }
795
805
  getConfig() {
796
806
  return this.config;
@@ -811,8 +821,7 @@ var MicrofrontendConfigIsomorphic = class {
811
821
  ].filter(Boolean);
812
822
  }
813
823
  getApplication(name) {
814
- var _a;
815
- if (((_a = this.defaultApplication) == null ? void 0 : _a.name) === name) {
824
+ if (this.defaultApplication?.name === name) {
816
825
  return this.defaultApplication;
817
826
  }
818
827
  const app = this.childApplications[name];
@@ -828,15 +837,11 @@ var MicrofrontendConfigIsomorphic = class {
828
837
  return app;
829
838
  }
830
839
  getApplicationByProjectId(projectId) {
831
- var _a, _b;
832
- if (((_b = (_a = this.defaultApplication) == null ? void 0 : _a.vercel) == null ? void 0 : _b.projectId) === projectId) {
840
+ if (this.defaultApplication?.vercel?.projectId === projectId) {
833
841
  return this.defaultApplication;
834
842
  }
835
843
  return Object.values(this.childApplications).find(
836
- (app) => {
837
- var _a2;
838
- return ((_a2 = app.vercel) == null ? void 0 : _a2.projectId) === projectId;
839
- }
844
+ (app) => app.vercel?.projectId === projectId
840
845
  );
841
846
  }
842
847
  /**
@@ -859,8 +864,7 @@ var MicrofrontendConfigIsomorphic = class {
859
864
  * Returns the configured port for the local proxy
860
865
  */
861
866
  getLocalProxyPort() {
862
- var _a, _b;
863
- return ((_b = (_a = this.config.options) == null ? void 0 : _a.localProxy) == null ? void 0 : _b.port) ?? DEFAULT_LOCAL_PROXY_PORT;
867
+ return this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
864
868
  }
865
869
  /**
866
870
  * Serializes the class back to the Schema type.
@@ -901,13 +905,12 @@ var MicrofrontendMainConfig = class extends MicrofrontendConfigIsomorphic {
901
905
  overrides,
902
906
  meta
903
907
  }) {
904
- var _a, _b, _c;
905
908
  super({ config, overrides, meta });
906
909
  this.isMainConfig = true;
907
- const disableOverrides = ((_b = (_a = config.options) == null ? void 0 : _a.vercel) == null ? void 0 : _b.disableOverrides) ?? false;
910
+ const disableOverrides = config.options?.vercel?.disableOverrides ?? false;
908
911
  let defaultApplication;
909
912
  for (const [appId, appConfig] of Object.entries(config.applications)) {
910
- const appOverrides = !disableOverrides ? (_c = this.overrides) == null ? void 0 : _c.applications[appId] : void 0;
913
+ const appOverrides = !disableOverrides ? this.overrides?.applications[appId] : void 0;
911
914
  if (isDefaultApp(appConfig)) {
912
915
  defaultApplication = new DefaultApplication(appId, {
913
916
  app: appConfig,
@@ -1122,7 +1125,7 @@ function findDefaultMicrofrontendsPackage(opts) {
1122
1125
  const result = findDefaultMicrofrontendsPackages(opts);
1123
1126
  if (!result) {
1124
1127
  throw new Error(
1125
- `Error trying to resolve the main microfrontends configuration`
1128
+ "Error trying to resolve the main microfrontends configuration"
1126
1129
  );
1127
1130
  }
1128
1131
  configCache2[cacheKey] = result;
@@ -1194,20 +1197,8 @@ var import_node_path7 = __toESM(require("path"), 1);
1194
1197
  var MFE_CONFIG_DEFAULT_FILE_PATH = "microfrontends";
1195
1198
  var MFE_CONFIG_DEFAULT_FILE_NAME = "microfrontends.json";
1196
1199
 
1197
- // src/utils/is-vercel.ts
1198
- function isVercel() {
1199
- return process.env.VERCEL === "1";
1200
- }
1201
-
1202
1200
  // src/config/microfrontends/server/utils/get-output-file-path.ts
1203
1201
  function getOutputFilePath() {
1204
- if (isVercel()) {
1205
- return import_node_path7.default.join(
1206
- ".vercel",
1207
- MFE_CONFIG_DEFAULT_FILE_PATH,
1208
- MFE_CONFIG_DEFAULT_FILE_NAME
1209
- );
1210
- }
1211
1202
  return import_node_path7.default.join(MFE_CONFIG_DEFAULT_FILE_PATH, MFE_CONFIG_DEFAULT_FILE_NAME);
1212
1203
  }
1213
1204
 
@@ -1238,7 +1229,7 @@ var schema_default = {
1238
1229
  },
1239
1230
  version: {
1240
1231
  type: "string",
1241
- const: "2"
1232
+ const: "1"
1242
1233
  },
1243
1234
  options: {
1244
1235
  $ref: "#/definitions/Options"
@@ -1248,6 +1239,9 @@ var schema_default = {
1248
1239
  additionalProperties: {
1249
1240
  $ref: "#/definitions/Application"
1250
1241
  },
1242
+ propertyNames: {
1243
+ description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1244
+ },
1251
1245
  description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1252
1246
  },
1253
1247
  applications: {
@@ -1255,7 +1249,9 @@ var schema_default = {
1255
1249
  description: "Mapping of application names to the routes that they host. Only needs to be defined in the application that owns the primary microfrontend domain"
1256
1250
  }
1257
1251
  },
1258
- required: ["applications", "version"],
1252
+ required: [
1253
+ "applications"
1254
+ ],
1259
1255
  additionalProperties: false
1260
1256
  },
1261
1257
  Options: {
@@ -1319,7 +1315,9 @@ var schema_default = {
1319
1315
  $ref: "#/definitions/HostConfig"
1320
1316
  }
1321
1317
  },
1322
- required: ["production"],
1318
+ required: [
1319
+ "production"
1320
+ ],
1323
1321
  additionalProperties: false
1324
1322
  },
1325
1323
  Vercel: {
@@ -1330,7 +1328,9 @@ var schema_default = {
1330
1328
  description: "Vercel project ID"
1331
1329
  }
1332
1330
  },
1333
- required: ["projectId"],
1331
+ required: [
1332
+ "projectId"
1333
+ ],
1334
1334
  additionalProperties: false
1335
1335
  },
1336
1336
  Development: {
@@ -1360,8 +1360,11 @@ var schema_default = {
1360
1360
  },
1361
1361
  protocol: {
1362
1362
  type: "string",
1363
- enum: ["http", "https"],
1364
- description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
1363
+ enum: [
1364
+ "http",
1365
+ "https"
1366
+ ],
1367
+ description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1365
1368
  },
1366
1369
  port: {
1367
1370
  type: "number",
@@ -1374,8 +1377,11 @@ var schema_default = {
1374
1377
  properties: {
1375
1378
  protocol: {
1376
1379
  type: "string",
1377
- enum: ["http", "https"],
1378
- description: 'The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n* @defaultValue "http" for local development, "https" for otherwise'
1380
+ enum: [
1381
+ "http",
1382
+ "https"
1383
+ ],
1384
+ description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1379
1385
  },
1380
1386
  host: {
1381
1387
  type: "string",
@@ -1386,7 +1392,9 @@ var schema_default = {
1386
1392
  description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
1387
1393
  }
1388
1394
  },
1389
- required: ["host"],
1395
+ required: [
1396
+ "host"
1397
+ ],
1390
1398
  additionalProperties: false
1391
1399
  },
1392
1400
  ChildApplication: {
@@ -1406,7 +1414,9 @@ var schema_default = {
1406
1414
  $ref: "#/definitions/HostConfig"
1407
1415
  }
1408
1416
  },
1409
- required: ["routing"],
1417
+ required: [
1418
+ "routing"
1419
+ ],
1410
1420
  additionalProperties: false
1411
1421
  },
1412
1422
  Routing: {
@@ -1433,13 +1443,18 @@ var schema_default = {
1433
1443
  }
1434
1444
  }
1435
1445
  },
1436
- required: ["paths"],
1446
+ required: [
1447
+ "paths"
1448
+ ],
1437
1449
  additionalProperties: false
1438
1450
  },
1439
1451
  ApplicationRouting: {
1440
1452
  type: "object",
1441
1453
  additionalProperties: {
1442
1454
  $ref: "#/definitions/Application"
1455
+ },
1456
+ propertyNames: {
1457
+ description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1443
1458
  }
1444
1459
  },
1445
1460
  ChildConfig: {
@@ -1450,7 +1465,7 @@ var schema_default = {
1450
1465
  },
1451
1466
  version: {
1452
1467
  type: "string",
1453
- const: "2"
1468
+ const: "1"
1454
1469
  },
1455
1470
  options: {
1456
1471
  $ref: "#/definitions/Options"
@@ -1460,6 +1475,9 @@ var schema_default = {
1460
1475
  additionalProperties: {
1461
1476
  $ref: "#/definitions/Application"
1462
1477
  },
1478
+ propertyNames: {
1479
+ description: "The unique identifier for a Microfrontend Application. Must match the `name` field of the application's `package.json`."
1480
+ },
1463
1481
  description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1464
1482
  },
1465
1483
  partOf: {
@@ -1467,7 +1485,9 @@ var schema_default = {
1467
1485
  description: "Applications that only serve a subset of the microfrontend routes only need to reference the name of the primary application that owns the full microfrontends configuration."
1468
1486
  }
1469
1487
  },
1470
- required: ["partOf", "version"],
1488
+ required: [
1489
+ "partOf"
1490
+ ],
1471
1491
  additionalProperties: false
1472
1492
  }
1473
1493
  }
@@ -1641,7 +1661,7 @@ var MicrofrontendsServer = class extends Microfrontends {
1641
1661
  try {
1642
1662
  const configJson = import_node_fs7.default.readFileSync(filePath, "utf-8");
1643
1663
  const config = MicrofrontendsServer.validate(configJson);
1644
- if (!isMainConfig(config) && (options == null ? void 0 : options.resolveMainConfig)) {
1664
+ if (!isMainConfig(config) && options?.resolveMainConfig) {
1645
1665
  const repositoryRoot = findRepositoryRoot();
1646
1666
  const isMonorepo2 = isMonorepo({ repositoryRoot });
1647
1667
  if (isMonorepo2) {
@@ -1725,53 +1745,29 @@ var mfeDebug = (message) => {
1725
1745
  console.log(message);
1726
1746
  }
1727
1747
  };
1728
- var LocalProxy = class {
1748
+ var ProxyRequestRouter = class {
1729
1749
  constructor(config, {
1730
- localApps,
1731
- proxyPort
1750
+ localApps
1732
1751
  }) {
1733
1752
  this.config = config;
1734
1753
  this.localApps = localApps;
1735
- this.proxyPort = proxyPort ?? this.config.getLocalProxyPort();
1736
- this.proxy = import_http_proxy.default.createProxyServer({ secure: true });
1737
- this.proxy.on("error", (err, req, res) => {
1738
- if (res instanceof http.ServerResponse) {
1739
- res.writeHead(500, {
1740
- "Content-Type": "text/plain"
1741
- });
1742
- }
1743
- const target = this.getTarget(req);
1744
- res.end(
1745
- `Error proxying request to ${target.application}. Is the server running locally on port ${target.port}?`
1746
- );
1747
- console.error(`Error proxying request for ${target.application}: `, err);
1748
- });
1749
- }
1750
- static fromFile(filePath, {
1751
- localApps,
1752
- proxyPort
1753
- }) {
1754
- const microfrontends = MicrofrontendsServer.infer({
1755
- directory: filePath
1756
- });
1757
- if (isMainConfig2(microfrontends.config)) {
1758
- return new LocalProxy(microfrontends.config, { localApps, proxyPort });
1759
- }
1760
- throw new Error(
1761
- `Unable to find main config from child application (${filePath})`
1762
- );
1763
1754
  }
1764
1755
  getDefaultHost(config) {
1765
1756
  const defaultApp = config.getDefaultApplication();
1766
1757
  return this.getApplicationTarget(defaultApp);
1767
1758
  }
1768
1759
  getApplicationTarget(application) {
1769
- var _a, _b;
1770
1760
  const useDev = this.localApps.includes(application.name);
1771
- let host = useDev ? application.development.local : application.production ?? this.config.getDefaultApplication().production;
1772
- if ((_b = (_a = application.overrides) == null ? void 0 : _a.environment) == null ? void 0 : _b.host) {
1761
+ let applicationName = application.name;
1762
+ let host = useDev ? application.development.local : application.production;
1763
+ if (application.overrides?.environment?.host) {
1773
1764
  host = application.overrides.environment;
1774
1765
  }
1766
+ if (!host) {
1767
+ const defaultApp = this.config.getDefaultApplication();
1768
+ host = defaultApp.production;
1769
+ applicationName = defaultApp.name;
1770
+ }
1775
1771
  const protocol = host.protocol;
1776
1772
  const hostname = host.host;
1777
1773
  const port = host.port;
@@ -1780,7 +1776,7 @@ var LocalProxy = class {
1780
1776
  protocol,
1781
1777
  hostname,
1782
1778
  port,
1783
- application: application.name
1779
+ application: applicationName
1784
1780
  };
1785
1781
  }
1786
1782
  /**
@@ -1790,12 +1786,11 @@ var LocalProxy = class {
1790
1786
  * protected host.
1791
1787
  */
1792
1788
  getAuthTarget(request2, config) {
1793
- var _a, _b;
1794
- const url = new URL(request2.url ?? "", `http://${request2.headers.host}`);
1795
- const isAuthRedirect = (_a = request2.url) == null ? void 0 : _a.startsWith(
1789
+ const url = new import_node_url.URL(request2.url ?? "", `http://${request2.headers.host}`);
1790
+ const isAuthRedirect = request2.url?.startsWith(
1796
1791
  "/.well-known/vercel-auth-redirect"
1797
1792
  );
1798
- const isSsoRedirect = (_b = request2.url) == null ? void 0 : _b.startsWith("/sso-api");
1793
+ const isSsoRedirect = request2.url?.startsWith("/sso-api");
1799
1794
  const isJWTRedirect = url.searchParams.has("_vercel_jwt");
1800
1795
  const defaultHost = this.getDefaultHost(config);
1801
1796
  let hostname = null;
@@ -1843,13 +1838,13 @@ var LocalProxy = class {
1843
1838
  if (authTarget) {
1844
1839
  return authTarget;
1845
1840
  }
1846
- const url = new URL(`http://example.com${path6}`);
1847
- const pathname = url.pathname;
1848
- const target = this.findMatchingApplication(
1849
- path6,
1850
- pathname,
1851
- config.getChildApplications()
1852
- );
1841
+ const url = new import_node_url.URL(`http://example.com${path6}`);
1842
+ const target = this.findMatchingApplication({
1843
+ path: path6,
1844
+ url,
1845
+ applications: config.getChildApplications(),
1846
+ referer: request2.headers.referer
1847
+ });
1853
1848
  if (target)
1854
1849
  return target;
1855
1850
  const defaultHost = this.getDefaultHost(config);
@@ -1858,13 +1853,31 @@ var LocalProxy = class {
1858
1853
  );
1859
1854
  return { path: path6, ...defaultHost };
1860
1855
  }
1861
- findMatchingApplication(path6, pathname, applications) {
1856
+ findMatchingApplication({
1857
+ path: path6,
1858
+ url,
1859
+ applications,
1860
+ referer = void 0
1861
+ }) {
1862
1862
  for (const application of Object.values(applications)) {
1863
+ const target = this.getApplicationTarget(application);
1864
+ const builtInRewrite = this.checkBuiltinAssetPrefix({
1865
+ rewrites: [
1866
+ "/_next/static/:path+",
1867
+ "/.well-known/vercel/flags",
1868
+ "/_vercel/:path*"
1869
+ ],
1870
+ path: path6,
1871
+ url,
1872
+ app: application
1873
+ }) || this.checkNextOriginalFrame({ url, referer, applications });
1874
+ if (builtInRewrite) {
1875
+ return builtInRewrite;
1876
+ }
1863
1877
  for (const group of application.routing) {
1864
1878
  for (const childPath of group.paths) {
1865
1879
  const regexp = (0, import_path_to_regexp3.pathToRegexp)(childPath);
1866
- if (regexp.test(pathname)) {
1867
- const target = this.getApplicationTarget(application);
1880
+ if (regexp.test(url.pathname)) {
1868
1881
  mfeDebug(
1869
1882
  `routing ${path6} to '${target.application}' at ${target.hostname}`
1870
1883
  );
@@ -1875,39 +1888,112 @@ var LocalProxy = class {
1875
1888
  }
1876
1889
  return null;
1877
1890
  }
1878
- // Handles requests that return data from the local proxy itself.
1879
- // Returns true if the request was handled, false otherwise.
1880
- handleProxyInfoRequest(path6, res) {
1881
- if (!path6) {
1882
- return false;
1883
- }
1884
- const url = new URL(`http://example.comf${path6}`);
1891
+ checkBuiltinAssetPrefix({
1892
+ rewrites,
1893
+ path: path6,
1894
+ url,
1895
+ app
1896
+ }) {
1885
1897
  const pathname = url.pathname;
1886
- switch (pathname) {
1887
- case "/.well-known/vercel/microfrontends/routing": {
1888
- res.writeHead(200, {
1889
- "Content-Type": "application/json"
1890
- });
1891
- const payload = Object.fromEntries(
1892
- this.config.getAllApplications().map((app) => {
1893
- const { hostname, port, protocol } = this.getApplicationTarget(app);
1894
- return [
1895
- app.name,
1896
- { routing: { host: hostname, port, protocol } }
1897
- ];
1898
- })
1898
+ const target = this.getApplicationTarget(app);
1899
+ const isTargetDefault = target.application === this.config.getDefaultApplication().name;
1900
+ for (const rewrite of rewrites) {
1901
+ if ((0, import_path_to_regexp3.pathToRegexp)(`/${app.getAssetPrefix()}${rewrite}`).test(pathname)) {
1902
+ mfeDebug(
1903
+ `routing ${pathname} to '${target.application}' at ${target.hostname}`
1899
1904
  );
1900
- res.end(JSON.stringify(payload));
1901
- return true;
1905
+ const processedPath = isTargetDefault ? path6 : path6.replace(`/${app.getAssetPrefix()}`, "");
1906
+ return {
1907
+ path: processedPath,
1908
+ ...target
1909
+ };
1902
1910
  }
1903
1911
  }
1904
- return false;
1912
+ return null;
1913
+ }
1914
+ checkNextOriginalFrame({
1915
+ url,
1916
+ referer = void 0,
1917
+ applications
1918
+ }) {
1919
+ const isStackFrame = (0, import_path_to_regexp3.pathToRegexp)("/__nextjs_original-stack-frame").test(
1920
+ url.pathname
1921
+ );
1922
+ if (!referer || !isStackFrame) {
1923
+ return null;
1924
+ }
1925
+ const refererURL = new import_node_url.URL(referer);
1926
+ const refererPath = `${refererURL.pathname}?${refererURL.search}`;
1927
+ const refererApp = this.findMatchingApplication({
1928
+ path: refererPath,
1929
+ url: refererURL,
1930
+ applications
1931
+ });
1932
+ mfeDebug(
1933
+ `routing nextjs stack frame request to ${refererApp?.application}`
1934
+ );
1935
+ return refererApp ? {
1936
+ ...refererApp,
1937
+ path: `${url.pathname}${url.search}`
1938
+ } : null;
1939
+ }
1940
+ };
1941
+ var LocalProxy = class {
1942
+ constructor(config, {
1943
+ localApps,
1944
+ proxyPort
1945
+ }) {
1946
+ this.router = new ProxyRequestRouter(config, { localApps });
1947
+ this.proxyPort = proxyPort ?? this.router.config.getLocalProxyPort();
1948
+ this.proxy = import_http_proxy.default.createProxyServer({ secure: true });
1949
+ this.proxy.on("error", (err, req, res) => {
1950
+ if (res instanceof http.ServerResponse) {
1951
+ res.writeHead(500, {
1952
+ "Content-Type": "text/plain"
1953
+ });
1954
+ }
1955
+ const target = this.router.getTarget(req);
1956
+ res.end(
1957
+ `Error proxying request to ${target.application}. Is the server running locally on port ${target.port}?`
1958
+ );
1959
+ console.error(`Error proxying request for ${target.application}: `, err);
1960
+ });
1961
+ }
1962
+ static fromFile(filePath, {
1963
+ localApps,
1964
+ proxyPort
1965
+ }) {
1966
+ const microfrontends = MicrofrontendsServer.infer({
1967
+ directory: filePath
1968
+ });
1969
+ if (isMainConfig2(microfrontends.config)) {
1970
+ return new LocalProxy(microfrontends.config, { localApps, proxyPort });
1971
+ }
1972
+ throw new Error(
1973
+ `Unable to find main config from child application (${filePath})`
1974
+ );
1975
+ }
1976
+ startServer() {
1977
+ const httpServer = http.createServer(
1978
+ (req, res) => this.handleRequest(req, res)
1979
+ );
1980
+ httpServer.on("upgrade", (req, socket, head) => {
1981
+ const target = this.router.getTarget(req);
1982
+ try {
1983
+ this.proxy.ws(req, socket, head, { target: target.url });
1984
+ } catch (err) {
1985
+ console.error("Error proxying ws: ", err);
1986
+ }
1987
+ });
1988
+ httpServer.listen(this.proxyPort, () => {
1989
+ console.log(`Microfrontends Proxy: http://localhost:${this.proxyPort}`);
1990
+ });
1905
1991
  }
1906
1992
  handleRequest(req, res) {
1907
1993
  if (this.handleProxyInfoRequest(req.url, res)) {
1908
1994
  return;
1909
1995
  }
1910
- const target = this.getTarget(req);
1996
+ const target = this.router.getTarget(req);
1911
1997
  if (target.protocol === "https") {
1912
1998
  const { hostname, port, path: path6 } = target;
1913
1999
  const requestOptions = {
@@ -1925,7 +2011,7 @@ var LocalProxy = class {
1925
2011
  if (realRes.statusCode === 307) {
1926
2012
  const locationHeader = realRes.headers.location;
1927
2013
  if (locationHeader) {
1928
- const redirectUrl = new URL(
2014
+ const redirectUrl = new import_node_url.URL(
1929
2015
  locationHeader.replace(/https:\/\/[^/]+\//, "/"),
1930
2016
  localhost
1931
2017
  );
@@ -1949,21 +2035,33 @@ var LocalProxy = class {
1949
2035
  });
1950
2036
  }
1951
2037
  }
1952
- startServer() {
1953
- const httpServer = http.createServer(
1954
- (req, res) => this.handleRequest(req, res)
1955
- );
1956
- httpServer.on("upgrade", (req, socket, head) => {
1957
- const target = this.getTarget(req);
1958
- try {
1959
- this.proxy.ws(req, socket, head, { target: target.url });
1960
- } catch (err) {
1961
- console.error("Error proxying ws: ", err);
2038
+ // Handles requests that return data from the local proxy itself.
2039
+ // Returns true if the request was handled, false otherwise.
2040
+ handleProxyInfoRequest(path6, res) {
2041
+ if (!path6) {
2042
+ return false;
2043
+ }
2044
+ const url = new import_node_url.URL(`http://example.comf${path6}`);
2045
+ const pathname = url.pathname;
2046
+ switch (pathname) {
2047
+ case "/.well-known/vercel/microfrontends/routing": {
2048
+ res.writeHead(200, {
2049
+ "Content-Type": "application/json"
2050
+ });
2051
+ const payload = Object.fromEntries(
2052
+ this.router.config.getAllApplications().map((app) => {
2053
+ const { hostname, port, protocol } = this.router.getApplicationTarget(app);
2054
+ return [
2055
+ app.name,
2056
+ { routing: { host: hostname, port, protocol } }
2057
+ ];
2058
+ })
2059
+ );
2060
+ res.end(JSON.stringify(payload));
2061
+ return true;
1962
2062
  }
1963
- });
1964
- httpServer.listen(this.proxyPort, () => {
1965
- console.log(`Microfrontends Proxy: http://localhost:${this.proxyPort}`);
1966
- });
2063
+ }
2064
+ return false;
1967
2065
  }
1968
2066
  };
1969
2067