@driftime/sanity-plugin-icon 0.4.0 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"file":"next-loader.d.ts","names":["LoaderContext","generateRegistryOnce","Promise","generateRegistry","ReturnType","LoaderContext","iconSetsLoader","Promise","default","generateRegistry"],"sources":["../src/build/loader.ts","../src/next-loader.ts"],"mappings":"AAgBA;;;;;UAAiBA;;EAEf;;;;;;EAMA;;;;;;EAMA,iBAAiB;;;;;;EAMjB,wBAAwB;;;;;;;;;;iBAWXC,qBAAqB,sBAAsB,mBAAgBC;;;;;;;;;;;;;;;wBA4EpDC,iBACpB,sBACA,kBACA,oBACCC,kBAAkBH;;;;;;;;;;;iBC/FNK,eAAe,MAAMD,gBAAaE"}
1
+ {"version":3,"file":"next-loader.d.ts","names":["LoaderContext","generateRegistryOnce","Promise","generateRegistry","ReturnType","LoaderContext","iconSetsLoader","Promise","default","generateRegistry"],"sources":["../src/build/loader.ts","../src/next-loader.ts"],"mappings":"AAiBA;;;;;UAAiBA;;EAEf;;;;;;EAMA;;;;;;EAMA,iBAAiB;;;;;;EAMjB,wBAAwB;;;;;;;;;;iBAWXC,qBAAqB,sBAAsB,mBAAgBC;;;;;;;;;;;;;;;wBA+EpDC,iBACpB,sBACA,kBACA,oBACCC,kBAAkBH;;;;;;;;;;;iBCnGNK,eAAe,MAAMD,gBAAaE"}
@@ -1,10 +1,11 @@
1
1
  import { n as logger } from "./sets-kepuObH8.js";
2
2
  import { r as isRecord } from "./utils-COPacfAq.js";
3
- import { t as createRegistryModule } from "./registry-dxVzo7ZX.js";
4
- import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-DVh8eYeP.js";
3
+ import { n as getSetsFolder, t as createRegistryModule } from "./registry-B0Dxiwhh.js";
4
+ import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-D5_YGFll.js";
5
5
  import { i as listPluginFiles, s as readPluginBuild } from "./adapters-Bx_MyEX_.js";
6
6
  import path from "node:path";
7
- import { mkdir, readFile, writeFile } from "node:fs/promises";
7
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
8
+ import { randomUUID } from "node:crypto";
8
9
  /**
9
10
  * Converts every installed library, writes each set to a file the bundler can split into its own chunk, and returns
10
11
  * the registry that replaces the placeholder.
@@ -14,14 +15,14 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
14
15
  * @returns The registry's code, and the files and folders it was generated from.
15
16
  */
16
17
  async function generateRegistryOnce(resourcePath, options) {
17
- let root = process.cwd(), custom = isRecord(options) && isRecord(options.custom) ? options.custom : {}, folders = Object.fromEntries(Object.entries(custom).flatMap(([name, folder]) => typeof folder == "string" ? [[name, folder]] : [])), cacheDir = path.join(root, "node_modules", ".cache"), setsDir = path.join(cacheDir, "driftime-icon", "sets");
18
+ let root = process.cwd(), custom = isRecord(options) && isRecord(options.custom) ? options.custom : {}, folders = Object.fromEntries(Object.entries(custom).flatMap(([name, folder]) => typeof folder == "string" ? [[name, folder]] : [])), cacheDir = path.join(root, "node_modules", ".cache"), setsDir = getSetsFolder(root);
18
19
  await mkdir(setsDir, { recursive: !0 });
19
20
  let libraries = await detectLibraries(root, folders), files = /* @__PURE__ */ new Map(), names = /* @__PURE__ */ new Map(), converted = await Promise.all(libraries.flatMap((library) => library.styles.map(async ({ style }) => {
20
21
  let { adapter } = library, { set, report } = await loadIconSet(library, style, {
21
22
  root,
22
23
  cacheDir
23
- }), file = path.join(setsDir, `${adapter.library}-${style}.json`);
24
- return await writeFile(file, JSON.stringify(set)), logger.info(describeReport(adapter.label, style, report)), {
24
+ }), file = path.join(setsDir, `${adapter.library}-${style}.json`), temporary = `${file}.${randomUUID()}.tmp`;
25
+ return await writeFile(temporary, JSON.stringify(set)), await rename(temporary, file), logger.info(describeReport(adapter.label, style, report)), {
25
26
  library: adapter.library,
26
27
  style,
27
28
  set,
@@ -1 +1 @@
1
- {"version":3,"file":"next-loader.js","names":["mkdir","readFile","writeFile","path","isRecord","writeIconNames","listPluginFiles","createRegistryModule","describeReport","detectLibraries","listRegistryDependencies","loadIconSet","logger","LoaderContext","resourcePath","getOptions","addDependency","file","addContextDependency","folder","generateRegistryOnce","options","root","process","cwd","custom","folders","Object","fromEntries","entries","flatMap","name","cacheDir","join","setsDir","recursive","libraries","files","Map","names","Set","converted","Promise","all","library","styles","map","style","adapter","set","report","JSON","stringify","info","label","libraryNames","get","icon","icons","add","filter","size","code","key","relative","dirname","replaceAll","startsWith","dependencies","readManifest","generateRegistry","attempts","ReturnType","before","result","after","isRecord","LoaderContext","generateRegistry","readPluginBuild","logger","LoaderModule","isLoaderModule","value","iconSetsLoader","this","fresh","import","meta","url","Error","format","code","files","folders","resourcePath","getOptions","file","addDependency","folder","addContextDependency","\"custom\"","\"generateRegistry\""],"sources":["../src/build/loader.ts","../src/next-loader.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { isRecord } from \"@repo/lib/utils\";\n\nimport { writeIconNames } from \"@/build/names\";\nimport { listPluginFiles } from \"@/build/packages\";\nimport { createRegistryModule } from \"@/build/registry\";\nimport { describeReport, detectLibraries, listRegistryDependencies, loadIconSet } from \"@/build/sets\";\nimport { logger } from \"@/config/defaults\";\n\n/**\n * The parts of a webpack or Turbopack loader's context the build step uses.\n *\n * @public\n */\nexport interface LoaderContext {\n /** Path of the module being loaded. */\n resourcePath: string;\n /**\n * Reads the loader's options.\n *\n * @returns The options.\n */\n getOptions: () => unknown;\n /**\n * Tells the bundler to run the loader again when a file changes.\n *\n * @param file - The file.\n */\n addDependency?: (file: string) => void;\n /**\n * Tells the bundler to run the loader again when anything in a folder changes.\n *\n * @param folder - The folder.\n */\n addContextDependency?: (folder: string) => void;\n}\n\n/**\n * Converts every installed library, writes each set to a file the bundler can split into its own chunk, and returns\n * the registry that replaces the placeholder.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @returns The registry's code, and the files and folders it was generated from.\n */\nasync function generateRegistryOnce(resourcePath: string, options: unknown) {\n const root = process.cwd();\n const custom = isRecord(options) && isRecord(options[\"custom\"]) ? options[\"custom\"] : {};\n const folders = Object.fromEntries(\n Object.entries(custom).flatMap(([name, folder]) => (typeof folder === \"string\" ? [[name, folder]] : [])),\n );\n\n const cacheDir = path.join(root, \"node_modules\", \".cache\");\n const setsDir = path.join(cacheDir, \"driftime-icon\", \"sets\");\n await mkdir(setsDir, { recursive: true });\n\n const libraries = await detectLibraries(root, folders);\n const files = new Map<string, string>();\n const names = new Map<string, Set<string>>();\n\n const converted = await Promise.all(\n libraries.flatMap((library) =>\n library.styles.map(async ({ style }) => {\n const { adapter } = library;\n const { set, report } = await loadIconSet(library, style, { root, cacheDir });\n const file = path.join(setsDir, `${adapter.library}-${style}.json`);\n\n await writeFile(file, JSON.stringify(set));\n logger.info(describeReport(adapter.label, style, report));\n\n return { library: adapter.library, style, set, file };\n }),\n ),\n );\n\n for (const { library, style, set, file } of converted) {\n const libraryNames = names.get(library) ?? new Set<string>();\n\n for (const icon of set.icons) libraryNames.add(icon.name);\n names.set(library, libraryNames);\n files.set(`${library}/${style}`, file);\n }\n\n await writeIconNames(new Map([...names].filter(([, libraryNames]) => libraryNames.size > 0)));\n\n const code = createRegistryModule(libraries, (key) => {\n const file = files.get(key) ?? \"\";\n const relative = path.relative(path.dirname(resourcePath), file).replaceAll(\"\\\\\", \"/\");\n\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n });\n\n const dependencies = listRegistryDependencies(root, libraries);\n\n // The plugin's own files are included, so updating it runs the loader again even when `package.json` doesn't change.\n return { code, files: [...dependencies.files, ...(await listPluginFiles())], folders: dependencies.folders };\n}\n\n/**\n * Reads the project's `package.json` as text.\n *\n * @returns The contents, or an empty string when there's no file.\n */\nasync function readManifest() {\n try {\n return await readFile(path.join(process.cwd(), \"package.json\"), \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Generates the registry, running again when the project's `package.json` changes while it runs, so a package\n * installed during a run isn't missed.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @param attempts - Runs allowed, including this one.\n * @returns The registry's code, and the files and folders it was generated from.\n * @public\n */\nexport async function generateRegistry(\n resourcePath: string,\n options: unknown,\n attempts = 3,\n): ReturnType<typeof generateRegistryOnce> {\n const before = await readManifest();\n const result = await generateRegistryOnce(resourcePath, options);\n const after = await readManifest();\n\n return before === after || attempts <= 1 ? result : generateRegistry(resourcePath, options, attempts - 1);\n}\n","import { isRecord } from \"@repo/lib/utils\";\n\nimport type { LoaderContext, generateRegistry } from \"@/build/loader\";\nimport { readPluginBuild } from \"@/build/packages\";\nimport { logger } from \"@/config/defaults\";\n\n/** This module as the loader imports it afresh on every run. */\ninterface LoaderModule {\n /** Generates the registry. */\n generateRegistry: typeof generateRegistry;\n}\n\n/**\n * Checks whether an imported module is a fresh copy of this one.\n *\n * @param value - The imported module.\n * @returns True if the module is this one.\n */\nfunction isLoaderModule(value: unknown): value is LoaderModule {\n return isRecord(value) && typeof value[\"generateRegistry\"] === \"function\";\n}\n\n/**\n * Webpack and Turbopack loader that replaces the placeholder registry with the project's converted icon sets. The\n * bundler keeps this module loaded, so it imports a fresh copy of itself, versioned by the plugin's code, and runs that\n * copy's build step, so updating the plugin takes effect without restarting the bundler.\n *\n * @param this - The loader context.\n * @returns The registry's code.\n * @throws When the plugin's build step can't be loaded.\n * @public\n */\nasync function iconSetsLoader(this: LoaderContext) {\n const fresh: unknown = await import(`${import.meta.url}?version=${await readPluginBuild()}`);\n if (!isLoaderModule(fresh)) throw new Error(logger.format(\"The build step couldn't be loaded.\"));\n\n const { code, files, folders } = await fresh.generateRegistry(this.resourcePath, this.getOptions());\n\n for (const file of files) this.addDependency?.(file);\n for (const folder of folders) this.addContextDependency?.(folder);\n\n return code;\n}\n\nexport default iconSetsLoader;\nexport { generateRegistry } from \"@/build/loader\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"next-loader.js","names":["randomUUID","mkdir","readFile","rename","writeFile","path","isRecord","writeIconNames","listPluginFiles","createRegistryModule","getSetsFolder","describeReport","detectLibraries","listRegistryDependencies","loadIconSet","logger","LoaderContext","resourcePath","getOptions","addDependency","file","addContextDependency","folder","generateRegistryOnce","options","root","process","cwd","custom","folders","Object","fromEntries","entries","flatMap","name","cacheDir","join","setsDir","recursive","libraries","files","Map","names","Set","converted","Promise","all","library","styles","map","style","adapter","set","report","temporary","JSON","stringify","info","label","libraryNames","get","icon","icons","add","filter","size","code","key","relative","dirname","replaceAll","startsWith","dependencies","readManifest","generateRegistry","attempts","ReturnType","before","result","after","isRecord","LoaderContext","generateRegistry","readPluginBuild","logger","LoaderModule","isLoaderModule","value","iconSetsLoader","this","fresh","import","meta","url","Error","format","code","files","folders","resourcePath","getOptions","file","addDependency","folder","addContextDependency","\"custom\"","\"generateRegistry\""],"sources":["../src/build/loader.ts","../src/next-loader.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { isRecord } from \"@repo/lib/utils\";\n\nimport { writeIconNames } from \"@/build/names\";\nimport { listPluginFiles } from \"@/build/packages\";\nimport { createRegistryModule, getSetsFolder } from \"@/build/registry\";\nimport { describeReport, detectLibraries, listRegistryDependencies, loadIconSet } from \"@/build/sets\";\nimport { logger } from \"@/config/defaults\";\n\n/**\n * The parts of a webpack or Turbopack loader's context the build step uses.\n *\n * @public\n */\nexport interface LoaderContext {\n /** Path of the module being loaded. */\n resourcePath: string;\n /**\n * Reads the loader's options.\n *\n * @returns The options.\n */\n getOptions: () => unknown;\n /**\n * Tells the bundler to run the loader again when a file changes.\n *\n * @param file - The file.\n */\n addDependency?: (file: string) => void;\n /**\n * Tells the bundler to run the loader again when anything in a folder changes.\n *\n * @param folder - The folder.\n */\n addContextDependency?: (folder: string) => void;\n}\n\n/**\n * Converts every installed library, writes each set to a file the bundler can split into its own chunk, and returns\n * the registry that replaces the placeholder.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @returns The registry's code, and the files and folders it was generated from.\n */\nasync function generateRegistryOnce(resourcePath: string, options: unknown) {\n const root = process.cwd();\n const custom = isRecord(options) && isRecord(options[\"custom\"]) ? options[\"custom\"] : {};\n const folders = Object.fromEntries(\n Object.entries(custom).flatMap(([name, folder]) => (typeof folder === \"string\" ? [[name, folder]] : [])),\n );\n\n const cacheDir = path.join(root, \"node_modules\", \".cache\");\n const setsDir = getSetsFolder(root);\n await mkdir(setsDir, { recursive: true });\n\n const libraries = await detectLibraries(root, folders);\n const files = new Map<string, string>();\n const names = new Map<string, Set<string>>();\n\n const converted = await Promise.all(\n libraries.flatMap((library) =>\n library.styles.map(async ({ style }) => {\n const { adapter } = library;\n const { set, report } = await loadIconSet(library, style, { root, cacheDir });\n const file = path.join(setsDir, `${adapter.library}-${style}.json`);\n const temporary = `${file}.${randomUUID()}.tmp`;\n\n // The browser and server builds convert at once, even in one process, so each set is swapped in whole.\n await writeFile(temporary, JSON.stringify(set));\n await rename(temporary, file);\n logger.info(describeReport(adapter.label, style, report));\n\n return { library: adapter.library, style, set, file };\n }),\n ),\n );\n\n for (const { library, style, set, file } of converted) {\n const libraryNames = names.get(library) ?? new Set<string>();\n\n for (const icon of set.icons) libraryNames.add(icon.name);\n names.set(library, libraryNames);\n files.set(`${library}/${style}`, file);\n }\n\n await writeIconNames(new Map([...names].filter(([, libraryNames]) => libraryNames.size > 0)));\n\n const code = createRegistryModule(libraries, (key) => {\n const file = files.get(key) ?? \"\";\n const relative = path.relative(path.dirname(resourcePath), file).replaceAll(\"\\\\\", \"/\");\n\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n });\n\n const dependencies = listRegistryDependencies(root, libraries);\n\n // The plugin's own files are included, so updating it runs the loader again even when `package.json` doesn't change.\n return { code, files: [...dependencies.files, ...(await listPluginFiles())], folders: dependencies.folders };\n}\n\n/**\n * Reads the project's `package.json` as text.\n *\n * @returns The contents, or an empty string when there's no file.\n */\nasync function readManifest() {\n try {\n return await readFile(path.join(process.cwd(), \"package.json\"), \"utf8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Generates the registry, running again when the project's `package.json` changes while it runs, so a package\n * installed during a run isn't missed.\n *\n * @param resourcePath - Path of the placeholder being replaced.\n * @param options - The loader's options.\n * @param attempts - Runs allowed, including this one.\n * @returns The registry's code, and the files and folders it was generated from.\n * @public\n */\nexport async function generateRegistry(\n resourcePath: string,\n options: unknown,\n attempts = 3,\n): ReturnType<typeof generateRegistryOnce> {\n const before = await readManifest();\n const result = await generateRegistryOnce(resourcePath, options);\n const after = await readManifest();\n\n return before === after || attempts <= 1 ? result : generateRegistry(resourcePath, options, attempts - 1);\n}\n","import { isRecord } from \"@repo/lib/utils\";\n\nimport type { LoaderContext, generateRegistry } from \"@/build/loader\";\nimport { readPluginBuild } from \"@/build/packages\";\nimport { logger } from \"@/config/defaults\";\n\n/** This module as the loader imports it afresh on every run. */\ninterface LoaderModule {\n /** Generates the registry. */\n generateRegistry: typeof generateRegistry;\n}\n\n/**\n * Checks whether an imported module is a fresh copy of this one.\n *\n * @param value - The imported module.\n * @returns True if the module is this one.\n */\nfunction isLoaderModule(value: unknown): value is LoaderModule {\n return isRecord(value) && typeof value[\"generateRegistry\"] === \"function\";\n}\n\n/**\n * Webpack and Turbopack loader that replaces the placeholder registry with the project's converted icon sets. The\n * bundler keeps this module loaded, so it imports a fresh copy of itself, versioned by the plugin's code, and runs that\n * copy's build step, so updating the plugin takes effect without restarting the bundler.\n *\n * @param this - The loader context.\n * @returns The registry's code.\n * @throws When the plugin's build step can't be loaded.\n * @public\n */\nasync function iconSetsLoader(this: LoaderContext) {\n const fresh: unknown = await import(`${import.meta.url}?version=${await readPluginBuild()}`);\n if (!isLoaderModule(fresh)) throw new Error(logger.format(\"The build step couldn't be loaded.\"));\n\n const { code, files, folders } = await fresh.generateRegistry(this.resourcePath, this.getOptions());\n\n for (const file of files) this.addDependency?.(file);\n for (const folder of folders) this.addContextDependency?.(folder);\n\n return code;\n}\n\nexport default iconSetsLoader;\nexport { generateRegistry } from \"@/build/loader\";\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"next.d.ts","names":["SanityIconBuildOptions","SanityIconWebpackConfig","SanityIconNextConfig","Record","SanityIconWebpackCustomizer","withIcons","Config"],"sources":["../src/build/next.ts"],"mappings":";;;;;;UAmBiBC;;EAEf;IAAW;;;;;;;;UAQIC;;EAEf;IAAc,QAAQC;;;EAEtB,UAAUC;;;;;;;;KASAA,+BAA+B,QAAQH,yBAAyB,mBAAmBA;;;;;;;;;wBAa/EI,UAAU,UAASL,0BAIJ,eAAeE,sBAAoB,QAAUI,WAASA"}
1
+ {"version":3,"file":"next.d.ts","names":["SanityIconBuildOptions","SanityIconWebpackConfig","SanityIconNextConfig","Record","SanityIconWebpackCustomizer","withIcons","Config"],"sources":["../src/build/next.ts"],"mappings":";;;;;;UAoBiBC;;EAEf;IAAW;;;;;;;;UAQIC;;EAEf;IAAc,QAAQC;;;EAEtB,UAAUC;;;;;;;;KASAA,+BAA+B,QAAQH,yBAAyB,mBAAmBA;;;;;;;;;wBAa/EI,UAAU,UAASL,0BAOJ,eAAeE,sBAAoB,QAAUI,WAASA"}
package/dist/next.js CHANGED
@@ -1,5 +1,6 @@
1
- import { n as isRegistryModule, r as registryModulePath } from "./registry-dxVzo7ZX.js";
1
+ import { i as registryModulePath, n as getSetsFolder, r as isRegistryModule } from "./registry-B0Dxiwhh.js";
2
2
  import path from "node:path";
3
+ import { mkdirSync } from "node:fs";
3
4
  import { fileURLToPath } from "node:url";
4
5
  /** Path of the loader, published next to this file. */
5
6
  const loaderPath = fileURLToPath(new URL("next-loader.js", import.meta.url));
@@ -16,7 +17,7 @@ function withIcons(options = {}) {
16
17
  loader: loaderPath,
17
18
  options: { custom: options.custom ?? {} }
18
19
  }, placeholder = path.basename(path.dirname(path.dirname(registryModulePath)));
19
- return function extendConfig(config) {
20
+ return mkdirSync(getSetsFolder(process.cwd()), { recursive: !0 }), function extendConfig(config) {
20
21
  let { turbopack, webpack } = config;
21
22
  return {
22
23
  ...config,
package/dist/next.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"next.js","names":["path","fileURLToPath","isRegistryModule","registryModulePath","SanityIconBuildOptions","WebpackRule","test","resource","use","loader","options","custom","Record","SanityIconWebpackConfig","module","rules","SanityIconNextConfig","turbopack","webpack","SanityIconWebpackCustomizer","config","context","loaderPath","URL","import","meta","url","withIcons","placeholder","basename","dirname","extendConfig","Config","loaders","as","webpackConfig","resolved","rule"],"sources":["../src/build/next.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { isRegistryModule, registryModulePath } from \"@/build/registry\";\nimport type { SanityIconBuildOptions } from \"@/build/vite\";\n\n/** A webpack rule, limited to what the build step adds. */\ninterface WebpackRule {\n /** Matches the placeholder registry. */\n test: (resource: string) => boolean;\n /** The loader that replaces it, with the build step's options. */\n use: { loader: string; options: { custom: Record<string, string> } }[];\n}\n\n/**\n * The parts of a webpack configuration the build step extends.\n *\n * @public\n */\nexport interface SanityIconWebpackConfig {\n /** Module settings, whose rules the build step adds to. */\n module?: { rules?: unknown[] };\n}\n\n/**\n * The parts of a Next.js configuration the build step extends, so the package doesn't depend on Next.js's own types.\n *\n * @public\n */\nexport interface SanityIconNextConfig {\n /** Turbopack settings, whose rules the build step adds to. */\n turbopack?: { rules?: Record<string, unknown> };\n /** Customises webpack, for projects that build with it instead of Turbopack. */\n webpack?: SanityIconWebpackCustomizer | null;\n}\n\n/**\n * Customises webpack, as Next.js's `webpack` option does. The context is typed `never` because the build step only\n * passes Next.js's own context through, so any context type a project's function declares is accepted.\n *\n * @public\n */\nexport type SanityIconWebpackCustomizer = (config: SanityIconWebpackConfig, context: never) => SanityIconWebpackConfig;\n\n/** Path of the loader, published next to this file. */\nconst loaderPath = fileURLToPath(new URL(\"next-loader.js\", import.meta.url));\n\n/**\n * Adds the icon build step to a Next.js configuration, for Studios embedded in a Next.js app. It works with both\n * Turbopack and webpack.\n *\n * @param options - Options for the build step.\n * @returns A function that extends the Next.js configuration.\n * @public\n */\nexport function withIcons(options: SanityIconBuildOptions = {}) {\n const loader = { loader: loaderPath, options: { custom: options.custom ?? {} } };\n const placeholder = path.basename(path.dirname(path.dirname(registryModulePath)));\n\n return function extendConfig<Config extends SanityIconNextConfig>(config: Config): Config {\n const { turbopack, webpack } = config;\n\n return {\n ...config,\n turbopack: {\n ...turbopack,\n rules: { ...turbopack?.rules, [`**/${placeholder}/dist/sets.js`]: { loaders: [loader], as: \"*.js\" } },\n },\n webpack(webpackConfig: SanityIconWebpackConfig, context: never) {\n const resolved = webpack?.(webpackConfig, context) ?? webpackConfig;\n const rule: WebpackRule = { test: isRegistryModule, use: [loader] };\n\n return { ...resolved, module: { ...resolved.module, rules: [...(resolved.module?.rules ?? []), rule] } };\n },\n };\n };\n}\n"],"mappings":";;;;AA6CA,MAAMsB,aAAarB,cAAc,IAAIsB,IAAI,kBAAkBC,YAAYE,GAAG,CAAC;;;;;;;;;AAU3E,SAAgBC,UAAUjB,UAAkC,CAAC,GAAG;CAC9D,IAAMD,SAAS;EAAEA,QAAQa;EAAYZ,SAAS,EAAEC,QAAQD,QAAQC,UAAU,CAAC,EAAE;CAAE,GACzEiB,cAAc5B,KAAK6B,SAAS7B,KAAK8B,QAAQ9B,KAAK8B,QAAQ3B,kBAAkB,CAAC,CAAC;CAEhF,OAAO,SAAS4B,aAAkDX,QAAwB;EACxF,IAAM,EAAEH,WAAWC,YAAYE;EAE/B,OAAO;GACL,GAAGA;GACHH,WAAW;IACT,GAAGA;IACHF,OAAO;KAAE,GAAGE,WAAWF;MAAQ,MAAMa,YAAW,iBAAkB;MAAEK,SAAS,CAACxB,MAAM;MAAGyB,IAAI;KAAO;IAAE;GACtG;GACAhB,QAAQiB,eAAwCd,SAAgB;IAC9D,IAAMe,WAAWlB,UAAUiB,eAAed,OAAO,KAAKc,eAChDE,OAAoB;KAAE/B,MAAMJ;KAAkBM,KAAK,CAACC,MAAM;IAAE;IAElE,OAAO;KAAE,GAAG2B;KAAUtB,QAAQ;MAAE,GAAGsB,SAAStB;MAAQC,OAAO,CAAC,GAAIqB,SAAStB,QAAQC,SAAS,CAAA,GAAKsB,IAAI;KAAE;IAAE;GACzG;EACF;CACF;AACF"}
1
+ {"version":3,"file":"next.js","names":["mkdirSync","path","fileURLToPath","getSetsFolder","isRegistryModule","registryModulePath","SanityIconBuildOptions","WebpackRule","test","resource","use","loader","options","custom","Record","SanityIconWebpackConfig","module","rules","SanityIconNextConfig","turbopack","webpack","SanityIconWebpackCustomizer","config","context","loaderPath","URL","import","meta","url","withIcons","placeholder","basename","dirname","process","cwd","recursive","extendConfig","Config","loaders","as","webpackConfig","resolved","rule"],"sources":["../src/build/next.ts"],"sourcesContent":["import { mkdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { getSetsFolder, isRegistryModule, registryModulePath } from \"@/build/registry\";\nimport type { SanityIconBuildOptions } from \"@/build/vite\";\n\n/** A webpack rule, limited to what the build step adds. */\ninterface WebpackRule {\n /** Matches the placeholder registry. */\n test: (resource: string) => boolean;\n /** The loader that replaces it, with the build step's options. */\n use: { loader: string; options: { custom: Record<string, string> } }[];\n}\n\n/**\n * The parts of a webpack configuration the build step extends.\n *\n * @public\n */\nexport interface SanityIconWebpackConfig {\n /** Module settings, whose rules the build step adds to. */\n module?: { rules?: unknown[] };\n}\n\n/**\n * The parts of a Next.js configuration the build step extends, so the package doesn't depend on Next.js's own types.\n *\n * @public\n */\nexport interface SanityIconNextConfig {\n /** Turbopack settings, whose rules the build step adds to. */\n turbopack?: { rules?: Record<string, unknown> };\n /** Customises webpack, for projects that build with it instead of Turbopack. */\n webpack?: SanityIconWebpackCustomizer | null;\n}\n\n/**\n * Customises webpack, as Next.js's `webpack` option does. The context is typed `never` because the build step only\n * passes Next.js's own context through, so any context type a project's function declares is accepted.\n *\n * @public\n */\nexport type SanityIconWebpackCustomizer = (config: SanityIconWebpackConfig, context: never) => SanityIconWebpackConfig;\n\n/** Path of the loader, published next to this file. */\nconst loaderPath = fileURLToPath(new URL(\"next-loader.js\", import.meta.url));\n\n/**\n * Adds the icon build step to a Next.js configuration, for Studios embedded in a Next.js app. It works with both\n * Turbopack and webpack.\n *\n * @param options - Options for the build step.\n * @returns A function that extends the Next.js configuration.\n * @public\n */\nexport function withIcons(options: SanityIconBuildOptions = {}) {\n const loader = { loader: loaderPath, options: { custom: options.custom ?? {} } };\n const placeholder = path.basename(path.dirname(path.dirname(registryModulePath)));\n\n // Turbopack never finds files in a folder that was missing when the build started, so it's made before then.\n mkdirSync(getSetsFolder(process.cwd()), { recursive: true });\n\n return function extendConfig<Config extends SanityIconNextConfig>(config: Config): Config {\n const { turbopack, webpack } = config;\n\n return {\n ...config,\n turbopack: {\n ...turbopack,\n rules: { ...turbopack?.rules, [`**/${placeholder}/dist/sets.js`]: { loaders: [loader], as: \"*.js\" } },\n },\n webpack(webpackConfig: SanityIconWebpackConfig, context: never) {\n const resolved = webpack?.(webpackConfig, context) ?? webpackConfig;\n const rule: WebpackRule = { test: isRegistryModule, use: [loader] };\n\n return { ...resolved, module: { ...resolved.module, rules: [...(resolved.module?.rules ?? []), rule] } };\n },\n };\n };\n}\n"],"mappings":";;;;;AA8CA,MAAMwB,aAAatB,cAAc,IAAIuB,IAAI,kBAAkBC,YAAYE,GAAG,CAAC;;;;;;;;;AAU3E,SAAgBC,UAAUjB,UAAkC,CAAC,GAAG;CAC9D,IAAMD,SAAS;EAAEA,QAAQa;EAAYZ,SAAS,EAAEC,QAAQD,QAAQC,UAAU,CAAC,EAAE;CAAE,GACzEiB,cAAc7B,KAAK8B,SAAS9B,KAAK+B,QAAQ/B,KAAK+B,QAAQ3B,kBAAkB,CAAC,CAAC;CAKhF,OAFAL,UAAUG,cAAc8B,QAAQC,IAAI,CAAC,GAAG,EAAEC,WAAW,GAAK,CAAC,GAEpD,SAASC,aAAkDd,QAAwB;EACxF,IAAM,EAAEH,WAAWC,YAAYE;EAE/B,OAAO;GACL,GAAGA;GACHH,WAAW;IACT,GAAGA;IACHF,OAAO;KAAE,GAAGE,WAAWF;MAAQ,MAAMa,YAAW,iBAAkB;MAAEQ,SAAS,CAAC3B,MAAM;MAAG4B,IAAI;KAAO;IAAE;GACtG;GACAnB,QAAQoB,eAAwCjB,SAAgB;IAC9D,IAAMkB,WAAWrB,UAAUoB,eAAejB,OAAO,KAAKiB,eAChDE,OAAoB;KAAElC,MAAMJ;KAAkBM,KAAK,CAACC,MAAM;IAAE;IAElE,OAAO;KAAE,GAAG8B;KAAUzB,QAAQ;MAAE,GAAGyB,SAASzB;MAAQC,OAAO,CAAC,GAAIwB,SAASzB,QAAQC,SAAS,CAAA,GAAKyB,IAAI;KAAE;IAAE;GACzG;EACF;CACF;AACF"}
@@ -1,5 +1,6 @@
1
1
  import { n as isDefined } from "./utils-COPacfAq.js";
2
2
  import { t as getIconSetKey } from "./registry-BEEpqK3z.js";
3
+ import path from "node:path";
3
4
  import { realpathSync } from "node:fs";
4
5
  import { fileURLToPath } from "node:url";
5
6
  /**
@@ -31,6 +32,15 @@ function isRegistryModule(id) {
31
32
  return isDefined(file) && resolveRealPath(file) === registryModulePath;
32
33
  }
33
34
  /**
35
+ * Works out the folder the Next.js build step writes converted sets to, inside the project's `node_modules`.
36
+ *
37
+ * @param root - The project's folder.
38
+ * @returns The folder's path.
39
+ */
40
+ function getSetsFolder(root) {
41
+ return path.join(root, "node_modules", ".cache", "driftime-icon", "sets");
42
+ }
43
+ /**
34
44
  * Writes the module that replaces the placeholder registry, with a loader for each installed library style, so each
35
45
  * set is only downloaded when a picker for it opens.
36
46
  *
@@ -53,6 +63,6 @@ function createRegistryModule(libraries, importFor) {
53
63
  }]));
54
64
  return [`const sets = {\n ${loaders.join(",\n ")}\n};`, `export const iconRegistry = { ready: true, sets, libraries: ${JSON.stringify(info)} };`].join("\n");
55
65
  }
56
- export { isRegistryModule as n, registryModulePath as r, createRegistryModule as t };
66
+ export { registryModulePath as i, getSetsFolder as n, isRegistryModule as r, createRegistryModule as t };
57
67
 
58
- //# sourceMappingURL=registry-dxVzo7ZX.js.map
68
+ //# sourceMappingURL=registry-B0Dxiwhh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-B0Dxiwhh.js","names":["realpathSync","path","fileURLToPath","isDefined","DetectedLibrary","getIconSetKey","IconLibraryInfo","resolveRealPath","file","registryModulePath","URL","import","meta","url","isRegistryModule","id","split","getSetsFolder","root","join","createRegistryModule","libraries","importFor","key","loaders","flatMap","adapter","styles","map","style","library","JSON","stringify","info","Record","Object","fromEntries","listed","sitePackage","label","packageName","packageExample","packagePrefix","installed"],"sources":["../src/build/registry.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport type { DetectedLibrary } from \"@/build/sets\";\nimport { getIconSetKey } from \"@/lib/registry\";\nimport type { IconLibraryInfo } from \"@/lib/sets\";\n\n/**\n * Resolves symbolic links in a path, so a package linked into `node_modules` matches its real location.\n *\n * @param file - The path.\n * @returns The real path, or the path unchanged when it doesn't exist.\n */\nfunction resolveRealPath(file: string) {\n try {\n return realpathSync(file);\n } catch {\n return file;\n }\n}\n\n/**\n * Path of the placeholder registry module the Studio imports, which the build step replaces. The build step's own\n * code is published next to it, so the path is found from this file's location.\n */\nexport const registryModulePath = resolveRealPath(fileURLToPath(new URL(\"sets.js\", import.meta.url)));\n\n/**\n * Checks whether a module the bundler is loading is the placeholder registry.\n *\n * @param id - The module's path, possibly followed by a query.\n * @returns Whether it's the placeholder.\n */\nexport function isRegistryModule(id: string) {\n const [file] = id.split(\"?\");\n\n return isDefined(file) && resolveRealPath(file) === registryModulePath;\n}\n\n/**\n * Works out the folder the Next.js build step writes converted sets to, inside the project's `node_modules`.\n *\n * @param root - The project's folder.\n * @returns The folder's path.\n */\nexport function getSetsFolder(root: string) {\n return path.join(root, \"node_modules\", \".cache\", \"driftime-icon\", \"sets\");\n}\n\n/**\n * Writes the module that replaces the placeholder registry, with a loader for each installed library style, so each\n * set is only downloaded when a picker for it opens.\n *\n * @param libraries - Every library the build step knows.\n * @param importFor - The specifier the bundler imports a set from, given its key.\n * @returns The module's code.\n */\nexport function createRegistryModule(libraries: DetectedLibrary[], importFor: (key: string) => string) {\n const loaders = libraries.flatMap(({ adapter, styles }) =>\n styles.map(({ style }) => {\n const key = getIconSetKey(adapter.library, style);\n\n return `${JSON.stringify(key)}: () => import(${JSON.stringify(importFor(key))})`;\n }),\n );\n\n const info: Record<string, IconLibraryInfo> = Object.fromEntries(\n libraries.map(({ adapter, styles, listed, sitePackage }) => [\n adapter.library,\n {\n label: adapter.label,\n packageName: adapter.packageName ?? adapter.packageExample ?? adapter.library,\n ...(isDefined(adapter.packagePrefix) && { packagePrefix: adapter.packagePrefix }),\n styles: isDefined(styles) ? styles.map(({ style }) => style) : adapter.styles,\n listed,\n installed: isDefined(styles),\n ...(isDefined(sitePackage) && { sitePackage }),\n },\n ]),\n );\n\n return [\n `const sets = {\\n ${loaders.join(\",\\n \")}\\n};`,\n `export const iconRegistry = { ready: true, sets, libraries: ${JSON.stringify(info)} };`,\n ].join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAASO,gBAAgBC,MAAc;CACrC,IAAI;EACF,OAAOR,aAAaQ,IAAI;CAC1B,QAAQ;EACN,OAAOA;CACT;AACF;;;;;AAMA,MAAaC,qBAAqBF,gBAAgBL,cAAc,IAAIQ,IAAI,WAAWC,YAAYE,GAAG,CAAC,CAAC;;;;;;;AAQpG,SAAgBC,iBAAiBC,IAAY;CAC3C,IAAM,CAACP,QAAQO,GAAGC,MAAM,GAAG;CAE3B,OAAOb,UAAUK,IAAI,KAAKD,gBAAgBC,IAAI,MAAMC;AACtD;;;;;;;AAQA,SAAgBQ,cAAcC,MAAc;CAC1C,OAAOjB,KAAKkB,KAAKD,MAAM,gBAAgB,UAAU,iBAAiB,MAAM;AAC1E;;;;;;;;;AAUA,SAAgBE,qBAAqBC,WAA8BC,WAAoC;CACrG,IAAME,UAAUH,UAAUI,SAAS,EAAEC,SAASC,aAC5CA,OAAOC,KAAK,EAAEC,YAAY;EACxB,IAAMN,MAAMlB,cAAcqB,QAAQI,SAASD,KAAK;EAEhD,OAAO,GAAGE,KAAKC,UAAUT,GAAG,EAAC,iBAAkBQ,KAAKC,UAAUV,UAAUC,GAAG,CAAC,EAAC;CAC/E,CAAC,CACH,GAEMU,OAAwCE,OAAOC,YACnDf,UAAUO,KAAK,EAAEF,SAASC,QAAQU,QAAQC,kBAAkB,CAC1DZ,QAAQI,SACR;EACES,OAAOb,QAAQa;EACfC,aAAad,QAAQc,eAAed,QAAQe,kBAAkBf,QAAQI;EACtE,GAAI3B,UAAUuB,QAAQgB,aAAa,KAAK,EAAEA,eAAehB,QAAQgB,cAAc;EAC/Ef,QAAQxB,UAAUwB,MAAM,IAAIA,OAAOC,KAAK,EAAEC,YAAYA,KAAK,IAAIH,QAAQC;EACvEU;EACAM,WAAWxC,UAAUwB,MAAM;EAC3B,GAAIxB,UAAUmC,WAAW,KAAK,EAAEA,YAAY;CAC9C,CAAC,CACF,CACH;CAEA,OAAO,CACL,qBAAqBd,QAAQL,KAAK,OAAO,EAAC,OAC1C,+DAA+DY,KAAKC,UAAUC,IAAI,EAAC,IAAK,CACzF,CAACd,KAAK,IAAI;AACb"}
@@ -1,6 +1,6 @@
1
1
  import { r as pluginName, t as parseIconSet } from "./sets-kepuObH8.js";
2
2
  import { n as isDefined, r as isRecord } from "./utils-COPacfAq.js";
3
- import { r as registryModulePath } from "./registry-dxVzo7ZX.js";
3
+ import { i as registryModulePath } from "./registry-B0Dxiwhh.js";
4
4
  import { a as readDeclaredPackages, c as convertIcon, n as createCustomAdapter, o as readJson, r as findPackage, s as readPluginBuild, t as iconAdapters } from "./adapters-Bx_MyEX_.js";
5
5
  import path from "node:path";
6
6
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
@@ -255,4 +255,4 @@ function describeReport(label, style, report) {
255
255
  }
256
256
  export { writeIconNames as a, loadIconSet as i, detectLibraries as n, listRegistryDependencies as r, describeReport as t };
257
257
 
258
- //# sourceMappingURL=sets-DVh8eYeP.js.map
258
+ //# sourceMappingURL=sets-D5_YGFll.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sets-DVh8eYeP.js","names":["readFile","rename","writeFile","path","isDefined","registryModulePath","pluginName","namesFile","join","dirname","writeIconNames","names","Map","Set","entries","toSorted","first","second","localeCompare","map","library","icons","union","name","JSON","stringify","content","current","catch","temporary","process","pid","once","mkdir","writeFile","path","Worker","isDefined","isRecord","createCustomAdapter","iconAdapters","IconAdapter","SourceIcon","convertIcon","InstalledPackage","findPackage","readDeclaredPackages","readJson","readPluginBuild","IconSet","IconSetIcon","parseIconSet","IconSetReport","total","skipped","name","reason","duration","DetectedStyle","style","installed","DetectedLibrary","adapter","styles","listed","sitePackage","folder","IconSetContext","root","cacheDir","detectLibraries","custom","Record","Promise","declared","known","all","map","packageName","packagePrefix","packagePattern","names","filter","startsWith","toSorted","found","slice","length","flat","has","undefined","find","test","folders","Object","entries","library","directory","resolve","version","findCommonRoot","icons","NonNullable","counts","Map","count","key","JSON","stringify","set","get","common","values","first","second","isSourceIcon","value","keywords","svg","Array","isArray","every","keyword","readSources","candidate","worker","URL","import","meta","url","workerData","env","process","NODE_ENV","received","sources","source","terminate","convertIconSet","started","performance","now","report","converted","icon","problem","push","iconRoot","Math","round","parseReport","flatMap","entry","loadIconSet","context","cacheable","cacheFile","join","replaceAll","cached","dirname","recursive","listRegistryDependencies","libraries","files","describeReport","label","kept","toLocaleString","timing","summary","shown","hidden","more","\"total\"","\"skipped\"","\"name\"","\"reason\"","\"set\"","\"report\""],"sources":["../src/build/names.ts","../src/build/sets.ts"],"sourcesContent":["import { readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport { registryModulePath } from \"@/build/registry\";\nimport { pluginName } from \"@/config/defaults\";\n\n/** Types file the plugin reads icon names from, published next to the placeholder registry. */\nconst namesFile = path.join(path.dirname(registryModulePath), \"names.d.ts\");\n\n/**\n * Writes the installed icon names into the plugin's own types, so options that list icons are checked against them.\n * The file is replaced rather than edited, because pnpm shares a package's files between projects.\n *\n * @param names - Icon names keyed by library.\n */\nexport async function writeIconNames(names: Map<string, Set<string>>) {\n const entries = [...names]\n .toSorted(([first], [second]) => first.localeCompare(second))\n .map(([library, icons]) => {\n const union = [...icons].toSorted().map((name) => JSON.stringify(name));\n\n return ` ${JSON.stringify(library)}: ${isDefined(union) ? union.join(\" | \") : \"never\"};`;\n });\n\n const content = [\n `// Written by ${pluginName}'s build step from the project's installed icon libraries.`,\n \"export type SanityIconNames = {\",\n ...entries,\n \"};\",\n \"\",\n ].join(\"\\n\");\n\n const current = await readFile(namesFile, \"utf8\").catch(() => \"\");\n if (current === content) return;\n\n const temporary = `${namesFile}.${process.pid}.tmp`;\n await writeFile(temporary, content);\n await rename(temporary, namesFile);\n}\n","import { once } from \"node:events\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Worker } from \"node:worker_threads\";\n\nimport { isDefined, isRecord } from \"@repo/lib/utils\";\n\nimport { createCustomAdapter } from \"@/build/adapters/custom\";\nimport { iconAdapters } from \"@/build/adapters/index\";\nimport type { IconAdapter } from \"@/build/adapters/types\";\nimport type { SourceIcon } from \"@/build/convert\";\nimport { convertIcon } from \"@/build/convert\";\nimport type { InstalledPackage } from \"@/build/packages\";\nimport { findPackage, readDeclaredPackages, readJson, readPluginBuild } from \"@/build/packages\";\nimport type { IconSet, IconSetIcon } from \"@/lib/sets\";\nimport { parseIconSet } from \"@/lib/sets\";\n\n/** What happened converting a set, for the build's log. */\nexport interface IconSetReport {\n /** Icons the library ships in the style. */\n total: number;\n /** Icons skipped, with why. */\n skipped: { name: string; reason: string }[];\n /** Time the conversion took, in milliseconds, or 0 when it came from the cache. */\n duration: number;\n}\n\n/** One installed style of a library, and the package it's read from. */\nexport interface DetectedStyle {\n /** Identifier of the style. */\n style: string;\n /** The package the style is read from. */\n installed: InstalledPackage;\n}\n\n/** A library found in the project, and where each of its styles is installed. */\nexport interface DetectedLibrary {\n /** How to read the library. */\n adapter: IconAdapter;\n /** The styles the project has installed, empty when it has none. */\n styles: DetectedStyle[];\n /** Whether the project's `package.json` lists the package the library is read from, installed or not. */\n listed: boolean;\n /**\n * Another package of the library the project lists, such as its React version, or undefined when there's none or the\n * library's own package is listed.\n */\n sitePackage?: string;\n /** Folder of the project's own icons, relative to the project, or undefined for a known library. */\n folder?: string;\n}\n\n/** Where the build step reads libraries from and caches conversions. */\nexport interface IconSetContext {\n /** The project folder. */\n root: string;\n /** Folder for cached conversions, or undefined to convert every time. */\n cacheDir: string | undefined;\n}\n\n/**\n * Finds every library the project can use: known libraries whose package it lists and has installed, and its own icon\n * folders. Only listed packages count, so a package that's only there because another one depends on it is ignored.\n *\n * @param root - The project folder.\n * @param custom - The project's own icon folders, keyed by identifier.\n * @returns Every library the build step knows, with where it's installed.\n */\nexport async function detectLibraries(root: string, custom: Record<string, string> = {}): Promise<DetectedLibrary[]> {\n const declared = await readDeclaredPackages(root);\n\n const known = await Promise.all(\n iconAdapters.map(async (adapter) => {\n const { packageName, packagePrefix, packagePattern } = adapter;\n\n if (isDefined(packagePrefix)) {\n const names = [...declared].filter((name) => name.startsWith(packagePrefix)).toSorted();\n const found = await Promise.all(\n names.map(async (name) => {\n const installed = await findPackage(root, name);\n\n return isDefined(installed) ? [{ style: name.slice(packagePrefix.length), installed }] : [];\n }),\n );\n\n return { adapter, styles: found.flat(), listed: isDefined(names) };\n }\n\n const listed = isDefined(packageName) && declared.has(packageName);\n const installed = listed ? await findPackage(root, packageName) : undefined;\n const styles = isDefined(installed) ? adapter.styles.map((style) => ({ style, installed })) : [];\n const sitePackage =\n listed || !isDefined(packagePattern)\n ? undefined\n : [...declared].toSorted().find((name) => packagePattern.test(name));\n\n return { adapter, styles, listed, ...(isDefined(sitePackage) && { sitePackage }) };\n }),\n );\n\n const folders = Object.entries(custom).map(([library, folder]) => ({\n adapter: createCustomAdapter(library, folder),\n listed: true,\n folder,\n styles: [\n { style: \"default\", installed: { name: library, directory: path.resolve(root, folder), version: \"custom\" } },\n ],\n }));\n\n return [...known, ...folders];\n}\n\n/**\n * Picks the root most icons in a set share, so only the others need their own.\n *\n * @param icons - The converted icons.\n * @returns The most common root.\n */\nfunction findCommonRoot(icons: (IconSetIcon & { root: NonNullable<IconSetIcon[\"root\"]> })[]) {\n const counts = new Map<string, { root: IconSet[\"root\"]; count: number }>();\n\n for (const { root } of icons) {\n const key = JSON.stringify(root);\n counts.set(key, { root, count: (counts.get(key)?.count ?? 0) + 1 });\n }\n\n const [common] = [...counts.values()].toSorted((first, second) => second.count - first.count);\n\n return common?.root ?? {};\n}\n\n/**\n * Checks whether a value is an icon as a worker read it from its library.\n *\n * @param value - The value to check.\n * @returns True if the value is a source icon.\n */\nfunction isSourceIcon(value: unknown): value is SourceIcon {\n if (!isRecord(value)) return false;\n\n const { name, keywords, svg } = value;\n\n return (\n typeof name === \"string\" &&\n Array.isArray(keywords) &&\n keywords.every((keyword) => typeof keyword === \"string\") &&\n typeof svg === \"string\"\n );\n}\n\n/**\n * Reads a library's icons in a fresh worker thread. A long-running bundler keeps every module it has imported, so an\n * icon package updated in place would otherwise be read from the old copy.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to read.\n * @param root - The project folder.\n * @returns The icons as the library ships them.\n */\nasync function readSources(library: DetectedLibrary, style: string, root: string) {\n const { adapter, folder } = library;\n const installed = library.styles.find((candidate) => candidate.style === style)?.installed;\n if (!isDefined(installed)) return [];\n\n const worker = new Worker(new URL(\"read-worker.js\", import.meta.url), {\n workerData: { library: adapter.library, folder, style, root, directory: installed.directory },\n // Libraries' components render with React's production build, which writes the same markup without warnings.\n env: { ...process.env, NODE_ENV: \"production\" },\n });\n\n try {\n const received: unknown[] = await once(worker, \"message\");\n const [sources] = received;\n\n return Array.isArray(sources) ? sources.filter((source) => isSourceIcon(source)) : [];\n } finally {\n void worker.terminate();\n }\n}\n\n/**\n * Converts one style of a library into a set, reporting anything skipped.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to convert.\n * @param root - The project folder.\n * @returns The set and its report.\n */\nasync function convertIconSet(library: DetectedLibrary, style: string, root: string) {\n const { adapter } = library;\n const started = performance.now();\n const sources = await readSources(library, style, root);\n\n const report: IconSetReport = { total: sources.length, skipped: [], duration: 0 };\n const converted: (IconSetIcon & { root: NonNullable<IconSetIcon[\"root\"]> })[] = [];\n\n for (const source of sources) {\n const { icon, problem } = convertIcon(source);\n\n if (isDefined(icon)) converted.push(icon);\n else if (isDefined(problem)) report.skipped.push({ name: source.name, reason: problem });\n }\n\n const common = findCommonRoot(converted);\n const set: IconSet = {\n library: adapter.library,\n style,\n root: common,\n icons: converted.map(({ root: iconRoot, ...icon }) =>\n JSON.stringify(iconRoot) === JSON.stringify(common) ? icon : { ...icon, root: iconRoot },\n ),\n };\n\n report.duration = Math.round(performance.now() - started);\n\n return { set, report };\n}\n\n/**\n * Reads a cached conversion's report.\n *\n * @param value - The cached report.\n * @returns The report, or undefined when the value isn't one.\n */\nfunction parseReport(value: unknown): IconSetReport | undefined {\n if (!isRecord(value) || typeof value[\"total\"] !== \"number\" || !Array.isArray(value[\"skipped\"])) return undefined;\n\n const skipped = value[\"skipped\"].flatMap((entry: unknown) =>\n isRecord(entry) && typeof entry[\"name\"] === \"string\" && typeof entry[\"reason\"] === \"string\"\n ? [{ name: entry[\"name\"], reason: entry[\"reason\"] }]\n : [],\n );\n\n return { total: value[\"total\"], skipped, duration: 0 };\n}\n\n/**\n * Loads a converted set, from the cache when the same package version was converted before.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to load.\n * @param context - The project folder and cache folder.\n * @returns The set and its report.\n */\nexport async function loadIconSet(library: DetectedLibrary, style: string, context: IconSetContext) {\n const { adapter, folder } = library;\n const installed = library.styles.find((candidate) => candidate.style === style)?.installed;\n const cacheable = isDefined(context.cacheDir) && isDefined(installed) && !isDefined(folder);\n const cacheFile =\n cacheable && isDefined(context.cacheDir)\n ? path.join(\n context.cacheDir,\n \"driftime-icon\",\n `${adapter.library}-${style}-${installed.name.replaceAll(/[@/]/gu, \"_\")}-${installed.version}-${await readPluginBuild()}.json`,\n )\n : undefined;\n\n if (isDefined(cacheFile)) {\n const cached = await readJson(cacheFile);\n const set = isRecord(cached) ? parseIconSet(cached[\"set\"]) : undefined;\n const report = isRecord(cached) ? parseReport(cached[\"report\"]) : undefined;\n\n if (isDefined(set) && isDefined(report)) return { set, report };\n }\n\n const { set, report } = await convertIconSet(library, style, context.root);\n\n if (isDefined(cacheFile)) {\n await mkdir(path.dirname(cacheFile), { recursive: true });\n await writeFile(cacheFile, JSON.stringify({ set, report }));\n }\n\n return { set, report };\n}\n\n/**\n * Lists the files the registry is generated from, so the bundler regenerates it when a library is installed, removed,\n * or updated, instead of keeping a cached copy.\n *\n * @param root - The project folder.\n * @param libraries - Every library the build step knows.\n * @returns The files, and the folders of the project's own icons.\n */\nexport function listRegistryDependencies(root: string, libraries: DetectedLibrary[]) {\n const files = [path.join(root, \"package.json\")];\n const folders: string[] = [];\n\n for (const { styles, folder } of libraries) {\n for (const { installed } of styles) {\n if (isDefined(folder)) folders.push(installed.directory);\n else files.push(path.join(installed.directory, \"package.json\"));\n }\n }\n\n return { files, folders };\n}\n\n/**\n * Summarises a set's conversion for the build's log, listing the first few icons it skipped and why.\n *\n * @param label - Readable name of the library.\n * @param style - The style converted.\n * @param report - What happened.\n * @returns The summary, one line per skipped icon after the first.\n */\nexport function describeReport(label: string, style: string, report: IconSetReport) {\n const { total, skipped, duration } = report;\n const kept = total - skipped.length;\n const count = `${kept.toLocaleString(\"en-US\")} ${kept === 1 ? \"icon\" : \"icons\"}`;\n const timing = duration > 0 ? `converted in ${duration.toLocaleString(\"en-US\")} ms` : \"loaded from the cache\";\n const summary = `${label} (\\`${style}\\`): ${count} ${timing}`;\n if (!isDefined(skipped)) return `${summary}.`;\n\n const shown = skipped.slice(0, 5).map(({ name, reason }) => ` \\`${name}\\` ${reason}.`);\n const hidden = skipped.length - shown.length;\n const more = hidden > 0 ? [` …and ${hidden.toLocaleString(\"en-US\")} more.`] : [];\n\n return [`${summary}, ${skipped.length.toLocaleString(\"en-US\")} skipped:`, ...shown, ...more].join(\"\\n\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sets-D5_YGFll.js","names":["readFile","rename","writeFile","path","isDefined","registryModulePath","pluginName","namesFile","join","dirname","writeIconNames","names","Map","Set","entries","toSorted","first","second","localeCompare","map","library","icons","union","name","JSON","stringify","content","current","catch","temporary","process","pid","once","mkdir","writeFile","path","Worker","isDefined","isRecord","createCustomAdapter","iconAdapters","IconAdapter","SourceIcon","convertIcon","InstalledPackage","findPackage","readDeclaredPackages","readJson","readPluginBuild","IconSet","IconSetIcon","parseIconSet","IconSetReport","total","skipped","name","reason","duration","DetectedStyle","style","installed","DetectedLibrary","adapter","styles","listed","sitePackage","folder","IconSetContext","root","cacheDir","detectLibraries","custom","Record","Promise","declared","known","all","map","packageName","packagePrefix","packagePattern","names","filter","startsWith","toSorted","found","slice","length","flat","has","undefined","find","test","folders","Object","entries","library","directory","resolve","version","findCommonRoot","icons","NonNullable","counts","Map","count","key","JSON","stringify","set","get","common","values","first","second","isSourceIcon","value","keywords","svg","Array","isArray","every","keyword","readSources","candidate","worker","URL","import","meta","url","workerData","env","process","NODE_ENV","received","sources","source","terminate","convertIconSet","started","performance","now","report","converted","icon","problem","push","iconRoot","Math","round","parseReport","flatMap","entry","loadIconSet","context","cacheable","cacheFile","join","replaceAll","cached","dirname","recursive","listRegistryDependencies","libraries","files","describeReport","label","kept","toLocaleString","timing","summary","shown","hidden","more","\"total\"","\"skipped\"","\"name\"","\"reason\"","\"set\"","\"report\""],"sources":["../src/build/names.ts","../src/build/sets.ts"],"sourcesContent":["import { readFile, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport { registryModulePath } from \"@/build/registry\";\nimport { pluginName } from \"@/config/defaults\";\n\n/** Types file the plugin reads icon names from, published next to the placeholder registry. */\nconst namesFile = path.join(path.dirname(registryModulePath), \"names.d.ts\");\n\n/**\n * Writes the installed icon names into the plugin's own types, so options that list icons are checked against them.\n * The file is replaced rather than edited, because pnpm shares a package's files between projects.\n *\n * @param names - Icon names keyed by library.\n */\nexport async function writeIconNames(names: Map<string, Set<string>>) {\n const entries = [...names]\n .toSorted(([first], [second]) => first.localeCompare(second))\n .map(([library, icons]) => {\n const union = [...icons].toSorted().map((name) => JSON.stringify(name));\n\n return ` ${JSON.stringify(library)}: ${isDefined(union) ? union.join(\" | \") : \"never\"};`;\n });\n\n const content = [\n `// Written by ${pluginName}'s build step from the project's installed icon libraries.`,\n \"export type SanityIconNames = {\",\n ...entries,\n \"};\",\n \"\",\n ].join(\"\\n\");\n\n const current = await readFile(namesFile, \"utf8\").catch(() => \"\");\n if (current === content) return;\n\n const temporary = `${namesFile}.${process.pid}.tmp`;\n await writeFile(temporary, content);\n await rename(temporary, namesFile);\n}\n","import { once } from \"node:events\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Worker } from \"node:worker_threads\";\n\nimport { isDefined, isRecord } from \"@repo/lib/utils\";\n\nimport { createCustomAdapter } from \"@/build/adapters/custom\";\nimport { iconAdapters } from \"@/build/adapters/index\";\nimport type { IconAdapter } from \"@/build/adapters/types\";\nimport type { SourceIcon } from \"@/build/convert\";\nimport { convertIcon } from \"@/build/convert\";\nimport type { InstalledPackage } from \"@/build/packages\";\nimport { findPackage, readDeclaredPackages, readJson, readPluginBuild } from \"@/build/packages\";\nimport type { IconSet, IconSetIcon } from \"@/lib/sets\";\nimport { parseIconSet } from \"@/lib/sets\";\n\n/** What happened converting a set, for the build's log. */\nexport interface IconSetReport {\n /** Icons the library ships in the style. */\n total: number;\n /** Icons skipped, with why. */\n skipped: { name: string; reason: string }[];\n /** Time the conversion took, in milliseconds, or 0 when it came from the cache. */\n duration: number;\n}\n\n/** One installed style of a library, and the package it's read from. */\nexport interface DetectedStyle {\n /** Identifier of the style. */\n style: string;\n /** The package the style is read from. */\n installed: InstalledPackage;\n}\n\n/** A library found in the project, and where each of its styles is installed. */\nexport interface DetectedLibrary {\n /** How to read the library. */\n adapter: IconAdapter;\n /** The styles the project has installed, empty when it has none. */\n styles: DetectedStyle[];\n /** Whether the project's `package.json` lists the package the library is read from, installed or not. */\n listed: boolean;\n /**\n * Another package of the library the project lists, such as its React version, or undefined when there's none or the\n * library's own package is listed.\n */\n sitePackage?: string;\n /** Folder of the project's own icons, relative to the project, or undefined for a known library. */\n folder?: string;\n}\n\n/** Where the build step reads libraries from and caches conversions. */\nexport interface IconSetContext {\n /** The project folder. */\n root: string;\n /** Folder for cached conversions, or undefined to convert every time. */\n cacheDir: string | undefined;\n}\n\n/**\n * Finds every library the project can use: known libraries whose package it lists and has installed, and its own icon\n * folders. Only listed packages count, so a package that's only there because another one depends on it is ignored.\n *\n * @param root - The project folder.\n * @param custom - The project's own icon folders, keyed by identifier.\n * @returns Every library the build step knows, with where it's installed.\n */\nexport async function detectLibraries(root: string, custom: Record<string, string> = {}): Promise<DetectedLibrary[]> {\n const declared = await readDeclaredPackages(root);\n\n const known = await Promise.all(\n iconAdapters.map(async (adapter) => {\n const { packageName, packagePrefix, packagePattern } = adapter;\n\n if (isDefined(packagePrefix)) {\n const names = [...declared].filter((name) => name.startsWith(packagePrefix)).toSorted();\n const found = await Promise.all(\n names.map(async (name) => {\n const installed = await findPackage(root, name);\n\n return isDefined(installed) ? [{ style: name.slice(packagePrefix.length), installed }] : [];\n }),\n );\n\n return { adapter, styles: found.flat(), listed: isDefined(names) };\n }\n\n const listed = isDefined(packageName) && declared.has(packageName);\n const installed = listed ? await findPackage(root, packageName) : undefined;\n const styles = isDefined(installed) ? adapter.styles.map((style) => ({ style, installed })) : [];\n const sitePackage =\n listed || !isDefined(packagePattern)\n ? undefined\n : [...declared].toSorted().find((name) => packagePattern.test(name));\n\n return { adapter, styles, listed, ...(isDefined(sitePackage) && { sitePackage }) };\n }),\n );\n\n const folders = Object.entries(custom).map(([library, folder]) => ({\n adapter: createCustomAdapter(library, folder),\n listed: true,\n folder,\n styles: [\n { style: \"default\", installed: { name: library, directory: path.resolve(root, folder), version: \"custom\" } },\n ],\n }));\n\n return [...known, ...folders];\n}\n\n/**\n * Picks the root most icons in a set share, so only the others need their own.\n *\n * @param icons - The converted icons.\n * @returns The most common root.\n */\nfunction findCommonRoot(icons: (IconSetIcon & { root: NonNullable<IconSetIcon[\"root\"]> })[]) {\n const counts = new Map<string, { root: IconSet[\"root\"]; count: number }>();\n\n for (const { root } of icons) {\n const key = JSON.stringify(root);\n counts.set(key, { root, count: (counts.get(key)?.count ?? 0) + 1 });\n }\n\n const [common] = [...counts.values()].toSorted((first, second) => second.count - first.count);\n\n return common?.root ?? {};\n}\n\n/**\n * Checks whether a value is an icon as a worker read it from its library.\n *\n * @param value - The value to check.\n * @returns True if the value is a source icon.\n */\nfunction isSourceIcon(value: unknown): value is SourceIcon {\n if (!isRecord(value)) return false;\n\n const { name, keywords, svg } = value;\n\n return (\n typeof name === \"string\" &&\n Array.isArray(keywords) &&\n keywords.every((keyword) => typeof keyword === \"string\") &&\n typeof svg === \"string\"\n );\n}\n\n/**\n * Reads a library's icons in a fresh worker thread. A long-running bundler keeps every module it has imported, so an\n * icon package updated in place would otherwise be read from the old copy.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to read.\n * @param root - The project folder.\n * @returns The icons as the library ships them.\n */\nasync function readSources(library: DetectedLibrary, style: string, root: string) {\n const { adapter, folder } = library;\n const installed = library.styles.find((candidate) => candidate.style === style)?.installed;\n if (!isDefined(installed)) return [];\n\n const worker = new Worker(new URL(\"read-worker.js\", import.meta.url), {\n workerData: { library: adapter.library, folder, style, root, directory: installed.directory },\n // Libraries' components render with React's production build, which writes the same markup without warnings.\n env: { ...process.env, NODE_ENV: \"production\" },\n });\n\n try {\n const received: unknown[] = await once(worker, \"message\");\n const [sources] = received;\n\n return Array.isArray(sources) ? sources.filter((source) => isSourceIcon(source)) : [];\n } finally {\n void worker.terminate();\n }\n}\n\n/**\n * Converts one style of a library into a set, reporting anything skipped.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to convert.\n * @param root - The project folder.\n * @returns The set and its report.\n */\nasync function convertIconSet(library: DetectedLibrary, style: string, root: string) {\n const { adapter } = library;\n const started = performance.now();\n const sources = await readSources(library, style, root);\n\n const report: IconSetReport = { total: sources.length, skipped: [], duration: 0 };\n const converted: (IconSetIcon & { root: NonNullable<IconSetIcon[\"root\"]> })[] = [];\n\n for (const source of sources) {\n const { icon, problem } = convertIcon(source);\n\n if (isDefined(icon)) converted.push(icon);\n else if (isDefined(problem)) report.skipped.push({ name: source.name, reason: problem });\n }\n\n const common = findCommonRoot(converted);\n const set: IconSet = {\n library: adapter.library,\n style,\n root: common,\n icons: converted.map(({ root: iconRoot, ...icon }) =>\n JSON.stringify(iconRoot) === JSON.stringify(common) ? icon : { ...icon, root: iconRoot },\n ),\n };\n\n report.duration = Math.round(performance.now() - started);\n\n return { set, report };\n}\n\n/**\n * Reads a cached conversion's report.\n *\n * @param value - The cached report.\n * @returns The report, or undefined when the value isn't one.\n */\nfunction parseReport(value: unknown): IconSetReport | undefined {\n if (!isRecord(value) || typeof value[\"total\"] !== \"number\" || !Array.isArray(value[\"skipped\"])) return undefined;\n\n const skipped = value[\"skipped\"].flatMap((entry: unknown) =>\n isRecord(entry) && typeof entry[\"name\"] === \"string\" && typeof entry[\"reason\"] === \"string\"\n ? [{ name: entry[\"name\"], reason: entry[\"reason\"] }]\n : [],\n );\n\n return { total: value[\"total\"], skipped, duration: 0 };\n}\n\n/**\n * Loads a converted set, from the cache when the same package version was converted before.\n *\n * @param library - The library and where it's installed.\n * @param style - The style to load.\n * @param context - The project folder and cache folder.\n * @returns The set and its report.\n */\nexport async function loadIconSet(library: DetectedLibrary, style: string, context: IconSetContext) {\n const { adapter, folder } = library;\n const installed = library.styles.find((candidate) => candidate.style === style)?.installed;\n const cacheable = isDefined(context.cacheDir) && isDefined(installed) && !isDefined(folder);\n const cacheFile =\n cacheable && isDefined(context.cacheDir)\n ? path.join(\n context.cacheDir,\n \"driftime-icon\",\n `${adapter.library}-${style}-${installed.name.replaceAll(/[@/]/gu, \"_\")}-${installed.version}-${await readPluginBuild()}.json`,\n )\n : undefined;\n\n if (isDefined(cacheFile)) {\n const cached = await readJson(cacheFile);\n const set = isRecord(cached) ? parseIconSet(cached[\"set\"]) : undefined;\n const report = isRecord(cached) ? parseReport(cached[\"report\"]) : undefined;\n\n if (isDefined(set) && isDefined(report)) return { set, report };\n }\n\n const { set, report } = await convertIconSet(library, style, context.root);\n\n if (isDefined(cacheFile)) {\n await mkdir(path.dirname(cacheFile), { recursive: true });\n await writeFile(cacheFile, JSON.stringify({ set, report }));\n }\n\n return { set, report };\n}\n\n/**\n * Lists the files the registry is generated from, so the bundler regenerates it when a library is installed, removed,\n * or updated, instead of keeping a cached copy.\n *\n * @param root - The project folder.\n * @param libraries - Every library the build step knows.\n * @returns The files, and the folders of the project's own icons.\n */\nexport function listRegistryDependencies(root: string, libraries: DetectedLibrary[]) {\n const files = [path.join(root, \"package.json\")];\n const folders: string[] = [];\n\n for (const { styles, folder } of libraries) {\n for (const { installed } of styles) {\n if (isDefined(folder)) folders.push(installed.directory);\n else files.push(path.join(installed.directory, \"package.json\"));\n }\n }\n\n return { files, folders };\n}\n\n/**\n * Summarises a set's conversion for the build's log, listing the first few icons it skipped and why.\n *\n * @param label - Readable name of the library.\n * @param style - The style converted.\n * @param report - What happened.\n * @returns The summary, one line per skipped icon after the first.\n */\nexport function describeReport(label: string, style: string, report: IconSetReport) {\n const { total, skipped, duration } = report;\n const kept = total - skipped.length;\n const count = `${kept.toLocaleString(\"en-US\")} ${kept === 1 ? \"icon\" : \"icons\"}`;\n const timing = duration > 0 ? `converted in ${duration.toLocaleString(\"en-US\")} ms` : \"loaded from the cache\";\n const summary = `${label} (\\`${style}\\`): ${count} ${timing}`;\n if (!isDefined(skipped)) return `${summary}.`;\n\n const shown = skipped.slice(0, 5).map(({ name, reason }) => ` \\`${name}\\` ${reason}.`);\n const hidden = skipped.length - shown.length;\n const more = hidden > 0 ? [` …and ${hidden.toLocaleString(\"en-US\")} more.`] : [];\n\n return [`${summary}, ${skipped.length.toLocaleString(\"en-US\")} skipped:`, ...shown, ...more].join(\"\\n\");\n}\n"],"mappings":"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"}
package/dist/vite.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as logger, r as pluginName } from "./sets-kepuObH8.js";
2
2
  import { n as isDefined } from "./utils-COPacfAq.js";
3
- import { n as isRegistryModule, t as createRegistryModule } from "./registry-dxVzo7ZX.js";
4
- import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-DVh8eYeP.js";
3
+ import { r as isRegistryModule, t as createRegistryModule } from "./registry-B0Dxiwhh.js";
4
+ import { a as writeIconNames, i as loadIconSet, n as detectLibraries, r as listRegistryDependencies, t as describeReport } from "./sets-D5_YGFll.js";
5
5
  import path from "node:path";
6
6
  /** Prefix of the module each set is loaded from, followed by its library and style. */
7
7
  const setPrefix = `virtual:${pluginName}/set/`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@driftime/sanity-plugin-icon",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Icons for Sanity Studio, managed as content by the authors who use them.",
5
5
  "keywords": [
6
6
  "central-icons",
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-dxVzo7ZX.js","names":["realpathSync","fileURLToPath","isDefined","DetectedLibrary","getIconSetKey","IconLibraryInfo","resolveRealPath","file","registryModulePath","URL","import","meta","url","isRegistryModule","id","split","createRegistryModule","libraries","importFor","key","loaders","flatMap","adapter","styles","map","style","library","JSON","stringify","info","Record","Object","fromEntries","listed","sitePackage","label","packageName","packageExample","packagePrefix","installed","join"],"sources":["../src/build/registry.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { isDefined } from \"@repo/lib/utils\";\n\nimport type { DetectedLibrary } from \"@/build/sets\";\nimport { getIconSetKey } from \"@/lib/registry\";\nimport type { IconLibraryInfo } from \"@/lib/sets\";\n\n/**\n * Resolves symbolic links in a path, so a package linked into `node_modules` matches its real location.\n *\n * @param file - The path.\n * @returns The real path, or the path unchanged when it doesn't exist.\n */\nfunction resolveRealPath(file: string) {\n try {\n return realpathSync(file);\n } catch {\n return file;\n }\n}\n\n/**\n * Path of the placeholder registry module the Studio imports, which the build step replaces. The build step's own\n * code is published next to it, so the path is found from this file's location.\n */\nexport const registryModulePath = resolveRealPath(fileURLToPath(new URL(\"sets.js\", import.meta.url)));\n\n/**\n * Checks whether a module the bundler is loading is the placeholder registry.\n *\n * @param id - The module's path, possibly followed by a query.\n * @returns Whether it's the placeholder.\n */\nexport function isRegistryModule(id: string) {\n const [file] = id.split(\"?\");\n\n return isDefined(file) && resolveRealPath(file) === registryModulePath;\n}\n\n/**\n * Writes the module that replaces the placeholder registry, with a loader for each installed library style, so each\n * set is only downloaded when a picker for it opens.\n *\n * @param libraries - Every library the build step knows.\n * @param importFor - The specifier the bundler imports a set from, given its key.\n * @returns The module's code.\n */\nexport function createRegistryModule(libraries: DetectedLibrary[], importFor: (key: string) => string) {\n const loaders = libraries.flatMap(({ adapter, styles }) =>\n styles.map(({ style }) => {\n const key = getIconSetKey(adapter.library, style);\n\n return `${JSON.stringify(key)}: () => import(${JSON.stringify(importFor(key))})`;\n }),\n );\n\n const info: Record<string, IconLibraryInfo> = Object.fromEntries(\n libraries.map(({ adapter, styles, listed, sitePackage }) => [\n adapter.library,\n {\n label: adapter.label,\n packageName: adapter.packageName ?? adapter.packageExample ?? adapter.library,\n ...(isDefined(adapter.packagePrefix) && { packagePrefix: adapter.packagePrefix }),\n styles: isDefined(styles) ? styles.map(({ style }) => style) : adapter.styles,\n listed,\n installed: isDefined(styles),\n ...(isDefined(sitePackage) && { sitePackage }),\n },\n ]),\n );\n\n return [\n `const sets = {\\n ${loaders.join(\",\\n \")}\\n};`,\n `export const iconRegistry = { ready: true, sets, libraries: ${JSON.stringify(info)} };`,\n ].join(\"\\n\");\n}\n"],"mappings":";;;;;;;;;;AAeA,SAASM,gBAAgBC,MAAc;CACrC,IAAI;EACF,OAAOP,aAAaO,IAAI;CAC1B,QAAQ;EACN,OAAOA;CACT;AACF;;;;;AAMA,MAAaC,qBAAqBF,gBAAgBL,cAAc,IAAIQ,IAAI,WAAWC,YAAYE,GAAG,CAAC,CAAC;;;;;;;AAQpG,SAAgBC,iBAAiBC,IAAY;CAC3C,IAAM,CAACP,QAAQO,GAAGC,MAAM,GAAG;CAE3B,OAAOb,UAAUK,IAAI,KAAKD,gBAAgBC,IAAI,MAAMC;AACtD;;;;;;;;;AAUA,SAAgBQ,qBAAqBC,WAA8BC,WAAoC;CACrG,IAAME,UAAUH,UAAUI,SAAS,EAAEC,SAASC,aAC5CA,OAAOC,KAAK,EAAEC,YAAY;EACxB,IAAMN,MAAMf,cAAckB,QAAQI,SAASD,KAAK;EAEhD,OAAO,GAAGE,KAAKC,UAAUT,GAAG,EAAC,iBAAkBQ,KAAKC,UAAUV,UAAUC,GAAG,CAAC,EAAC;CAC/E,CAAC,CACH,GAEMU,OAAwCE,OAAOC,YACnDf,UAAUO,KAAK,EAAEF,SAASC,QAAQU,QAAQC,kBAAkB,CAC1DZ,QAAQI,SACR;EACES,OAAOb,QAAQa;EACfC,aAAad,QAAQc,eAAed,QAAQe,kBAAkBf,QAAQI;EACtE,GAAIxB,UAAUoB,QAAQgB,aAAa,KAAK,EAAEA,eAAehB,QAAQgB,cAAc;EAC/Ef,QAAQrB,UAAUqB,MAAM,IAAIA,OAAOC,KAAK,EAAEC,YAAYA,KAAK,IAAIH,QAAQC;EACvEU;EACAM,WAAWrC,UAAUqB,MAAM;EAC3B,GAAIrB,UAAUgC,WAAW,KAAK,EAAEA,YAAY;CAC9C,CAAC,CACF,CACH;CAEA,OAAO,CACL,qBAAqBd,QAAQoB,KAAK,OAAO,EAAC,OAC1C,+DAA+Db,KAAKC,UAAUC,IAAI,EAAC,IAAK,CACzF,CAACW,KAAK,IAAI;AACb"}