@vercel/microfrontends 2.0.0-canary.1 → 2.0.0

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 (45) hide show
  1. package/CHANGELOG.md +11 -9
  2. package/README.md +21 -4
  3. package/dist/bin/cli.cjs +142 -13
  4. package/dist/config.cjs +123 -3
  5. package/dist/config.cjs.map +1 -1
  6. package/dist/config.d.ts +33 -2
  7. package/dist/config.js +122 -2
  8. package/dist/config.js.map +1 -1
  9. package/dist/experimental/sveltekit.cjs +128 -4
  10. package/dist/experimental/sveltekit.cjs.map +1 -1
  11. package/dist/experimental/sveltekit.js +127 -3
  12. package/dist/experimental/sveltekit.js.map +1 -1
  13. package/dist/experimental/vite.cjs +128 -4
  14. package/dist/experimental/vite.cjs.map +1 -1
  15. package/dist/experimental/vite.js +127 -3
  16. package/dist/experimental/vite.js.map +1 -1
  17. package/dist/microfrontends/server.cjs +128 -4
  18. package/dist/microfrontends/server.cjs.map +1 -1
  19. package/dist/microfrontends/server.d.ts +4 -3
  20. package/dist/microfrontends/server.js +127 -3
  21. package/dist/microfrontends/server.js.map +1 -1
  22. package/dist/next/config.cjs +131 -131
  23. package/dist/next/config.cjs.map +1 -1
  24. package/dist/next/config.d.ts +5 -0
  25. package/dist/next/config.js +130 -130
  26. package/dist/next/config.js.map +1 -1
  27. package/dist/next/middleware.cjs +125 -105
  28. package/dist/next/middleware.cjs.map +1 -1
  29. package/dist/next/middleware.js +125 -105
  30. package/dist/next/middleware.js.map +1 -1
  31. package/dist/next/testing.cjs +126 -6
  32. package/dist/next/testing.cjs.map +1 -1
  33. package/dist/next/testing.d.ts +2 -2
  34. package/dist/next/testing.js +124 -4
  35. package/dist/next/testing.js.map +1 -1
  36. package/dist/overrides.d.ts +3 -3
  37. package/dist/schema.d.ts +2 -2
  38. package/dist/{types-4299bff1.d.ts → types-88602303.d.ts} +1 -1
  39. package/dist/{types-0deb756b.d.ts → types-e7523e61.d.ts} +1 -1
  40. package/dist/utils/mfe-port.cjs +128 -4
  41. package/dist/utils/mfe-port.cjs.map +1 -1
  42. package/dist/utils/mfe-port.js +127 -3
  43. package/dist/utils/mfe-port.js.map +1 -1
  44. package/dist/validation.d.ts +1 -1
  45. package/package.json +7 -2
@@ -360,8 +360,106 @@ function findConfig({ dir }) {
360
360
  // src/config/microfrontends-config/isomorphic/index.ts
361
361
  import { parse as parse2 } from "jsonc-parser";
362
362
 
363
+ // src/config/microfrontends-config/client/index.ts
364
+ import { pathToRegexp } from "path-to-regexp";
365
+ var regexpCache = /* @__PURE__ */ new Map();
366
+ var getRegexp = (path6) => {
367
+ const existing = regexpCache.get(path6);
368
+ if (existing) {
369
+ return existing;
370
+ }
371
+ const regexp = pathToRegexp(path6);
372
+ regexpCache.set(path6, regexp);
373
+ return regexp;
374
+ };
375
+ var MicrofrontendConfigClient = class {
376
+ constructor(config, opts) {
377
+ this.pathCache = {};
378
+ this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;
379
+ for (const app of Object.values(config.applications)) {
380
+ if (app.routing) {
381
+ if (app.routing.some((match) => match.flag)) {
382
+ this.hasFlaggedPaths = true;
383
+ }
384
+ const newRouting = [];
385
+ const pathsWithoutFlags = [];
386
+ for (const group of app.routing) {
387
+ if (group.flag) {
388
+ if (opts?.removeFlaggedPaths) {
389
+ continue;
390
+ }
391
+ if (group.group) {
392
+ delete group.group;
393
+ }
394
+ newRouting.push(group);
395
+ } else {
396
+ pathsWithoutFlags.push(...group.paths);
397
+ }
398
+ }
399
+ if (pathsWithoutFlags.length > 0) {
400
+ newRouting.push({ paths: pathsWithoutFlags });
401
+ }
402
+ app.routing = newRouting;
403
+ }
404
+ }
405
+ this.serialized = config;
406
+ if (this.hasFlaggedPaths) {
407
+ this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;
408
+ }
409
+ this.applications = config.applications;
410
+ }
411
+ /**
412
+ * Create a new `MicrofrontendConfigClient` from a JSON string.
413
+ * Config must be passed in to remain framework agnostic
414
+ */
415
+ static fromEnv(config) {
416
+ if (!config) {
417
+ throw new Error(
418
+ "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
419
+ );
420
+ }
421
+ return new MicrofrontendConfigClient(JSON.parse(config));
422
+ }
423
+ isEqual(other) {
424
+ return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
425
+ }
426
+ getApplicationNameForPath(path6) {
427
+ if (!path6.startsWith("/")) {
428
+ throw new Error(`Path must start with a /`);
429
+ }
430
+ if (this.pathCache[path6]) {
431
+ return this.pathCache[path6];
432
+ }
433
+ const pathname = new URL(path6, "https://example.com").pathname;
434
+ for (const [name, application] of Object.entries(this.applications)) {
435
+ if (application.routing) {
436
+ for (const group of application.routing) {
437
+ for (const childPath of group.paths) {
438
+ const regexp = getRegexp(childPath);
439
+ if (regexp.test(pathname)) {
440
+ this.pathCache[path6] = name;
441
+ return name;
442
+ }
443
+ }
444
+ }
445
+ }
446
+ }
447
+ const defaultApplication = Object.entries(this.applications).find(
448
+ ([, application]) => application.default
449
+ );
450
+ if (!defaultApplication) {
451
+ return null;
452
+ }
453
+ this.pathCache[path6] = defaultApplication[0];
454
+ return defaultApplication[0];
455
+ }
456
+ serialize() {
457
+ return this.serialized;
458
+ }
459
+ };
460
+
363
461
  // src/config/microfrontends-config/isomorphic/validation.ts
364
- import { pathToRegexp, parse as parsePathRegexp } from "path-to-regexp";
462
+ import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
365
463
  var LIST_FORMATTER = new Intl.ListFormat("en", {
366
464
  style: "long",
367
465
  type: "conjunction"
@@ -389,7 +487,7 @@ var validateConfigPaths = (applicationConfigsById) => {
389
487
  } else {
390
488
  pathsByApplicationId.set(path6, {
391
489
  applications: [id],
392
- matcher: pathToRegexp(path6),
490
+ matcher: pathToRegexp2(path6),
393
491
  applicationId: id
394
492
  });
395
493
  }
@@ -894,6 +992,28 @@ var MicrofrontendConfigIsomorphic = class {
894
992
  getLocalProxyPort() {
895
993
  return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
896
994
  }
995
+ toClientConfig(options) {
996
+ const applications = Object.fromEntries(
997
+ Object.entries(this.childApplications).map(([name, application]) => [
998
+ hashApplicationName(name),
999
+ {
1000
+ default: false,
1001
+ routing: application.routing
1002
+ }
1003
+ ])
1004
+ );
1005
+ applications[hashApplicationName(this.defaultApplication.name)] = {
1006
+ default: true
1007
+ };
1008
+ return new MicrofrontendConfigClient(
1009
+ {
1010
+ applications
1011
+ },
1012
+ {
1013
+ removeFlaggedPaths: options?.removeFlaggedPaths
1014
+ }
1015
+ );
1016
+ }
897
1017
  /**
898
1018
  * Serializes the class back to the Schema type.
899
1019
  *
@@ -1313,6 +1433,7 @@ var MicrofrontendsServer = class {
1313
1433
  * This can return either a Child or Main configuration.
1314
1434
  */
1315
1435
  static infer({
1436
+ appName,
1316
1437
  directory,
1317
1438
  filePath,
1318
1439
  cookies
@@ -1325,7 +1446,10 @@ var MicrofrontendsServer = class {
1325
1446
  }
1326
1447
  try {
1327
1448
  const packageRoot = findPackageRoot(directory);
1328
- const applicationContext = getApplicationContext({ packageRoot });
1449
+ const applicationContext = getApplicationContext({
1450
+ appName,
1451
+ packageRoot
1452
+ });
1329
1453
  const maybeConfig = findConfig({ dir: packageRoot });
1330
1454
  if (maybeConfig) {
1331
1455
  return MicrofrontendsServer.fromFile({