trix-ui 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/contracts/registry.test.d.ts +1 -0
- package/dist/__tests__/contracts/registry.test.js +42 -0
- package/dist/__tests__/contracts/registry.test.js.map +1 -0
- package/dist/__tests__/e2e/cli.test.d.ts +1 -0
- package/dist/__tests__/e2e/cli.test.js +67 -0
- package/dist/__tests__/e2e/cli.test.js.map +1 -0
- package/dist/__tests__/helpers/fs.d.ts +5 -0
- package/dist/__tests__/helpers/fs.js +26 -0
- package/dist/__tests__/helpers/fs.js.map +1 -0
- package/dist/__tests__/integration/commands.integration.test.d.ts +1 -0
- package/dist/__tests__/integration/commands.integration.test.js +184 -0
- package/dist/__tests__/integration/commands.integration.test.js.map +1 -0
- package/dist/commands/__tests__/add-composite.test.d.ts +2 -0
- package/dist/commands/__tests__/add-composite.test.js +171 -0
- package/dist/commands/__tests__/add-composite.test.js.map +1 -0
- package/dist/commands/__tests__/add-entry.mocks.d.ts +23 -0
- package/dist/commands/__tests__/add-entry.mocks.js +64 -0
- package/dist/commands/__tests__/add-entry.mocks.js.map +1 -0
- package/dist/commands/__tests__/add-section.test.d.ts +2 -0
- package/dist/commands/__tests__/add-section.test.js +191 -0
- package/dist/commands/__tests__/add-section.test.js.map +1 -0
- package/dist/commands/__tests__/add-wrapper.test.d.ts +2 -0
- package/dist/commands/__tests__/add-wrapper.test.js +171 -0
- package/dist/commands/__tests__/add-wrapper.test.js.map +1 -0
- package/dist/commands/__tests__/cli-mocks.d.ts +1 -0
- package/dist/commands/__tests__/cli-mocks.js +24 -0
- package/dist/commands/__tests__/cli-mocks.js.map +1 -0
- package/dist/commands/__tests__/doctor.mocks.d.ts +6 -0
- package/dist/commands/__tests__/doctor.mocks.js +20 -0
- package/dist/commands/__tests__/doctor.mocks.js.map +1 -0
- package/dist/commands/__tests__/doctor.test.d.ts +2 -0
- package/dist/commands/__tests__/doctor.test.js +80 -0
- package/dist/commands/__tests__/doctor.test.js.map +1 -0
- package/dist/commands/__tests__/list.mocks.d.ts +8 -0
- package/dist/commands/__tests__/list.mocks.js +20 -0
- package/dist/commands/__tests__/list.mocks.js.map +1 -0
- package/dist/commands/__tests__/list.test.d.ts +2 -0
- package/dist/commands/__tests__/list.test.js +60 -0
- package/dist/commands/__tests__/list.test.js.map +1 -0
- package/dist/commands/__tests__/remove.mocks.d.ts +9 -0
- package/dist/commands/__tests__/remove.mocks.js +26 -0
- package/dist/commands/__tests__/remove.mocks.js.map +1 -0
- package/dist/commands/__tests__/remove.test.d.ts +2 -0
- package/dist/commands/__tests__/remove.test.js +116 -0
- package/dist/commands/__tests__/remove.test.js.map +1 -0
- package/dist/commands/add/__tests__/add.mocks.d.ts +19 -19
- package/dist/commands/add/__tests__/add.mocks.js +59 -59
- package/dist/commands/add/__tests__/add.test.d.ts +2 -2
- package/dist/commands/add/__tests__/add.test.js +140 -140
- package/dist/commands/add/analysis.d.ts +4 -4
- package/dist/commands/add/analysis.js +56 -56
- package/dist/commands/add/command.d.ts +2 -2
- package/dist/commands/add/command.js +202 -202
- package/dist/commands/add/config.d.ts +2 -2
- package/dist/commands/add/config.js +11 -11
- package/dist/commands/add/install.d.ts +27 -27
- package/dist/commands/add/install.js +80 -80
- package/dist/commands/add/package-manager.d.ts +1 -1
- package/dist/commands/add/package-manager.js +4 -4
- package/dist/commands/add/project-files.d.ts +2 -2
- package/dist/commands/add/project-files.js +17 -17
- package/dist/commands/add/prompts.d.ts +3 -3
- package/dist/commands/add/prompts.js +28 -28
- package/dist/commands/add/registry.d.ts +4 -4
- package/dist/commands/add/registry.js +6 -6
- package/dist/commands/add/types.d.ts +33 -33
- package/dist/commands/add/types.js +1 -1
- package/dist/commands/add/ui.d.ts +4 -4
- package/dist/commands/add/ui.js +55 -55
- package/dist/commands/add/validation.d.ts +3 -3
- package/dist/commands/add/validation.js +30 -30
- package/dist/commands/add-collection.d.ts +1 -1
- package/dist/commands/add-collection.js +1 -1
- package/dist/commands/add-composite.d.ts +2 -2
- package/dist/commands/add-composite.js +201 -201
- package/dist/commands/add-section.d.ts +2 -2
- package/dist/commands/add-section.js +201 -201
- package/dist/commands/add-wrapper.d.ts +2 -2
- package/dist/commands/add-wrapper.js +201 -201
- package/dist/commands/add.d.ts +1 -1
- package/dist/commands/add.js +1 -1
- package/dist/commands/build.d.ts +2 -2
- package/dist/commands/doctor.d.ts +2 -2
- package/dist/commands/doctor.js +67 -67
- package/dist/commands/init/__tests__/init.mocks.d.ts +24 -0
- package/dist/commands/init/__tests__/init.mocks.js +84 -0
- package/dist/commands/init/__tests__/init.mocks.js.map +1 -0
- package/dist/commands/init/__tests__/init.test.d.ts +2 -0
- package/dist/commands/init/__tests__/init.test.js +283 -0
- package/dist/commands/init/__tests__/init.test.js.map +1 -0
- package/dist/commands/init/__tests__/tailwind.test.d.ts +1 -0
- package/dist/commands/init/__tests__/tailwind.test.js +56 -0
- package/dist/commands/init/__tests__/tailwind.test.js.map +1 -0
- package/dist/commands/init/__tests__/tsconfig.test.d.ts +1 -0
- package/dist/commands/init/__tests__/tsconfig.test.js +108 -0
- package/dist/commands/init/__tests__/tsconfig.test.js.map +1 -0
- package/dist/commands/init/__tests__/vite.test.d.ts +1 -0
- package/dist/commands/init/__tests__/vite.test.js +66 -0
- package/dist/commands/init/__tests__/vite.test.js.map +1 -0
- package/dist/commands/init/command.d.ts +2 -2
- package/dist/commands/init/command.js +114 -114
- package/dist/commands/init/config.d.ts +2 -2
- package/dist/commands/init/config.js +25 -25
- package/dist/commands/init/constants.d.ts +3 -3
- package/dist/commands/init/constants.js +105 -105
- package/dist/commands/init/dependencies.d.ts +5 -5
- package/dist/commands/init/dependencies.js +52 -52
- package/dist/commands/init/filesystem.d.ts +1 -1
- package/dist/commands/init/filesystem.js +10 -10
- package/dist/commands/init/lockfile.d.ts +1 -1
- package/dist/commands/init/lockfile.js +1 -1
- package/dist/commands/init/package-json.d.ts +6 -6
- package/dist/commands/init/package-json.js +18 -18
- package/dist/commands/init/project-files.d.ts +8 -0
- package/dist/commands/init/project-files.js +37 -0
- package/dist/commands/init/project-files.js.map +1 -0
- package/dist/commands/init/project.d.ts +3 -3
- package/dist/commands/init/project.js +97 -97
- package/dist/commands/init/style-imports.d.ts +9 -0
- package/dist/commands/init/style-imports.js +218 -0
- package/dist/commands/init/style-imports.js.map +1 -0
- package/dist/commands/init/tailwind.d.ts +3 -3
- package/dist/commands/init/tailwind.js +34 -34
- package/dist/commands/init/templates.d.ts +3 -3
- package/dist/commands/init/templates.js +15 -15
- package/dist/commands/init/tsconfig.d.ts +2 -2
- package/dist/commands/init/tsconfig.js +273 -273
- package/dist/commands/init/types.d.ts +33 -33
- package/dist/commands/init/types.js +1 -1
- package/dist/commands/init/ui.d.ts +3 -3
- package/dist/commands/init/ui.js +33 -33
- package/dist/commands/init/vite.d.ts +23 -0
- package/dist/commands/init/vite.js +347 -0
- package/dist/commands/init/vite.js.map +1 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/list.d.ts +2 -2
- package/dist/commands/list.js +62 -62
- package/dist/commands/remove.d.ts +2 -2
- package/dist/commands/remove.js +93 -93
- package/dist/commands/shared/add-collection.d.ts +50 -50
- package/dist/commands/shared/add-collection.js +206 -206
- package/dist/commands/shared/list-entries.d.ts +6 -6
- package/dist/commands/shared/list-entries.js +12 -12
- package/dist/commands/shared/name-utils.d.ts +1 -1
- package/dist/commands/shared/name-utils.js +13 -13
- package/dist/commands/shared/remove-entries.d.ts +16 -16
- package/dist/commands/shared/remove-entries.js +41 -41
- package/dist/icons/index.d.ts +1 -1
- package/dist/icons/index.js +1 -1
- package/dist/icons/libraries.d.ts +37 -37
- package/dist/icons/libraries.js +34 -34
- package/dist/index.d.ts +2 -2
- package/dist/index.js +30 -30
- package/dist/lib/__tests__/config.test.d.ts +1 -0
- package/dist/lib/__tests__/config.test.js +49 -0
- package/dist/lib/__tests__/config.test.js.map +1 -0
- package/dist/lib/__tests__/install.test.d.ts +1 -0
- package/dist/lib/__tests__/install.test.js +149 -0
- package/dist/lib/__tests__/install.test.js.map +1 -0
- package/dist/lib/__tests__/lockfile.test.d.ts +1 -0
- package/dist/lib/__tests__/lockfile.test.js +89 -0
- package/dist/lib/__tests__/lockfile.test.js.map +1 -0
- package/dist/lib/__tests__/paths.test.d.ts +1 -0
- package/dist/lib/__tests__/paths.test.js +39 -0
- package/dist/lib/__tests__/paths.test.js.map +1 -0
- package/dist/lib/__tests__/registry.test.d.ts +1 -0
- package/dist/lib/__tests__/registry.test.js +76 -0
- package/dist/lib/__tests__/registry.test.js.map +1 -0
- package/dist/lib/config.d.ts +45 -45
- package/dist/lib/config.js +97 -97
- package/dist/lib/fs.d.ts +76 -76
- package/dist/lib/fs.js +302 -302
- package/dist/lib/highlighter.d.ts +6 -6
- package/dist/lib/highlighter.js +7 -7
- package/dist/lib/install.d.ts +19 -19
- package/dist/lib/install.js +55 -55
- package/dist/lib/lockfile.d.ts +63 -63
- package/dist/lib/lockfile.js +173 -173
- package/dist/lib/logger.d.ts +8 -8
- package/dist/lib/logger.js +41 -41
- package/dist/lib/paths.d.ts +14 -14
- package/dist/lib/paths.js +31 -31
- package/dist/lib/registry.d.ts +35 -35
- package/dist/lib/registry.js +180 -180
- package/dist/schema/index.d.ts +1128 -1128
- package/dist/schema/index.js +238 -238
- package/dist/styles/create-style-map.d.ts +4 -4
- package/dist/styles/create-style-map.js +68 -68
- package/dist/styles/transform-style-map.d.ts +3 -3
- package/dist/styles/transform-style-map.js +428 -428
- package/dist/styles/transform.d.ts +10 -10
- package/dist/styles/transform.js +15 -15
- package/dist/utils/index.d.ts +6 -6
- package/dist/utils/index.js +5 -5
- package/dist/utils/transformers/transform-icons.d.ts +2 -2
- package/dist/utils/transformers/transform-icons.js +164 -164
- package/dist/utils/transformers/transform-menu.d.ts +2 -2
- package/dist/utils/transformers/transform-menu.js +39 -39
- package/dist/utils/transformers/transform-render.d.ts +2 -2
- package/dist/utils/transformers/transform-render.js +97 -97
- package/dist/utils/transformers/types.d.ts +14 -14
- package/dist/utils/transformers/types.js +1 -1
- package/package.json +1 -1
package/dist/lib/fs.js
CHANGED
|
@@ -1,303 +1,303 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { logger } from "./logger.js";
|
|
4
|
-
/**
|
|
5
|
-
* Check if a file exists
|
|
6
|
-
*/
|
|
7
|
-
export async function fileExists(filePath) {
|
|
8
|
-
try {
|
|
9
|
-
await fs.access(filePath, fs.constants.F_OK);
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Check if a directory exists
|
|
18
|
-
*/
|
|
19
|
-
export async function directoryExists(dirPath) {
|
|
20
|
-
try {
|
|
21
|
-
const stat = await fs.stat(dirPath);
|
|
22
|
-
return stat.isDirectory();
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Ensure a directory exists, create if it doesn't
|
|
30
|
-
*/
|
|
31
|
-
export async function ensureDir(dirPath) {
|
|
32
|
-
try {
|
|
33
|
-
await fs.mkdir(dirPath, { recursive: true });
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
throw new Error(`Failed to create directory ${dirPath}: ${error.message}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Read a file as a string with proper encoding and BOM handling
|
|
41
|
-
*/
|
|
42
|
-
export async function readFile(filePath) {
|
|
43
|
-
try {
|
|
44
|
-
// Check if file exists first
|
|
45
|
-
if (!(await fileExists(filePath))) {
|
|
46
|
-
throw new Error(`File not found: ${filePath}`);
|
|
47
|
-
}
|
|
48
|
-
// Read with explicit UTF-8 encoding
|
|
49
|
-
let content = await fs.readFile(filePath, { encoding: "utf-8" });
|
|
50
|
-
// Remove BOM if present (UTF-8 BOM is EF BB BF)
|
|
51
|
-
if (content.charCodeAt(0) === 0xfeff) {
|
|
52
|
-
content = content.slice(1);
|
|
53
|
-
}
|
|
54
|
-
// Trim whitespace that might cause JSON parsing issues
|
|
55
|
-
content = content.trim();
|
|
56
|
-
// Check if file is empty
|
|
57
|
-
if (content.length === 0) {
|
|
58
|
-
throw new Error(`File is empty: ${filePath}`);
|
|
59
|
-
}
|
|
60
|
-
return content;
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
if (error instanceof Error) {
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
throw new Error(`Failed to read file ${filePath}: ${error}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Read and parse a JSON file with comprehensive error handling
|
|
71
|
-
*/
|
|
72
|
-
export async function readJsonFile(filePath) {
|
|
73
|
-
try {
|
|
74
|
-
const content = await readFile(filePath);
|
|
75
|
-
// Attempt to parse JSON
|
|
76
|
-
try {
|
|
77
|
-
const parsed = JSON.parse(content);
|
|
78
|
-
return parsed;
|
|
79
|
-
}
|
|
80
|
-
catch (parseError) {
|
|
81
|
-
// Provide helpful error message with context
|
|
82
|
-
const errorMessage = parseError.message;
|
|
83
|
-
const preview = content.substring(0, 100);
|
|
84
|
-
throw new Error(`Invalid JSON in ${path.basename(filePath)}: ${errorMessage}\n` +
|
|
85
|
-
`Preview: ${preview}${content.length > 100 ? "..." : ""}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
throw error;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Write content to a file
|
|
94
|
-
*/
|
|
95
|
-
export async function writeFile(filePath, content) {
|
|
96
|
-
try {
|
|
97
|
-
// Ensure parent directory exists
|
|
98
|
-
const dir = path.dirname(filePath);
|
|
99
|
-
await ensureDir(dir);
|
|
100
|
-
// Write with UTF-8 encoding, no BOM
|
|
101
|
-
await fs.writeFile(filePath, content, { encoding: "utf-8" });
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
throw new Error(`Failed to write file ${filePath}: ${error.message}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Write content to a file only if it doesn't exist or force is true
|
|
109
|
-
*/
|
|
110
|
-
export async function writeFileSafe(filePath, content, force = false) {
|
|
111
|
-
try {
|
|
112
|
-
const exists = await fileExists(filePath);
|
|
113
|
-
if (exists && !force) {
|
|
114
|
-
logger.warn(`File already exists, skipping: ${filePath}`);
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
await writeFile(filePath, content);
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
throw new Error(`Failed to write file ${filePath}: ${error.message}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Write JSON to a file with pretty formatting
|
|
126
|
-
*/
|
|
127
|
-
export async function writeJsonFile(filePath, data, force = false) {
|
|
128
|
-
try {
|
|
129
|
-
const exists = await fileExists(filePath);
|
|
130
|
-
if (exists && !force) {
|
|
131
|
-
throw new Error(`File already exists: ${filePath}. Use --force to overwrite.`);
|
|
132
|
-
}
|
|
133
|
-
const content = JSON.stringify(data, null, 2) + "\n";
|
|
134
|
-
await writeFile(filePath, content);
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
if (error instanceof Error) {
|
|
138
|
-
throw error;
|
|
139
|
-
}
|
|
140
|
-
throw new Error(`Failed to write JSON file ${filePath}: ${error}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Copy a file from source to destination
|
|
145
|
-
*/
|
|
146
|
-
export async function copyFile(src, dest) {
|
|
147
|
-
try {
|
|
148
|
-
if (!(await fileExists(src))) {
|
|
149
|
-
throw new Error(`Source file not found: ${src}`);
|
|
150
|
-
}
|
|
151
|
-
// Ensure destination directory exists
|
|
152
|
-
const destDir = path.dirname(dest);
|
|
153
|
-
await ensureDir(destDir);
|
|
154
|
-
await fs.copyFile(src, dest);
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
throw new Error(`Failed to copy file from ${src} to ${dest}: ${error.message}`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Copy a file only if destination doesn't exist or force is true
|
|
162
|
-
*/
|
|
163
|
-
export async function copyFileSafe(src, dest, force = false) {
|
|
164
|
-
try {
|
|
165
|
-
const exists = await fileExists(dest);
|
|
166
|
-
if (exists && !force) {
|
|
167
|
-
logger.warn(`File already exists, skipping: ${dest}`);
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
await copyFile(src, dest);
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
throw new Error(`Failed to copy file from ${src} to ${dest}: ${error.message}`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Delete a file
|
|
179
|
-
*/
|
|
180
|
-
export async function deleteFile(filePath) {
|
|
181
|
-
try {
|
|
182
|
-
if (await fileExists(filePath)) {
|
|
183
|
-
await fs.unlink(filePath);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
catch (error) {
|
|
187
|
-
throw new Error(`Failed to delete file ${filePath}: ${error.message}`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Delete a directory recursively
|
|
192
|
-
*/
|
|
193
|
-
export async function deleteDirectory(dirPath) {
|
|
194
|
-
try {
|
|
195
|
-
if (await directoryExists(dirPath)) {
|
|
196
|
-
await fs.rm(dirPath, { recursive: true, force: true });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
throw new Error(`Failed to delete directory ${dirPath}: ${error.message}`);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* List files in a directory
|
|
205
|
-
*/
|
|
206
|
-
export async function listFiles(dirPath, options) {
|
|
207
|
-
try {
|
|
208
|
-
if (!(await directoryExists(dirPath))) {
|
|
209
|
-
return [];
|
|
210
|
-
}
|
|
211
|
-
const files = [];
|
|
212
|
-
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
213
|
-
for (const entry of entries) {
|
|
214
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
215
|
-
if (entry.isDirectory() && options?.recursive) {
|
|
216
|
-
const subFiles = await listFiles(fullPath, options);
|
|
217
|
-
files.push(...subFiles);
|
|
218
|
-
}
|
|
219
|
-
else if (entry.isFile()) {
|
|
220
|
-
if (options?.extension) {
|
|
221
|
-
if (entry.name.endsWith(options.extension)) {
|
|
222
|
-
files.push(fullPath);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
files.push(fullPath);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return files;
|
|
231
|
-
}
|
|
232
|
-
catch (error) {
|
|
233
|
-
throw new Error(`Failed to list files in ${dirPath}: ${error.message}`);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Get file stats
|
|
238
|
-
*/
|
|
239
|
-
export async function getFileStats(filePath) {
|
|
240
|
-
try {
|
|
241
|
-
return await fs.stat(filePath);
|
|
242
|
-
}
|
|
243
|
-
catch {
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Check if path is a file
|
|
249
|
-
*/
|
|
250
|
-
export async function isFile(filePath) {
|
|
251
|
-
try {
|
|
252
|
-
const stat = await fs.stat(filePath);
|
|
253
|
-
return stat.isFile();
|
|
254
|
-
}
|
|
255
|
-
catch {
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Check if path is a directory
|
|
261
|
-
*/
|
|
262
|
-
export async function isDirectory(dirPath) {
|
|
263
|
-
return directoryExists(dirPath);
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Read package.json with validation
|
|
267
|
-
*/
|
|
268
|
-
export async function readPackageJson(cwd) {
|
|
269
|
-
const packageJsonPath = path.join(cwd, "package.json");
|
|
270
|
-
try {
|
|
271
|
-
const packageJson = await readJsonFile(packageJsonPath);
|
|
272
|
-
// Validate it's actually a package.json
|
|
273
|
-
if (!packageJson.name) {
|
|
274
|
-
throw new Error("Invalid package.json: missing 'name' field");
|
|
275
|
-
}
|
|
276
|
-
return packageJson;
|
|
277
|
-
}
|
|
278
|
-
catch (error) {
|
|
279
|
-
if (error instanceof Error) {
|
|
280
|
-
throw new Error(`Failed to read package.json: ${error.message}`);
|
|
281
|
-
}
|
|
282
|
-
throw error;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Update package.json dependencies
|
|
287
|
-
*/
|
|
288
|
-
export async function updatePackageJsonDependencies(cwd, dependencies, dev = false) {
|
|
289
|
-
try {
|
|
290
|
-
const packageJson = await readPackageJson(cwd);
|
|
291
|
-
const depKey = dev ? "devDependencies" : "dependencies";
|
|
292
|
-
packageJson[depKey] = {
|
|
293
|
-
...packageJson[depKey],
|
|
294
|
-
...dependencies,
|
|
295
|
-
};
|
|
296
|
-
const packageJsonPath = path.join(cwd, "package.json");
|
|
297
|
-
await writeJsonFile(packageJsonPath, packageJson, true);
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
throw new Error(`Failed to update package.json: ${error.message}`);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* Check if a file exists
|
|
6
|
+
*/
|
|
7
|
+
export async function fileExists(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
await fs.access(filePath, fs.constants.F_OK);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if a directory exists
|
|
18
|
+
*/
|
|
19
|
+
export async function directoryExists(dirPath) {
|
|
20
|
+
try {
|
|
21
|
+
const stat = await fs.stat(dirPath);
|
|
22
|
+
return stat.isDirectory();
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ensure a directory exists, create if it doesn't
|
|
30
|
+
*/
|
|
31
|
+
export async function ensureDir(dirPath) {
|
|
32
|
+
try {
|
|
33
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throw new Error(`Failed to create directory ${dirPath}: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read a file as a string with proper encoding and BOM handling
|
|
41
|
+
*/
|
|
42
|
+
export async function readFile(filePath) {
|
|
43
|
+
try {
|
|
44
|
+
// Check if file exists first
|
|
45
|
+
if (!(await fileExists(filePath))) {
|
|
46
|
+
throw new Error(`File not found: ${filePath}`);
|
|
47
|
+
}
|
|
48
|
+
// Read with explicit UTF-8 encoding
|
|
49
|
+
let content = await fs.readFile(filePath, { encoding: "utf-8" });
|
|
50
|
+
// Remove BOM if present (UTF-8 BOM is EF BB BF)
|
|
51
|
+
if (content.charCodeAt(0) === 0xfeff) {
|
|
52
|
+
content = content.slice(1);
|
|
53
|
+
}
|
|
54
|
+
// Trim whitespace that might cause JSON parsing issues
|
|
55
|
+
content = content.trim();
|
|
56
|
+
// Check if file is empty
|
|
57
|
+
if (content.length === 0) {
|
|
58
|
+
throw new Error(`File is empty: ${filePath}`);
|
|
59
|
+
}
|
|
60
|
+
return content;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof Error) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Failed to read file ${filePath}: ${error}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Read and parse a JSON file with comprehensive error handling
|
|
71
|
+
*/
|
|
72
|
+
export async function readJsonFile(filePath) {
|
|
73
|
+
try {
|
|
74
|
+
const content = await readFile(filePath);
|
|
75
|
+
// Attempt to parse JSON
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(content);
|
|
78
|
+
return parsed;
|
|
79
|
+
}
|
|
80
|
+
catch (parseError) {
|
|
81
|
+
// Provide helpful error message with context
|
|
82
|
+
const errorMessage = parseError.message;
|
|
83
|
+
const preview = content.substring(0, 100);
|
|
84
|
+
throw new Error(`Invalid JSON in ${path.basename(filePath)}: ${errorMessage}\n` +
|
|
85
|
+
`Preview: ${preview}${content.length > 100 ? "..." : ""}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Write content to a file
|
|
94
|
+
*/
|
|
95
|
+
export async function writeFile(filePath, content) {
|
|
96
|
+
try {
|
|
97
|
+
// Ensure parent directory exists
|
|
98
|
+
const dir = path.dirname(filePath);
|
|
99
|
+
await ensureDir(dir);
|
|
100
|
+
// Write with UTF-8 encoding, no BOM
|
|
101
|
+
await fs.writeFile(filePath, content, { encoding: "utf-8" });
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
throw new Error(`Failed to write file ${filePath}: ${error.message}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Write content to a file only if it doesn't exist or force is true
|
|
109
|
+
*/
|
|
110
|
+
export async function writeFileSafe(filePath, content, force = false) {
|
|
111
|
+
try {
|
|
112
|
+
const exists = await fileExists(filePath);
|
|
113
|
+
if (exists && !force) {
|
|
114
|
+
logger.warn(`File already exists, skipping: ${filePath}`);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
await writeFile(filePath, content);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
throw new Error(`Failed to write file ${filePath}: ${error.message}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Write JSON to a file with pretty formatting
|
|
126
|
+
*/
|
|
127
|
+
export async function writeJsonFile(filePath, data, force = false) {
|
|
128
|
+
try {
|
|
129
|
+
const exists = await fileExists(filePath);
|
|
130
|
+
if (exists && !force) {
|
|
131
|
+
throw new Error(`File already exists: ${filePath}. Use --force to overwrite.`);
|
|
132
|
+
}
|
|
133
|
+
const content = JSON.stringify(data, null, 2) + "\n";
|
|
134
|
+
await writeFile(filePath, content);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (error instanceof Error) {
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`Failed to write JSON file ${filePath}: ${error}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Copy a file from source to destination
|
|
145
|
+
*/
|
|
146
|
+
export async function copyFile(src, dest) {
|
|
147
|
+
try {
|
|
148
|
+
if (!(await fileExists(src))) {
|
|
149
|
+
throw new Error(`Source file not found: ${src}`);
|
|
150
|
+
}
|
|
151
|
+
// Ensure destination directory exists
|
|
152
|
+
const destDir = path.dirname(dest);
|
|
153
|
+
await ensureDir(destDir);
|
|
154
|
+
await fs.copyFile(src, dest);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
throw new Error(`Failed to copy file from ${src} to ${dest}: ${error.message}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Copy a file only if destination doesn't exist or force is true
|
|
162
|
+
*/
|
|
163
|
+
export async function copyFileSafe(src, dest, force = false) {
|
|
164
|
+
try {
|
|
165
|
+
const exists = await fileExists(dest);
|
|
166
|
+
if (exists && !force) {
|
|
167
|
+
logger.warn(`File already exists, skipping: ${dest}`);
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
await copyFile(src, dest);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
throw new Error(`Failed to copy file from ${src} to ${dest}: ${error.message}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Delete a file
|
|
179
|
+
*/
|
|
180
|
+
export async function deleteFile(filePath) {
|
|
181
|
+
try {
|
|
182
|
+
if (await fileExists(filePath)) {
|
|
183
|
+
await fs.unlink(filePath);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
throw new Error(`Failed to delete file ${filePath}: ${error.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Delete a directory recursively
|
|
192
|
+
*/
|
|
193
|
+
export async function deleteDirectory(dirPath) {
|
|
194
|
+
try {
|
|
195
|
+
if (await directoryExists(dirPath)) {
|
|
196
|
+
await fs.rm(dirPath, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
throw new Error(`Failed to delete directory ${dirPath}: ${error.message}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* List files in a directory
|
|
205
|
+
*/
|
|
206
|
+
export async function listFiles(dirPath, options) {
|
|
207
|
+
try {
|
|
208
|
+
if (!(await directoryExists(dirPath))) {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
const files = [];
|
|
212
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
213
|
+
for (const entry of entries) {
|
|
214
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
215
|
+
if (entry.isDirectory() && options?.recursive) {
|
|
216
|
+
const subFiles = await listFiles(fullPath, options);
|
|
217
|
+
files.push(...subFiles);
|
|
218
|
+
}
|
|
219
|
+
else if (entry.isFile()) {
|
|
220
|
+
if (options?.extension) {
|
|
221
|
+
if (entry.name.endsWith(options.extension)) {
|
|
222
|
+
files.push(fullPath);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
files.push(fullPath);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return files;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
throw new Error(`Failed to list files in ${dirPath}: ${error.message}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get file stats
|
|
238
|
+
*/
|
|
239
|
+
export async function getFileStats(filePath) {
|
|
240
|
+
try {
|
|
241
|
+
return await fs.stat(filePath);
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Check if path is a file
|
|
249
|
+
*/
|
|
250
|
+
export async function isFile(filePath) {
|
|
251
|
+
try {
|
|
252
|
+
const stat = await fs.stat(filePath);
|
|
253
|
+
return stat.isFile();
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Check if path is a directory
|
|
261
|
+
*/
|
|
262
|
+
export async function isDirectory(dirPath) {
|
|
263
|
+
return directoryExists(dirPath);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Read package.json with validation
|
|
267
|
+
*/
|
|
268
|
+
export async function readPackageJson(cwd) {
|
|
269
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
270
|
+
try {
|
|
271
|
+
const packageJson = await readJsonFile(packageJsonPath);
|
|
272
|
+
// Validate it's actually a package.json
|
|
273
|
+
if (!packageJson.name) {
|
|
274
|
+
throw new Error("Invalid package.json: missing 'name' field");
|
|
275
|
+
}
|
|
276
|
+
return packageJson;
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (error instanceof Error) {
|
|
280
|
+
throw new Error(`Failed to read package.json: ${error.message}`);
|
|
281
|
+
}
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Update package.json dependencies
|
|
287
|
+
*/
|
|
288
|
+
export async function updatePackageJsonDependencies(cwd, dependencies, dev = false) {
|
|
289
|
+
try {
|
|
290
|
+
const packageJson = await readPackageJson(cwd);
|
|
291
|
+
const depKey = dev ? "devDependencies" : "dependencies";
|
|
292
|
+
packageJson[depKey] = {
|
|
293
|
+
...packageJson[depKey],
|
|
294
|
+
...dependencies,
|
|
295
|
+
};
|
|
296
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
297
|
+
await writeJsonFile(packageJsonPath, packageJson, true);
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
throw new Error(`Failed to update package.json: ${error.message}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
303
|
//# sourceMappingURL=fs.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export declare const highlighter: {
|
|
2
|
-
error: typeof import("kleur/colors").print;
|
|
3
|
-
warn: typeof import("kleur/colors").print;
|
|
4
|
-
info: typeof import("kleur/colors").print;
|
|
5
|
-
success: typeof import("kleur/colors").print;
|
|
6
|
-
};
|
|
1
|
+
export declare const highlighter: {
|
|
2
|
+
error: typeof import("kleur/colors").print;
|
|
3
|
+
warn: typeof import("kleur/colors").print;
|
|
4
|
+
info: typeof import("kleur/colors").print;
|
|
5
|
+
success: typeof import("kleur/colors").print;
|
|
6
|
+
};
|
package/dist/lib/highlighter.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { cyan, green, red, yellow } from "kleur/colors";
|
|
2
|
-
export const highlighter = {
|
|
3
|
-
error: red,
|
|
4
|
-
warn: yellow,
|
|
5
|
-
info: cyan,
|
|
6
|
-
success: green,
|
|
7
|
-
};
|
|
1
|
+
import { cyan, green, red, yellow } from "kleur/colors";
|
|
2
|
+
export const highlighter = {
|
|
3
|
+
error: red,
|
|
4
|
+
warn: yellow,
|
|
5
|
+
info: cyan,
|
|
6
|
+
success: green,
|
|
7
|
+
};
|
|
8
8
|
//# sourceMappingURL=highlighter.js.map
|
package/dist/lib/install.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import type { TrixUIConfig } from "./config.js";
|
|
2
|
-
import { type LockfileComponent } from "./lockfile.js";
|
|
3
|
-
import { type RegistryItem } from "./registry.js";
|
|
4
|
-
export type InstallSummary = {
|
|
5
|
-
installed: string[];
|
|
6
|
-
skipped: string[];
|
|
7
|
-
npmDependencies: Set<string>;
|
|
8
|
-
};
|
|
9
|
-
type InstallOptions = {
|
|
10
|
-
cwd: string;
|
|
11
|
-
config: TrixUIConfig;
|
|
12
|
-
entries: RegistryItem[];
|
|
13
|
-
names: string[];
|
|
14
|
-
lockEntries: Record<string, LockfileComponent>;
|
|
15
|
-
force: boolean;
|
|
16
|
-
itemLabel: string;
|
|
17
|
-
};
|
|
18
|
-
export declare function installRegistryEntries(options: InstallOptions): Promise<InstallSummary>;
|
|
19
|
-
export {};
|
|
1
|
+
import type { TrixUIConfig } from "./config.js";
|
|
2
|
+
import { type LockfileComponent } from "./lockfile.js";
|
|
3
|
+
import { type RegistryItem } from "./registry.js";
|
|
4
|
+
export type InstallSummary = {
|
|
5
|
+
installed: string[];
|
|
6
|
+
skipped: string[];
|
|
7
|
+
npmDependencies: Set<string>;
|
|
8
|
+
};
|
|
9
|
+
type InstallOptions = {
|
|
10
|
+
cwd: string;
|
|
11
|
+
config: TrixUIConfig;
|
|
12
|
+
entries: RegistryItem[];
|
|
13
|
+
names: string[];
|
|
14
|
+
lockEntries: Record<string, LockfileComponent>;
|
|
15
|
+
force: boolean;
|
|
16
|
+
itemLabel: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function installRegistryEntries(options: InstallOptions): Promise<InstallSummary>;
|
|
19
|
+
export {};
|