@xbg.solutions/create-frontend 1.1.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/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/package.json +21 -0
- package/src/generate-component.cjs +602 -0
- package/src/generate-route.cjs +774 -0
- package/src/generate-service.cjs +1306 -0
- package/src/index.ts +2 -0
- package/src/manage-auth-users.cjs +410 -0
- package/src/setup.cjs +1049 -0
- package/src/validate-setup.cjs +341 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validates the project setup and configuration
|
|
5
|
+
*
|
|
6
|
+
* Checks:
|
|
7
|
+
* - Environment variables
|
|
8
|
+
* - Firebase configuration
|
|
9
|
+
* - Dependencies
|
|
10
|
+
* - Build configuration
|
|
11
|
+
* - Test setup
|
|
12
|
+
*
|
|
13
|
+
* Usage: npm run validate
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
|
|
20
|
+
// ANSI colors
|
|
21
|
+
const colors = {
|
|
22
|
+
reset: '\x1b[0m',
|
|
23
|
+
green: '\x1b[32m',
|
|
24
|
+
red: '\x1b[31m',
|
|
25
|
+
yellow: '\x1b[33m',
|
|
26
|
+
cyan: '\x1b[36m',
|
|
27
|
+
bright: '\x1b[1m'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const log = {
|
|
31
|
+
success: (msg) => console.log(`${colors.green}โ${colors.reset} ${msg}`),
|
|
32
|
+
error: (msg) => console.log(`${colors.red}โ${colors.reset} ${msg}`),
|
|
33
|
+
warn: (msg) => console.log(`${colors.yellow}โ ${colors.reset} ${msg}`),
|
|
34
|
+
info: (msg) => console.log(`${colors.cyan}โน${colors.reset} ${msg}`),
|
|
35
|
+
title: (msg) => console.log(`\n${colors.bright}${msg}${colors.reset}`)
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let errorCount = 0;
|
|
39
|
+
let warningCount = 0;
|
|
40
|
+
|
|
41
|
+
function checkFile(filePath, description) {
|
|
42
|
+
if (fs.existsSync(filePath)) {
|
|
43
|
+
log.success(`${description} exists`);
|
|
44
|
+
return true;
|
|
45
|
+
} else {
|
|
46
|
+
log.error(`${description} missing: ${filePath}`);
|
|
47
|
+
errorCount++;
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function checkEnvVar(varName, description, isRequired = true) {
|
|
53
|
+
// Read .env file
|
|
54
|
+
if (!fs.existsSync('.env')) {
|
|
55
|
+
if (isRequired) {
|
|
56
|
+
log.error(`.env file not found - run 'npm run setup'`);
|
|
57
|
+
errorCount++;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const envContent = fs.readFileSync('.env', 'utf8');
|
|
63
|
+
const match = envContent.match(new RegExp(`${varName}=(.+)`));
|
|
64
|
+
|
|
65
|
+
if (match && match[1] && match[1].trim() !== '') {
|
|
66
|
+
const value = match[1].trim().replace(/"/g, '');
|
|
67
|
+
|
|
68
|
+
// Check if it's still a placeholder
|
|
69
|
+
if (value.includes('your-') || value.includes('FIXME') || value === 'localhost') {
|
|
70
|
+
if (isRequired) {
|
|
71
|
+
log.warn(`${description} is set to placeholder value: ${value}`);
|
|
72
|
+
warningCount++;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
log.success(`${description} configured`);
|
|
78
|
+
return true;
|
|
79
|
+
} else {
|
|
80
|
+
if (isRequired) {
|
|
81
|
+
log.error(`${description} missing (${varName})`);
|
|
82
|
+
errorCount++;
|
|
83
|
+
} else {
|
|
84
|
+
log.warn(`${description} not set (${varName})`);
|
|
85
|
+
warningCount++;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function validatePackageJson() {
|
|
92
|
+
log.title('๐ฆ Package.json Validation');
|
|
93
|
+
|
|
94
|
+
if (!checkFile('package.json', 'package.json')) return;
|
|
95
|
+
|
|
96
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
97
|
+
|
|
98
|
+
// Check required scripts
|
|
99
|
+
const requiredScripts = ['dev', 'build', 'test', 'lint'];
|
|
100
|
+
requiredScripts.forEach(script => {
|
|
101
|
+
if (pkg.scripts && pkg.scripts[script]) {
|
|
102
|
+
log.success(`Script '${script}' defined`);
|
|
103
|
+
} else {
|
|
104
|
+
log.error(`Script '${script}' missing`);
|
|
105
|
+
errorCount++;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Check required dependencies
|
|
110
|
+
const requiredDeps = ['svelte', 'firebase', 'tailwindcss'];
|
|
111
|
+
requiredDeps.forEach(dep => {
|
|
112
|
+
if (pkg.dependencies && pkg.dependencies[dep]) {
|
|
113
|
+
log.success(`Dependency '${dep}' installed`);
|
|
114
|
+
} else if (pkg.devDependencies && pkg.devDependencies[dep]) {
|
|
115
|
+
log.success(`Dev dependency '${dep}' installed`);
|
|
116
|
+
} else {
|
|
117
|
+
log.error(`Required dependency '${dep}' missing`);
|
|
118
|
+
errorCount++;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function validateFiles() {
|
|
124
|
+
log.title('๐ File Structure Validation');
|
|
125
|
+
|
|
126
|
+
const requiredFiles = [
|
|
127
|
+
{ path: 'src/app.html', desc: 'App HTML template' },
|
|
128
|
+
{ path: 'src/routes/+page.svelte', desc: 'Home page' },
|
|
129
|
+
{ path: 'src/lib/config/app.config.ts', desc: 'App configuration' },
|
|
130
|
+
{ path: 'svelte.config.js', desc: 'Svelte config' },
|
|
131
|
+
{ path: 'vite.config.ts', desc: 'Vite config' },
|
|
132
|
+
{ path: 'tailwind.config.js', desc: 'Tailwind config' },
|
|
133
|
+
{ path: 'tsconfig.json', desc: 'TypeScript config' }
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
requiredFiles.forEach(({ path, desc }) => checkFile(path, desc));
|
|
137
|
+
|
|
138
|
+
// Check component library
|
|
139
|
+
if (fs.existsSync('src/lib/components/ui')) {
|
|
140
|
+
const uiComponents = fs.readdirSync('src/lib/components/ui');
|
|
141
|
+
log.success(`UI component library (${uiComponents.length} components)`);
|
|
142
|
+
} else {
|
|
143
|
+
log.error('UI component library missing');
|
|
144
|
+
errorCount++;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function validateEnvironment() {
|
|
149
|
+
log.title('๐ Environment Configuration Validation');
|
|
150
|
+
|
|
151
|
+
// Check .env file
|
|
152
|
+
checkFile('.env', 'Environment file (.env)');
|
|
153
|
+
checkFile('.env.example', 'Environment template (.env.example)');
|
|
154
|
+
|
|
155
|
+
// Check required environment variables
|
|
156
|
+
checkEnvVar('VITE_APP_NAME', 'App name', true);
|
|
157
|
+
checkEnvVar('VITE_APP_DOMAIN', 'App domain', true);
|
|
158
|
+
checkEnvVar('VITE_FIREBASE_PROJECT_ID', 'Firebase Project ID', true);
|
|
159
|
+
checkEnvVar('VITE_FIREBASE_API_KEY', 'Firebase API Key', true);
|
|
160
|
+
checkEnvVar('VITE_FIREBASE_AUTH_DOMAIN', 'Firebase Auth Domain', true);
|
|
161
|
+
|
|
162
|
+
// Optional but recommended
|
|
163
|
+
checkEnvVar('VITE_API_BASE_URL_DEV', 'Development API URL', false);
|
|
164
|
+
checkEnvVar('VITE_API_BASE_URL_PROD', 'Production API URL', false);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function validateFirebase() {
|
|
168
|
+
log.title('๐ฅ Firebase Configuration Validation');
|
|
169
|
+
|
|
170
|
+
// Check firebase.json
|
|
171
|
+
if (checkFile('firebase.json', 'Firebase config (firebase.json)')) {
|
|
172
|
+
try {
|
|
173
|
+
const firebaseConfig = JSON.parse(fs.readFileSync('firebase.json', 'utf8'));
|
|
174
|
+
|
|
175
|
+
if (firebaseConfig.hosting) {
|
|
176
|
+
log.success('Firebase Hosting configured');
|
|
177
|
+
} else {
|
|
178
|
+
log.warn('Firebase Hosting not configured');
|
|
179
|
+
warningCount++;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (firebaseConfig.emulators) {
|
|
183
|
+
log.success('Firebase Emulators configured');
|
|
184
|
+
} else {
|
|
185
|
+
log.info('Firebase Emulators not configured (optional)');
|
|
186
|
+
}
|
|
187
|
+
} catch (e) {
|
|
188
|
+
log.error(`Invalid firebase.json: ${e.message}`);
|
|
189
|
+
errorCount++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Check if Firebase CLI is installed
|
|
194
|
+
try {
|
|
195
|
+
execSync('firebase --version', { stdio: 'ignore' });
|
|
196
|
+
log.success('Firebase CLI installed');
|
|
197
|
+
} catch (e) {
|
|
198
|
+
log.warn('Firebase CLI not found - install: npm install -g firebase-tools');
|
|
199
|
+
warningCount++;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function validateBuild() {
|
|
204
|
+
log.title('๐๏ธ Build Configuration Validation');
|
|
205
|
+
|
|
206
|
+
// Check if node_modules exists
|
|
207
|
+
if (fs.existsSync('node_modules')) {
|
|
208
|
+
log.success('Dependencies installed');
|
|
209
|
+
} else {
|
|
210
|
+
log.error('Dependencies not installed - run: npm install');
|
|
211
|
+
errorCount++;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Try a build (optional - can be slow)
|
|
216
|
+
const quickBuild = process.argv.includes('--quick');
|
|
217
|
+
if (!quickBuild) {
|
|
218
|
+
log.info('Testing build process (use --quick to skip)...');
|
|
219
|
+
try {
|
|
220
|
+
execSync('npm run build', { stdio: 'ignore', timeout: 60000 });
|
|
221
|
+
log.success('Build successful');
|
|
222
|
+
} catch (e) {
|
|
223
|
+
log.error('Build failed - check build output for errors');
|
|
224
|
+
errorCount++;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function validateTests() {
|
|
230
|
+
log.title('๐งช Test Setup Validation');
|
|
231
|
+
|
|
232
|
+
// Check test configuration
|
|
233
|
+
if (checkFile('vitest.config.ts', 'Vitest config')) {
|
|
234
|
+
// Try running tests
|
|
235
|
+
log.info('Running tests (use --quick to skip)...');
|
|
236
|
+
const quickTest = process.argv.includes('--quick');
|
|
237
|
+
if (!quickTest) {
|
|
238
|
+
try {
|
|
239
|
+
const testOutput = execSync('npm test', { encoding: 'utf8', timeout: 30000 });
|
|
240
|
+
|
|
241
|
+
// Parse test results
|
|
242
|
+
const passMatch = testOutput.match(/(\d+) passed/);
|
|
243
|
+
if (passMatch) {
|
|
244
|
+
log.success(`Tests passing: ${passMatch[1]} tests`);
|
|
245
|
+
} else {
|
|
246
|
+
log.success('Tests completed');
|
|
247
|
+
}
|
|
248
|
+
} catch (e) {
|
|
249
|
+
log.error('Tests failed - check test output for errors');
|
|
250
|
+
errorCount++;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function validateAppConfig() {
|
|
257
|
+
log.title('โ๏ธ App Configuration Validation');
|
|
258
|
+
|
|
259
|
+
const configPath = 'src/lib/config/app.config.ts';
|
|
260
|
+
if (!fs.existsSync(configPath)) {
|
|
261
|
+
log.error('app.config.ts not found');
|
|
262
|
+
errorCount++;
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
267
|
+
|
|
268
|
+
// Check for FIXME comments
|
|
269
|
+
const fixmeMatches = configContent.match(/\/\/ FIXME:/g);
|
|
270
|
+
if (fixmeMatches && fixmeMatches.length > 0) {
|
|
271
|
+
log.warn(`Found ${fixmeMatches.length} FIXME comments in app.config.ts`);
|
|
272
|
+
log.info(' Review and update these configuration items');
|
|
273
|
+
warningCount++;
|
|
274
|
+
} else {
|
|
275
|
+
log.success('No FIXME comments in app.config.ts');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Check for placeholder values
|
|
279
|
+
const placeholders = [
|
|
280
|
+
'your-project-id',
|
|
281
|
+
'your-api-key',
|
|
282
|
+
'your-app-id',
|
|
283
|
+
'your-domain.com'
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
let placeholderCount = 0;
|
|
287
|
+
placeholders.forEach(placeholder => {
|
|
288
|
+
if (configContent.includes(placeholder)) {
|
|
289
|
+
placeholderCount++;
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (placeholderCount > 0) {
|
|
294
|
+
log.warn(`Found ${placeholderCount} placeholder values in app.config.ts`);
|
|
295
|
+
log.info(' Run `npm run setup` to configure automatically');
|
|
296
|
+
warningCount++;
|
|
297
|
+
} else {
|
|
298
|
+
log.success('No placeholder values in app.config.ts');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function displaySummary() {
|
|
303
|
+
log.title('๐ Validation Summary');
|
|
304
|
+
|
|
305
|
+
console.log(`\nResults:`);
|
|
306
|
+
console.log(` ${colors.green}โ Checks passed${colors.reset}`);
|
|
307
|
+
console.log(` ${colors.red}โ Errors: ${errorCount}${colors.reset}`);
|
|
308
|
+
console.log(` ${colors.yellow}โ Warnings: ${warningCount}${colors.reset}\n`);
|
|
309
|
+
|
|
310
|
+
if (errorCount === 0 && warningCount === 0) {
|
|
311
|
+
console.log(`${colors.green}${colors.bright}๐ Your project is fully configured and ready!${colors.reset}\n`);
|
|
312
|
+
console.log(`Next steps:`);
|
|
313
|
+
console.log(` ${colors.cyan}npm run dev${colors.reset} - Start development server`);
|
|
314
|
+
console.log(` ${colors.cyan}npm test${colors.reset} - Run tests`);
|
|
315
|
+
console.log(` ${colors.cyan}npm run build${colors.reset} - Build for production\n`);
|
|
316
|
+
} else if (errorCount === 0) {
|
|
317
|
+
console.log(`${colors.yellow}โ Project is mostly configured with ${warningCount} warnings${colors.reset}\n`);
|
|
318
|
+
console.log(`Consider addressing the warnings above for best results.\n`);
|
|
319
|
+
} else {
|
|
320
|
+
console.log(`${colors.red}โ Project has ${errorCount} errors that need to be fixed${colors.reset}\n`);
|
|
321
|
+
console.log(`Fix the errors above before continuing.\n`);
|
|
322
|
+
console.log(`Quick fixes:`);
|
|
323
|
+
console.log(` ${colors.cyan}npm run setup${colors.reset} - Run interactive setup wizard`);
|
|
324
|
+
console.log(` ${colors.cyan}npm install${colors.reset} - Install missing dependencies\n`);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
process.exit(errorCount > 0 ? 1 : 0);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Main validation
|
|
331
|
+
console.clear();
|
|
332
|
+
console.log(`${colors.bright}${colors.cyan}๐ SvelteKit Boilerplate - Setup Validation${colors.reset}\n`);
|
|
333
|
+
|
|
334
|
+
validatePackageJson();
|
|
335
|
+
validateFiles();
|
|
336
|
+
validateEnvironment();
|
|
337
|
+
validateFirebase();
|
|
338
|
+
validateAppConfig();
|
|
339
|
+
validateBuild();
|
|
340
|
+
validateTests();
|
|
341
|
+
displaySummary();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"sourceMap": true,
|
|
9
|
+
"outDir": "lib",
|
|
10
|
+
"rootDir": "src",
|
|
11
|
+
"strict": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"isolatedModules": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*.ts"],
|
|
19
|
+
"exclude": ["node_modules", "lib"]
|
|
20
|
+
}
|