voidui-cli 0.1.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 +1 -0
- package/dist/commands/add.d.ts +28 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +104 -0
- package/dist/commands/augment.d.ts +2 -0
- package/dist/commands/augment.d.ts.map +1 -0
- package/dist/commands/augment.js +97 -0
- package/dist/commands/diff.d.ts +19 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +233 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/snapshot.d.ts +2 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +99 -0
- package/dist/commands/update.d.ts +28 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +203 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +89 -0
- package/dist/types/changelog.d.ts +17 -0
- package/dist/types/changelog.d.ts.map +1 -0
- package/dist/types/changelog.js +1 -0
- package/dist/types/lock-file.d.ts +41 -0
- package/dist/types/lock-file.d.ts.map +1 -0
- package/dist/types/lock-file.js +4 -0
- package/dist/types/registry.d.ts +84 -0
- package/dist/types/registry.d.ts.map +1 -0
- package/dist/types/registry.js +4 -0
- package/dist/utils/checksum.d.ts +27 -0
- package/dist/utils/checksum.d.ts.map +1 -0
- package/dist/utils/checksum.js +50 -0
- package/dist/utils/component-locator.d.ts +23 -0
- package/dist/utils/component-locator.d.ts.map +1 -0
- package/dist/utils/component-locator.js +59 -0
- package/dist/utils/diff-formatter.d.ts +47 -0
- package/dist/utils/diff-formatter.d.ts.map +1 -0
- package/dist/utils/diff-formatter.js +186 -0
- package/dist/utils/file-operations.d.ts +7 -0
- package/dist/utils/file-operations.d.ts.map +1 -0
- package/dist/utils/file-operations.js +37 -0
- package/dist/utils/lock-file.d.ts +60 -0
- package/dist/utils/lock-file.d.ts.map +1 -0
- package/dist/utils/lock-file.js +110 -0
- package/dist/utils/merge.d.ts +54 -0
- package/dist/utils/merge.d.ts.map +1 -0
- package/dist/utils/merge.js +84 -0
- package/dist/utils/prompts.d.ts +8 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +49 -0
- package/dist/utils/registry.d.ts +32 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +139 -0
- package/dist/utils/shadcn.d.ts +30 -0
- package/dist/utils/shadcn.d.ts.map +1 -0
- package/dist/utils/shadcn.js +67 -0
- package/dist/validators/changelog.d.ts +50 -0
- package/dist/validators/changelog.d.ts.map +1 -0
- package/dist/validators/changelog.js +31 -0
- package/dist/validators/lock-file.d.ts +32 -0
- package/dist/validators/lock-file.d.ts.map +1 -0
- package/dist/validators/lock-file.js +39 -0
- package/package.json +56 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry API client for fetching component metadata
|
|
3
|
+
*/
|
|
4
|
+
import type { RegistryItem } from "../types/registry.js";
|
|
5
|
+
/**
|
|
6
|
+
* Fetch component metadata from the registry
|
|
7
|
+
* Includes retry logic for network failures
|
|
8
|
+
*
|
|
9
|
+
* @param componentName - Name of the component (e.g., "separator")
|
|
10
|
+
* @param registryUrl - Base registry URL
|
|
11
|
+
* @returns Registry item or null if not found
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchRegistryItem(componentName: string, registryUrl: string): Promise<RegistryItem | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Fetch specific version of a component from the registry
|
|
16
|
+
* Note: This fetches from the versions endpoint in the registry
|
|
17
|
+
*
|
|
18
|
+
* @param componentName - Name of the component
|
|
19
|
+
* @param version - Semantic version (e.g., "1.0.0")
|
|
20
|
+
* @param registryUrl - Base registry URL
|
|
21
|
+
* @returns Component source code or null if not found
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchComponentVersion(componentName: string, version: string, registryUrl: string): Promise<string | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Extract component source code from a registry item
|
|
26
|
+
* Finds the main component file (usually in components/ui/)
|
|
27
|
+
*
|
|
28
|
+
* @param registryItem - Registry item metadata
|
|
29
|
+
* @returns Component source code
|
|
30
|
+
*/
|
|
31
|
+
export declare function extractComponentCode(registryItem: RegistryItem): string;
|
|
32
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/utils/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAuB9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBxB;AAqDD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,YAAY,GAAG,MAAM,CAavE"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry API client for fetching component metadata
|
|
3
|
+
*/
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { readFile } from "fs/promises";
|
|
6
|
+
import { fileExists } from "./file-operations.js";
|
|
7
|
+
/**
|
|
8
|
+
* Fetch component metadata from the registry
|
|
9
|
+
* Includes retry logic for network failures
|
|
10
|
+
*
|
|
11
|
+
* @param componentName - Name of the component (e.g., "separator")
|
|
12
|
+
* @param registryUrl - Base registry URL
|
|
13
|
+
* @returns Registry item or null if not found
|
|
14
|
+
*/
|
|
15
|
+
export async function fetchRegistryItem(componentName, registryUrl) {
|
|
16
|
+
const url = `${registryUrl}/${componentName}.json`;
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetchWithRetry(url, { maxRetries: 1 });
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
if (response.status === 404) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
24
|
+
}
|
|
25
|
+
const data = await response.json();
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error instanceof Error && error.message.includes("fetch failed")) {
|
|
30
|
+
throw new Error(`Failed to fetch registry data. Check your internet connection.\n Tried: ${url}`);
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fetch specific version of a component from the registry
|
|
37
|
+
* Note: This fetches from the versions endpoint in the registry
|
|
38
|
+
*
|
|
39
|
+
* @param componentName - Name of the component
|
|
40
|
+
* @param version - Semantic version (e.g., "1.0.0")
|
|
41
|
+
* @param registryUrl - Base registry URL
|
|
42
|
+
* @returns Component source code or null if not found
|
|
43
|
+
*/
|
|
44
|
+
export async function fetchComponentVersion(componentName, version, registryUrl) {
|
|
45
|
+
const item = await fetchRegistryItem(componentName, registryUrl);
|
|
46
|
+
if (!item) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
// If requesting current version, return from files
|
|
50
|
+
if (item.meta?.versioning?.currentVersion === version) {
|
|
51
|
+
return extractComponentCode(item);
|
|
52
|
+
}
|
|
53
|
+
// For historical versions, try localhost file system fallback for local development
|
|
54
|
+
if (registryUrl.includes("localhost") || registryUrl.includes("127.0.0.1")) {
|
|
55
|
+
const localVersion = await tryFetchLocalVersion(componentName, version);
|
|
56
|
+
if (localVersion) {
|
|
57
|
+
return localVersion;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// For historical versions on production, we'd need to fetch from a versions endpoint
|
|
61
|
+
// This requires registry infrastructure to serve historical versions
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Try to fetch a historical version from local file system
|
|
66
|
+
* Only used for local development testing
|
|
67
|
+
*
|
|
68
|
+
* @param componentName - Name of the component
|
|
69
|
+
* @param version - Semantic version
|
|
70
|
+
* @returns Component source code or null if not found
|
|
71
|
+
*/
|
|
72
|
+
async function tryFetchLocalVersion(componentName, version) {
|
|
73
|
+
// Try common local paths for version files
|
|
74
|
+
const possiblePaths = [
|
|
75
|
+
// From www-docs directory
|
|
76
|
+
path.join(process.cwd(), "registry", "components", "ui", `${componentName}.versions`, `${version}.tsx`),
|
|
77
|
+
// From monorepo root
|
|
78
|
+
path.join(process.cwd(), "apps", "www-docs", "registry", "components", "ui", `${componentName}.versions`, `${version}.tsx`),
|
|
79
|
+
];
|
|
80
|
+
for (const versionPath of possiblePaths) {
|
|
81
|
+
if (await fileExists(versionPath)) {
|
|
82
|
+
try {
|
|
83
|
+
const content = await readFile(versionPath, "utf-8");
|
|
84
|
+
return content;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// Continue trying other paths
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Extract component source code from a registry item
|
|
96
|
+
* Finds the main component file (usually in components/ui/)
|
|
97
|
+
*
|
|
98
|
+
* @param registryItem - Registry item metadata
|
|
99
|
+
* @returns Component source code
|
|
100
|
+
*/
|
|
101
|
+
export function extractComponentCode(registryItem) {
|
|
102
|
+
// Find the main UI component file
|
|
103
|
+
const mainFile = registryItem.files.find((file) => file.type === "registry:ui" || file.path.includes("/components/ui/"));
|
|
104
|
+
if (!mainFile) {
|
|
105
|
+
// Fallback to first file if no UI file found
|
|
106
|
+
return registryItem.files[0]?.content || "";
|
|
107
|
+
}
|
|
108
|
+
return mainFile.content;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Fetch with retry logic
|
|
112
|
+
*
|
|
113
|
+
* @param url - URL to fetch
|
|
114
|
+
* @param options - Fetch options with maxRetries
|
|
115
|
+
* @returns Fetch response
|
|
116
|
+
*/
|
|
117
|
+
async function fetchWithRetry(url, options = {}) {
|
|
118
|
+
const maxRetries = options.maxRetries ?? 1;
|
|
119
|
+
let lastError = null;
|
|
120
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
121
|
+
try {
|
|
122
|
+
const response = await fetch(url, {
|
|
123
|
+
headers: {
|
|
124
|
+
"User-Agent": "voidui-cli",
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
return response;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
131
|
+
// Don't retry on last attempt
|
|
132
|
+
if (attempt < maxRetries) {
|
|
133
|
+
// Wait 2 seconds before retry
|
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw lastError || new Error("Fetch failed");
|
|
139
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shadcn CLI integration utilities
|
|
3
|
+
* Handles executing shadcn CLI commands
|
|
4
|
+
*/
|
|
5
|
+
export interface ShadcnOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Registry URL
|
|
8
|
+
*/
|
|
9
|
+
registryUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to show command output
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
silent?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Execute shadcn add command to install a component
|
|
18
|
+
*
|
|
19
|
+
* @param componentName - Component to install
|
|
20
|
+
* @param options - Execution options
|
|
21
|
+
* @returns Promise that resolves when installation completes
|
|
22
|
+
*/
|
|
23
|
+
export declare function execShadcnAdd(componentName: string, options: ShadcnOptions): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Check if shadcn CLI is available
|
|
26
|
+
*
|
|
27
|
+
* @returns Promise that resolves to true if shadcn is available
|
|
28
|
+
*/
|
|
29
|
+
export declare function isShadcnAvailable(): Promise<boolean>;
|
|
30
|
+
//# sourceMappingURL=shadcn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shadcn.d.ts","sourceRoot":"","sources":["../../src/utils/shadcn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAe1D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shadcn CLI integration utilities
|
|
3
|
+
* Handles executing shadcn CLI commands
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from "child_process";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
/**
|
|
8
|
+
* Execute shadcn add command to install a component
|
|
9
|
+
*
|
|
10
|
+
* @param componentName - Component to install
|
|
11
|
+
* @param options - Execution options
|
|
12
|
+
* @returns Promise that resolves when installation completes
|
|
13
|
+
*/
|
|
14
|
+
export async function execShadcnAdd(componentName, options) {
|
|
15
|
+
const { registryUrl, silent = false } = options;
|
|
16
|
+
// Build the component URL
|
|
17
|
+
const componentUrl = `${registryUrl}/${componentName}`;
|
|
18
|
+
if (!silent) {
|
|
19
|
+
console.log(chalk.blue(`\n📦 Installing ${componentName} via shadcn...\n`));
|
|
20
|
+
}
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
// Spawn npx shadcn@latest add <component-url>
|
|
23
|
+
const child = spawn("npx", [
|
|
24
|
+
"shadcn@latest",
|
|
25
|
+
"add",
|
|
26
|
+
componentUrl,
|
|
27
|
+
"--yes", // Auto-confirm prompts
|
|
28
|
+
"--overwrite", // Overwrite if exists (for --force mode)
|
|
29
|
+
], {
|
|
30
|
+
stdio: silent ? "pipe" : "inherit", // Inherit to show output to user
|
|
31
|
+
shell: true,
|
|
32
|
+
});
|
|
33
|
+
child.on("error", (error) => {
|
|
34
|
+
reject(new Error(`Failed to execute shadcn CLI: ${error.message}\nMake sure npx is available in your PATH.`));
|
|
35
|
+
});
|
|
36
|
+
child.on("close", (code) => {
|
|
37
|
+
if (code === 0) {
|
|
38
|
+
if (!silent) {
|
|
39
|
+
console.log(chalk.green(`\n✓ Component installed successfully\n`));
|
|
40
|
+
}
|
|
41
|
+
resolve();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
reject(new Error(`shadcn CLI exited with code ${code}. Installation failed.`));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if shadcn CLI is available
|
|
51
|
+
*
|
|
52
|
+
* @returns Promise that resolves to true if shadcn is available
|
|
53
|
+
*/
|
|
54
|
+
export async function isShadcnAvailable() {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const child = spawn("npx", ["shadcn@latest", "--version"], {
|
|
57
|
+
stdio: "pipe",
|
|
58
|
+
shell: true,
|
|
59
|
+
});
|
|
60
|
+
child.on("error", () => {
|
|
61
|
+
resolve(false);
|
|
62
|
+
});
|
|
63
|
+
child.on("close", (code) => {
|
|
64
|
+
resolve(code === 0);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const changelogChangeSchema: z.ZodObject<{
|
|
3
|
+
type: z.ZodEnum<{
|
|
4
|
+
added: "added";
|
|
5
|
+
changed: "changed";
|
|
6
|
+
deprecated: "deprecated";
|
|
7
|
+
removed: "removed";
|
|
8
|
+
fixed: "fixed";
|
|
9
|
+
security: "security";
|
|
10
|
+
}>;
|
|
11
|
+
description: z.ZodString;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export declare const changelogEntrySchema: z.ZodObject<{
|
|
14
|
+
version: z.ZodString;
|
|
15
|
+
date: z.ZodString;
|
|
16
|
+
changes: z.ZodArray<z.ZodObject<{
|
|
17
|
+
type: z.ZodEnum<{
|
|
18
|
+
added: "added";
|
|
19
|
+
changed: "changed";
|
|
20
|
+
deprecated: "deprecated";
|
|
21
|
+
removed: "removed";
|
|
22
|
+
fixed: "fixed";
|
|
23
|
+
security: "security";
|
|
24
|
+
}>;
|
|
25
|
+
description: z.ZodString;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
breaking: z.ZodOptional<z.ZodBoolean>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export declare const componentChangelogSchema: z.ZodObject<{
|
|
30
|
+
component: z.ZodString;
|
|
31
|
+
currentVersion: z.ZodString;
|
|
32
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
33
|
+
version: z.ZodString;
|
|
34
|
+
date: z.ZodString;
|
|
35
|
+
changes: z.ZodArray<z.ZodObject<{
|
|
36
|
+
type: z.ZodEnum<{
|
|
37
|
+
added: "added";
|
|
38
|
+
changed: "changed";
|
|
39
|
+
deprecated: "deprecated";
|
|
40
|
+
removed: "removed";
|
|
41
|
+
fixed: "fixed";
|
|
42
|
+
security: "security";
|
|
43
|
+
}>;
|
|
44
|
+
description: z.ZodString;
|
|
45
|
+
}, z.core.$strip>>;
|
|
46
|
+
breaking: z.ZodOptional<z.ZodBoolean>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export type { z } from "zod";
|
|
50
|
+
//# sourceMappingURL=changelog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/validators/changelog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB;;;;;;;;;;iBAUhC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAS/B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;iBAQnC,CAAC;AAEH,YAAY,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const changelogChangeSchema = z.object({
|
|
3
|
+
type: z.enum([
|
|
4
|
+
"added",
|
|
5
|
+
"changed",
|
|
6
|
+
"deprecated",
|
|
7
|
+
"removed",
|
|
8
|
+
"fixed",
|
|
9
|
+
"security",
|
|
10
|
+
]),
|
|
11
|
+
description: z.string().min(1, "Description cannot be empty"),
|
|
12
|
+
});
|
|
13
|
+
export const changelogEntrySchema = z.object({
|
|
14
|
+
version: z
|
|
15
|
+
.string()
|
|
16
|
+
.regex(/^\d+\.\d+\.\d+$/, "Version must be in semver format (e.g., 1.0.0)"),
|
|
17
|
+
date: z.string().datetime("Date must be in ISO 8601 format"),
|
|
18
|
+
changes: z
|
|
19
|
+
.array(changelogChangeSchema)
|
|
20
|
+
.min(1, "At least one change is required"),
|
|
21
|
+
breaking: z.boolean().optional(),
|
|
22
|
+
});
|
|
23
|
+
export const componentChangelogSchema = z.object({
|
|
24
|
+
component: z.string().min(1, "Component name cannot be empty"),
|
|
25
|
+
currentVersion: z
|
|
26
|
+
.string()
|
|
27
|
+
.regex(/^\d+\.\d+\.\d+$/, "Version must be in semver format (e.g., 1.0.0)"),
|
|
28
|
+
entries: z
|
|
29
|
+
.array(changelogEntrySchema)
|
|
30
|
+
.min(1, "At least one changelog entry is required"),
|
|
31
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod validators for lock file structure
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/**
|
|
6
|
+
* Schema for a single component lock entry
|
|
7
|
+
*/
|
|
8
|
+
export declare const componentLockEntrySchema: z.ZodObject<{
|
|
9
|
+
installedVersion: z.ZodString;
|
|
10
|
+
installedAt: z.ZodString;
|
|
11
|
+
checksum: z.ZodString;
|
|
12
|
+
registryUrl: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
/**
|
|
15
|
+
* Schema for the complete lock file
|
|
16
|
+
*/
|
|
17
|
+
export declare const lockFileSchema: z.ZodObject<{
|
|
18
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
19
|
+
version: z.ZodString;
|
|
20
|
+
components: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
21
|
+
installedVersion: z.ZodString;
|
|
22
|
+
installedAt: z.ZodString;
|
|
23
|
+
checksum: z.ZodString;
|
|
24
|
+
registryUrl: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
/**
|
|
28
|
+
* Infer TypeScript types from schemas
|
|
29
|
+
*/
|
|
30
|
+
export type ComponentLockEntry = z.infer<typeof componentLockEntrySchema>;
|
|
31
|
+
export type LockFile = z.infer<typeof lockFileSchema>;
|
|
32
|
+
//# sourceMappingURL=lock-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-file.d.ts","sourceRoot":"","sources":["../../src/validators/lock-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBxB;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;iBAKnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;;;iBAIzB,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod validators for lock file structure
|
|
3
|
+
*/
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/**
|
|
6
|
+
* Validates a semver version string (e.g., "1.2.0")
|
|
7
|
+
*/
|
|
8
|
+
const semverSchema = z.string().regex(/^\d+\.\d+\.\d+$/, {
|
|
9
|
+
message: "Version must be in semver format (e.g., 1.2.0)",
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Validates a SHA-256 checksum string
|
|
13
|
+
*/
|
|
14
|
+
const checksumSchema = z.string().regex(/^sha256:[a-f0-9]{64}$/, {
|
|
15
|
+
message: "Checksum must be in format: sha256:[64 hex chars]",
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Validates an ISO 8601 datetime string
|
|
19
|
+
*/
|
|
20
|
+
const isoDateSchema = z.string().datetime({
|
|
21
|
+
message: "Date must be in ISO 8601 format",
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Schema for a single component lock entry
|
|
25
|
+
*/
|
|
26
|
+
export const componentLockEntrySchema = z.object({
|
|
27
|
+
installedVersion: semverSchema,
|
|
28
|
+
installedAt: isoDateSchema,
|
|
29
|
+
checksum: checksumSchema,
|
|
30
|
+
registryUrl: z.string().url().optional(),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Schema for the complete lock file
|
|
34
|
+
*/
|
|
35
|
+
export const lockFileSchema = z.object({
|
|
36
|
+
$schema: z.string().optional(),
|
|
37
|
+
version: z.string(),
|
|
38
|
+
components: z.record(z.string(), componentLockEntrySchema),
|
|
39
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "voidui-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tools for voidui component versioning",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/mnove/voidui.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/mnove/voidui#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/mnove/voidui/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"voidui",
|
|
17
|
+
"cli",
|
|
18
|
+
"component",
|
|
19
|
+
"versioning"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bin": {
|
|
23
|
+
"voidui": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"dev": "tsc --watch",
|
|
28
|
+
"lint": "eslint . --max-warnings 0"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"chalk": "^5.4.1",
|
|
32
|
+
"commander": "^12.1.0",
|
|
33
|
+
"diff": "^8.0.3",
|
|
34
|
+
"glob": "^10.3.10",
|
|
35
|
+
"node-diff3": "^3.1.2",
|
|
36
|
+
"prompts": "^2.4.2",
|
|
37
|
+
"zod": "^4.0.17"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^24.1.0",
|
|
41
|
+
"@types/prompts": "^2.4.9",
|
|
42
|
+
"@workspace/eslint-config": "workspace:*",
|
|
43
|
+
"@workspace/typescript-config": "workspace:*",
|
|
44
|
+
"eslint": "^9.32.0",
|
|
45
|
+
"typescript": "^5.9.2"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"dist"
|
|
52
|
+
],
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
}
|
|
56
|
+
}
|