@avleon/cli 0.0.47 → 0.4.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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.d.ts +2 -0
  3. package/dist/bin.js +10 -0
  4. package/dist/commands/build.d.ts +11 -0
  5. package/dist/commands/build.js +65 -0
  6. package/dist/commands/doctor.d.ts +10 -0
  7. package/dist/commands/doctor.js +96 -0
  8. package/dist/commands/new.d.ts +19 -0
  9. package/dist/commands/new.js +306 -0
  10. package/dist/commands/route-list.d.ts +19 -0
  11. package/dist/commands/route-list.js +160 -0
  12. package/dist/commands/serve.d.ts +17 -0
  13. package/dist/commands/serve.js +238 -0
  14. package/dist/commands/start.d.ts +10 -0
  15. package/dist/commands/start.js +43 -0
  16. package/dist/compiler.d.ts +24 -0
  17. package/dist/compiler.js +83 -0
  18. package/dist/errors.d.ts +8 -0
  19. package/dist/errors.js +16 -0
  20. package/dist/generators/make.d.ts +24 -0
  21. package/dist/generators/make.js +157 -0
  22. package/dist/index.d.ts +17 -0
  23. package/dist/index.js +40 -15
  24. package/dist/program.d.ts +22 -0
  25. package/dist/program.js +178 -0
  26. package/dist/utils/entry.d.ts +15 -0
  27. package/dist/utils/entry.js +55 -0
  28. package/dist/utils/env-types.d.ts +8 -0
  29. package/dist/utils/env-types.js +19 -0
  30. package/dist/utils/log.d.ts +25 -0
  31. package/dist/utils/log.js +39 -0
  32. package/dist/utils/names.d.ts +27 -0
  33. package/dist/utils/names.js +58 -0
  34. package/dist/utils/process.d.ts +18 -0
  35. package/dist/utils/process.js +84 -0
  36. package/dist/utils/project.d.ts +17 -0
  37. package/dist/utils/project.js +91 -0
  38. package/dist/utils/stubs.d.ts +15 -0
  39. package/dist/utils/stubs.js +52 -0
  40. package/dist/utils/tsconfig.d.ts +13 -0
  41. package/dist/utils/tsconfig.js +102 -0
  42. package/package.json +28 -27
  43. package/readme.md +50 -11
  44. package/stubs/config/config.stub +9 -0
  45. package/stubs/controllers/basic-controller.stub +3 -3
  46. package/stubs/controllers/resource-controller.stub +45 -0
  47. package/stubs/controllers/rest-controller.stub +2 -2
  48. package/stubs/dtos/dto.stub +11 -0
  49. package/stubs/middlewares/middleware.stub +9 -0
  50. package/stubs/models/basic-model.stub +2 -2
  51. package/stubs/models/entity-model.stub +6 -8
  52. package/stubs/{app → project}/app-minimal.stub +1 -1
  53. package/stubs/{app/app-controller.stub → project/app.stub} +2 -7
  54. package/stubs/project/env.stub +3 -0
  55. package/stubs/project/gitignore.stub +5 -0
  56. package/stubs/project/home.controller.spec.stub +19 -0
  57. package/stubs/project/home.controller.stub +12 -0
  58. package/stubs/project/home.service.stub +8 -0
  59. package/stubs/{config.stub → project/openapi.config.stub} +4 -4
  60. package/stubs/project/readme.stub +26 -0
  61. package/stubs/{serve.stub → project/serve.stub} +1 -1
  62. package/stubs/project/tsconfig.build.stub +4 -0
  63. package/stubs/project/tsconfig.stub +18 -0
  64. package/stubs/project/vitest-e2e.config.stub +10 -0
  65. package/stubs/project/vitest.config.stub +17 -0
  66. package/stubs/services/basic-service.stub +1 -1
  67. package/stubs/services/orm-rest-service.stub +15 -14
  68. package/stubs/services/rest-service.stub +9 -9
  69. package/dist/av-cli.js +0 -60
  70. package/dist/avcli.js +0 -26
  71. package/dist/cli.interface.js +0 -2
  72. package/dist/cli.js +0 -332
  73. package/dist/commands.js +0 -63
  74. package/dist/controller.js +0 -96
  75. package/dist/create.js +0 -512
  76. package/dist/helpers/file-helper.js +0 -30
  77. package/dist/helpers/path-helper.js +0 -36
  78. package/dist/paths.js +0 -32
  79. package/dist/scripts/serve.js +0 -290
  80. package/dist/serve.js +0 -311
  81. package/dist/service.js +0 -69
  82. package/stubs/controllers/orm-rest-controller.stub +0 -45
package/dist/create.js DELETED
@@ -1,512 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.createApplication = createApplication;
40
- const fs_extra_1 = __importDefault(require("fs-extra"));
41
- const paths_1 = require("./paths");
42
- const prettier = __importStar(require("prettier"));
43
- const path_1 = __importDefault(require("path"));
44
- const os_1 = __importDefault(require("os"));
45
- const inquirer_1 = __importDefault(require("inquirer"));
46
- const child_process_1 = require("child_process");
47
- const lodash_1 = require("lodash");
48
- // ─── Colors ───────────────────────────────────────────────────────────────────
49
- const C = {
50
- reset: '\x1b[0m',
51
- dim: '\x1b[90m',
52
- bold: '\x1b[1m',
53
- cyan: '\x1b[36m',
54
- green: '\x1b[32m',
55
- yellow: '\x1b[33m',
56
- red: '\x1b[31m',
57
- white: '\x1b[37m',
58
- };
59
- const icon = {
60
- success: `${C.green}✔${C.reset}`,
61
- error: `${C.red}✖${C.reset}`,
62
- warn: `${C.yellow}⚠${C.reset}`,
63
- arrow: `${C.dim}→${C.reset}`,
64
- };
65
- function step(label, detail) {
66
- const pad = label.padEnd(30, ' ');
67
- console.log(` ${icon.arrow} ${C.white}${pad}${C.reset}${detail ? C.dim + detail + C.reset : ''}`);
68
- }
69
- function success(msg) {
70
- console.log(` ${icon.success} ${C.green}${msg}${C.reset}`);
71
- }
72
- function fail(msg) {
73
- console.log(` ${icon.error} ${C.red}${msg}${C.reset}`);
74
- }
75
- function section(title) {
76
- console.log(`\n${C.bold}${C.cyan} ${title}${C.reset}`);
77
- console.log(` ${'─'.repeat(40)}`);
78
- }
79
- // ─── Version resolver ─────────────────────────────────────────────────────────
80
- function resolveDepVersion(pkgName, fallback = 'latest') {
81
- try {
82
- const pkgJsonPath = require.resolve(`${pkgName}/package.json`);
83
- const pkg = JSON.parse(fs_extra_1.default.readFileSync(pkgJsonPath, 'utf8'));
84
- return `^${pkg.version}`;
85
- }
86
- catch {
87
- return fallback;
88
- }
89
- }
90
- function getAvleonVersions() {
91
- try {
92
- // Read CLI's own package.json (this file lives inside @avleon/cli)
93
- const cliPkgPath = path_1.default.resolve(__dirname, '../../package.json');
94
- const cliPkg = JSON.parse(fs_extra_1.default.readFileSync(cliPkgPath, 'utf8'));
95
- // Core version — resolve from installed node_modules
96
- const corePkgPath = require.resolve('@avleon/core/package.json');
97
- const corePkg = JSON.parse(fs_extra_1.default.readFileSync(corePkgPath, 'utf8'));
98
- return {
99
- core: `^${corePkg.version}`,
100
- cli: `^${cliPkg.version}`,
101
- };
102
- }
103
- catch {
104
- return { core: 'latest', cli: 'latest' };
105
- }
106
- }
107
- // ─── Banner ───────────────────────────────────────────────────────────────────
108
- function banner(fname) {
109
- const { core } = getAvleonVersions();
110
- console.clear();
111
- console.log();
112
- console.log(`${C.bold}${C.cyan} ╔═══════════════════════════════════════╗${C.reset}`);
113
- console.log(`${C.bold}${C.cyan} ║ AVLEON APPLICATION CLI ║${C.reset}`);
114
- console.log(`${C.bold}${C.cyan} ╚═══════════════════════════════════════╝${C.reset}`);
115
- console.log();
116
- console.log(` ${C.dim}Creating project :${C.reset} ${C.bold}${C.white}${fname}${C.reset}`);
117
- console.log(` ${C.dim}Avleon version :${C.reset} ${C.bold}${C.cyan}${core}${C.reset}`);
118
- console.log();
119
- }
120
- // ─── Shell ────────────────────────────────────────────────────────────────────
121
- const getShell = () => os_1.default.platform() === 'win32'
122
- ? process.env.ComSpec || 'cmd.exe'
123
- : process.env.SHELL || '/bin/sh';
124
- // ─── Prompts ──────────────────────────────────────────────────────────────────
125
- async function askForPackageManager() {
126
- const { packageManager } = await inquirer_1.default.prompt([
127
- {
128
- type: 'list',
129
- name: 'packageManager',
130
- message: 'Package manager:',
131
- choices: [
132
- { name: 'npm', value: 'npm' },
133
- { name: 'yarn', value: 'yarn' },
134
- { name: 'pnpm (recommended)', value: 'pnpm' },
135
- ],
136
- default: 'npm',
137
- },
138
- ]);
139
- return packageManager;
140
- }
141
- async function askForFeatures() {
142
- const { features } = await inquirer_1.default.prompt([
143
- {
144
- type: 'checkbox',
145
- name: 'features',
146
- message: 'Select features to include:',
147
- choices: [
148
- { name: 'OpenAPI / Swagger docs', value: 'openapi', checked: true },
149
- { name: 'CORS support', value: 'cors', checked: false },
150
- { name: 'TypeORM', value: 'typeorm', checked: false },
151
- { name: 'Knex', value: 'knex', checked: false },
152
- { name: 'Scalar UI (replaces Swagger UI)', value: 'scalar', checked: false },
153
- ],
154
- },
155
- ]);
156
- return features;
157
- }
158
- // ─── Installer ────────────────────────────────────────────────────────────────
159
- async function installDependencies(pm, cwd) {
160
- return new Promise((resolve, reject) => {
161
- const child = (0, child_process_1.spawn)(pm, ['install'], {
162
- cwd,
163
- shell: getShell(),
164
- stdio: 'inherit',
165
- });
166
- child.on('exit', (code) => {
167
- code === 0
168
- ? resolve()
169
- : reject(new Error(`Install failed with exit code ${code}`));
170
- });
171
- child.on('error', reject);
172
- });
173
- }
174
- // ─── Format helper ────────────────────────────────────────────────────────────
175
- async function fmt(source, parser = 'typescript') {
176
- return prettier.format(source, {
177
- singleQuote: true,
178
- singleAttributePerLine: true,
179
- parser,
180
- });
181
- }
182
- // ─── File writer ──────────────────────────────────────────────────────────────
183
- async function writeFile(filePath, content, label) {
184
- await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
185
- await fs_extra_1.default.writeFile(filePath, content);
186
- if (label)
187
- step(label, path_1.default.relative(process.cwd(), filePath));
188
- }
189
- // ─── Templates ────────────────────────────────────────────────────────────────
190
- function homeServiceTemplate() {
191
- return `
192
- import { AppService } from '@avleon/core';
193
-
194
- @AppService
195
- export class HomeService {
196
- sayHello() {
197
- return { message: 'Hello World!' };
198
- }
199
- }
200
- `;
201
- }
202
- function homeControllerTemplate() {
203
- return `
204
- import { ApiController, Get } from '@avleon/core';
205
- import { HomeService } from '../services/home.service';
206
-
207
- @ApiController('/')
208
- export class HomeController {
209
- constructor(private readonly homeService: HomeService) {}
210
-
211
- @Get()
212
- sayHello() {
213
- return this.homeService.sayHello();
214
- }
215
- }
216
- `;
217
- }
218
- function homeControllerTestTemplate() {
219
- return `
220
- import { AvleonTest } from '@avleon/core';
221
- import { HomeController } from './home.controller';
222
-
223
- describe('HomeController', () => {
224
- let controller!: HomeController;
225
-
226
- beforeAll(() => {
227
- controller = AvleonTest.getController(HomeController);
228
- });
229
-
230
- it('should be defined', () => {
231
- expect(controller).toBeDefined();
232
- });
233
-
234
- it('should have sayHello method', () => {
235
- expect(typeof controller.sayHello).toBe('function');
236
- });
237
-
238
- it('should return hello message', () => {
239
- expect(controller.sayHello()).toEqual({ message: 'Hello World!' });
240
- });
241
- });
242
- `;
243
- }
244
- function openApiConfigTemplate(fname, useScalar) {
245
- return `
246
- import { AppConfig, AvleonConfig, Environment, OpenApiUiOptions } from '@avleon/core';
247
-
248
- @AppConfig
249
- export class OpenApiConfig extends AvleonConfig<OpenApiUiOptions> {
250
- config(env: Environment): OpenApiUiOptions {
251
- return {
252
- info: {
253
- title: '${(0, lodash_1.capitalize)(fname)} API',
254
- version: '0.0.1',
255
- description: 'API documentation for ${(0, lodash_1.capitalize)(fname)}',
256
- },
257
- ${useScalar ? "provider: 'scalar'," : ''}
258
- routePrefix: '/docs',
259
- };
260
- }
261
- }
262
- `;
263
- }
264
- function appTemplate(features) {
265
- const hasOpenApi = features.includes('openapi');
266
- const hasCors = features.includes('cors');
267
- const hasTypeorm = features.includes('typeorm');
268
- const hasKnex = features.includes('knex');
269
- const imports = [`import { Avleon } from '@avleon/core';`];
270
- imports.push(`import { HomeController } from './controllers/home.controller';`);
271
- if (hasOpenApi) {
272
- imports.push(`import { OpenApiConfig } from './config/openapi.config';`);
273
- }
274
- const body = [`const app = Avleon.createApplication();`, ''];
275
- if (hasCors) {
276
- body.push(`app.useCors({ origin: '*' });`);
277
- }
278
- if (hasOpenApi) {
279
- body.push(`if (app.isDevelopment()) {`);
280
- body.push(` app.useOpenApi(OpenApiConfig);`);
281
- body.push(`}`);
282
- body.push('');
283
- }
284
- if (hasTypeorm) {
285
- body.push(`// TODO: pass your TypeORM DataSourceOptions (or an @AppConfig class)`);
286
- body.push(`// await app.useTypeORM({ type: 'postgres', url: process.env.DATABASE_URL, entities: [] });`);
287
- body.push('');
288
- }
289
- if (hasKnex) {
290
- body.push(`// TODO: pass your Knex config (or an @AppConfig class)`);
291
- body.push(`// await app.useKnex({ client: 'pg', connection: process.env.DATABASE_URL });`);
292
- body.push('');
293
- }
294
- body.push(`app.useControllers([HomeController]);`);
295
- body.push('');
296
- body.push(`export default app;`);
297
- return `${imports.join('\n')}\n\n${body.join('\n')}\n`;
298
- }
299
- function serveTemplate() {
300
- return `
301
- import { Environment, inject } from '@avleon/core';
302
- import app from './app';
303
-
304
- async function start() {
305
- const env = inject(Environment);
306
- const port = env.get<number>('PORT') || 4000;
307
- await app.run(port);
308
- }
309
-
310
- start();
311
- `;
312
- }
313
- function packageJsonTemplate(fname, features) {
314
- // ✅ Always resolve current installed versions at generation time
315
- const { core, cli } = getAvleonVersions();
316
- const deps = {
317
- '@avleon/core': core,
318
- '@avleon/cli': cli,
319
- 'class-transformer': resolveDepVersion('class-transformer', '^0.5.1'),
320
- 'class-validator': resolveDepVersion('class-validator', '^0.14.1'),
321
- 'rimraf': resolveDepVersion('rimraf', '^6.0.1'),
322
- 'reflect-metadata': resolveDepVersion('reflect-metadata', '^0.2.2'),
323
- };
324
- if (features.includes('cors')) {
325
- deps['@fastify/cors'] = resolveDepVersion('@fastify/cors', '^10.0.0');
326
- }
327
- if (features.includes('typeorm')) {
328
- deps['typeorm'] = resolveDepVersion('typeorm', '^0.3.20');
329
- deps['pg'] = resolveDepVersion('pg', '^8.11.0');
330
- }
331
- if (features.includes('knex')) {
332
- deps['knex'] = resolveDepVersion('knex', '^3.1.0');
333
- deps['pg'] = resolveDepVersion('pg', '^8.11.0');
334
- }
335
- if (features.includes('scalar')) {
336
- deps['@scalar/fastify-api-reference'] = resolveDepVersion('@scalar/fastify-api-reference', '^1.0.0');
337
- }
338
- const devDeps = {
339
- '@types/jest': resolveDepVersion('@types/jest', '^29.5.14'),
340
- '@types/node': resolveDepVersion('@types/node', '^24.0.3'),
341
- 'jest': resolveDepVersion('jest', '^29.7.0'),
342
- 'ts-jest': resolveDepVersion('ts-jest', '^29.2.6'),
343
- 'typescript': resolveDepVersion('typescript', '^5.7.2'),
344
- };
345
- return JSON.stringify({
346
- name: (0, lodash_1.kebabCase)(fname),
347
- version: '0.0.1',
348
- description: `${(0, lodash_1.capitalize)(fname)} API built with Avleon`,
349
- main: 'dist/serve.js',
350
- scripts: {
351
- 'start:dev': 'avleon serve',
352
- 'clean': 'rimraf ./dist',
353
- 'build': 'npm run clean && tsc --project ./tsconfig.build.json',
354
- 'start': 'node ./dist/serve.js',
355
- 'test': 'jest',
356
- 'test:watch': 'jest --watch',
357
- 'test:cov': 'jest --coverage',
358
- 'test:e2e': 'jest --config ./test/e2e-spec.json',
359
- },
360
- keywords: ['avleon', 'nodejs', 'typescript'],
361
- license: 'ISC',
362
- dependencies: deps,
363
- devDependencies: devDeps,
364
- jest: {
365
- preset: 'ts-jest',
366
- rootDir: 'src',
367
- testRegex: '.*.spec.ts$',
368
- collectCoverageFrom: ['**/*.(t|j)s'],
369
- coverageDirectory: '../coverage',
370
- testEnvironment: 'node',
371
- },
372
- }, null, 2);
373
- }
374
- function tsconfigTemplate() {
375
- return JSON.stringify({
376
- compilerOptions: {
377
- target: 'ES2017',
378
- module: 'CommonJS',
379
- moduleResolution: 'node',
380
- experimentalDecorators: true,
381
- emitDecoratorMetadata: true,
382
- outDir: './dist',
383
- esModuleInterop: true,
384
- allowSyntheticDefaultImports: true,
385
- forceConsistentCasingInFileNames: true,
386
- skipLibCheck: true,
387
- strict: false,
388
- },
389
- include: ['src/**/*'],
390
- exclude: ['node_modules', 'dist'],
391
- }, null, 2);
392
- }
393
- function tsconfigBuildTemplate() {
394
- return JSON.stringify({
395
- extends: './tsconfig.json',
396
- exclude: ['node_modules', 'coverage', 'test', 'dist', '**/*spec.ts'],
397
- }, null, 2);
398
- }
399
- function e2eConfigTemplate() {
400
- return JSON.stringify({
401
- moduleFileExtensions: ['js', 'json', 'ts'],
402
- rootDir: '.',
403
- testEnvironment: 'node',
404
- testRegex: '.e2e-spec.ts$',
405
- transform: { '^.+\\.(t|j)s$': 'ts-jest' },
406
- }, null, 2);
407
- }
408
- function gitignoreTemplate() {
409
- return `node_modules/\ndist/\n.env\n.env.local\ncoverage/\n`;
410
- }
411
- function envTemplate() {
412
- return `NODE_ENV=development\nPORT=4000\n`;
413
- }
414
- function readmeTemplate(fname, pm) {
415
- const runCmd = pm === 'npm' ? 'npm run start:dev' : `${pm} start:dev`;
416
- return `# ${(0, lodash_1.capitalize)(fname)}
417
-
418
- Built with [Avleon](https://github.com/xtareq/avleon).
419
-
420
- ## Getting Started
421
-
422
- \`\`\`bash
423
- ${runCmd}
424
- \`\`\`
425
-
426
- ## Scripts
427
-
428
- | Script | Description |
429
- |--------|-------------|
430
- | \`start:dev\` | Start development server with hot reload |
431
- | \`build\` | Compile TypeScript to JavaScript |
432
- | \`start\` | Start production server |
433
- | \`test\` | Run unit tests |
434
-
435
- ## Project Structure
436
-
437
- \`\`\`
438
- src/
439
- ├── controllers/ # Route controllers
440
- ├── services/ # Business logic
441
- ├── config/ # App configuration
442
- ├── app.ts # App setup
443
- └── serve.ts # Entry point
444
- \`\`\`
445
- `;
446
- }
447
- // ─── Main ─────────────────────────────────────────────────────────────────────
448
- async function createApplication(fname, flags = {}) {
449
- const appPaths = (0, paths_1.appPaths)(fname);
450
- banner(fname);
451
- // ── Prompts ───────────────────────────────────────────────────────────────
452
- const pm = await askForPackageManager();
453
- const features = await askForFeatures();
454
- const useScalar = features.includes('scalar');
455
- // ── Directories ───────────────────────────────────────────────────────────
456
- section('Scaffolding project structure');
457
- const dirs = [
458
- appPaths.root + '/src',
459
- appPaths.root + '/src/controllers',
460
- appPaths.root + '/src/config',
461
- appPaths.root + '/src/services',
462
- appPaths.root + '/test',
463
- appPaths.root + '/public',
464
- ];
465
- for (const dir of dirs) {
466
- await fs_extra_1.default.ensureDir(dir);
467
- step('Created directory', path_1.default.relative(process.cwd(), dir));
468
- }
469
- // ── Source files ──────────────────────────────────────────────────────────
470
- section('Generating source files');
471
- await writeFile(path_1.default.join(appPaths.services, 'home.service.ts'), await fmt(homeServiceTemplate()), 'HomeService');
472
- await writeFile(path_1.default.join(appPaths.controllers, 'home.controller.ts'), await fmt(homeControllerTemplate()), 'HomeController');
473
- await writeFile(path_1.default.join(appPaths.controllers, 'home.controller.spec.ts'), await fmt(homeControllerTestTemplate()), 'HomeController spec');
474
- if (features.includes('openapi')) {
475
- await writeFile(path_1.default.join(appPaths.configs, 'openapi.config.ts'), await fmt(openApiConfigTemplate(fname, useScalar)), 'OpenApiConfig');
476
- }
477
- await writeFile(path_1.default.join(appPaths.src, 'app.ts'), await fmt(appTemplate(features)), 'app.ts');
478
- await writeFile(path_1.default.join(appPaths.src, 'serve.ts'), await fmt(serveTemplate()), 'serve.ts');
479
- // ── Config files ──────────────────────────────────────────────────────────
480
- section('Generating config files');
481
- await writeFile(path_1.default.join(appPaths.root, 'package.json'), await fmt(packageJsonTemplate(fname, features), 'json'), 'package.json');
482
- await writeFile(path_1.default.join(appPaths.root, 'tsconfig.json'), await fmt(tsconfigTemplate(), 'json'), 'tsconfig.json');
483
- await writeFile(path_1.default.join(appPaths.root, 'tsconfig.build.json'), await fmt(tsconfigBuildTemplate(), 'json'), 'tsconfig.build.json');
484
- await writeFile(path_1.default.join(appPaths.root, 'test/e2e-spec.json'), await fmt(e2eConfigTemplate(), 'json'), 'e2e-spec.json');
485
- await writeFile(path_1.default.join(appPaths.root, '.gitignore'), gitignoreTemplate(), '.gitignore');
486
- await writeFile(path_1.default.join(appPaths.root, '.env'), envTemplate(), '.env');
487
- await writeFile(path_1.default.join(appPaths.root, 'README.md'), readmeTemplate(fname, pm), 'README.md');
488
- // ── Install ───────────────────────────────────────────────────────────────
489
- section('Installing dependencies');
490
- try {
491
- await installDependencies(pm, appPaths.root);
492
- success('Dependencies installed');
493
- }
494
- catch (error) {
495
- fail(`Installation failed: ${error instanceof Error ? error.message : error}`);
496
- console.log(`\n ${C.yellow}Install manually:${C.reset}`);
497
- console.log(` ${C.dim}cd ${fname} && ${pm} install${C.reset}\n`);
498
- }
499
- // ── Done ──────────────────────────────────────────────────────────────────
500
- const runCmd = pm === 'npm' ? 'npm run start:dev' : `${pm} start:dev`;
501
- console.log();
502
- console.log(`${C.bold}${C.green} ✔ Project created successfully!${C.reset}`);
503
- console.log();
504
- console.log(` ${C.dim}Next steps:${C.reset}`);
505
- console.log(` ${C.cyan} cd ${fname}${C.reset}`);
506
- console.log(` ${C.cyan} ${runCmd}${C.reset}`);
507
- if (features.includes('openapi')) {
508
- console.log();
509
- console.log(` ${C.dim}API docs:${C.reset} ${C.white}http://localhost:4000/docs${C.reset}`);
510
- }
511
- console.log();
512
- }
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fh = void 0;
4
- exports.getLastPart = getLastPart;
5
- exports.getFilePathWithoutName = getFilePathWithoutName;
6
- exports.resolveNames = resolveNames;
7
- const filenameFromPath = (fpath) => fpath.split('/')[fpath.split('/').length - 1];
8
- function getLastPart(str, separator) {
9
- if (!str.includes(separator))
10
- return str;
11
- const parts = str.split(separator);
12
- return parts.at(-1);
13
- }
14
- function getFilePathWithoutName(fpath) {
15
- const parts = fpath.split("/");
16
- if (parts.length < 2) {
17
- return "";
18
- }
19
- parts.splice(parts.length - 1, 1);
20
- return parts.join("/");
21
- }
22
- function resolveNames(name, exclude) {
23
- const parsedName = name.replace(exclude, '');
24
- return {
25
- className: parsedName.charAt(0).toUpperCase() + name.slice(1),
26
- fileName: parsedName.toLowerCase(),
27
- varName: parsedName.toLowerCase(),
28
- };
29
- }
30
- exports.fh = { filenameFromPath };
@@ -1,36 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.pathHelper = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = require("fs");
9
- /**
10
- * Resolve the package root (the directory holding `stubs/`) by walking up from
11
- * this file. Compiled output lives under `dist/`, at a depth that differs per
12
- * file, so anchoring on a fixed number of `..` segments is not reliable.
13
- */
14
- function packageRoot() {
15
- let dir = __dirname;
16
- for (let i = 0; i < 5; i++) {
17
- if ((0, fs_1.existsSync)(path_1.default.join(dir, 'stubs')))
18
- return dir;
19
- const parent = path_1.default.dirname(dir);
20
- if (parent === dir)
21
- break;
22
- dir = parent;
23
- }
24
- return path_1.default.join(__dirname, '../..');
25
- }
26
- exports.pathHelper = {
27
- appSoucePath(p) {
28
- return path_1.default.join(process.cwd(), p ? './src/' + p : './src/');
29
- },
30
- appTestPath(p) {
31
- return path_1.default.join(process.cwd(), p ? './test/' + p : './test/');
32
- },
33
- stubPath(p) {
34
- return path_1.default.join(packageRoot(), 'stubs', p ?? '');
35
- },
36
- };
package/dist/paths.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.appPaths = exports.appPathsMinimal = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- const appPathsMinimal = (rootPath) => {
9
- const root = rootPath ? rootPath : node_path_1.default.join(process.cwd(), "./");
10
- return {
11
- root: root,
12
- src: node_path_1.default.join(root, "src"),
13
- public: node_path_1.default.join(root, "public"),
14
- test: node_path_1.default.join(root, "test"),
15
- };
16
- };
17
- exports.appPathsMinimal = appPathsMinimal;
18
- const appPaths = (rootPath) => {
19
- const root = rootPath ? rootPath : node_path_1.default.join(process.cwd(), "./");
20
- return {
21
- root: root,
22
- src: node_path_1.default.join(root, "src"),
23
- public: node_path_1.default.join(root, "public"),
24
- test: node_path_1.default.join(root, "test"),
25
- controllers: node_path_1.default.join(root, "src/controllers"),
26
- models: node_path_1.default.join(root, "src/models"),
27
- services: node_path_1.default.join(root, "src/services"),
28
- dtos: node_path_1.default.join(root, "src/dtos"),
29
- configs: node_path_1.default.join(root, "src/config")
30
- };
31
- };
32
- exports.appPaths = appPaths;