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,47 @@
1
+ /**
2
+ * Utilities for formatting diffs and changelogs for terminal output
3
+ */
4
+ import type { ChangelogEntry } from "../types/changelog.js";
5
+ export interface DiffOptions {
6
+ /**
7
+ * Number of context lines to show around changes
8
+ * @default 3
9
+ */
10
+ contextLines?: number;
11
+ }
12
+ /**
13
+ * Generate and format a unified diff between two code strings
14
+ *
15
+ * @param oldContent - Original content
16
+ * @param newContent - New content
17
+ * @param oldLabel - Label for old version (e.g., "separator@1.0.0")
18
+ * @param newLabel - Label for new version (e.g., "separator@1.1.0")
19
+ * @param options - Diff options
20
+ * @returns Formatted diff string with syntax highlighting
21
+ */
22
+ export declare function formatDiff(oldContent: string, newContent: string, oldLabel: string, newLabel: string, options?: DiffOptions): string;
23
+ /**
24
+ * Apply syntax highlighting to a unified diff
25
+ * Uses chalk for terminal colors
26
+ *
27
+ * @param diffString - Raw unified diff string
28
+ * @returns Colored diff string
29
+ */
30
+ export declare function highlightDiff(diffString: string): string;
31
+ /**
32
+ * Format changelog entries between two versions
33
+ *
34
+ * @param entries - All changelog entries
35
+ * @param fromVersion - Starting version (older)
36
+ * @param toVersion - Ending version (newer)
37
+ * @returns Formatted changelog string
38
+ */
39
+ export declare function formatChangelog(entries: ChangelogEntry[], fromVersion: string, toVersion: string): string;
40
+ /**
41
+ * Format a single changelog entry summary (for compact display)
42
+ *
43
+ * @param entry - Changelog entry
44
+ * @returns Formatted summary string
45
+ */
46
+ export declare function formatChangelogSummary(entry: ChangelogEntry): string;
47
+ //# sourceMappingURL=diff-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/diff-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,MAAM,CAeR;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAwBxD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CA0CR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAWpE"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Utilities for formatting diffs and changelogs for terminal output
3
+ */
4
+ import { createPatch } from "diff";
5
+ import chalk from "chalk";
6
+ /**
7
+ * Generate and format a unified diff between two code strings
8
+ *
9
+ * @param oldContent - Original content
10
+ * @param newContent - New content
11
+ * @param oldLabel - Label for old version (e.g., "separator@1.0.0")
12
+ * @param newLabel - Label for new version (e.g., "separator@1.1.0")
13
+ * @param options - Diff options
14
+ * @returns Formatted diff string with syntax highlighting
15
+ */
16
+ export function formatDiff(oldContent, newContent, oldLabel, newLabel, options = {}) {
17
+ const contextLines = options.contextLines ?? 3;
18
+ // Generate unified diff
19
+ const patch = createPatch(oldLabel, oldContent, newContent, oldLabel, newLabel, { context: contextLines });
20
+ // Apply syntax highlighting
21
+ return highlightDiff(patch);
22
+ }
23
+ /**
24
+ * Apply syntax highlighting to a unified diff
25
+ * Uses chalk for terminal colors
26
+ *
27
+ * @param diffString - Raw unified diff string
28
+ * @returns Colored diff string
29
+ */
30
+ export function highlightDiff(diffString) {
31
+ const lines = diffString.split("\n");
32
+ const coloredLines = [];
33
+ for (const line of lines) {
34
+ if (line.startsWith("---") || line.startsWith("+++")) {
35
+ // File headers
36
+ coloredLines.push(chalk.bold(line));
37
+ }
38
+ else if (line.startsWith("@@")) {
39
+ // Hunk headers (line numbers)
40
+ coloredLines.push(chalk.cyan(line));
41
+ }
42
+ else if (line.startsWith("+")) {
43
+ // Additions
44
+ coloredLines.push(chalk.green(line));
45
+ }
46
+ else if (line.startsWith("-")) {
47
+ // Deletions
48
+ coloredLines.push(chalk.red(line));
49
+ }
50
+ else {
51
+ // Context lines
52
+ coloredLines.push(chalk.gray(line));
53
+ }
54
+ }
55
+ return coloredLines.join("\n");
56
+ }
57
+ /**
58
+ * Format changelog entries between two versions
59
+ *
60
+ * @param entries - All changelog entries
61
+ * @param fromVersion - Starting version (older)
62
+ * @param toVersion - Ending version (newer)
63
+ * @returns Formatted changelog string
64
+ */
65
+ export function formatChangelog(entries, fromVersion, toVersion) {
66
+ // Filter entries between versions
67
+ const relevantEntries = filterEntriesBetweenVersions(entries, fromVersion, toVersion);
68
+ if (relevantEntries.length === 0) {
69
+ return chalk.gray("No changes found between these versions.");
70
+ }
71
+ const output = [];
72
+ for (const entry of relevantEntries) {
73
+ // Version header
74
+ const date = new Date(entry.date).toLocaleDateString("en-US", {
75
+ year: "numeric",
76
+ month: "short",
77
+ day: "numeric",
78
+ });
79
+ let versionLine = chalk.bold(`Version ${entry.version}`) + chalk.gray(` (${date})`);
80
+ if (entry.breaking) {
81
+ versionLine += " " + chalk.red.bold("BREAKING");
82
+ }
83
+ output.push(versionLine);
84
+ // Changes
85
+ for (const change of entry.changes) {
86
+ const icon = getChangeIcon(change.type);
87
+ const color = getChangeColor(change.type);
88
+ output.push(` ${icon} ${color(change.description)}`);
89
+ }
90
+ output.push(""); // Empty line between versions
91
+ }
92
+ return output.join("\n");
93
+ }
94
+ /**
95
+ * Format a single changelog entry summary (for compact display)
96
+ *
97
+ * @param entry - Changelog entry
98
+ * @returns Formatted summary string
99
+ */
100
+ export function formatChangelogSummary(entry) {
101
+ const lines = [];
102
+ for (const change of entry.changes) {
103
+ const icon = getChangeIcon(change.type);
104
+ const label = getChangeLabel(change.type);
105
+ const color = getChangeColor(change.type);
106
+ lines.push(` ${icon} ${color(`${label}: ${change.description}`)}`);
107
+ }
108
+ return lines.join("\n");
109
+ }
110
+ /**
111
+ * Filter changelog entries between two versions
112
+ */
113
+ function filterEntriesBetweenVersions(entries, fromVersion, toVersion) {
114
+ const fromIndex = entries.findIndex((e) => e.version === fromVersion);
115
+ const toIndex = entries.findIndex((e) => e.version === toVersion);
116
+ if (fromIndex === -1 || toIndex === -1) {
117
+ return [];
118
+ }
119
+ // Entries are typically sorted newest first, so we need the range between indices
120
+ const start = Math.min(fromIndex, toIndex);
121
+ const end = Math.max(fromIndex, toIndex);
122
+ return entries.slice(start, end + 1).reverse(); // Reverse to show oldest first
123
+ }
124
+ /**
125
+ * Get icon for change type
126
+ */
127
+ function getChangeIcon(type) {
128
+ switch (type) {
129
+ case "added":
130
+ return "+";
131
+ case "changed":
132
+ return "~";
133
+ case "deprecated":
134
+ return "!";
135
+ case "removed":
136
+ return "-";
137
+ case "fixed":
138
+ return "*";
139
+ case "security":
140
+ return "!";
141
+ default:
142
+ return "•";
143
+ }
144
+ }
145
+ /**
146
+ * Get label for change type
147
+ */
148
+ function getChangeLabel(type) {
149
+ switch (type) {
150
+ case "added":
151
+ return "Added";
152
+ case "changed":
153
+ return "Changed";
154
+ case "deprecated":
155
+ return "Deprecated";
156
+ case "removed":
157
+ return "Removed";
158
+ case "fixed":
159
+ return "Fixed";
160
+ case "security":
161
+ return "Security";
162
+ default:
163
+ return "Changed";
164
+ }
165
+ }
166
+ /**
167
+ * Get color function for change type
168
+ */
169
+ function getChangeColor(type) {
170
+ switch (type) {
171
+ case "added":
172
+ return chalk.green;
173
+ case "changed":
174
+ return chalk.blue;
175
+ case "deprecated":
176
+ return chalk.yellow;
177
+ case "removed":
178
+ return chalk.red;
179
+ case "fixed":
180
+ return chalk.cyan;
181
+ case "security":
182
+ return chalk.magenta;
183
+ default:
184
+ return chalk.white;
185
+ }
186
+ }
@@ -0,0 +1,7 @@
1
+ export declare function fileExists(filePath: string): Promise<boolean>;
2
+ export declare function readJsonFile<T>(filePath: string): Promise<T | null>;
3
+ export declare function writeJsonFile(filePath: string, data: unknown): Promise<void>;
4
+ export declare function copyFile(source: string, destination: string): Promise<void>;
5
+ export declare function ensureDir(dirPath: string): Promise<void>;
6
+ export declare function readDir(dirPath: string): Promise<string[]>;
7
+ //# sourceMappingURL=file-operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-operations.d.ts","sourceRoot":"","sources":["../../src/utils/file-operations.ts"],"names":[],"mappings":"AAEA,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAOzE;AAED,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAMhE"}
@@ -0,0 +1,37 @@
1
+ import fs from "fs/promises";
2
+ export async function fileExists(filePath) {
3
+ try {
4
+ await fs.access(filePath);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ export async function readJsonFile(filePath) {
12
+ try {
13
+ const content = await fs.readFile(filePath, "utf-8");
14
+ return JSON.parse(content);
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ export async function writeJsonFile(filePath, data) {
21
+ const content = JSON.stringify(data, null, 2);
22
+ await fs.writeFile(filePath, content, "utf-8");
23
+ }
24
+ export async function copyFile(source, destination) {
25
+ await fs.copyFile(source, destination);
26
+ }
27
+ export async function ensureDir(dirPath) {
28
+ await fs.mkdir(dirPath, { recursive: true });
29
+ }
30
+ export async function readDir(dirPath) {
31
+ try {
32
+ return await fs.readdir(dirPath);
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Lock file management utilities
3
+ * Handles reading, writing, and updating voidui.lock.json
4
+ */
5
+ import type { LockFile, ComponentLockEntry } from "../types/lock-file.js";
6
+ /**
7
+ * Read existing lock file or return null if not found
8
+ *
9
+ * @param cwd - Current working directory
10
+ * @returns Lock file or null
11
+ */
12
+ export declare function readLockFile(cwd: string): Promise<LockFile | null>;
13
+ /**
14
+ * Read lock file or create a new empty one if it doesn't exist
15
+ *
16
+ * @param cwd - Current working directory
17
+ * @returns Lock file
18
+ */
19
+ export declare function readOrCreateLockFile(cwd: string): Promise<LockFile>;
20
+ /**
21
+ * Write lock file to disk
22
+ *
23
+ * @param cwd - Current working directory
24
+ * @param lockFile - Lock file to write
25
+ */
26
+ export declare function writeLockFile(cwd: string, lockFile: LockFile): Promise<void>;
27
+ /**
28
+ * Update a component entry in the lock file
29
+ *
30
+ * @param lockFile - Lock file to update
31
+ * @param componentName - Component name
32
+ * @param entry - Component entry data
33
+ * @returns Updated lock file
34
+ */
35
+ export declare function updateComponentEntry(lockFile: LockFile, componentName: string, entry: ComponentLockEntry): LockFile;
36
+ /**
37
+ * Remove a component entry from the lock file
38
+ *
39
+ * @param lockFile - Lock file to update
40
+ * @param componentName - Component name to remove
41
+ * @returns Updated lock file
42
+ */
43
+ export declare function removeComponentEntry(lockFile: LockFile, componentName: string): LockFile;
44
+ /**
45
+ * Check if a component is tracked in the lock file
46
+ *
47
+ * @param lockFile - Lock file
48
+ * @param componentName - Component name
49
+ * @returns True if component is tracked
50
+ */
51
+ export declare function isComponentTracked(lockFile: LockFile, componentName: string): boolean;
52
+ /**
53
+ * Get component entry from lock file
54
+ *
55
+ * @param lockFile - Lock file
56
+ * @param componentName - Component name
57
+ * @returns Component entry or null
58
+ */
59
+ export declare function getComponentEntry(lockFile: LockFile, componentName: string): ComponentLockEntry | null;
60
+ //# sourceMappingURL=lock-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock-file.d.ts","sourceRoot":"","sources":["../../src/utils/lock-file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAM1E;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAqBxE;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAYzE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,kBAAkB,GACxB,QAAQ,CAQV;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,GACpB,QAAQ,CAOV;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,GACpB,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,GACpB,kBAAkB,GAAG,IAAI,CAE3B"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Lock file management utilities
3
+ * Handles reading, writing, and updating voidui.lock.json
4
+ */
5
+ import path from "path";
6
+ import { lockFileSchema } from "../validators/lock-file.js";
7
+ import { fileExists, readJsonFile, writeJsonFile } from "./file-operations.js";
8
+ const LOCK_FILE_NAME = "voidui.lock.json";
9
+ const LOCK_FILE_VERSION = "1.0";
10
+ /**
11
+ * Read existing lock file or return null if not found
12
+ *
13
+ * @param cwd - Current working directory
14
+ * @returns Lock file or null
15
+ */
16
+ export async function readLockFile(cwd) {
17
+ const lockFilePath = path.join(cwd, LOCK_FILE_NAME);
18
+ if (!(await fileExists(lockFilePath))) {
19
+ return null;
20
+ }
21
+ const rawLockFile = await readJsonFile(lockFilePath);
22
+ if (!rawLockFile) {
23
+ return null;
24
+ }
25
+ try {
26
+ const lockFile = lockFileSchema.parse(rawLockFile);
27
+ return lockFile;
28
+ }
29
+ catch (error) {
30
+ throw new Error(`Lock file is corrupted. Please delete ${LOCK_FILE_NAME} and re-install components.`);
31
+ }
32
+ }
33
+ /**
34
+ * Read lock file or create a new empty one if it doesn't exist
35
+ *
36
+ * @param cwd - Current working directory
37
+ * @returns Lock file
38
+ */
39
+ export async function readOrCreateLockFile(cwd) {
40
+ const existing = await readLockFile(cwd);
41
+ if (existing) {
42
+ return existing;
43
+ }
44
+ // Create new lock file structure
45
+ return {
46
+ version: LOCK_FILE_VERSION,
47
+ components: {},
48
+ };
49
+ }
50
+ /**
51
+ * Write lock file to disk
52
+ *
53
+ * @param cwd - Current working directory
54
+ * @param lockFile - Lock file to write
55
+ */
56
+ export async function writeLockFile(cwd, lockFile) {
57
+ const lockFilePath = path.join(cwd, LOCK_FILE_NAME);
58
+ await writeJsonFile(lockFilePath, lockFile);
59
+ }
60
+ /**
61
+ * Update a component entry in the lock file
62
+ *
63
+ * @param lockFile - Lock file to update
64
+ * @param componentName - Component name
65
+ * @param entry - Component entry data
66
+ * @returns Updated lock file
67
+ */
68
+ export function updateComponentEntry(lockFile, componentName, entry) {
69
+ return {
70
+ ...lockFile,
71
+ components: {
72
+ ...lockFile.components,
73
+ [componentName]: entry,
74
+ },
75
+ };
76
+ }
77
+ /**
78
+ * Remove a component entry from the lock file
79
+ *
80
+ * @param lockFile - Lock file to update
81
+ * @param componentName - Component name to remove
82
+ * @returns Updated lock file
83
+ */
84
+ export function removeComponentEntry(lockFile, componentName) {
85
+ const { [componentName]: _, ...remainingComponents } = lockFile.components;
86
+ return {
87
+ ...lockFile,
88
+ components: remainingComponents,
89
+ };
90
+ }
91
+ /**
92
+ * Check if a component is tracked in the lock file
93
+ *
94
+ * @param lockFile - Lock file
95
+ * @param componentName - Component name
96
+ * @returns True if component is tracked
97
+ */
98
+ export function isComponentTracked(lockFile, componentName) {
99
+ return componentName in lockFile.components;
100
+ }
101
+ /**
102
+ * Get component entry from lock file
103
+ *
104
+ * @param lockFile - Lock file
105
+ * @param componentName - Component name
106
+ * @returns Component entry or null
107
+ */
108
+ export function getComponentEntry(lockFile, componentName) {
109
+ return lockFile.components[componentName] || null;
110
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * 3-way merge utilities for component updates
3
+ * Handles merging local changes with upstream updates
4
+ */
5
+ export interface MergeResult {
6
+ /**
7
+ * Whether the merge was successful (no conflicts)
8
+ */
9
+ success: boolean;
10
+ /**
11
+ * Merged content (may contain conflict markers if !success)
12
+ */
13
+ content: string;
14
+ /**
15
+ * Number of conflicts found
16
+ */
17
+ conflictCount: number;
18
+ }
19
+ /**
20
+ * Perform a 3-way merge of component files
21
+ *
22
+ * @param base - Original version (what was installed)
23
+ * @param ours - Current local version (potentially modified)
24
+ * @param theirs - New version from registry
25
+ * @param labels - Optional labels for conflict markers
26
+ * @returns Merge result
27
+ */
28
+ export declare function threeWayMerge(base: string, ours: string, theirs: string, labels?: {
29
+ ours?: string;
30
+ theirs?: string;
31
+ }): MergeResult;
32
+ /**
33
+ * Check if content contains merge conflict markers
34
+ *
35
+ * @param content - File content to check
36
+ * @returns True if conflict markers are present
37
+ */
38
+ export declare function hasConflictMarkers(content: string): boolean;
39
+ /**
40
+ * Count the number of conflict regions in content
41
+ *
42
+ * @param content - File content
43
+ * @returns Number of conflict regions
44
+ */
45
+ export declare function countConflicts(content: string): number;
46
+ /**
47
+ * Generate a user-friendly message for merge results
48
+ *
49
+ * @param result - Merge result
50
+ * @param componentPath - Path to component file
51
+ * @returns Formatted message
52
+ */
53
+ export declare function formatMergeMessage(result: MergeResult, componentPath: string): string;
54
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE;IACP,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,WAAW,CAoCb;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,MAAM,GACpB,MAAM,CAeR"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 3-way merge utilities for component updates
3
+ * Handles merging local changes with upstream updates
4
+ */
5
+ import { diff3Merge } from "node-diff3";
6
+ /**
7
+ * Perform a 3-way merge of component files
8
+ *
9
+ * @param base - Original version (what was installed)
10
+ * @param ours - Current local version (potentially modified)
11
+ * @param theirs - New version from registry
12
+ * @param labels - Optional labels for conflict markers
13
+ * @returns Merge result
14
+ */
15
+ export function threeWayMerge(base, ours, theirs, labels) {
16
+ // Split content into lines for diff3
17
+ const baseLines = base.split("\n");
18
+ const oursLines = ours.split("\n");
19
+ const theirsLines = theirs.split("\n");
20
+ // Perform 3-way merge
21
+ const mergeResults = diff3Merge(oursLines, baseLines, theirsLines);
22
+ let conflictCount = 0;
23
+ const mergedLines = [];
24
+ for (const result of mergeResults) {
25
+ if (result.ok) {
26
+ // No conflict, use the merged result
27
+ mergedLines.push(...result.ok);
28
+ }
29
+ else if (result.conflict) {
30
+ // Conflict detected
31
+ conflictCount++;
32
+ // Add conflict markers
33
+ mergedLines.push(`<<<<<<< ${labels?.ours || "ours (your changes)"}`, ...result.conflict.a, "=======", ...result.conflict.b, `>>>>>>> ${labels?.theirs || "theirs (upstream)"}`);
34
+ }
35
+ }
36
+ return {
37
+ success: conflictCount === 0,
38
+ content: mergedLines.join("\n"),
39
+ conflictCount,
40
+ };
41
+ }
42
+ /**
43
+ * Check if content contains merge conflict markers
44
+ *
45
+ * @param content - File content to check
46
+ * @returns True if conflict markers are present
47
+ */
48
+ export function hasConflictMarkers(content) {
49
+ return (content.includes("<<<<<<<") &&
50
+ content.includes("=======") &&
51
+ content.includes(">>>>>>>"));
52
+ }
53
+ /**
54
+ * Count the number of conflict regions in content
55
+ *
56
+ * @param content - File content
57
+ * @returns Number of conflict regions
58
+ */
59
+ export function countConflicts(content) {
60
+ const matches = content.match(/<<<<<<</g);
61
+ return matches ? matches.length : 0;
62
+ }
63
+ /**
64
+ * Generate a user-friendly message for merge results
65
+ *
66
+ * @param result - Merge result
67
+ * @param componentPath - Path to component file
68
+ * @returns Formatted message
69
+ */
70
+ export function formatMergeMessage(result, componentPath) {
71
+ if (result.success) {
72
+ return `✓ Successfully merged your changes with the latest version`;
73
+ }
74
+ return `⚠️ Merge completed with ${result.conflictCount} conflict${result.conflictCount > 1 ? "s" : ""}
75
+
76
+ Conflict markers have been added to: ${componentPath}
77
+
78
+ To resolve:
79
+ 1. Open the file and search for "<<<<<<<"
80
+ 2. Edit each conflict region to keep the code you want
81
+ 3. Remove the conflict markers (<<<<<<<, =======, >>>>>>>)
82
+ 4. Save the file
83
+ 5. Run: voidui add ${componentPath.split("/").pop()?.replace(".tsx", "")} --force`;
84
+ }
@@ -0,0 +1,8 @@
1
+ import type { ChangeType } from "../types/changelog.js";
2
+ export declare function promptForChange(): Promise<{
3
+ type: ChangeType;
4
+ description: string;
5
+ } | null>;
6
+ export declare function promptForMore(message: string): Promise<boolean>;
7
+ export declare function promptForBreaking(): Promise<boolean>;
8
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,IAAI,EAAE,UAAU,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,IAAI,CAAC,CAgCR;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASrE;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS1D"}
@@ -0,0 +1,49 @@
1
+ import prompts from "prompts";
2
+ export async function promptForChange() {
3
+ const response = await prompts([
4
+ {
5
+ type: "select",
6
+ name: "type",
7
+ message: "Change type:",
8
+ choices: [
9
+ { title: "✨ Added", value: "added" },
10
+ { title: "🔄 Changed", value: "changed" },
11
+ { title: "⚠️ Deprecated", value: "deprecated" },
12
+ { title: "🗑️ Removed", value: "removed" },
13
+ { title: "🐛 Fixed", value: "fixed" },
14
+ { title: "🔒 Security", value: "security" },
15
+ ],
16
+ },
17
+ {
18
+ type: "text",
19
+ name: "description",
20
+ message: "Change description:",
21
+ validate: (value) => value.length > 0 ? true : "Description cannot be empty",
22
+ },
23
+ ]);
24
+ if (!response.type || !response.description) {
25
+ return null;
26
+ }
27
+ return {
28
+ type: response.type,
29
+ description: response.description,
30
+ };
31
+ }
32
+ export async function promptForMore(message) {
33
+ const response = await prompts({
34
+ type: "confirm",
35
+ name: "more",
36
+ message,
37
+ initial: false,
38
+ });
39
+ return response.more ?? false;
40
+ }
41
+ export async function promptForBreaking() {
42
+ const response = await prompts({
43
+ type: "confirm",
44
+ name: "breaking",
45
+ message: "Is this a breaking change?",
46
+ initial: false,
47
+ });
48
+ return response.breaking ?? false;
49
+ }