katax-cli 0.1.1 → 1.0.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.
- package/README.md +0 -0
- package/dist/commands/init.js +71 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
Binary file
|
package/dist/commands/init.js
CHANGED
|
@@ -371,8 +371,8 @@ async function createProjectStructure(projectPath, config, generateJwtSecrets) {
|
|
|
371
371
|
if (config.database !== 'none') {
|
|
372
372
|
dirs.push('src/database');
|
|
373
373
|
}
|
|
374
|
-
// Add default
|
|
375
|
-
dirs.push('src/api/
|
|
374
|
+
// Add default hello endpoint
|
|
375
|
+
dirs.push('src/api/hello');
|
|
376
376
|
for (const dir of dirs) {
|
|
377
377
|
await ensureDir(path.join(projectPath, dir));
|
|
378
378
|
}
|
|
@@ -427,20 +427,24 @@ async function createProjectStructure(projectPath, config, generateJwtSecrets) {
|
|
|
427
427
|
}
|
|
428
428
|
};
|
|
429
429
|
await writeFile(path.join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
430
|
-
// Create tsconfig.json
|
|
430
|
+
// Create tsconfig.json - ESM optimized for Linux/Ubuntu deployment
|
|
431
431
|
const tsConfig = {
|
|
432
432
|
compilerOptions: {
|
|
433
|
-
target: '
|
|
434
|
-
module: '
|
|
433
|
+
target: 'ES2022',
|
|
434
|
+
module: 'ES2022',
|
|
435
|
+
lib: ['ES2022'],
|
|
436
|
+
moduleResolution: 'node',
|
|
435
437
|
sourceMap: true,
|
|
436
438
|
outDir: './dist',
|
|
437
|
-
|
|
439
|
+
rootDir: './src',
|
|
438
440
|
esModuleInterop: true,
|
|
439
441
|
forceConsistentCasingInFileNames: true,
|
|
440
442
|
strict: true,
|
|
441
|
-
skipLibCheck: true
|
|
443
|
+
skipLibCheck: true,
|
|
444
|
+
resolveJsonModule: true,
|
|
445
|
+
declaration: true
|
|
442
446
|
},
|
|
443
|
-
include: ['src'],
|
|
447
|
+
include: ['src/**/*'],
|
|
444
448
|
exclude: ['node_modules', 'dist']
|
|
445
449
|
};
|
|
446
450
|
await writeFile(path.join(projectPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2));
|
|
@@ -527,6 +531,27 @@ coverage/
|
|
|
527
531
|
.vscode/
|
|
528
532
|
`;
|
|
529
533
|
await writeFile(path.join(projectPath, '.gitignore'), gitignoreContent);
|
|
534
|
+
// Create .gitattributes for consistent line endings across Windows/Linux
|
|
535
|
+
const gitattributesContent = `# Auto normalize line endings to LF on checkout (critical for Ubuntu deployment)
|
|
536
|
+
* text=auto eol=lf
|
|
537
|
+
|
|
538
|
+
# Explicit file types
|
|
539
|
+
*.ts text eol=lf
|
|
540
|
+
*.js text eol=lf
|
|
541
|
+
*.json text eol=lf
|
|
542
|
+
*.md text eol=lf
|
|
543
|
+
*.yml text eol=lf
|
|
544
|
+
*.yaml text eol=lf
|
|
545
|
+
|
|
546
|
+
# Binaries
|
|
547
|
+
*.png binary
|
|
548
|
+
*.jpg binary
|
|
549
|
+
*.jpeg binary
|
|
550
|
+
*.gif binary
|
|
551
|
+
*.ico binary
|
|
552
|
+
*.pdf binary
|
|
553
|
+
`;
|
|
554
|
+
await writeFile(path.join(projectPath, '.gitattributes'), gitattributesContent);
|
|
530
555
|
// Create index.ts
|
|
531
556
|
const indexContent = `import app from './app.js';
|
|
532
557
|
import dotenv from 'dotenv';
|
|
@@ -583,7 +608,7 @@ export default app;
|
|
|
583
608
|
await writeFile(path.join(projectPath, 'src/app.ts'), appContent);
|
|
584
609
|
// Create routes.ts
|
|
585
610
|
const routesContent = `import { Router } from 'express';
|
|
586
|
-
import
|
|
611
|
+
import helloRouter from './hello/hello.routes.js';
|
|
587
612
|
import { healthCheckHandler } from './health/health.handler.js';
|
|
588
613
|
|
|
589
614
|
const router = Router();
|
|
@@ -592,7 +617,7 @@ const router = Router();
|
|
|
592
617
|
router.get('/health', healthCheckHandler);
|
|
593
618
|
|
|
594
619
|
// Example endpoint
|
|
595
|
-
router.use('/
|
|
620
|
+
router.use('/hello', helloRouter);
|
|
596
621
|
|
|
597
622
|
export default router;
|
|
598
623
|
`;
|
|
@@ -1186,86 +1211,86 @@ katax generate crud products
|
|
|
1186
1211
|
MIT
|
|
1187
1212
|
`;
|
|
1188
1213
|
await writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
|
1189
|
-
// Create default
|
|
1190
|
-
await
|
|
1214
|
+
// Create default hello endpoint
|
|
1215
|
+
await createHelloEndpoint(projectPath, config);
|
|
1191
1216
|
}
|
|
1192
|
-
async function
|
|
1193
|
-
const
|
|
1194
|
-
//
|
|
1217
|
+
async function createHelloEndpoint(projectPath, config) {
|
|
1218
|
+
const helloPath = path.join(projectPath, 'src/api/hello');
|
|
1219
|
+
// hello.controller.ts
|
|
1195
1220
|
const controllerContent = [
|
|
1196
1221
|
"import { ControllerResult, createSuccessResult, createErrorResult } from '../../shared/api.utils.js';",
|
|
1197
|
-
"import {
|
|
1222
|
+
"import { HelloQuery } from './hello.validator.js';",
|
|
1198
1223
|
"import { logger } from '../../shared/logger.utils.js';",
|
|
1199
1224
|
"",
|
|
1200
1225
|
"/**",
|
|
1201
|
-
" * Get
|
|
1226
|
+
" * Get hello message",
|
|
1202
1227
|
" */",
|
|
1203
|
-
"export async function
|
|
1228
|
+
"export async function getHello(queryData: HelloQuery): Promise<ControllerResult<{ message: string; timestamp: string }>> {",
|
|
1204
1229
|
" try {",
|
|
1205
1230
|
" const name = queryData.name || 'World';",
|
|
1206
|
-
" logger.debug({ name }, 'Processing
|
|
1231
|
+
" logger.debug({ name }, 'Processing hello request');",
|
|
1207
1232
|
" ",
|
|
1208
1233
|
" return createSuccessResult(",
|
|
1209
|
-
" '
|
|
1234
|
+
" 'Hello endpoint working!',",
|
|
1210
1235
|
" {",
|
|
1211
|
-
" message: `
|
|
1236
|
+
" message: `Hello ${name}! Welcome to your API 🚀`,",
|
|
1212
1237
|
" timestamp: new Date().toISOString()",
|
|
1213
1238
|
" }",
|
|
1214
1239
|
" );",
|
|
1215
1240
|
" } catch (error) {",
|
|
1216
|
-
" logger.error({ err: error }, 'Error in
|
|
1241
|
+
" logger.error({ err: error }, 'Error in getHello controller');",
|
|
1217
1242
|
" return createErrorResult(",
|
|
1218
|
-
" 'Failed to get
|
|
1243
|
+
" 'Failed to get hello message',",
|
|
1219
1244
|
" error instanceof Error ? error.message : 'Unknown error',",
|
|
1220
1245
|
" 500",
|
|
1221
1246
|
" );",
|
|
1222
1247
|
" }",
|
|
1223
1248
|
"}"
|
|
1224
1249
|
].join('\n');
|
|
1225
|
-
await writeFile(path.join(
|
|
1226
|
-
//
|
|
1250
|
+
await writeFile(path.join(helloPath, 'hello.controller.ts'), controllerContent);
|
|
1251
|
+
// hello.handler.ts
|
|
1227
1252
|
const handlerContent = [
|
|
1228
1253
|
"import { Request, Response } from 'express';",
|
|
1229
|
-
"import {
|
|
1230
|
-
"import {
|
|
1254
|
+
"import { getHello } from './hello.controller.js';",
|
|
1255
|
+
"import { validateHelloQuery } from './hello.validator.js';",
|
|
1231
1256
|
"import { sendResponse } from '../../shared/api.utils.js';",
|
|
1232
1257
|
"",
|
|
1233
1258
|
"// ==================== HANDLERS ====================",
|
|
1234
1259
|
"",
|
|
1235
1260
|
"/**",
|
|
1236
|
-
" * Handler for GET /api/
|
|
1261
|
+
" * Handler for GET /api/hello",
|
|
1237
1262
|
" * Uses sendResponse utility for automatic validation and response handling",
|
|
1238
1263
|
" */",
|
|
1239
|
-
"export async function
|
|
1264
|
+
"export async function getHelloHandler(req: Request, res: Response): Promise<void> {",
|
|
1240
1265
|
" await sendResponse(",
|
|
1241
1266
|
" req,",
|
|
1242
1267
|
" res,",
|
|
1243
|
-
" // Validator returns Promise<ValidationResult<
|
|
1244
|
-
" () =>
|
|
1245
|
-
" // validData is automatically:
|
|
1246
|
-
" (validData) =>
|
|
1268
|
+
" // Validator returns Promise<ValidationResult<HelloQuery>>",
|
|
1269
|
+
" () => validateHelloQuery(req.query),",
|
|
1270
|
+
" // validData is automatically: HelloQuery (not any)",
|
|
1271
|
+
" (validData) => getHello(validData)",
|
|
1247
1272
|
" );",
|
|
1248
1273
|
"}"
|
|
1249
1274
|
].join('\n');
|
|
1250
|
-
await writeFile(path.join(
|
|
1251
|
-
//
|
|
1275
|
+
await writeFile(path.join(helloPath, 'hello.handler.ts'), handlerContent);
|
|
1276
|
+
// hello.routes.ts
|
|
1252
1277
|
const routesContent = [
|
|
1253
1278
|
"import { Router } from 'express';",
|
|
1254
|
-
"import {
|
|
1279
|
+
"import { getHelloHandler } from './hello.handler.js';",
|
|
1255
1280
|
"",
|
|
1256
1281
|
"const router = Router();",
|
|
1257
1282
|
"",
|
|
1258
1283
|
"// ==================== ROUTES ====================",
|
|
1259
1284
|
"",
|
|
1260
1285
|
"/**",
|
|
1261
|
-
" * @route GET /api/
|
|
1286
|
+
" * @route GET /api/hello",
|
|
1262
1287
|
" * @desc Example endpoint - returns a greeting message",
|
|
1263
1288
|
" */",
|
|
1264
|
-
"router.get('/',
|
|
1289
|
+
"router.get('/', getHelloHandler);",
|
|
1265
1290
|
"",
|
|
1266
1291
|
"export default router;"
|
|
1267
1292
|
].join('\n');
|
|
1268
|
-
await writeFile(path.join(
|
|
1293
|
+
await writeFile(path.join(helloPath, 'hello.routes.ts'), routesContent);
|
|
1269
1294
|
// Only create validator if katax-core is enabled
|
|
1270
1295
|
if (config.validation === 'katax-core') {
|
|
1271
1296
|
const validatorContent = [
|
|
@@ -1275,22 +1300,22 @@ async function createHolaEndpoint(projectPath, config) {
|
|
|
1275
1300
|
"// ==================== SCHEMAS ====================",
|
|
1276
1301
|
"",
|
|
1277
1302
|
"/**",
|
|
1278
|
-
" * Schema for
|
|
1303
|
+
" * Schema for hello query params",
|
|
1279
1304
|
" */",
|
|
1280
|
-
"export const
|
|
1305
|
+
"export const helloQuerySchema = k.object({",
|
|
1281
1306
|
" name: k.string().minLength(2).optional()",
|
|
1282
1307
|
"});",
|
|
1283
1308
|
"",
|
|
1284
1309
|
"/**",
|
|
1285
1310
|
" * Inferred TypeScript type from schema",
|
|
1286
1311
|
" */",
|
|
1287
|
-
"export type
|
|
1312
|
+
"export type HelloQuery = kataxInfer<typeof helloQuerySchema>;",
|
|
1288
1313
|
"",
|
|
1289
1314
|
"/**",
|
|
1290
|
-
" * Validate
|
|
1315
|
+
" * Validate hello query params",
|
|
1291
1316
|
" */",
|
|
1292
|
-
"export async function
|
|
1293
|
-
" const result =
|
|
1317
|
+
"export async function validateHelloQuery(data: unknown): Promise<ValidationResult<HelloQuery>> {",
|
|
1318
|
+
" const result = helloQuerySchema.safeParse(data);",
|
|
1294
1319
|
"",
|
|
1295
1320
|
" if (!result.success) {",
|
|
1296
1321
|
" const errors = result.issues.map(issue => ({",
|
|
@@ -1310,6 +1335,6 @@ async function createHolaEndpoint(projectPath, config) {
|
|
|
1310
1335
|
" };",
|
|
1311
1336
|
"}"
|
|
1312
1337
|
].join('\n');
|
|
1313
|
-
await writeFile(path.join(
|
|
1338
|
+
await writeFile(path.join(helloPath, 'hello.validator.ts'), validatorContent);
|
|
1314
1339
|
}
|
|
1315
1340
|
}
|