@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
@@ -0,0 +1,45 @@
1
+ import { ApiController, Get, Post, Put, Delete, Param, Query, Body, HttpExceptions } from '@avleon/core';
2
+ import { {ServiceClass} } from '{serviceImport}';
3
+
4
+ @ApiController('/{route}')
5
+ export class {ClassName} {
6
+ constructor(private readonly {serviceVar}: {ServiceClass}) {}
7
+
8
+ @Get()
9
+ async index(@Query() query?: any) {
10
+ if (query && query.page) {
11
+ return this.{serviceVar}.paginate(Number(query.page));
12
+ }
13
+ return this.{serviceVar}.findAll();
14
+ }
15
+
16
+ @Get('/:id')
17
+ async findOne(@Param('id') id: number) {
18
+ const {modelVar} = await this.{serviceVar}.findByPk(Number(id));
19
+ if (!{modelVar}) throw HttpExceptions.notFound('{Model} not found.');
20
+ return {modelVar};
21
+ }
22
+
23
+ @Post()
24
+ async create(@Body() body: any) {
25
+ return this.{serviceVar}.create(body);
26
+ }
27
+
28
+ @Put('/:id')
29
+ async update(@Param('id') id: number, @Body() updateBody: any) {
30
+ const {modelVar} = await this.{serviceVar}.findByPk(Number(id));
31
+ if (!{modelVar}) throw HttpExceptions.notFound('{Model} not found.');
32
+ const isUpdated = await this.{serviceVar}.update(Number(id), updateBody);
33
+ if (!isUpdated) throw HttpExceptions.internalError("Can't update {Model}");
34
+ return { message: 'Updated successfully' };
35
+ }
36
+
37
+ @Delete('/:id')
38
+ async delete(@Param('id') id: number) {
39
+ const {modelVar} = await this.{serviceVar}.findByPk(Number(id));
40
+ if (!{modelVar}) throw HttpExceptions.notFound('{Model} not found.');
41
+ const isDeleted = await this.{serviceVar}.delete(Number(id));
42
+ if (!isDeleted) throw HttpExceptions.internalError("Can't delete {Model}");
43
+ return { message: 'Deleted successfully' };
44
+ }
45
+ }
@@ -1,7 +1,7 @@
1
1
  import { ApiController, Get, Post, Put, Delete, Param, Query, Body } from '@avleon/core';
2
2
 
3
- @ApiController('/{controller}s')
4
- export class {Controller}Controller {
3
+ @ApiController('/{route}')
4
+ export class {ClassName} {
5
5
  @Get()
6
6
  async index(@Query() query?: any) {
7
7
  throw new Error('Method not implemented.');
@@ -0,0 +1,11 @@
1
+ import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
2
+
3
+ export class {ClassName} {
4
+ @IsString()
5
+ @IsNotEmpty()
6
+ name!: string;
7
+
8
+ @IsString()
9
+ @IsOptional()
10
+ description?: string;
11
+ }
@@ -0,0 +1,9 @@
1
+ import { AppMiddleware, AvleonMiddleware, IRequest, IResponse } from '@avleon/core';
2
+
3
+ @AppMiddleware
4
+ export class {ClassName} extends AvleonMiddleware {
5
+ async invoke(req: IRequest, res?: IResponse) {
6
+ // your logic goes here
7
+ return req;
8
+ }
9
+ }
@@ -1,4 +1,4 @@
1
1
  export class {Model} {
2
- id: number;
3
- name: string;
2
+ id!: number;
3
+ name!: string;
4
4
  }
@@ -1,18 +1,16 @@
1
1
  import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
2
2
 
3
- @Entity({ name: '{model}' })
3
+ @Entity({ name: '{table}' })
4
4
  export class {Model} {
5
5
  @PrimaryGeneratedColumn()
6
- id: number;
6
+ id!: number;
7
7
 
8
- // your fields
9
-
10
- // @Column()
11
- // name: string;
8
+ @Column()
9
+ name!: string;
12
10
 
13
11
  @CreateDateColumn()
14
- createdAt: Date;
12
+ createdAt!: Date;
15
13
 
16
14
  @UpdateDateColumn()
17
- updatedAt: Date;
15
+ updatedAt!: Date;
18
16
  }
@@ -2,6 +2,6 @@ import { Avleon } from '@avleon/core';
2
2
 
3
3
  const app = Avleon.createApplication();
4
4
 
5
- app.mapGet('/', () => 'Hello World!');
5
+ app.mapGet('/', () => ({ message: 'Hello World!' }));
6
6
 
7
7
  export default app;
@@ -1,13 +1,8 @@
1
1
  import { Avleon } from '@avleon/core';
2
- import { OpenApiConfig } from './config/openapi.config';
3
2
  import { HomeController } from './controllers/home.controller';
4
-
3
+ {Imports}
5
4
  const app = Avleon.createApplication();
6
-
7
- if (app.isDevelopment()) {
8
- app.useOpenApi(OpenApiConfig);
9
- }
10
-
5
+ {Setup}
11
6
  app.useControllers([HomeController]);
12
7
 
13
8
  export default app;
@@ -0,0 +1,3 @@
1
+ # Core treats an unset NODE_ENV as production.
2
+ NODE_ENV=development
3
+ PORT=4000
@@ -0,0 +1,5 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.local
5
+ coverage/
@@ -0,0 +1,19 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest';
2
+ import { AvleonTest } from '@avleon/core';
3
+ import { HomeController } from './home.controller';
4
+
5
+ describe('HomeController', () => {
6
+ let controller!: HomeController;
7
+
8
+ beforeAll(() => {
9
+ controller = AvleonTest.getController(HomeController);
10
+ });
11
+
12
+ it('should be defined', () => {
13
+ expect(controller).toBeDefined();
14
+ });
15
+
16
+ it('should return hello message', () => {
17
+ expect(controller.sayHello()).toEqual({ message: 'Hello World!' });
18
+ });
19
+ });
@@ -0,0 +1,12 @@
1
+ import { ApiController, Get } from '@avleon/core';
2
+ import { HomeService } from '../services/home.service';
3
+
4
+ @ApiController('/')
5
+ export class HomeController {
6
+ constructor(private readonly homeService: HomeService) {}
7
+
8
+ @Get()
9
+ sayHello() {
10
+ return this.homeService.sayHello();
11
+ }
12
+ }
@@ -0,0 +1,8 @@
1
+ import { AppService } from '@avleon/core';
2
+
3
+ @AppService
4
+ export class HomeService {
5
+ sayHello() {
6
+ return { message: 'Hello World!' };
7
+ }
8
+ }
@@ -5,10 +5,10 @@ export class OpenApiConfig extends AvleonConfig<OpenApiUiOptions> {
5
5
  config(env: Environment): OpenApiUiOptions {
6
6
  return {
7
7
  info: {
8
- title: 'My API',
9
- version: '1.0.0',
10
- description: 'API documentation',
11
- },
8
+ title: '{AppTitle} API',
9
+ version: '0.0.1',
10
+ description: 'API documentation for {AppTitle}',
11
+ },{Provider}
12
12
  routePrefix: '/docs',
13
13
  };
14
14
  }
@@ -0,0 +1,26 @@
1
+ # {AppTitle}
2
+
3
+ Built with [Avleon](https://github.com/avleonjs/avleon-core).
4
+
5
+ ## Getting Started
6
+
7
+ ```bash
8
+ {InstallCmd}
9
+ {DevCmd}
10
+ ```
11
+
12
+ ## Scripts
13
+
14
+ | Script | Description |
15
+ |--------|-------------|
16
+ | `start:dev` | Start the development server with reload (`avleon serve`) |
17
+ | `build` | Compile TypeScript to `dist/` (`avleon build`) |
18
+ | `start` | Run the compiled app in production (`avleon start`) |
19
+ {TestRow}
20
+ ## Project Structure
21
+
22
+ ```
23
+ src/
24
+ {Tree}├── app.ts # App setup
25
+ └── serve.ts # Entry point
26
+ ```
@@ -3,7 +3,7 @@ import app from './app';
3
3
 
4
4
  async function serve() {
5
5
  const env = inject(Environment);
6
- const port = env.get<number>('PORT') || 4000;
6
+ const port = Number(env.get('PORT')) || 4000;
7
7
  await app.run(port);
8
8
  }
9
9
 
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": ["node_modules", "coverage", "test", "dist", "**/*.spec.ts", "**/*.test.ts"]
4
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "CommonJS",
5
+ "moduleResolution": "node",
6
+ "experimentalDecorators": true,
7
+ "emitDecoratorMetadata": true,
8
+ "outDir": "./dist",
9
+ "esModuleInterop": true,
10
+ "allowSyntheticDefaultImports": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "skipLibCheck": true,
13
+ "sourceMap": true,
14
+ "strict": false
15
+ },
16
+ "include": ["avleon-env.d.ts", "src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }
@@ -0,0 +1,10 @@
1
+ import swc from 'unplugin-swc';
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ plugins: [swc.vite()],
6
+ test: {
7
+ environment: 'node',
8
+ include: ['test/**/*.e2e-spec.ts'],
9
+ },
10
+ });
@@ -0,0 +1,17 @@
1
+ import swc from 'unplugin-swc';
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ // SWC emits the decorator metadata that Avleon's dependency injection
6
+ // and validation rely on; Vitest's default transform (esbuild) does not.
7
+ plugins: [swc.vite()],
8
+ test: {
9
+ environment: 'node',
10
+ include: ['src/**/*.spec.ts'],
11
+ coverage: {
12
+ include: ['src/**/*.ts'],
13
+ exclude: ['src/**/*.spec.ts'],
14
+ reportsDirectory: 'coverage',
15
+ },
16
+ },
17
+ });
@@ -1,7 +1,7 @@
1
1
  import { AppService } from '@avleon/core';
2
2
 
3
3
  @AppService
4
- export class {Service}Service {
4
+ export class {ClassName} {
5
5
  sayHello() {
6
6
  return 'Hello World!';
7
7
  }
@@ -1,25 +1,26 @@
1
- import { AppService, InjectRepository } from '@avleon/core';
1
+ import { AppService } from '@avleon/core';
2
+ import { InjectRepository } from '@avleon/data';
2
3
  import { Repository } from 'typeorm';
3
- import { {Model} } from '../models/{model}';
4
+ import { {Model} } from '{modelImport}';
4
5
 
5
6
  @AppService
6
- export class {Service}Service {
7
+ export class {ClassName} {
7
8
  constructor(
8
9
  @InjectRepository({Model})
9
- private readonly {model}Repository: Repository<{Model}>,
10
+ private readonly {modelVar}Repository: Repository<{Model}>,
10
11
  ) {}
11
12
 
12
13
  async findAll(options: any = {}) {
13
- return this.{model}Repository.find(options);
14
+ return this.{modelVar}Repository.find(options);
14
15
  }
15
16
 
16
17
  async paginate(current = 1, options: any = {}) {
17
18
  const take = 10;
18
19
  const skip = current > 1 ? (current - 1) * take : 0;
19
- const total = await this.{model}Repository.count(options);
20
+ const total = await this.{modelVar}Repository.count(options);
20
21
  const totalPage = Math.ceil(total / take);
21
22
 
22
- const data = await this.{model}Repository.find({ ...options, take, skip });
23
+ const data = await this.{modelVar}Repository.find({ ...options, take, skip });
23
24
 
24
25
  return {
25
26
  total,
@@ -32,29 +33,29 @@ export class {Service}Service {
32
33
  }
33
34
 
34
35
  async findByPk(id: number) {
35
- return this.{model}Repository.findOneBy({ id } as any);
36
+ return this.{modelVar}Repository.findOneBy({ id } as any);
36
37
  }
37
38
 
38
39
  async findBy(options: any) {
39
- return this.{model}Repository.findBy(options);
40
+ return this.{modelVar}Repository.findBy(options);
40
41
  }
41
42
 
42
43
  async findOneBy(options: any) {
43
- return this.{model}Repository.findOneBy(options);
44
+ return this.{modelVar}Repository.findOneBy(options);
44
45
  }
45
46
 
46
47
  async create(createBody: Partial<{Model}>) {
47
- const newItem = this.{model}Repository.create(createBody as any);
48
- return this.{model}Repository.save(newItem);
48
+ const newItem = this.{modelVar}Repository.create(createBody as any);
49
+ return this.{modelVar}Repository.save(newItem);
49
50
  }
50
51
 
51
52
  async update(id: number, updateBody: Partial<{Model}>) {
52
- const result = await this.{model}Repository.update({ id } as any, updateBody as any);
53
+ const result = await this.{modelVar}Repository.update({ id } as any, updateBody as any);
53
54
  return (result.affected ?? 0) > 0;
54
55
  }
55
56
 
56
57
  async delete(id: number) {
57
- const result = await this.{model}Repository.delete({ id } as any);
58
+ const result = await this.{modelVar}Repository.delete({ id } as any);
58
59
  return (result.affected ?? 0) > 0;
59
60
  }
60
61
  }
@@ -1,34 +1,34 @@
1
1
  import { AppService, Collection } from '@avleon/core';
2
- import { {Model} } from '../models/{model}';
2
+ import { {Model} } from '{modelImport}';
3
3
 
4
4
  @AppService
5
- export class {Service}Service {
6
- private readonly {model}Collection = Collection.from<{Model}>([]);
5
+ export class {ClassName} {
6
+ private readonly {modelVar}Collection = Collection.from<{Model}>([]);
7
7
 
8
8
  async findAll() {
9
- return this.{model}Collection.find();
9
+ return this.{modelVar}Collection.find();
10
10
  }
11
11
 
12
12
  async paginate(page = 1, take = 10) {
13
13
  const skip = page > 1 ? (page - 1) * take : 0;
14
- return this.{model}Collection.paginate({ take, skip });
14
+ return this.{modelVar}Collection.paginate({ take, skip });
15
15
  }
16
16
 
17
17
  async findByPk(id: number) {
18
- return this.{model}Collection.findOne((item) => item.id === id);
18
+ return this.{modelVar}Collection.findOne((item) => item.id === id);
19
19
  }
20
20
 
21
21
  async create(createBody: Partial<{Model}>) {
22
- return this.{model}Collection.add(createBody);
22
+ return this.{modelVar}Collection.add(createBody);
23
23
  }
24
24
 
25
25
  async update(id: number, updateBody: Partial<{Model}>) {
26
- this.{model}Collection.update((item) => item.id === id, updateBody);
26
+ this.{modelVar}Collection.update((item) => item.id === id, updateBody);
27
27
  return true;
28
28
  }
29
29
 
30
30
  async delete(id: number) {
31
- this.{model}Collection.delete((item) => item.id === id);
31
+ this.{modelVar}Collection.delete((item) => item.id === id);
32
32
  return true;
33
33
  }
34
34
  }
package/dist/av-cli.js DELETED
@@ -1,60 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.PathExtractor = PathExtractor;
5
- function formatFileName(name) {
6
- return name
7
- .replace(/[_\s]+/g, "-")
8
- .replace(/([a-z])([A-Z])/g, "$1-$2")
9
- .replace(/((-|_|\.)+(Controller|Service|Model))|(Controller|Service|Model)/gi, "")
10
- .toLowerCase();
11
- }
12
- function formatClassName(name) {
13
- return name
14
- .replace(/[_\s-]+/g, " ")
15
- .replace(/([a-z])([A-Z])/g, "$1 $2")
16
- .toLowerCase()
17
- .replace(/\b\w/g, (char) => char.toUpperCase())
18
- .replace(/\s+/g, "");
19
- }
20
- function PathExtractor(givenPath, options) {
21
- let pathSplits = givenPath.split("/");
22
- let splitSize = pathSplits.length;
23
- let hasSubDirectory = splitSize > 0;
24
- let name = hasSubDirectory ? pathSplits[splitSize - 1] : pathSplits[0];
25
- let className = formatClassName(name);
26
- let fileType = "any";
27
- let isRest = false;
28
- let isForced = false;
29
- if (options.includes("make:controller") || options.includes("m:c")) {
30
- fileType = "controller";
31
- className = name.toLowerCase().replace(/controller|Controller/g, "");
32
- }
33
- if (options.includes("make:model") || options.includes("m:m")) {
34
- fileType = "model";
35
- className = name.toLowerCase().replace(/controller|Controller/g, "");
36
- }
37
- if (options.includes("make:service") || options.includes("m:s")) {
38
- fileType = "service";
39
- className = name.toLowerCase().replace(/controller|Controller/g, "");
40
- }
41
- if (options.includes("make:util") || options.includes("m:u")) {
42
- fileType = "util";
43
- className = name.toLowerCase().replace(/controller|Controller/g, "");
44
- }
45
- if (options.includes("make:config")) {
46
- fileType = "config";
47
- className = name.toLowerCase().replace(/controller|Controller/g, "");
48
- }
49
- if (options.includes("--rest") || options.includes("-r")) {
50
- isRest = true;
51
- className = name.toLowerCase().replace(/controller|Controller/g, "");
52
- }
53
- if (options.includes("--force") || options.includes("-f")) {
54
- isForced = true;
55
- className = name.toLowerCase().replace(/controller|Controller/g, "");
56
- }
57
- let outputFileName = formatFileName(name);
58
- let outputPath = givenPath + "." + fileType + ".ts";
59
- return {};
60
- }
package/dist/avcli.js DELETED
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AvCli = void 0;
4
- const node_child_process_1 = require("node:child_process");
5
- class AvCli {
6
- constructor() { }
7
- formatFileName() { }
8
- async executeCommand(cmd) {
9
- const { stdout, stderr } = (0, node_child_process_1.exec)(cmd, { encoding: "utf8" });
10
- if (stderr) {
11
- throw new Error("Can't execute command");
12
- }
13
- console.log(stdout);
14
- }
15
- displayHelp() { }
16
- newProject() { }
17
- makeModel() { }
18
- makeController() { }
19
- makeService() { }
20
- makeConfig() { }
21
- makeHelper() { }
22
- makeRestController() { }
23
- makeRestService() { }
24
- run() { }
25
- }
26
- exports.AvCli = AvCli;
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });