react-apps-ui 1.0.3 → 1.0.5
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/index.js +88 -8
- package/package.json +1 -1
- package/src/index.ts +149 -12
package/dist/index.js
CHANGED
|
@@ -61,11 +61,10 @@ program
|
|
|
61
61
|
const hasSrcDir = fs_1.default.existsSync(path_1.default.join(process.cwd(), "src"));
|
|
62
62
|
// 4. Loop through the files and write them smartly
|
|
63
63
|
for (const file of themeComponent.files) {
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
const safeTarget = file.target || file.name;
|
|
64
|
+
// A. Force the target to be a string so it can never be undefined
|
|
65
|
+
const safeTarget = String(file.target || file.name || "unknown-file");
|
|
67
66
|
let finalTargetPath = path_1.default.join(process.cwd(), safeTarget);
|
|
68
|
-
//
|
|
67
|
+
//B. Safely check includes on the guaranteed string
|
|
69
68
|
const isRootConfig = safeTarget.includes("tailwind") ||
|
|
70
69
|
safeTarget.endsWith(".config.js") ||
|
|
71
70
|
safeTarget.endsWith(".json");
|
|
@@ -81,10 +80,17 @@ program
|
|
|
81
80
|
if (file.type === "css" ||
|
|
82
81
|
finalTargetPath.endsWith(".css")) {
|
|
83
82
|
console.log(chalk_1.default.yellow(` ⚠️ ${file.target} already exists. Appending theme variables safely...`));
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
try {
|
|
84
|
+
// C. Read the file and forcefully convert it to a String
|
|
85
|
+
const rawContent = fs_1.default.readFileSync(finalTargetPath, "utf-8");
|
|
86
|
+
const safeExistingContent = String(rawContent || "");
|
|
87
|
+
// D. Safely check includes (This line can no longer crash!)
|
|
88
|
+
if (!safeExistingContent.includes("--background:")) {
|
|
89
|
+
fs_1.default.appendFileSync(finalTargetPath, `\n/* React Apps UI Theme */\n${file.content || ""}`, "utf-8");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.log(chalk_1.default.red(` ❌ Error reading or appending to ${safeTarget}`));
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
else {
|
|
@@ -105,4 +111,78 @@ program
|
|
|
105
111
|
console.error(error);
|
|
106
112
|
}
|
|
107
113
|
});
|
|
114
|
+
// --- THE ADD COMMAND ---
|
|
115
|
+
program
|
|
116
|
+
.command("add [components...]")
|
|
117
|
+
.description("Add components to your project")
|
|
118
|
+
.action(async (components) => {
|
|
119
|
+
if (!components || components.length === 0) {
|
|
120
|
+
console.log(chalk_1.default.red("Please specify at least one component to add. (e.g., npx react-apps-ui add action-button)"));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// 1. SMART AUTO-DETECT: Check if they are using NativeWind by looking for the preset or config
|
|
124
|
+
const hasTailwind = fs_1.default.existsSync(path_1.default.join(process.cwd(), "tailwind.config.js")) ||
|
|
125
|
+
fs_1.default.existsSync(path_1.default.join(process.cwd(), "theme/tailwind-preset.js")) ||
|
|
126
|
+
fs_1.default.existsSync(path_1.default.join(process.cwd(), "src/theme/tailwind-preset.js"));
|
|
127
|
+
const engine = hasTailwind ? "mobile-nativewind" : "mobile-stylesheet";
|
|
128
|
+
console.log(chalk_1.default.dim(`\nDetected engine: ${engine}`));
|
|
129
|
+
const manifestUrl = `${REGISTRY_URL}/${engine}.json`;
|
|
130
|
+
try {
|
|
131
|
+
// 2. Fetch the massive JSON database
|
|
132
|
+
const res = await fetch(manifestUrl);
|
|
133
|
+
if (!res.ok)
|
|
134
|
+
throw new Error(`Failed to fetch registry: ${res.statusText}`);
|
|
135
|
+
const registry = await res.json();
|
|
136
|
+
// 3. RECURSIVE DEPENDENCY RESOLUTION
|
|
137
|
+
// If action-button needs wave-dots-loader, this automatically grabs it!
|
|
138
|
+
const componentsToAdd = new Set();
|
|
139
|
+
const resolveDependencies = (compName) => {
|
|
140
|
+
if (componentsToAdd.has(compName))
|
|
141
|
+
return; // Prevent infinite loops
|
|
142
|
+
componentsToAdd.add(compName);
|
|
143
|
+
const compData = registry.find((c) => c.name === compName);
|
|
144
|
+
if (compData && compData.registryDependencies) {
|
|
145
|
+
compData.registryDependencies.forEach(resolveDependencies);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
// Run the resolver for every component the user typed in the terminal
|
|
149
|
+
components.forEach(resolveDependencies);
|
|
150
|
+
// We don't need to reinstall the theme if it was pulled as a dependency
|
|
151
|
+
componentsToAdd.delete("theme");
|
|
152
|
+
console.log(chalk_1.default.blue(`\nInstalling: ${Array.from(componentsToAdd).join(", ")}...`));
|
|
153
|
+
const hasSrcDir = fs_1.default.existsSync(path_1.default.join(process.cwd(), "src"));
|
|
154
|
+
// 4. WRITE THE FILES
|
|
155
|
+
for (const compName of componentsToAdd) {
|
|
156
|
+
const compData = registry.find((c) => c.name === compName);
|
|
157
|
+
if (!compData) {
|
|
158
|
+
console.log(chalk_1.default.red(` ❌ Component '${compName}' not found in registry.`));
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
for (const file of compData.files) {
|
|
162
|
+
const safeTarget = String(file.target || file.name || "unknown-file");
|
|
163
|
+
let finalTargetPath = path_1.default.join(process.cwd(), safeTarget);
|
|
164
|
+
if (hasSrcDir) {
|
|
165
|
+
finalTargetPath = path_1.default.join(process.cwd(), "src", safeTarget);
|
|
166
|
+
}
|
|
167
|
+
// Ensure the folder exists
|
|
168
|
+
fs_1.default.mkdirSync(path_1.default.dirname(finalTargetPath), {
|
|
169
|
+
recursive: true,
|
|
170
|
+
});
|
|
171
|
+
// Safe Write
|
|
172
|
+
if (!fs_1.default.existsSync(finalTargetPath)) {
|
|
173
|
+
fs_1.default.writeFileSync(finalTargetPath, file.content || "", "utf-8");
|
|
174
|
+
console.log(chalk_1.default.green(` Created ${safeTarget}`));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
console.log(chalk_1.default.yellow(` ⚠️ ${safeTarget} already exists. Skipping.`));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
console.log(chalk_1.default.blue("\n🎉 Components installed successfully!"));
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.log(chalk_1.default.red(`\nFailed to add components:`));
|
|
185
|
+
console.error(error);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
108
188
|
program.parse();
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -75,16 +75,18 @@ program
|
|
|
75
75
|
|
|
76
76
|
// 4. Loop through the files and write them smartly
|
|
77
77
|
for (const file of themeComponent.files) {
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
// A. Force the target to be a string so it can never be undefined
|
|
79
|
+
const safeTarget = String(
|
|
80
|
+
file.target || file.name || "unknown-file",
|
|
81
|
+
);
|
|
81
82
|
let finalTargetPath = path.join(process.cwd(), safeTarget);
|
|
82
83
|
|
|
83
|
-
//
|
|
84
|
+
//B. Safely check includes on the guaranteed string
|
|
84
85
|
const isRootConfig =
|
|
85
86
|
safeTarget.includes("tailwind") ||
|
|
86
87
|
safeTarget.endsWith(".config.js") ||
|
|
87
88
|
safeTarget.endsWith(".json");
|
|
89
|
+
|
|
88
90
|
if (hasSrcDir && !isRootConfig) {
|
|
89
91
|
finalTargetPath = path.join(
|
|
90
92
|
process.cwd(),
|
|
@@ -109,18 +111,33 @@ program
|
|
|
109
111
|
` ⚠️ ${file.target} already exists. Appending theme variables safely...`,
|
|
110
112
|
),
|
|
111
113
|
);
|
|
112
|
-
const existingContent = fs.readFileSync(
|
|
113
|
-
finalTargetPath,
|
|
114
|
-
"utf-8",
|
|
115
|
-
);
|
|
116
114
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
fs.
|
|
115
|
+
try {
|
|
116
|
+
// C. Read the file and forcefully convert it to a String
|
|
117
|
+
const rawContent = fs.readFileSync(
|
|
120
118
|
finalTargetPath,
|
|
121
|
-
`\n/* React Apps UI Theme */\n${file.content}`,
|
|
122
119
|
"utf-8",
|
|
123
120
|
);
|
|
121
|
+
const safeExistingContent = String(
|
|
122
|
+
rawContent || "",
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// D. Safely check includes (This line can no longer crash!)
|
|
126
|
+
if (
|
|
127
|
+
!safeExistingContent.includes("--background:")
|
|
128
|
+
) {
|
|
129
|
+
fs.appendFileSync(
|
|
130
|
+
finalTargetPath,
|
|
131
|
+
`\n/* React Apps UI Theme */\n${file.content || ""}`,
|
|
132
|
+
"utf-8",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.log(
|
|
137
|
+
chalk.red(
|
|
138
|
+
` ❌ Error reading or appending to ${safeTarget}`,
|
|
139
|
+
),
|
|
140
|
+
);
|
|
124
141
|
}
|
|
125
142
|
} else {
|
|
126
143
|
console.log(
|
|
@@ -148,4 +165,124 @@ program
|
|
|
148
165
|
}
|
|
149
166
|
});
|
|
150
167
|
|
|
168
|
+
// --- THE ADD COMMAND ---
|
|
169
|
+
program
|
|
170
|
+
.command("add [components...]")
|
|
171
|
+
.description("Add components to your project")
|
|
172
|
+
.action(async (components: string[]) => {
|
|
173
|
+
if (!components || components.length === 0) {
|
|
174
|
+
console.log(
|
|
175
|
+
chalk.red(
|
|
176
|
+
"Please specify at least one component to add. (e.g., npx react-apps-ui add action-button)",
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 1. SMART AUTO-DETECT: Check if they are using NativeWind by looking for the preset or config
|
|
183
|
+
const hasTailwind =
|
|
184
|
+
fs.existsSync(path.join(process.cwd(), "tailwind.config.js")) ||
|
|
185
|
+
fs.existsSync(
|
|
186
|
+
path.join(process.cwd(), "theme/tailwind-preset.js"),
|
|
187
|
+
) ||
|
|
188
|
+
fs.existsSync(
|
|
189
|
+
path.join(process.cwd(), "src/theme/tailwind-preset.js"),
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const engine = hasTailwind ? "mobile-nativewind" : "mobile-stylesheet";
|
|
193
|
+
|
|
194
|
+
console.log(chalk.dim(`\nDetected engine: ${engine}`));
|
|
195
|
+
const manifestUrl = `${REGISTRY_URL}/${engine}.json`;
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
// 2. Fetch the massive JSON database
|
|
199
|
+
const res = await fetch(manifestUrl);
|
|
200
|
+
if (!res.ok)
|
|
201
|
+
throw new Error(`Failed to fetch registry: ${res.statusText}`);
|
|
202
|
+
const registry = await res.json();
|
|
203
|
+
|
|
204
|
+
// 3. RECURSIVE DEPENDENCY RESOLUTION
|
|
205
|
+
// If action-button needs wave-dots-loader, this automatically grabs it!
|
|
206
|
+
const componentsToAdd = new Set<string>();
|
|
207
|
+
|
|
208
|
+
const resolveDependencies = (compName: string) => {
|
|
209
|
+
if (componentsToAdd.has(compName)) return; // Prevent infinite loops
|
|
210
|
+
componentsToAdd.add(compName);
|
|
211
|
+
|
|
212
|
+
const compData = registry.find((c: any) => c.name === compName);
|
|
213
|
+
if (compData && compData.registryDependencies) {
|
|
214
|
+
compData.registryDependencies.forEach(resolveDependencies);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Run the resolver for every component the user typed in the terminal
|
|
219
|
+
components.forEach(resolveDependencies);
|
|
220
|
+
|
|
221
|
+
// We don't need to reinstall the theme if it was pulled as a dependency
|
|
222
|
+
componentsToAdd.delete("theme");
|
|
223
|
+
|
|
224
|
+
console.log(
|
|
225
|
+
chalk.blue(
|
|
226
|
+
`\nInstalling: ${Array.from(componentsToAdd).join(", ")}...`,
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const hasSrcDir = fs.existsSync(path.join(process.cwd(), "src"));
|
|
231
|
+
|
|
232
|
+
// 4. WRITE THE FILES
|
|
233
|
+
for (const compName of componentsToAdd) {
|
|
234
|
+
const compData = registry.find((c: any) => c.name === compName);
|
|
235
|
+
if (!compData) {
|
|
236
|
+
console.log(
|
|
237
|
+
chalk.red(
|
|
238
|
+
` ❌ Component '${compName}' not found in registry.`,
|
|
239
|
+
),
|
|
240
|
+
);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
for (const file of compData.files) {
|
|
245
|
+
const safeTarget = String(
|
|
246
|
+
file.target || file.name || "unknown-file",
|
|
247
|
+
);
|
|
248
|
+
let finalTargetPath = path.join(process.cwd(), safeTarget);
|
|
249
|
+
|
|
250
|
+
if (hasSrcDir) {
|
|
251
|
+
finalTargetPath = path.join(
|
|
252
|
+
process.cwd(),
|
|
253
|
+
"src",
|
|
254
|
+
safeTarget,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Ensure the folder exists
|
|
259
|
+
fs.mkdirSync(path.dirname(finalTargetPath), {
|
|
260
|
+
recursive: true,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Safe Write
|
|
264
|
+
if (!fs.existsSync(finalTargetPath)) {
|
|
265
|
+
fs.writeFileSync(
|
|
266
|
+
finalTargetPath,
|
|
267
|
+
file.content || "",
|
|
268
|
+
"utf-8",
|
|
269
|
+
);
|
|
270
|
+
console.log(chalk.green(` Created ${safeTarget}`));
|
|
271
|
+
} else {
|
|
272
|
+
console.log(
|
|
273
|
+
chalk.yellow(
|
|
274
|
+
` ⚠️ ${safeTarget} already exists. Skipping.`,
|
|
275
|
+
),
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
console.log(chalk.blue("\n🎉 Components installed successfully!"));
|
|
282
|
+
} catch (error) {
|
|
283
|
+
console.log(chalk.red(`\nFailed to add components:`));
|
|
284
|
+
console.error(error);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
151
288
|
program.parse();
|