@vercel/microfrontends 1.1.1-canary.5 → 1.1.1-canary.7

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 (60) hide show
  1. package/dist/bin/cli.cjs +406 -205
  2. package/dist/config.cjs +26 -69
  3. package/dist/config.cjs.map +1 -1
  4. package/dist/config.d.ts +5 -5
  5. package/dist/config.js +26 -69
  6. package/dist/config.js.map +1 -1
  7. package/dist/experimental/sveltekit.cjs +65 -194
  8. package/dist/experimental/sveltekit.cjs.map +1 -1
  9. package/dist/experimental/sveltekit.js +65 -194
  10. package/dist/experimental/sveltekit.js.map +1 -1
  11. package/dist/experimental/vite.cjs +65 -194
  12. package/dist/experimental/vite.cjs.map +1 -1
  13. package/dist/experimental/vite.js +65 -194
  14. package/dist/experimental/vite.js.map +1 -1
  15. package/dist/microfrontends/server.cjs +65 -194
  16. package/dist/microfrontends/server.cjs.map +1 -1
  17. package/dist/microfrontends/server.d.ts +3 -3
  18. package/dist/microfrontends/server.js +65 -194
  19. package/dist/microfrontends/server.js.map +1 -1
  20. package/dist/next/client.cjs +1 -1
  21. package/dist/next/client.cjs.map +1 -1
  22. package/dist/next/client.d.ts +2 -2
  23. package/dist/next/client.js +1 -1
  24. package/dist/next/client.js.map +1 -1
  25. package/dist/next/config.cjs +70 -359
  26. package/dist/next/config.cjs.map +1 -1
  27. package/dist/next/config.d.ts +1 -1
  28. package/dist/next/config.js +70 -359
  29. package/dist/next/config.js.map +1 -1
  30. package/dist/next/endpoints.d.ts +2 -2
  31. package/dist/next/middleware.cjs +26 -69
  32. package/dist/next/middleware.cjs.map +1 -1
  33. package/dist/next/middleware.js +26 -69
  34. package/dist/next/middleware.js.map +1 -1
  35. package/dist/next/testing.cjs +124 -145
  36. package/dist/next/testing.cjs.map +1 -1
  37. package/dist/next/testing.d.ts +36 -5
  38. package/dist/next/testing.js +123 -144
  39. package/dist/next/testing.js.map +1 -1
  40. package/dist/overrides.d.ts +3 -3
  41. package/dist/schema.d.ts +2 -2
  42. package/dist/{types-f1260e44.d.ts → types-b970b583.d.ts} +1 -1
  43. package/dist/{types-a4add5ab.d.ts → types-bee19651.d.ts} +11 -2
  44. package/dist/{types-54064641.d.ts → types-c9f15465.d.ts} +31 -85
  45. package/dist/utils/mfe-port.cjs +65 -194
  46. package/dist/utils/mfe-port.cjs.map +1 -1
  47. package/dist/utils/mfe-port.js +65 -194
  48. package/dist/utils/mfe-port.js.map +1 -1
  49. package/dist/validation.cjs +39 -125
  50. package/dist/validation.cjs.map +1 -1
  51. package/dist/validation.d.ts +1 -1
  52. package/dist/validation.js +39 -125
  53. package/dist/validation.js.map +1 -1
  54. package/package.json +4 -10
  55. package/schema/schema.json +45 -131
  56. package/dist/routing.cjs +0 -19
  57. package/dist/routing.cjs.map +0 -1
  58. package/dist/routing.d.ts +0 -26
  59. package/dist/routing.js +0 -1
  60. package/dist/routing.js.map +0 -1
package/dist/bin/cli.cjs CHANGED
@@ -25,11 +25,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/bin/index.ts
27
27
  var import_commander = require("commander");
28
+ var import_env = require("@next/env");
28
29
 
29
30
  // package.json
30
31
  var package_default = {
31
32
  name: "@vercel/microfrontends",
32
- version: "1.1.1-canary.5",
33
+ version: "1.1.1-canary.7",
33
34
  private: false,
34
35
  description: "Defines configuration and utilities for microfrontends development",
35
36
  keywords: [
@@ -66,10 +67,6 @@ var package_default = {
66
67
  import: "./dist/overrides.js",
67
68
  require: "./dist/overrides.cjs"
68
69
  },
69
- "./routing": {
70
- import: "./dist/routing.js",
71
- require: "./dist/routing.cjs"
72
- },
73
70
  "./microfrontends/server": {
74
71
  import: "./dist/microfrontends/server.js",
75
72
  require: "./dist/microfrontends/server.cjs"
@@ -124,9 +121,6 @@ var package_default = {
124
121
  overrides: [
125
122
  "./dist/overrides.d.ts"
126
123
  ],
127
- routing: [
128
- "./dist/routing.d.ts"
129
- ],
130
124
  "microfrontends/server": [
131
125
  "./dist/microfrontends/server.d.ts"
132
126
  ],
@@ -176,6 +170,7 @@ var package_default = {
176
170
  typecheck: "tsc --noEmit"
177
171
  },
178
172
  dependencies: {
173
+ "@next/env": "15.1.6",
179
174
  ajv: "^8.17.1",
180
175
  commander: "^12.1.0",
181
176
  cookie: "0.4.0",
@@ -481,8 +476,7 @@ var validateConfigPaths = (applicationConfigsById) => {
481
476
  if (isDefaultApp(app)) {
482
477
  continue;
483
478
  }
484
- const childApp = app;
485
- for (const pathMatch of childApp.routing) {
479
+ for (const pathMatch of app.routing) {
486
480
  for (const path7 of pathMatch.paths) {
487
481
  const maybeError = validatePathExpression(path7);
488
482
  if (maybeError) {
@@ -562,7 +556,7 @@ function validatePathExpression(path7) {
562
556
  }
563
557
  if (token.pattern !== PATH_DEFAULT_PATTERN && // Allows (a|b|c) and ((?!a|b|c).*) regex
564
558
  // Only limited regex is supported for now, due to performance considerations
565
- !/^(?<allowed>[\w]+(?:\|[^|()]+)+)$|^\(\?!(?<disallowed>[\w]+(?:\|[^|()]+)+)\)\.\*$/.test(
559
+ !/^(?<allowed>[\w]+(?:\|[^:|()]+)+)$|^\(\?!(?<disallowed>[\w]+(?:\|[^:|()]+)*)\)\.\*$/.test(
566
560
  token.pattern
567
561
  )) {
568
562
  return `Path ${path7} cannot use unsupported regular expression wildcard`;
@@ -630,64 +624,15 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
630
624
  };
631
625
  var validateDeprecatedFields = (config) => {
632
626
  const errors = [];
633
- if (config.options?.vercel) {
634
- errors.push(
635
- `Configuration cannot contain deprecated field 'options.vercel'. Use 'options.disableOverrides' instead.`
636
- );
637
- }
638
- if (config.options?.localProxy) {
639
- errors.push(
640
- `Configuration cannot contain deprecated field 'options.localProxy'. Use 'options.localProxyPort' instead.`
641
- );
642
- }
643
627
  for (const [applicationId, application] of Object.entries(
644
628
  config.applications
645
629
  )) {
646
- if (application.vercel) {
647
- errors.push(
648
- `Application '${applicationId}' cannot contain deprecated field 'vercel'. Use 'projectId' instead.`
649
- );
650
- }
651
- if (application.production) {
652
- errors.push(
653
- `Application '${applicationId}' cannot contain deprecated field 'production'. Use 'development.fallback' instead.`
654
- );
655
- }
656
630
  if (application.development?.localPort) {
657
631
  errors.push(
658
632
  `Application '${applicationId}' cannot contain deprecated field 'development.localPort'. Use 'developement.local' instead.`
659
633
  );
660
634
  }
661
- if (application.development?.fallback && typeof application.development.fallback !== "string") {
662
- const fallback = application.development.fallback;
663
- let asString = fallback.host;
664
- if (fallback.protocol) {
665
- asString = `${fallback.protocol}://${asString}`;
666
- }
667
- if (fallback.port) {
668
- asString = `${asString}:${fallback.port}`;
669
- }
670
- errors.push(
671
- `Application '${applicationId}' requires a string (not an object) for the 'development.fallback' field. Please set 'development.fallback' to '${asString}'.`
672
- );
673
- }
674
- if (application.development?.local && typeof application.development.local !== "string" && typeof application.development.local !== "number") {
675
- const local = application.development.local;
676
- let asString;
677
- if (local.port && !local.protocol && !local.host) {
678
- asString = String(local.port);
679
- } else {
680
- asString = local.host ?? "localhost";
681
- if (local.protocol) {
682
- asString = `${local.protocol}://${asString}`;
683
- }
684
- if (local.port) {
685
- asString = `${asString}:${local.port}`;
686
- }
687
- }
688
- errors.push(
689
- `Application '${applicationId}' requires a string or number (not an object) for the 'development.local' field. Please set 'development.local' to '${asString}'.`
690
- );
635
+ if (application.projectId) {
691
636
  }
692
637
  }
693
638
  if (errors.length) {
@@ -842,6 +787,13 @@ var LocalHost = class extends Host {
842
787
  }
843
788
  };
844
789
 
790
+ // src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
791
+ function generateAutomationBypassEnvVarName({
792
+ name
793
+ }) {
794
+ return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
795
+ }
796
+
845
797
  // src/config/microfrontends-config/isomorphic/application.ts
846
798
  var Application = class {
847
799
  constructor(name, {
@@ -860,10 +812,8 @@ var Application = class {
860
812
  };
861
813
  if (app.development?.fallback) {
862
814
  this.fallback = new Host(app.development.fallback);
863
- } else if (app.production) {
864
- this.fallback = new Host(app.production);
865
815
  }
866
- this.projectId = app.projectId ?? app.vercel?.projectId;
816
+ this.projectId = app.projectId;
867
817
  this.packageName = app.packageName;
868
818
  this.overrides = overrides?.environment ? {
869
819
  environment: new Host(overrides.environment)
@@ -877,6 +827,9 @@ var Application = class {
877
827
  getAssetPrefix() {
878
828
  return generateAssetPrefixFromName({ name: this.name });
879
829
  }
830
+ getAutomationBypassEnvVarName() {
831
+ return generateAutomationBypassEnvVarName({ name: this.name });
832
+ }
880
833
  serialize() {
881
834
  return this.serialized;
882
835
  }
@@ -892,16 +845,7 @@ var DefaultApplication = class extends Application {
892
845
  isDefault: true
893
846
  });
894
847
  this.default = true;
895
- const fallbackHost = app.development?.fallback ?? app.production;
896
- if (fallbackHost === void 0) {
897
- throw new Error(
898
- "`app.production` or `app.development.fallback` must be set in the default application in microfrontends.json."
899
- );
900
- }
901
- this.fallback = new Host(fallbackHost);
902
- if (app.production) {
903
- this.production = new Host(app.production);
904
- }
848
+ this.fallback = new Host(app.development.fallback);
905
849
  }
906
850
  getAssetPrefix() {
907
851
  return "";
@@ -938,7 +882,7 @@ var MicrofrontendConfigIsomorphic = class {
938
882
  }) {
939
883
  this.childApplications = {};
940
884
  MicrofrontendConfigIsomorphic.validate(config, opts);
941
- const disableOverrides = config.options?.disableOverrides ?? config.options?.vercel?.disableOverrides ?? false;
885
+ const disableOverrides = config.options?.disableOverrides ?? false;
942
886
  this.overrides = overrides && !disableOverrides ? overrides : void 0;
943
887
  let defaultApplication;
944
888
  for (const [appId, appConfig] of Object.entries(config.applications)) {
@@ -991,7 +935,7 @@ var MicrofrontendConfigIsomorphic = class {
991
935
  });
992
936
  }
993
937
  isOverridesDisabled() {
994
- return this.options?.vercel?.disableOverrides ?? false;
938
+ return this.options?.disableOverrides ?? false;
995
939
  }
996
940
  getConfig() {
997
941
  return this.config;
@@ -1029,6 +973,14 @@ var MicrofrontendConfigIsomorphic = class {
1029
973
  }
1030
974
  return app;
1031
975
  }
976
+ hasApplication(name) {
977
+ try {
978
+ this.getApplication(name);
979
+ return true;
980
+ } catch {
981
+ return false;
982
+ }
983
+ }
1032
984
  getApplicationByProjectId(projectId) {
1033
985
  if (this.defaultApplication.projectId === projectId) {
1034
986
  return this.defaultApplication;
@@ -1047,7 +999,7 @@ var MicrofrontendConfigIsomorphic = class {
1047
999
  * Returns the configured port for the local proxy
1048
1000
  */
1049
1001
  getLocalProxyPort() {
1050
- return this.config.options?.localProxyPort ?? this.config.options?.localProxy?.port ?? DEFAULT_LOCAL_PROXY_PORT;
1002
+ return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
1051
1003
  }
1052
1004
  /**
1053
1005
  * Serializes the class back to the Schema type.
@@ -1325,20 +1277,10 @@ var schema_default = {
1325
1277
  Options: {
1326
1278
  type: "object",
1327
1279
  properties: {
1328
- vercel: {
1329
- $ref: "#/definitions/VercelOptions",
1330
- description: "Microfrontends wide options for Vercel.",
1331
- deprecated: "This is being replaced by the `disableOverrides` field below."
1332
- },
1333
1280
  disableOverrides: {
1334
1281
  type: "boolean",
1335
1282
  description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
1336
1283
  },
1337
- localProxy: {
1338
- $ref: "#/definitions/LocalProxyOptions",
1339
- description: "Options for local proxy.",
1340
- deprecated: "This is being replaced by the `localProxyPort` field below."
1341
- },
1342
1284
  localProxyPort: {
1343
1285
  type: "number",
1344
1286
  description: "The port number used by the local proxy server.\n\nThe default is `3024`."
@@ -1346,26 +1288,6 @@ var schema_default = {
1346
1288
  },
1347
1289
  additionalProperties: false
1348
1290
  },
1349
- VercelOptions: {
1350
- type: "object",
1351
- properties: {
1352
- disableOverrides: {
1353
- type: "boolean",
1354
- description: "If you want to disable the overrides for the site. For example, if you are managing rewrites between applications externally, you may wish to disable the overrides on the toolbar as they will have no effect."
1355
- }
1356
- },
1357
- additionalProperties: false
1358
- },
1359
- LocalProxyOptions: {
1360
- type: "object",
1361
- properties: {
1362
- port: {
1363
- type: "number",
1364
- description: "The port number used by the local proxy server.\n\nThe default is `3024`."
1365
- }
1366
- },
1367
- additionalProperties: false
1368
- },
1369
1291
  ApplicationRouting: {
1370
1292
  type: "object",
1371
1293
  additionalProperties: {
@@ -1388,141 +1310,62 @@ var schema_default = {
1388
1310
  DefaultApplication: {
1389
1311
  type: "object",
1390
1312
  properties: {
1391
- vercel: {
1392
- $ref: "#/definitions/Vercel",
1393
- deprecated: "This is being replaced by the `projectId` field below."
1394
- },
1395
1313
  projectId: {
1396
1314
  type: "string",
1397
1315
  description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1398
- deprecated: "Instead, the application id should match the Vercel project name."
1316
+ deprecated: "Instead, the application id should match the Vercel project name. `packageName` can optionally\nbe set to the name of the package.json (if it is different from the project name)."
1399
1317
  },
1400
1318
  packageName: {
1401
1319
  type: "string",
1402
1320
  description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1403
1321
  },
1404
- production: {
1405
- $ref: "#/definitions/HostConfig",
1406
- deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
1407
- },
1408
1322
  development: {
1409
- $ref: "#/definitions/Development"
1410
- }
1411
- },
1412
- additionalProperties: false
1413
- },
1414
- Vercel: {
1415
- type: "object",
1416
- properties: {
1417
- projectId: {
1418
- type: "string",
1419
- description: "Vercel project ID"
1420
- }
1421
- },
1422
- required: ["projectId"],
1423
- additionalProperties: false
1424
- },
1425
- HostConfig: {
1426
- type: "object",
1427
- properties: {
1428
- protocol: {
1429
- type: "string",
1430
- enum: ["http", "https"],
1431
- description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1432
- },
1433
- host: {
1434
- type: "string",
1435
- description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
1436
- },
1437
- port: {
1438
- type: "number",
1439
- description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
1323
+ $ref: "#/definitions/DefaultDevelopment",
1324
+ description: "Development configuration for the default application."
1440
1325
  }
1441
1326
  },
1442
- required: ["host"],
1327
+ required: ["development"],
1443
1328
  additionalProperties: false
1444
1329
  },
1445
- Development: {
1330
+ DefaultDevelopment: {
1446
1331
  type: "object",
1447
1332
  properties: {
1448
1333
  local: {
1449
- anyOf: [
1450
- {
1451
- type: "number"
1452
- },
1453
- {
1454
- type: "string"
1455
- },
1456
- {
1457
- $ref: "#/definitions/LocalHostConfig"
1458
- }
1459
- ],
1460
- description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080\n\nPassing a LocalHostConfig is deprecated and will go away soon, please pass a number or string."
1334
+ type: ["number", "string"],
1335
+ description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080"
1461
1336
  },
1462
1337
  localPort: {
1463
1338
  type: "number",
1464
1339
  description: "The local port number that this application runs on when it is running locally. Common values include `80` for HTTP and `443` for HTTPS. If omitted, the port defaults to a unique, but stable (based on the application name) number.",
1465
1340
  deprecated: "Please set the port with the 'local' field instead."
1466
1341
  },
1467
- fallback: {
1468
- anyOf: [
1469
- {
1470
- $ref: "#/definitions/HostConfig"
1471
- },
1472
- {
1473
- type: "string"
1474
- }
1475
- ],
1476
- description: "Fallback for local development, could point to any environment. If this is not provided, or the application is not running - requests to the application in local development will error.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS.\n\nPassing a HostConfig is deprecated and will go away soon, please pass a string."
1477
- },
1478
1342
  task: {
1479
1343
  type: "string",
1480
1344
  description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
1481
- }
1482
- },
1483
- additionalProperties: false
1484
- },
1485
- LocalHostConfig: {
1486
- type: "object",
1487
- additionalProperties: false,
1488
- properties: {
1489
- host: {
1490
- type: "string",
1491
- description: "The hostname or IP address of the server. This can be a domain name (e.g., `example.com`) or an IP address (e.g., `192.168.1.1`)."
1492
1345
  },
1493
- protocol: {
1346
+ fallback: {
1494
1347
  type: "string",
1495
- enum: ["http", "https"],
1496
- description: "The protocol to be used for the connection.\n- `http`: Hypertext Transfer Protocol (HTTP).\n- `https`: Secure Hypertext Transfer Protocol (HTTPS).\n\n*"
1497
- },
1498
- port: {
1499
- type: "number",
1500
- description: "The port number to be used for the connection. Common values include `80` for HTTP and `443` for HTTPS."
1348
+ description: "Fallback for local development, could point to any environment. This is required for the default app. This value is used as the fallback for child apps as well if they do not have a fallback.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS."
1501
1349
  }
1502
- }
1350
+ },
1351
+ required: ["fallback"],
1352
+ additionalProperties: false
1503
1353
  },
1504
1354
  ChildApplication: {
1505
1355
  type: "object",
1506
1356
  properties: {
1507
- vercel: {
1508
- $ref: "#/definitions/Vercel",
1509
- deprecated: "This is being replaced by the `projectId` field below."
1510
- },
1511
1357
  projectId: {
1512
1358
  type: "string",
1513
1359
  description: "Vercel project ID, only required if the application name / id is different to the Vercel project name.",
1514
- deprecated: "Instead, the application id should match the Vercel project name."
1360
+ deprecated: "Instead, the application id should match the Vercel project name. `packageName` can optionally\nbe set to the name of the package.json (if it is different from the project name)."
1515
1361
  },
1516
1362
  packageName: {
1517
1363
  type: "string",
1518
1364
  description: "The name used to run the application, e.g. the `name` field in the `package.json`.\n\nThis is used by the local proxy to map the application config to the locally running app.\n\nThis is only necessary when the application name does not match the `name` used in `package.json`."
1519
1365
  },
1520
- production: {
1521
- $ref: "#/definitions/HostConfig",
1522
- deprecated: "This is a duplicate of the `development.fallback` field and this will be removed soon."
1523
- },
1524
1366
  development: {
1525
- $ref: "#/definitions/Development"
1367
+ $ref: "#/definitions/ChildDevelopment",
1368
+ description: "Development configuration for the child application."
1526
1369
  },
1527
1370
  routing: {
1528
1371
  $ref: "#/definitions/Routing",
@@ -1532,6 +1375,29 @@ var schema_default = {
1532
1375
  required: ["routing"],
1533
1376
  additionalProperties: false
1534
1377
  },
1378
+ ChildDevelopment: {
1379
+ type: "object",
1380
+ properties: {
1381
+ local: {
1382
+ type: ["number", "string"],
1383
+ description: "A local port number or host string that this application runs on when it is running locally. If passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTP. If omitted, the port defaults to a unique, but stable (based on the application name) number.\n\nExamples of valid values:\n- 8080\n- my.localhost.me\n- my.localhost.me:8080\n- https://my.localhost.me\n- https://my.localhost.me:8080"
1384
+ },
1385
+ localPort: {
1386
+ type: "number",
1387
+ description: "The local port number that this application runs on when it is running locally. Common values include `80` for HTTP and `443` for HTTPS. If omitted, the port defaults to a unique, but stable (based on the application name) number.",
1388
+ deprecated: "Please set the port with the 'local' field instead."
1389
+ },
1390
+ task: {
1391
+ type: "string",
1392
+ description: "Optional task to run when starting the development server. Should reference a script in the package.json of the application."
1393
+ },
1394
+ fallback: {
1395
+ type: "string",
1396
+ description: "Fallback for local development, could point to any environment. This is optional for child apps. If not provided, the fallback of the default app will be used.\n\nIf passing a string, include the protocol (optional), host (required) and port (optional). For example: `https://this.ismyhost:8080`. If omitted, the protocol defaults to HTTPS. If omitted, the port defaults to `80` for HTTP and `443` for HTTPS."
1397
+ }
1398
+ },
1399
+ additionalProperties: false
1400
+ },
1535
1401
  Routing: {
1536
1402
  type: "array",
1537
1403
  items: {
@@ -1617,7 +1483,7 @@ function formatAjvErrors(errors) {
1617
1483
  }
1618
1484
  function validateSchema(configString) {
1619
1485
  const parsedConfig = (0, import_jsonc_parser3.parse)(configString);
1620
- const ajv = new import_ajv.Ajv();
1486
+ const ajv = new import_ajv.Ajv({ allowUnionTypes: true });
1621
1487
  const validate = ajv.compile(SCHEMA);
1622
1488
  const isValid = validate(parsedConfig);
1623
1489
  if (!isValid) {
@@ -1810,6 +1676,311 @@ var MicrofrontendsServer = class {
1810
1676
  }
1811
1677
  };
1812
1678
 
1679
+ // src/bin/local-auth.ts
1680
+ var localAuthHtml = ({
1681
+ app,
1682
+ hostname,
1683
+ defaultApp,
1684
+ automationBypassEnvVarName,
1685
+ automationBypass
1686
+ }) => {
1687
+ const content = automationBypass ? `<b><code>${automationBypassEnvVarName}</code></b> is set with the value <b><code>${automationBypass}</code></b>, please verify this value equals the <a href="https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation">Protection Bypass for Automation</a> for the Vercel project hosting the deployment.` : `To access, set a local environment variable <b><code>${automationBypassEnvVarName}</code></b> with the value of the <a href="https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation">Protection Bypass for Automation</a> for the Vercel project hosting the deployment.`;
1688
+ return `<!DOCTYPE html>
1689
+ <html lang="en">
1690
+ <head>
1691
+ <meta charset="utf-8">
1692
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1693
+ <meta name="theme-color" content="#000">
1694
+ <title>Authentication Required</title>
1695
+ <style>
1696
+ html {
1697
+ font-size: 62.5%;
1698
+ box-sizing: border-box;
1699
+ height: -webkit-fill-available
1700
+ }
1701
+
1702
+ *,
1703
+ ::after,
1704
+ ::before {
1705
+ box-sizing: inherit
1706
+ }
1707
+
1708
+ body {
1709
+ font-family: "SF Pro Text", "SF Pro Icons", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
1710
+ font-size: 1.6rem;
1711
+ line-height: 1.65;
1712
+ word-break: break-word;
1713
+ font-kerning: auto;
1714
+ font-variant: normal;
1715
+ -webkit-font-smoothing: antialiased;
1716
+ -moz-osx-font-smoothing: grayscale;
1717
+ text-rendering: optimizeLegibility;
1718
+ hyphens: none;
1719
+ height: 100vh;
1720
+ height: -webkit-fill-available;
1721
+ max-height: 100vh;
1722
+ max-height: -webkit-fill-available;
1723
+ margin: 0
1724
+ }
1725
+
1726
+ ::selection {
1727
+ background: #79FFE1;
1728
+ }
1729
+ ::-moz-selection {
1730
+ background: #79FFE1;
1731
+ }
1732
+
1733
+ a {
1734
+ cursor: pointer;
1735
+ color: #0070f3;
1736
+ text-decoration: none;
1737
+ transition: all .2s ease;
1738
+ border-bottom: 1px solid transparent
1739
+ }
1740
+
1741
+ a:hover {
1742
+ border-bottom: 1px solid #0070f3
1743
+ }
1744
+
1745
+ ul {
1746
+ padding: 0;
1747
+ margin-left: 1.5em;
1748
+ list-style-type: none
1749
+ }
1750
+
1751
+ li {
1752
+ margin-bottom: 10px
1753
+ }
1754
+
1755
+ ul li:before {
1756
+ content: '\\02013'
1757
+ }
1758
+
1759
+ li:before {
1760
+ display: inline-block;
1761
+ color: #ccc;
1762
+ position: absolute;
1763
+ margin-left: -18px;
1764
+ transition: color .2s ease
1765
+ }
1766
+
1767
+ code {
1768
+ font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
1769
+ font-size: .92em;
1770
+ }
1771
+
1772
+ code:after,
1773
+ code:before {
1774
+ content: '\`'
1775
+ }
1776
+
1777
+ .container {
1778
+ display: flex;
1779
+ justify-content: center;
1780
+ flex-direction: column;
1781
+ min-height: 100%
1782
+ }
1783
+
1784
+ main {
1785
+ max-width: 80rem;
1786
+ padding: 4rem 6rem;
1787
+ margin: auto
1788
+ }
1789
+
1790
+ ul {
1791
+ margin-bottom: 32px
1792
+ }
1793
+
1794
+ .error-title {
1795
+ font-size: 2rem;
1796
+ padding-left: 22px;
1797
+ line-height: 1.5;
1798
+ margin-bottom: 24px;
1799
+ }
1800
+
1801
+ .error-title-guilty {
1802
+ border-left: 2px solid #ED367F;
1803
+ }
1804
+
1805
+ .error-title-innocent {
1806
+ border-left: 2px solid #59B89C;
1807
+ }
1808
+
1809
+ main p {
1810
+ color: #333
1811
+ }
1812
+
1813
+ .devinfo-container {
1814
+ border: 1px solid #ddd;
1815
+ border-radius: 4px;
1816
+ padding: 2rem;
1817
+ display: flex;
1818
+ flex-direction: column;
1819
+ margin-bottom: 32px
1820
+ }
1821
+
1822
+ .error-code {
1823
+ margin: 0;
1824
+ font-size: 1.6rem;
1825
+ color: #000;
1826
+ margin-bottom: 1.6rem
1827
+ }
1828
+
1829
+ .devinfo-line {
1830
+ color: #333
1831
+ }
1832
+
1833
+ .devinfo-line code,
1834
+ code,
1835
+ li {
1836
+ color: #000
1837
+ }
1838
+
1839
+ .devinfo-line:not(:last-child) {
1840
+ margin-bottom: 8px
1841
+ }
1842
+
1843
+ .docs-link,
1844
+ .contact-link {
1845
+ font-weight: 500
1846
+ }
1847
+
1848
+ header,
1849
+ footer,
1850
+ footer a {
1851
+ display: flex;
1852
+ justify-content: center;
1853
+ align-items: center
1854
+ }
1855
+
1856
+ header,
1857
+ footer {
1858
+ min-height: 100px;
1859
+ height: 100px;
1860
+ }
1861
+
1862
+ header {
1863
+ border-bottom: 1px solid #eaeaea;
1864
+ }
1865
+
1866
+ header h1 {
1867
+ font-size: 1.8rem;
1868
+ margin: 0;
1869
+ font-weight: 500;
1870
+ }
1871
+
1872
+ header p {
1873
+ font-size: 1.3rem;
1874
+ margin: 0;
1875
+ font-weight: 500;
1876
+ }
1877
+
1878
+ .header-item {
1879
+ display: flex;
1880
+ padding: 0 2rem;
1881
+ margin: 2rem 0;
1882
+ text-decoration: line-through;
1883
+ color: #999;
1884
+ }
1885
+
1886
+ .header-item.active {
1887
+ color: #ff0080;
1888
+ text-decoration: none;
1889
+ }
1890
+
1891
+ .header-item.first {
1892
+ border-right: 1px solid #eaeaea;
1893
+ }
1894
+
1895
+ .header-item-content {
1896
+ display: flex;
1897
+ flex-direction: column;
1898
+ }
1899
+
1900
+ .header-item-icon {
1901
+ margin-right: 1rem;
1902
+ margin-top: 0.6rem;
1903
+ }
1904
+
1905
+ footer {
1906
+ border-top: 1px solid #eaeaea;
1907
+ }
1908
+
1909
+ footer a {
1910
+ color: #000
1911
+ }
1912
+
1913
+ footer a:hover {
1914
+ border-bottom-color: transparent
1915
+ }
1916
+
1917
+ footer svg {
1918
+ margin-left: .8rem
1919
+ }
1920
+
1921
+ .note {
1922
+ padding: 8pt 16pt;
1923
+ border-radius: 5px;
1924
+ border: 1px solid #0070f3;
1925
+ font-size: 14px;
1926
+ line-height: 1.8;
1927
+ color: #0070f3;
1928
+ }
1929
+
1930
+ @media (max-width:500px) {
1931
+ .devinfo-container .devinfo-line code {
1932
+ margin-top: .4rem
1933
+ }
1934
+ .devinfo-container .devinfo-line:not(:last-child) {
1935
+ margin-bottom: 1.6rem
1936
+ }
1937
+ .devinfo-container {
1938
+ margin-bottom: 0;
1939
+ }
1940
+ header {
1941
+ flex-direction: column;
1942
+ height: auto;
1943
+ min-height: auto;
1944
+ align-items: flex-start;
1945
+ }
1946
+ .header-item.first {
1947
+ border-right: none;
1948
+ margin-bottom: 0;
1949
+ }
1950
+ main {
1951
+ padding: 1rem 2rem;
1952
+ }
1953
+ body {
1954
+ font-size: 1.4rem;
1955
+ line-height: 1.55;
1956
+ }
1957
+ footer {
1958
+ display: none;
1959
+ }
1960
+ .note {
1961
+ margin-top: 16px;
1962
+ }
1963
+ }
1964
+ </style>
1965
+ </head>
1966
+ <body>
1967
+ <div class="container">
1968
+ <main>
1969
+ <p class="devinfo-container">
1970
+ <span><b><code>${app}</code></b> is falling back to a protected deployment <a target="_blank" href="https://${hostname}">${hostname}</a>.</span>
1971
+ <br>
1972
+ <span>${content}</span>
1973
+ <br>
1974
+ <span>The environment variable should be set in the default app <b><code>${defaultApp}</code></b>, where the local proxy is running.</span>
1975
+ </p>
1976
+
1977
+ <a href="https://vercel.com/docs/microfrontends/local-development#falling-back-to-protected-deployments"><div class="note">Click here to learn more about setting up the environment variable.</div></a>
1978
+ </main>
1979
+ </div>
1980
+ </body>
1981
+ </html>`;
1982
+ };
1983
+
1813
1984
  // src/bin/local-proxy.ts
1814
1985
  var MFE_LOCAL_PROXY_HEADER = "x-vercel-mfe-local-proxy-origin";
1815
1986
  var MFE_FLAG_VALUE = "vercel-mfe-flag-value";
@@ -2133,15 +2304,35 @@ var LocalProxy = class {
2133
2304
  const { req: strippedReq, mfeFlagValue } = removeMfeFlagQuery(req);
2134
2305
  if (target.protocol === "https") {
2135
2306
  const { hostname, port, path: path7 } = target;
2307
+ const app = this.router.config.getApplication(target.application);
2308
+ const automationBypass = process.env[app.getAutomationBypassEnvVarName()];
2136
2309
  const requestOptions = {
2137
2310
  hostname,
2138
2311
  path: path7,
2139
2312
  method: req.method,
2140
- headers: { ...req.headers, host: hostname },
2313
+ headers: {
2314
+ ...req.headers,
2315
+ host: hostname,
2316
+ ...automationBypass ? { "x-vercel-protection-bypass": automationBypass } : {}
2317
+ },
2141
2318
  port
2142
2319
  };
2143
2320
  const localhost = `http://localhost:${this.proxyPort}`;
2144
2321
  const proxyReq = https.request(requestOptions, (realRes) => {
2322
+ if (realRes.statusCode === 401 && realRes.headers["set-cookie"]?.find(
2323
+ (cookie) => cookie.startsWith("_vercel_sso_nonce=")
2324
+ )) {
2325
+ const defaultApp = this.router.config.getDefaultApplication();
2326
+ return res.end(
2327
+ localAuthHtml({
2328
+ app: target.application,
2329
+ hostname,
2330
+ defaultApp: defaultApp.packageName || defaultApp.name,
2331
+ automationBypassEnvVarName: app.getAutomationBypassEnvVarName(),
2332
+ automationBypass
2333
+ })
2334
+ );
2335
+ }
2145
2336
  if (realRes.statusCode === 307) {
2146
2337
  const locationHeader = realRes.headers.location;
2147
2338
  if (locationHeader) {
@@ -2291,17 +2482,27 @@ function header({ name, version, port }) {
2291
2482
 
2292
2483
  // src/bin/index.ts
2293
2484
  function main() {
2485
+ (0, import_env.loadEnvConfig)(process.cwd());
2294
2486
  const program = new import_commander.Command();
2295
2487
  program.name(package_default.name).description("Tools for working with micro-frontend applications").version(package_default.version, "-v, --version", "output the current version");
2296
- program.command("proxy").argument("[filePath]", "Path to the micro-frontend configuration file").option("--names, --local-apps <names...>", "List of locally running applications", []).option("--port <port>", "Port proxy will use", (value) => {
2488
+ program.command("proxy").argument("[filePath]", "Path to the micro-frontend configuration file").option(
2489
+ "--local-apps <names...>",
2490
+ "List of locally running applications",
2491
+ []
2492
+ ).addOption(new import_commander.Option("--names <names...>").hideHelp()).option("--port <port>", "Port proxy will use", (value) => {
2297
2493
  const parsedValue = Number.parseInt(value, 10);
2298
2494
  if (isNaN(parsedValue) || parsedValue <= 0) {
2299
2495
  throw new Error("Port must be a positive number");
2300
2496
  }
2301
2497
  return parsedValue;
2302
2498
  }).action((filePath, options) => {
2499
+ if (options.names && options.localApps.length) {
2500
+ throw new Error(
2501
+ "Both --names and --local-apps are set. --names is deprecated and has been replaced with --local-apps, which functions exactly the same. Please only set --local-apps."
2502
+ );
2503
+ }
2303
2504
  const localProxy = LocalProxy.fromFile(filePath, {
2304
- localApps: options.localApps,
2505
+ localApps: options.names ?? options.localApps,
2305
2506
  proxyPort: options.port
2306
2507
  });
2307
2508
  localProxy.startServer();