@fumadocs/cli 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,829 +1,626 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/index.ts
4
- import fs6 from "fs/promises";
5
- import path5 from "path";
2
+ import { n as transformSpecifiers, r as typescriptExtensions, t as toImportSpecifier } from "./ast-DFGM1gEn.js";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
6
5
  import { Command } from "commander";
7
- import picocolors3 from "picocolors";
8
-
9
- // src/config.ts
10
- import fs2 from "fs/promises";
6
+ import picocolors from "picocolors";
7
+ import { z } from "zod";
8
+ import { x } from "tinyexec";
9
+ import { cancel, confirm, group, intro, isCancel, log, multiselect, outro, select, spinner } from "@clack/prompts";
10
+ import { parse } from "oxc-parser";
11
+ import { detect } from "package-manager-detector";
12
+ import MagicString from "magic-string";
11
13
 
12
- // src/utils/fs.ts
13
- import fs from "fs/promises";
14
- import path from "path";
14
+ //#region src/utils/fs.ts
15
15
  async function exists(pathLike) {
16
- try {
17
- await fs.access(pathLike);
18
- return true;
19
- } catch {
20
- return false;
21
- }
16
+ try {
17
+ await fs.access(pathLike);
18
+ return true;
19
+ } catch {
20
+ return false;
21
+ }
22
22
  }
23
23
 
24
- // src/utils/is-src.ts
24
+ //#endregion
25
+ //#region src/utils/is-src.ts
25
26
  async function isSrc() {
26
- return exists("./src");
27
+ return exists("./src");
27
28
  }
28
29
 
29
- // src/config.ts
30
- import { z } from "zod";
31
- function createConfigSchema(isSrc2) {
32
- const defaultAliases = {
33
- uiDir: "./components/ui",
34
- componentsDir: "./components",
35
- blockDir: "./components",
36
- cssDir: "./styles",
37
- libDir: "./lib"
38
- };
39
- return z.object({
40
- $schema: z.string().default(
41
- isSrc2 ? "node_modules/@fumadocs/cli/dist/schema/src.json" : "node_modules/@fumadocs/cli/dist/schema/default.json"
42
- ).optional(),
43
- aliases: z.object({
44
- uiDir: z.string().default(defaultAliases.uiDir),
45
- componentsDir: z.string().default(defaultAliases.uiDir),
46
- blockDir: z.string().default(defaultAliases.blockDir),
47
- cssDir: z.string().default(defaultAliases.componentsDir),
48
- libDir: z.string().default(defaultAliases.libDir)
49
- }).default(defaultAliases),
50
- baseDir: z.string().default(isSrc2 ? "src" : ""),
51
- uiLibrary: z.enum(["radix-ui", "base-ui"]).default("radix-ui"),
52
- commands: z.object({
53
- /**
54
- * command to format output code automatically
55
- */
56
- format: z.string().optional()
57
- }).default({})
58
- });
30
+ //#endregion
31
+ //#region src/config.ts
32
+ function createConfigSchema(isSrc$1) {
33
+ const defaultAliases = {
34
+ uiDir: "./components/ui",
35
+ componentsDir: "./components",
36
+ blockDir: "./components",
37
+ cssDir: "./styles",
38
+ libDir: "./lib"
39
+ };
40
+ return z.object({
41
+ $schema: z.string().default(isSrc$1 ? "node_modules/@fumadocs/cli/dist/schema/src.json" : "node_modules/@fumadocs/cli/dist/schema/default.json").optional(),
42
+ aliases: z.object({
43
+ uiDir: z.string().default(defaultAliases.uiDir),
44
+ componentsDir: z.string().default(defaultAliases.uiDir),
45
+ blockDir: z.string().default(defaultAliases.blockDir),
46
+ cssDir: z.string().default(defaultAliases.componentsDir),
47
+ libDir: z.string().default(defaultAliases.libDir)
48
+ }).default(defaultAliases),
49
+ baseDir: z.string().default(isSrc$1 ? "src" : ""),
50
+ uiLibrary: z.enum(["radix-ui", "base-ui"]).default("radix-ui"),
51
+ commands: z.object({ format: z.string().optional() }).default({})
52
+ });
59
53
  }
60
54
  async function createOrLoadConfig(file = "./cli.json") {
61
- const inited = await initConfig(file);
62
- if (inited) return inited;
63
- const content = (await fs2.readFile(file)).toString();
64
- const src = await isSrc();
65
- const configSchema = createConfigSchema(src);
66
- return configSchema.parse(JSON.parse(content));
55
+ const inited = await initConfig(file);
56
+ if (inited) return inited;
57
+ const content = (await fs.readFile(file)).toString();
58
+ return createConfigSchema(await isSrc()).parse(JSON.parse(content));
67
59
  }
60
+ /**
61
+ * Write new config, skip if a config already exists
62
+ *
63
+ * @returns the created config, `undefined` if not created
64
+ */
68
65
  async function initConfig(file = "./cli.json", src) {
69
- if (await fs2.stat(file).then(() => true).catch(() => false)) {
70
- return;
71
- }
72
- const defaultConfig = createConfigSchema(src ?? await isSrc()).parse(
73
- {}
74
- );
75
- await fs2.writeFile(file, JSON.stringify(defaultConfig, null, 2));
76
- return defaultConfig;
66
+ if (await fs.stat(file).then(() => true).catch(() => false)) return;
67
+ const defaultConfig = createConfigSchema(src ?? await isSrc()).parse({});
68
+ await fs.writeFile(file, JSON.stringify(defaultConfig, null, 2));
69
+ return defaultConfig;
77
70
  }
78
71
 
79
- // src/commands/file-tree.ts
80
- var scanned = ["file", "directory", "link"];
72
+ //#endregion
73
+ //#region src/commands/file-tree.ts
74
+ const scanned = [
75
+ "file",
76
+ "directory",
77
+ "link"
78
+ ];
81
79
  function treeToMdx(input, noRoot = false) {
82
- function toNode(item) {
83
- if (item.type === "file" || item.type === "link") {
84
- return `<File name=${JSON.stringify(item.name)} />`;
85
- }
86
- if (item.type === "directory") {
87
- if (item.contents.length === 1 && "name" in item.contents[0]) {
88
- const child = item.contents[0];
89
- return toNode({
90
- ...child,
91
- name: `${item.name}/${child.name}`
92
- });
93
- }
94
- return `<Folder name=${JSON.stringify(item.name)}>
80
+ function toNode(item) {
81
+ if (item.type === "file" || item.type === "link") return `<File name=${JSON.stringify(item.name)} />`;
82
+ if (item.type === "directory") {
83
+ if (item.contents.length === 1 && "name" in item.contents[0]) {
84
+ const child = item.contents[0];
85
+ return toNode({
86
+ ...child,
87
+ name: `${item.name}/${child.name}`
88
+ });
89
+ }
90
+ return `<Folder name=${JSON.stringify(item.name)}>
95
91
  ${item.contents.map(toNode).filter(Boolean).join("\n")}
96
92
  </Folder>`;
97
- }
98
- return "";
99
- }
100
- let children = input.filter((v) => scanned.includes(v.type));
101
- if (noRoot && children.length === 1 && input[0].type === "directory") {
102
- children = input[0].contents;
103
- }
104
- return `<Files>
93
+ }
94
+ return "";
95
+ }
96
+ let children = input.filter((v) => scanned.includes(v.type));
97
+ if (noRoot && children.length === 1 && input[0].type === "directory") children = input[0].contents;
98
+ return `<Files>
105
99
  ${children.map(toNode).filter(Boolean).join("\n")}
106
100
  </Files>`;
107
101
  }
108
102
  function treeToJavaScript(input, noRoot, importName = "fumadocs-ui/components/files") {
109
- return `import { File, Files, Folder } from ${JSON.stringify(importName)}
103
+ return `import { File, Files, Folder } from ${JSON.stringify(importName)}
110
104
 
111
105
  export default (${treeToMdx(input, noRoot)})`;
112
106
  }
113
107
 
114
- // src/utils/file-tree/run-tree.ts
115
- import { x } from "tinyexec";
108
+ //#endregion
109
+ //#region src/utils/file-tree/run-tree.ts
116
110
  async function runTree(args) {
117
- const out = await x("tree", [args, "--gitignore", "--prune", "-J"]);
118
- try {
119
- return JSON.parse(out.stdout);
120
- } catch (e) {
121
- throw new Error("failed to run `tree` command", {
122
- cause: e
123
- });
124
- }
125
- }
126
-
127
- // package.json
128
- var package_default = {
129
- name: "@fumadocs/cli",
130
- version: "1.2.0",
131
- description: "The CLI tool for Fumadocs",
132
- keywords: [
133
- "NextJs",
134
- "Docs",
135
- "Fumadocs"
136
- ],
137
- homepage: "https://fumadocs.dev",
138
- repository: "github:fuma-nama/fumadocs",
139
- license: "MIT",
140
- author: "Fuma Nama",
141
- type: "module",
142
- exports: {
143
- "./build": {
144
- import: "./dist/build/index.js",
145
- types: "./dist/build/index.d.ts"
146
- }
147
- },
148
- main: "./dist/index.js",
149
- bin: {
150
- fumadocs: "./dist/index.js"
151
- },
152
- files: [
153
- "dist/*"
154
- ],
155
- scripts: {
156
- build: "tsup",
157
- clean: "rimraf dist",
158
- dev: "tsup --watch",
159
- lint: "eslint .",
160
- "types:check": "tsc --noEmit"
161
- },
162
- dependencies: {
163
- "@clack/prompts": "^0.11.0",
164
- commander: "^14.0.2",
165
- "package-manager-detector": "^1.6.0",
166
- picocolors: "^1.1.1",
167
- tinyexec: "^1.0.2",
168
- "ts-morph": "^27.0.2",
169
- zod: "^4.2.1"
170
- },
171
- devDependencies: {
172
- "@types/node": "24.10.2",
173
- "eslint-config-custom": "workspace:*",
174
- shadcn: "3.6.2",
175
- tsconfig: "workspace:*"
176
- },
177
- publishConfig: {
178
- access: "public"
179
- }
180
- };
181
-
182
- // src/commands/customise.ts
183
- import { cancel, group, intro as intro2, log as log4, outro as outro3, select } from "@clack/prompts";
184
- import picocolors2 from "picocolors";
185
-
186
- // src/commands/add.ts
187
- import {
188
- intro,
189
- isCancel as isCancel3,
190
- log as log3,
191
- multiselect,
192
- outro as outro2,
193
- spinner as spinner2
194
- } from "@clack/prompts";
195
- import picocolors from "picocolors";
196
-
197
- // src/registry/installer/index.ts
198
- import path4 from "path";
199
- import fs5 from "fs/promises";
200
- import { confirm as confirm2, isCancel as isCancel2, log as log2, outro } from "@clack/prompts";
201
-
202
- // src/utils/typescript.ts
203
- import { Project } from "ts-morph";
204
- function createEmptyProject() {
205
- return new Project({
206
- compilerOptions: {}
207
- });
111
+ const out = await x("tree", [
112
+ args,
113
+ "--gitignore",
114
+ "--prune",
115
+ "-J"
116
+ ]);
117
+ try {
118
+ return JSON.parse(out.stdout);
119
+ } catch (e) {
120
+ throw new Error("failed to run `tree` command", { cause: e });
121
+ }
208
122
  }
209
123
 
210
- // src/constants.ts
211
- var typescriptExtensions = [".ts", ".tsx", ".js", ".jsx"];
124
+ //#endregion
125
+ //#region package.json
126
+ var version = "1.2.2";
212
127
 
213
- // src/utils/ast.ts
214
- import path2 from "path";
215
- function toImportSpecifier(sourceFile, referenceFile) {
216
- const extname = path2.extname(referenceFile);
217
- const removeExt = typescriptExtensions.includes(extname);
218
- let importPath = path2.relative(
219
- path2.dirname(sourceFile),
220
- removeExt ? referenceFile.substring(0, referenceFile.length - extname.length) : referenceFile
221
- ).replaceAll(path2.sep, "/");
222
- if (removeExt && importPath.endsWith("/index")) {
223
- importPath = importPath.slice(0, -"/index".length);
224
- }
225
- return importPath.startsWith("../") ? importPath : `./${importPath}`;
226
- }
227
-
228
- // src/registry/schema.ts
229
- import { z as z2 } from "zod";
230
- var namespaces = [
231
- "components",
232
- "lib",
233
- "css",
234
- "route",
235
- "ui",
236
- "block"
128
+ //#endregion
129
+ //#region src/registry/schema.ts
130
+ const namespaces = [
131
+ "components",
132
+ "lib",
133
+ "css",
134
+ "route",
135
+ "ui",
136
+ "block"
237
137
  ];
238
- var indexSchema = z2.object({
239
- name: z2.string(),
240
- title: z2.string().optional(),
241
- description: z2.string().optional()
138
+ const indexSchema = z.object({
139
+ name: z.string(),
140
+ title: z.string().optional(),
141
+ description: z.string().optional()
242
142
  });
243
- var fileSchema = z2.object({
244
- type: z2.literal(namespaces),
245
- path: z2.string(),
246
- target: z2.string().optional(),
247
- content: z2.string()
143
+ const fileSchema = z.object({
144
+ type: z.literal(namespaces),
145
+ path: z.string(),
146
+ target: z.string().optional(),
147
+ content: z.string()
248
148
  });
249
- var httpSubComponent = z2.object({
250
- type: z2.literal("http"),
251
- baseUrl: z2.string(),
252
- component: z2.string()
149
+ const httpSubComponent = z.object({
150
+ type: z.literal("http"),
151
+ baseUrl: z.string(),
152
+ component: z.string()
253
153
  });
254
- var componentSchema = z2.object({
255
- name: z2.string(),
256
- title: z2.string().optional(),
257
- description: z2.string().optional(),
258
- files: z2.array(fileSchema),
259
- dependencies: z2.record(z2.string(), z2.string().or(z2.null())),
260
- devDependencies: z2.record(z2.string(), z2.string().or(z2.null())),
261
- /**
262
- * list of sub components, either local (component name) or remote (registry info & component name)
263
- */
264
- subComponents: z2.array(z2.string().or(httpSubComponent)).default([])
154
+ const componentSchema = z.object({
155
+ name: z.string(),
156
+ title: z.string().optional(),
157
+ description: z.string().optional(),
158
+ files: z.array(fileSchema),
159
+ dependencies: z.record(z.string(), z.string().or(z.null())),
160
+ devDependencies: z.record(z.string(), z.string().or(z.null())),
161
+ subComponents: z.array(z.string().or(httpSubComponent)).default([])
265
162
  });
266
- var registryInfoSchema = z2.object({
267
- /**
268
- * define used variables, variables can be referenced in the import specifiers of component files.
269
- */
270
- variables: z2.record(
271
- z2.string(),
272
- z2.object({
273
- description: z2.string().optional(),
274
- default: z2.unknown().optional()
275
- })
276
- ).optional(),
277
- /**
278
- * provide variables to sub components
279
- */
280
- env: z2.record(z2.string(), z2.unknown()).optional(),
281
- indexes: z2.array(indexSchema).default([]),
282
- registries: z2.array(z2.string()).optional()
163
+ const registryInfoSchema = z.object({
164
+ variables: z.record(z.string(), z.object({
165
+ description: z.string().optional(),
166
+ default: z.unknown().optional()
167
+ })).optional(),
168
+ env: z.record(z.string(), z.unknown()).optional(),
169
+ indexes: z.array(indexSchema).default([]),
170
+ registries: z.array(z.string()).optional()
283
171
  });
284
172
 
285
- // src/registry/client.ts
286
- import path3 from "path";
287
- import fs3 from "fs/promises";
288
- import { log } from "@clack/prompts";
289
-
290
- // src/utils/cache.ts
291
- var AsyncCache = class {
292
- constructor() {
293
- this.store = /* @__PURE__ */ new Map();
294
- }
295
- cached(key, fn) {
296
- let cached = this.store.get(key);
297
- if (cached !== void 0) return cached;
298
- cached = fn();
299
- this.store.set(key, cached);
300
- return cached;
301
- }
302
- };
173
+ //#endregion
174
+ //#region src/utils/cache.ts
175
+ /**
176
+ * cache for async resources, finished promises will be resolved into original value, otherwise wrapped with a promise.
177
+ */
178
+ function createCache(store = /* @__PURE__ */ new Map()) {
179
+ return {
180
+ cached(key, fn) {
181
+ let cached = store.get(key);
182
+ if (cached) return cached;
183
+ cached = fn((v) => store.set(key, v));
184
+ if (cached instanceof Promise) cached = cached.then((out) => {
185
+ if (store.has(key)) store.set(key, out);
186
+ return out;
187
+ });
188
+ store.set(key, cached);
189
+ return cached;
190
+ },
191
+ invalidate(key) {
192
+ store.delete(key);
193
+ },
194
+ $value() {
195
+ return this;
196
+ }
197
+ };
198
+ }
303
199
 
304
- // src/registry/client.ts
305
- var fetchCache = new AsyncCache();
306
- var HttpRegistryClient = class _HttpRegistryClient {
307
- constructor(baseUrl, config) {
308
- this.baseUrl = baseUrl;
309
- this.config = config;
310
- this.registryId = baseUrl;
311
- }
312
- async fetchRegistryInfo(baseUrl = this.baseUrl) {
313
- const url = new URL("_registry.json", `${baseUrl}/`);
314
- return fetchCache.cached(url.href, async () => {
315
- const res = await fetch(url);
316
- if (!res.ok) {
317
- throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);
318
- }
319
- return registryInfoSchema.parse(await res.json());
320
- });
321
- }
322
- async fetchComponent(name) {
323
- const url = new URL(`${name}.json`, `${this.baseUrl}/`);
324
- return fetchCache.cached(url.href, async () => {
325
- const res = await fetch(`${this.baseUrl}/${name}.json`);
326
- if (!res.ok) {
327
- log.error(`component ${name} not found at ${url.href}`);
328
- throw new Error(await res.text());
329
- }
330
- return componentSchema.parse(await res.json());
331
- });
332
- }
333
- async hasComponent(name) {
334
- const url = new URL(`${name}.json`, `${this.baseUrl}/`);
335
- const res = await fetch(url, { method: "HEAD" });
336
- return res.ok;
337
- }
338
- createLinkedRegistryClient(name) {
339
- return new _HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);
340
- }
200
+ //#endregion
201
+ //#region src/registry/client.ts
202
+ const fetchCache = createCache();
203
+ var HttpRegistryClient = class HttpRegistryClient {
204
+ constructor(baseUrl, config) {
205
+ this.baseUrl = baseUrl;
206
+ this.config = config;
207
+ this.registryId = baseUrl;
208
+ }
209
+ async fetchRegistryInfo(baseUrl = this.baseUrl) {
210
+ const url = new URL("_registry.json", `${baseUrl}/`);
211
+ return fetchCache.$value().cached(url.href, async () => {
212
+ const res = await fetch(url);
213
+ if (!res.ok) throw new Error(`failed to fetch ${url.href}: ${res.statusText}`);
214
+ return registryInfoSchema.parse(await res.json());
215
+ });
216
+ }
217
+ async fetchComponent(name) {
218
+ const url = new URL(`${name}.json`, `${this.baseUrl}/`);
219
+ return fetchCache.$value().cached(url.href, async () => {
220
+ const res = await fetch(`${this.baseUrl}/${name}.json`);
221
+ if (!res.ok) {
222
+ log.error(`component ${name} not found at ${url.href}`);
223
+ throw new Error(await res.text());
224
+ }
225
+ return componentSchema.parse(await res.json());
226
+ });
227
+ }
228
+ async hasComponent(name) {
229
+ const url = new URL(`${name}.json`, `${this.baseUrl}/`);
230
+ return (await fetch(url, { method: "HEAD" })).ok;
231
+ }
232
+ createLinkedRegistryClient(name) {
233
+ return new HttpRegistryClient(`${this.baseUrl}/${name}`, this.config);
234
+ }
341
235
  };
342
- var LocalRegistryClient = class _LocalRegistryClient {
343
- constructor(dir, config) {
344
- this.dir = dir;
345
- this.config = config;
346
- this.registryId = dir;
347
- }
348
- async fetchRegistryInfo(dir = this.dir) {
349
- if (this.registryInfo) return this.registryInfo;
350
- const filePath = path3.join(dir, "_registry.json");
351
- const out = await fs3.readFile(filePath).then((res) => JSON.parse(res.toString())).catch((e) => {
352
- throw new Error(`failed to resolve local file "${filePath}"`, {
353
- cause: e
354
- });
355
- });
356
- return this.registryInfo = registryInfoSchema.parse(out);
357
- }
358
- async fetchComponent(name) {
359
- const filePath = path3.join(this.dir, `${name}.json`);
360
- const out = await fs3.readFile(filePath).then((res) => JSON.parse(res.toString())).catch((e) => {
361
- log.error(`component ${name} not found at ${filePath}`);
362
- throw e;
363
- });
364
- return componentSchema.parse(out);
365
- }
366
- async hasComponent(name) {
367
- const filePath = path3.join(this.dir, `${name}.json`);
368
- try {
369
- await fs3.stat(filePath);
370
- return true;
371
- } catch {
372
- return false;
373
- }
374
- }
375
- createLinkedRegistryClient(name) {
376
- return new _LocalRegistryClient(path3.join(this.dir, name), this.config);
377
- }
236
+ var LocalRegistryClient = class LocalRegistryClient {
237
+ constructor(dir, config) {
238
+ this.dir = dir;
239
+ this.config = config;
240
+ this.registryId = dir;
241
+ }
242
+ async fetchRegistryInfo(dir = this.dir) {
243
+ if (this.registryInfo) return this.registryInfo;
244
+ const filePath = path.join(dir, "_registry.json");
245
+ const out = await fs.readFile(filePath).then((res) => JSON.parse(res.toString())).catch((e) => {
246
+ throw new Error(`failed to resolve local file "${filePath}"`, { cause: e });
247
+ });
248
+ return this.registryInfo = registryInfoSchema.parse(out);
249
+ }
250
+ async fetchComponent(name) {
251
+ const filePath = path.join(this.dir, `${name}.json`);
252
+ const out = await fs.readFile(filePath).then((res) => JSON.parse(res.toString())).catch((e) => {
253
+ log.error(`component ${name} not found at ${filePath}`);
254
+ throw e;
255
+ });
256
+ return componentSchema.parse(out);
257
+ }
258
+ async hasComponent(name) {
259
+ const filePath = path.join(this.dir, `${name}.json`);
260
+ try {
261
+ await fs.stat(filePath);
262
+ return true;
263
+ } catch {
264
+ return false;
265
+ }
266
+ }
267
+ createLinkedRegistryClient(name) {
268
+ return new LocalRegistryClient(path.join(this.dir, name), this.config);
269
+ }
378
270
  };
379
271
 
380
- // src/registry/installer/index.ts
381
- import { x as x3 } from "tinyexec";
382
-
383
- // src/registry/installer/dep-manager.ts
384
- import fs4 from "fs/promises";
385
-
386
- // src/utils/get-package-manager.ts
387
- import { detect } from "package-manager-detector";
272
+ //#endregion
273
+ //#region src/utils/get-package-manager.ts
388
274
  async function getPackageManager() {
389
- const result = await detect();
390
- return result?.name ?? "npm";
275
+ return (await detect())?.name ?? "npm";
391
276
  }
392
277
 
393
- // src/registry/installer/dep-manager.ts
394
- import { confirm, isCancel, spinner } from "@clack/prompts";
395
- import { x as x2 } from "tinyexec";
278
+ //#endregion
279
+ //#region src/registry/installer/dep-manager.ts
396
280
  var DependencyManager = class {
397
- /**
398
- * Get dependencies from `package.json`
399
- */
400
- async getDeps() {
401
- if (this.cachedInstalledDeps) return this.cachedInstalledDeps;
402
- const dependencies = /* @__PURE__ */ new Map();
403
- if (!await exists("package.json")) return dependencies;
404
- const content = await fs4.readFile("package.json");
405
- const parsed = JSON.parse(content.toString());
406
- if ("dependencies" in parsed && typeof parsed.dependencies === "object") {
407
- const records = parsed.dependencies;
408
- for (const [k, v] of Object.entries(records)) {
409
- dependencies.set(k, v);
410
- }
411
- }
412
- if ("devDependencies" in parsed && typeof parsed.devDependencies === "object") {
413
- const records = parsed.devDependencies;
414
- for (const [k, v] of Object.entries(records)) {
415
- dependencies.set(k, v);
416
- }
417
- }
418
- return this.cachedInstalledDeps = dependencies;
419
- }
420
- async resolveInstallDependencies(deps) {
421
- const cachedInstalledDeps = await this.getDeps();
422
- return Object.entries(deps).filter(([k]) => !cachedInstalledDeps.has(k)).map(([k, v]) => v === null || v.length === 0 ? k : `${k}@${v}`);
423
- }
424
- async installDeps(deps, devDeps) {
425
- const items = await this.resolveInstallDependencies(deps);
426
- const devItems = await this.resolveInstallDependencies(devDeps);
427
- if (items.length === 0 && devItems.length === 0) return;
428
- const manager = await getPackageManager();
429
- const value = await confirm({
430
- message: `Do you want to install with ${manager}?
431
- ${[...items, ...devItems].map((v) => `- ${v}`).join("\n")}`
432
- });
433
- if (isCancel(value) || !value) {
434
- return;
435
- }
436
- const spin = spinner();
437
- spin.start("Installing dependencies...");
438
- if (items.length > 0) await x2(manager, ["install", ...items]);
439
- if (devItems.length > 0) await x2(manager, ["install", ...devItems, "-D"]);
440
- spin.stop("Dependencies installed.");
441
- }
281
+ /**
282
+ * Get dependencies from `package.json`
283
+ */
284
+ async getDeps() {
285
+ if (this.cachedInstalledDeps) return this.cachedInstalledDeps;
286
+ const dependencies = /* @__PURE__ */ new Map();
287
+ if (!await exists("package.json")) return dependencies;
288
+ const content = await fs.readFile("package.json");
289
+ const parsed = JSON.parse(content.toString());
290
+ if ("dependencies" in parsed && typeof parsed.dependencies === "object") {
291
+ const records = parsed.dependencies;
292
+ for (const [k, v] of Object.entries(records)) dependencies.set(k, v);
293
+ }
294
+ if ("devDependencies" in parsed && typeof parsed.devDependencies === "object") {
295
+ const records = parsed.devDependencies;
296
+ for (const [k, v] of Object.entries(records)) dependencies.set(k, v);
297
+ }
298
+ return this.cachedInstalledDeps = dependencies;
299
+ }
300
+ async resolveInstallDependencies(deps) {
301
+ const cachedInstalledDeps = await this.getDeps();
302
+ return Object.entries(deps).filter(([k]) => !cachedInstalledDeps.has(k)).map(([k, v]) => v === null || v.length === 0 ? k : `${k}@${v}`);
303
+ }
304
+ async installDeps(deps, devDeps) {
305
+ const items = await this.resolveInstallDependencies(deps);
306
+ const devItems = await this.resolveInstallDependencies(devDeps);
307
+ if (items.length === 0 && devItems.length === 0) return;
308
+ const manager = await getPackageManager();
309
+ const value = await confirm({ message: `Do you want to install with ${manager}?
310
+ ${[...items, ...devItems].map((v) => `- ${v}`).join("\n")}` });
311
+ if (isCancel(value) || !value) return;
312
+ const spin = spinner();
313
+ spin.start("Installing dependencies...");
314
+ if (items.length > 0) await x(manager, ["install", ...items]);
315
+ if (devItems.length > 0) await x(manager, [
316
+ "install",
317
+ ...devItems,
318
+ "-D"
319
+ ]);
320
+ spin.stop("Dependencies installed.");
321
+ }
442
322
  };
443
323
 
444
- // src/registry/installer/index.ts
324
+ //#endregion
325
+ //#region src/registry/installer/index.ts
445
326
  var ComponentInstaller = class {
446
- constructor(rootClient, plugins = []) {
447
- this.rootClient = rootClient;
448
- this.plugins = plugins;
449
- this.project = createEmptyProject();
450
- this.installedFiles = /* @__PURE__ */ new Set();
451
- this.downloadCache = new AsyncCache();
452
- this.dependencies = {};
453
- this.devDependencies = {};
454
- this.pathToFileCache = new AsyncCache();
455
- }
456
- async install(name) {
457
- let downloaded;
458
- const info = await this.rootClient.fetchRegistryInfo();
459
- for (const registry of info.registries ?? []) {
460
- if (name.startsWith(`${registry}/`)) {
461
- downloaded = await this.download(
462
- name.slice(registry.length + 1),
463
- this.rootClient.createLinkedRegistryClient(registry)
464
- );
465
- break;
466
- }
467
- }
468
- downloaded ??= await this.download(name, this.rootClient);
469
- for (const item of downloaded) {
470
- Object.assign(this.dependencies, item.dependencies);
471
- Object.assign(this.devDependencies, item.devDependencies);
472
- }
473
- for (const comp of downloaded) {
474
- for (const file of comp.files) {
475
- const outPath = this.resolveOutputPath(file);
476
- if (this.installedFiles.has(outPath)) continue;
477
- this.installedFiles.add(outPath);
478
- const output = typescriptExtensions.includes(path4.extname(outPath)) ? await this.transform(name, file, comp, downloaded) : file.content;
479
- const status = await fs5.readFile(outPath).then((res) => {
480
- if (res.toString() === output) return "ignore";
481
- return "need-update";
482
- }).catch(() => "write");
483
- if (status === "ignore") continue;
484
- if (status === "need-update") {
485
- const override = await confirm2({
486
- message: `Do you want to override ${outPath}?`,
487
- initialValue: false
488
- });
489
- if (isCancel2(override)) {
490
- outro("Ended");
491
- process.exit(0);
492
- }
493
- if (!override) continue;
494
- }
495
- await fs5.mkdir(path4.dirname(outPath), { recursive: true });
496
- await fs5.writeFile(outPath, output);
497
- log2.step(`downloaded ${outPath}`);
498
- }
499
- }
500
- }
501
- async installDeps() {
502
- await new DependencyManager().installDeps(
503
- this.dependencies,
504
- this.devDependencies
505
- );
506
- }
507
- async onEnd() {
508
- const config = this.rootClient.config;
509
- if (config.commands.format) {
510
- await x3(config.commands.format);
511
- }
512
- }
513
- /**
514
- * return a list of components, merged with child components & variables.
515
- */
516
- async download(name, client, contextVariables) {
517
- const hash = `${client.registryId} ${name}`;
518
- const info = await client.fetchRegistryInfo();
519
- const variables = { ...contextVariables, ...info.env };
520
- for (const [k, v] of Object.entries(info.variables ?? {})) {
521
- variables[k] ??= v.default;
522
- }
523
- const out = await this.downloadCache.cached(hash, async () => {
524
- const comp = await client.fetchComponent(name);
525
- const result = [comp];
526
- this.downloadCache.store.set(hash, result);
527
- const child = await Promise.all(
528
- comp.subComponents.map((sub) => {
529
- if (typeof sub === "string") return this.download(sub, client);
530
- const baseUrl = this.rootClient instanceof HttpRegistryClient ? new URL(sub.baseUrl, `${this.rootClient.baseUrl}/`).href : sub.baseUrl;
531
- return this.download(
532
- sub.component,
533
- new HttpRegistryClient(baseUrl, client.config),
534
- variables
535
- );
536
- })
537
- );
538
- for (const sub of child) result.push(...sub);
539
- return result;
540
- });
541
- return out.map((file) => ({ ...file, variables }));
542
- }
543
- async transform(taskId, file, component, allComponents) {
544
- const filePath = this.resolveOutputPath(file);
545
- const sourceFile = this.project.createSourceFile(filePath, file.content, {
546
- overwrite: true
547
- });
548
- const prefix = "@/";
549
- const variables = Object.entries(component.variables ?? {});
550
- const pathToFile = await this.pathToFileCache.cached(taskId, () => {
551
- const map = /* @__PURE__ */ new Map();
552
- for (const comp of allComponents) {
553
- for (const file2 of comp.files) map.set(file2.target ?? file2.path, file2);
554
- }
555
- return map;
556
- });
557
- for (const specifier of sourceFile.getImportStringLiterals()) {
558
- for (const [k, v] of variables) {
559
- specifier.setLiteralValue(
560
- specifier.getLiteralValue().replaceAll(`<${k}>`, v)
561
- );
562
- }
563
- if (specifier.getLiteralValue().startsWith(prefix)) {
564
- const lookup = specifier.getLiteralValue().substring(prefix.length);
565
- const target = pathToFile.get(lookup);
566
- if (target) {
567
- specifier.setLiteralValue(
568
- toImportSpecifier(filePath, this.resolveOutputPath(target))
569
- );
570
- } else {
571
- console.warn(`cannot find the referenced file of ${specifier}`);
572
- }
573
- }
574
- }
575
- for (const plugin of this.plugins) {
576
- await plugin.transform?.({
577
- file: sourceFile,
578
- componentFile: file,
579
- component
580
- });
581
- }
582
- return sourceFile.getFullText();
583
- }
584
- resolveOutputPath(file) {
585
- const config = this.rootClient.config;
586
- const dir = {
587
- components: config.aliases.componentsDir,
588
- block: config.aliases.blockDir,
589
- ui: config.aliases.uiDir,
590
- css: config.aliases.cssDir,
591
- lib: config.aliases.libDir,
592
- route: "./"
593
- }[file.type];
594
- if (file.target) {
595
- return path4.join(config.baseDir, file.target.replace("<dir>", dir));
596
- }
597
- return path4.join(config.baseDir, dir, path4.basename(file.path));
598
- }
327
+ constructor(rootClient, plugins = []) {
328
+ this.rootClient = rootClient;
329
+ this.plugins = plugins;
330
+ this.installedFiles = /* @__PURE__ */ new Set();
331
+ this.downloadCache = createCache();
332
+ this.dependencies = {};
333
+ this.devDependencies = {};
334
+ this.pathToFileCache = createCache();
335
+ }
336
+ async install(name) {
337
+ let downloaded;
338
+ const info = await this.rootClient.fetchRegistryInfo();
339
+ for (const registry of info.registries ?? []) if (name.startsWith(`${registry}/`)) {
340
+ downloaded = await this.download(name.slice(registry.length + 1), this.rootClient.createLinkedRegistryClient(registry));
341
+ break;
342
+ }
343
+ downloaded ??= await this.download(name, this.rootClient);
344
+ for (const item of downloaded) {
345
+ Object.assign(this.dependencies, item.dependencies);
346
+ Object.assign(this.devDependencies, item.devDependencies);
347
+ }
348
+ for (const comp of downloaded) for (const file of comp.files) {
349
+ const outPath = this.resolveOutputPath(file);
350
+ if (this.installedFiles.has(outPath)) continue;
351
+ this.installedFiles.add(outPath);
352
+ const output = typescriptExtensions.includes(path.extname(outPath)) ? await this.transform(name, file, comp, downloaded) : file.content;
353
+ const status = await fs.readFile(outPath).then((res) => {
354
+ if (res.toString() === output) return "ignore";
355
+ return "need-update";
356
+ }).catch(() => "write");
357
+ if (status === "ignore") continue;
358
+ if (status === "need-update") {
359
+ const override = await confirm({
360
+ message: `Do you want to override ${outPath}?`,
361
+ initialValue: false
362
+ });
363
+ if (isCancel(override)) {
364
+ outro("Ended");
365
+ process.exit(0);
366
+ }
367
+ if (!override) continue;
368
+ }
369
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
370
+ await fs.writeFile(outPath, output);
371
+ log.step(`downloaded ${outPath}`);
372
+ }
373
+ }
374
+ async installDeps() {
375
+ await new DependencyManager().installDeps(this.dependencies, this.devDependencies);
376
+ }
377
+ async onEnd() {
378
+ const config = this.rootClient.config;
379
+ if (config.commands.format) await x(config.commands.format);
380
+ }
381
+ /**
382
+ * return a list of components, merged with child components & variables.
383
+ */
384
+ async download(name, client, contextVariables) {
385
+ const hash = `${client.registryId} ${name}`;
386
+ const info = await client.fetchRegistryInfo();
387
+ const variables = {
388
+ ...contextVariables,
389
+ ...info.env
390
+ };
391
+ for (const [k, v] of Object.entries(info.variables ?? {})) variables[k] ??= v.default;
392
+ return (await this.downloadCache.cached(hash, async (presolve) => {
393
+ const comp = await client.fetchComponent(name);
394
+ const result = [comp];
395
+ presolve(result);
396
+ const child = await Promise.all(comp.subComponents.map((sub) => {
397
+ if (typeof sub === "string") return this.download(sub, client);
398
+ const baseUrl = this.rootClient instanceof HttpRegistryClient ? new URL(sub.baseUrl, `${this.rootClient.baseUrl}/`).href : sub.baseUrl;
399
+ return this.download(sub.component, new HttpRegistryClient(baseUrl, client.config), variables);
400
+ }));
401
+ for (const sub of child) result.push(...sub);
402
+ return result;
403
+ })).map((file) => ({
404
+ ...file,
405
+ variables
406
+ }));
407
+ }
408
+ async transform(taskId, file, component, allComponents) {
409
+ const filePath = this.resolveOutputPath(file);
410
+ const parsed = await parse(filePath, file.content);
411
+ const s = new MagicString(file.content);
412
+ const prefix = "@/";
413
+ const variables = Object.entries(component.variables ?? {});
414
+ const pathToFile = await this.pathToFileCache.cached(taskId, () => {
415
+ const map = /* @__PURE__ */ new Map();
416
+ for (const comp of allComponents) for (const file$1 of comp.files) map.set(file$1.target ?? file$1.path, file$1);
417
+ return map;
418
+ });
419
+ transformSpecifiers(parsed.program, s, (specifier) => {
420
+ for (const [k, v] of variables) specifier = specifier.replaceAll(`<${k}>`, v);
421
+ if (specifier.startsWith(prefix)) {
422
+ const lookup = specifier.substring(2);
423
+ const target = pathToFile.get(lookup);
424
+ if (target) specifier = toImportSpecifier(filePath, this.resolveOutputPath(target));
425
+ else console.warn(`cannot find the referenced file of ${specifier}`);
426
+ }
427
+ return specifier;
428
+ });
429
+ for (const plugin of this.plugins) await plugin.transformFile?.({
430
+ s,
431
+ parsed,
432
+ file,
433
+ component
434
+ });
435
+ return s.toString();
436
+ }
437
+ resolveOutputPath(file) {
438
+ const config = this.rootClient.config;
439
+ const dir = {
440
+ components: config.aliases.componentsDir,
441
+ block: config.aliases.blockDir,
442
+ ui: config.aliases.uiDir,
443
+ css: config.aliases.cssDir,
444
+ lib: config.aliases.libDir,
445
+ route: "./"
446
+ }[file.type];
447
+ if (file.target) return path.join(config.baseDir, file.target.replace("<dir>", dir));
448
+ return path.join(config.baseDir, dir, path.basename(file.path));
449
+ }
599
450
  };
600
451
 
601
- // src/commands/shared.ts
602
- var UIRegistries = {
603
- "base-ui": "fumadocs/base-ui",
604
- "radix-ui": "fumadocs/radix-ui"
452
+ //#endregion
453
+ //#region src/commands/shared.ts
454
+ const UIRegistries = {
455
+ "base-ui": "fumadocs/base-ui",
456
+ "radix-ui": "fumadocs/radix-ui"
605
457
  };
606
458
 
607
- // src/commands/add.ts
459
+ //#endregion
460
+ //#region src/commands/add.ts
608
461
  async function add(input, client) {
609
- const config = client.config;
610
- let target;
611
- const installer = new ComponentInstaller(client);
612
- const registry = UIRegistries[config.uiLibrary];
613
- if (input.length === 0) {
614
- const spin = spinner2();
615
- spin.start("fetching registry");
616
- const info = await client.fetchRegistryInfo();
617
- const options = [];
618
- for (const item of info.indexes) {
619
- options.push({
620
- label: item.title ?? item.name,
621
- value: item.name,
622
- hint: item.description
623
- });
624
- }
625
- const { indexes } = await client.createLinkedRegistryClient(registry).fetchRegistryInfo();
626
- for (const item of indexes) {
627
- options.push({
628
- label: item.title ?? item.name,
629
- value: `${registry}/${item.name}`,
630
- hint: item.description
631
- });
632
- }
633
- spin.stop(picocolors.bold(picocolors.greenBright("registry fetched")));
634
- const value = await multiselect({
635
- message: "Select components to install",
636
- options
637
- });
638
- if (isCancel3(value)) {
639
- outro2("Ended");
640
- return;
641
- }
642
- target = value;
643
- } else {
644
- target = await Promise.all(
645
- input.map(
646
- async (item) => await client.hasComponent(item) ? item : `${registry}/${item}`
647
- )
648
- );
649
- }
650
- await install(target, installer);
462
+ const config = client.config;
463
+ let target;
464
+ const installer = new ComponentInstaller(client);
465
+ const registry = UIRegistries[config.uiLibrary];
466
+ if (input.length === 0) {
467
+ const spin = spinner();
468
+ spin.start("fetching registry");
469
+ const info = await client.fetchRegistryInfo();
470
+ const options = [];
471
+ for (const item of info.indexes) options.push({
472
+ label: item.title ?? item.name,
473
+ value: item.name,
474
+ hint: item.description
475
+ });
476
+ const { indexes } = await client.createLinkedRegistryClient(registry).fetchRegistryInfo();
477
+ for (const item of indexes) options.push({
478
+ label: item.title ?? item.name,
479
+ value: `${registry}/${item.name}`,
480
+ hint: item.description
481
+ });
482
+ spin.stop(picocolors.bold(picocolors.greenBright("registry fetched")));
483
+ const value = await multiselect({
484
+ message: "Select components to install",
485
+ options
486
+ });
487
+ if (isCancel(value)) {
488
+ outro("Ended");
489
+ return;
490
+ }
491
+ target = value;
492
+ } else target = await Promise.all(input.map(async (item) => await client.hasComponent(item) ? item : `${registry}/${item}`));
493
+ await install(target, installer);
651
494
  }
652
495
  async function install(target, installer) {
653
- for (const name of target) {
654
- intro(
655
- picocolors.bold(
656
- picocolors.inverse(picocolors.cyanBright(`Add Component: ${name}`))
657
- )
658
- );
659
- try {
660
- await installer.install(name);
661
- outro2(picocolors.bold(picocolors.greenBright(`${name} installed`)));
662
- } catch (e) {
663
- log3.error(String(e));
664
- throw e;
665
- }
666
- }
667
- intro(picocolors.bold("New Dependencies"));
668
- await installer.installDeps();
669
- await installer.onEnd();
670
- outro2(picocolors.bold(picocolors.greenBright("Successful")));
496
+ for (const name of target) {
497
+ intro(picocolors.bold(picocolors.inverse(picocolors.cyanBright(`Add Component: ${name}`))));
498
+ try {
499
+ await installer.install(name);
500
+ outro(picocolors.bold(picocolors.greenBright(`${name} installed`)));
501
+ } catch (e) {
502
+ log.error(String(e));
503
+ throw e;
504
+ }
505
+ }
506
+ intro(picocolors.bold("New Dependencies"));
507
+ await installer.installDeps();
508
+ await installer.onEnd();
509
+ outro(picocolors.bold(picocolors.greenBright("Successful")));
671
510
  }
672
511
 
673
- // src/commands/customise.ts
512
+ //#endregion
513
+ //#region src/commands/customise.ts
674
514
  async function customise(client) {
675
- intro2(picocolors2.bgBlack(picocolors2.whiteBright("Customise Fumadocs UI")));
676
- const config = client.config;
677
- const installer = new ComponentInstaller(client);
678
- const result = await group(
679
- {
680
- target: () => select({
681
- message: "What do you want to customise?",
682
- options: [
683
- {
684
- label: "Docs Layout",
685
- value: "docs",
686
- hint: "main UI of your docs"
687
- },
688
- {
689
- label: "Home Layout",
690
- value: "home",
691
- hint: "the navbar for your other pages"
692
- }
693
- ]
694
- }),
695
- mode: (v) => {
696
- if (v.results.target !== "docs") return;
697
- return select({
698
- message: "Which variant do you want to start from?",
699
- options: [
700
- {
701
- label: "Start from minimal styles",
702
- value: "minimal",
703
- hint: "for those who want to build their own variant from ground up."
704
- },
705
- {
706
- label: "Start from default layout",
707
- value: "full-default",
708
- hint: "useful for adjusting small details."
709
- },
710
- {
711
- label: "Start from Notebook layout",
712
- value: "full-notebook",
713
- hint: "useful for adjusting small details."
714
- }
715
- ]
716
- });
717
- }
718
- },
719
- {
720
- onCancel: () => {
721
- cancel("Installation Stopped.");
722
- process.exit(0);
723
- }
724
- }
725
- );
726
- const registry = UIRegistries[config.uiLibrary];
727
- if (result.target === "docs") {
728
- const targets = [];
729
- if (result.mode === "minimal") {
730
- targets.push("fumadocs/ui/layouts/docs-min");
731
- } else {
732
- targets.push(
733
- result.mode === "full-default" ? `${registry}/layouts/docs` : `${registry}/layouts/notebook`
734
- );
735
- }
736
- await install(targets, installer);
737
- const maps = result.mode === "full-notebook" ? [
738
- ["fumadocs-ui/layouts/notebook", "@/components/layout/notebook"],
739
- [
740
- "fumadocs-ui/layouts/notebook/page",
741
- "@/components/layout/notebook/page"
742
- ]
743
- ] : [
744
- ["fumadocs-ui/layouts/docs", "@/components/layout/docs"],
745
- ["fumadocs-ui/layouts/docs/page", "@/components/layout/docs/page"]
746
- ];
747
- printNext(...maps);
748
- }
749
- if (result.target === "home") {
750
- await install([`${registry}/layouts/home`], installer);
751
- printNext(["fumadocs-ui/layouts/home", `@/components/layout/home`]);
752
- }
753
- outro3(picocolors2.bold("Have fun!"));
515
+ intro(picocolors.bgBlack(picocolors.whiteBright("Customise Fumadocs UI")));
516
+ const config = client.config;
517
+ const installer = new ComponentInstaller(client);
518
+ const result = await group({
519
+ target: () => select({
520
+ message: "What do you want to customise?",
521
+ options: [{
522
+ label: "Docs Layout",
523
+ value: "docs",
524
+ hint: "main UI of your docs"
525
+ }, {
526
+ label: "Home Layout",
527
+ value: "home",
528
+ hint: "the navbar for your other pages"
529
+ }]
530
+ }),
531
+ mode: (v) => {
532
+ if (v.results.target !== "docs") return;
533
+ return select({
534
+ message: "Which variant do you want to start from?",
535
+ options: [
536
+ {
537
+ label: "Start from minimal styles",
538
+ value: "minimal",
539
+ hint: "for those who want to build their own variant from ground up."
540
+ },
541
+ {
542
+ label: "Start from default layout",
543
+ value: "full-default",
544
+ hint: "useful for adjusting small details."
545
+ },
546
+ {
547
+ label: "Start from Notebook layout",
548
+ value: "full-notebook",
549
+ hint: "useful for adjusting small details."
550
+ }
551
+ ]
552
+ });
553
+ }
554
+ }, { onCancel: () => {
555
+ cancel("Installation Stopped.");
556
+ process.exit(0);
557
+ } });
558
+ const registry = UIRegistries[config.uiLibrary];
559
+ if (result.target === "docs") {
560
+ const targets = [];
561
+ if (result.mode === "minimal") targets.push("fumadocs/ui/layouts/docs-min");
562
+ else targets.push(result.mode === "full-default" ? `${registry}/layouts/docs` : `${registry}/layouts/notebook`);
563
+ await install(targets, installer);
564
+ printNext(...result.mode === "full-notebook" ? [["fumadocs-ui/layouts/notebook", "@/components/layout/notebook"], ["fumadocs-ui/layouts/notebook/page", "@/components/layout/notebook/page"]] : [["fumadocs-ui/layouts/docs", "@/components/layout/docs"], ["fumadocs-ui/layouts/docs/page", "@/components/layout/docs/page"]]);
565
+ }
566
+ if (result.target === "home") {
567
+ await install([`${registry}/layouts/home`], installer);
568
+ printNext(["fumadocs-ui/layouts/home", `@/components/layout/home`]);
569
+ }
570
+ outro(picocolors.bold("Have fun!"));
754
571
  }
755
572
  function printNext(...maps) {
756
- intro2(picocolors2.bold("What is Next?"));
757
- log4.info(
758
- [
759
- "You can check the installed components in `components`.",
760
- picocolors2.dim("---"),
761
- "Open your `layout.tsx` files, replace the imports of components:",
762
- ...maps.map(
763
- ([from, to]) => picocolors2.greenBright(`"${from}" -> "${to}"`)
764
- )
765
- ].join("\n")
766
- );
573
+ intro(picocolors.bold("What is Next?"));
574
+ log.info([
575
+ "You can check the installed components in `components`.",
576
+ picocolors.dim("---"),
577
+ "Open your `layout.tsx` files, replace the imports of components:",
578
+ ...maps.map(([from, to]) => picocolors.greenBright(`"${from}" -> "${to}"`))
579
+ ].join("\n"));
767
580
  }
768
581
 
769
- // src/index.ts
770
- var program = new Command().option("--config <string>");
771
- program.name("fumadocs").description("CLI to setup Fumadocs, init a config").version(package_default.version).action(async () => {
772
- if (await initConfig()) {
773
- console.log(picocolors3.green("Initialized a `./cli.json` config file."));
774
- } else {
775
- console.log(picocolors3.redBright("A config file already exists."));
776
- }
582
+ //#endregion
583
+ //#region src/index.ts
584
+ const program = new Command().option("--config <string>");
585
+ program.name("fumadocs").description("CLI to setup Fumadocs, init a config").version(version).action(async () => {
586
+ if (await initConfig()) console.log(picocolors.green("Initialized a `./cli.json` config file."));
587
+ else console.log(picocolors.redBright("A config file already exists."));
777
588
  });
778
589
  program.command("customise").alias("customize").description("simple way to customise layouts with Fumadocs UI").option("--dir <string>", "the root url or directory to resolve registry").action(async (options) => {
779
- await customise(
780
- createClientFromDir(
781
- options.dir,
782
- await createOrLoadConfig(options.config)
783
- )
784
- );
590
+ await customise(createClientFromDir(options.dir, await createOrLoadConfig(options.config)));
785
591
  });
786
- var dirShortcuts = {
787
- ":preview": "https://preview.fumadocs.dev/registry",
788
- ":dev": "http://localhost:3000/registry"
592
+ const dirShortcuts = {
593
+ ":preview": "https://preview.fumadocs.dev/registry",
594
+ ":dev": "http://localhost:3000/registry"
789
595
  };
790
- program.command("add").description("add a new component to your docs").argument("[components...]", "components to download").option("--dir <string>", "the root url or directory to resolve registry").action(
791
- async (input, options) => {
792
- const client = createClientFromDir(
793
- options.dir,
794
- await createOrLoadConfig(options.config)
795
- );
796
- await add(input, client);
797
- }
798
- );
799
- program.command("tree").argument(
800
- "[json_or_args]",
801
- "JSON output of `tree` command or arguments for the `tree` command"
802
- ).argument("[output]", "output path of file").option("--js", "output as JavaScript file").option("--no-root", "remove the root node").option("--import-name <name>", "where to import components (JS only)").action(
803
- async (str, output, {
804
- js,
805
- root,
806
- importName
807
- }) => {
808
- const jsExtensions = [".js", ".tsx", ".jsx"];
809
- const noRoot = !root;
810
- let nodes;
811
- try {
812
- nodes = JSON.parse(str ?? "");
813
- } catch {
814
- nodes = await runTree(str ?? "./");
815
- }
816
- const out = js || output && jsExtensions.includes(path5.extname(output)) ? treeToJavaScript(nodes, noRoot, importName) : treeToMdx(nodes, noRoot);
817
- if (output) {
818
- await fs6.mkdir(path5.dirname(output), { recursive: true });
819
- await fs6.writeFile(output, out);
820
- } else {
821
- console.log(out);
822
- }
823
- }
824
- );
596
+ program.command("add").description("add a new component to your docs").argument("[components...]", "components to download").option("--dir <string>", "the root url or directory to resolve registry").action(async (input, options) => {
597
+ await add(input, createClientFromDir(options.dir, await createOrLoadConfig(options.config)));
598
+ });
599
+ program.command("tree").argument("[json_or_args]", "JSON output of `tree` command or arguments for the `tree` command").argument("[output]", "output path of file").option("--js", "output as JavaScript file").option("--no-root", "remove the root node").option("--import-name <name>", "where to import components (JS only)").action(async (str, output, { js, root, importName }) => {
600
+ const jsExtensions = [
601
+ ".js",
602
+ ".tsx",
603
+ ".jsx"
604
+ ];
605
+ const noRoot = !root;
606
+ let nodes;
607
+ try {
608
+ nodes = JSON.parse(str ?? "");
609
+ } catch {
610
+ nodes = await runTree(str ?? "./");
611
+ }
612
+ const out = js || output && jsExtensions.includes(path.extname(output)) ? treeToJavaScript(nodes, noRoot, importName) : treeToMdx(nodes, noRoot);
613
+ if (output) {
614
+ await fs.mkdir(path.dirname(output), { recursive: true });
615
+ await fs.writeFile(output, out);
616
+ } else console.log(out);
617
+ });
825
618
  function createClientFromDir(dir = "https://fumadocs.dev/registry", config) {
826
- if (dir in dirShortcuts) dir = dirShortcuts[dir];
827
- return dir.startsWith("http://") || dir.startsWith("https://") ? new HttpRegistryClient(dir, config) : new LocalRegistryClient(dir, config);
619
+ if (dir in dirShortcuts) dir = dirShortcuts[dir];
620
+ return dir.startsWith("http://") || dir.startsWith("https://") ? new HttpRegistryClient(dir, config) : new LocalRegistryClient(dir, config);
828
621
  }
829
622
  program.parse();
623
+
624
+ //#endregion
625
+ export { };
626
+ //# sourceMappingURL=index.js.map