@vercel/microfrontends 2.1.3 → 2.2.1

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 (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -0
  3. package/dist/bin/cli.cjs +207 -90
  4. package/dist/config.d.ts +2 -2
  5. package/dist/experimental/sveltekit.cjs +180 -63
  6. package/dist/experimental/sveltekit.cjs.map +1 -1
  7. package/dist/experimental/sveltekit.d.ts +6 -0
  8. package/dist/experimental/sveltekit.js +180 -63
  9. package/dist/experimental/sveltekit.js.map +1 -1
  10. package/dist/experimental/vite.cjs +177 -66
  11. package/dist/experimental/vite.cjs.map +1 -1
  12. package/dist/experimental/vite.js +177 -66
  13. package/dist/experimental/vite.js.map +1 -1
  14. package/dist/microfrontends/server.cjs +173 -60
  15. package/dist/microfrontends/server.cjs.map +1 -1
  16. package/dist/microfrontends/server.d.ts +2 -2
  17. package/dist/microfrontends/server.js +173 -60
  18. package/dist/microfrontends/server.js.map +1 -1
  19. package/dist/microfrontends/utils.cjs +50 -7
  20. package/dist/microfrontends/utils.cjs.map +1 -1
  21. package/dist/microfrontends/utils.d.ts +1 -1
  22. package/dist/microfrontends/utils.js +50 -7
  23. package/dist/microfrontends/utils.js.map +1 -1
  24. package/dist/next/config.cjs +208 -113
  25. package/dist/next/config.cjs.map +1 -1
  26. package/dist/next/config.d.ts +11 -1
  27. package/dist/next/config.js +208 -113
  28. package/dist/next/config.js.map +1 -1
  29. package/dist/next/middleware.cjs +35 -17
  30. package/dist/next/middleware.cjs.map +1 -1
  31. package/dist/next/middleware.js +35 -17
  32. package/dist/next/middleware.js.map +1 -1
  33. package/dist/next/testing.d.ts +2 -2
  34. package/dist/overrides.d.ts +3 -3
  35. package/dist/schema.d.ts +2 -2
  36. package/dist/{types-88602303.d.ts → types-b9ea41b2.d.ts} +1 -1
  37. package/dist/{types-e7523e61.d.ts → types-dcd8b17a.d.ts} +71 -24
  38. package/dist/utils/mfe-port.cjs +173 -60
  39. package/dist/utils/mfe-port.cjs.map +1 -1
  40. package/dist/utils/mfe-port.js +173 -60
  41. package/dist/utils/mfe-port.js.map +1 -1
  42. package/dist/validation.cjs +47 -38
  43. package/dist/validation.cjs.map +1 -1
  44. package/dist/validation.d.ts +1 -1
  45. package/dist/validation.js +47 -38
  46. package/dist/validation.js.map +1 -1
  47. package/package.json +1 -1
  48. package/schema/schema.json +47 -38
@@ -42,8 +42,8 @@ var import_node_path = require("path");
42
42
 
43
43
  // src/config/microfrontends/utils/get-config-file-name.ts
44
44
  var DEFAULT_CONFIGURATION_FILENAMES = [
45
- "microfrontends.jsonc",
46
- "microfrontends.json"
45
+ "microfrontends.json",
46
+ "microfrontends.jsonc"
47
47
  ];
48
48
  function getPossibleConfigurationFilenames({
49
49
  customConfigFilename
@@ -51,7 +51,7 @@ function getPossibleConfigurationFilenames({
51
51
  if (customConfigFilename) {
52
52
  if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
53
53
  throw new Error(
54
- `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
54
+ `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
55
55
  );
56
56
  }
57
57
  return Array.from(
@@ -175,6 +175,28 @@ var MicrofrontendError = class extends Error {
175
175
  }
176
176
  };
177
177
 
178
+ // src/bin/logger.ts
179
+ function debug(...args) {
180
+ if (process.env.MFE_DEBUG) {
181
+ console.log(...args);
182
+ }
183
+ }
184
+ function info(...args) {
185
+ console.log(...args);
186
+ }
187
+ function warn(...args) {
188
+ console.warn(...args);
189
+ }
190
+ function error(...args) {
191
+ console.error(...args);
192
+ }
193
+ var logger = {
194
+ debug,
195
+ info,
196
+ warn,
197
+ error
198
+ };
199
+
178
200
  // src/config/microfrontends/utils/infer-microfrontends-location.ts
179
201
  var configCache = {};
180
202
  function findPackageWithMicrofrontendsConfig({
@@ -183,6 +205,10 @@ function findPackageWithMicrofrontendsConfig({
183
205
  customConfigFilename
184
206
  }) {
185
207
  const applicationName = applicationContext.name;
208
+ logger.debug(
209
+ "[MFE Config] Searching repository for configs containing application:",
210
+ applicationName
211
+ );
186
212
  try {
187
213
  const microfrontendsJsonPaths = import_fast_glob.default.globSync(
188
214
  `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
@@ -194,6 +220,11 @@ function findPackageWithMicrofrontendsConfig({
194
220
  ignore: ["**/node_modules/**", "**/.git/**"]
195
221
  }
196
222
  );
223
+ logger.debug(
224
+ "[MFE Config] Found",
225
+ microfrontendsJsonPaths.length,
226
+ "config file(s) in repository"
227
+ );
197
228
  const matchingPaths = [];
198
229
  for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
199
230
  try {
@@ -203,19 +234,31 @@ function findPackageWithMicrofrontendsConfig({
203
234
  );
204
235
  const microfrontendsJson = (0, import_jsonc_parser.parse)(microfrontendsJsonContent);
205
236
  if (microfrontendsJson.applications[applicationName]) {
237
+ logger.debug(
238
+ "[MFE Config] Found application in config:",
239
+ microfrontendsJsonPath
240
+ );
206
241
  matchingPaths.push(microfrontendsJsonPath);
207
242
  } else {
208
243
  for (const [_, app] of Object.entries(
209
244
  microfrontendsJson.applications
210
245
  )) {
211
246
  if (app.packageName === applicationName) {
247
+ logger.debug(
248
+ "[MFE Config] Found application via packageName in config:",
249
+ microfrontendsJsonPath
250
+ );
212
251
  matchingPaths.push(microfrontendsJsonPath);
213
252
  }
214
253
  }
215
254
  }
216
- } catch (error) {
255
+ } catch (error2) {
217
256
  }
218
257
  }
258
+ logger.debug(
259
+ "[MFE Config] Total matching config files:",
260
+ matchingPaths.length
261
+ );
219
262
  if (matchingPaths.length > 1) {
220
263
  throw new MicrofrontendError(
221
264
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
@@ -249,9 +292,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
249
292
  }
250
293
  const [packageJsonPath] = matchingPaths;
251
294
  return (0, import_node_path2.dirname)(packageJsonPath);
252
- } catch (error) {
253
- if (error instanceof MicrofrontendError) {
254
- throw error;
295
+ } catch (error2) {
296
+ if (error2 instanceof MicrofrontendError) {
297
+ throw error2;
255
298
  }
256
299
  return null;
257
300
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.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';\nexport { getPossibleConfigurationFilenames } from './get-config-file-name';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","const DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\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 { MicrofrontendError } from '../../errors';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\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 applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\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 applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).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 let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \\`packageName\\` field for the application in \\`microfrontends.json\\` to ensure that the configuration can be found locally.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the \"vercel microfrontends pull\" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.\\n\\n` +\n `If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the \"vercel env pull\" command.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\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.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\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.applicationContext.name}\" 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"]}
1
+ {"version":3,"sources":["../../src/config/microfrontends/utils/index.ts","../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts","../../src/bin/logger.ts"],"sourcesContent":["export { findConfig } from './find-config';\nexport { inferMicrofrontendsLocation } from './infer-microfrontends-location';\nexport { getPossibleConfigurationFilenames } from './get-config-file-name';\n","import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\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 { MicrofrontendError } from '../../errors';\nimport { logger } from '../../../bin/logger';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\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 applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\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 applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\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 logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\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 let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \\`packageName\\` field for the application in \\`microfrontends.json\\` to ensure that the configuration can be found locally.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the \"vercel microfrontends pull\" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.\\n\\n` +\n `If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the \"vercel env pull\" command.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\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.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\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.applicationContext.name}\" 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","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n"],"mappings":"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","names":["fs","import_node_path","import_node_fs","fg","error"]}
@@ -18,6 +18,6 @@ declare function inferMicrofrontendsLocation(opts: FindDefaultMicrofrontendPacka
18
18
 
19
19
  declare function getPossibleConfigurationFilenames({ customConfigFilename, }: {
20
20
  customConfigFilename: string | undefined;
21
- }): string[] | readonly ["microfrontends.jsonc", "microfrontends.json"];
21
+ }): string[] | readonly ["microfrontends.json", "microfrontends.jsonc"];
22
22
 
23
23
  export { findConfig, getPossibleConfigurationFilenames, inferMicrofrontendsLocation };
@@ -4,8 +4,8 @@ import { join } from "node:path";
4
4
 
5
5
  // src/config/microfrontends/utils/get-config-file-name.ts
6
6
  var DEFAULT_CONFIGURATION_FILENAMES = [
7
- "microfrontends.jsonc",
8
- "microfrontends.json"
7
+ "microfrontends.json",
8
+ "microfrontends.jsonc"
9
9
  ];
10
10
  function getPossibleConfigurationFilenames({
11
11
  customConfigFilename
@@ -13,7 +13,7 @@ function getPossibleConfigurationFilenames({
13
13
  if (customConfigFilename) {
14
14
  if (!customConfigFilename.endsWith(".json") && !customConfigFilename.endsWith(".jsonc")) {
15
15
  throw new Error(
16
- `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`
16
+ `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}. The file name must end with '.json' or '.jsonc'. It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`
17
17
  );
18
18
  }
19
19
  return Array.from(
@@ -137,6 +137,28 @@ var MicrofrontendError = class extends Error {
137
137
  }
138
138
  };
139
139
 
140
+ // src/bin/logger.ts
141
+ function debug(...args) {
142
+ if (process.env.MFE_DEBUG) {
143
+ console.log(...args);
144
+ }
145
+ }
146
+ function info(...args) {
147
+ console.log(...args);
148
+ }
149
+ function warn(...args) {
150
+ console.warn(...args);
151
+ }
152
+ function error(...args) {
153
+ console.error(...args);
154
+ }
155
+ var logger = {
156
+ debug,
157
+ info,
158
+ warn,
159
+ error
160
+ };
161
+
140
162
  // src/config/microfrontends/utils/infer-microfrontends-location.ts
141
163
  var configCache = {};
142
164
  function findPackageWithMicrofrontendsConfig({
@@ -145,6 +167,10 @@ function findPackageWithMicrofrontendsConfig({
145
167
  customConfigFilename
146
168
  }) {
147
169
  const applicationName = applicationContext.name;
170
+ logger.debug(
171
+ "[MFE Config] Searching repository for configs containing application:",
172
+ applicationName
173
+ );
148
174
  try {
149
175
  const microfrontendsJsonPaths = fg.globSync(
150
176
  `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(",")}}`,
@@ -156,6 +182,11 @@ function findPackageWithMicrofrontendsConfig({
156
182
  ignore: ["**/node_modules/**", "**/.git/**"]
157
183
  }
158
184
  );
185
+ logger.debug(
186
+ "[MFE Config] Found",
187
+ microfrontendsJsonPaths.length,
188
+ "config file(s) in repository"
189
+ );
159
190
  const matchingPaths = [];
160
191
  for (const microfrontendsJsonPath of microfrontendsJsonPaths) {
161
192
  try {
@@ -165,19 +196,31 @@ function findPackageWithMicrofrontendsConfig({
165
196
  );
166
197
  const microfrontendsJson = parse(microfrontendsJsonContent);
167
198
  if (microfrontendsJson.applications[applicationName]) {
199
+ logger.debug(
200
+ "[MFE Config] Found application in config:",
201
+ microfrontendsJsonPath
202
+ );
168
203
  matchingPaths.push(microfrontendsJsonPath);
169
204
  } else {
170
205
  for (const [_, app] of Object.entries(
171
206
  microfrontendsJson.applications
172
207
  )) {
173
208
  if (app.packageName === applicationName) {
209
+ logger.debug(
210
+ "[MFE Config] Found application via packageName in config:",
211
+ microfrontendsJsonPath
212
+ );
174
213
  matchingPaths.push(microfrontendsJsonPath);
175
214
  }
176
215
  }
177
216
  }
178
- } catch (error) {
217
+ } catch (error2) {
179
218
  }
180
219
  }
220
+ logger.debug(
221
+ "[MFE Config] Total matching config files:",
222
+ matchingPaths.length
223
+ );
181
224
  if (matchingPaths.length > 1) {
182
225
  throw new MicrofrontendError(
183
226
  `Found multiple \`microfrontends.json\` files in the repository referencing the application "${applicationName}", but only one is allowed.
@@ -211,9 +254,9 @@ If you suspect this is thrown in error, please reach out to the Vercel team.`,
211
254
  }
212
255
  const [packageJsonPath] = matchingPaths;
213
256
  return dirname(packageJsonPath);
214
- } catch (error) {
215
- if (error instanceof MicrofrontendError) {
216
- throw error;
257
+ } catch (error2) {
258
+ if (error2 instanceof MicrofrontendError) {
259
+ throw error2;
217
260
  }
218
261
  return null;
219
262
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.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 { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","const DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.jsonc',\n 'microfrontends.json',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `The VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable must end with '.json' or '.jsonc'. Received: ${customConfigFilename}`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\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 { MicrofrontendError } from '../../errors';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\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 applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\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 applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).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 let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \\`packageName\\` field for the application in \\`microfrontends.json\\` to ensure that the configuration can be found locally.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the \"vercel microfrontends pull\" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.\\n\\n` +\n `If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the \"vercel env pull\" command.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\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.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\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.applicationContext.name}\" 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":[]}
1
+ {"version":3,"sources":["../../src/config/microfrontends/utils/find-config.ts","../../src/config/microfrontends/utils/get-config-file-name.ts","../../src/config/microfrontends/utils/infer-microfrontends-location.ts","../../src/config/errors.ts","../../src/bin/logger.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { join } from 'node:path';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\n\nexport function findConfig({\n dir,\n customConfigFilename,\n}: {\n dir: string;\n customConfigFilename: string | undefined;\n}): string | null {\n for (const filename of getPossibleConfigurationFilenames({\n customConfigFilename,\n })) {\n const maybeConfig = join(dir, filename);\n if (fs.existsSync(maybeConfig)) {\n return maybeConfig;\n }\n }\n\n return null;\n}\n","// ordered by most likely to be the correct one\nconst DEFAULT_CONFIGURATION_FILENAMES = [\n 'microfrontends.json',\n 'microfrontends.jsonc',\n] as const;\n\nexport function getPossibleConfigurationFilenames({\n customConfigFilename,\n}: {\n // from env\n customConfigFilename: string | undefined;\n}) {\n if (customConfigFilename) {\n if (\n !customConfigFilename.endsWith('.json') &&\n !customConfigFilename.endsWith('.jsonc')\n ) {\n throw new Error(\n `Found VC_MICROFRONTENDS_CONFIG_FILE_NAME but the name is invalid. Received: ${customConfigFilename}.` +\n ` The file name must end with '.json' or '.jsonc'.` +\n ` It's also possible for the env var to include the path, eg microfrontends-dev.json or /path/to/microfrontends-dev.json.`,\n );\n }\n return Array.from(\n new Set([customConfigFilename, ...DEFAULT_CONFIGURATION_FILENAMES]),\n );\n }\n return DEFAULT_CONFIGURATION_FILENAMES;\n}\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 { MicrofrontendError } from '../../errors';\nimport { logger } from '../../../bin/logger';\nimport { getPossibleConfigurationFilenames } from './get-config-file-name';\nimport type { ApplicationContext } from './get-application-context';\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 applicationContext: ApplicationContext;\n customConfigFilename: string | undefined;\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 applicationContext,\n customConfigFilename,\n}: FindDefaultMicrofrontendPackageArgs): string | null {\n const applicationName = applicationContext.name;\n logger.debug(\n '[MFE Config] Searching repository for configs containing application:',\n applicationName,\n );\n\n try {\n // eslint-disable-next-line import/no-named-as-default-member\n const microfrontendsJsonPaths = fg.globSync(\n `**/{${getPossibleConfigurationFilenames({ customConfigFilename }).join(',')}}`,\n {\n cwd: repositoryRoot,\n absolute: true,\n onlyFiles: true,\n followSymbolicLinks: false,\n ignore: ['**/node_modules/**', '**/.git/**'],\n },\n );\n\n logger.debug(\n '[MFE Config] Found',\n microfrontendsJsonPaths.length,\n 'config file(s) in repository',\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 logger.debug(\n '[MFE Config] Found application in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n } else {\n for (const [_, app] of Object.entries(\n microfrontendsJson.applications,\n )) {\n if (app.packageName === applicationName) {\n logger.debug(\n '[MFE Config] Found application via packageName in config:',\n microfrontendsJsonPath,\n );\n matchingPaths.push(microfrontendsJsonPath);\n }\n }\n }\n } catch (error) {\n // malformed json most likely, skip this file\n }\n }\n\n logger.debug(\n '[MFE Config] Total matching config files:',\n matchingPaths.length,\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 let additionalErrorMessage = '';\n if (microfrontendsJsonPaths.length > 0) {\n if (!applicationContext.projectName) {\n additionalErrorMessage = `\\n\\nIf the name in package.json (${applicationContext.packageJsonName}) differs from your Vercel Project name, set the \\`packageName\\` field for the application in \\`microfrontends.json\\` to ensure that the configuration can be found locally.`;\n } else {\n additionalErrorMessage = `\\n\\nNames of applications in \\`microfrontends.json\\` must match the Vercel Project name (${applicationContext.projectName}).`;\n }\n }\n throw new MicrofrontendError(\n `Could not find a \\`microfrontends.json\\` file in the repository that contains the \"${applicationName}\" application.${additionalErrorMessage}\\n\\n` +\n `If your Vercel Microfrontends configuration is not in this repository, you can use the Vercel CLI to pull the Vercel Microfrontends configuration using the \"vercel microfrontends pull\" command, or you can specify the path manually using the VC_MICROFRONTENDS_CONFIG environment variable.\\n\\n` +\n `If your Vercel Microfrontends configuration has a custom name, ensure the VC_MICROFRONTENDS_CONFIG_FILE_NAME environment variable is set, you can pull the vercel project environment variables using the \"vercel env pull\" command.\\n\\n` +\n `If you suspect this is thrown in error, please reach out to the Vercel team.`,\n { type: 'config', subtype: 'inference_failed' },\n );\n }\n\n const [packageJsonPath] = matchingPaths as [string];\n return dirname(packageJsonPath);\n } catch (error) {\n if (error instanceof MicrofrontendError) {\n throw error;\n }\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.applicationContext.name}${opts.customConfigFilename ? `-${opts.customConfigFilename}` : ''}`;\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.applicationContext.name}\" 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","/* eslint-disable no-console */\n\nfunction debug(...args: unknown[]): void {\n if (process.env.MFE_DEBUG) {\n console.log(...args);\n }\n}\n\nfunction info(...args: unknown[]): void {\n console.log(...args);\n}\n\nfunction warn(...args: unknown[]): void {\n console.warn(...args);\n}\n\nfunction error(...args: unknown[]): void {\n console.error(...args);\n}\n\nexport const logger = {\n debug,\n info,\n warn,\n error,\n};\n"],"mappings":"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","names":["error"]}