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.
Files changed (65) hide show
  1. package/README.md +1 -0
  2. package/dist/commands/add.d.ts +28 -0
  3. package/dist/commands/add.d.ts.map +1 -0
  4. package/dist/commands/add.js +104 -0
  5. package/dist/commands/augment.d.ts +2 -0
  6. package/dist/commands/augment.d.ts.map +1 -0
  7. package/dist/commands/augment.js +97 -0
  8. package/dist/commands/diff.d.ts +19 -0
  9. package/dist/commands/diff.d.ts.map +1 -0
  10. package/dist/commands/diff.js +233 -0
  11. package/dist/commands/index.d.ts +3 -0
  12. package/dist/commands/index.d.ts.map +1 -0
  13. package/dist/commands/index.js +2 -0
  14. package/dist/commands/snapshot.d.ts +2 -0
  15. package/dist/commands/snapshot.d.ts.map +1 -0
  16. package/dist/commands/snapshot.js +99 -0
  17. package/dist/commands/update.d.ts +28 -0
  18. package/dist/commands/update.d.ts.map +1 -0
  19. package/dist/commands/update.js +203 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +89 -0
  23. package/dist/types/changelog.d.ts +17 -0
  24. package/dist/types/changelog.d.ts.map +1 -0
  25. package/dist/types/changelog.js +1 -0
  26. package/dist/types/lock-file.d.ts +41 -0
  27. package/dist/types/lock-file.d.ts.map +1 -0
  28. package/dist/types/lock-file.js +4 -0
  29. package/dist/types/registry.d.ts +84 -0
  30. package/dist/types/registry.d.ts.map +1 -0
  31. package/dist/types/registry.js +4 -0
  32. package/dist/utils/checksum.d.ts +27 -0
  33. package/dist/utils/checksum.d.ts.map +1 -0
  34. package/dist/utils/checksum.js +50 -0
  35. package/dist/utils/component-locator.d.ts +23 -0
  36. package/dist/utils/component-locator.d.ts.map +1 -0
  37. package/dist/utils/component-locator.js +59 -0
  38. package/dist/utils/diff-formatter.d.ts +47 -0
  39. package/dist/utils/diff-formatter.d.ts.map +1 -0
  40. package/dist/utils/diff-formatter.js +186 -0
  41. package/dist/utils/file-operations.d.ts +7 -0
  42. package/dist/utils/file-operations.d.ts.map +1 -0
  43. package/dist/utils/file-operations.js +37 -0
  44. package/dist/utils/lock-file.d.ts +60 -0
  45. package/dist/utils/lock-file.d.ts.map +1 -0
  46. package/dist/utils/lock-file.js +110 -0
  47. package/dist/utils/merge.d.ts +54 -0
  48. package/dist/utils/merge.d.ts.map +1 -0
  49. package/dist/utils/merge.js +84 -0
  50. package/dist/utils/prompts.d.ts +8 -0
  51. package/dist/utils/prompts.d.ts.map +1 -0
  52. package/dist/utils/prompts.js +49 -0
  53. package/dist/utils/registry.d.ts +32 -0
  54. package/dist/utils/registry.d.ts.map +1 -0
  55. package/dist/utils/registry.js +139 -0
  56. package/dist/utils/shadcn.d.ts +30 -0
  57. package/dist/utils/shadcn.d.ts.map +1 -0
  58. package/dist/utils/shadcn.js +67 -0
  59. package/dist/validators/changelog.d.ts +50 -0
  60. package/dist/validators/changelog.d.ts.map +1 -0
  61. package/dist/validators/changelog.js +31 -0
  62. package/dist/validators/lock-file.d.ts +32 -0
  63. package/dist/validators/lock-file.d.ts.map +1 -0
  64. package/dist/validators/lock-file.js +39 -0
  65. 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
+ }