expo-app-ui 1.0.0 → 1.0.1
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/bin/expo-app-ui.js +72 -409
- package/package.json +2 -1
- package/src/commands/add.js +416 -0
- package/src/commands/list.js +100 -0
- package/src/core/dependencyDetector.js +32 -0
- package/src/core/templateProcessor.js +83 -0
- package/src/utils/config.js +62 -0
- package/src/utils/errors.js +41 -0
- package/src/utils/logger.js +52 -0
- package/src/utils/pathUtils.js +120 -0
- package/templates/LoadingBar.tsx +70 -0
- package/templates/components/ui/loading-bar.tsx +70 -0
- package/templates/context/top-loading-bar-context.tsx +39 -0
- /package/templates/{box-view.tsx → components/ui/box-view.tsx} +0 -0
- /package/templates/{button.tsx → components/ui/button.tsx} +0 -0
- /package/templates/{custom-modal.tsx → components/ui/custom-modal.tsx} +0 -0
- /package/templates/{custom-text.tsx → components/ui/custom-text.tsx} +0 -0
- /package/templates/{marquee.tsx → components/ui/marquee.tsx} +0 -0
- /package/templates/{otp-input.tsx → components/ui/otp-input.tsx} +0 -0
- /package/templates/{profile-pic.tsx → components/ui/profile-pic.tsx} +0 -0
- /package/templates/{progress-bar.tsx → components/ui/progress-bar.tsx} +0 -0
package/bin/expo-app-ui.js
CHANGED
|
@@ -1,430 +1,93 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const getPackageDir = () => {
|
|
10
|
-
let currentDir = __dirname;
|
|
11
|
-
|
|
12
|
-
while (currentDir !== path.dirname(currentDir)) {
|
|
13
|
-
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
14
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
15
|
-
const pkg = fs.readJsonSync(packageJsonPath);
|
|
16
|
-
if (pkg.bin && (pkg.bin['expo-app-ui'] || pkg.name === 'expo-app-ui')) {
|
|
17
|
-
return currentDir;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
currentDir = path.dirname(currentDir);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return path.dirname(__dirname);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const packageDir = getPackageDir();
|
|
27
|
-
const templatesDir = path.join(packageDir, 'templates');
|
|
28
|
-
|
|
29
|
-
// Get the current working directory (user's project)
|
|
30
|
-
const getProjectRoot = () => {
|
|
31
|
-
let currentDir = process.cwd();
|
|
32
|
-
|
|
33
|
-
while (currentDir !== path.dirname(currentDir)) {
|
|
34
|
-
if (fs.existsSync(path.join(currentDir, 'package.json')) ||
|
|
35
|
-
fs.existsSync(path.join(currentDir, 'app.json'))) {
|
|
36
|
-
return currentDir;
|
|
37
|
-
}
|
|
38
|
-
currentDir = path.dirname(currentDir);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return process.cwd();
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const projectRoot = getProjectRoot();
|
|
45
|
-
|
|
46
|
-
// Function to convert component name to file name
|
|
47
|
-
const toKebabCase = (str) => {
|
|
48
|
-
return str
|
|
49
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
50
|
-
.replace(/[\s_]+/g, '-')
|
|
51
|
-
.toLowerCase();
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
// Function to convert kebab-case to PascalCase
|
|
55
|
-
const toPascalCase = (str) => {
|
|
56
|
-
return str
|
|
57
|
-
.split('-')
|
|
58
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
59
|
-
.join('');
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Detect dependencies in component content
|
|
63
|
-
const detectDependencies = (content) => {
|
|
64
|
-
const dependencies = {
|
|
65
|
-
needsNormalizeSize: false,
|
|
66
|
-
needsTheme: false,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
if (content.includes('@/helper/normalizeSize') || content.includes('normalizeSize')) {
|
|
70
|
-
dependencies.needsNormalizeSize = true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (content.includes('@/constants/theme') || content.includes('from "@/constants/theme"')) {
|
|
74
|
-
dependencies.needsTheme = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return dependencies;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// Add helper file
|
|
81
|
-
async function addHelper(helperName, options = {}) {
|
|
82
|
-
const kebabName = toKebabCase(helperName);
|
|
83
|
-
const templatePath = path.join(templatesDir, 'helpers', `${kebabName}.ts`);
|
|
84
|
-
const helpersDir = path.join(projectRoot, 'helpers');
|
|
85
|
-
const targetPath = path.join(helpersDir, `${kebabName}.ts`);
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
if (!fs.existsSync(templatePath)) {
|
|
89
|
-
console.error(chalk.red(`✖ Helper "${helperName}" not found.`));
|
|
90
|
-
|
|
91
|
-
// List available helpers
|
|
92
|
-
const helpersTemplateDir = path.join(templatesDir, 'helpers');
|
|
93
|
-
if (fs.existsSync(helpersTemplateDir)) {
|
|
94
|
-
const helpers = fs.readdirSync(helpersTemplateDir)
|
|
95
|
-
.filter(file => file.endsWith('.ts') || file.endsWith('.tsx'))
|
|
96
|
-
.map(file => path.basename(file, path.extname(file)));
|
|
97
|
-
|
|
98
|
-
if (helpers.length > 0) {
|
|
99
|
-
console.log(chalk.yellow('\nAvailable helpers:'));
|
|
100
|
-
helpers.forEach(helper => {
|
|
101
|
-
console.log(chalk.gray(` - ${helper}`));
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
await fs.ensureDir(helpersDir);
|
|
110
|
-
|
|
111
|
-
const overwrite = process.argv.includes('--overwrite') || options.overwrite;
|
|
112
|
-
|
|
113
|
-
if (fs.existsSync(targetPath) && !overwrite) {
|
|
114
|
-
console.error(chalk.red(`✖ Helper "${helperName}" already exists at ${targetPath}`));
|
|
115
|
-
console.log(chalk.yellow(' Use --overwrite to replace it.'));
|
|
116
|
-
process.exit(1);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
let content = await fs.readFile(templatePath, 'utf-8');
|
|
120
|
-
await fs.writeFile(targetPath, content, 'utf-8');
|
|
121
|
-
|
|
122
|
-
if (!options.silent) {
|
|
123
|
-
console.log(chalk.green(`✓ Added ${helperName} helper to ${path.relative(projectRoot, targetPath)}`));
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return true;
|
|
127
|
-
} catch (error) {
|
|
128
|
-
console.error(chalk.red(`✖ Error adding helper: ${error.message}`));
|
|
129
|
-
process.exit(1);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Add constants file
|
|
134
|
-
async function addConstant(constantName, options = {}) {
|
|
135
|
-
const kebabName = toKebabCase(constantName);
|
|
136
|
-
const templatePath = path.join(templatesDir, 'constants', `${kebabName}.ts`);
|
|
137
|
-
const constantsDir = path.join(projectRoot, 'constants');
|
|
138
|
-
const targetPath = path.join(constantsDir, `${kebabName}.ts`);
|
|
139
|
-
|
|
140
|
-
try {
|
|
141
|
-
if (!fs.existsSync(templatePath)) {
|
|
142
|
-
console.error(chalk.red(`✖ Constant "${constantName}" not found.`));
|
|
143
|
-
|
|
144
|
-
// List available constants
|
|
145
|
-
const constantsTemplateDir = path.join(templatesDir, 'constants');
|
|
146
|
-
if (fs.existsSync(constantsTemplateDir)) {
|
|
147
|
-
const constants = fs.readdirSync(constantsTemplateDir)
|
|
148
|
-
.filter(file => file.endsWith('.ts') || file.endsWith('.tsx'))
|
|
149
|
-
.map(file => path.basename(file, path.extname(file)));
|
|
150
|
-
|
|
151
|
-
if (constants.length > 0) {
|
|
152
|
-
console.log(chalk.yellow('\nAvailable constants:'));
|
|
153
|
-
constants.forEach(constant => {
|
|
154
|
-
console.log(chalk.gray(` - ${constant}`));
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
process.exit(1);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
await fs.ensureDir(constantsDir);
|
|
163
|
-
|
|
164
|
-
const overwrite = process.argv.includes('--overwrite') || options.overwrite;
|
|
165
|
-
|
|
166
|
-
if (fs.existsSync(targetPath) && !overwrite) {
|
|
167
|
-
console.error(chalk.red(`✖ Constant "${constantName}" already exists at ${targetPath}`));
|
|
168
|
-
console.log(chalk.yellow(' Use --overwrite to replace it.'));
|
|
169
|
-
process.exit(1);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
let content = await fs.readFile(templatePath, 'utf-8');
|
|
173
|
-
|
|
174
|
-
// Auto-add normalizeSize dependency for theme.ts
|
|
175
|
-
if (kebabName === 'theme') {
|
|
176
|
-
const normalizeSizePath = path.join(projectRoot, 'helpers', 'normalizeSize.ts');
|
|
177
|
-
if (!fs.existsSync(normalizeSizePath)) {
|
|
178
|
-
if (!options.silent) {
|
|
179
|
-
console.log(chalk.blue('ℹ Adding normalizeSize helper (required dependency for theme)...'));
|
|
180
|
-
}
|
|
181
|
-
await addHelper('normalizeSize', { silent: true, overwrite: false });
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Fix import path to use relative path
|
|
185
|
-
const normalizeSizeExists = fs.existsSync(normalizeSizePath);
|
|
186
|
-
if (normalizeSizeExists) {
|
|
187
|
-
// The import in theme.ts already uses '../helpers/normalizeSize' which is correct
|
|
188
|
-
// No need to change it
|
|
189
|
-
}
|
|
190
|
-
}
|
|
3
|
+
/**
|
|
4
|
+
* Expo App UI CLI - Production Ready
|
|
5
|
+
*
|
|
6
|
+
* A UI component library CLI for Expo React Native
|
|
7
|
+
* Copy components directly into your project and customize them
|
|
8
|
+
*/
|
|
191
9
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Function to add a component
|
|
206
|
-
async function addComponent(componentName) {
|
|
207
|
-
const kebabName = toKebabCase(componentName);
|
|
208
|
-
const templatePath = path.join(templatesDir, `${kebabName}.tsx`);
|
|
209
|
-
const componentsDir = path.join(projectRoot, 'components', 'ui');
|
|
210
|
-
const targetPath = path.join(componentsDir, `${toPascalCase(kebabName)}.tsx`);
|
|
211
|
-
|
|
212
|
-
try {
|
|
213
|
-
// Check if template exists
|
|
214
|
-
if (!fs.existsSync(templatePath)) {
|
|
215
|
-
console.error(chalk.red(`✖ Component "${componentName}" not found.`));
|
|
216
|
-
console.log(chalk.yellow(`Available components:`));
|
|
217
|
-
|
|
218
|
-
// List available components
|
|
219
|
-
const templates = fs.readdirSync(templatesDir)
|
|
220
|
-
.filter(file => (file.endsWith('.tsx') || file.endsWith('.ts')) &&
|
|
221
|
-
!fs.statSync(path.join(templatesDir, file)).isDirectory())
|
|
222
|
-
.map(file => path.basename(file, path.extname(file)));
|
|
223
|
-
|
|
224
|
-
if (templates.length === 0) {
|
|
225
|
-
console.log(chalk.gray(' No components available.'));
|
|
226
|
-
} else {
|
|
227
|
-
templates.forEach(template => {
|
|
228
|
-
console.log(chalk.gray(` - ${template}`));
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Ensure components/ui directory exists
|
|
235
|
-
await fs.ensureDir(componentsDir);
|
|
236
|
-
|
|
237
|
-
// Get overwrite option from command
|
|
238
|
-
const overwrite = process.argv.includes('--overwrite');
|
|
239
|
-
|
|
240
|
-
// Check if component already exists
|
|
241
|
-
if (fs.existsSync(targetPath) && !overwrite) {
|
|
242
|
-
console.error(chalk.red(`✖ Component "${componentName}" already exists at ${targetPath}`));
|
|
243
|
-
console.log(chalk.yellow(' Use --overwrite to replace it.'));
|
|
244
|
-
process.exit(1);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Read template content
|
|
248
|
-
let content = await fs.readFile(templatePath, 'utf-8');
|
|
249
|
-
|
|
250
|
-
// Detect dependencies
|
|
251
|
-
const dependencies = detectDependencies(content);
|
|
252
|
-
|
|
253
|
-
// Auto-add dependencies if needed
|
|
254
|
-
const dependenciesToAdd = [];
|
|
255
|
-
|
|
256
|
-
if (dependencies.needsNormalizeSize) {
|
|
257
|
-
const normalizeSizePath = path.join(projectRoot, 'helpers', 'normalizeSize.ts');
|
|
258
|
-
if (!fs.existsSync(normalizeSizePath)) {
|
|
259
|
-
dependenciesToAdd.push('normalizeSize helper');
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (dependencies.needsTheme) {
|
|
264
|
-
const themePath = path.join(projectRoot, 'constants', 'theme.ts');
|
|
265
|
-
if (!fs.existsSync(themePath)) {
|
|
266
|
-
dependenciesToAdd.push('theme constants');
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Show summary of what will be added
|
|
271
|
-
if (dependenciesToAdd.length > 0) {
|
|
272
|
-
console.log(chalk.blue(`\nℹ Detected dependencies: ${dependenciesToAdd.join(', ')}`));
|
|
273
|
-
console.log(chalk.gray(' Adding required dependencies...\n'));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Add dependencies
|
|
277
|
-
if (dependencies.needsNormalizeSize) {
|
|
278
|
-
const normalizeSizePath = path.join(projectRoot, 'helpers', 'normalizeSize.ts');
|
|
279
|
-
if (!fs.existsSync(normalizeSizePath)) {
|
|
280
|
-
await addHelper('normalizeSize', { silent: true });
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (dependencies.needsTheme) {
|
|
285
|
-
const themePath = path.join(projectRoot, 'constants', 'theme.ts');
|
|
286
|
-
if (!fs.existsSync(themePath)) {
|
|
287
|
-
await addConstant('theme', { silent: true });
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Fix relative imports (e.g., CustomText from "./CustomText")
|
|
292
|
-
// This will be handled by the user's path aliases, so we keep @/ imports
|
|
293
|
-
|
|
294
|
-
// Write to target location
|
|
295
|
-
await fs.writeFile(targetPath, content, 'utf-8');
|
|
296
|
-
|
|
297
|
-
console.log(chalk.green(`✓ Added ${componentName} component to ${path.relative(projectRoot, targetPath)}`));
|
|
298
|
-
|
|
299
|
-
if (dependencies.needsNormalizeSize || dependencies.needsTheme) {
|
|
300
|
-
console.log(chalk.gray('\n💡 Tip: Make sure your project has path aliases configured for @/ imports.'));
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
} catch (error) {
|
|
304
|
-
console.error(chalk.red(`✖ Error adding component: ${error.message}`));
|
|
305
|
-
process.exit(1);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Function to list available items
|
|
310
|
-
function listItems() {
|
|
311
|
-
try {
|
|
312
|
-
const items = {
|
|
313
|
-
components: [],
|
|
314
|
-
helpers: [],
|
|
315
|
-
constants: [],
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
// List components
|
|
319
|
-
if (fs.existsSync(templatesDir)) {
|
|
320
|
-
const files = fs.readdirSync(templatesDir);
|
|
321
|
-
files.forEach(file => {
|
|
322
|
-
const filePath = path.join(templatesDir, file);
|
|
323
|
-
if (fs.statSync(filePath).isFile() && (file.endsWith('.tsx') || file.endsWith('.ts'))) {
|
|
324
|
-
items.components.push(path.basename(file, path.extname(file)));
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
// List helpers
|
|
330
|
-
const helpersDir = path.join(templatesDir, 'helpers');
|
|
331
|
-
if (fs.existsSync(helpersDir)) {
|
|
332
|
-
const files = fs.readdirSync(helpersDir);
|
|
333
|
-
files.forEach(file => {
|
|
334
|
-
if (file.endsWith('.ts') || file.endsWith('.tsx')) {
|
|
335
|
-
items.helpers.push(path.basename(file, path.extname(file)));
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// List constants
|
|
341
|
-
const constantsDir = path.join(templatesDir, 'constants');
|
|
342
|
-
if (fs.existsSync(constantsDir)) {
|
|
343
|
-
const files = fs.readdirSync(constantsDir);
|
|
344
|
-
files.forEach(file => {
|
|
345
|
-
if (file.endsWith('.ts') || file.endsWith('.tsx')) {
|
|
346
|
-
items.constants.push(path.basename(file, path.extname(file)));
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (items.components.length === 0 && items.helpers.length === 0 && items.constants.length === 0) {
|
|
352
|
-
console.log(chalk.yellow('No items available.'));
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (items.components.length > 0) {
|
|
357
|
-
console.log(chalk.blue('Available components:\n'));
|
|
358
|
-
items.components.forEach(item => {
|
|
359
|
-
console.log(chalk.gray(` - ${item}`));
|
|
360
|
-
});
|
|
361
|
-
console.log();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if (items.helpers.length > 0) {
|
|
365
|
-
console.log(chalk.blue('Available helpers:\n'));
|
|
366
|
-
items.helpers.forEach(item => {
|
|
367
|
-
console.log(chalk.gray(` - ${item}`));
|
|
368
|
-
});
|
|
369
|
-
console.log();
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (items.constants.length > 0) {
|
|
373
|
-
console.log(chalk.blue('Available constants:\n'));
|
|
374
|
-
items.constants.forEach(item => {
|
|
375
|
-
console.log(chalk.gray(` - ${item}`));
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
} catch (error) {
|
|
379
|
-
console.error(chalk.red(`✖ Error listing items: ${error.message}`));
|
|
380
|
-
process.exit(1);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
10
|
+
const { program } = require('commander');
|
|
11
|
+
const packageJson = require('../package.json');
|
|
12
|
+
const { handleAdd } = require('../src/commands/add');
|
|
13
|
+
const { handleList } = require('../src/commands/list');
|
|
14
|
+
const { CLIError, TemplateNotFoundError, FileExistsError, InvalidInputError } = require('../src/utils/errors');
|
|
15
|
+
const Logger = require('../src/utils/logger');
|
|
16
|
+
|
|
17
|
+
// Initialize logger
|
|
18
|
+
const logger = new Logger({
|
|
19
|
+
verbose: process.argv.includes('--verbose') || process.argv.includes('-v'),
|
|
20
|
+
silent: process.argv.includes('--silent') || process.argv.includes('-s'),
|
|
21
|
+
});
|
|
383
22
|
|
|
384
23
|
// CLI setup
|
|
385
24
|
program
|
|
386
|
-
.name('expo-ui')
|
|
25
|
+
.name('expo-app-ui')
|
|
387
26
|
.description('A UI component library for Expo React Native')
|
|
388
|
-
.version(
|
|
27
|
+
.version(packageJson.version)
|
|
28
|
+
.option('-v, --verbose', 'verbose output')
|
|
29
|
+
.option('-s, --silent', 'silent mode');
|
|
389
30
|
|
|
31
|
+
// Add command
|
|
390
32
|
program
|
|
391
33
|
.option('--overwrite', 'Overwrite existing files')
|
|
392
34
|
.command('add <name>')
|
|
393
35
|
.description('Add a component, helper, or constant to your project')
|
|
394
36
|
.action(async (name) => {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
37
|
+
try {
|
|
38
|
+
await handleAdd(name, {
|
|
39
|
+
overwrite: program.opts().overwrite || false,
|
|
40
|
+
verbose: logger.verbose,
|
|
41
|
+
silent: logger.silent,
|
|
42
|
+
});
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof TemplateNotFoundError) {
|
|
45
|
+
logger.error(`"${name}" not found.`);
|
|
46
|
+
logger.info('Run "npx expo-app-ui list" to see available items.');
|
|
47
|
+
} else if (error instanceof FileExistsError) {
|
|
48
|
+
logger.error(`File already exists: ${error.filePath}`);
|
|
49
|
+
logger.info('Use --overwrite to replace it.');
|
|
50
|
+
} else if (error instanceof InvalidInputError) {
|
|
51
|
+
logger.error(error.message);
|
|
52
|
+
} else if (error instanceof CLIError) {
|
|
53
|
+
logger.error(error.message);
|
|
54
|
+
} else {
|
|
55
|
+
logger.error(`Unexpected error: ${error.message}`);
|
|
56
|
+
if (logger.verbose) {
|
|
57
|
+
console.error(error.stack);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
process.exit(1);
|
|
417
61
|
}
|
|
418
|
-
|
|
419
|
-
// Not found
|
|
420
|
-
console.error(chalk.red(`✖ "${name}" not found.`));
|
|
421
|
-
console.log(chalk.yellow('Run "npx expo-app-ui list" to see available items.'));
|
|
422
|
-
process.exit(1);
|
|
423
62
|
});
|
|
424
63
|
|
|
64
|
+
// List command
|
|
425
65
|
program
|
|
426
66
|
.command('list')
|
|
427
67
|
.description('List all available components, helpers, and constants')
|
|
428
|
-
.action(
|
|
68
|
+
.action(() => {
|
|
69
|
+
try {
|
|
70
|
+
handleList({
|
|
71
|
+
verbose: logger.verbose,
|
|
72
|
+
silent: logger.silent,
|
|
73
|
+
});
|
|
74
|
+
} catch (error) {
|
|
75
|
+
logger.error(`Error: ${error.message}`);
|
|
76
|
+
if (logger.verbose) {
|
|
77
|
+
console.error(error);
|
|
78
|
+
}
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Global error handler
|
|
84
|
+
process.on('unhandledRejection', (error) => {
|
|
85
|
+
logger.error(`Unhandled error: ${error.message}`);
|
|
86
|
+
if (logger.verbose) {
|
|
87
|
+
console.error(error);
|
|
88
|
+
}
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
429
91
|
|
|
92
|
+
// Parse arguments
|
|
430
93
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-app-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A UI component library for Expo React Native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
|
+
"src",
|
|
11
12
|
"templates",
|
|
12
13
|
"README.md"
|
|
13
14
|
],
|