{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["// eslint-disable-next-line eslint-comments/disable-enable-pair\n/* eslint-disable unicorn/no-null */\nimport { Plugin, ResolvedConfig, UserConfig } from \"vite\";\nimport { Plugin as EsbuildPlugin, PluginBuild, OnResolveArgs } from \"esbuild\";\n\ntype ExternalCriteria = string | RegExp | ((id: string) => boolean);\n\ninterface ModulePrefixTransformPluginOptions {\n  /** The base path of the vite configuration */\n  base: string;\n}\n\ninterface PluginOptions {\n  externals: ExternalCriteria[];\n}\n\nconst resolvedExternals = new Set<string>();\n\nconst isExternal = (id: string, externals: ExternalCriteria[]): boolean =>\n  externals.some((external) => {\n    if (typeof external === \"string\") {\n      return id === external || id.startsWith(`${external}/`);\n    }\n\n    if (external instanceof RegExp) {\n      return external.test(id);\n    }\n\n    if (typeof external === \"function\") {\n      return external(id);\n    }\n\n    return false;\n  });\n\n/**\n * Creates a plugin for esbuild to externalize specific modules.\n * esbuild is used by Vite during development.\n * This plugin is injected into optimizeDeps.esbuildOptions.plugins, and runs during the dependency scanning / optimization phase.\n *\n * @param options - Plugin options\n *\n * @returns The esbuild plugin\n */\nconst esbuildPluginExternalize = (\n  externals: ExternalCriteria[],\n): EsbuildPlugin => ({\n  name: \"externalize\",\n  setup(build: PluginBuild) {\n    build.onResolve({ filter: /.*/ }, (args: OnResolveArgs) => {\n      if (\n        isExternal(args.path, externals) &&\n        args.kind === \"import-statement\"\n      ) {\n        resolvedExternals.add(args.path);\n        return {\n          path: args.path,\n          external: true,\n        };\n      }\n\n      // Supresses the following error:\n      // The entry point [moduleName] cannot be marked as external\n      if (isExternal(args.path, externals) && args.kind === \"entry-point\") {\n        resolvedExternals.add(args.path);\n        return { path: args.path, namespace: \"externalized-modules\" };\n      }\n\n      return null;\n    });\n    // Supresses the following error:\n    // Do not know how to load path: [namespace:moduleName]\n    build.onLoad({ filter: /.*/ }, (args) => {\n      if (isExternal(args.path, externals)) {\n        return { contents: \"\" };\n      }\n\n      return null;\n    });\n  },\n});\n\n/**\n * Creates a plugin to remove prefix from imports injected by Vite.\n * If module is externalized, Vite will prefix imports with \"/\\@id/\" during development.\n *\n * @param options - The plugin options\n *\n * @returns Vite plugin to remove prefix from imports\n */\nconst modulePrefixTransform = ({\n  base,\n}: ModulePrefixTransformPluginOptions): Plugin => ({\n  name: \"vite-plugin-remove-prefix\",\n  transform: (code: string): string => {\n    // Verify if there are any external modules resolved to avoid having /\\/@id\\/()/g regex\n    if (resolvedExternals.size === 0) return code;\n\n    const viteImportAnalysisModulePrefix = \"@id/\";\n    const prefixedImportRegex = new RegExp(\n      `${base}${viteImportAnalysisModulePrefix}(${[...resolvedExternals].join(\n        \"|\",\n      )})`,\n      \"g\",\n    );\n\n    if (prefixedImportRegex.test(code)) {\n      // eslint-disable-next-line unicorn/prefer-string-replace-all\n      return code.replace(\n        prefixedImportRegex,\n        (_: string, externalName: string) => externalName,\n      );\n    }\n    return code;\n  },\n});\n\n/**\n * Creates a Vite plugin to externalize specific modules.\n * This plugin is only used during development.\n * To externalize modules in production, configure build.rollupOptions.external.\n *\n * @param externals - The list of modules to externalize.\n *\n * @returns The Vite plugin.\n */\nconst vitePluginExternalize = (options: PluginOptions): Plugin => ({\n  name: \"vite-plugin-externalize\",\n  enforce: \"pre\",\n  apply: \"serve\",\n  config: (config: UserConfig): Omit<UserConfig, \"plugins\"> | null | void => {\n    config.optimizeDeps ??= {}; // eslint-disable-line no-param-reassign\n    config.optimizeDeps.esbuildOptions ??= {}; // eslint-disable-line no-param-reassign\n    config.optimizeDeps.esbuildOptions.plugins ??= []; // eslint-disable-line no-param-reassign\n\n    // Prevent the plugin from being inserted multiple times\n    const pluginName = \"externalize\";\n    const isPluginAdded = config.optimizeDeps.esbuildOptions.plugins.some(\n      (plugin: EsbuildPlugin) => plugin.name === pluginName,\n    );\n\n    if (!isPluginAdded) {\n      config.optimizeDeps.esbuildOptions.plugins.push(\n        esbuildPluginExternalize(options.externals),\n      );\n    }\n    return null;\n  },\n  configResolved: (resolvedConfig: ResolvedConfig) => {\n    // Plugins are read-only, and should not be modified,\n    // however modulePrefixTransformPlugin MUST run after vite:import-analysis (which adds the prefix to imports)\n\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore\n    // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n    resolvedConfig.plugins.push(\n      modulePrefixTransform({ base: resolvedConfig.base ?? \"/\" }),\n    );\n  },\n  // Supresses the following warning:\n  // Failed to resolve import [dependency] from [sourceFile]. Does the file exist?\n  resolveId: (id: string) => {\n    if (resolvedExternals.has(id)) {\n      return { id, external: true };\n    }\n\n    // During subsequent runs after the dependency optimization is completed, esbuild plugin might not be called.\n    // This will cause the resolvedExternals to be empty, and the plugin will not be able to resolve the external modules, which is why a direct check is required.\n    if (isExternal(id, options.externals)) {\n      resolvedExternals.add(id);\n      return { id, external: true };\n    }\n\n    return null;\n  },\n  // Supresses the following warning:\n  // The following dependencies are imported but could not be resolved: [dependency] (imported by [sourceFile])\n  load: (id: string) => {\n    if (resolvedExternals.has(id)) {\n      return { code: \"export default {};\" };\n    }\n    return null;\n  },\n});\n\n// Justification: Vite plugins are expected to provide a default export\n// eslint-disable-next-line import/no-default-export\nexport default vitePluginExternalize;\n"],"names":["resolvedExternals","isExternal","id","externals","external","esbuildPluginExternalize","build","args","modulePrefixTransform","base","code","viteImportAnalysisModulePrefix","prefixedImportRegex","_","externalName","vitePluginExternalize","options","config","_a","_b","pluginName","plugin","resolvedConfig"],"mappings":"aAgBA,MAAMA,MAAwB,IAExBC,EAAa,CAACC,EAAYC,IAC9BA,EAAU,KAAMC,GACV,OAAOA,GAAa,SACfF,IAAOE,GAAYF,EAAG,WAAW,GAAGE,CAAQ,GAAG,EAGpDA,aAAoB,OACfA,EAAS,KAAKF,CAAE,EAGrB,OAAOE,GAAa,WACfA,EAASF,CAAE,EAGb,EACR,EAWGG,EACJF,IACmB,CACnB,KAAM,cACN,MAAMG,EAAoB,CACxBA,EAAM,UAAU,CAAE,OAAQ,IAAK,EAAIC,GAE/BN,EAAWM,EAAK,KAAMJ,CAAS,GAC/BI,EAAK,OAAS,oBAEIP,EAAA,IAAIO,EAAK,IAAI,EACxB,CACL,KAAMA,EAAK,KACX,SAAU,EAAA,GAMVN,EAAWM,EAAK,KAAMJ,CAAS,GAAKI,EAAK,OAAS,eAClCP,EAAA,IAAIO,EAAK,IAAI,EACxB,CAAE,KAAMA,EAAK,KAAM,UAAW,sBAAuB,GAGvD,IACR,EAGDD,EAAM,OAAO,CAAE,OAAQ,IAAK,EAAIC,GAC1BN,EAAWM,EAAK,KAAMJ,CAAS,EAC1B,CAAE,SAAU,IAGd,IACR,CACH,CACF,GAUMK,EAAwB,CAAC,CAC7B,KAAAC,CACF,KAAmD,CACjD,KAAM,4BACN,UAAYC,GAAyB,CAEnC,GAAIV,EAAkB,OAAS,EAAU,OAAAU,EAEzC,MAAMC,EAAiC,OACjCC,EAAsB,IAAI,OAC9B,GAAGH,CAAI,GAAGE,CAA8B,IAAI,CAAC,GAAGX,CAAiB,EAAE,KACjE,GACD,CAAA,IACD,GAAA,EAGE,OAAAY,EAAoB,KAAKF,CAAI,EAExBA,EAAK,QACVE,EACA,CAACC,EAAWC,IAAyBA,CAAA,EAGlCJ,CACT,CACF,GAWMK,EAAyBC,IAAoC,CACjE,KAAM,0BACN,QAAS,MACT,MAAO,QACP,OAASC,GAAkE,SACzEA,EAAO,eAAPA,EAAO,aAAiB,KACjBC,EAAAD,EAAA,cAAa,iBAAbC,EAAa,eAAmB,KAChCC,EAAAF,EAAA,aAAa,gBAAe,UAA5BE,EAA4B,QAAY,CAAA,GAG/C,MAAMC,EAAa,cAKnB,OAJsBH,EAAO,aAAa,eAAe,QAAQ,KAC9DI,GAA0BA,EAAO,OAASD,CAAA,GAIpCH,EAAA,aAAa,eAAe,QAAQ,KACzCZ,EAAyBW,EAAQ,SAAS,CAAA,EAGvC,IACT,EACA,eAAiBM,GAAmC,CAOlDA,EAAe,QAAQ,KACrBd,EAAsB,CAAE,KAAMc,EAAe,MAAQ,IAAK,CAAA,CAE9D,EAGA,UAAYpB,GACNF,EAAkB,IAAIE,CAAE,EACnB,CAAE,GAAAA,EAAI,SAAU,IAKrBD,EAAWC,EAAIc,EAAQ,SAAS,GAClChB,EAAkB,IAAIE,CAAE,EACjB,CAAE,GAAAA,EAAI,SAAU,KAGlB,KAIT,KAAOA,GACDF,EAAkB,IAAIE,CAAE,EACnB,CAAE,KAAM,sBAEV,IAEX"}