@anvia/cli 1.1.0 → 1.2.0
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/README.md +16 -0
- package/dist/chunk-IH4ZNWHB.js +285 -0
- package/dist/chunk-IH4ZNWHB.js.map +1 -0
- package/dist/cli.js +53 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +9 -3
- package/package.json +3 -3
- package/dist/chunk-TE2ODJOV.js +0 -135
- package/dist/chunk-TE2ODJOV.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,3 +13,19 @@ pnpm dlx @anvia/cli add chat
|
|
|
13
13
|
|
|
14
14
|
Available items: `chat`, `thread`, `message`, `composer`, `attachment`, `markdown`, and
|
|
15
15
|
`tool-fallback`.
|
|
16
|
+
|
|
17
|
+
## Updating installed components
|
|
18
|
+
|
|
19
|
+
`update` compares the Anvia components in your project against the current registry:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm dlx @anvia/cli update # check every item (preview only, writes nothing)
|
|
23
|
+
pnpm dlx @anvia/cli update composer # check a single item
|
|
24
|
+
pnpm dlx @anvia/cli update --overwrite
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Without `--overwrite`, `update` is a preview: it reports each file as `up-to-date`,
|
|
28
|
+
`modified` (the installed copy differs from the registry), or `missing`. Pass `--overwrite`
|
|
29
|
+
to write the registry content over out-of-date and missing files of installed components.
|
|
30
|
+
`update` never installs new items — use `add` for that. Locally edited copies are
|
|
31
|
+
overwritten, so commit or stash your changes first.
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { spawnSync } from "child_process";
|
|
3
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
import { tmpdir } from "os";
|
|
6
|
+
import { basename, dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
var registryItemNames = [
|
|
9
|
+
"chat",
|
|
10
|
+
"thread",
|
|
11
|
+
"message",
|
|
12
|
+
"composer",
|
|
13
|
+
"attachment",
|
|
14
|
+
"markdown",
|
|
15
|
+
"tool-fallback"
|
|
16
|
+
];
|
|
17
|
+
var itemFiles = {
|
|
18
|
+
attachment: ["attachment.tsx"],
|
|
19
|
+
chat: [
|
|
20
|
+
"attachment.tsx",
|
|
21
|
+
"markdown.tsx",
|
|
22
|
+
"tool-fallback.tsx",
|
|
23
|
+
"message.tsx",
|
|
24
|
+
"composer.tsx",
|
|
25
|
+
"thread.tsx",
|
|
26
|
+
"chat.tsx"
|
|
27
|
+
],
|
|
28
|
+
composer: ["attachment.tsx", "composer.tsx"],
|
|
29
|
+
markdown: ["markdown.tsx"],
|
|
30
|
+
message: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx"],
|
|
31
|
+
thread: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx", "thread.tsx"],
|
|
32
|
+
"tool-fallback": ["tool-fallback.tsx"]
|
|
33
|
+
};
|
|
34
|
+
var revealCss = {
|
|
35
|
+
"@keyframes anvia-stream-gradient-settle": {
|
|
36
|
+
to: {
|
|
37
|
+
opacity: "1"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"@layer components": {
|
|
41
|
+
'.anvia-markdown [data-state="revealing"]': {
|
|
42
|
+
animation: "anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both",
|
|
43
|
+
opacity: "var(--anvia-stream-reveal-opacity, 1)"
|
|
44
|
+
},
|
|
45
|
+
"@media (prefers-reduced-motion: reduce)": {
|
|
46
|
+
'.anvia-markdown [data-state="revealing"]': {
|
|
47
|
+
animation: "none",
|
|
48
|
+
opacity: "1"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
function createRegistryItem(name, options = {}) {
|
|
54
|
+
const packageVersion = options.packageVersion ?? currentPackageVersion();
|
|
55
|
+
const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();
|
|
56
|
+
const files = itemFiles[name].map((filename) => ({
|
|
57
|
+
content: readFileSync(join(registryDirectory, filename), "utf8"),
|
|
58
|
+
path: `registry/anvia/${filename}`,
|
|
59
|
+
target: `@components/anvia/${filename}`,
|
|
60
|
+
type: "registry:component"
|
|
61
|
+
}));
|
|
62
|
+
const item = {
|
|
63
|
+
$schema: "https://ui.shadcn.com/schema/registry-item.json",
|
|
64
|
+
dependencies: [`@anvia/react-ui@${packageVersion}`],
|
|
65
|
+
description: registryItemDescription(name),
|
|
66
|
+
files,
|
|
67
|
+
name,
|
|
68
|
+
title: `Anvia ${name}`,
|
|
69
|
+
type: files.length === 1 ? "registry:component" : "registry:block"
|
|
70
|
+
};
|
|
71
|
+
if (name === "chat" || name === "markdown" || name === "message" || name === "thread") {
|
|
72
|
+
item.css = revealCss;
|
|
73
|
+
}
|
|
74
|
+
return item;
|
|
75
|
+
}
|
|
76
|
+
function initializeProject(options = {}) {
|
|
77
|
+
const cwd = options.cwd ?? process.cwd();
|
|
78
|
+
const args = ["init", "--cwd", cwd, "--yes", "--no-monorepo", "--base", "radix"];
|
|
79
|
+
if (options.template !== void 0) args.push("--template", options.template);
|
|
80
|
+
if (options.force === true) args.push("--force");
|
|
81
|
+
runShadcn(args);
|
|
82
|
+
}
|
|
83
|
+
function addRegistryItem(name, options = {}) {
|
|
84
|
+
const cwd = options.cwd ?? process.cwd();
|
|
85
|
+
const temporaryDirectory = mkdtempSync(join(tmpdir(), "anvia-registry-"));
|
|
86
|
+
const itemPath = join(temporaryDirectory, `${name}.json`);
|
|
87
|
+
try {
|
|
88
|
+
writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}
|
|
89
|
+
`);
|
|
90
|
+
const args = ["add", itemPath, "--cwd", cwd, "--yes"];
|
|
91
|
+
if (options.overwrite === true) args.push("--overwrite");
|
|
92
|
+
runShadcn(args);
|
|
93
|
+
} finally {
|
|
94
|
+
rmSync(temporaryDirectory, { force: true, recursive: true });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function isRegistryItemName(value) {
|
|
98
|
+
return registryItemNames.includes(value);
|
|
99
|
+
}
|
|
100
|
+
function inspectInstalledItems(options = {}) {
|
|
101
|
+
const names = options.items ?? registryItemNames;
|
|
102
|
+
const directory = componentsDirectory(options);
|
|
103
|
+
const registry = options.registryDirectory ?? bundledRegistryDirectory();
|
|
104
|
+
return names.map((name) => {
|
|
105
|
+
const files = itemFiles[name].map((filename) => {
|
|
106
|
+
const path = join(directory, "anvia", filename);
|
|
107
|
+
let status = "missing";
|
|
108
|
+
if (existsSync(path)) {
|
|
109
|
+
const installed = readFileSync(path, "utf8");
|
|
110
|
+
status = installed === registryFileContent(registry, filename) ? "up-to-date" : "modified";
|
|
111
|
+
}
|
|
112
|
+
return { filename, path, status };
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
name,
|
|
116
|
+
installed: files.some((file) => file.status !== "missing"),
|
|
117
|
+
complete: files.every((file) => file.status !== "missing"),
|
|
118
|
+
files
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function updateInstalledItems(options = {}) {
|
|
123
|
+
const registry = options.registryDirectory ?? bundledRegistryDirectory();
|
|
124
|
+
const report = inspectInstalledItems(options);
|
|
125
|
+
const updated = [];
|
|
126
|
+
if (options.overwrite === true) {
|
|
127
|
+
const actionable = /* @__PURE__ */ new Map();
|
|
128
|
+
for (const item of report) {
|
|
129
|
+
if (!item.installed) continue;
|
|
130
|
+
for (const file of item.files) {
|
|
131
|
+
if (file.status === "up-to-date" || actionable.has(file.path)) continue;
|
|
132
|
+
actionable.set(file.path, registryFileContent(registry, file.filename));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const [path, content] of actionable) {
|
|
136
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
137
|
+
writeFileSync(path, content);
|
|
138
|
+
updated.push(path);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { report, updated };
|
|
142
|
+
}
|
|
143
|
+
function closestRegistryItemName(value) {
|
|
144
|
+
let best;
|
|
145
|
+
let bestDistance = Number.POSITIVE_INFINITY;
|
|
146
|
+
for (const name of registryItemNames) {
|
|
147
|
+
const distance = levenshteinDistance(value, name);
|
|
148
|
+
if (distance < bestDistance) {
|
|
149
|
+
bestDistance = distance;
|
|
150
|
+
best = name;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return bestDistance <= 2 ? best : void 0;
|
|
154
|
+
}
|
|
155
|
+
function componentsDirectory(options = {}) {
|
|
156
|
+
const cwd = options.cwd ?? process.cwd();
|
|
157
|
+
const manifestPath = join(cwd, "components.json");
|
|
158
|
+
let manifest;
|
|
159
|
+
try {
|
|
160
|
+
manifest = JSON.parse(stripJsonComments(readFileSync(manifestPath, "utf8")));
|
|
161
|
+
} catch {
|
|
162
|
+
throw new Error(`Missing or unreadable components.json in ${cwd}. Run \`anvia init\` first.`);
|
|
163
|
+
}
|
|
164
|
+
const alias = manifest.aliases?.components ?? "@/components";
|
|
165
|
+
return resolveAliasDirectory(cwd, alias);
|
|
166
|
+
}
|
|
167
|
+
function resolveAliasDirectory(cwd, alias) {
|
|
168
|
+
for (const configName of ["tsconfig.json", "jsconfig.json"]) {
|
|
169
|
+
let config;
|
|
170
|
+
try {
|
|
171
|
+
config = JSON.parse(stripJsonComments(readFileSync(join(cwd, configName), "utf8")));
|
|
172
|
+
} catch {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const paths = config.compilerOptions?.paths;
|
|
176
|
+
if (paths === void 0) continue;
|
|
177
|
+
const target = resolveAliasTarget(alias, paths);
|
|
178
|
+
if (target === void 0) continue;
|
|
179
|
+
return join(cwd, config.compilerOptions?.baseUrl ?? ".", target);
|
|
180
|
+
}
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Cannot resolve the components alias "${alias}" from tsconfig.json or jsconfig.json in ${cwd}.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
function resolveAliasTarget(alias, paths) {
|
|
186
|
+
for (const [key, targets] of Object.entries(paths)) {
|
|
187
|
+
const target = targets[0];
|
|
188
|
+
if (target === void 0) continue;
|
|
189
|
+
if (key.endsWith("/*")) {
|
|
190
|
+
const prefix = key.slice(0, -2);
|
|
191
|
+
if (alias === prefix) return target.replace(/\/\*$/, "");
|
|
192
|
+
if (alias.startsWith(`${prefix}/`)) {
|
|
193
|
+
return join(target.replace(/\/\*$/, ""), alias.slice(prefix.length + 1));
|
|
194
|
+
}
|
|
195
|
+
} else if (key === alias) {
|
|
196
|
+
return target;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
function stripJsonComments(source) {
|
|
202
|
+
let result = "";
|
|
203
|
+
let inString = false;
|
|
204
|
+
let escaped = false;
|
|
205
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
206
|
+
const character = source[index];
|
|
207
|
+
if (inString) {
|
|
208
|
+
result += character;
|
|
209
|
+
if (escaped) escaped = false;
|
|
210
|
+
else if (character === "\\") escaped = true;
|
|
211
|
+
else if (character === '"') inString = false;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (character === '"') {
|
|
215
|
+
inString = true;
|
|
216
|
+
result += character;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (character === "/" && source[index + 1] === "/") {
|
|
220
|
+
while (index < source.length && source[index] !== "\n") index += 1;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
result += character;
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
function registryFileContent(registryDirectory, filename) {
|
|
228
|
+
return readFileSync(join(registryDirectory, filename), "utf8");
|
|
229
|
+
}
|
|
230
|
+
function levenshteinDistance(left, right) {
|
|
231
|
+
const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
|
|
232
|
+
for (let i = 1; i <= left.length; i += 1) {
|
|
233
|
+
let diagonal = previous[0];
|
|
234
|
+
previous[0] = i;
|
|
235
|
+
for (let j = 1; j <= right.length; j += 1) {
|
|
236
|
+
const above = previous[j];
|
|
237
|
+
previous[j] = Math.min(
|
|
238
|
+
above + 1,
|
|
239
|
+
previous[j - 1] + 1,
|
|
240
|
+
diagonal + (left[i - 1] === right[j - 1] ? 0 : 1)
|
|
241
|
+
);
|
|
242
|
+
diagonal = above;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return previous[right.length];
|
|
246
|
+
}
|
|
247
|
+
function runShadcn(args) {
|
|
248
|
+
const require2 = createRequire(import.meta.url);
|
|
249
|
+
const shadcnEntry = require2.resolve("shadcn");
|
|
250
|
+
const result = spawnSync(process.execPath, [shadcnEntry, ...args], {
|
|
251
|
+
encoding: "utf8",
|
|
252
|
+
stdio: "inherit"
|
|
253
|
+
});
|
|
254
|
+
if (result.error !== void 0) throw result.error;
|
|
255
|
+
if (result.status !== 0) {
|
|
256
|
+
throw new Error(`shadcn ${args[0] ?? "command"} failed with exit code ${result.status}.`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function bundledRegistryDirectory() {
|
|
260
|
+
return fileURLToPath(new URL("./registry/", import.meta.url));
|
|
261
|
+
}
|
|
262
|
+
function currentPackageVersion() {
|
|
263
|
+
const manifestPath = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
264
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
265
|
+
if (typeof manifest.version !== "string") {
|
|
266
|
+
throw new Error(`Missing package version in ${basename(manifestPath)}.`);
|
|
267
|
+
}
|
|
268
|
+
return manifest.version;
|
|
269
|
+
}
|
|
270
|
+
function registryItemDescription(name) {
|
|
271
|
+
if (name === "chat") return "A complete editable Anvia chat interface.";
|
|
272
|
+
return `Editable Anvia ${name} UI.`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
registryItemNames,
|
|
277
|
+
createRegistryItem,
|
|
278
|
+
initializeProject,
|
|
279
|
+
addRegistryItem,
|
|
280
|
+
isRegistryItemName,
|
|
281
|
+
inspectInstalledItems,
|
|
282
|
+
updateInstalledItems,
|
|
283
|
+
closestRegistryItemName
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=chunk-IH4ZNWHB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const registryItemNames = [\n \"chat\",\n \"thread\",\n \"message\",\n \"composer\",\n \"attachment\",\n \"markdown\",\n \"tool-fallback\",\n] as const;\n\nexport type RegistryItemName = (typeof registryItemNames)[number];\n\ntype RegistryFile = {\n content: string;\n path: string;\n target: string;\n type: \"registry:component\";\n};\n\ntype RegistryCss = {\n [rule: string]: RegistryCss | string;\n};\n\nexport type AnviaRegistryItem = {\n $schema: string;\n css?: RegistryCss;\n dependencies: string[];\n description: string;\n files: RegistryFile[];\n name: RegistryItemName;\n title: string;\n type: \"registry:block\" | \"registry:component\";\n};\n\nconst itemFiles: Record<RegistryItemName, readonly string[]> = {\n attachment: [\"attachment.tsx\"],\n chat: [\n \"attachment.tsx\",\n \"markdown.tsx\",\n \"tool-fallback.tsx\",\n \"message.tsx\",\n \"composer.tsx\",\n \"thread.tsx\",\n \"chat.tsx\",\n ],\n composer: [\"attachment.tsx\", \"composer.tsx\"],\n markdown: [\"markdown.tsx\"],\n message: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\"],\n thread: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\", \"thread.tsx\"],\n \"tool-fallback\": [\"tool-fallback.tsx\"],\n};\n\nconst revealCss = {\n \"@keyframes anvia-stream-gradient-settle\": {\n to: {\n opacity: \"1\",\n },\n },\n \"@layer components\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation:\n \"anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both\",\n opacity: \"var(--anvia-stream-reveal-opacity, 1)\",\n },\n \"@media (prefers-reduced-motion: reduce)\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation: \"none\",\n opacity: \"1\",\n },\n },\n },\n} satisfies RegistryCss;\n\nexport function createRegistryItem(\n name: RegistryItemName,\n options: { packageVersion?: string; registryDirectory?: string } = {},\n): AnviaRegistryItem {\n const packageVersion = options.packageVersion ?? currentPackageVersion();\n const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();\n const files = itemFiles[name].map((filename) => ({\n content: readFileSync(join(registryDirectory, filename), \"utf8\"),\n path: `registry/anvia/${filename}`,\n target: `@components/anvia/${filename}`,\n type: \"registry:component\" as const,\n }));\n const item: AnviaRegistryItem = {\n $schema: \"https://ui.shadcn.com/schema/registry-item.json\",\n dependencies: [`@anvia/react-ui@${packageVersion}`],\n description: registryItemDescription(name),\n files,\n name,\n title: `Anvia ${name}`,\n type: files.length === 1 ? \"registry:component\" : \"registry:block\",\n };\n if (name === \"chat\" || name === \"markdown\" || name === \"message\" || name === \"thread\") {\n item.css = revealCss;\n }\n return item;\n}\n\nexport function initializeProject(\n options: { cwd?: string; force?: boolean; template?: \"next\" | \"vite\" } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const args = [\"init\", \"--cwd\", cwd, \"--yes\", \"--no-monorepo\", \"--base\", \"radix\"];\n if (options.template !== undefined) args.push(\"--template\", options.template);\n if (options.force === true) args.push(\"--force\");\n runShadcn(args);\n}\n\nexport function addRegistryItem(\n name: RegistryItemName,\n options: { cwd?: string; overwrite?: boolean } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const temporaryDirectory = mkdtempSync(join(tmpdir(), \"anvia-registry-\"));\n const itemPath = join(temporaryDirectory, `${name}.json`);\n try {\n writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}\\n`);\n const args = [\"add\", itemPath, \"--cwd\", cwd, \"--yes\"];\n if (options.overwrite === true) args.push(\"--overwrite\");\n runShadcn(args);\n } finally {\n rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nexport function isRegistryItemName(value: string): value is RegistryItemName {\n return registryItemNames.includes(value as RegistryItemName);\n}\n\nexport type InstalledFileStatus = \"up-to-date\" | \"modified\" | \"missing\";\n\nexport type InstalledItemFile = {\n filename: string;\n path: string;\n status: InstalledFileStatus;\n};\n\nexport type InstalledItemReport = {\n name: RegistryItemName;\n installed: boolean;\n complete: boolean;\n files: InstalledItemFile[];\n};\n\nexport function inspectInstalledItems(\n options: {\n cwd?: string;\n items?: readonly RegistryItemName[];\n registryDirectory?: string;\n } = {},\n): InstalledItemReport[] {\n const names = options.items ?? registryItemNames;\n const directory = componentsDirectory(options);\n const registry = options.registryDirectory ?? bundledRegistryDirectory();\n return names.map((name) => {\n const files = itemFiles[name].map((filename) => {\n const path = join(directory, \"anvia\", filename);\n let status: InstalledFileStatus = \"missing\";\n if (existsSync(path)) {\n const installed = readFileSync(path, \"utf8\");\n status = installed === registryFileContent(registry, filename) ? \"up-to-date\" : \"modified\";\n }\n return { filename, path, status };\n });\n return {\n name,\n installed: files.some((file) => file.status !== \"missing\"),\n complete: files.every((file) => file.status !== \"missing\"),\n files,\n };\n });\n}\n\nexport function updateInstalledItems(\n options: {\n cwd?: string;\n items?: readonly RegistryItemName[];\n overwrite?: boolean;\n registryDirectory?: string;\n } = {},\n): { report: InstalledItemReport[]; updated: string[] } {\n const registry = options.registryDirectory ?? bundledRegistryDirectory();\n const report = inspectInstalledItems(options);\n const updated: string[] = [];\n if (options.overwrite === true) {\n const actionable = new Map<string, string>();\n for (const item of report) {\n if (!item.installed) continue;\n for (const file of item.files) {\n if (file.status === \"up-to-date\" || actionable.has(file.path)) continue;\n actionable.set(file.path, registryFileContent(registry, file.filename));\n }\n }\n for (const [path, content] of actionable) {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, content);\n updated.push(path);\n }\n }\n return { report, updated };\n}\n\nexport function closestRegistryItemName(value: string): RegistryItemName | undefined {\n let best: RegistryItemName | undefined;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const name of registryItemNames) {\n const distance = levenshteinDistance(value, name);\n if (distance < bestDistance) {\n bestDistance = distance;\n best = name;\n }\n }\n return bestDistance <= 2 ? best : undefined;\n}\n\nfunction componentsDirectory(options: { cwd?: string } = {}): string {\n const cwd = options.cwd ?? process.cwd();\n const manifestPath = join(cwd, \"components.json\");\n let manifest: { aliases?: { components?: string } };\n try {\n manifest = JSON.parse(stripJsonComments(readFileSync(manifestPath, \"utf8\"))) as {\n aliases?: { components?: string };\n };\n } catch {\n throw new Error(`Missing or unreadable components.json in ${cwd}. Run \\`anvia init\\` first.`);\n }\n const alias = manifest.aliases?.components ?? \"@/components\";\n return resolveAliasDirectory(cwd, alias);\n}\n\nfunction resolveAliasDirectory(cwd: string, alias: string): string {\n for (const configName of [\"tsconfig.json\", \"jsconfig.json\"]) {\n let config: { compilerOptions?: { baseUrl?: string; paths?: Record<string, string[]> } };\n try {\n config = JSON.parse(stripJsonComments(readFileSync(join(cwd, configName), \"utf8\"))) as {\n compilerOptions?: { baseUrl?: string; paths?: Record<string, string[]> };\n };\n } catch {\n continue;\n }\n const paths = config.compilerOptions?.paths;\n if (paths === undefined) continue;\n const target = resolveAliasTarget(alias, paths);\n if (target === undefined) continue;\n return join(cwd, config.compilerOptions?.baseUrl ?? \".\", target);\n }\n throw new Error(\n `Cannot resolve the components alias \"${alias}\" from tsconfig.json or jsconfig.json in ${cwd}.`,\n );\n}\n\nfunction resolveAliasTarget(alias: string, paths: Record<string, string[]>): string | undefined {\n for (const [key, targets] of Object.entries(paths)) {\n const target = targets[0];\n if (target === undefined) continue;\n if (key.endsWith(\"/*\")) {\n const prefix = key.slice(0, -2);\n if (alias === prefix) return target.replace(/\\/\\*$/, \"\");\n if (alias.startsWith(`${prefix}/`)) {\n return join(target.replace(/\\/\\*$/, \"\"), alias.slice(prefix.length + 1));\n }\n } else if (key === alias) {\n return target;\n }\n }\n return undefined;\n}\n\nfunction stripJsonComments(source: string): string {\n let result = \"\";\n let inString = false;\n let escaped = false;\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index];\n if (inString) {\n result += character;\n if (escaped) escaped = false;\n else if (character === \"\\\\\") escaped = true;\n else if (character === '\"') inString = false;\n continue;\n }\n if (character === '\"') {\n inString = true;\n result += character;\n continue;\n }\n if (character === \"/\" && source[index + 1] === \"/\") {\n while (index < source.length && source[index] !== \"\\n\") index += 1;\n continue;\n }\n result += character;\n }\n return result;\n}\n\nfunction registryFileContent(registryDirectory: string, filename: string): string {\n return readFileSync(join(registryDirectory, filename), \"utf8\");\n}\n\nfunction levenshteinDistance(left: string, right: string): number {\n const previous = Array.from({ length: right.length + 1 }, (_, index) => index);\n for (let i = 1; i <= left.length; i += 1) {\n let diagonal = previous[0]!;\n previous[0] = i;\n for (let j = 1; j <= right.length; j += 1) {\n const above = previous[j]!;\n previous[j] = Math.min(\n above + 1,\n previous[j - 1]! + 1,\n diagonal + (left[i - 1] === right[j - 1] ? 0 : 1),\n );\n diagonal = above;\n }\n }\n return previous[right.length]!;\n}\n\nfunction runShadcn(args: string[]): void {\n const require = createRequire(import.meta.url);\n const shadcnEntry = require.resolve(\"shadcn\");\n const result = spawnSync(process.execPath, [shadcnEntry, ...args], {\n encoding: \"utf8\",\n stdio: \"inherit\",\n });\n if (result.error !== undefined) throw result.error;\n if (result.status !== 0) {\n throw new Error(`shadcn ${args[0] ?? \"command\"} failed with exit code ${result.status}.`);\n }\n}\n\nfunction bundledRegistryDirectory(): string {\n return fileURLToPath(new URL(\"./registry/\", import.meta.url));\n}\n\nfunction currentPackageVersion(): string {\n const manifestPath = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { version?: unknown };\n if (typeof manifest.version !== \"string\") {\n throw new Error(`Missing package version in ${basename(manifestPath)}.`);\n }\n return manifest.version;\n}\n\nfunction registryItemDescription(name: RegistryItemName): string {\n if (name === \"chat\") return \"A complete editable Anvia chat interface.\";\n return `Editable Anvia ${name} UI.`;\n}\n"],"mappings":"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","names":["require"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
addRegistryItem,
|
|
4
|
+
closestRegistryItemName,
|
|
4
5
|
initializeProject,
|
|
5
6
|
isRegistryItemName,
|
|
6
|
-
registryItemNames
|
|
7
|
-
|
|
7
|
+
registryItemNames,
|
|
8
|
+
updateInstalledItems
|
|
9
|
+
} from "./chunk-IH4ZNWHB.js";
|
|
8
10
|
|
|
9
11
|
// src/cli.ts
|
|
10
12
|
function main(args) {
|
|
@@ -40,9 +42,57 @@ function main(args) {
|
|
|
40
42
|
console.log(`Added Anvia ${value}.`);
|
|
41
43
|
return;
|
|
42
44
|
}
|
|
45
|
+
if (command === "update") {
|
|
46
|
+
const items = positional.map((value) => {
|
|
47
|
+
if (isRegistryItemName(value)) return value;
|
|
48
|
+
const suggestion = closestRegistryItemName(value);
|
|
49
|
+
const suffix = suggestion === void 0 ? "" : ` Did you mean "${suggestion}"?`;
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Unknown registry item "${value}".${suffix} Choose an item: ${registryItemNames.join(", ")}.`
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
const overwrite = commandArgs.includes("--overwrite");
|
|
55
|
+
const options = { overwrite };
|
|
56
|
+
if (cwd !== void 0) options.cwd = cwd;
|
|
57
|
+
if (items.length > 0) options.items = items;
|
|
58
|
+
const { report, updated } = updateInstalledItems(options);
|
|
59
|
+
const updatedPaths = new Set(updated);
|
|
60
|
+
if (overwrite === true) {
|
|
61
|
+
for (const item of report) {
|
|
62
|
+
if (!item.installed) {
|
|
63
|
+
console.log(`Anvia ${item.name}: not installed. Use \`anvia add ${item.name}\` first.`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const changed = item.files.some(
|
|
67
|
+
(file) => file.status !== "up-to-date" && updatedPaths.has(file.path)
|
|
68
|
+
);
|
|
69
|
+
console.log(`Anvia ${item.name}: ${changed ? "updated" : "up to date"}.`);
|
|
70
|
+
}
|
|
71
|
+
console.log(
|
|
72
|
+
updated.length === 0 ? "All installed Anvia components are up to date." : `Updated ${updated.length} ${updated.length === 1 ? "file" : "files"}.`
|
|
73
|
+
);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let changeCount = 0;
|
|
77
|
+
for (const item of report) {
|
|
78
|
+
if (!item.installed) {
|
|
79
|
+
console.log(`Anvia ${item.name}: not installed.`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
for (const file of item.files) {
|
|
83
|
+
if (file.status !== "up-to-date") changeCount += 1;
|
|
84
|
+
console.log(`Anvia ${item.name}: ${file.status} ${file.path}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
console.log(
|
|
88
|
+
changeCount === 0 ? "Everything is up to date." : `Found ${changeCount} out-of-date ${changeCount === 1 ? "file" : "files"}. Re-run with --overwrite to apply.`
|
|
89
|
+
);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
43
92
|
console.log(`Usage:
|
|
44
93
|
anvia init [next|vite] [--cwd <path>] [--force]
|
|
45
|
-
anvia add <${registryItemNames.join("|")}> [--cwd <path>] [--overwrite]
|
|
94
|
+
anvia add <${registryItemNames.join("|")}> [--cwd <path>] [--overwrite]
|
|
95
|
+
anvia update [${registryItemNames.join("|")}] [--cwd <path>] [--overwrite]`);
|
|
46
96
|
}
|
|
47
97
|
function optionValue(args, name) {
|
|
48
98
|
const index = args.indexOf(name);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport {\n addRegistryItem,\n closestRegistryItemName,\n initializeProject,\n isRegistryItemName,\n registryItemNames,\n updateInstalledItems,\n} from \"./index\";\n\nfunction main(args: string[]): void {\n const [command, ...commandArgs] = args;\n const cwd = optionValue(commandArgs, \"--cwd\");\n const positional = commandArgs.filter(\n (value, index) =>\n !value.startsWith(\"--\") && (index === 0 || commandArgs[index - 1] !== \"--cwd\"),\n );\n\n if (command === \"init\") {\n const value = positional[0];\n if (positional.length > 1 || (value !== undefined && value !== \"next\" && value !== \"vite\")) {\n throw new Error(\"The init template must be next or vite.\");\n }\n const options: Parameters<typeof initializeProject>[0] = {\n force: commandArgs.includes(\"--force\"),\n };\n if (cwd !== undefined) options.cwd = cwd;\n if (value === \"next\" || value === \"vite\") options.template = value;\n initializeProject(options);\n console.log(\"Anvia UI configuration is ready.\");\n return;\n }\n\n if (command === \"add\") {\n const value = positional[0];\n if (value === undefined || positional.length !== 1 || !isRegistryItemName(value)) {\n throw new Error(`Choose an item: ${registryItemNames.join(\", \")}.`);\n }\n const options: Parameters<typeof addRegistryItem>[1] = {\n overwrite: commandArgs.includes(\"--overwrite\"),\n };\n if (cwd !== undefined) options.cwd = cwd;\n addRegistryItem(value, options);\n console.log(`Added Anvia ${value}.`);\n return;\n }\n\n if (command === \"update\") {\n const items = positional.map((value) => {\n if (isRegistryItemName(value)) return value;\n const suggestion = closestRegistryItemName(value);\n const suffix = suggestion === undefined ? \"\" : ` Did you mean \"${suggestion}\"?`;\n throw new Error(\n `Unknown registry item \"${value}\".${suffix} Choose an item: ${registryItemNames.join(\", \")}.`,\n );\n });\n const overwrite = commandArgs.includes(\"--overwrite\");\n const options: Parameters<typeof updateInstalledItems>[0] = { overwrite };\n if (cwd !== undefined) options.cwd = cwd;\n if (items.length > 0) options.items = items;\n const { report, updated } = updateInstalledItems(options);\n const updatedPaths = new Set(updated);\n if (overwrite === true) {\n for (const item of report) {\n if (!item.installed) {\n console.log(`Anvia ${item.name}: not installed. Use \\`anvia add ${item.name}\\` first.`);\n continue;\n }\n const changed = item.files.some(\n (file) => file.status !== \"up-to-date\" && updatedPaths.has(file.path),\n );\n console.log(`Anvia ${item.name}: ${changed ? \"updated\" : \"up to date\"}.`);\n }\n console.log(\n updated.length === 0\n ? \"All installed Anvia components are up to date.\"\n : `Updated ${updated.length} ${updated.length === 1 ? \"file\" : \"files\"}.`,\n );\n return;\n }\n let changeCount = 0;\n for (const item of report) {\n if (!item.installed) {\n console.log(`Anvia ${item.name}: not installed.`);\n continue;\n }\n for (const file of item.files) {\n if (file.status !== \"up-to-date\") changeCount += 1;\n console.log(`Anvia ${item.name}: ${file.status} ${file.path}`);\n }\n }\n console.log(\n changeCount === 0\n ? \"Everything is up to date.\"\n : `Found ${changeCount} out-of-date ${changeCount === 1 ? \"file\" : \"files\"}. Re-run with --overwrite to apply.`,\n );\n return;\n }\n\n console.log(`Usage:\n anvia init [next|vite] [--cwd <path>] [--force]\n anvia add <${registryItemNames.join(\"|\")}> [--cwd <path>] [--overwrite]\n anvia update [${registryItemNames.join(\"|\")}] [--cwd <path>] [--overwrite]`);\n}\n\nfunction optionValue(args: string[], name: string): string | undefined {\n const index = args.indexOf(name);\n if (index === -1) return undefined;\n const value = args[index + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new Error(`${name} requires a value.`);\n }\n return value;\n}\n\ntry {\n main(process.argv.slice(2));\n} catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,5 +33,32 @@ declare function addRegistryItem(name: RegistryItemName, options?: {
|
|
|
33
33
|
overwrite?: boolean;
|
|
34
34
|
}): void;
|
|
35
35
|
declare function isRegistryItemName(value: string): value is RegistryItemName;
|
|
36
|
+
type InstalledFileStatus = "up-to-date" | "modified" | "missing";
|
|
37
|
+
type InstalledItemFile = {
|
|
38
|
+
filename: string;
|
|
39
|
+
path: string;
|
|
40
|
+
status: InstalledFileStatus;
|
|
41
|
+
};
|
|
42
|
+
type InstalledItemReport = {
|
|
43
|
+
name: RegistryItemName;
|
|
44
|
+
installed: boolean;
|
|
45
|
+
complete: boolean;
|
|
46
|
+
files: InstalledItemFile[];
|
|
47
|
+
};
|
|
48
|
+
declare function inspectInstalledItems(options?: {
|
|
49
|
+
cwd?: string;
|
|
50
|
+
items?: readonly RegistryItemName[];
|
|
51
|
+
registryDirectory?: string;
|
|
52
|
+
}): InstalledItemReport[];
|
|
53
|
+
declare function updateInstalledItems(options?: {
|
|
54
|
+
cwd?: string;
|
|
55
|
+
items?: readonly RegistryItemName[];
|
|
56
|
+
overwrite?: boolean;
|
|
57
|
+
registryDirectory?: string;
|
|
58
|
+
}): {
|
|
59
|
+
report: InstalledItemReport[];
|
|
60
|
+
updated: string[];
|
|
61
|
+
};
|
|
62
|
+
declare function closestRegistryItemName(value: string): RegistryItemName | undefined;
|
|
36
63
|
|
|
37
|
-
export { type AnviaRegistryItem, type RegistryItemName, addRegistryItem, createRegistryItem, initializeProject, isRegistryItemName, registryItemNames };
|
|
64
|
+
export { type AnviaRegistryItem, type InstalledFileStatus, type InstalledItemFile, type InstalledItemReport, type RegistryItemName, addRegistryItem, closestRegistryItemName, createRegistryItem, initializeProject, inspectInstalledItems, isRegistryItemName, registryItemNames, updateInstalledItems };
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
addRegistryItem,
|
|
3
|
+
closestRegistryItemName,
|
|
3
4
|
createRegistryItem,
|
|
4
5
|
initializeProject,
|
|
6
|
+
inspectInstalledItems,
|
|
5
7
|
isRegistryItemName,
|
|
6
|
-
registryItemNames
|
|
7
|
-
|
|
8
|
+
registryItemNames,
|
|
9
|
+
updateInstalledItems
|
|
10
|
+
} from "./chunk-IH4ZNWHB.js";
|
|
8
11
|
export {
|
|
9
12
|
addRegistryItem,
|
|
13
|
+
closestRegistryItemName,
|
|
10
14
|
createRegistryItem,
|
|
11
15
|
initializeProject,
|
|
16
|
+
inspectInstalledItems,
|
|
12
17
|
isRegistryItemName,
|
|
13
|
-
registryItemNames
|
|
18
|
+
registryItemNames,
|
|
19
|
+
updateInstalledItems
|
|
14
20
|
};
|
|
15
21
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anvia/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Install editable Anvia UI components into React applications.",
|
|
5
5
|
"author": "anvia",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"node": ">=20.18.1"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"shadcn": "^4.
|
|
32
|
+
"shadcn": "^4.21.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^24.9.1",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"tsup": "^8.5.0",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
40
|
"vitest": "^4.0.8",
|
|
41
|
-
"@anvia/react-ui": "1.1.
|
|
41
|
+
"@anvia/react-ui": "1.1.3"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup src/index.ts src/cli.ts --format esm --dts --sourcemap --clean && node scripts/copy-registry.mjs && chmod +x dist/cli.js",
|
package/dist/chunk-TE2ODJOV.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import { spawnSync } from "child_process";
|
|
3
|
-
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
4
|
-
import { createRequire } from "module";
|
|
5
|
-
import { tmpdir } from "os";
|
|
6
|
-
import { basename, join } from "path";
|
|
7
|
-
import { fileURLToPath } from "url";
|
|
8
|
-
var registryItemNames = [
|
|
9
|
-
"chat",
|
|
10
|
-
"thread",
|
|
11
|
-
"message",
|
|
12
|
-
"composer",
|
|
13
|
-
"attachment",
|
|
14
|
-
"markdown",
|
|
15
|
-
"tool-fallback"
|
|
16
|
-
];
|
|
17
|
-
var itemFiles = {
|
|
18
|
-
attachment: ["attachment.tsx"],
|
|
19
|
-
chat: [
|
|
20
|
-
"attachment.tsx",
|
|
21
|
-
"markdown.tsx",
|
|
22
|
-
"tool-fallback.tsx",
|
|
23
|
-
"message.tsx",
|
|
24
|
-
"composer.tsx",
|
|
25
|
-
"thread.tsx",
|
|
26
|
-
"chat.tsx"
|
|
27
|
-
],
|
|
28
|
-
composer: ["attachment.tsx", "composer.tsx"],
|
|
29
|
-
markdown: ["markdown.tsx"],
|
|
30
|
-
message: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx"],
|
|
31
|
-
thread: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx", "thread.tsx"],
|
|
32
|
-
"tool-fallback": ["tool-fallback.tsx"]
|
|
33
|
-
};
|
|
34
|
-
var revealCss = {
|
|
35
|
-
"@keyframes anvia-stream-gradient-settle": {
|
|
36
|
-
to: {
|
|
37
|
-
opacity: "1"
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"@layer components": {
|
|
41
|
-
'.anvia-markdown [data-state="revealing"]': {
|
|
42
|
-
animation: "anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both",
|
|
43
|
-
opacity: "var(--anvia-stream-reveal-opacity, 1)"
|
|
44
|
-
},
|
|
45
|
-
"@media (prefers-reduced-motion: reduce)": {
|
|
46
|
-
'.anvia-markdown [data-state="revealing"]': {
|
|
47
|
-
animation: "none",
|
|
48
|
-
opacity: "1"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
function createRegistryItem(name, options = {}) {
|
|
54
|
-
const packageVersion = options.packageVersion ?? currentPackageVersion();
|
|
55
|
-
const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();
|
|
56
|
-
const files = itemFiles[name].map((filename) => ({
|
|
57
|
-
content: readFileSync(join(registryDirectory, filename), "utf8"),
|
|
58
|
-
path: `registry/anvia/${filename}`,
|
|
59
|
-
target: `@components/anvia/${filename}`,
|
|
60
|
-
type: "registry:component"
|
|
61
|
-
}));
|
|
62
|
-
const item = {
|
|
63
|
-
$schema: "https://ui.shadcn.com/schema/registry-item.json",
|
|
64
|
-
dependencies: [`@anvia/react-ui@${packageVersion}`],
|
|
65
|
-
description: registryItemDescription(name),
|
|
66
|
-
files,
|
|
67
|
-
name,
|
|
68
|
-
title: `Anvia ${name}`,
|
|
69
|
-
type: files.length === 1 ? "registry:component" : "registry:block"
|
|
70
|
-
};
|
|
71
|
-
if (name === "chat" || name === "markdown" || name === "message" || name === "thread") {
|
|
72
|
-
item.css = revealCss;
|
|
73
|
-
}
|
|
74
|
-
return item;
|
|
75
|
-
}
|
|
76
|
-
function initializeProject(options = {}) {
|
|
77
|
-
const cwd = options.cwd ?? process.cwd();
|
|
78
|
-
const args = ["init", "--cwd", cwd, "--yes", "--no-monorepo", "--base", "radix"];
|
|
79
|
-
if (options.template !== void 0) args.push("--template", options.template);
|
|
80
|
-
if (options.force === true) args.push("--force");
|
|
81
|
-
runShadcn(args);
|
|
82
|
-
}
|
|
83
|
-
function addRegistryItem(name, options = {}) {
|
|
84
|
-
const cwd = options.cwd ?? process.cwd();
|
|
85
|
-
const temporaryDirectory = mkdtempSync(join(tmpdir(), "anvia-registry-"));
|
|
86
|
-
const itemPath = join(temporaryDirectory, `${name}.json`);
|
|
87
|
-
try {
|
|
88
|
-
writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}
|
|
89
|
-
`);
|
|
90
|
-
const args = ["add", itemPath, "--cwd", cwd, "--yes"];
|
|
91
|
-
if (options.overwrite === true) args.push("--overwrite");
|
|
92
|
-
runShadcn(args);
|
|
93
|
-
} finally {
|
|
94
|
-
rmSync(temporaryDirectory, { force: true, recursive: true });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function isRegistryItemName(value) {
|
|
98
|
-
return registryItemNames.includes(value);
|
|
99
|
-
}
|
|
100
|
-
function runShadcn(args) {
|
|
101
|
-
const require2 = createRequire(import.meta.url);
|
|
102
|
-
const shadcnEntry = require2.resolve("shadcn");
|
|
103
|
-
const result = spawnSync(process.execPath, [shadcnEntry, ...args], {
|
|
104
|
-
encoding: "utf8",
|
|
105
|
-
stdio: "inherit"
|
|
106
|
-
});
|
|
107
|
-
if (result.error !== void 0) throw result.error;
|
|
108
|
-
if (result.status !== 0) {
|
|
109
|
-
throw new Error(`shadcn ${args[0] ?? "command"} failed with exit code ${result.status}.`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
function bundledRegistryDirectory() {
|
|
113
|
-
return fileURLToPath(new URL("./registry/", import.meta.url));
|
|
114
|
-
}
|
|
115
|
-
function currentPackageVersion() {
|
|
116
|
-
const manifestPath = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
117
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
118
|
-
if (typeof manifest.version !== "string") {
|
|
119
|
-
throw new Error(`Missing package version in ${basename(manifestPath)}.`);
|
|
120
|
-
}
|
|
121
|
-
return manifest.version;
|
|
122
|
-
}
|
|
123
|
-
function registryItemDescription(name) {
|
|
124
|
-
if (name === "chat") return "A complete editable Anvia chat interface.";
|
|
125
|
-
return `Editable Anvia ${name} UI.`;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export {
|
|
129
|
-
registryItemNames,
|
|
130
|
-
createRegistryItem,
|
|
131
|
-
initializeProject,
|
|
132
|
-
addRegistryItem,
|
|
133
|
-
isRegistryItemName
|
|
134
|
-
};
|
|
135
|
-
//# sourceMappingURL=chunk-TE2ODJOV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const registryItemNames = [\n \"chat\",\n \"thread\",\n \"message\",\n \"composer\",\n \"attachment\",\n \"markdown\",\n \"tool-fallback\",\n] as const;\n\nexport type RegistryItemName = (typeof registryItemNames)[number];\n\ntype RegistryFile = {\n content: string;\n path: string;\n target: string;\n type: \"registry:component\";\n};\n\ntype RegistryCss = {\n [rule: string]: RegistryCss | string;\n};\n\nexport type AnviaRegistryItem = {\n $schema: string;\n css?: RegistryCss;\n dependencies: string[];\n description: string;\n files: RegistryFile[];\n name: RegistryItemName;\n title: string;\n type: \"registry:block\" | \"registry:component\";\n};\n\nconst itemFiles: Record<RegistryItemName, readonly string[]> = {\n attachment: [\"attachment.tsx\"],\n chat: [\n \"attachment.tsx\",\n \"markdown.tsx\",\n \"tool-fallback.tsx\",\n \"message.tsx\",\n \"composer.tsx\",\n \"thread.tsx\",\n \"chat.tsx\",\n ],\n composer: [\"attachment.tsx\", \"composer.tsx\"],\n markdown: [\"markdown.tsx\"],\n message: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\"],\n thread: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\", \"thread.tsx\"],\n \"tool-fallback\": [\"tool-fallback.tsx\"],\n};\n\nconst revealCss = {\n \"@keyframes anvia-stream-gradient-settle\": {\n to: {\n opacity: \"1\",\n },\n },\n \"@layer components\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation:\n \"anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both\",\n opacity: \"var(--anvia-stream-reveal-opacity, 1)\",\n },\n \"@media (prefers-reduced-motion: reduce)\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation: \"none\",\n opacity: \"1\",\n },\n },\n },\n} satisfies RegistryCss;\n\nexport function createRegistryItem(\n name: RegistryItemName,\n options: { packageVersion?: string; registryDirectory?: string } = {},\n): AnviaRegistryItem {\n const packageVersion = options.packageVersion ?? currentPackageVersion();\n const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();\n const files = itemFiles[name].map((filename) => ({\n content: readFileSync(join(registryDirectory, filename), \"utf8\"),\n path: `registry/anvia/${filename}`,\n target: `@components/anvia/${filename}`,\n type: \"registry:component\" as const,\n }));\n const item: AnviaRegistryItem = {\n $schema: \"https://ui.shadcn.com/schema/registry-item.json\",\n dependencies: [`@anvia/react-ui@${packageVersion}`],\n description: registryItemDescription(name),\n files,\n name,\n title: `Anvia ${name}`,\n type: files.length === 1 ? \"registry:component\" : \"registry:block\",\n };\n if (name === \"chat\" || name === \"markdown\" || name === \"message\" || name === \"thread\") {\n item.css = revealCss;\n }\n return item;\n}\n\nexport function initializeProject(\n options: { cwd?: string; force?: boolean; template?: \"next\" | \"vite\" } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const args = [\"init\", \"--cwd\", cwd, \"--yes\", \"--no-monorepo\", \"--base\", \"radix\"];\n if (options.template !== undefined) args.push(\"--template\", options.template);\n if (options.force === true) args.push(\"--force\");\n runShadcn(args);\n}\n\nexport function addRegistryItem(\n name: RegistryItemName,\n options: { cwd?: string; overwrite?: boolean } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const temporaryDirectory = mkdtempSync(join(tmpdir(), \"anvia-registry-\"));\n const itemPath = join(temporaryDirectory, `${name}.json`);\n try {\n writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}\\n`);\n const args = [\"add\", itemPath, \"--cwd\", cwd, \"--yes\"];\n if (options.overwrite === true) args.push(\"--overwrite\");\n runShadcn(args);\n } finally {\n rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nexport function isRegistryItemName(value: string): value is RegistryItemName {\n return registryItemNames.includes(value as RegistryItemName);\n}\n\nfunction runShadcn(args: string[]): void {\n const require = createRequire(import.meta.url);\n const shadcnEntry = require.resolve(\"shadcn\");\n const result = spawnSync(process.execPath, [shadcnEntry, ...args], {\n encoding: \"utf8\",\n stdio: \"inherit\",\n });\n if (result.error !== undefined) throw result.error;\n if (result.status !== 0) {\n throw new Error(`shadcn ${args[0] ?? \"command\"} failed with exit code ${result.status}.`);\n }\n}\n\nfunction bundledRegistryDirectory(): string {\n return fileURLToPath(new URL(\"./registry/\", import.meta.url));\n}\n\nfunction currentPackageVersion(): string {\n const manifestPath = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { version?: unknown };\n if (typeof manifest.version !== \"string\") {\n throw new Error(`Missing package version in ${basename(manifestPath)}.`);\n }\n return manifest.version;\n}\n\nfunction registryItemDescription(name: RegistryItemName): string {\n if (name === \"chat\") return \"A complete editable Anvia chat interface.\";\n return `Editable Anvia ${name} UI.`;\n}\n"],"mappings":"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","names":["require"]}
|