@hanzo/docs-cli 1.2.1 → 1.2.5
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/ast-BS3xj9uY.js +72 -0
- package/dist/ast-BS3xj9uY.js.map +1 -0
- package/dist/build/index.d.ts +8 -7
- package/dist/build/index.d.ts.map +1 -1
- package/dist/build/index.js +84 -66
- package/dist/build/index.js.map +1 -1
- package/dist/index.js +182 -160
- package/dist/index.js.map +1 -1
- package/package.json +18 -15
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { Visitor } from "oxc-parser";
|
|
3
|
+
|
|
4
|
+
//#region src/constants.ts
|
|
5
|
+
const typescriptExtensions = [
|
|
6
|
+
".ts",
|
|
7
|
+
".tsx",
|
|
8
|
+
".js",
|
|
9
|
+
".jsx"
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/utils/ast.ts
|
|
14
|
+
/**
|
|
15
|
+
* Return the import modifier for `sourceFile` to import `referenceFile`
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* toReferencePath('index.ts', 'dir/hello.ts')
|
|
20
|
+
* // should output './dir/hello'
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function toImportSpecifier(sourceFile, referenceFile) {
|
|
24
|
+
const extname = path.extname(referenceFile);
|
|
25
|
+
const removeExt = typescriptExtensions.includes(extname);
|
|
26
|
+
let importPath = path.relative(path.dirname(sourceFile), removeExt ? referenceFile.substring(0, referenceFile.length - extname.length) : referenceFile).replaceAll(path.sep, "/");
|
|
27
|
+
if (removeExt && importPath.endsWith("/index")) importPath = importPath.slice(0, -6);
|
|
28
|
+
return importPath.startsWith("../") ? importPath : `./${importPath}`;
|
|
29
|
+
}
|
|
30
|
+
function transformSpecifiers(program, s, transformSpecifier) {
|
|
31
|
+
new Visitor({
|
|
32
|
+
ImportDeclaration(node) {
|
|
33
|
+
const source = node.source;
|
|
34
|
+
const out = transformSpecifier(source.value);
|
|
35
|
+
if (out) {
|
|
36
|
+
s.update(source.start + 1, source.end - 1, out);
|
|
37
|
+
source.value = out;
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
ImportExpression(node) {
|
|
41
|
+
if (node.source.type === "Literal") {
|
|
42
|
+
const source = node.source;
|
|
43
|
+
const out = transformSpecifier(source.value);
|
|
44
|
+
if (out) {
|
|
45
|
+
s.update(source.start + 1, source.end - 1, out);
|
|
46
|
+
source.value = out;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
ExportAllDeclaration(node) {
|
|
51
|
+
const source = node.source;
|
|
52
|
+
const out = transformSpecifier(source.value);
|
|
53
|
+
if (out) {
|
|
54
|
+
s.update(source.start + 1, source.end - 1, out);
|
|
55
|
+
source.value = out;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
ExportNamedDeclaration(node) {
|
|
59
|
+
const source = node.source;
|
|
60
|
+
if (!source) return;
|
|
61
|
+
const out = transformSpecifier(source.value);
|
|
62
|
+
if (out) {
|
|
63
|
+
s.update(source.start + 1, source.end - 1, out);
|
|
64
|
+
source.value = out;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}).visit(program);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { transformSpecifiers as n, typescriptExtensions as r, toImportSpecifier as t };
|
|
72
|
+
//# sourceMappingURL=ast-BS3xj9uY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-BS3xj9uY.js","names":[],"sources":["../src/constants.ts","../src/utils/ast.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';\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"],"mappings":";;;;AAAA,MAAa,uBAAuB;CAAC;CAAO;CAAQ;CAAO;CAAO;;;;;;;;;;;;;ACclE,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"}
|
package/dist/build/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
3
3
|
|
|
4
4
|
//#region src/registry/schema.d.ts
|
|
5
5
|
type NamespaceType = (typeof namespaces)[number];
|
|
@@ -90,11 +90,9 @@ interface Registry extends Omit<z.input<typeof registryInfoSchema>, 'indexes'> {
|
|
|
90
90
|
}
|
|
91
91
|
declare class RegistryCompiler {
|
|
92
92
|
readonly raw: Registry;
|
|
93
|
-
readonly project: Project;
|
|
94
93
|
resolver: RegistryResolver;
|
|
95
94
|
constructor(registry: Registry);
|
|
96
95
|
private readPackageJson;
|
|
97
|
-
createSourceFile(file: string): Promise<SourceFile>;
|
|
98
96
|
compile(): Promise<CompiledRegistry>;
|
|
99
97
|
}
|
|
100
98
|
declare class RegistryResolver {
|
|
@@ -102,6 +100,7 @@ declare class RegistryResolver {
|
|
|
102
100
|
private readonly deps;
|
|
103
101
|
private readonly devDeps;
|
|
104
102
|
private readonly fileToComponent;
|
|
103
|
+
readonly oxc: ResolverFactory;
|
|
105
104
|
constructor(compiler: RegistryCompiler, packageJson?: PackageJson);
|
|
106
105
|
getDepFromSpecifier(specifier: string): string;
|
|
107
106
|
getDepInfo(name: string): {
|
|
@@ -137,6 +136,9 @@ type SourceReference = {
|
|
|
137
136
|
file: ComponentFile;
|
|
138
137
|
registryName: string;
|
|
139
138
|
};
|
|
139
|
+
} | {
|
|
140
|
+
type: 'unknown-specifier';
|
|
141
|
+
specifier: string;
|
|
140
142
|
};
|
|
141
143
|
type Reference = SourceReference | {
|
|
142
144
|
type: 'custom';
|
|
@@ -153,8 +155,7 @@ declare class ComponentCompiler {
|
|
|
153
155
|
constructor(compiler: RegistryCompiler, component: Component);
|
|
154
156
|
private toImportPath;
|
|
155
157
|
build(): Promise<CompiledComponent>;
|
|
156
|
-
private
|
|
157
|
-
private resolveImport;
|
|
158
|
+
private onBuildFile;
|
|
158
159
|
private buildFile;
|
|
159
160
|
}
|
|
160
161
|
declare function resolveFromRemote(r: Registry, component: string, selectFile: (file: ComponentFile) => boolean): Reference | undefined;
|
|
@@ -164,7 +165,7 @@ interface MonoRegistry extends CompiledRegistry {
|
|
|
164
165
|
registries: CompiledRegistry[];
|
|
165
166
|
}
|
|
166
167
|
declare function combineRegistry(root: CompiledRegistry, ...items: CompiledRegistry[]): MonoRegistry;
|
|
167
|
-
declare function
|
|
168
|
+
declare function writeDocsRegistry(out: CompiledRegistry | MonoRegistry, options: {
|
|
168
169
|
dir: string;
|
|
169
170
|
/**
|
|
170
171
|
* Remove previous outputs
|
|
@@ -175,5 +176,5 @@ declare function writeFumadocsRegistry(out: CompiledRegistry | MonoRegistry, opt
|
|
|
175
176
|
log?: boolean;
|
|
176
177
|
}): Promise<void>;
|
|
177
178
|
//#endregion
|
|
178
|
-
export { CompiledRegistry, Component, ComponentCompiler, ComponentFile, MonoRegistry, OnResolve, PackageJson, Reference, Registry, RegistryCompiler, SourceReference, combineRegistry, resolveFromRemote,
|
|
179
|
+
export { CompiledRegistry, Component, ComponentCompiler, ComponentFile, MonoRegistry, OnResolve, PackageJson, Reference, Registry, RegistryCompiler, SourceReference, combineRegistry, resolveFromRemote, writeDocsRegistry };
|
|
179
180
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/registry/schema.ts","../../src/build/compiler.ts","../../src/build/index.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/registry/schema.ts","../../src/build/compiler.ts","../../src/build/index.ts"],"mappings":"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"}
|
package/dist/build/index.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
+
import { n as transformSpecifiers } from "../ast-BS3xj9uY.js";
|
|
1
2
|
import * as fs$1 from "node:fs/promises";
|
|
2
3
|
import * as path$1 from "node:path";
|
|
3
4
|
import picocolors from "picocolors";
|
|
4
|
-
import {
|
|
5
|
+
import { parse } from "oxc-parser";
|
|
6
|
+
import MagicString from "magic-string";
|
|
7
|
+
import { ResolverFactory } from "oxc-resolver";
|
|
5
8
|
|
|
6
9
|
//#region src/build/compiler.ts
|
|
7
10
|
var RegistryCompiler = class {
|
|
8
11
|
constructor(registry) {
|
|
9
12
|
this.raw = registry;
|
|
10
|
-
this.project = new Project({ tsConfigFilePath: path$1.join(registry.dir, registry.tsconfigPath) });
|
|
11
13
|
}
|
|
12
14
|
async readPackageJson() {
|
|
13
15
|
if (typeof this.raw.packageJson !== "string") return this.raw.packageJson;
|
|
14
16
|
return fs$1.readFile(path$1.join(this.raw.dir, this.raw.packageJson)).then((res) => JSON.parse(res.toString())).catch(() => void 0);
|
|
15
17
|
}
|
|
16
|
-
async createSourceFile(file) {
|
|
17
|
-
const content = await fs$1.readFile(file);
|
|
18
|
-
return this.project.createSourceFile(file, content.toString(), { overwrite: true });
|
|
19
|
-
}
|
|
20
18
|
async compile() {
|
|
21
19
|
const registry = this.raw;
|
|
22
20
|
this.resolver = new RegistryResolver(this, await this.readPackageJson());
|
|
@@ -60,6 +58,23 @@ var RegistryResolver = class {
|
|
|
60
58
|
...packageJson?.devDependencies,
|
|
61
59
|
...registry.devDependencies
|
|
62
60
|
};
|
|
61
|
+
this.oxc = new ResolverFactory({
|
|
62
|
+
extensions: [
|
|
63
|
+
".js",
|
|
64
|
+
".jsx",
|
|
65
|
+
".ts",
|
|
66
|
+
".tsx",
|
|
67
|
+
".node"
|
|
68
|
+
],
|
|
69
|
+
conditionNames: [
|
|
70
|
+
"node",
|
|
71
|
+
"import",
|
|
72
|
+
"require",
|
|
73
|
+
"default",
|
|
74
|
+
"types"
|
|
75
|
+
],
|
|
76
|
+
tsconfig: { configFile: path$1.join(registry.dir, registry.tsconfigPath) }
|
|
77
|
+
});
|
|
63
78
|
}
|
|
64
79
|
getDepFromSpecifier(specifier) {
|
|
65
80
|
return specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
|
|
@@ -95,7 +110,7 @@ var ComponentCompiler = class {
|
|
|
95
110
|
this.compiler = compiler;
|
|
96
111
|
this.component = component;
|
|
97
112
|
this.processedFiles = /* @__PURE__ */ new Set();
|
|
98
|
-
this.subComponents = /* @__PURE__ */ new
|
|
113
|
+
this.subComponents = /* @__PURE__ */ new Map();
|
|
99
114
|
this.devDependencies = /* @__PURE__ */ new Map();
|
|
100
115
|
this.dependencies = /* @__PURE__ */ new Map();
|
|
101
116
|
this.registry = compiler.raw;
|
|
@@ -110,18 +125,22 @@ var ComponentCompiler = class {
|
|
|
110
125
|
name: this.component.name,
|
|
111
126
|
title: this.component.title,
|
|
112
127
|
description: this.component.description,
|
|
113
|
-
files: (await Promise.all(this.component.files.map((file) => this.
|
|
114
|
-
subComponents: Array.from(this.subComponents),
|
|
128
|
+
files: (await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))).flat(),
|
|
129
|
+
subComponents: Array.from(this.subComponents.values()),
|
|
115
130
|
dependencies: Object.fromEntries(this.dependencies),
|
|
116
131
|
devDependencies: Object.fromEntries(this.devDependencies)
|
|
117
132
|
};
|
|
118
133
|
}
|
|
119
|
-
async
|
|
134
|
+
async onBuildFile(file) {
|
|
120
135
|
if (this.processedFiles.has(file.path)) return [];
|
|
121
136
|
this.processedFiles.add(file.path);
|
|
122
137
|
const resolver = this.compiler.resolver;
|
|
123
138
|
const queue = [];
|
|
124
139
|
return [await this.buildFile(file, (reference) => {
|
|
140
|
+
if (reference.type === "unknown-specifier") {
|
|
141
|
+
if (!reference.specifier.startsWith("node:")) console.warn(`Unknown specifier ${reference.specifier}, skipping for now`);
|
|
142
|
+
return reference.specifier;
|
|
143
|
+
}
|
|
125
144
|
if (reference.type === "custom") return reference.specifier;
|
|
126
145
|
if (reference.type === "file") {
|
|
127
146
|
const refFile = this.registry.onUnknownFile?.(reference.file);
|
|
@@ -134,75 +153,74 @@ var ComponentCompiler = class {
|
|
|
134
153
|
}
|
|
135
154
|
if (reference.type === "sub-component") {
|
|
136
155
|
const resolved = reference.resolved;
|
|
137
|
-
if (resolved.component.name
|
|
156
|
+
if (resolved.component.name === this.component.name) return this.toImportPath(resolved.file);
|
|
157
|
+
if (resolved.type === "remote") this.subComponents.set(`${resolved.registryName}:${resolved.component.name}`, {
|
|
138
158
|
type: "http",
|
|
139
159
|
baseUrl: resolved.registryName,
|
|
140
160
|
component: resolved.component.name
|
|
141
161
|
});
|
|
142
|
-
else this.subComponents.
|
|
162
|
+
else this.subComponents.set(resolved.component.name, resolved.component.name);
|
|
143
163
|
return this.toImportPath(resolved.file);
|
|
144
164
|
}
|
|
145
165
|
const dep = resolver.getDepInfo(reference.dep);
|
|
146
166
|
if (dep) (dep.type === "dev" ? this.devDependencies : this.dependencies).set(dep.name, dep.version);
|
|
147
167
|
return reference.specifier;
|
|
148
|
-
}), ...(await Promise.all(queue.map((file
|
|
149
|
-
}
|
|
150
|
-
resolveImport(sourceFilePath, specifier, specified) {
|
|
151
|
-
let filePath;
|
|
152
|
-
if (specified) filePath = specified.getFilePath();
|
|
153
|
-
else if (specifier.startsWith("./") || specifier.startsWith("../")) filePath = path$1.join(path$1.dirname(sourceFilePath), specifier);
|
|
154
|
-
else {
|
|
155
|
-
if (!specifier.startsWith("node:")) console.warn(`Unknown specifier ${specifier}, skipping for now`);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const resolver = this.compiler.resolver;
|
|
159
|
-
if (path$1.relative(this.registry.dir, filePath).startsWith("../")) return {
|
|
160
|
-
type: "dependency",
|
|
161
|
-
dep: resolver.getDepFromSpecifier(specifier),
|
|
162
|
-
specifier
|
|
163
|
-
};
|
|
164
|
-
const sub = resolver.getSubComponent(filePath);
|
|
165
|
-
if (sub) return {
|
|
166
|
-
type: "sub-component",
|
|
167
|
-
resolved: {
|
|
168
|
-
type: "local",
|
|
169
|
-
component: sub.component,
|
|
170
|
-
file: sub.file
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
return {
|
|
174
|
-
type: "file",
|
|
175
|
-
file: filePath
|
|
176
|
-
};
|
|
168
|
+
}), ...(await Promise.all(queue.map((file) => this.onBuildFile(file)))).flat()];
|
|
177
169
|
}
|
|
178
170
|
async buildFile(file, writeReference) {
|
|
179
171
|
const sourceFilePath = path$1.join(this.registry.dir, file.path);
|
|
172
|
+
const astType = {
|
|
173
|
+
".ts": "ts",
|
|
174
|
+
".tsx": "ts",
|
|
175
|
+
".js": "js",
|
|
176
|
+
".jsx": "js"
|
|
177
|
+
}[path$1.extname(file.path)];
|
|
178
|
+
const content = (await fs$1.readFile(sourceFilePath)).toString();
|
|
179
|
+
if (!astType) return {
|
|
180
|
+
content,
|
|
181
|
+
path: file.path,
|
|
182
|
+
type: file.type,
|
|
183
|
+
target: file.target
|
|
184
|
+
};
|
|
185
|
+
const resolver = this.compiler.resolver;
|
|
186
|
+
const ast = await parse(sourceFilePath, content, { astType });
|
|
187
|
+
if (ast.errors.length > 0) throw new Error(`failed to parse file ${sourceFilePath}: \n${ast.errors.join("\n")}`);
|
|
188
|
+
const s = new MagicString(content);
|
|
180
189
|
/**
|
|
181
190
|
* Process import paths
|
|
182
191
|
*/
|
|
183
|
-
|
|
192
|
+
transformSpecifiers(ast.program, s, (specifier) => {
|
|
193
|
+
let resolved = {
|
|
194
|
+
type: "unknown-specifier",
|
|
195
|
+
specifier
|
|
196
|
+
};
|
|
184
197
|
const onResolve = this.component.onResolve ?? this.registry.onResolve;
|
|
185
|
-
|
|
186
|
-
if (!resolved)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
const resolvedSpecifier = resolver.oxc.resolveFileSync(sourceFilePath, specifier);
|
|
199
|
+
if (resolvedSpecifier.error || !resolvedSpecifier.path) return writeReference(onResolve ? onResolve(resolved) : resolved);
|
|
200
|
+
resolved = {
|
|
201
|
+
type: "file",
|
|
202
|
+
file: resolvedSpecifier.path
|
|
203
|
+
};
|
|
204
|
+
if (path$1.relative(this.registry.dir, resolvedSpecifier.path).startsWith("../")) resolved = {
|
|
205
|
+
type: "dependency",
|
|
206
|
+
dep: resolver.getDepFromSpecifier(specifier),
|
|
207
|
+
specifier
|
|
208
|
+
};
|
|
209
|
+
else {
|
|
210
|
+
const sub = resolver.getSubComponent(resolvedSpecifier.path);
|
|
211
|
+
if (sub) resolved = {
|
|
212
|
+
type: "sub-component",
|
|
213
|
+
resolved: {
|
|
214
|
+
type: "local",
|
|
215
|
+
component: sub.component,
|
|
216
|
+
file: sub.file
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return writeReference(onResolve ? onResolve(resolved) : resolved);
|
|
221
|
+
});
|
|
204
222
|
return {
|
|
205
|
-
content:
|
|
223
|
+
content: s.toString(),
|
|
206
224
|
type: file.type,
|
|
207
225
|
path: file.path,
|
|
208
226
|
target: file.target
|
|
@@ -210,7 +228,7 @@ var ComponentCompiler = class {
|
|
|
210
228
|
}
|
|
211
229
|
};
|
|
212
230
|
function resolveFromRemote(r, component, selectFile) {
|
|
213
|
-
const comp = r.components.find((comp
|
|
231
|
+
const comp = r.components.find((comp) => comp.name === component);
|
|
214
232
|
if (!comp) return;
|
|
215
233
|
const file = comp.files.find(selectFile);
|
|
216
234
|
if (!file) return;
|
|
@@ -237,7 +255,7 @@ function combineRegistry(root, ...items) {
|
|
|
237
255
|
registries: items
|
|
238
256
|
};
|
|
239
257
|
}
|
|
240
|
-
async function
|
|
258
|
+
async function writeDocsRegistry(out, options) {
|
|
241
259
|
const { dir, cleanDir = false, log = true } = options;
|
|
242
260
|
if (cleanDir) {
|
|
243
261
|
await fs$1.rm(dir, {
|
|
@@ -253,7 +271,7 @@ async function writeFumadocsRegistry(out, options) {
|
|
|
253
271
|
await writeFile(path$1.join(dir, `${comp.name}.json`), JSON.stringify(comp, null, 2), log);
|
|
254
272
|
});
|
|
255
273
|
write.push(writeInfo());
|
|
256
|
-
if ("registries" in out) for (const child of out.registries) write.push(
|
|
274
|
+
if ("registries" in out) for (const child of out.registries) write.push(writeDocsRegistry(child, {
|
|
257
275
|
dir: path$1.join(dir, child.name),
|
|
258
276
|
log: options.log
|
|
259
277
|
}));
|
|
@@ -269,5 +287,5 @@ async function writeFile(file, content, log = true) {
|
|
|
269
287
|
}
|
|
270
288
|
|
|
271
289
|
//#endregion
|
|
272
|
-
export { ComponentCompiler, RegistryCompiler, combineRegistry, resolveFromRemote,
|
|
290
|
+
export { ComponentCompiler, RegistryCompiler, combineRegistry, resolveFromRemote, writeDocsRegistry };
|
|
273
291
|
//# sourceMappingURL=index.js.map
|
package/dist/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["path","fs","output: CompiledRegistry","compiler: RegistryCompiler","component: Component","queue: ComponentFile[]","file","filePath: string","process","resolved: Reference | undefined","comp","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 { Project, SourceFile, StringLiteral, ts } from 'ts-morph';\n\nexport type OnResolve = (reference: SourceReference) => 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\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 readonly project: Project;\n resolver!: RegistryResolver;\n\n constructor(registry: Registry) {\n this.raw = registry;\n this.project = new Project({\n tsConfigFilePath: path.join(registry.dir, registry.tsconfigPath),\n });\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 createSourceFile(file: string) {\n const content = await fs.readFile(file);\n return this.project.createSourceFile(file, content.toString(), {\n overwrite: true,\n });\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\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\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\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 Set<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 // see https://github.com/shadcn-ui/ui/blob/396275e46a58333caa1fa0a991bd9bc5237d2ee3/packages/shadcn/src/utils/updaters/update-files.ts#L585\n // to hit the fast-path step, we need to import `target` path first because it's detected from `fileSet`, a set of output file paths\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 return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files: (\n await Promise.all(this.component.files.map((file) => this.buildFileAndDeps(file)))\n ).flat(),\n subComponents: Array.from(this.subComponents),\n dependencies: Object.fromEntries(this.dependencies),\n devDependencies: Object.fromEntries(this.devDependencies),\n };\n }\n\n private async buildFileAndDeps(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 === '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 if (resolved.type === 'remote') {\n this.subComponents.add({\n type: 'http',\n baseUrl: resolved.registryName,\n component: resolved.component.name,\n });\n } else {\n this.subComponents.add(resolved.component.name);\n }\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 [\n result,\n ...(await Promise.all(queue.map((file) => this.buildFileAndDeps(file)))).flat(),\n ];\n }\n\n private resolveImport(\n sourceFilePath: string,\n specifier: string,\n specified: SourceFile | undefined,\n ): SourceReference | undefined {\n let filePath: string;\n if (specified) {\n filePath = specified.getFilePath();\n } else if (specifier.startsWith('./') || specifier.startsWith('../')) {\n filePath = path.join(path.dirname(sourceFilePath), specifier);\n } else {\n if (!specifier.startsWith('node:'))\n console.warn(`Unknown specifier ${specifier}, skipping for now`);\n return;\n }\n\n const resolver = this.compiler.resolver;\n // outside of registry dir\n if (path.relative(this.registry.dir, filePath).startsWith('../')) {\n return {\n type: 'dependency',\n dep: resolver.getDepFromSpecifier(specifier),\n specifier,\n };\n }\n\n const sub = resolver.getSubComponent(filePath);\n if (sub) {\n return {\n type: 'sub-component',\n resolved: {\n type: 'local',\n component: sub.component,\n file: sub.file,\n },\n };\n }\n\n return {\n type: 'file',\n file: filePath,\n };\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\n /**\n * Process import paths\n */\n const process = (specifier: StringLiteral, specifiedFile: SourceFile | undefined) => {\n const onResolve = this.component.onResolve ?? this.registry.onResolve;\n let resolved: Reference | undefined = this.resolveImport(\n sourceFilePath,\n specifier.getLiteralValue(),\n specifiedFile,\n );\n\n if (!resolved) return;\n if (onResolve) resolved = onResolve(resolved);\n const out = writeReference(resolved);\n if (out) specifier.setLiteralValue(out);\n };\n\n const sourceFile = await this.compiler.createSourceFile(sourceFilePath);\n\n for (const item of sourceFile.getImportDeclarations()) {\n process(item.getModuleSpecifier(), item.getModuleSpecifierSourceFile());\n }\n\n for (const item of sourceFile.getExportDeclarations()) {\n const specifier = item.getModuleSpecifier();\n if (!specifier) continue;\n\n process(specifier, item.getModuleSpecifierSourceFile());\n }\n\n // transform async imports\n const calls = sourceFile.getDescendantsOfKind(ts.SyntaxKind.CallExpression);\n\n for (const expression of calls) {\n if (\n expression.getExpression().isKind(ts.SyntaxKind.ImportKeyword) &&\n expression.getArguments().length === 1\n ) {\n const argument = expression.getArguments()[0];\n\n if (!argument.isKind(ts.SyntaxKind.StringLiteral)) continue;\n\n process(argument, argument.getSymbol()?.getDeclarations()[0].getSourceFile());\n }\n }\n\n return {\n content: sourceFile.getFullText(),\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 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';\n\nexport type OnResolve = (reference: SourceReference) => 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\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 // see https://github.com/shadcn-ui/ui/blob/396275e46a58333caa1fa0a991bd9bc5237d2ee3/packages/shadcn/src/utils/updaters/update-files.ts#L585\n // to hit the fast-path step, we need to import `target` path first because it's detected from `fileSet`, a set of output file paths\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 return {\n name: this.component.name,\n title: this.component.title,\n description: this.component.description,\n files: (await Promise.all(this.component.files.map((file) => this.onBuildFile(file)))).flat(),\n subComponents: Array.from(this.subComponents.values()),\n dependencies: Object.fromEntries(this.dependencies),\n devDependencies: Object.fromEntries(this.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 /**\n * Process import paths\n */\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) : resolved);\n }\n\n resolved = {\n type: 'file',\n file: resolvedSpecifier.path,\n };\n\n // outside of registry dir\n if (path.relative(this.registry.dir, resolvedSpecifier.path).startsWith('../')) {\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) : 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 writeDocsRegistry(\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 writeDocsRegistry(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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"}
|