@vercel/microfrontends 2.2.1 → 2.2.2

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 (59) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/cli/index.cjs +0 -1
  3. package/dist/bin/cli.cjs +483 -394
  4. package/dist/config.cjs +191 -169
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.d.ts +3 -2
  7. package/dist/config.js +192 -170
  8. package/dist/config.js.map +1 -1
  9. package/dist/experimental/sveltekit.cjs +583 -511
  10. package/dist/experimental/sveltekit.cjs.map +1 -1
  11. package/dist/experimental/sveltekit.js +589 -517
  12. package/dist/experimental/sveltekit.js.map +1 -1
  13. package/dist/experimental/vite.cjs +605 -533
  14. package/dist/experimental/vite.cjs.map +1 -1
  15. package/dist/experimental/vite.js +614 -542
  16. package/dist/experimental/vite.js.map +1 -1
  17. package/dist/microfrontends/server.cjs +601 -529
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +2 -2
  20. package/dist/microfrontends/server.js +607 -535
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/microfrontends/utils.cjs +101 -50
  23. package/dist/microfrontends/utils.cjs.map +1 -1
  24. package/dist/microfrontends/utils.d.ts +4 -4
  25. package/dist/microfrontends/utils.js +102 -51
  26. package/dist/microfrontends/utils.js.map +1 -1
  27. package/dist/next/client.cjs +1 -1
  28. package/dist/next/client.cjs.map +1 -1
  29. package/dist/next/client.d.ts +8 -8
  30. package/dist/next/client.js +1 -1
  31. package/dist/next/client.js.map +1 -1
  32. package/dist/next/config.cjs +723 -647
  33. package/dist/next/config.cjs.map +1 -1
  34. package/dist/next/config.js +720 -644
  35. package/dist/next/config.js.map +1 -1
  36. package/dist/next/middleware.cjs +244 -222
  37. package/dist/next/middleware.cjs.map +1 -1
  38. package/dist/next/middleware.js +245 -223
  39. package/dist/next/middleware.js.map +1 -1
  40. package/dist/next/testing.cjs +192 -170
  41. package/dist/next/testing.cjs.map +1 -1
  42. package/dist/next/testing.d.ts +1 -1
  43. package/dist/next/testing.js +193 -171
  44. package/dist/next/testing.js.map +1 -1
  45. package/dist/overrides.cjs +5 -5
  46. package/dist/overrides.cjs.map +1 -1
  47. package/dist/overrides.d.ts +9 -9
  48. package/dist/overrides.js +5 -5
  49. package/dist/overrides.js.map +1 -1
  50. package/dist/utils/mfe-port.cjs +620 -533
  51. package/dist/utils/mfe-port.cjs.map +1 -1
  52. package/dist/utils/mfe-port.d.ts +9 -1
  53. package/dist/utils/mfe-port.js +632 -546
  54. package/dist/utils/mfe-port.js.map +1 -1
  55. package/dist/validation.cjs +8 -24
  56. package/dist/validation.cjs.map +1 -1
  57. package/dist/validation.js +8 -24
  58. package/dist/validation.js.map +1 -1
  59. package/package.json +4 -6
@@ -2,45 +2,33 @@
2
2
  import { NextResponse } from "next/server";
3
3
  import { pathToRegexp as pathToRegexp3 } from "path-to-regexp";
4
4
 
5
- // src/config/well-known/endpoints.ts
6
- async function getWellKnownClientData(config, flagValues = {}) {
7
- const clientConfig = config.toClientConfig();
8
- for (const [applicationName, application] of Object.entries(
9
- clientConfig.applications
10
- )) {
11
- if (!application.routing) {
12
- continue;
13
- }
14
- const allPaths = [];
15
- for (const pathGroup of application.routing) {
16
- if (pathGroup.flag) {
17
- const flagName = pathGroup.flag;
18
- const flagFn = flagValues[flagName];
19
- if (!flagFn) {
20
- throw new Error(
21
- `Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${applicationName} but not found in provided flag values.`
22
- );
23
- }
24
- const flagEnabled = await flagFn();
25
- if (flagEnabled) {
26
- allPaths.push(...pathGroup.paths);
27
- }
28
- } else {
29
- allPaths.push(...pathGroup.paths);
30
- }
31
- }
32
- application.routing = allPaths.length > 0 ? [{ paths: allPaths }] : [];
33
- }
34
- return {
35
- config: clientConfig.serialize()
36
- };
37
- }
38
-
39
5
  // src/bin/local-proxy-is-running.ts
40
6
  function localProxyIsRunning() {
41
7
  return process.env.TURBO_TASK_HAS_MFE_PROXY === "true";
42
8
  }
43
9
 
10
+ // src/bin/logger.ts
11
+ function debug(...args) {
12
+ if (process.env.MFE_DEBUG) {
13
+ console.log(...args);
14
+ }
15
+ }
16
+ function info(...args) {
17
+ console.log(...args);
18
+ }
19
+ function warn(...args) {
20
+ console.warn(...args);
21
+ }
22
+ function error(...args) {
23
+ console.error(...args);
24
+ }
25
+ var logger = {
26
+ debug,
27
+ info,
28
+ warn,
29
+ error
30
+ };
31
+
44
32
  // src/config/microfrontends-config/isomorphic/index.ts
45
33
  import { parse } from "jsonc-parser";
46
34
 
@@ -136,23 +124,6 @@ var MicrofrontendError = class extends Error {
136
124
  }
137
125
  };
138
126
 
139
- // src/config/microfrontends-config/utils/get-config-from-env.ts
140
- function getConfigStringFromEnv() {
141
- const config = process.env.MFE_CONFIG;
142
- if (!config) {
143
- throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
144
- type: "config",
145
- subtype: "not_found_in_env"
146
- });
147
- }
148
- return config;
149
- }
150
-
151
- // src/config/schema/utils/is-default-app.ts
152
- function isDefaultApp(a) {
153
- return !("routing" in a);
154
- }
155
-
156
127
  // src/config/overrides/constants.ts
157
128
  var OVERRIDES_COOKIE_PREFIX = "vercel-micro-frontends-override";
158
129
  var OVERRIDES_ENV_COOKIE_PREFIX = `${OVERRIDES_COOKIE_PREFIX}:env:`;
@@ -186,6 +157,11 @@ function parseOverrides(cookies) {
186
157
  return overridesConfig;
187
158
  }
188
159
 
160
+ // src/config/schema/utils/is-default-app.ts
161
+ function isDefaultApp(a) {
162
+ return !("routing" in a);
163
+ }
164
+
189
165
  // src/config/microfrontends-config/client/index.ts
190
166
  import { pathToRegexp } from "path-to-regexp";
191
167
  var regexpCache = /* @__PURE__ */ new Map();
@@ -284,8 +260,185 @@ var MicrofrontendConfigClient = class {
284
260
  }
285
261
  };
286
262
 
263
+ // src/config/microfrontends-config/utils/get-config-from-env.ts
264
+ function getConfigStringFromEnv() {
265
+ const config = process.env.MFE_CONFIG;
266
+ if (!config) {
267
+ throw new MicrofrontendError(`Missing "MFE_CONFIG" in environment.`, {
268
+ type: "config",
269
+ subtype: "not_found_in_env"
270
+ });
271
+ }
272
+ return config;
273
+ }
274
+
275
+ // src/config/microfrontends-config/isomorphic/constants.ts
276
+ var DEFAULT_LOCAL_PROXY_PORT = 3024;
277
+ var MFE_APP_PORT_ENV = "MFE_APP_PORT";
278
+ var MFE_LOCAL_PROXY_PORT_ENV = "MFE_LOCAL_PROXY_PORT";
279
+
280
+ // src/config/microfrontends-config/isomorphic/utils/generate-port.ts
281
+ function generatePortFromName({
282
+ name,
283
+ minPort = 3e3,
284
+ maxPort = 8e3
285
+ }) {
286
+ if (!name) {
287
+ throw new Error("Name is required to generate a port");
288
+ }
289
+ let hash = 0;
290
+ for (let i = 0; i < name.length; i++) {
291
+ hash = (hash << 5) - hash + name.charCodeAt(i);
292
+ hash |= 0;
293
+ }
294
+ hash = Math.abs(hash);
295
+ const range = maxPort - minPort;
296
+ const port = minPort + hash % range;
297
+ return port;
298
+ }
299
+
300
+ // src/config/microfrontends-config/isomorphic/host.ts
301
+ var Host = class {
302
+ constructor(hostConfig, options) {
303
+ if (typeof hostConfig === "string") {
304
+ ({
305
+ protocol: this.protocol,
306
+ host: this.host,
307
+ port: this.port
308
+ } = Host.parseUrl(hostConfig));
309
+ } else {
310
+ const { protocol = "https", host, port } = hostConfig;
311
+ this.protocol = protocol;
312
+ this.host = host;
313
+ this.port = port;
314
+ }
315
+ this.local = options?.isLocal;
316
+ }
317
+ static parseUrl(url, defaultProtocol = "https") {
318
+ let hostToParse = url;
319
+ if (!/^https?:\/\//.exec(hostToParse)) {
320
+ hostToParse = `${defaultProtocol}://${hostToParse}`;
321
+ }
322
+ const parsed = new URL(hostToParse);
323
+ if (!parsed.hostname) {
324
+ throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
325
+ }
326
+ if (parsed.hash) {
327
+ throw new Error(
328
+ Host.getMicrofrontendsError(url, "cannot have a fragment")
329
+ );
330
+ }
331
+ if (parsed.username || parsed.password) {
332
+ throw new Error(
333
+ Host.getMicrofrontendsError(
334
+ url,
335
+ "cannot have authentication credentials (username and/or password)"
336
+ )
337
+ );
338
+ }
339
+ if (parsed.pathname !== "/") {
340
+ throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
341
+ }
342
+ if (parsed.search) {
343
+ throw new Error(
344
+ Host.getMicrofrontendsError(url, "cannot have query parameters")
345
+ );
346
+ }
347
+ const protocol = parsed.protocol.slice(0, -1);
348
+ return {
349
+ protocol,
350
+ host: parsed.hostname,
351
+ port: parsed.port ? Number.parseInt(parsed.port, 10) : void 0
352
+ };
353
+ }
354
+ static getMicrofrontendsError(url, message) {
355
+ return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
356
+ }
357
+ isLocal() {
358
+ return this.local || this.host === "localhost" || this.host === "127.0.0.1";
359
+ }
360
+ toString() {
361
+ const url = this.toUrl();
362
+ return url.toString().replace(/\/$/, "");
363
+ }
364
+ toUrl() {
365
+ const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
366
+ return new URL(url);
367
+ }
368
+ };
369
+ var LocalHost = class extends Host {
370
+ constructor({
371
+ appName,
372
+ local
373
+ }) {
374
+ const portOverride = process.env[MFE_APP_PORT_ENV];
375
+ if (portOverride) {
376
+ const overridePort = Number.parseInt(portOverride, 10);
377
+ if (!Number.isNaN(overridePort) && overridePort > 0 && overridePort < 65536) {
378
+ super({
379
+ protocol: "http",
380
+ host: "localhost",
381
+ port: overridePort
382
+ });
383
+ return;
384
+ }
385
+ }
386
+ let protocol;
387
+ let host;
388
+ let port;
389
+ if (typeof local === "number") {
390
+ port = local;
391
+ } else if (typeof local === "string") {
392
+ if (/^\d+$/.test(local)) {
393
+ port = Number.parseInt(local, 10);
394
+ } else {
395
+ const parsed = Host.parseUrl(local, "http");
396
+ protocol = parsed.protocol;
397
+ host = parsed.host;
398
+ port = parsed.port;
399
+ }
400
+ } else if (local) {
401
+ protocol = local.protocol;
402
+ host = local.host;
403
+ port = local.port;
404
+ }
405
+ super({
406
+ protocol: protocol ?? "http",
407
+ host: host ?? "localhost",
408
+ port: port ?? generatePortFromName({ name: appName })
409
+ });
410
+ }
411
+ };
412
+
413
+ // src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
414
+ import md5 from "md5";
415
+ function hashApplicationName(name) {
416
+ if (!name) {
417
+ throw new Error("Application name is required to generate hash");
418
+ }
419
+ return md5(name).substring(0, 6).padStart(6, "0");
420
+ }
421
+
422
+ // src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
423
+ var PREFIX = "vc-ap";
424
+ function generateAssetPrefixFromName({
425
+ name
426
+ }) {
427
+ if (!name) {
428
+ throw new Error("Name is required to generate an asset prefix");
429
+ }
430
+ return `${PREFIX}-${hashApplicationName(name)}`;
431
+ }
432
+
433
+ // src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
434
+ function generateAutomationBypassEnvVarName({
435
+ name
436
+ }) {
437
+ return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
438
+ }
439
+
287
440
  // src/config/microfrontends-config/isomorphic/validation.ts
288
- import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
441
+ import { parse as parsePathRegexp, pathToRegexp as pathToRegexp2 } from "path-to-regexp";
289
442
  var LIST_FORMATTER = new Intl.ListFormat("en", {
290
443
  style: "long",
291
444
  type: "conjunction"
@@ -465,154 +618,6 @@ var validateConfigDefaultApplication = (applicationConfigsById) => {
465
618
  }
466
619
  };
467
620
 
468
- // src/config/microfrontends-config/isomorphic/utils/hash-application-name.ts
469
- import md5 from "md5";
470
- function hashApplicationName(name) {
471
- if (!name) {
472
- throw new Error("Application name is required to generate hash");
473
- }
474
- return md5(name).substring(0, 6).padStart(6, "0");
475
- }
476
-
477
- // src/config/microfrontends-config/isomorphic/utils/generate-asset-prefix.ts
478
- var PREFIX = "vc-ap";
479
- function generateAssetPrefixFromName({
480
- name
481
- }) {
482
- if (!name) {
483
- throw new Error("Name is required to generate an asset prefix");
484
- }
485
- return `${PREFIX}-${hashApplicationName(name)}`;
486
- }
487
-
488
- // src/config/microfrontends-config/isomorphic/utils/generate-port.ts
489
- function generatePortFromName({
490
- name,
491
- minPort = 3e3,
492
- maxPort = 8e3
493
- }) {
494
- if (!name) {
495
- throw new Error("Name is required to generate a port");
496
- }
497
- let hash = 0;
498
- for (let i = 0; i < name.length; i++) {
499
- hash = (hash << 5) - hash + name.charCodeAt(i);
500
- hash |= 0;
501
- }
502
- hash = Math.abs(hash);
503
- const range = maxPort - minPort;
504
- const port = minPort + hash % range;
505
- return port;
506
- }
507
-
508
- // src/config/microfrontends-config/isomorphic/host.ts
509
- var Host = class {
510
- constructor(hostConfig, options) {
511
- if (typeof hostConfig === "string") {
512
- ({
513
- protocol: this.protocol,
514
- host: this.host,
515
- port: this.port
516
- } = Host.parseUrl(hostConfig));
517
- } else {
518
- const { protocol = "https", host, port } = hostConfig;
519
- this.protocol = protocol;
520
- this.host = host;
521
- this.port = port;
522
- }
523
- this.local = options?.isLocal;
524
- }
525
- static parseUrl(url, defaultProtocol = "https") {
526
- let hostToParse = url;
527
- if (!/^https?:\/\//.exec(hostToParse)) {
528
- hostToParse = `${defaultProtocol}://${hostToParse}`;
529
- }
530
- const parsed = new URL(hostToParse);
531
- if (!parsed.hostname) {
532
- throw new Error(Host.getMicrofrontendsError(url, "requires a host"));
533
- }
534
- if (parsed.hash) {
535
- throw new Error(
536
- Host.getMicrofrontendsError(url, "cannot have a fragment")
537
- );
538
- }
539
- if (parsed.username || parsed.password) {
540
- throw new Error(
541
- Host.getMicrofrontendsError(
542
- url,
543
- "cannot have authentication credentials (username and/or password)"
544
- )
545
- );
546
- }
547
- if (parsed.pathname !== "/") {
548
- throw new Error(Host.getMicrofrontendsError(url, "cannot have a path"));
549
- }
550
- if (parsed.search) {
551
- throw new Error(
552
- Host.getMicrofrontendsError(url, "cannot have query parameters")
553
- );
554
- }
555
- const protocol = parsed.protocol.slice(0, -1);
556
- return {
557
- protocol,
558
- host: parsed.hostname,
559
- port: parsed.port ? Number.parseInt(parsed.port) : void 0
560
- };
561
- }
562
- static getMicrofrontendsError(url, message) {
563
- return `Microfrontends configuration error: the URL ${url} in your microfrontends.json ${message}.`;
564
- }
565
- isLocal() {
566
- return this.local || this.host === "localhost" || this.host === "127.0.0.1";
567
- }
568
- toString() {
569
- const url = this.toUrl();
570
- return url.toString().replace(/\/$/, "");
571
- }
572
- toUrl() {
573
- const url = `${this.protocol}://${this.host}${this.port ? `:${this.port}` : ""}`;
574
- return new URL(url);
575
- }
576
- };
577
- var LocalHost = class extends Host {
578
- constructor({
579
- appName,
580
- local
581
- }) {
582
- let protocol;
583
- let host;
584
- let port;
585
- if (typeof local === "number") {
586
- port = local;
587
- } else if (typeof local === "string") {
588
- if (/^\d+$/.test(local)) {
589
- port = Number.parseInt(local);
590
- } else {
591
- const parsed = Host.parseUrl(local, "http");
592
- protocol = parsed.protocol;
593
- host = parsed.host;
594
- port = parsed.port;
595
- }
596
- } else if (local) {
597
- protocol = local.protocol;
598
- host = local.host;
599
- port = local.port;
600
- }
601
- super({
602
- protocol: protocol ?? "http",
603
- host: host ?? "localhost",
604
- port: port ?? generatePortFromName({ name: appName })
605
- });
606
- }
607
- };
608
-
609
- // src/config/microfrontends-config/isomorphic/utils/generate-automation-bypass-env-var-name.ts
610
- function generateAutomationBypassEnvVarName({
611
- name
612
- }) {
613
- return `AUTOMATION_BYPASS_${name.toUpperCase().replace(/[^a-zA-Z0-9]/g, "_")}`;
614
- }
615
-
616
621
  // src/config/microfrontends-config/isomorphic/application.ts
617
622
  var Application = class {
618
623
  constructor(name, {
@@ -693,9 +698,6 @@ var ChildApplication = class extends Application {
693
698
  }
694
699
  };
695
700
 
696
- // src/config/microfrontends-config/isomorphic/constants.ts
697
- var DEFAULT_LOCAL_PROXY_PORT = 3024;
698
-
699
701
  // src/config/microfrontends-config/isomorphic/index.ts
700
702
  var MicrofrontendConfigIsomorphic = class {
701
703
  constructor({
@@ -814,9 +816,17 @@ var MicrofrontendConfigIsomorphic = class {
814
816
  return this.defaultApplication;
815
817
  }
816
818
  /**
817
- * Returns the configured port for the local proxy
819
+ * Returns the configured port for the local proxy.
820
+ * Can be overridden via MFE_LOCAL_PROXY_PORT environment variable.
818
821
  */
819
822
  getLocalProxyPort() {
823
+ const portOverride = process.env[MFE_LOCAL_PROXY_PORT_ENV];
824
+ if (portOverride) {
825
+ const port = Number.parseInt(portOverride, 10);
826
+ if (!Number.isNaN(port) && port > 0 && port < 65536) {
827
+ return port;
828
+ }
829
+ }
820
830
  return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
821
831
  }
822
832
  toClientConfig(options) {
@@ -854,27 +864,39 @@ var MicrofrontendConfigIsomorphic = class {
854
864
  }
855
865
  };
856
866
 
857
- // src/bin/logger.ts
858
- function debug(...args) {
859
- if (process.env.MFE_DEBUG) {
860
- console.log(...args);
867
+ // src/config/well-known/endpoints.ts
868
+ async function getWellKnownClientData(config, flagValues = {}) {
869
+ const clientConfig = config.toClientConfig();
870
+ for (const [applicationName, application] of Object.entries(
871
+ clientConfig.applications
872
+ )) {
873
+ if (!application.routing) {
874
+ continue;
875
+ }
876
+ const allPaths = [];
877
+ for (const pathGroup of application.routing) {
878
+ if (pathGroup.flag) {
879
+ const flagName = pathGroup.flag;
880
+ const flagFn = flagValues[flagName];
881
+ if (!flagFn) {
882
+ throw new Error(
883
+ `Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${applicationName} but not found in provided flag values.`
884
+ );
885
+ }
886
+ const flagEnabled = await flagFn();
887
+ if (flagEnabled) {
888
+ allPaths.push(...pathGroup.paths);
889
+ }
890
+ } else {
891
+ allPaths.push(...pathGroup.paths);
892
+ }
893
+ }
894
+ application.routing = allPaths.length > 0 ? [{ paths: allPaths }] : [];
861
895
  }
896
+ return {
897
+ config: clientConfig.serialize()
898
+ };
862
899
  }
863
- function info(...args) {
864
- console.log(...args);
865
- }
866
- function warn(...args) {
867
- console.warn(...args);
868
- }
869
- function error(...args) {
870
- console.error(...args);
871
- }
872
- var logger = {
873
- debug,
874
- info,
875
- warn,
876
- error
877
- };
878
900
 
879
901
  // src/next/middleware/middleware.ts
880
902
  function getMfeFlagHeader(req) {