@vercel/microfrontends 1.2.4 → 1.4.0-canary.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 (41) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +5 -1
  3. package/dist/bin/cli.cjs +8 -12
  4. package/dist/config.d.ts +10 -3
  5. package/dist/experimental/sveltekit.cjs.map +1 -1
  6. package/dist/experimental/sveltekit.js.map +1 -1
  7. package/dist/experimental/vite.cjs.map +1 -1
  8. package/dist/experimental/vite.js.map +1 -1
  9. package/dist/microfrontends/server.cjs +4 -2
  10. package/dist/microfrontends/server.cjs.map +1 -1
  11. package/dist/microfrontends/server.d.ts +13 -4
  12. package/dist/microfrontends/server.js +2 -1
  13. package/dist/microfrontends/server.js.map +1 -1
  14. package/dist/next/config.cjs +59 -30
  15. package/dist/next/config.cjs.map +1 -1
  16. package/dist/next/config.js +66 -30
  17. package/dist/next/config.js.map +1 -1
  18. package/dist/next/middleware.cjs +117 -69
  19. package/dist/next/middleware.cjs.map +1 -1
  20. package/dist/next/middleware.d.ts +4 -2
  21. package/dist/next/middleware.js +117 -69
  22. package/dist/next/middleware.js.map +1 -1
  23. package/dist/next/testing.cjs +6 -0
  24. package/dist/next/testing.cjs.map +1 -1
  25. package/dist/next/testing.d.ts +2 -3
  26. package/dist/next/testing.js +6 -0
  27. package/dist/next/testing.js.map +1 -1
  28. package/dist/overrides.d.ts +3 -3
  29. package/dist/schema.d.ts +2 -2
  30. package/dist/{types-c9f15465.d.ts → types-ab31c948.d.ts} +1 -1
  31. package/dist/{types-bee19651.d.ts → types-d3cb74a6.d.ts} +1 -1
  32. package/dist/utils/mfe-port.cjs.map +1 -1
  33. package/dist/utils/mfe-port.js.map +1 -1
  34. package/dist/validation.d.ts +1 -1
  35. package/package.json +8 -12
  36. package/dist/next/endpoints.cjs +0 -154
  37. package/dist/next/endpoints.cjs.map +0 -1
  38. package/dist/next/endpoints.d.ts +0 -68
  39. package/dist/next/endpoints.js +0 -127
  40. package/dist/next/endpoints.js.map +0 -1
  41. package/dist/types-b970b583.d.ts +0 -11
@@ -1,154 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/next/endpoints/index.ts
21
- var endpoints_exports = {};
22
- __export(endpoints_exports, {
23
- getWellKnownClientData: () => getWellKnownClientData,
24
- handleClientConfigForPagesRouter: () => handleClientConfigForPagesRouter,
25
- wellKnownNextjsClientConfigAppRoute: () => wellKnownNextjsClientConfigAppRoute
26
- });
27
- module.exports = __toCommonJS(endpoints_exports);
28
- var import_server = require("next/server");
29
-
30
- // src/config/microfrontends-config/client/index.ts
31
- var import_path_to_regexp = require("path-to-regexp");
32
- var MicrofrontendConfigClient = class {
33
- constructor(config, opts) {
34
- this.pathCache = {};
35
- this.serialized = config;
36
- if (opts?.removeFlaggedPaths) {
37
- for (const app of Object.values(config.applications)) {
38
- if (app.routing) {
39
- app.routing = app.routing.filter((match) => !match.flag);
40
- }
41
- }
42
- }
43
- this.applications = config.applications;
44
- }
45
- /**
46
- * Create a new `MicrofrontendConfigClient` from a JSON string.
47
- * Config must be passed in to remain framework agnostic
48
- */
49
- static fromEnv(config, opts) {
50
- if (!config) {
51
- throw new Error(
52
- "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
53
- );
54
- }
55
- return new MicrofrontendConfigClient(
56
- JSON.parse(config),
57
- opts
58
- );
59
- }
60
- isEqual(other) {
61
- return JSON.stringify(this.applications) === JSON.stringify(other.applications);
62
- }
63
- getApplicationNameForPath(path) {
64
- if (!path.startsWith("/")) {
65
- throw new Error(`Path must start with a /`);
66
- }
67
- if (this.pathCache[path]) {
68
- return this.pathCache[path];
69
- }
70
- const pathname = new URL(path, "https://example.com").pathname;
71
- for (const [name, application] of Object.entries(this.applications)) {
72
- if (application.routing) {
73
- for (const group of application.routing) {
74
- for (const childPath of group.paths) {
75
- const regexp = (0, import_path_to_regexp.pathToRegexp)(childPath);
76
- if (regexp.test(pathname)) {
77
- this.pathCache[path] = name;
78
- return name;
79
- }
80
- }
81
- }
82
- }
83
- }
84
- const defaultApplication = Object.entries(this.applications).find(
85
- ([, application]) => application.default
86
- );
87
- if (!defaultApplication) {
88
- return null;
89
- }
90
- this.pathCache[path] = defaultApplication[0];
91
- return defaultApplication[0];
92
- }
93
- serialize() {
94
- return this.serialized;
95
- }
96
- };
97
-
98
- // src/config/well-known/endpoints.ts
99
- async function getWellKnownClientData(clientConfig, flagValues = {}) {
100
- const config = MicrofrontendConfigClient.fromEnv(clientConfig);
101
- for (const [applicationName, application] of Object.entries(
102
- config.applications
103
- )) {
104
- if (!application.routing) {
105
- continue;
106
- }
107
- const newRoutingMatches = [];
108
- for (const pathGroup of application.routing) {
109
- if (pathGroup.flag) {
110
- const flagName = pathGroup.flag;
111
- const flagFn = flagValues[flagName];
112
- if (!flagFn) {
113
- throw new Error(
114
- `Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${applicationName} but not found in provided flag values.`
115
- );
116
- }
117
- const flagEnabled = await flagFn();
118
- if (flagEnabled) {
119
- newRoutingMatches.push(pathGroup);
120
- }
121
- } else {
122
- newRoutingMatches.push(pathGroup);
123
- }
124
- }
125
- application.routing = newRoutingMatches;
126
- }
127
- return {
128
- config: config.serialize()
129
- };
130
- }
131
-
132
- // src/next/endpoints/index.ts
133
- async function wellKnownNextjsClientConfigAppRoute(flagValues) {
134
- return import_server.NextResponse.json(
135
- await getWellKnownClientData(
136
- process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,
137
- flagValues
138
- )
139
- );
140
- }
141
- async function handleClientConfigForPagesRouter(res, flagValues) {
142
- const clientData = await getWellKnownClientData(
143
- process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,
144
- flagValues
145
- );
146
- res.status(200).json(clientData);
147
- }
148
- // Annotate the CommonJS export names for ESM import in node:
149
- 0 && (module.exports = {
150
- getWellKnownClientData,
151
- handleClientConfigForPagesRouter,
152
- wellKnownNextjsClientConfigAppRoute
153
- });
154
- //# sourceMappingURL=endpoints.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\n }\n this.applications = config.applications;\n }\n\n /**\n * Create a new `MicrofrontendConfigClient` from a JSON string.\n * Config must be passed in to remain framework agnostic\n */\n static fromEnv(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): MicrofrontendConfigClient {\n if (!config) {\n throw new Error(\n 'Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?',\n );\n }\n return new MicrofrontendConfigClient(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\n JSON.stringify(this.applications) === JSON.stringify(other.applications)\n );\n }\n\n getApplicationNameForPath(path: string): string | null {\n if (!path.startsWith('/')) {\n throw new Error(`Path must start with a /`);\n }\n\n if (this.pathCache[path]) {\n return this.pathCache[path];\n }\n\n const pathname = new URL(path, 'https://example.com').pathname;\n for (const [name, application] of Object.entries(this.applications)) {\n if (application.routing) {\n for (const group of application.routing) {\n for (const childPath of group.paths) {\n const regexp = pathToRegexp(childPath);\n if (regexp.test(pathname)) {\n this.pathCache[path] = name;\n return name;\n }\n }\n }\n }\n }\n const defaultApplication = Object.entries(this.applications).find(\n ([, application]) => application.default,\n );\n if (!defaultApplication) {\n return null;\n }\n\n this.pathCache[path] = defaultApplication[0];\n return defaultApplication[0];\n }\n\n serialize(): ClientConfig {\n return this.serialized;\n }\n}\n","import { MicrofrontendConfigClient } from '../microfrontends-config/client';\nimport type { WellKnownClientData } from './types';\n\n/**\n * Returns data used by the client to ensure that navigations across\n * microfrontend boundaries are routed and prefetched correctly. The client\n * configuration is safe to expose to users.\n *\n * This data should be exposed in a `.well-known/vercel/microfrontends/client-config`\n * endpoint.\n */\nexport async function getWellKnownClientData(\n clientConfig: string | undefined,\n flagValues: Record<string, () => Promise<boolean>> = {},\n): Promise<WellKnownClientData> {\n const config = MicrofrontendConfigClient.fromEnv(clientConfig);\n for (const [applicationName, application] of Object.entries(\n config.applications,\n )) {\n if (!application.routing) {\n continue;\n }\n const newRoutingMatches = [];\n for (const pathGroup of application.routing) {\n if (pathGroup.flag) {\n const flagName = pathGroup.flag;\n const flagFn = flagValues[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${applicationName} but not found in provided flag values.`,\n );\n }\n // eslint-disable-next-line no-await-in-loop\n const flagEnabled = await flagFn();\n if (flagEnabled) {\n newRoutingMatches.push(pathGroup);\n }\n } else {\n newRoutingMatches.push(pathGroup);\n }\n }\n application.routing = newRoutingMatches;\n }\n\n return {\n config: config.serialize(),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,68 +0,0 @@
1
- import { NextApiResponse } from 'next';
2
- import { NextResponse } from 'next/server';
3
- import { C as ClientConfig } from '../types-b970b583.js';
4
- import '../types-c9f15465.js';
5
-
6
- /**
7
- * Data that is returned from the `.well-known/vercel/microfrontends/client-config`
8
- * endpoint that is used by the client to ensure that navigations and prefetches
9
- * are routed correctly.
10
- */
11
- interface WellKnownClientData {
12
- config: ClientConfig;
13
- }
14
-
15
- /**
16
- * Returns data used by the client to ensure that navigations across
17
- * microfrontend boundaries are routed and prefetched correctly. The client
18
- * configuration is safe to expose to users.
19
- *
20
- * This data should be exposed in a `.well-known/vercel/microfrontends/client-config`
21
- * endpoint.
22
- */
23
- declare function getWellKnownClientData(clientConfig: string | undefined, flagValues?: Record<string, () => Promise<boolean>>): Promise<WellKnownClientData>;
24
-
25
- /**
26
- * A Next.js App Router API handler to export the microfrontends client config
27
- * data.
28
- *
29
- * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,
30
- * add this code:
31
- * ```
32
- * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';
33
- * ```
34
- */
35
- declare function wellKnownNextjsClientConfigAppRoute(flagValues: Record<string, () => Promise<boolean>>): Promise<NextResponse>;
36
- /**
37
- * A Next.js Pages Router API to export the microfrontends client config data to the client.
38
- *
39
- * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,
40
- * add this code:
41
- * ```
42
- * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';
43
- * import type { NextApiResponse } from 'next';
44
- *
45
- * async function handler(
46
- * _,
47
- * res: NextApiResponse,
48
- * ): Promise<void> {
49
- * await handleClientConfigForPagesRouter(res, {
50
- * flagValue: () => Promise.resolve(true)
51
- * });
52
- * }
53
- * ```
54
- *
55
- * Then also make sure to add the following rewrite rule to your `next.config.js` file:
56
- * ```
57
- * rewrites: () =>
58
- * Promise.resolve([
59
- * {
60
- * source: '/.well-known/vercel/microfrontends/client-config',
61
- * destination: '/api/.well-known/vercel/microfrontends/client-config',
62
- * },
63
- * ]),
64
- * ```
65
- */
66
- declare function handleClientConfigForPagesRouter(res: NextApiResponse, flagValues: Record<string, () => Promise<boolean>>): Promise<void>;
67
-
68
- export { WellKnownClientData, getWellKnownClientData, handleClientConfigForPagesRouter, wellKnownNextjsClientConfigAppRoute };
@@ -1,127 +0,0 @@
1
- // src/next/endpoints/index.ts
2
- import { NextResponse } from "next/server";
3
-
4
- // src/config/microfrontends-config/client/index.ts
5
- import { pathToRegexp } from "path-to-regexp";
6
- var MicrofrontendConfigClient = class {
7
- constructor(config, opts) {
8
- this.pathCache = {};
9
- this.serialized = config;
10
- if (opts?.removeFlaggedPaths) {
11
- for (const app of Object.values(config.applications)) {
12
- if (app.routing) {
13
- app.routing = app.routing.filter((match) => !match.flag);
14
- }
15
- }
16
- }
17
- this.applications = config.applications;
18
- }
19
- /**
20
- * Create a new `MicrofrontendConfigClient` from a JSON string.
21
- * Config must be passed in to remain framework agnostic
22
- */
23
- static fromEnv(config, opts) {
24
- if (!config) {
25
- throw new Error(
26
- "Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?"
27
- );
28
- }
29
- return new MicrofrontendConfigClient(
30
- JSON.parse(config),
31
- opts
32
- );
33
- }
34
- isEqual(other) {
35
- return JSON.stringify(this.applications) === JSON.stringify(other.applications);
36
- }
37
- getApplicationNameForPath(path) {
38
- if (!path.startsWith("/")) {
39
- throw new Error(`Path must start with a /`);
40
- }
41
- if (this.pathCache[path]) {
42
- return this.pathCache[path];
43
- }
44
- const pathname = new URL(path, "https://example.com").pathname;
45
- for (const [name, application] of Object.entries(this.applications)) {
46
- if (application.routing) {
47
- for (const group of application.routing) {
48
- for (const childPath of group.paths) {
49
- const regexp = pathToRegexp(childPath);
50
- if (regexp.test(pathname)) {
51
- this.pathCache[path] = name;
52
- return name;
53
- }
54
- }
55
- }
56
- }
57
- }
58
- const defaultApplication = Object.entries(this.applications).find(
59
- ([, application]) => application.default
60
- );
61
- if (!defaultApplication) {
62
- return null;
63
- }
64
- this.pathCache[path] = defaultApplication[0];
65
- return defaultApplication[0];
66
- }
67
- serialize() {
68
- return this.serialized;
69
- }
70
- };
71
-
72
- // src/config/well-known/endpoints.ts
73
- async function getWellKnownClientData(clientConfig, flagValues = {}) {
74
- const config = MicrofrontendConfigClient.fromEnv(clientConfig);
75
- for (const [applicationName, application] of Object.entries(
76
- config.applications
77
- )) {
78
- if (!application.routing) {
79
- continue;
80
- }
81
- const newRoutingMatches = [];
82
- for (const pathGroup of application.routing) {
83
- if (pathGroup.flag) {
84
- const flagName = pathGroup.flag;
85
- const flagFn = flagValues[flagName];
86
- if (!flagFn) {
87
- throw new Error(
88
- `Flag "${flagName}" was specified to control routing for path group "${pathGroup.group}" in application ${applicationName} but not found in provided flag values.`
89
- );
90
- }
91
- const flagEnabled = await flagFn();
92
- if (flagEnabled) {
93
- newRoutingMatches.push(pathGroup);
94
- }
95
- } else {
96
- newRoutingMatches.push(pathGroup);
97
- }
98
- }
99
- application.routing = newRoutingMatches;
100
- }
101
- return {
102
- config: config.serialize()
103
- };
104
- }
105
-
106
- // src/next/endpoints/index.ts
107
- async function wellKnownNextjsClientConfigAppRoute(flagValues) {
108
- return NextResponse.json(
109
- await getWellKnownClientData(
110
- process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,
111
- flagValues
112
- )
113
- );
114
- }
115
- async function handleClientConfigForPagesRouter(res, flagValues) {
116
- const clientData = await getWellKnownClientData(
117
- process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,
118
- flagValues
119
- );
120
- res.status(200).json(clientData);
121
- }
122
- export {
123
- getWellKnownClientData,
124
- handleClientConfigForPagesRouter,
125
- wellKnownNextjsClientConfigAppRoute
126
- };
127
- //# sourceMappingURL=endpoints.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/next/endpoints/index.ts","../../src/config/microfrontends-config/client/index.ts","../../src/config/well-known/endpoints.ts"],"sourcesContent":["import type { NextApiResponse } from 'next';\nimport { NextResponse } from 'next/server';\nimport { getWellKnownClientData } from '../../config/well-known/endpoints';\nimport type { WellKnownClientData } from '../../config/well-known/types';\n\n/**\n * A Next.js App Router API handler to export the microfrontends client config\n * data.\n *\n * @example In the `app/.well-known/vercel/microfrontends/client-config/route.ts` file,\n * add this code:\n * ```\n * export { wellKnownNextjsClientConfigAppRoute as GET } from '@vercel/microfrontends/next/endpoints';\n * ```\n */\nexport async function wellKnownNextjsClientConfigAppRoute(\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<NextResponse> {\n return NextResponse.json<WellKnownClientData>(\n await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n ),\n );\n}\n\n/**\n * A Next.js Pages Router API to export the microfrontends client config data to the client.\n *\n * @example In the `pages/api/.well-known/vercel/microfrontends/client-config/index.ts` file,\n * add this code:\n * ```\n * import { handleClientConfigForPagesRouter } from '@vercel/microfrontends/next/endpoints';\n * import type { NextApiResponse } from 'next';\n *\n * async function handler(\n * _,\n * res: NextApiResponse,\n * ): Promise<void> {\n * await handleClientConfigForPagesRouter(res, {\n * flagValue: () => Promise.resolve(true)\n * });\n * }\n * ```\n *\n * Then also make sure to add the following rewrite rule to your `next.config.js` file:\n * ```\n * rewrites: () =>\n * Promise.resolve([\n * {\n * source: '/.well-known/vercel/microfrontends/client-config',\n * destination: '/api/.well-known/vercel/microfrontends/client-config',\n * },\n * ]),\n * ```\n */\nexport async function handleClientConfigForPagesRouter(\n res: NextApiResponse,\n flagValues: Record<string, () => Promise<boolean>>,\n): Promise<void> {\n const clientData = await getWellKnownClientData(\n process.env.NEXT_PUBLIC_MFE_CLIENT_CONFIG,\n flagValues,\n );\n res.status(200).json(clientData);\n}\n\nexport { getWellKnownClientData };\nexport type { WellKnownClientData };\n","import { pathToRegexp } from 'path-to-regexp';\nimport type { ClientConfig } from './types';\n\ninterface MicrofrontendConfigClientOptions {\n removeFlaggedPaths?: boolean;\n}\n\nexport class MicrofrontendConfigClient {\n applications: ClientConfig['applications'];\n pathCache: Record<string, string> = {};\n private readonly serialized: ClientConfig;\n\n constructor(config: ClientConfig, opts?: MicrofrontendConfigClientOptions) {\n this.serialized = config;\n if (opts?.removeFlaggedPaths) {\n for (const app of Object.values(config.applications)) {\n if (app.routing) {\n app.routing = app.routing.filter((match) => !match.flag);\n }\n }\n }\n this.applications = config.applications;\n }\n\n /**\n * Create a new `MicrofrontendConfigClient` from a JSON string.\n * Config must be passed in to remain framework agnostic\n */\n static fromEnv(\n config: string | undefined,\n opts?: MicrofrontendConfigClientOptions,\n ): MicrofrontendConfigClient {\n if (!config) {\n throw new Error(\n 'Could not construct MicrofrontendConfigClient: configuration is empty or undefined. Did you set up your application with `withMicrofrontends`?',\n );\n }\n return new MicrofrontendConfigClient(\n JSON.parse(config) as ClientConfig,\n opts,\n );\n }\n\n isEqual(other: MicrofrontendConfigClient): boolean {\n return (\n JSON.stringify(this.applications) === JSON.stringify(other.applications)\n );\n }\n\n getApplicationNameForPath(path: string): string | null {\n if (!path.startsWith('/')) {\n throw new Error(`Path must start with a /`);\n }\n\n if (this.pathCache[path]) {\n return this.pathCache[path];\n }\n\n const pathname = new URL(path, 'https://example.com').pathname;\n for (const [name, application] of Object.entries(this.applications)) {\n if (application.routing) {\n for (const group of application.routing) {\n for (const childPath of group.paths) {\n const regexp = pathToRegexp(childPath);\n if (regexp.test(pathname)) {\n this.pathCache[path] = name;\n return name;\n }\n }\n }\n }\n }\n const defaultApplication = Object.entries(this.applications).find(\n ([, application]) => application.default,\n );\n if (!defaultApplication) {\n return null;\n }\n\n this.pathCache[path] = defaultApplication[0];\n return defaultApplication[0];\n }\n\n serialize(): ClientConfig {\n return this.serialized;\n }\n}\n","import { MicrofrontendConfigClient } from '../microfrontends-config/client';\nimport type { WellKnownClientData } from './types';\n\n/**\n * Returns data used by the client to ensure that navigations across\n * microfrontend boundaries are routed and prefetched correctly. The client\n * configuration is safe to expose to users.\n *\n * This data should be exposed in a `.well-known/vercel/microfrontends/client-config`\n * endpoint.\n */\nexport async function getWellKnownClientData(\n clientConfig: string | undefined,\n flagValues: Record<string, () => Promise<boolean>> = {},\n): Promise<WellKnownClientData> {\n const config = MicrofrontendConfigClient.fromEnv(clientConfig);\n for (const [applicationName, application] of Object.entries(\n config.applications,\n )) {\n if (!application.routing) {\n continue;\n }\n const newRoutingMatches = [];\n for (const pathGroup of application.routing) {\n if (pathGroup.flag) {\n const flagName = pathGroup.flag;\n const flagFn = flagValues[flagName];\n if (!flagFn) {\n throw new Error(\n `Flag \"${flagName}\" was specified to control routing for path group \"${pathGroup.group}\" in application ${applicationName} but not found in provided flag values.`,\n );\n }\n // eslint-disable-next-line no-await-in-loop\n const flagEnabled = await flagFn();\n if (flagEnabled) {\n newRoutingMatches.push(pathGroup);\n }\n } else {\n newRoutingMatches.push(pathGroup);\n }\n }\n application.routing = newRoutingMatches;\n }\n\n return {\n config: config.serialize(),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +0,0 @@
1
- import { b as ApplicationId, P as PathGroup } from './types-c9f15465.js';
2
-
3
- interface ClientApplication {
4
- routing?: PathGroup[];
5
- default?: boolean;
6
- }
7
- interface ClientConfig {
8
- applications: Record<ApplicationId, ClientApplication>;
9
- }
10
-
11
- export { ClientConfig as C };