@fumadocs/cli 1.3.1 → 1.3.3

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 (47) hide show
  1. package/dist/build/index.d.ts +4 -6
  2. package/dist/build/index.d.ts.map +1 -1
  3. package/dist/build/index.js +12 -19
  4. package/dist/build/index.js.map +1 -1
  5. package/dist/{client-YTcWP1iz.js → client-C2A4Jf2w.js} +1 -1
  6. package/dist/{client-YTcWP1iz.js.map → client-C2A4Jf2w.js.map} +1 -1
  7. package/dist/{config-Dyass4D9.d.ts → config-Bx-m6awG.d.ts} +9 -5
  8. package/dist/config-Bx-m6awG.d.ts.map +1 -0
  9. package/dist/config.d.ts +2 -2
  10. package/dist/config.js +74 -1
  11. package/dist/config.js.map +1 -0
  12. package/dist/{fs-CigSthjp.js → fs-C3j4H046.js} +1 -1
  13. package/dist/{fs-CigSthjp.js.map → fs-C3j4H046.js.map} +1 -1
  14. package/dist/{ast-BRNdmLn5.js → import-CSbSteB3.js} +56 -2
  15. package/dist/import-CSbSteB3.js.map +1 -0
  16. package/dist/index.js +273 -59
  17. package/dist/index.js.map +1 -1
  18. package/dist/installer-BWoLnsXE.js +673 -0
  19. package/dist/installer-BWoLnsXE.js.map +1 -0
  20. package/dist/registry/client.d.ts +27 -9
  21. package/dist/registry/client.d.ts.map +1 -1
  22. package/dist/registry/client.js +1 -1
  23. package/dist/registry/installer/index.d.ts +17 -27
  24. package/dist/registry/installer/index.d.ts.map +1 -1
  25. package/dist/registry/installer/index.js +1 -3
  26. package/dist/registry/macros/route-handler.d.ts +21 -0
  27. package/dist/registry/macros/route-handler.d.ts.map +1 -0
  28. package/dist/registry/macros/route-handler.js +11 -0
  29. package/dist/registry/macros/route-handler.js.map +1 -0
  30. package/dist/registry/schema.d.ts +2 -2
  31. package/dist/registry/schema.js +15 -11
  32. package/dist/registry/schema.js.map +1 -1
  33. package/dist/{schema-80shuzWO.d.ts → schema-BAaUX4uu.d.ts} +26 -10
  34. package/dist/schema-BAaUX4uu.d.ts.map +1 -0
  35. package/dist/schema.json +1 -0
  36. package/dist/types-79PW0lgM.d.ts +6 -0
  37. package/dist/types-79PW0lgM.d.ts.map +1 -0
  38. package/package.json +6 -6
  39. package/dist/ast-BRNdmLn5.js.map +0 -1
  40. package/dist/config-BYrMmXOw.js +0 -55
  41. package/dist/config-BYrMmXOw.js.map +0 -1
  42. package/dist/config-Dyass4D9.d.ts.map +0 -1
  43. package/dist/installer-B3-my9zN.js +0 -248
  44. package/dist/installer-B3-my9zN.js.map +0 -1
  45. package/dist/schema/default.json +0 -1
  46. package/dist/schema/src.json +0 -1
  47. package/dist/schema-80shuzWO.d.ts.map +0 -1
@@ -1,4 +1,5 @@
1
- import { p as registryInfoSchema, s as NamespaceType, t as CompiledComponent } from "../schema-80shuzWO.js";
1
+ import { d as registryInfoSchema, n as CompiledFile, t as CompiledComponent } from "../schema-BAaUX4uu.js";
2
+ import { n as DistributiveOmit } from "../types-79PW0lgM.js";
2
3
  import { z } from "zod";
3
4
  import { ResolverFactory } from "oxc-resolver";
4
5
 
@@ -12,11 +13,9 @@ interface CompiledRegistry {
12
13
  components: CompiledComponent[];
13
14
  info: z.output<typeof registryInfoSchema>;
14
15
  }
15
- interface ComponentFile {
16
- type: NamespaceType;
16
+ type ComponentFile = DistributiveOmit<CompiledFile, 'content'> & {
17
17
  path: string;
18
- target?: string;
19
- }
18
+ };
20
19
  interface Component {
21
20
  name: string;
22
21
  title?: string;
@@ -123,7 +122,6 @@ declare class ComponentCompiler {
123
122
  private readonly devDependencies;
124
123
  private readonly dependencies;
125
124
  constructor(compiler: RegistryCompiler, component: Component);
126
- private toImportPath;
127
125
  build(): Promise<CompiledComponent>;
128
126
  private onBuildFile;
129
127
  private buildFile;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { n as isRelative } from "../fs-CigSthjp.js";
2
- import { n as transformSpecifiers } from "../ast-BRNdmLn5.js";
1
+ import { a as transformSpecifiers, n as encodeImport } from "../import-CSbSteB3.js";
2
+ import { n as isRelative } from "../fs-C3j4H046.js";
3
3
  import * as fs$1 from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
5
5
  import picocolors from "picocolors";
@@ -22,6 +22,7 @@ var RegistryCompiler = class {
22
22
  name: registry.name,
23
23
  info: {
24
24
  indexes: [],
25
+ unlistedIndexes: [],
25
26
  env: registry.env,
26
27
  variables: registry.variables
27
28
  },
@@ -31,7 +32,7 @@ var RegistryCompiler = class {
31
32
  return [component, await new ComponentCompiler(this, component).build()];
32
33
  }));
33
34
  for (const [input, comp] of builtComps) {
34
- if (!input.unlisted) output.info.indexes.push({
35
+ (input.unlisted ? output.info.unlistedIndexes : output.info.indexes).push({
35
36
  name: input.name,
36
37
  title: input.title,
37
38
  description: input.description
@@ -115,11 +116,6 @@ var ComponentCompiler = class {
115
116
  this.dependencies = /* @__PURE__ */ new Map();
116
117
  this.registry = compiler.raw;
117
118
  }
118
- toImportPath(file) {
119
- let filePath = file.target ?? file.path;
120
- if (filePath.startsWith("./")) filePath = filePath.slice(2);
121
- return `@/${filePath.replaceAll(path$1.sep, "/")}`;
122
- }
123
119
  async build() {
124
120
  const files = (await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))).flat();
125
121
  const dependencies = Object.fromEntries(this.dependencies);
@@ -142,6 +138,7 @@ var ComponentCompiler = class {
142
138
  const resolver = this.compiler.resolver;
143
139
  const queue = [];
144
140
  return [await this.buildFile(file, (reference) => {
141
+ if (reference.type === "dependency" && reference.dep === "@fumadocs/cli") return reference.specifier;
145
142
  if (reference.type === "unknown-specifier") {
146
143
  if (!reference.specifier.startsWith("node:")) console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);
147
144
  return reference.specifier;
@@ -151,21 +148,21 @@ var ComponentCompiler = class {
151
148
  const refFile = this.registry.onUnknownFile?.(reference.file);
152
149
  if (refFile) {
153
150
  queue.push(refFile);
154
- return this.toImportPath(refFile);
151
+ return encodeImport(refFile);
155
152
  }
156
153
  if (refFile === false) return;
157
154
  throw new Error(`Unknown file ${reference.file} referenced by ${file.path}`);
158
155
  }
159
156
  if (reference.type === "sub-component") {
160
157
  const resolved = reference.resolved;
161
- if (resolved.component.name === this.component.name) return this.toImportPath(resolved.file);
158
+ if (resolved.component.name === this.component.name) return encodeImport(resolved.file);
162
159
  if (resolved.type === "remote") this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {
163
160
  type: "http",
164
161
  baseUrl: resolved.registryName,
165
162
  component: resolved.component.name
166
163
  });
167
164
  else this.subComponents.set(resolved.component.name, resolved.component.name);
168
- return this.toImportPath(resolved.file);
165
+ return encodeImport(resolved.file);
169
166
  }
170
167
  const dep = resolver.getDepInfo(reference.dep);
171
168
  if (dep) (dep.type === "dev" ? this.devDependencies : this.dependencies).set(dep.name, dep.version);
@@ -182,10 +179,8 @@ var ComponentCompiler = class {
182
179
  }[path$1.extname(file.path)];
183
180
  const content = (await fs$1.readFile(sourceFilePath)).toString();
184
181
  if (!astType) return {
185
- content,
186
- path: file.path,
187
- type: file.type,
188
- target: file.target
182
+ ...file,
183
+ content
189
184
  };
190
185
  const resolver = this.compiler.resolver;
191
186
  const ast = await parse(sourceFilePath, content, { astType });
@@ -226,10 +221,8 @@ var ComponentCompiler = class {
226
221
  return writeReference(onResolve ? onResolve(resolved, ctx) : resolved);
227
222
  });
228
223
  return {
229
- content: s.toString(),
230
- type: file.type,
231
- path: file.path,
232
- target: file.target
224
+ ...file,
225
+ content: s.toString()
233
226
  };
234
227
  }
235
228
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["fs","path","fs","path"],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n CompiledComponent,\n CompiledFile,\n httpSubComponent,\n NamespaceType,\n registryInfoSchema,\n} from '@/registry/schema';\nimport type { z } from 'zod';\nimport { parse } from 'oxc-parser';\nimport { ResolverFactory } from 'oxc-resolver';\nimport MagicString from 'magic-string';\nimport { transformSpecifiers } from '@/utils/ast';\nimport { isRelative } from '@/utils/fs';\n\nexport type OnResolve = (\n reference: SourceReference,\n from: { component: Component; file: ComponentFile },\n) => Reference;\n\nexport interface CompiledRegistry {\n name: string;\n components: CompiledComponent[];\n info: z.output<typeof registryInfoSchema>;\n}\n\nexport interface ComponentFile {\n type: NamespaceType;\n path: string;\n target?: string;\n}\n\nexport interface Component {\n name: string;\n title?: string;\n description?: string;\n files: ComponentFile[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n\n /**\n * Don't list the component in registry index file\n */\n unlisted?: boolean;\n\n /**\n * Map imported file paths, inherit from registry if not defined.\n */\n onResolve?: OnResolve;\n}\n\nexport interface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport interface Registry extends Omit<z.input<typeof registryInfoSchema>, 'indexes'> {\n name: string;\n packageJson: string | PackageJson;\n tsconfigPath: string;\n components: Component[];\n\n /**\n * The directory of registry, used to resolve relative paths\n */\n dir: string;\n\n /**\n * Map import paths of components\n */\n onResolve?: OnResolve;\n /**\n * When a referenced file is not found in component files, this function is called.\n * @returns file, or `false` to mark as external.\n */\n onUnknownFile?: (absolutePath: string) => ComponentFile | false | undefined;\n\n dependencies?: Record<string, string | null>;\n devDependencies?: Record<string, string | null>;\n}\n\nexport class RegistryCompiler {\n readonly raw: Registry;\n resolver!: RegistryResolver;\n\n constructor(registry: Registry) {\n this.raw = registry;\n }\n\n private async readPackageJson(): Promise<PackageJson | undefined> {\n if (typeof this.raw.packageJson !== 'string') return this.raw.packageJson;\n\n return fs\n .readFile(path.join(this.raw.dir, this.raw.packageJson))\n .then((res) => JSON.parse(res.toString()) as PackageJson)\n .catch(() => undefined);\n }\n\n async compile(): Promise<CompiledRegistry> {\n const registry = this.raw;\n this.resolver = new RegistryResolver(this, await this.readPackageJson());\n const output: CompiledRegistry = {\n name: registry.name,\n info: {\n indexes: [],\n env: registry.env,\n variables: registry.variables,\n },\n components: [],\n };\n\n const builtComps = await Promise.all(\n registry.components.map(async (component) => {\n const compiler = new ComponentCompiler(this, component);\n\n return [component, await compiler.build()] as [Component, CompiledComponent];\n }),\n );\n\n for (const [input, comp] of builtComps) {\n if (!input.unlisted) {\n output.info.indexes.push({\n name: input.name,\n title: input.title,\n description: input.description,\n });\n }\n\n output.components.push(comp);\n }\n\n return output;\n }\n}\n\nclass RegistryResolver {\n private readonly deps: Record<string, string | null>;\n private readonly devDeps: Record<string, string | null>;\n private readonly fileToComponent = new Map<string, [Component, ComponentFile]>();\n readonly oxc: ResolverFactory;\n\n constructor(\n private readonly compiler: RegistryCompiler,\n packageJson: PackageJson = {},\n ) {\n const registry = compiler.raw;\n\n for (const comp of registry.components) {\n for (const file of comp.files) {\n if (this.fileToComponent.has(file.path))\n console.warn(\n `the same file ${file.path} exists in multiple component, you should make the shared file a separate component.`,\n );\n this.fileToComponent.set(file.path, [comp, file]);\n }\n }\n\n this.deps = {\n ...packageJson?.dependencies,\n ...registry.dependencies,\n };\n\n this.devDeps = {\n ...packageJson?.devDependencies,\n ...registry.devDependencies,\n };\n\n // resolve anything possible\n this.oxc = new ResolverFactory({\n extensions: ['.js', '.jsx', '.ts', '.tsx', '.node'],\n conditionNames: ['node', 'import', 'require', 'default', 'types'],\n tsconfig: {\n configFile: path.join(registry.dir, registry.tsconfigPath),\n },\n });\n }\n\n getDepFromSpecifier(specifier: string) {\n return specifier.startsWith('@')\n ? specifier.split('/').slice(0, 2).join('/')\n : specifier.split('/')[0];\n }\n\n getDepInfo(name: string):\n | {\n type: 'runtime' | 'dev';\n name: string;\n version: string | null;\n }\n | undefined {\n if (name in this.deps)\n return {\n name,\n type: 'runtime',\n version: this.deps[name],\n };\n\n if (name in this.devDeps)\n return {\n name,\n type: 'dev',\n version: this.devDeps[name],\n };\n\n console.warn(`dep info for ${name} cannot be found`);\n }\n\n getComponentByName(name: string): Component | undefined {\n return this.compiler.raw.components.find((comp) => comp.name === name);\n }\n\n getSubComponent(file: string) {\n const relativeFile = path.relative(this.compiler.raw.dir, file);\n const comp = this.fileToComponent.get(relativeFile);\n\n if (!comp) return;\n return {\n component: comp[0],\n file: comp[1],\n };\n }\n}\n\nexport type SourceReference =\n | {\n type: 'file';\n /**\n * Absolute path\n */\n file: string;\n }\n | {\n type: 'dependency';\n dep: string;\n specifier: string;\n }\n | {\n type: 'sub-component';\n resolved:\n | {\n type: 'local';\n component: Component;\n file: ComponentFile;\n }\n | {\n type: 'remote';\n component: Component;\n file: ComponentFile;\n registryName: string;\n };\n }\n | {\n type: 'unknown-specifier';\n specifier: string;\n };\n\nexport type Reference =\n | SourceReference\n | {\n type: 'custom';\n specifier: string;\n };\n\nexport class ComponentCompiler {\n private readonly processedFiles = new Set<string>();\n private readonly registry: Registry;\n private readonly subComponents = new Map<string, string | z.input<typeof httpSubComponent>>();\n private readonly devDependencies = new Map<string, string | null>();\n private readonly dependencies = new Map<string, string | null>();\n\n constructor(\n private readonly compiler: RegistryCompiler,\n private readonly component: Component,\n ) {\n this.registry = compiler.raw;\n }\n\n private toImportPath(file: ComponentFile): string {\n let filePath = file.target ?? file.path;\n\n if (filePath.startsWith('./')) filePath = filePath.slice(2);\n\n return `@/${filePath.replaceAll(path.sep, '/')}`;\n }\n\n async build(): Promise<CompiledComponent> {\n const files = (\n await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))\n ).flat();\n const dependencies = Object.fromEntries(this.dependencies);\n const devDependencies = Object.fromEntries(this.devDependencies);\n\n if (this.component.dependencies) {\n Object.assign(dependencies, this.component.dependencies);\n }\n if (this.component.devDependencies) {\n Object.assign(devDependencies, this.component.devDependencies);\n }\n\n return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files,\n subComponents: Array.from(this.subComponents.values()),\n dependencies,\n devDependencies,\n };\n }\n\n private async onBuildFile(file: ComponentFile): Promise<CompiledFile[]> {\n if (this.processedFiles.has(file.path)) return [];\n this.processedFiles.add(file.path);\n const resolver = this.compiler.resolver;\n\n const queue: ComponentFile[] = [];\n const result = await this.buildFile(file, (reference) => {\n if (reference.type === 'unknown-specifier') {\n if (!reference.specifier.startsWith('node:')) {\n console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);\n }\n\n return reference.specifier;\n }\n\n if (reference.type === 'custom') return reference.specifier;\n\n if (reference.type === 'file') {\n const refFile = this.registry.onUnknownFile?.(reference.file);\n if (refFile) {\n queue.push(refFile);\n return this.toImportPath(refFile);\n }\n\n if (refFile === false) return;\n\n throw new Error(`Unknown file ${reference.file} referenced by ${file.path}`);\n }\n\n if (reference.type === 'sub-component') {\n const resolved = reference.resolved;\n if (resolved.component.name === this.component.name)\n return this.toImportPath(resolved.file);\n\n if (resolved.type === 'remote') {\n this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {\n type: 'http',\n baseUrl: resolved.registryName,\n component: resolved.component.name,\n });\n } else {\n this.subComponents.set(resolved.component.name, resolved.component.name);\n }\n\n return this.toImportPath(resolved.file);\n }\n\n const dep = resolver.getDepInfo(reference.dep);\n if (dep) {\n const map = dep.type === 'dev' ? this.devDependencies : this.dependencies;\n map.set(dep.name, dep.version);\n }\n\n return reference.specifier;\n });\n\n return [result, ...(await Promise.all(queue.map((file) => this.onBuildFile(file)))).flat()];\n }\n\n private async buildFile(\n file: ComponentFile,\n /**\n * write references back to import specifiers\n *\n * keep original one if `undefined`\n */\n writeReference: (reference: Reference) => string | undefined,\n ): Promise<CompiledFile> {\n const sourceFilePath = path.join(this.registry.dir, file.path);\n const astTypes: Record<string, 'js' | 'ts' | undefined> = {\n '.ts': 'ts',\n '.tsx': 'ts',\n '.js': 'js',\n '.jsx': 'js',\n };\n const astType = astTypes[path.extname(file.path)];\n const content = (await fs.readFile(sourceFilePath)).toString();\n\n if (!astType)\n return {\n content,\n path: file.path,\n type: file.type,\n target: file.target,\n };\n\n const resolver = this.compiler.resolver;\n\n const ast = await parse(sourceFilePath, content, {\n astType,\n });\n\n if (ast.errors.length > 0) {\n throw new Error(`failed to parse file ${sourceFilePath}: \\n${ast.errors.join('\\n')}`);\n }\n\n const s = new MagicString(content);\n const ctx = { component: this.component, file };\n // Process import paths\n transformSpecifiers(ast.program, s, (specifier) => {\n let resolved: Reference = {\n type: 'unknown-specifier',\n specifier: specifier,\n };\n const onResolve = this.component.onResolve ?? this.registry.onResolve;\n const resolvedSpecifier = resolver.oxc.resolveFileSync(sourceFilePath, specifier);\n if (resolvedSpecifier.error || !resolvedSpecifier.path) {\n return writeReference(onResolve ? onResolve(resolved, ctx) : resolved);\n }\n\n resolved = {\n type: 'file',\n file: resolvedSpecifier.path,\n };\n\n // outside of registry dir\n if (!isRelative(this.registry.dir, resolvedSpecifier.path)) {\n resolved = {\n type: 'dependency',\n dep: resolver.getDepFromSpecifier(specifier),\n specifier,\n };\n } else {\n const sub = resolver.getSubComponent(resolvedSpecifier.path);\n if (sub) {\n resolved = {\n type: 'sub-component',\n resolved: {\n type: 'local',\n component: sub.component,\n file: sub.file,\n },\n };\n }\n }\n\n return writeReference(onResolve ? onResolve(resolved, ctx) : resolved);\n });\n\n return {\n content: s.toString(),\n type: file.type,\n path: file.path,\n target: file.target,\n };\n }\n}\n\nexport function resolveFromRemote(\n r: Registry,\n component: string,\n selectFile: (file: ComponentFile) => boolean,\n): Reference | undefined {\n const comp = r.components.find((comp) => comp.name === component);\n if (!comp) return;\n const file = comp.files.find(selectFile);\n if (!file) return;\n\n return {\n type: 'sub-component',\n resolved: {\n type: 'remote',\n registryName: r.name,\n component: comp,\n file,\n },\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport picocolors from 'picocolors';\nimport type { CompiledRegistry } from '@/build/compiler';\n\nexport * from './compiler';\n\nexport interface MonoRegistry extends CompiledRegistry {\n registries: CompiledRegistry[];\n}\n\nexport function combineRegistry(\n root: CompiledRegistry,\n ...items: CompiledRegistry[]\n): MonoRegistry {\n return {\n ...root,\n info: {\n ...root.info,\n registries: items.map((item) => item.name),\n },\n registries: items,\n };\n}\n\nexport async function writeFumadocsRegistry(\n out: CompiledRegistry | MonoRegistry,\n options: {\n dir: string;\n\n /**\n * Remove previous outputs\n *\n * @defaultValue false\n */\n cleanDir?: boolean;\n\n log?: boolean;\n },\n): Promise<void> {\n const { dir, cleanDir = false, log = true } = options;\n\n if (cleanDir) {\n await fs.rm(dir, {\n recursive: true,\n force: true,\n });\n console.log(picocolors.bold(picocolors.greenBright('Cleaned directory')));\n }\n\n async function writeInfo() {\n const file = path.join(dir, '_registry.json');\n const json = JSON.stringify(out.info, null, 2);\n\n await writeFile(file, json, log);\n }\n\n const write = out.components.map(async (comp) => {\n const file = path.join(dir, `${comp.name}.json`);\n const json = JSON.stringify(comp, null, 2);\n\n await writeFile(file, json, log);\n });\n\n write.push(writeInfo());\n if ('registries' in out) {\n for (const child of out.registries) {\n write.push(\n writeFumadocsRegistry(child, {\n dir: path.join(dir, child.name),\n log: options.log,\n }),\n );\n }\n }\n\n await Promise.all(write);\n}\n\nasync function writeFile(file: string, content: string, log = true): Promise<void> {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n\n if (log) {\n const size = (Buffer.byteLength(content) / 1024).toFixed(2);\n\n console.log(\n `${picocolors.greenBright('+')} ${path.relative(process.cwd(), file)} ${picocolors.dim(`${size} KB`)}`,\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["fs","path","fs","path"],"sources":["../../src/build/compiler.ts","../../src/build/index.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n CompiledComponent,\n CompiledFile,\n httpSubComponent,\n registryInfoSchema,\n} from '@/registry/schema';\nimport type { z } from 'zod';\nimport { parse } from 'oxc-parser';\nimport { ResolverFactory } from 'oxc-resolver';\nimport MagicString from 'magic-string';\nimport { transformSpecifiers } from '@/utils/ast';\nimport { isRelative } from '@/utils/fs';\nimport type { DistributiveOmit } from '@/types';\nimport { encodeImport } from '@/registry/protocols/import';\n\nexport type OnResolve = (\n reference: SourceReference,\n from: { component: Component; file: ComponentFile },\n) => Reference;\n\nexport interface CompiledRegistry {\n name: string;\n components: CompiledComponent[];\n info: z.output<typeof registryInfoSchema>;\n}\n\nexport type ComponentFile = DistributiveOmit<CompiledFile, 'content'> & {\n path: string;\n};\n\nexport interface Component {\n name: string;\n title?: string;\n description?: string;\n files: ComponentFile[];\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n\n /**\n * Don't list the component in registry index file\n */\n unlisted?: boolean;\n\n /**\n * Map imported file paths, inherit from registry if not defined.\n */\n onResolve?: OnResolve;\n}\n\nexport interface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport interface Registry extends Omit<z.input<typeof registryInfoSchema>, 'indexes'> {\n name: string;\n packageJson: string | PackageJson;\n tsconfigPath: string;\n components: Component[];\n\n /**\n * The directory of registry, used to resolve relative paths\n */\n dir: string;\n\n /**\n * Map import paths of components\n */\n onResolve?: OnResolve;\n /**\n * When a referenced file is not found in component files, this function is called.\n * @returns file, or `false` to mark as external.\n */\n onUnknownFile?: (absolutePath: string) => ComponentFile | false | undefined;\n\n dependencies?: Record<string, string | null>;\n devDependencies?: Record<string, string | null>;\n}\n\nexport class RegistryCompiler {\n readonly raw: Registry;\n resolver!: RegistryResolver;\n\n constructor(registry: Registry) {\n this.raw = registry;\n }\n\n private async readPackageJson(): Promise<PackageJson | undefined> {\n if (typeof this.raw.packageJson !== 'string') return this.raw.packageJson;\n\n return fs\n .readFile(path.join(this.raw.dir, this.raw.packageJson))\n .then((res) => JSON.parse(res.toString()) as PackageJson)\n .catch(() => undefined);\n }\n\n async compile(): Promise<CompiledRegistry> {\n const registry = this.raw;\n this.resolver = new RegistryResolver(this, await this.readPackageJson());\n const output: CompiledRegistry = {\n name: registry.name,\n info: {\n indexes: [],\n unlistedIndexes: [],\n env: registry.env,\n variables: registry.variables,\n },\n components: [],\n };\n\n const builtComps = await Promise.all(\n registry.components.map(async (component) => {\n const compiler = new ComponentCompiler(this, component);\n\n return [component, await compiler.build()] as [Component, CompiledComponent];\n }),\n );\n\n for (const [input, comp] of builtComps) {\n const arr = input.unlisted ? output.info.unlistedIndexes : output.info.indexes;\n\n arr.push({\n name: input.name,\n title: input.title,\n description: input.description,\n });\n output.components.push(comp);\n }\n\n return output;\n }\n}\n\nclass RegistryResolver {\n private readonly deps: Record<string, string | null>;\n private readonly devDeps: Record<string, string | null>;\n private readonly fileToComponent = new Map<string, [Component, ComponentFile]>();\n readonly oxc: ResolverFactory;\n\n constructor(\n private readonly compiler: RegistryCompiler,\n packageJson: PackageJson = {},\n ) {\n const registry = compiler.raw;\n\n for (const comp of registry.components) {\n for (const file of comp.files) {\n if (this.fileToComponent.has(file.path))\n console.warn(\n `the same file ${file.path} exists in multiple component, you should make the shared file a separate component.`,\n );\n this.fileToComponent.set(file.path, [comp, file]);\n }\n }\n\n this.deps = {\n ...packageJson?.dependencies,\n ...registry.dependencies,\n };\n\n this.devDeps = {\n ...packageJson?.devDependencies,\n ...registry.devDependencies,\n };\n\n // resolve anything possible\n this.oxc = new ResolverFactory({\n extensions: ['.js', '.jsx', '.ts', '.tsx', '.node'],\n conditionNames: ['node', 'import', 'require', 'default', 'types'],\n tsconfig: {\n configFile: path.join(registry.dir, registry.tsconfigPath),\n },\n });\n }\n\n getDepFromSpecifier(specifier: string) {\n return specifier.startsWith('@')\n ? specifier.split('/').slice(0, 2).join('/')\n : specifier.split('/')[0];\n }\n\n getDepInfo(name: string):\n | {\n type: 'runtime' | 'dev';\n name: string;\n version: string | null;\n }\n | undefined {\n if (name in this.deps)\n return {\n name,\n type: 'runtime',\n version: this.deps[name],\n };\n\n if (name in this.devDeps)\n return {\n name,\n type: 'dev',\n version: this.devDeps[name],\n };\n\n console.warn(`dep info for ${name} cannot be found`);\n }\n\n getComponentByName(name: string): Component | undefined {\n return this.compiler.raw.components.find((comp) => comp.name === name);\n }\n\n getSubComponent(file: string) {\n const relativeFile = path.relative(this.compiler.raw.dir, file);\n const comp = this.fileToComponent.get(relativeFile);\n\n if (!comp) return;\n return {\n component: comp[0],\n file: comp[1],\n };\n }\n}\n\nexport type SourceReference =\n | {\n type: 'file';\n /**\n * Absolute path\n */\n file: string;\n }\n | {\n type: 'dependency';\n dep: string;\n specifier: string;\n }\n | {\n type: 'sub-component';\n resolved:\n | {\n type: 'local';\n component: Component;\n file: ComponentFile;\n }\n | {\n type: 'remote';\n component: Component;\n file: ComponentFile;\n registryName: string;\n };\n }\n | {\n type: 'unknown-specifier';\n specifier: string;\n };\n\nexport type Reference =\n | SourceReference\n | {\n type: 'custom';\n specifier: string;\n };\n\nexport class ComponentCompiler {\n private readonly processedFiles = new Set<string>();\n private readonly registry: Registry;\n private readonly subComponents = new Map<string, string | z.input<typeof httpSubComponent>>();\n private readonly devDependencies = new Map<string, string | null>();\n private readonly dependencies = new Map<string, string | null>();\n\n constructor(\n private readonly compiler: RegistryCompiler,\n private readonly component: Component,\n ) {\n this.registry = compiler.raw;\n }\n\n async build(): Promise<CompiledComponent> {\n const files = (\n await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))\n ).flat();\n const dependencies = Object.fromEntries(this.dependencies);\n const devDependencies = Object.fromEntries(this.devDependencies);\n\n if (this.component.dependencies) {\n Object.assign(dependencies, this.component.dependencies);\n }\n if (this.component.devDependencies) {\n Object.assign(devDependencies, this.component.devDependencies);\n }\n\n return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files,\n subComponents: Array.from(this.subComponents.values()),\n dependencies,\n devDependencies,\n };\n }\n\n private async onBuildFile(file: ComponentFile): Promise<CompiledFile[]> {\n if (this.processedFiles.has(file.path)) return [];\n this.processedFiles.add(file.path);\n const resolver = this.compiler.resolver;\n\n const queue: ComponentFile[] = [];\n const result = await this.buildFile(file, (reference) => {\n const external = reference.type === 'dependency' && reference.dep === '@fumadocs/cli';\n\n if (external) {\n return reference.specifier;\n }\n\n if (reference.type === 'unknown-specifier') {\n if (!reference.specifier.startsWith('node:')) {\n console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);\n }\n\n return reference.specifier;\n }\n\n if (reference.type === 'custom') return reference.specifier;\n\n if (reference.type === 'file') {\n const refFile = this.registry.onUnknownFile?.(reference.file);\n if (refFile) {\n queue.push(refFile);\n return encodeImport(refFile);\n }\n\n if (refFile === false) return;\n\n throw new Error(`Unknown file ${reference.file} referenced by ${file.path}`);\n }\n\n if (reference.type === 'sub-component') {\n const resolved = reference.resolved;\n if (resolved.component.name === this.component.name) return encodeImport(resolved.file);\n\n if (resolved.type === 'remote') {\n this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {\n type: 'http',\n baseUrl: resolved.registryName,\n component: resolved.component.name,\n });\n } else {\n this.subComponents.set(resolved.component.name, resolved.component.name);\n }\n\n return encodeImport(resolved.file);\n }\n\n const dep = resolver.getDepInfo(reference.dep);\n if (dep) {\n const map = dep.type === 'dev' ? this.devDependencies : this.dependencies;\n map.set(dep.name, dep.version);\n }\n\n return reference.specifier;\n });\n\n return [result, ...(await Promise.all(queue.map((file) => this.onBuildFile(file)))).flat()];\n }\n\n private async buildFile(\n file: ComponentFile,\n /**\n * write references back to import specifiers\n *\n * keep original one if `undefined`\n */\n writeReference: (reference: Reference) => string | undefined,\n ): Promise<CompiledFile> {\n const sourceFilePath = path.join(this.registry.dir, file.path);\n const astTypes: Record<string, 'js' | 'ts' | undefined> = {\n '.ts': 'ts',\n '.tsx': 'ts',\n '.js': 'js',\n '.jsx': 'js',\n };\n const astType = astTypes[path.extname(file.path)];\n const content = (await fs.readFile(sourceFilePath)).toString();\n\n if (!astType) {\n return {\n ...file,\n content,\n };\n }\n\n const resolver = this.compiler.resolver;\n\n const ast = await parse(sourceFilePath, content, {\n astType,\n });\n\n if (ast.errors.length > 0) {\n throw new Error(`failed to parse file ${sourceFilePath}: \\n${ast.errors.join('\\n')}`);\n }\n\n const s = new MagicString(content);\n const ctx = { component: this.component, file };\n // Process import paths\n transformSpecifiers(ast.program, s, (specifier) => {\n let resolved: Reference = {\n type: 'unknown-specifier',\n specifier: specifier,\n };\n const onResolve = this.component.onResolve ?? this.registry.onResolve;\n const resolvedSpecifier = resolver.oxc.resolveFileSync(sourceFilePath, specifier);\n if (resolvedSpecifier.error || !resolvedSpecifier.path) {\n return writeReference(onResolve ? onResolve(resolved, ctx) : resolved);\n }\n\n resolved = {\n type: 'file',\n file: resolvedSpecifier.path,\n };\n\n // outside of registry dir\n if (!isRelative(this.registry.dir, resolvedSpecifier.path)) {\n resolved = {\n type: 'dependency',\n dep: resolver.getDepFromSpecifier(specifier),\n specifier,\n };\n } else {\n const sub = resolver.getSubComponent(resolvedSpecifier.path);\n if (sub) {\n resolved = {\n type: 'sub-component',\n resolved: {\n type: 'local',\n component: sub.component,\n file: sub.file,\n },\n };\n }\n }\n\n return writeReference(onResolve ? onResolve(resolved, ctx) : resolved);\n });\n\n return {\n ...file,\n content: s.toString(),\n };\n }\n}\n\nexport function resolveFromRemote(\n r: Registry,\n component: string,\n selectFile: (file: ComponentFile) => boolean,\n): Reference | undefined {\n const comp = r.components.find((comp) => comp.name === component);\n if (!comp) return;\n const file = comp.files.find(selectFile);\n if (!file) return;\n\n return {\n type: 'sub-component',\n resolved: {\n type: 'remote',\n registryName: r.name,\n component: comp,\n file,\n },\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport picocolors from 'picocolors';\nimport type { CompiledRegistry } from '@/build/compiler';\n\nexport * from './compiler';\n\nexport interface MonoRegistry extends CompiledRegistry {\n registries: CompiledRegistry[];\n}\n\nexport function combineRegistry(\n root: CompiledRegistry,\n ...items: CompiledRegistry[]\n): MonoRegistry {\n return {\n ...root,\n info: {\n ...root.info,\n registries: items.map((item) => item.name),\n },\n registries: items,\n };\n}\n\nexport async function writeFumadocsRegistry(\n out: CompiledRegistry | MonoRegistry,\n options: {\n dir: string;\n\n /**\n * Remove previous outputs\n *\n * @defaultValue false\n */\n cleanDir?: boolean;\n\n log?: boolean;\n },\n): Promise<void> {\n const { dir, cleanDir = false, log = true } = options;\n\n if (cleanDir) {\n await fs.rm(dir, {\n recursive: true,\n force: true,\n });\n console.log(picocolors.bold(picocolors.greenBright('Cleaned directory')));\n }\n\n async function writeInfo() {\n const file = path.join(dir, '_registry.json');\n const json = JSON.stringify(out.info, null, 2);\n\n await writeFile(file, json, log);\n }\n\n const write = out.components.map(async (comp) => {\n const file = path.join(dir, `${comp.name}.json`);\n const json = JSON.stringify(comp, null, 2);\n\n await writeFile(file, json, log);\n });\n\n write.push(writeInfo());\n if ('registries' in out) {\n for (const child of out.registries) {\n write.push(\n writeFumadocsRegistry(child, {\n dir: path.join(dir, child.name),\n log: options.log,\n }),\n );\n }\n }\n\n await Promise.all(write);\n}\n\nasync function writeFile(file: string, content: string, log = true): Promise<void> {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n\n if (log) {\n const size = (Buffer.byteLength(content) / 1024).toFixed(2);\n\n console.log(\n `${picocolors.greenBright('+')} ${path.relative(process.cwd(), file)} ${picocolors.dim(`${size} KB`)}`,\n );\n }\n}\n"],"mappings":";;;;;;;;;AAiFA,IAAa,mBAAb,MAA8B;CAI5B,YAAY,UAAoB;AAC9B,OAAK,MAAM;;CAGb,MAAc,kBAAoD;AAChE,MAAI,OAAO,KAAK,IAAI,gBAAgB,SAAU,QAAO,KAAK,IAAI;AAE9D,SAAOA,KACJ,SAASC,OAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI,YAAY,CAAC,CACvD,MAAM,QAAQ,KAAK,MAAM,IAAI,UAAU,CAAC,CAAgB,CACxD,YAAY,KAAA,EAAU;;CAG3B,MAAM,UAAqC;EACzC,MAAM,WAAW,KAAK;AACtB,OAAK,WAAW,IAAI,iBAAiB,MAAM,MAAM,KAAK,iBAAiB,CAAC;EACxE,MAAM,SAA2B;GAC/B,MAAM,SAAS;GACf,MAAM;IACJ,SAAS,EAAE;IACX,iBAAiB,EAAE;IACnB,KAAK,SAAS;IACd,WAAW,SAAS;IACrB;GACD,YAAY,EAAE;GACf;EAED,MAAM,aAAa,MAAM,QAAQ,IAC/B,SAAS,WAAW,IAAI,OAAO,cAAc;AAG3C,UAAO,CAAC,WAAW,MAFF,IAAI,kBAAkB,MAAM,UAAU,CAErB,OAAO,CAAC;IAC1C,CACH;AAED,OAAK,MAAM,CAAC,OAAO,SAAS,YAAY;AAGtC,IAFY,MAAM,WAAW,OAAO,KAAK,kBAAkB,OAAO,KAAK,SAEnE,KAAK;IACP,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,aAAa,MAAM;IACpB,CAAC;AACF,UAAO,WAAW,KAAK,KAAK;;AAG9B,SAAO;;;AAIX,IAAM,mBAAN,MAAuB;CAMrB,YACE,UACA,cAA2B,EAAE,EAC7B;AAFiB,OAAA,WAAA;yCAJgB,IAAI,KAAyC;EAO9E,MAAM,WAAW,SAAS;AAE1B,OAAK,MAAM,QAAQ,SAAS,WAC1B,MAAK,MAAM,QAAQ,KAAK,OAAO;AAC7B,OAAI,KAAK,gBAAgB,IAAI,KAAK,KAAK,CACrC,SAAQ,KACN,iBAAiB,KAAK,KAAK,sFAC5B;AACH,QAAK,gBAAgB,IAAI,KAAK,MAAM,CAAC,MAAM,KAAK,CAAC;;AAIrD,OAAK,OAAO;GACV,GAAG,aAAa;GAChB,GAAG,SAAS;GACb;AAED,OAAK,UAAU;GACb,GAAG,aAAa;GAChB,GAAG,SAAS;GACb;AAGD,OAAK,MAAM,IAAI,gBAAgB;GAC7B,YAAY;IAAC;IAAO;IAAQ;IAAO;IAAQ;IAAQ;GACnD,gBAAgB;IAAC;IAAQ;IAAU;IAAW;IAAW;IAAQ;GACjE,UAAU,EACR,YAAYA,OAAK,KAAK,SAAS,KAAK,SAAS,aAAa,EAC3D;GACF,CAAC;;CAGJ,oBAAoB,WAAmB;AACrC,SAAO,UAAU,WAAW,IAAI,GAC5B,UAAU,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,GAC1C,UAAU,MAAM,IAAI,CAAC;;CAG3B,WAAW,MAMG;AACZ,MAAI,QAAQ,KAAK,KACf,QAAO;GACL;GACA,MAAM;GACN,SAAS,KAAK,KAAK;GACpB;AAEH,MAAI,QAAQ,KAAK,QACf,QAAO;GACL;GACA,MAAM;GACN,SAAS,KAAK,QAAQ;GACvB;AAEH,UAAQ,KAAK,gBAAgB,KAAK,kBAAkB;;CAGtD,mBAAmB,MAAqC;AACtD,SAAO,KAAK,SAAS,IAAI,WAAW,MAAM,SAAS,KAAK,SAAS,KAAK;;CAGxE,gBAAgB,MAAc;EAC5B,MAAM,eAAeA,OAAK,SAAS,KAAK,SAAS,IAAI,KAAK,KAAK;EAC/D,MAAM,OAAO,KAAK,gBAAgB,IAAI,aAAa;AAEnD,MAAI,CAAC,KAAM;AACX,SAAO;GACL,WAAW,KAAK;GAChB,MAAM,KAAK;GACZ;;;AA4CL,IAAa,oBAAb,MAA+B;CAO7B,YACE,UACA,WACA;AAFiB,OAAA,WAAA;AACA,OAAA,YAAA;wCARe,IAAI,KAAa;uCAElB,IAAI,KAAwD;yCAC1D,IAAI,KAA4B;sCACnC,IAAI,KAA4B;AAM9D,OAAK,WAAW,SAAS;;CAG3B,MAAM,QAAoC;EACxC,MAAM,SACJ,MAAM,QAAQ,IAAI,KAAK,UAAU,MAAM,KAAK,SAAS,KAAK,YAAY,KAAK,CAAC,CAAC,EAC7E,MAAM;EACR,MAAM,eAAe,OAAO,YAAY,KAAK,aAAa;EAC1D,MAAM,kBAAkB,OAAO,YAAY,KAAK,gBAAgB;AAEhE,MAAI,KAAK,UAAU,aACjB,QAAO,OAAO,cAAc,KAAK,UAAU,aAAa;AAE1D,MAAI,KAAK,UAAU,gBACjB,QAAO,OAAO,iBAAiB,KAAK,UAAU,gBAAgB;AAGhE,SAAO;GACL,MAAM,KAAK,UAAU;GACrB,OAAO,KAAK,UAAU;GACtB,aAAa,KAAK,UAAU;GAC5B;GACA,eAAe,MAAM,KAAK,KAAK,cAAc,QAAQ,CAAC;GACtD;GACA;GACD;;CAGH,MAAc,YAAY,MAA8C;AACtE,MAAI,KAAK,eAAe,IAAI,KAAK,KAAK,CAAE,QAAO,EAAE;AACjD,OAAK,eAAe,IAAI,KAAK,KAAK;EAClC,MAAM,WAAW,KAAK,SAAS;EAE/B,MAAM,QAAyB,EAAE;AAwDjC,SAAO,CAvDQ,MAAM,KAAK,UAAU,OAAO,cAAc;AAGvD,OAFiB,UAAU,SAAS,gBAAgB,UAAU,QAAQ,gBAGpE,QAAO,UAAU;AAGnB,OAAI,UAAU,SAAS,qBAAqB;AAC1C,QAAI,CAAC,UAAU,UAAU,WAAW,QAAQ,CAC1C,SAAQ,KAAK,qBAAqB,UAAU,UAAU,oBAAoB;AAG5E,WAAO,UAAU;;AAGnB,OAAI,UAAU,SAAS,SAAU,QAAO,UAAU;AAElD,OAAI,UAAU,SAAS,QAAQ;IAC7B,MAAM,UAAU,KAAK,SAAS,gBAAgB,UAAU,KAAK;AAC7D,QAAI,SAAS;AACX,WAAM,KAAK,QAAQ;AACnB,YAAO,aAAa,QAAQ;;AAG9B,QAAI,YAAY,MAAO;AAEvB,UAAM,IAAI,MAAM,gBAAgB,UAAU,KAAK,iBAAiB,KAAK,OAAO;;AAG9E,OAAI,UAAU,SAAS,iBAAiB;IACtC,MAAM,WAAW,UAAU;AAC3B,QAAI,SAAS,UAAU,SAAS,KAAK,UAAU,KAAM,QAAO,aAAa,SAAS,KAAK;AAEvF,QAAI,SAAS,SAAS,SACpB,MAAK,cAAc,IAAI,GAAG,SAAS,aAAa,GAAG,SAAS,UAAU,QAAQ;KAC5E,MAAM;KACN,SAAS,SAAS;KAClB,WAAW,SAAS,UAAU;KAC/B,CAAC;QAEF,MAAK,cAAc,IAAI,SAAS,UAAU,MAAM,SAAS,UAAU,KAAK;AAG1E,WAAO,aAAa,SAAS,KAAK;;GAGpC,MAAM,MAAM,SAAS,WAAW,UAAU,IAAI;AAC9C,OAAI,IAEF,EADY,IAAI,SAAS,QAAQ,KAAK,kBAAkB,KAAK,cACzD,IAAI,IAAI,MAAM,IAAI,QAAQ;AAGhC,UAAO,UAAU;IACjB,EAEc,IAAI,MAAM,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK,YAAY,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;;CAG7F,MAAc,UACZ,MAMA,gBACuB;EACvB,MAAM,iBAAiBA,OAAK,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK;EAO9D,MAAM,UANoD;GACxD,OAAO;GACP,QAAQ;GACR,OAAO;GACP,QAAQ;GACT,CACwBA,OAAK,QAAQ,KAAK,KAAK;EAChD,MAAM,WAAW,MAAMD,KAAG,SAAS,eAAe,EAAE,UAAU;AAE9D,MAAI,CAAC,QACH,QAAO;GACL,GAAG;GACH;GACD;EAGH,MAAM,WAAW,KAAK,SAAS;EAE/B,MAAM,MAAM,MAAM,MAAM,gBAAgB,SAAS,EAC/C,SACD,CAAC;AAEF,MAAI,IAAI,OAAO,SAAS,EACtB,OAAM,IAAI,MAAM,wBAAwB,eAAe,MAAM,IAAI,OAAO,KAAK,KAAK,GAAG;EAGvF,MAAM,IAAI,IAAI,YAAY,QAAQ;EAClC,MAAM,MAAM;GAAE,WAAW,KAAK;GAAW;GAAM;AAE/C,sBAAoB,IAAI,SAAS,IAAI,cAAc;GACjD,IAAI,WAAsB;IACxB,MAAM;IACK;IACZ;GACD,MAAM,YAAY,KAAK,UAAU,aAAa,KAAK,SAAS;GAC5D,MAAM,oBAAoB,SAAS,IAAI,gBAAgB,gBAAgB,UAAU;AACjF,OAAI,kBAAkB,SAAS,CAAC,kBAAkB,KAChD,QAAO,eAAe,YAAY,UAAU,UAAU,IAAI,GAAG,SAAS;AAGxE,cAAW;IACT,MAAM;IACN,MAAM,kBAAkB;IACzB;AAGD,OAAI,CAAC,WAAW,KAAK,SAAS,KAAK,kBAAkB,KAAK,CACxD,YAAW;IACT,MAAM;IACN,KAAK,SAAS,oBAAoB,UAAU;IAC5C;IACD;QACI;IACL,MAAM,MAAM,SAAS,gBAAgB,kBAAkB,KAAK;AAC5D,QAAI,IACF,YAAW;KACT,MAAM;KACN,UAAU;MACR,MAAM;MACN,WAAW,IAAI;MACf,MAAM,IAAI;MACX;KACF;;AAIL,UAAO,eAAe,YAAY,UAAU,UAAU,IAAI,GAAG,SAAS;IACtE;AAEF,SAAO;GACL,GAAG;GACH,SAAS,EAAE,UAAU;GACtB;;;AAIL,SAAgB,kBACd,GACA,WACA,YACuB;CACvB,MAAM,OAAO,EAAE,WAAW,MAAM,SAAS,KAAK,SAAS,UAAU;AACjE,KAAI,CAAC,KAAM;CACX,MAAM,OAAO,KAAK,MAAM,KAAK,WAAW;AACxC,KAAI,CAAC,KAAM;AAEX,QAAO;EACL,MAAM;EACN,UAAU;GACR,MAAM;GACN,cAAc,EAAE;GAChB,WAAW;GACX;GACD;EACF;;;;AC3cH,SAAgB,gBACd,MACA,GAAG,OACW;AACd,QAAO;EACL,GAAG;EACH,MAAM;GACJ,GAAG,KAAK;GACR,YAAY,MAAM,KAAK,SAAS,KAAK,KAAK;GAC3C;EACD,YAAY;EACb;;AAGH,eAAsB,sBACpB,KACA,SAYe;CACf,MAAM,EAAE,KAAK,WAAW,OAAO,MAAM,SAAS;AAE9C,KAAI,UAAU;AACZ,QAAME,KAAG,GAAG,KAAK;GACf,WAAW;GACX,OAAO;GACR,CAAC;AACF,UAAQ,IAAI,WAAW,KAAK,WAAW,YAAY,oBAAoB,CAAC,CAAC;;CAG3E,eAAe,YAAY;AAIzB,QAAM,UAHOC,OAAK,KAAK,KAAK,iBAAiB,EAChC,KAAK,UAAU,IAAI,MAAM,MAAM,EAAE,EAElB,IAAI;;CAGlC,MAAM,QAAQ,IAAI,WAAW,IAAI,OAAO,SAAS;AAI/C,QAAM,UAHOA,OAAK,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO,EACnC,KAAK,UAAU,MAAM,MAAM,EAAE,EAEd,IAAI;GAChC;AAEF,OAAM,KAAK,WAAW,CAAC;AACvB,KAAI,gBAAgB,IAClB,MAAK,MAAM,SAAS,IAAI,WACtB,OAAM,KACJ,sBAAsB,OAAO;EAC3B,KAAKA,OAAK,KAAK,KAAK,MAAM,KAAK;EAC/B,KAAK,QAAQ;EACd,CAAC,CACH;AAIL,OAAM,QAAQ,IAAI,MAAM;;AAG1B,eAAe,UAAU,MAAc,SAAiB,MAAM,MAAqB;AACjF,OAAMD,KAAG,MAAMC,OAAK,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AACvD,OAAMD,KAAG,UAAU,MAAM,QAAQ;AAEjC,KAAI,KAAK;EACP,MAAM,QAAQ,OAAO,WAAW,QAAQ,GAAG,MAAM,QAAQ,EAAE;AAE3D,UAAQ,IACN,GAAG,WAAW,YAAY,IAAI,CAAC,GAAGC,OAAK,SAAS,QAAQ,KAAK,EAAE,KAAK,CAAC,GAAG,WAAW,IAAI,GAAG,KAAK,KAAK,GACrG"}
@@ -99,4 +99,4 @@ var LocalRegistryClient = class LocalRegistryClient {
99
99
  //#endregion
100
100
  export { LocalRegistryClient as n, createCache as r, HttpRegistryClient as t };
101
101
 
102
- //# sourceMappingURL=client-YTcWP1iz.js.map
102
+ //# sourceMappingURL=client-C2A4Jf2w.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-YTcWP1iz.js","names":[],"sources":["../src/utils/cache.ts","../src/registry/client.ts"],"sourcesContent":["export interface AsyncCache<V> {\n cached: (\n key: string,\n fn: (\n /**\n * set a cache value before the compute function completes.\n *\n * useful to handle recursive access.\n */\n presolve: (v: V) => void,\n ) => V | Promise<V>,\n ) => V | Promise<V>;\n $value: <T>() => AsyncCache<T>;\n invalidate: (key: string) => void;\n}\n\n/**\n * cache for async resources, finished promises will be resolved into original value, otherwise wrapped with a promise.\n */\nexport function createCache<V>(store = new Map<string, V | Promise<V>>()): AsyncCache<V> {\n return {\n cached(key, fn) {\n let cached = store.get(key);\n if (cached) return cached;\n\n cached = fn((v) => store.set(key, v));\n if (cached instanceof Promise) {\n cached = cached.then((out) => {\n // replace with resolved if still exists\n if (store.has(key)) {\n store.set(key, out);\n }\n\n return out;\n });\n }\n store.set(key, cached);\n return cached;\n },\n invalidate(key) {\n store.delete(key);\n },\n $value<T>() {\n return this as unknown as AsyncCache<T>;\n },\n };\n}\n","import {\n type DownloadedRegistryInfo,\n type Component,\n componentSchema,\n registryInfoSchema,\n} from '@/registry/schema';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport type { LoadedConfig } from '@/config';\nimport { createCache } from '@/utils/cache';\n\nexport interface RegistryClient {\n readonly registryId: string;\n readonly config: LoadedConfig;\n fetchRegistryInfo: () => Promise<DownloadedRegistryInfo>;\n fetchComponent: (name: string) => Promise<Component>;\n hasComponent: (name: string) => Promise<boolean>;\n createLinkedRegistryClient: (registryName: string) => RegistryClient;\n}\n\nconst fetchCache = createCache<unknown>();\n\nexport class HttpRegistryClient implements RegistryClient {\n readonly registryId: string;\n\n constructor(\n readonly baseUrl: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = baseUrl;\n }\n\n async fetchRegistryInfo(baseUrl = this.baseUrl) {\n const url = new URL('_registry.json', `${baseUrl}/`);\n\n return fetchCache.$value<DownloadedRegistryInfo>().cached(url.href, async () => {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);\n }\n\n return registryInfoSchema.parse(await res.json());\n });\n }\n\n async fetchComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n\n return fetchCache.$value<Component>().cached(url.href, async () => {\n const res = await fetch(`${this.baseUrl}/${name}.json`);\n if (!res.ok) {\n if (res.status === 404) {\n throw new Error(`component ${name} not found at ${url.href}`);\n }\n throw new Error(await res.text());\n }\n\n return componentSchema.parse(await res.json());\n });\n }\n\n async hasComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok;\n }\n\n createLinkedRegistryClient(name: string) {\n return new HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);\n }\n}\n\nexport class LocalRegistryClient implements RegistryClient {\n readonly registryId: string;\n private registryInfo: DownloadedRegistryInfo | undefined;\n\n constructor(\n private readonly dir: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = dir;\n }\n\n async fetchRegistryInfo(dir = this.dir) {\n if (this.registryInfo) return this.registryInfo;\n\n const filePath = path.join(dir, '_registry.json');\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`failed to resolve local file \"${filePath}\"`, {\n cause: e,\n });\n });\n\n return (this.registryInfo = registryInfoSchema.parse(out));\n }\n\n async fetchComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`component ${name} not found at ${filePath}`, { cause: e });\n });\n\n return componentSchema.parse(out);\n }\n\n async hasComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n try {\n await fs.stat(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n createLinkedRegistryClient(name: string) {\n return new LocalRegistryClient(path.join(this.dir, name), this.config);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client-C2A4Jf2w.js","names":[],"sources":["../src/utils/cache.ts","../src/registry/client.ts"],"sourcesContent":["export interface AsyncCache<V> {\n cached: (\n key: string,\n fn: (\n /**\n * set a cache value before the compute function completes.\n *\n * useful to handle recursive access.\n */\n presolve: (v: V) => void,\n ) => V | Promise<V>,\n ) => V | Promise<V>;\n $value: <T>() => AsyncCache<T>;\n invalidate: (key: string) => void;\n}\n\n/**\n * cache for async resources, finished promises will be resolved into original value, otherwise wrapped with a promise.\n */\nexport function createCache<V>(store = new Map<string, V | Promise<V>>()): AsyncCache<V> {\n return {\n cached(key, fn) {\n let cached = store.get(key);\n if (cached) return cached;\n\n cached = fn((v) => store.set(key, v));\n if (cached instanceof Promise) {\n cached = cached.then((out) => {\n // replace with resolved if still exists\n if (store.has(key)) {\n store.set(key, out);\n }\n\n return out;\n });\n }\n store.set(key, cached);\n return cached;\n },\n invalidate(key) {\n store.delete(key);\n },\n $value<T>() {\n return this as unknown as AsyncCache<T>;\n },\n };\n}\n","import {\n type DownloadedRegistryInfo,\n type Component,\n componentSchema,\n registryInfoSchema,\n} from '@/registry/schema';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\nimport type { LoadedConfig } from '@/config';\nimport { createCache } from '@/utils/cache';\n\nexport interface RegistryClient {\n readonly registryId: string;\n readonly config: LoadedConfig;\n fetchRegistryInfo: () => Promise<DownloadedRegistryInfo>;\n fetchComponent: (name: string) => Promise<Component>;\n hasComponent: (name: string) => Promise<boolean>;\n createLinkedRegistryClient: (registryName: string) => RegistryClient;\n}\n\nconst fetchCache = createCache<unknown>();\n\nexport class HttpRegistryClient implements RegistryClient {\n readonly registryId: string;\n\n constructor(\n readonly baseUrl: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = baseUrl;\n }\n\n async fetchRegistryInfo(baseUrl = this.baseUrl) {\n const url = new URL('_registry.json', `${baseUrl}/`);\n\n return fetchCache.$value<DownloadedRegistryInfo>().cached(url.href, async () => {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);\n }\n\n return registryInfoSchema.parse(await res.json());\n });\n }\n\n async fetchComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n\n return fetchCache.$value<Component>().cached(url.href, async () => {\n const res = await fetch(`${this.baseUrl}/${name}.json`);\n if (!res.ok) {\n if (res.status === 404) {\n throw new Error(`component ${name} not found at ${url.href}`);\n }\n throw new Error(await res.text());\n }\n\n return componentSchema.parse(await res.json());\n });\n }\n\n async hasComponent(name: string) {\n const url = new URL(`${name}.json`, `${this.baseUrl}/`);\n const res = await fetch(url, { method: 'HEAD' });\n return res.ok;\n }\n\n createLinkedRegistryClient(name: string) {\n return new HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);\n }\n}\n\nexport class LocalRegistryClient implements RegistryClient {\n readonly registryId: string;\n private registryInfo: DownloadedRegistryInfo | undefined;\n\n constructor(\n private readonly dir: string,\n readonly config: LoadedConfig,\n ) {\n this.registryId = dir;\n }\n\n async fetchRegistryInfo(dir = this.dir) {\n if (this.registryInfo) return this.registryInfo;\n\n const filePath = path.join(dir, '_registry.json');\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`failed to resolve local file \"${filePath}\"`, {\n cause: e,\n });\n });\n\n return (this.registryInfo = registryInfoSchema.parse(out));\n }\n\n async fetchComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n const out = await fs\n .readFile(filePath)\n .then((res) => JSON.parse(res.toString()))\n .catch((e) => {\n throw new Error(`component ${name} not found at ${filePath}`, { cause: e });\n });\n\n return componentSchema.parse(out);\n }\n\n async hasComponent(name: string) {\n const filePath = path.join(this.dir, `${name}.json`);\n try {\n await fs.stat(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n createLinkedRegistryClient(name: string) {\n return new LocalRegistryClient(path.join(this.dir, name), this.config);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  //#region src/config.d.ts
4
- declare function createConfigSchema(isSrc: boolean): z.ZodObject<{
4
+ declare const frameworks: readonly ["next", "waku", "react-router", "tanstack-start"];
5
+ type Framework = (typeof frameworks)[number];
6
+ declare function createConfigSchema(): z.ZodObject<{
5
7
  $schema: z.ZodOptional<z.ZodDefault<z.ZodString>>;
6
8
  aliases: z.ZodDefault<z.ZodObject<{
7
9
  uiDir: z.ZodDefault<z.ZodString>;
@@ -15,6 +17,7 @@ declare function createConfigSchema(isSrc: boolean): z.ZodObject<{
15
17
  "radix-ui": "radix-ui";
16
18
  "base-ui": "base-ui";
17
19
  }>>;
20
+ framework: z.ZodDefault<z.ZodLiteral<"next" | "waku" | "react-router" | "tanstack-start">>;
18
21
  commands: z.ZodDefault<z.ZodObject<{
19
22
  format: z.ZodOptional<z.ZodString>;
20
23
  }, z.core.$strip>>;
@@ -28,8 +31,8 @@ declare function createOrLoadConfig(file?: string): Promise<LoadedConfig>;
28
31
  *
29
32
  * @returns the created config, `undefined` if not created
30
33
  */
31
- declare function initConfig(file?: string, src?: boolean): Promise<LoadedConfig | undefined>;
32
- declare function getDefaultConfig(src?: boolean): Promise<{
34
+ declare function initConfig(file?: string): Promise<LoadedConfig | undefined>;
35
+ declare function getDefaultConfig(): Promise<{
33
36
  aliases: {
34
37
  uiDir: string;
35
38
  componentsDir: string;
@@ -39,11 +42,12 @@ declare function getDefaultConfig(src?: boolean): Promise<{
39
42
  };
40
43
  baseDir: string;
41
44
  uiLibrary: "radix-ui" | "base-ui";
45
+ framework: "next" | "waku" | "react-router" | "tanstack-start";
42
46
  commands: {
43
47
  format?: string | undefined;
44
48
  };
45
49
  $schema?: string | undefined;
46
50
  }>;
47
51
  //#endregion
48
- export { getDefaultConfig as a, createOrLoadConfig as i, LoadedConfig as n, initConfig as o, createConfigSchema as r, ConfigInput as t };
49
- //# sourceMappingURL=config-Dyass4D9.d.ts.map
52
+ export { createOrLoadConfig as a, createConfigSchema as i, Framework as n, getDefaultConfig as o, LoadedConfig as r, initConfig as s, ConfigInput as t };
53
+ //# sourceMappingURL=config-Bx-m6awG.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-Bx-m6awG.d.ts","names":[],"sources":["../src/config.ts"],"mappings":";;;cAIM,UAAA;AAAA,KACM,SAAA,WAAoB,UAAA;AAAA,iBAEhB,kBAAA,CAAA,GAAkB,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;KAyD7B,YAAA,GAAe,UAAA,QAAkB,kBAAA;AAAA,KAE1B,WAAA,GAAc,CAAA,CAAE,KAAA,CAAM,YAAA;AAAA,KACtB,YAAA,GAAe,CAAA,CAAE,MAAA,CAAO,YAAA;AAAA,iBAEd,kBAAA,CAAmB,IAAA,YAAsB,OAAA,CAAQ,YAAA;;;;;;iBAejD,UAAA,CAAW,IAAA,YAAsB,OAAA,CAAQ,YAAA;AAAA,iBAezC,gBAAA,CAAA,GAAgB,OAAA"}
package/dist/config.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as getDefaultConfig, i as createOrLoadConfig, n as LoadedConfig, o as initConfig, r as createConfigSchema, t as ConfigInput } from "./config-Dyass4D9.js";
2
- export { ConfigInput, LoadedConfig, createConfigSchema, createOrLoadConfig, getDefaultConfig, initConfig };
1
+ import { a as createOrLoadConfig, i as createConfigSchema, n as Framework, o as getDefaultConfig, r as LoadedConfig, s as initConfig, t as ConfigInput } from "./config-Bx-m6awG.js";
2
+ export { ConfigInput, Framework, LoadedConfig, createConfigSchema, createOrLoadConfig, getDefaultConfig, initConfig };
package/dist/config.js CHANGED
@@ -1,2 +1,75 @@
1
- import { i as initConfig, n as createOrLoadConfig, r as getDefaultConfig, t as createConfigSchema } from "./config-BYrMmXOw.js";
1
+ import fs from "node:fs/promises";
2
+ import { z } from "zod";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ //#region src/config.ts
5
+ const frameworks = [
6
+ "next",
7
+ "waku",
8
+ "react-router",
9
+ "tanstack-start"
10
+ ];
11
+ function createConfigSchema() {
12
+ const defaultAliases = {
13
+ uiDir: "./components/ui",
14
+ componentsDir: "./components",
15
+ layoutDir: "./layouts",
16
+ cssDir: "./styles",
17
+ libDir: "./lib"
18
+ };
19
+ return z.object({
20
+ $schema: z.string().default("node_modules/@fumadocs/cli/dist/schema.json").optional(),
21
+ aliases: z.object({
22
+ uiDir: z.string().default(defaultAliases.uiDir),
23
+ componentsDir: z.string().default(defaultAliases.uiDir),
24
+ layoutDir: z.string().default(defaultAliases.layoutDir),
25
+ cssDir: z.string().default(defaultAliases.componentsDir),
26
+ libDir: z.string().default(defaultAliases.libDir)
27
+ }).default(defaultAliases),
28
+ baseDir: z.string().default(() => existsSync("./src") ? "src" : ""),
29
+ uiLibrary: z.enum(["radix-ui", "base-ui"]).default("radix-ui"),
30
+ framework: z.literal(frameworks).default(() => {
31
+ return detectFrameworkFromPackageJson() ?? "next";
32
+ }),
33
+ commands: z.object({ format: z.string().optional() }).default({})
34
+ });
35
+ }
36
+ function detectFrameworkFromPackageJson(pkgPath = "./package.json") {
37
+ try {
38
+ const pkgRaw = readFileSync(pkgPath, "utf-8");
39
+ const pkg = JSON.parse(pkgRaw);
40
+ const deps = {
41
+ ...pkg.dependencies,
42
+ ...pkg.devDependencies
43
+ };
44
+ if (deps["next"]) return "next";
45
+ if (deps["waku"]) return "waku";
46
+ if (deps["react-router"] || deps["react-router-dom"]) return "react-router";
47
+ if (deps["@tanstack/react-start"]) return "tanstack-start";
48
+ } catch {
49
+ return;
50
+ }
51
+ }
52
+ async function createOrLoadConfig(file = "./cli.json") {
53
+ const inited = await initConfig(file);
54
+ if (inited) return inited;
55
+ const content = (await fs.readFile(file)).toString();
56
+ return createConfigSchema().parse(JSON.parse(content));
57
+ }
58
+ /**
59
+ * Write new config, skip if a config already exists
60
+ *
61
+ * @returns the created config, `undefined` if not created
62
+ */
63
+ async function initConfig(file = "./cli.json") {
64
+ if (await fs.stat(file).then(() => true).catch(() => false)) return;
65
+ const defaultConfig = await getDefaultConfig();
66
+ await fs.writeFile(file, JSON.stringify(defaultConfig, null, 2));
67
+ return defaultConfig;
68
+ }
69
+ async function getDefaultConfig() {
70
+ return createConfigSchema().parse({});
71
+ }
72
+ //#endregion
2
73
  export { createConfigSchema, createOrLoadConfig, getDefaultConfig, initConfig };
74
+
75
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport { z } from 'zod';\nimport { existsSync, readFileSync } from 'node:fs';\n\nconst frameworks = ['next', 'waku', 'react-router', 'tanstack-start'] as const;\nexport type Framework = (typeof frameworks)[number];\n\nexport function createConfigSchema() {\n const defaultAliases = {\n uiDir: './components/ui',\n componentsDir: './components',\n layoutDir: './layouts',\n cssDir: './styles',\n libDir: './lib',\n };\n\n return z.object({\n $schema: z.string().default('node_modules/@fumadocs/cli/dist/schema.json').optional(),\n aliases: z\n .object({\n uiDir: z.string().default(defaultAliases.uiDir),\n componentsDir: z.string().default(defaultAliases.uiDir),\n layoutDir: z.string().default(defaultAliases.layoutDir),\n cssDir: z.string().default(defaultAliases.componentsDir),\n libDir: z.string().default(defaultAliases.libDir),\n })\n .default(defaultAliases),\n\n baseDir: z.string().default(() => (existsSync('./src') ? 'src' : '')),\n uiLibrary: z.enum(['radix-ui', 'base-ui']).default('radix-ui'),\n framework: z.literal(frameworks).default(() => {\n return detectFrameworkFromPackageJson() ?? 'next';\n }),\n\n commands: z\n .object({\n /**\n * command to format output code automatically\n */\n format: z.string().optional(),\n })\n .default({}),\n });\n}\n\nfunction detectFrameworkFromPackageJson(pkgPath = './package.json'): Framework | undefined {\n try {\n const pkgRaw = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgRaw);\n\n const deps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n if (deps['next']) return 'next';\n if (deps['waku']) return 'waku';\n if (deps['react-router'] || deps['react-router-dom']) return 'react-router';\n if (deps['@tanstack/react-start']) return 'tanstack-start';\n } catch {\n return;\n }\n}\n\ntype ConfigSchema = ReturnType<typeof createConfigSchema>;\n\nexport type ConfigInput = z.input<ConfigSchema>;\nexport type LoadedConfig = z.output<ConfigSchema>;\n\nexport async function createOrLoadConfig(file = './cli.json'): Promise<LoadedConfig> {\n const inited = await initConfig(file);\n if (inited) return inited;\n\n const content = (await fs.readFile(file)).toString();\n const configSchema = createConfigSchema();\n\n return configSchema.parse(JSON.parse(content));\n}\n\n/**\n * Write new config, skip if a config already exists\n *\n * @returns the created config, `undefined` if not created\n */\nexport async function initConfig(file = './cli.json'): Promise<LoadedConfig | undefined> {\n if (\n await fs\n .stat(file)\n .then(() => true)\n .catch(() => false)\n ) {\n return;\n }\n\n const defaultConfig = await getDefaultConfig();\n await fs.writeFile(file, JSON.stringify(defaultConfig, null, 2));\n return defaultConfig;\n}\n\nexport async function getDefaultConfig() {\n return createConfigSchema().parse({} satisfies ConfigInput);\n}\n"],"mappings":";;;;AAIA,MAAM,aAAa;CAAC;CAAQ;CAAQ;CAAgB;CAAiB;AAGrE,SAAgB,qBAAqB;CACnC,MAAM,iBAAiB;EACrB,OAAO;EACP,eAAe;EACf,WAAW;EACX,QAAQ;EACR,QAAQ;EACT;AAED,QAAO,EAAE,OAAO;EACd,SAAS,EAAE,QAAQ,CAAC,QAAQ,8CAA8C,CAAC,UAAU;EACrF,SAAS,EACN,OAAO;GACN,OAAO,EAAE,QAAQ,CAAC,QAAQ,eAAe,MAAM;GAC/C,eAAe,EAAE,QAAQ,CAAC,QAAQ,eAAe,MAAM;GACvD,WAAW,EAAE,QAAQ,CAAC,QAAQ,eAAe,UAAU;GACvD,QAAQ,EAAE,QAAQ,CAAC,QAAQ,eAAe,cAAc;GACxD,QAAQ,EAAE,QAAQ,CAAC,QAAQ,eAAe,OAAO;GAClD,CAAC,CACD,QAAQ,eAAe;EAE1B,SAAS,EAAE,QAAQ,CAAC,cAAe,WAAW,QAAQ,GAAG,QAAQ,GAAI;EACrE,WAAW,EAAE,KAAK,CAAC,YAAY,UAAU,CAAC,CAAC,QAAQ,WAAW;EAC9D,WAAW,EAAE,QAAQ,WAAW,CAAC,cAAc;AAC7C,UAAO,gCAAgC,IAAI;IAC3C;EAEF,UAAU,EACP,OAAO,EAIN,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAC9B,CAAC,CACD,QAAQ,EAAE,CAAC;EACf,CAAC;;AAGJ,SAAS,+BAA+B,UAAU,kBAAyC;AACzF,KAAI;EACF,MAAM,SAAS,aAAa,SAAS,QAAQ;EAC7C,MAAM,MAAM,KAAK,MAAM,OAAO;EAE9B,MAAM,OAAO;GACX,GAAG,IAAI;GACP,GAAG,IAAI;GACR;AAED,MAAI,KAAK,QAAS,QAAO;AACzB,MAAI,KAAK,QAAS,QAAO;AACzB,MAAI,KAAK,mBAAmB,KAAK,oBAAqB,QAAO;AAC7D,MAAI,KAAK,yBAA0B,QAAO;SACpC;AACN;;;AASJ,eAAsB,mBAAmB,OAAO,cAAqC;CACnF,MAAM,SAAS,MAAM,WAAW,KAAK;AACrC,KAAI,OAAQ,QAAO;CAEnB,MAAM,WAAW,MAAM,GAAG,SAAS,KAAK,EAAE,UAAU;AAGpD,QAFqB,oBAAoB,CAErB,MAAM,KAAK,MAAM,QAAQ,CAAC;;;;;;;AAQhD,eAAsB,WAAW,OAAO,cAAiD;AACvF,KACE,MAAM,GACH,KAAK,KAAK,CACV,WAAW,KAAK,CAChB,YAAY,MAAM,CAErB;CAGF,MAAM,gBAAgB,MAAM,kBAAkB;AAC9C,OAAM,GAAG,UAAU,MAAM,KAAK,UAAU,eAAe,MAAM,EAAE,CAAC;AAChE,QAAO;;AAGT,eAAsB,mBAAmB;AACvC,QAAO,oBAAoB,CAAC,MAAM,EAAE,CAAuB"}
@@ -15,4 +15,4 @@ function isRelative(from, to) {
15
15
  //#endregion
16
16
  export { isRelative as n, exists as t };
17
17
 
18
- //# sourceMappingURL=fs-CigSthjp.js.map
18
+ //# sourceMappingURL=fs-C3j4H046.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs-CigSthjp.js","names":[],"sources":["../src/utils/fs.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function exists(pathLike: string): Promise<boolean> {\n try {\n await fs.access(pathLike);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isRelative(from: string, to: string): boolean {\n return !path.relative(from, to).startsWith(`..${path.sep}`);\n}\n"],"mappings":";;;AAGA,eAAsB,OAAO,UAAoC;AAC/D,KAAI;AACF,QAAM,GAAG,OAAO,SAAS;AACzB,SAAO;SACD;AACN,SAAO;;;AAIX,SAAgB,WAAW,MAAc,IAAqB;AAC5D,QAAO,CAAC,KAAK,SAAS,MAAM,GAAG,CAAC,WAAW,KAAK,KAAK,MAAM"}
1
+ {"version":3,"file":"fs-C3j4H046.js","names":[],"sources":["../src/utils/fs.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function exists(pathLike: string): Promise<boolean> {\n try {\n await fs.access(pathLike);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function isRelative(from: string, to: string): boolean {\n return !path.relative(from, to).startsWith(`..${path.sep}`);\n}\n"],"mappings":";;;AAGA,eAAsB,OAAO,UAAoC;AAC/D,KAAI;AACF,QAAM,GAAG,OAAO,SAAS;AACzB,SAAO;SACD;AACN,SAAO;;;AAIX,SAAgB,WAAW,MAAc,IAAqB;AAC5D,QAAO,CAAC,KAAK,SAAS,MAAM,GAAG,CAAC,WAAW,KAAK,KAAK,MAAM"}
@@ -64,7 +64,61 @@ function transformSpecifiers(program, s, transformSpecifier) {
64
64
  }
65
65
  }).visit(program);
66
66
  }
67
+ function getImportedBinding(spec) {
68
+ if (spec.type === "ImportSpecifier") {
69
+ let imported;
70
+ switch (spec.imported.type) {
71
+ case "Identifier":
72
+ imported = spec.imported.name;
73
+ break;
74
+ case "Literal":
75
+ imported = spec.imported.value;
76
+ break;
77
+ }
78
+ return {
79
+ imported,
80
+ local: spec.local.name
81
+ };
82
+ }
83
+ if (spec.type === "ImportDefaultSpecifier") return {
84
+ imported: "default",
85
+ local: spec.local.name
86
+ };
87
+ return null;
88
+ }
89
+ function collectMacroBindings(program, name) {
90
+ const locals = /* @__PURE__ */ new Set();
91
+ const importDecls = [];
92
+ const seenDecl = /* @__PURE__ */ new Set();
93
+ new Visitor({ ImportDeclaration(node) {
94
+ for (const spec of node.specifiers) {
95
+ const b = getImportedBinding(spec);
96
+ if (!b || b.imported !== name) continue;
97
+ locals.add(b.local);
98
+ if (!seenDecl.has(node)) {
99
+ seenDecl.add(node);
100
+ importDecls.push(node);
101
+ }
102
+ }
103
+ } }).visit(program);
104
+ if (locals.size === 0) return null;
105
+ return {
106
+ importDecls,
107
+ locals
108
+ };
109
+ }
110
+ //#endregion
111
+ //#region src/registry/protocols/import.ts
112
+ function encodeImport(file) {
113
+ if (file.type === "route-handler") return `route-handler:${file.route}`;
114
+ return `:${file.target ?? file.path}`;
115
+ }
116
+ function decodeImport(s) {
117
+ if (s.startsWith(":")) return { target: s.slice(1) };
118
+ if (s.startsWith("route-handler:")) return { route: s.slice(14) };
119
+ return { raw: s };
120
+ }
67
121
  //#endregion
68
- export { transformSpecifiers as n, typescriptExtensions as r, toImportSpecifier as t };
122
+ export { transformSpecifiers as a, toImportSpecifier as i, encodeImport as n, typescriptExtensions as o, collectMacroBindings as r, decodeImport as t };
69
123
 
70
- //# sourceMappingURL=ast-BRNdmLn5.js.map
124
+ //# sourceMappingURL=import-CSbSteB3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-CSbSteB3.js","names":[],"sources":["../src/constants.ts","../src/utils/ast.ts","../src/registry/protocols/import.ts"],"sourcesContent":["export const typescriptExtensions = ['.ts', '.tsx', '.js', '.jsx'];\n","import path from 'node:path';\nimport { typescriptExtensions } from '@/constants';\nimport { type Program, Visitor } from 'oxc-parser';\nimport type MagicString from 'magic-string';\nimport type { ImportDeclaration, ImportDeclarationSpecifier } from '@oxc-project/types';\n\n/**\n * Return the import modifier for `sourceFile` to import `referenceFile`\n *\n * @example\n * ```ts\n * toReferencePath('index.ts', 'dir/hello.ts')\n * // should output './dir/hello'\n * ```\n */\nexport function toImportSpecifier(sourceFile: string, referenceFile: string): string {\n const extname = path.extname(referenceFile);\n const removeExt = typescriptExtensions.includes(extname);\n\n let importPath = path\n .relative(\n path.dirname(sourceFile),\n removeExt ? referenceFile.substring(0, referenceFile.length - extname.length) : referenceFile,\n )\n .replaceAll(path.sep, '/');\n\n if (removeExt && importPath.endsWith('/index')) {\n importPath = importPath.slice(0, -'/index'.length);\n }\n\n return importPath.startsWith('../') ? importPath : `./${importPath}`;\n}\n\nexport function transformSpecifiers(\n program: Program,\n s: MagicString,\n transformSpecifier: (value: string) => string | undefined,\n) {\n new Visitor({\n // static imports\n ImportDeclaration(node) {\n const source = node.source;\n const out = transformSpecifier(source.value);\n if (out) {\n s.update(source.start + 1, source.end - 1, out);\n source.value = out;\n }\n },\n // dynamic imports\n ImportExpression(node) {\n if (node.source.type === 'Literal') {\n const source = node.source;\n const out = transformSpecifier(source.value as string);\n if (out) {\n s.update(source.start + 1, source.end - 1, out);\n source.value = out;\n }\n }\n },\n // exports\n ExportAllDeclaration(node) {\n const source = node.source;\n const out = transformSpecifier(source.value);\n if (out) {\n s.update(source.start + 1, source.end - 1, out);\n source.value = out;\n }\n },\n ExportNamedDeclaration(node) {\n const source = node.source;\n if (!source) return;\n const out = transformSpecifier(source.value);\n if (out) {\n s.update(source.start + 1, source.end - 1, out);\n source.value = out;\n }\n },\n }).visit(program);\n}\n\nfunction getImportedBinding(\n spec: ImportDeclarationSpecifier,\n): { imported: string; local: string } | null {\n if (spec.type === 'ImportSpecifier') {\n let imported: string;\n switch (spec.imported.type) {\n case 'Identifier':\n imported = spec.imported.name;\n break;\n case 'Literal':\n imported = spec.imported.value;\n break;\n }\n\n return {\n imported,\n local: spec.local.name,\n };\n }\n if (spec.type === 'ImportDefaultSpecifier') {\n return { imported: 'default', local: spec.local.name };\n }\n return null;\n}\n\nexport function collectMacroBindings(\n program: Program,\n name: string,\n): { importDecls: ImportDeclaration[]; locals: Set<string> } | null {\n const locals = new Set<string>();\n const importDecls: ImportDeclaration[] = [];\n const seenDecl = new Set<ImportDeclaration>();\n\n new Visitor({\n ImportDeclaration(node: ImportDeclaration) {\n for (const spec of node.specifiers) {\n const b = getImportedBinding(spec);\n if (!b || b.imported !== name) continue;\n\n locals.add(b.local);\n\n if (!seenDecl.has(node)) {\n seenDecl.add(node);\n importDecls.push(node);\n }\n }\n },\n }).visit(program);\n\n if (locals.size === 0) return null;\n return { importDecls, locals };\n}\n","import type { ComponentFile } from '@/build';\nimport type { CompiledFile } from '../schema';\n\nexport type ImportInfo =\n | {\n raw: string;\n }\n | {\n target: string;\n }\n | {\n route: string;\n };\n\nexport function encodeImport(file: ComponentFile | CompiledFile): string {\n if (file.type === 'route-handler') return `route-handler:${file.route}`;\n return `:${file.target ?? file.path}`;\n}\n\nexport function decodeImport(s: string): ImportInfo {\n if (s.startsWith(':'))\n return {\n target: s.slice(1),\n };\n\n if (s.startsWith('route-handler:'))\n return {\n route: s.slice('route-handler:'.length),\n };\n\n return { raw: s };\n}\n"],"mappings":";;;AAAA,MAAa,uBAAuB;CAAC;CAAO;CAAQ;CAAO;CAAO;;;;;;;;;;;;ACelE,SAAgB,kBAAkB,YAAoB,eAA+B;CACnF,MAAM,UAAU,KAAK,QAAQ,cAAc;CAC3C,MAAM,YAAY,qBAAqB,SAAS,QAAQ;CAExD,IAAI,aAAa,KACd,SACC,KAAK,QAAQ,WAAW,EACxB,YAAY,cAAc,UAAU,GAAG,cAAc,SAAS,QAAQ,OAAO,GAAG,cACjF,CACA,WAAW,KAAK,KAAK,IAAI;AAE5B,KAAI,aAAa,WAAW,SAAS,SAAS,CAC5C,cAAa,WAAW,MAAM,GAAG,GAAiB;AAGpD,QAAO,WAAW,WAAW,MAAM,GAAG,aAAa,KAAK;;AAG1D,SAAgB,oBACd,SACA,GACA,oBACA;AACA,KAAI,QAAQ;EAEV,kBAAkB,MAAM;GACtB,MAAM,SAAS,KAAK;GACpB,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,OAAI,KAAK;AACP,MAAE,OAAO,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,IAAI;AAC/C,WAAO,QAAQ;;;EAInB,iBAAiB,MAAM;AACrB,OAAI,KAAK,OAAO,SAAS,WAAW;IAClC,MAAM,SAAS,KAAK;IACpB,MAAM,MAAM,mBAAmB,OAAO,MAAgB;AACtD,QAAI,KAAK;AACP,OAAE,OAAO,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,IAAI;AAC/C,YAAO,QAAQ;;;;EAKrB,qBAAqB,MAAM;GACzB,MAAM,SAAS,KAAK;GACpB,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,OAAI,KAAK;AACP,MAAE,OAAO,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,IAAI;AAC/C,WAAO,QAAQ;;;EAGnB,uBAAuB,MAAM;GAC3B,MAAM,SAAS,KAAK;AACpB,OAAI,CAAC,OAAQ;GACb,MAAM,MAAM,mBAAmB,OAAO,MAAM;AAC5C,OAAI,KAAK;AACP,MAAE,OAAO,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,IAAI;AAC/C,WAAO,QAAQ;;;EAGpB,CAAC,CAAC,MAAM,QAAQ;;AAGnB,SAAS,mBACP,MAC4C;AAC5C,KAAI,KAAK,SAAS,mBAAmB;EACnC,IAAI;AACJ,UAAQ,KAAK,SAAS,MAAtB;GACE,KAAK;AACH,eAAW,KAAK,SAAS;AACzB;GACF,KAAK;AACH,eAAW,KAAK,SAAS;AACzB;;AAGJ,SAAO;GACL;GACA,OAAO,KAAK,MAAM;GACnB;;AAEH,KAAI,KAAK,SAAS,yBAChB,QAAO;EAAE,UAAU;EAAW,OAAO,KAAK,MAAM;EAAM;AAExD,QAAO;;AAGT,SAAgB,qBACd,SACA,MACkE;CAClE,MAAM,yBAAS,IAAI,KAAa;CAChC,MAAM,cAAmC,EAAE;CAC3C,MAAM,2BAAW,IAAI,KAAwB;AAE7C,KAAI,QAAQ,EACV,kBAAkB,MAAyB;AACzC,OAAK,MAAM,QAAQ,KAAK,YAAY;GAClC,MAAM,IAAI,mBAAmB,KAAK;AAClC,OAAI,CAAC,KAAK,EAAE,aAAa,KAAM;AAE/B,UAAO,IAAI,EAAE,MAAM;AAEnB,OAAI,CAAC,SAAS,IAAI,KAAK,EAAE;AACvB,aAAS,IAAI,KAAK;AAClB,gBAAY,KAAK,KAAK;;;IAI7B,CAAC,CAAC,MAAM,QAAQ;AAEjB,KAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAO;EAAE;EAAa;EAAQ;;;;ACpHhC,SAAgB,aAAa,MAA4C;AACvE,KAAI,KAAK,SAAS,gBAAiB,QAAO,iBAAiB,KAAK;AAChE,QAAO,IAAI,KAAK,UAAU,KAAK;;AAGjC,SAAgB,aAAa,GAAuB;AAClD,KAAI,EAAE,WAAW,IAAI,CACnB,QAAO,EACL,QAAQ,EAAE,MAAM,EAAE,EACnB;AAEH,KAAI,EAAE,WAAW,iBAAiB,CAChC,QAAO,EACL,OAAO,EAAE,MAAM,GAAwB,EACxC;AAEH,QAAO,EAAE,KAAK,GAAG"}