@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
@@ -355,8 +355,106 @@ function findConfig({ dir }) {
355
355
  // src/config/microfrontends-config/isomorphic/index.ts
356
356
  import { parse as parse2 } from "jsonc-parser";
357
357
 
358
+ // src/config/microfrontends-config/client/index.ts
359
+ import { pathToRegexp } from "path-to-regexp";
360
+ var regexpCache = /* @__PURE__ */ new Map();
361
+ var getRegexp = (path7) => {
362
+ const existing = regexpCache.get(path7);
363
+ if (existing) {
364
+ return existing;
365
+ }
366
+ const regexp = pathToRegexp(path7);
367
+ regexpCache.set(path7, regexp);
368
+ return regexp;
369
+ };
370
+ var MicrofrontendConfigClient = class {
371
+ constructor(config, opts) {
372
+ this.pathCache = {};
373
+ this.hasFlaggedPaths = config.hasFlaggedPaths ?? false;
374
+ for (const app of Object.values(config.applications)) {
375
+ if (app.routing) {
376
+ if (app.routing.some((match) => match.flag)) {
377
+ this.hasFlaggedPaths = true;
378
+ }
379
+ const newRouting = [];
380
+ const pathsWithoutFlags = [];
381
+ for (const group of app.routing) {
382
+ if (group.flag) {
383
+ if (opts?.removeFlaggedPaths) {
384
+ continue;
385
+ }
386
+ if (group.group) {
387
+ delete group.group;
388
+ }
389
+ newRouting.push(group);
390
+ } else {
391
+ pathsWithoutFlags.push(...group.paths);
392
+ }
393
+ }
394
+ if (pathsWithoutFlags.length > 0) {
395
+ newRouting.push({ paths: pathsWithoutFlags });
396
+ }
397
+ app.routing = newRouting;
398
+ }
399
+ }
400
+ this.serialized = config;
401
+ if (this.hasFlaggedPaths) {
402
+ this.serialized.hasFlaggedPaths = this.hasFlaggedPaths;
403
+ }
404
+ this.applications = config.applications;
405
+ }
406
+ /**
407
+ * Create a new `MicrofrontendConfigClient` from a JSON string.
408
+ * Config must be passed in to remain framework agnostic
409
+ */
410
+ static fromEnv(config) {
411
+ if (!config) {
412
+ throw new Error(
413
+ "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
414
+ );
415
+ }
416
+ return new MicrofrontendConfigClient(JSON.parse(config));
417
+ }
418
+ isEqual(other) {
419
+ return this === other || JSON.stringify(this.applications) === JSON.stringify(other.applications);
420
+ }
421
+ getApplicationNameForPath(path7) {
422
+ if (!path7.startsWith("/")) {
423
+ throw new Error(`Path must start with a /`);
424
+ }
425
+ if (this.pathCache[path7]) {
426
+ return this.pathCache[path7];
427
+ }
428
+ const pathname = new URL(path7, "https://example.com").pathname;
429
+ for (const [name, application] of Object.entries(this.applications)) {
430
+ if (application.routing) {
431
+ for (const group of application.routing) {
432
+ for (const childPath of group.paths) {
433
+ const regexp = getRegexp(childPath);
434
+ if (regexp.test(pathname)) {
435
+ this.pathCache[path7] = name;
436
+ return name;
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+ const defaultApplication = Object.entries(this.applications).find(
443
+ ([, application]) => application.default
444
+ );
445
+ if (!defaultApplication) {
446
+ return null;
447
+ }
448
+ this.pathCache[path7] = defaultApplication[0];
449
+ return defaultApplication[0];
450
+ }
451
+ serialize() {
452
+ return this.serialized;
453
+ }
454
+ };
455
+
358
456
  // src/config/microfrontends-config/isomorphic/validation.ts
359
- import { pathToRegexp, parse as parsePathRegexp } from "path-to-regexp";
457
+ import { pathToRegexp as pathToRegexp2, parse as parsePathRegexp } from "path-to-regexp";
360
458
  var LIST_FORMATTER = new Intl.ListFormat("en", {
361
459
  style: "long",
362
460
  type: "conjunction"
@@ -384,7 +482,7 @@ var validateConfigPaths = (applicationConfigsById) => {
384
482
  } else {
385
483
  pathsByApplicationId.set(path7, {
386
484
  applications: [id],
387
- matcher: pathToRegexp(path7),
485
+ matcher: pathToRegexp2(path7),
388
486
  applicationId: id
389
487
  });
390
488
  }
@@ -889,6 +987,28 @@ var MicrofrontendConfigIsomorphic = class {
889
987
  getLocalProxyPort() {
890
988
  return this.config.options?.localProxyPort ?? DEFAULT_LOCAL_PROXY_PORT;
891
989
  }
990
+ toClientConfig(options) {
991
+ const applications = Object.fromEntries(
992
+ Object.entries(this.childApplications).map(([name, application]) => [
993
+ hashApplicationName(name),
994
+ {
995
+ default: false,
996
+ routing: application.routing
997
+ }
998
+ ])
999
+ );
1000
+ applications[hashApplicationName(this.defaultApplication.name)] = {
1001
+ default: true
1002
+ };
1003
+ return new MicrofrontendConfigClient(
1004
+ {
1005
+ applications
1006
+ },
1007
+ {
1008
+ removeFlaggedPaths: options?.removeFlaggedPaths
1009
+ }
1010
+ );
1011
+ }
892
1012
  /**
893
1013
  * Serializes the class back to the Schema type.
894
1014
  *
@@ -1308,6 +1428,7 @@ var MicrofrontendsServer = class {
1308
1428
  * This can return either a Child or Main configuration.
1309
1429
  */
1310
1430
  static infer({
1431
+ appName,
1311
1432
  directory,
1312
1433
  filePath,
1313
1434
  cookies
@@ -1320,7 +1441,10 @@ var MicrofrontendsServer = class {
1320
1441
  }
1321
1442
  try {
1322
1443
  const packageRoot = findPackageRoot(directory);
1323
- const applicationContext = getApplicationContext({ packageRoot });
1444
+ const applicationContext = getApplicationContext({
1445
+ appName,
1446
+ packageRoot
1447
+ });
1324
1448
  const maybeConfig = findConfig({ dir: packageRoot });
1325
1449
  if (maybeConfig) {
1326
1450
  return MicrofrontendsServer.fromFile({