achscli 1.3.5

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/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "achscli",
3
+ "version": "1.3.5",
4
+ "description": "Scaffolding CLI to generate files and update modules",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "author": "sorodriguezz",
8
+ "bin": {
9
+ "achscli": "dist/bin.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "templates",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "type": "commonjs",
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "scripts": {
22
+ "build": "node esbuild.config.mjs",
23
+ "dev": "node esbuild.config.mjs --watch",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "dependencies": {
27
+ "chalk": "5.6.2",
28
+ "commander": "14.0.2",
29
+ "handlebars": "4.7.8",
30
+ "ts-morph": "27.0.2"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "25.0.3",
34
+ "esbuild": "0.27.2",
35
+ "typescript": "5.9.3"
36
+ }
37
+ }
@@ -0,0 +1,30 @@
1
+ import { Controller, Get, Logger } from '@nestjs/common';
2
+ import { ApplyControllerDocs } from '#app/common/docs.decorator.ts';
3
+ import { {{PASCALCASE className}}ControllerDocs } from './{{KEBABCASE className}}.controller.docs.ts';
4
+
5
+ /**
6
+ * {{PASCALCASE className}} controller.
7
+ * NOTE: import it in your context module at 'controllers' array.
8
+ *
9
+ * @see https://docs.nestjs.com/controllers
10
+ */
11
+ @Controller({
12
+ path: '{{route}}',
13
+ version: '1',
14
+ })
15
+ @ApplyControllerDocs({{PASCALCASE className}}ControllerDocs)
16
+ export class {{PASCALCASE className}} {
17
+ /**
18
+ * Return sample result.
19
+ *
20
+ * @returns returns a sample
21
+ */
22
+ @Get()
23
+ run(): string {
24
+ return 'Hello World';
25
+ }
26
+
27
+ constructor() {}
28
+
29
+ private readonly _logger = new Logger({{PASCALCASE className}}.name);
30
+ }
@@ -0,0 +1,10 @@
1
+ import { applyDecorators } from '@nestjs/common';
2
+
3
+ /**
4
+ * {{PASCALCASE decoratorName}} decorator.
5
+ *
6
+ * @see https://docs.nestjs.com/custom-decorators
7
+ */
8
+ export function {{PASCALCASE decoratorName}}() {
9
+ return applyDecorators(/* your decorators here */);
10
+ }
@@ -0,0 +1,19 @@
1
+ import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
2
+ import { HttpStatus } from '@nestjs/common';
3
+ import type { DecoratorsLookUp } from '#common/decorators/apply.decorator.js';
4
+ import { type {{PASCALCASE className}}Controller } from './{{KEBABCASE className}}.controller.ts';
5
+
6
+ export const {{PASCALCASE className}}ControllerDocs: DecoratorsLookUp<{{PASCALCASE className}}Controller> =
7
+ {
8
+ class: [ApiTags('{{PASCALCASE className}}')],
9
+ method: {
10
+ run: [
11
+ ApiOperation({ summary: 'A Description' }),
12
+ ApiResponse({
13
+ description: 'DTO',
14
+ status: HttpStatus.OK,
15
+ type: String,
16
+ }),
17
+ ],
18
+ },
19
+ };
@@ -0,0 +1,17 @@
1
+ import { ZodDto } from '#libs/zod';
2
+ import { z } from 'zod';
3
+
4
+ /**
5
+ * {{PASCALCASE className}} Schema.
6
+ */
7
+ const {{PASCALCASE className}}Schema = z.object({
8
+ prop: z.string().describe('my prop'),
9
+ });
10
+
11
+ /**
12
+ * {{PASCALCASE className}} Dto.
13
+ */
14
+ export class {{PASCALCASE className}}Dto extends ZodDto(
15
+ {{PASCALCASE className}}Schema,
16
+ '{{PASCALCASE className}}',
17
+ ) {}
@@ -0,0 +1,36 @@
1
+ import {
2
+ type DynamicModule,
3
+ Logger,
4
+ Module,
5
+ type OnModuleInit,
6
+ } from '@nestjs/common';
7
+
8
+ /**
9
+ * {{PASCALCASE className}} dynamic module.
10
+ * NOTE: import it in your 'main.module' at 'imports' array.
11
+ *
12
+ * @see https://docs.nestjs.com/fundamentals/dynamic-modules
13
+ */
14
+ @Module({})
15
+ export class {{PASCALCASE className}}Module implements OnModuleInit {
16
+ onModuleInit(): void {
17
+ this._logger.debug('Module started');
18
+ }
19
+
20
+ private readonly _logger = new Logger({{PASCALCASE className}}Module.name);
21
+
22
+ /**
23
+ * Register the module with configuration.
24
+ *
25
+ * @returns module registration
26
+ */
27
+ static register(): DynamicModule {
28
+ return {
29
+ module: {{PASCALCASE className}}Module,
30
+ controllers: [],
31
+ imports: [],
32
+ exports: [],
33
+ providers: [],
34
+ };
35
+ }
36
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * {{PASCALCASE entityName}} Entity.
3
+ */
4
+ export class {{PASCALCASE entityName}}Entity {
5
+ /**
6
+ * A member.
7
+ */
8
+ private _member: string;
9
+
10
+ /**
11
+ * Returns member value.
12
+ */
13
+ get member(): string {
14
+ return this._member;
15
+ }
16
+
17
+ /**
18
+ * Sets member value.
19
+ */
20
+ set member(value: string) {
21
+ this._member = value;
22
+ }
23
+ }
@@ -0,0 +1,52 @@
1
+ import { HttpAdapterHost } from '@nestjs/core';
2
+ import {
3
+ type ArgumentsHost,
4
+ Catch,
5
+ type ExceptionFilter,
6
+ HttpException,
7
+ HttpStatus,
8
+ Logger,
9
+ } from '@nestjs/common';
10
+
11
+ /**
12
+ * {{PASCALCASE filterName}} exception filter.
13
+ * NOTE: import it in your context module at 'providers' array
14
+ * or with decorator @UseFilters(new {{PASCALCASE filterName}}ExceptionFilter())
15
+ *
16
+ * Remove @Catch() decorator for scoped catching.
17
+ *
18
+ * @see https://docs.nestjs.com/exception-filters
19
+ */
20
+ @Catch()
21
+ export class {{PASCALCASE filterName}}ExceptionFilter implements ExceptionFilter {
22
+ /**
23
+ * Captures all exceptions.
24
+ *
25
+ * @param exception - thrown exception
26
+ * @param host - execution context
27
+ */
28
+ catch(exception: unknown, host: ArgumentsHost) {
29
+ // in certain situations `httpAdapter` might not be available in the
30
+ // constructor method, thus we should resolve it here.
31
+ const { httpAdapter } = this.httpAdapterHost;
32
+
33
+ const ctx = host.switchToHttp();
34
+
35
+ const httpStatus =
36
+ exception instanceof HttpException
37
+ ? exception.getStatus()
38
+ : HttpStatus.INTERNAL_SERVER_ERROR;
39
+
40
+ const responseBody = {
41
+ path: httpAdapter.getRequestUrl(ctx.getRequest()),
42
+ statusCode: httpStatus,
43
+ timestamp: new Date().toISOString(),
44
+ };
45
+
46
+ httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
47
+ }
48
+
49
+ constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
50
+
51
+ private readonly _logger = new Logger({{PASCALCASE filterName}}ExceptionFilter.name);
52
+ }
@@ -0,0 +1,34 @@
1
+ import { type Observable } from 'rxjs';
2
+ import {
3
+ type CanActivate,
4
+ type ExecutionContext,
5
+ Injectable,
6
+ UseGuards,
7
+ } from '@nestjs/common';
8
+
9
+ /**
10
+ * {{PASCALCASE guardName}} guard.
11
+ *
12
+ * @see https://docs.nestjs.com/guards
13
+ */
14
+ @Injectable()
15
+ class {{PASCALCASE guardName}}Guard implements CanActivate {
16
+ /**
17
+ * Validates if request may continue
18
+ *
19
+ * @param context - current request context
20
+ *
21
+ * @returns whether can be executed
22
+ */
23
+ canActivate(
24
+ context: ExecutionContext,
25
+ ): boolean | Promise<boolean> | Observable<boolean> {
26
+ console.log(`Guard ${ {{PASCALCASE guardName}}Guard.name } triggered!`);
27
+
28
+ return true;
29
+ }
30
+ }
31
+
32
+ const guard = UseGuards(new {{PASCALCASE guardName}}Guard());
33
+
34
+ export const {{PASCALCASE guardName}} = () => guard;
@@ -0,0 +1,11 @@
1
+ import { HttpException, HttpStatus } from '@nestjs/common';
2
+
3
+ /**
4
+ * {{PASCALCASE httpExceptionName}} HTTP exception.
5
+ */
6
+ export class {{PASCALCASE httpExceptionName}}HttpException extends HttpException {
7
+ constructor() {
8
+ // add description
9
+ super('', HttpStatus.INTERNAL_SERVER_ERROR);
10
+ }
11
+ }
@@ -0,0 +1,40 @@
1
+ import { tap } from 'rxjs/operators';
2
+ import { type Observable } from 'rxjs';
3
+ import {
4
+ Injectable,
5
+ type NestInterceptor,
6
+ type ExecutionContext,
7
+ type CallHandler,
8
+ UseInterceptors,
9
+ Logger,
10
+ } from '@nestjs/common';
11
+
12
+ /**
13
+ * {{PASCALCASE interceptorName}} interceptor.
14
+ *
15
+ * @see https://docs.nestjs.com/interceptors
16
+ */
17
+ @Injectable()
18
+ class {{PASCALCASE interceptorName}}Interceptor implements NestInterceptor {
19
+ /**
20
+ * Intercepts a method execution.
21
+ *
22
+ * @param context - execution context
23
+ * @param next - continues to the next handler
24
+ *
25
+ * @returns
26
+ */
27
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
28
+ this._logger.debug('Before...');
29
+
30
+ return next.handle().pipe(tap(() => this._logger.debug('After...')));
31
+ }
32
+
33
+ private readonly _logger = new Logger(
34
+ {{PASCALCASE interceptorName}}Interceptor.name,
35
+ );
36
+ }
37
+
38
+ const interceptor = UseInterceptors(new {{PASCALCASE interceptorName}}Interceptor());
39
+
40
+ export const {{PASCALCASE interceptorName}} = () => interceptor;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * {{PASCALCASE interfaceName}}.
3
+ */
4
+ export interface {{PASCALCASE interfaceName}} {
5
+ /**
6
+ * A member.
7
+ */
8
+ readonly _member: string;
9
+ }
@@ -0,0 +1,24 @@
1
+ import { type FastifyRequest, type FastifyReply } from 'fastify';
2
+ import { Injectable, type NestMiddleware, Logger } from '@nestjs/common';
3
+
4
+ /**
5
+ * User middleware.
6
+ *
7
+ * @see https://docs.nestjs.com/middleware
8
+ */
9
+ @Injectable()
10
+ export class UserMiddleware implements NestMiddleware {
11
+ /**
12
+ * Intercepts requests.
13
+ *
14
+ * @param req - inbound request
15
+ * @param next - continues to the next middleware
16
+ */
17
+ use(req: FastifyRequest, res: FastifyReply, next: () => void): void {
18
+ this._logger.debug('Middleware triggered');
19
+
20
+ next();
21
+ }
22
+
23
+ private readonly _logger = new Logger(UserMiddleware.name);
24
+ }
@@ -0,0 +1,9 @@
1
+ import { Module } from '@nestjs/common';
2
+
3
+ @Module({
4
+ imports: [],
5
+ controllers: [],
6
+ providers: [],
7
+ exports: [],
8
+ })
9
+ export class {{PASCALCASE className}}Module {}
@@ -0,0 +1,15 @@
1
+ import { type FastifyRequest } from 'fastify';
2
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
3
+
4
+ /**
5
+ * {{PASCALCASE decoratorName}} decorator.
6
+ *
7
+ * @see https://docs.nestjs.com/custom-decorators
8
+ */
9
+ export const {{PASCALCASE decoratorName}} = createParamDecorator(
10
+ (data: unknown, ctx: ExecutionContext) => {
11
+ const { params }: FastifyRequest = ctx.switchToHttp().getRequest();
12
+
13
+ return params;
14
+ },
15
+ );
@@ -0,0 +1,35 @@
1
+ import { Injectable, Provider } from '@nestjs/common';
2
+
3
+ /**
4
+ * {{PASCALCASE className}} Repository.
5
+ * NOTE: import it in your context module at 'providers' array.
6
+ *
7
+ * @see https://docs.nestjs.com/Providers
8
+ */
9
+ @Injectable()
10
+ export class {{PASCALCASE className}}Repository {
11
+ /**
12
+ * Returns sample phrase
13
+ *
14
+ * @returns sample phrase
15
+ */
16
+ sample(): string {
17
+ return 'Hello World';
18
+ }
19
+
20
+ constructor() {}
21
+
22
+ /**
23
+ * Repository initializer for module.
24
+ *
25
+ * @returns Repository
26
+ */
27
+ static register(): Provider<{{PASCALCASE className}}Repository> {
28
+ return {
29
+ provide: {{PASCALCASE className}}Repository,
30
+ inject: [], // your injected dependencies tokens here
31
+ useFactory: (/* your dependencies from inject */) =>
32
+ new {{PASCALCASE className}}Repository(),
33
+ };
34
+ }
35
+ }
@@ -0,0 +1,24 @@
1
+ import { Injectable } from '@nestjs/common';
2
+
3
+ /**
4
+ * {{PASCALCASE className}} service.
5
+ * NOTE: import it in your context module at 'providers' array.
6
+ *
7
+ * @see https://docs.nestjs.com/providers
8
+ */
9
+ @Injectable()
10
+ export class {{PASCALCASE className}}Service {
11
+ /**
12
+ * Sums two numbers.
13
+ *
14
+ * @param a - any number
15
+ * @param b - any number
16
+ *
17
+ * @returns sum
18
+ */
19
+ sum(a: number, b: number): number {
20
+ return a + b;
21
+ }
22
+
23
+ constructor() {}
24
+ }
@@ -0,0 +1,35 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from 'vitest';
2
+ import { Test, type TestingModule } from '@nestjs/testing';
3
+ import { {{PASCALCASE className}}Controller } from './{{KEBABCASE className}}.controller.ts';
4
+
5
+ describe({{PASCALCASE className}}Controller, () => {
6
+ let _module: TestingModule;
7
+ let _controller: {{PASCALCASE className}}Controller;
8
+
9
+ // hooks
10
+ beforeAll(async () => {
11
+ _module = await Test.createTestingModule({
12
+ controllers: [{{PASCALCASE className}}Controller],
13
+ }).compile();
14
+
15
+ _controller = _module.get<{{PASCALCASE className}}Controller>(
16
+ {{PASCALCASE className}}Controller,
17
+ );
18
+
19
+ // disables logger
20
+ (_controller as any)._logger?.localInstance.setLogLevels?.([]);
21
+ });
22
+
23
+ afterAll(async () => {
24
+ await _module.close();
25
+ });
26
+
27
+ // tests
28
+ test('should be defined', () => {
29
+ expect(_controller).toBeDefined();
30
+ });
31
+
32
+ test('should return "Hello World"', () => {
33
+ expect(_controller.run()).toBe('Hello World');
34
+ });
35
+ });
@@ -0,0 +1,32 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from 'vitest';
2
+ import { Test, type TestingModule } from '@nestjs/testing';
3
+ import { {{PASCALCASE className}}Repository } from './{{KEBABCASE className}}.repository.ts';
4
+
5
+ describe({{PASCALCASE className}}Repository.name, () => {
6
+ let _module: TestingModule;
7
+ let _repository: {{PASCALCASE className}}Repository;
8
+
9
+ // hooks
10
+ beforeAll(async () => {
11
+ _module = await Test.createTestingModule({
12
+ providers: [{{PASCALCASE className}}Repository.register()],
13
+ }).compile();
14
+
15
+ _repository = _module.get<{{PASCALCASE className}}Repository>(
16
+ {{PASCALCASE className}}Repository,
17
+ );
18
+ });
19
+
20
+ afterAll(async () => {
21
+ await _module.close();
22
+ });
23
+
24
+ // tests
25
+ test('should be defined', () => {
26
+ expect(_repository).toBeDefined();
27
+ });
28
+
29
+ test('sample() return "Hello World"', () => {
30
+ expect(_repository.sample()).toBe('Hello World');
31
+ });
32
+ });
@@ -0,0 +1,28 @@
1
+ import { afterAll, beforeAll, describe, expect, test } from 'vitest';
2
+ import { Test, type TestingModule } from '@nestjs/testing';
3
+ import { {{PASCALCASE className}}Service } from './{{KEBABCASE className}}.service.ts';
4
+
5
+ describe({{PASCALCASE className}}Service.name, () => {
6
+ let _module: TestingModule;
7
+ let _service: {{PASCALCASE className}}Service;
8
+
9
+ // hooks
10
+ beforeAll(async () => {
11
+ _module = await Test.createTestingModule({
12
+ providers: [{{PASCALCASE className}}Service],
13
+ }).compile();
14
+
15
+ _service = _module.get<{{PASCALCASE className}}Service>(
16
+ {{PASCALCASE className}}Service,
17
+ );
18
+ });
19
+
20
+ afterAll(async () => {
21
+ await _module.close();
22
+ });
23
+
24
+ // tests
25
+ test('1 + 1 should sum 2', () => {
26
+ expect(_service.sum(1, 1)).toBe(2);
27
+ });
28
+ });
@@ -0,0 +1,8 @@
1
+ import { describe, expect, test } from 'vitest';
2
+
3
+ describe('{{className}}', () => {
4
+ // tests
5
+ test('1 to be 1', () => {
6
+ expect(1).toBe(1);
7
+ });
8
+ });