Creando app de NestJS
💡Este template esta basado en el repositorio de nestjs template de Inlaze. Se debe generar una estructura parecida o igual a la siguiente para tener un proyecto configurado de acuerdo a los estándares.
├───.husky/
│ └───pre-commit
├───src/
│ ├───app/
│ │ ├───app.controller.spec.ts
│ │ ├───app.controller.ts
│ │ ├───app.module.ts
│ │ └───app.service.ts
│ └───main.ts
├───test/
│ └───jest-e2e.json
├───.eslintignore
├───.eslintrc.js
├───.lintstagedrc
├───.prettierignore
├───.prettierrc
├───nest-cli.json
├───package.json
├───pnpm-lock.yaml
├───README.md
├───tsconfig.build.json
└───tsconfig.json
Husky Precommit
Se trata de un paquete que permite ejecutar precommits para hacer validaciones de código. Se complementa con el paquete de lint-staged para poder validar sólo lo que el desarrollador tiene el stage, para tener esto configurado debemos instalar los paquetes como devDependencies
, así:
pnpm i -D husky lint-staged
El husky debe tener un bash que es el que ejecuta antes de cada commit, este debe ser el contenido:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
Como la ejecución es del lint-staged, entonces toca crear un .lintstagedrc
que es un json con la configuración de la ejecución que debe ejecutar el precommit:
{
"**/{src,test}/**/*.{ts,tsx}": ["eslint", "prettier --write"],
"**/*.{ts,tsx}": "bash -c tsc -p tsconfig.json --noEmit"
}
Eslint
La configuración que debe haber de eslint es:
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
tsconfigRootDir : __dirname,
sourceType: "module",
},
plugins: [
"@typescript-eslint/eslint-plugin",
"unused-imports"
],
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:@typescript-eslint/strict",
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: [".eslintrc.js", "global.d.ts"],
rules: {
"unused-imports/no-unused-imports": "error",
"@typescript-eslint/triple-slash-reference": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"@typescript-eslint/ban-tslint-comment": "error",
"@typescript-eslint/class-literal-property-style": "error",
"@typescript-eslint/consistent-generic-constructors": "error",
"@typescript-eslint/consistent-indexed-object-style": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/consistent-type-definitions": "error",
"@typescript-eslint/consistent-type-exports": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/explicit-member-accessibility": "error",
"@typescript-eslint/explicit-module-boundary-types": "error",
"@typescript-eslint/method-signature-style": "error",
"@typescript-eslint/no-confusing-non-null-assertion": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-extraneous-class": "off",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-import-type-side-effects": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/prefer-reduce-type-parameter": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/prefer-readonly": "error",
"no-return-await": "off",
"@typescript-eslint/return-await": "error",
"@typescript-eslint/no-misused-promises": "off",
"eqeqeq": ["error", "always"],
"no-console": "error",
"@typescript-eslint/unified-signatures": "off",
"@typescript-eslint/naming-convention": ["error",
{
selector: 'default',
format: ['camelCase'],
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
leadingUnderscore: 'allow',
},
{
selector: 'parameter',
format: ['camelCase'],
leadingUnderscore: 'allow',
},
{
selector: 'memberLike',
modifiers: ['private'],
format: ['camelCase', "UPPER_CASE", "snake_case"],
leadingUnderscore: 'allow',
},
{
selector: 'memberLike',
modifiers: ['public'],
format: ['camelCase', "UPPER_CASE", "snake_case", "PascalCase"],
},
{
selector: 'typeLike',
format: ['PascalCase'],
},
{
selector: "enumMember",
format: ["UPPER_CASE"]
},
{
selector: "objectLiteralMethod",
format: ["camelCase", "PascalCase"]
},
{
selector: "objectLiteralProperty",
format: ["camelCase", "UPPER_CASE", "PascalCase", "snake_case"]
}
]
},
};
Prettier
El prettier debe tener lo siguiente configurado:
{
"singleQuote": false,
"jsxSingleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"bracketSpacing": true,
"bracketSameLine": true,
"printWidth": 100,
"proseWrap": "always",
"endOfLine": "crlf",
"useTabs": false
}
TS Config
La configuración de typescript es estricta, por lo que debe tener las siguientes normas para que sea de acuerdo a los estándares planteados:
{
"compilerOptions": {
"strict": true,
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "ES2021",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": true,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"resolveJsonModule": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"alwaysStrict": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"useUnknownInCatchVariables": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"noImplicitOverride": true,
}
}
Last updated