@vercel/microfrontends 1.2.1 → 1.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/constants.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts"],"sourcesContent":["export { findConfig } from './find-config';\nexport { inferMicrofrontendsLocation } from './infer-microfrontends-location';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\nexport function findConfig({ dir }: { dir: string }): string | null {\n for (const filename of CONFIGURATION_FILENAMES) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","export const CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationName: string;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationName,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${CONFIGURATION_FILENAMES.join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n if (matchingPaths.length > 1) {\n throw new Error(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n );\n }\n\n if (matchingPaths.length === 0) {\n throw new Error(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains \"applications.${applicationName}\". Microfrontends defined in separate repositories are not supported yet.`,\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new Error(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationName}\" starting in directory \"${opts.repositoryRoot}\".`,\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAAe;AACf,uBAAqB;;;ACDd,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AACF;;;ADCO,SAAS,WAAW,EAAE,IAAI,GAAmC;AAClE,aAAW,YAAY,yBAAyB;AAC9C,UAAM,kBAAc,uBAAK,KAAK,QAAQ;AACtC,QAAI,eAAAA,QAAG,WAAW,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AEbA,IAAAC,oBAAwB;AACxB,IAAAC,kBAA6B;AAC7B,0BAAsB;AACtB,uBAAe;AAKf,IAAM,cAAsC,CAAC;AAa7C,SAAS,oCAAoC;AAAA,EAC3C;AAAA,EACA;AACF,GAAuD;AACrD,MAAI;AAEF,UAAM,0BAA0B,iBAAAC,QAAG;AAAA,MACjC,OAAO,wBAAwB,KAAK,GAAG;AAAA,MACvC;AAAA,QACE,KAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,QAAQ,CAAC,sBAAsB,YAAY;AAAA,MAC7C;AAAA,IACF;AAEA,UAAM,gBAA0B,CAAC;AACjC,eAAW,0BAA0B,yBAAyB;AAC5D,UAAI;AACF,cAAM,gCAA4B;AAAA,UAChC;AAAA,UACA;AAAA,QACF;AACA,cAAM,yBAAqB,2BAAM,yBAAyB;AAE1D,YAAI,mBAAmB,aAAa,eAAe,GAAG;AACpD,wBAAc,KAAK,sBAAsB;AAAA,QAC3C;AAAA,MACF,SAAS,OAAP;AAAA,MAEF;AAAA,IACF;AAEA,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,IAAI;AAAA,QACR,+FAA+F;AAAA,EAA+C,cAAc,KAAK,aAAQ;AAAA,MAC3K;AAAA,IACF;AAEA,QAAI,cAAc,WAAW,GAAG;AAC9B,YAAM,IAAI;AAAA,QACR,+FAA+F;AAAA,MACjG;AAAA,IACF;AAEA,UAAM,CAAC,eAAe,IAAI;AAC1B,eAAO,2BAAQ,eAAe;AAAA,EAChC,SAAS,OAAP;AACA,WAAO;AAAA,EACT;AACF;AAMO,SAAS,4BACd,MACQ;AAER,QAAM,WAAW,GAAG,KAAK,kBAAkB,KAAK;AAGhD,MAAI,YAAY,QAAQ,GAAG;AACzB,WAAO,YAAY,QAAQ;AAAA,EAC7B;AAEA,QAAM,SAAS,oCAAoC,IAAI;AAEvD,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,qFAAqF,KAAK,2CAA2C,KAAK;AAAA,IAC5I;AAAA,EACF;AAGA,cAAY,QAAQ,IAAI;AACxB,SAAO;AACT;","names":["fs","import_node_path","import_node_fs","fg"]}
1
+ {"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/constants.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts"],"sourcesContent":["export { findConfig } from './find-config';\nexport { inferMicrofrontendsLocation } from './infer-microfrontends-location';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\nexport function findConfig({ dir }: { dir: string }): string | null {\n for (const filename of CONFIGURATION_FILENAMES) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","export const CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\nimport { MicrofrontendError } from '../../errors';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationName: string;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationName,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${CONFIGURATION_FILENAMES.join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains \"applications.${applicationName}\". Microfrontends defined in separate repositories are not supported yet.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationName}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n"],"mappings":"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","names":["fs","import_node_path","import_node_fs","fg"]}
@@ -24,6 +24,100 @@ import { dirname } from "node:path";
24
24
  import { readFileSync } from "node:fs";
25
25
  import { parse } from "jsonc-parser";
26
26
  import fg from "fast-glob";
27
+
28
+ // src/config/errors.ts
29
+ var MicrofrontendError = class extends Error {
30
+ constructor(message, opts) {
31
+ super(message, { cause: opts?.cause });
32
+ this.name = "MicrofrontendsError";
33
+ this.source = opts?.source ?? "@vercel/microfrontends";
34
+ this.type = opts?.type ?? "unknown";
35
+ this.subtype = opts?.subtype;
36
+ Error.captureStackTrace(this, MicrofrontendError);
37
+ }
38
+ isKnown() {
39
+ return this.type !== "unknown";
40
+ }
41
+ isUnknown() {
42
+ return !this.isKnown();
43
+ }
44
+ /**
45
+ * Converts an error to a MicrofrontendsError.
46
+ * @param original - The original error to convert.
47
+ * @returns The converted MicrofrontendsError.
48
+ */
49
+ static convert(original, opts) {
50
+ if (opts?.fileName) {
51
+ const err = MicrofrontendError.convertFSError(original, opts.fileName);
52
+ if (err) {
53
+ return err;
54
+ }
55
+ }
56
+ if (original.message.includes(
57
+ "Code generation from strings disallowed for this context"
58
+ )) {
59
+ return new MicrofrontendError(original.message, {
60
+ type: "config",
61
+ subtype: "unsupported_validation_env",
62
+ source: "ajv"
63
+ });
64
+ }
65
+ return new MicrofrontendError(original.message);
66
+ }
67
+ static convertFSError(original, fileName) {
68
+ if (original instanceof Error && "code" in original) {
69
+ if (original.code === "ENOENT") {
70
+ return new MicrofrontendError(`Could not find "${fileName}"`, {
71
+ type: "config",
72
+ subtype: "unable_to_read_file",
73
+ source: "fs"
74
+ });
75
+ }
76
+ if (original.code === "EACCES") {
77
+ return new MicrofrontendError(
78
+ `Permission denied while accessing "${fileName}"`,
79
+ {
80
+ type: "config",
81
+ subtype: "invalid_permissions",
82
+ source: "fs"
83
+ }
84
+ );
85
+ }
86
+ }
87
+ if (original instanceof SyntaxError) {
88
+ return new MicrofrontendError(
89
+ `Failed to parse "${fileName}": Invalid JSON format.`,
90
+ {
91
+ type: "config",
92
+ subtype: "invalid_syntax",
93
+ source: "fs"
94
+ }
95
+ );
96
+ }
97
+ return null;
98
+ }
99
+ /**
100
+ * Handles an unknown error and returns a MicrofrontendsError instance.
101
+ * @param err - The error to handle.
102
+ * @returns A MicrofrontendsError instance.
103
+ */
104
+ static handle(err, opts) {
105
+ if (err instanceof MicrofrontendError) {
106
+ return err;
107
+ }
108
+ if (err instanceof Error) {
109
+ return MicrofrontendError.convert(err, opts);
110
+ }
111
+ if (typeof err === "object" && err !== null) {
112
+ if ("message" in err && typeof err.message === "string") {
113
+ return MicrofrontendError.convert(new Error(err.message), opts);
114
+ }
115
+ }
116
+ return new MicrofrontendError("An unknown error occurred");
117
+ }
118
+ };
119
+
120
+ // src/config/microfrontends/utils/infer-microfrontends-location.ts
27
121
  var configCache = {};
28
122
  function findPackageWithMicrofrontendsConfig({
29
123
  repositoryRoot,
@@ -50,19 +144,29 @@ function findPackageWithMicrofrontendsConfig({
50
144
  const microfrontendsJson = parse(microfrontendsJsonContent);
51
145
  if (microfrontendsJson.applications[applicationName]) {
52
146
  matchingPaths.push(microfrontendsJsonPath);
147
+ } else {
148
+ for (const [_, app] of Object.entries(
149
+ microfrontendsJson.applications
150
+ )) {
151
+ if (app.packageName === applicationName) {
152
+ matchingPaths.push(microfrontendsJsonPath);
153
+ }
154
+ }
53
155
  }
54
156
  } catch (error) {
55
157
  }
56
158
  }
57
159
  if (matchingPaths.length > 1) {
58
- throw new Error(
160
+ throw new MicrofrontendError(
59
161
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
60
- ${matchingPaths.join("\n \u2022 ")}`
162
+ ${matchingPaths.join("\n \u2022 ")}`,
163
+ { type: "config", subtype: "inference_failed" }
61
164
  );
62
165
  }
63
166
  if (matchingPaths.length === 0) {
64
- throw new Error(
65
- `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". Microfrontends defined in separate repositories are not supported yet.`
167
+ throw new MicrofrontendError(
168
+ `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". Microfrontends defined in separate repositories are not supported yet.`,
169
+ { type: "config", subtype: "inference_failed" }
66
170
  );
67
171
  }
68
172
  const [packageJsonPath] = matchingPaths;
@@ -78,8 +182,9 @@ function inferMicrofrontendsLocation(opts) {
78
182
  }
79
183
  const result = findPackageWithMicrofrontendsConfig(opts);
80
184
  if (!result) {
81
- throw new Error(
82
- `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`
185
+ throw new MicrofrontendError(
186
+ `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`,
187
+ { type: "config", subtype: "inference_failed" }
83
188
  );
84
189
  }
85
190
  configCache[cacheKey] = result;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/constants.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\nexport function findConfig({ dir }: { dir: string }): string | null {\n for (const filename of CONFIGURATION_FILENAMES) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","export const CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationName: string;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationName,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${CONFIGURATION_FILENAMES.join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n if (matchingPaths.length > 1) {\n throw new Error(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n );\n }\n\n if (matchingPaths.length === 0) {\n throw new Error(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains \"applications.${applicationName}\". Microfrontends defined in separate repositories are not supported yet.`,\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new Error(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationName}\" starting in directory \"${opts.repositoryRoot}\".`,\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,SAAS,YAAY;;;ACDd,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AACF;;;ADCO,SAAS,WAAW,EAAE,IAAI,GAAmC;AAClE,aAAW,YAAY,yBAAyB;AAC9C,UAAM,cAAc,KAAK,KAAK,QAAQ;AACtC,QAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AEbA,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,aAAa;AACtB,OAAO,QAAQ;AAKf,IAAM,cAAsC,CAAC;AAa7C,SAAS,oCAAoC;AAAA,EAC3C;AAAA,EACA;AACF,GAAuD;AACrD,MAAI;AAEF,UAAM,0BAA0B,GAAG;AAAA,MACjC,OAAO,wBAAwB,KAAK,GAAG;AAAA,MACvC;AAAA,QACE,KAAK;AAAA,QACL,UAAU;AAAA,QACV,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,QAAQ,CAAC,sBAAsB,YAAY;AAAA,MAC7C;AAAA,IACF;AAEA,UAAM,gBAA0B,CAAC;AACjC,eAAW,0BAA0B,yBAAyB;AAC5D,UAAI;AACF,cAAM,4BAA4B;AAAA,UAChC;AAAA,UACA;AAAA,QACF;AACA,cAAM,qBAAqB,MAAM,yBAAyB;AAE1D,YAAI,mBAAmB,aAAa,eAAe,GAAG;AACpD,wBAAc,KAAK,sBAAsB;AAAA,QAC3C;AAAA,MACF,SAAS,OAAP;AAAA,MAEF;AAAA,IACF;AAEA,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,IAAI;AAAA,QACR,+FAA+F;AAAA,EAA+C,cAAc,KAAK,aAAQ;AAAA,MAC3K;AAAA,IACF;AAEA,QAAI,cAAc,WAAW,GAAG;AAC9B,YAAM,IAAI;AAAA,QACR,+FAA+F;AAAA,MACjG;AAAA,IACF;AAEA,UAAM,CAAC,eAAe,IAAI;AAC1B,WAAO,QAAQ,eAAe;AAAA,EAChC,SAAS,OAAP;AACA,WAAO;AAAA,EACT;AACF;AAMO,SAAS,4BACd,MACQ;AAER,QAAM,WAAW,GAAG,KAAK,kBAAkB,KAAK;AAGhD,MAAI,YAAY,QAAQ,GAAG;AACzB,WAAO,YAAY,QAAQ;AAAA,EAC7B;AAEA,QAAM,SAAS,oCAAoC,IAAI;AAEvD,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR,qFAAqF,KAAK,2CAA2C,KAAK;AAAA,IAC5I;AAAA,EACF;AAGA,cAAY,QAAQ,IAAI;AACxB,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/constants.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\n\nexport function findConfig({ dir }: { dir: string }): string | null {\n for (const filename of CONFIGURATION_FILENAMES) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","export const CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n","import { dirname } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { parse } from 'jsonc-parser';\nimport fg from 'fast-glob';\nimport type { Config } from '../../schema/types';\nimport { CONFIGURATION_FILENAMES } from '../../constants';\nimport { MicrofrontendError } from '../../errors';\n\n// cache the path to default configuration to avoid having to walk the file system multiple times\nconst configCache: Record<string, string> = {};\n\ninterface FindDefaultMicrofrontendPackageArgs {\n repositoryRoot: string;\n applicationName: string;\n}\n\n/**\n * Given a repository root and a package name, find the path to the package.json file with the\n * given name.\n *\n * This method uses globby to find all package.json files and then reads them in parallel\n */\nfunction findPackageWithMicrofrontendsConfig({\n repositoryRoot,\n applicationName,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${CONFIGURATION_FILENAMES.join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n const matchingPaths: string[] = [];\n for (const microfrontendsJsonPath of microfrontendsJsonPaths) {\n try {\n const microfrontendsJsonContent = readFileSync(\n microfrontendsJsonPath,\n 'utf-8',\n );\n const microfrontendsJson = parse(microfrontendsJsonContent) as Config;\n\n if (microfrontendsJson.applications[applicationName]) {\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n if (matchingPaths.length > 1) {\n throw new MicrofrontendError(\n `Found multiple \\`microfrontends.json\\` files in the repository referencing the application \"${applicationName}\", but only one is allowed.\\n${matchingPaths.join('\\n • ')}`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n if (matchingPaths.length === 0) {\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains \"applications.${applicationName}\". Microfrontends defined in separate repositories are not supported yet.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Given a repository root and a package name, find the path to the package directory with\n * a microfrontends config that contains the given name in its applications.\n */\nexport function inferMicrofrontendsLocation(\n opts: FindDefaultMicrofrontendPackageArgs,\n): string {\n // cache this with name to support multiple configurations in the same repository\n const cacheKey = `${opts.repositoryRoot}-${opts.applicationName}`;\n\n // Check if we have a cached result\n if (configCache[cacheKey]) {\n return configCache[cacheKey];\n }\n\n const result = findPackageWithMicrofrontendsConfig(opts);\n\n if (!result) {\n throw new MicrofrontendError(\n `Could not infer the location of the \\`microfrontends.json\\` file for application \"${opts.applicationName}\" starting in directory \"${opts.repositoryRoot}\".`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n // Cache the result\n configCache[cacheKey] = result;\n return result;\n}\n","export type MicrofrontendErrorType =\n | 'config'\n | 'packageJson'\n | 'vercelJson'\n | 'application'\n | 'unknown';\n\nexport type MicrofrontendErrorSubtype =\n | 'not_found'\n | 'inference_failed'\n | 'not_found_in_env'\n | 'invalid_asset_prefix'\n | 'invalid_main_path'\n | 'does_not_match_schema'\n | 'unable_to_read_file'\n | 'unsupported_validation_env'\n | 'unsupported_version'\n | 'invalid_path'\n | 'invalid_permissions'\n | 'invalid_syntax'\n | 'missing_microfrontend_config_path'\n | 'unsupported_operation';\n\n// A mapping of error types to their subtypes.\ninterface TypeToSubtype {\n application:\n | 'invalid_asset_prefix'\n | 'invalid_path'\n | 'multiple_package_managers'\n | 'not_found';\n config:\n | 'conflicting_paths'\n | 'depcrecated_field'\n | 'does_not_match_schema'\n | 'invalid_main_path'\n | 'invalid_preview_deployment_suffix'\n | 'multiple_default_applications'\n | 'no_default_application'\n | 'not_found_in_env'\n | 'not_found'\n | 'inference_failed'\n | 'unable_to_read_file'\n | 'invalid_syntax'\n | 'invalid_permissions'\n | 'unsupported_operation'\n | 'unsupported_validation_env'\n | 'unsupported_version';\n packageJson:\n | 'missing_field_name'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n vercelJson:\n | 'missing_field_microfrontend_config_path'\n | 'unable_to_read_file'\n | 'invalid_permissions'\n | 'invalid_syntax';\n unknown: never;\n}\n\nexport type MicrofrontendErrorSource =\n | '@vercel/microfrontends'\n | '@vercel/microfrontends/next'\n | 'fs'\n | 'ajv';\n\nexport interface MicrofrontendErrorOptions<T extends MicrofrontendErrorType> {\n cause?: unknown;\n source?: MicrofrontendErrorSource;\n type?: T;\n subtype?: TypeToSubtype[T];\n}\n\ninterface HandleOptions {\n fileName?: string;\n}\n\nexport class MicrofrontendError<\n T extends MicrofrontendErrorType = 'unknown',\n> extends Error {\n public source: MicrofrontendErrorSource;\n public type: T;\n public subtype?: TypeToSubtype[T];\n\n constructor(message: string, opts?: MicrofrontendErrorOptions<T>) {\n super(message, { cause: opts?.cause });\n this.name = 'MicrofrontendsError';\n this.source = opts?.source ?? '@vercel/microfrontends';\n this.type = opts?.type ?? ('unknown' as T);\n this.subtype = opts?.subtype;\n Error.captureStackTrace(this, MicrofrontendError);\n }\n\n isKnown(): boolean {\n return this.type !== 'unknown';\n }\n\n isUnknown(): boolean {\n return !this.isKnown();\n }\n\n /**\n * Converts an error to a MicrofrontendsError.\n * @param original - The original error to convert.\n * @returns The converted MicrofrontendsError.\n */\n static convert(\n original: Error,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (opts?.fileName) {\n const err = MicrofrontendError.convertFSError(original, opts.fileName);\n if (err) {\n return err;\n }\n }\n\n if (\n original.message.includes(\n 'Code generation from strings disallowed for this context',\n )\n ) {\n return new MicrofrontendError(original.message, {\n type: 'config',\n subtype: 'unsupported_validation_env',\n source: 'ajv',\n });\n }\n\n // unknown catch-all\n return new MicrofrontendError(original.message);\n }\n\n static convertFSError(\n original: Error,\n fileName: string,\n ): MicrofrontendError<MicrofrontendErrorType> | null {\n if (original instanceof Error && 'code' in original) {\n if (original.code === 'ENOENT') {\n return new MicrofrontendError(`Could not find \"${fileName}\"`, {\n type: 'config',\n subtype: 'unable_to_read_file',\n source: 'fs',\n });\n }\n if (original.code === 'EACCES') {\n return new MicrofrontendError(\n `Permission denied while accessing \"${fileName}\"`,\n {\n type: 'config',\n subtype: 'invalid_permissions',\n source: 'fs',\n },\n );\n }\n }\n\n if (original instanceof SyntaxError) {\n return new MicrofrontendError(\n `Failed to parse \"${fileName}\": Invalid JSON format.`,\n {\n type: 'config',\n subtype: 'invalid_syntax',\n source: 'fs',\n },\n );\n }\n\n return null;\n }\n\n /**\n * Handles an unknown error and returns a MicrofrontendsError instance.\n * @param err - The error to handle.\n * @returns A MicrofrontendsError instance.\n */\n static handle(\n err: unknown,\n opts?: HandleOptions,\n ): MicrofrontendError<MicrofrontendErrorType> {\n if (err instanceof MicrofrontendError) {\n return err as MicrofrontendError<MicrofrontendErrorType>;\n }\n\n // handle Error instances\n if (err instanceof Error) {\n return MicrofrontendError.convert(err, opts);\n }\n\n // handle object errors\n if (typeof err === 'object' && err !== null) {\n if ('message' in err && typeof err.message === 'string') {\n return MicrofrontendError.convert(new Error(err.message), opts);\n }\n }\n\n return new MicrofrontendError('An unknown error occurred');\n }\n}\n"],"mappings":"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","names":[]}
@@ -255,19 +255,29 @@ function findPackageWithMicrofrontendsConfig({
255
255
  const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
256
256
  if (microfrontendsJson.applications[applicationName]) {
257
257
  matchingPaths.push(microfrontendsJsonPath);
258
+ } else {
259
+ for (const [_, app] of Object.entries(
260
+ microfrontendsJson.applications
261
+ )) {
262
+ if (app.packageName === applicationName) {
263
+ matchingPaths.push(microfrontendsJsonPath);
264
+ }
265
+ }
258
266
  }
259
267
  } catch (error) {
260
268
  }
261
269
  }
262
270
  if (matchingPaths.length > 1) {
263
- throw new Error(
271
+ throw new MicrofrontendError(
264
272
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
265
- ${matchingPaths.join("\n \u2022 ")}`
273
+ ${matchingPaths.join("\n \u2022 ")}`,
274
+ { type: "config", subtype: "inference_failed" }
266
275
  );
267
276
  }
268
277
  if (matchingPaths.length === 0) {
269
- throw new Error(
270
- `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". Microfrontends defined in separate repositories are not supported yet.`
278
+ throw new MicrofrontendError(
279
+ `Could not find a \`microfrontends.json\` file in the repository that contains "applications.${applicationName}". Microfrontends defined in separate repositories are not supported yet.`,
280
+ { type: "config", subtype: "inference_failed" }
271
281
  );
272
282
  }
273
283
  const [packageJsonPath] = matchingPaths;
@@ -283,8 +293,9 @@ function inferMicrofrontendsLocation(opts) {
283
293
  }
284
294
  const result = findPackageWithMicrofrontendsConfig(opts);
285
295
  if (!result) {
286
- throw new Error(
287
- `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`
296
+ throw new MicrofrontendError(
297
+ `Could not infer the location of the \`microfrontends.json\` file for application "${opts.applicationName}" starting in directory "${opts.repositoryRoot}".`,
298
+ { type: "config", subtype: "inference_failed" }
288
299
  );
289
300
  }
290
301
  configCache[cacheKey] = result;
@@ -1412,15 +1423,17 @@ var MicrofrontendsServer = class {
1412
1423
  });
1413
1424
  }
1414
1425
  }
1415
- throw new Error(
1416
- "Unable to automatically infer the location of the `microfrontends.json` file. Microfrontends defined in separate repositories are not supported yet. If you suspect this is thrown in error, please reach out to the Vercel team."
1426
+ throw new MicrofrontendError(
1427
+ "Unable to automatically infer the location of the `microfrontends.json` file. Microfrontends defined in separate repositories are not supported yet. If you suspect this is thrown in error, please reach out to the Vercel team.",
1428
+ { type: "config", subtype: "inference_failed" }
1417
1429
  );
1418
1430
  } catch (e) {
1419
1431
  if (e instanceof MicrofrontendError) {
1420
1432
  throw e;
1421
1433
  }
1434
+ const errorMessage = e instanceof Error ? e.message : String(e);
1422
1435
  throw new MicrofrontendError(
1423
- "Unable to locate and parse the `microfrontends.json` configuration file.",
1436
+ `Unable to locate and parse the \`microfrontends.json\` configuration file. Original error message: ${errorMessage}`,
1424
1437
  { cause: e, type: "config", subtype: "inference_failed" }
1425
1438
  );
1426
1439
  }