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