feat(repo): init ebitemp-api + type-checked eslint

This commit is contained in:
Francesco Spilla 2025-02-06 11:14:02 +01:00
parent de35ed5841
commit 9ddbd45b03
34 changed files with 6615 additions and 25 deletions

2
.gitignore vendored
View File

@ -40,3 +40,5 @@ Thumbs.db
.nx/cache
.nx/workspace-data
test-output

View File

@ -1,3 +1,8 @@
{
"recommendations": ["nrwl.angular-console", "esbenp.prettier-vscode"]
"recommendations": [
"nrwl.angular-console",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"firsttris.vscode-jest-runner"
]
}

View File

@ -0,0 +1,3 @@
import baseConfig from '../../eslint.config.mjs';
export default [...baseConfig];

View File

@ -0,0 +1,18 @@
export default {
displayName: 'ebitemp-api-e2e',
preset: '../../jest.preset.js',
globalSetup: '<rootDir>/src/support/global-setup.ts',
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.json',
},
],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/ebitemp-api-e2e',
};

View File

@ -0,0 +1,27 @@
{
"name": "@insiemesalute-3p/ebitemp-api-e2e",
"version": "0.0.1",
"private": true,
"nx": {
"name": "ebitemp-api-e2e",
"projectType": "application",
"implicitDependencies": [
"ebitemp-api"
],
"targets": {
"e2e": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/{e2eProjectRoot}"
],
"options": {
"jestConfig": "apps/ebitemp-api-e2e/jest.config.ts",
"passWithNoTests": true
},
"dependsOn": [
"ebitemp-api:build"
]
}
}
}
}

View File

@ -0,0 +1,10 @@
import axios from 'axios';
describe('GET /api', () => {
it('should return a message', async () => {
const res = await axios.get(`/api`);
expect(res.status).toBe(200);
expect(res.data).toEqual({ message: 'Hello API' });
});
});

View File

@ -0,0 +1,10 @@
/* eslint-disable */
var __TEARDOWN_MESSAGE__: string;
module.exports = async function () {
// Start services that that the app needs to run (e.g. database, docker-compose, etc.).
console.log('\nSetting up...\n');
// Hint: Use `globalThis` to pass variables to global teardown.
globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
};

View File

@ -0,0 +1,7 @@
/* eslint-disable */
module.exports = async function () {
// Put clean up logic here (e.g. stopping services, docker-compose, etc.).
// Hint: `globalThis` is shared between setup and teardown.
console.log(globalThis.__TEARDOWN_MESSAGE__);
};

View File

@ -0,0 +1,9 @@
/* eslint-disable */
import axios from 'axios';
module.exports = async function () {
// Configure axios for tests to use.
const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ?? '3000';
axios.defaults.baseURL = `http://${host}:${port}`;
};

View File

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "out-tsc/ebitemp-api-e2e",
"esModuleInterop": true,
"noUnusedLocals": false,
"noImplicitAny": false
},
"include": ["jest.config.ts", "src/**/*.ts"],
"references": []
}

View File

@ -0,0 +1,22 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "es6"
},
"sourceMaps": true,
"exclude": []
}

View File

@ -0,0 +1,16 @@
import baseConfig from '../../eslint.config.mjs';
import tseslint from 'typescript-eslint';
export default tseslint.config([
...baseConfig,
{
files: ['src/**/*.ts', 'src/**/*.tsx'],
extends: [tseslint.configs.recommendedTypeCheckedOnly],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
]);

View File

@ -0,0 +1,21 @@
/* eslint-disable */
import { readFileSync } from 'fs';
// Reading the SWC compilation config for the spec files
const swcJestConfig = JSON.parse(
readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
);
// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
swcJestConfig.swcrc = false;
export default {
displayName: 'ebitemp-api',
preset: '../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: 'test-output/jest/coverage',
};

View File

@ -0,0 +1,52 @@
{
"name": "@insiemesalute-3p/ebitemp-api",
"version": "0.0.1",
"private": true,
"nx": {
"name": "ebitemp-api",
"projectType": "application",
"sourceRoot": "apps/ebitemp-api/src",
"targets": {
"build": {
"executor": "nx:run-commands",
"options": {
"command": "webpack-cli build",
"args": [
"node-env=production"
]
},
"configurations": {
"development": {
"args": [
"node-env=development"
]
}
}
},
"serve": {
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"dependsOn": [
"build"
],
"options": {
"buildTarget": "ebitemp-api:build",
"runBuildTargetDependencies": false
},
"configurations": {
"development": {
"buildTarget": "ebitemp-api:build:development"
},
"production": {
"buildTarget": "ebitemp-api:build:production"
}
}
},
"test": {
"options": {
"passWithNoTests": true
}
}
}
}
}

View File

@ -0,0 +1,21 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let app: TestingModule;
beforeAll(async () => {
app = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
});
describe('getData', () => {
it('should return "Hello API"', () => {
const appController = app.get<AppController>(AppController);
expect(appController.getData()).toEqual({ message: 'Hello API' });
});
});
});

View File

@ -0,0 +1,12 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getData() {
return this.appService.getData();
}
}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

View File

@ -0,0 +1,20 @@
import { Test } from '@nestjs/testing';
import { AppService } from './app.service';
describe('AppService', () => {
let service: AppService;
beforeAll(async () => {
const app = await Test.createTestingModule({
providers: [AppService],
}).compile();
service = app.get<AppService>(AppService);
});
describe('getData', () => {
it('should return "Hello API"', () => {
expect(service.getData()).toEqual({ message: 'Hello API' });
});
});
});

View File

@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getData(): { message: string } {
return { message: 'Hello API' };
}
}

View File

View File

@ -0,0 +1,21 @@
/**
* This is not a production server yet!
* This is only a minimal backend to get started.
*/
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app/app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const globalPrefix = 'api';
app.setGlobalPrefix(globalPrefix);
const port = process.env.PORT || 3000;
await app.listen(port);
Logger.log(
`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`
);
}
void bootstrap();

View File

@ -0,0 +1,28 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "out-tsc/ebitemp-api",
"types": ["node"],
"rootDir": "src",
"tsBuildInfoFile": "out-tsc/ebitemp-api/tsconfig.app.tsbuildinfo",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "es2021",
"strictNullChecks": true,
"noImplicitAny": true,
"strictBindCallApply": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts"],
"exclude": [
"out-tsc",
"dist",
"jest.config.ts",
"src/**/*.spec.ts",
"src/**/*.test.ts",
"eslint.config.js",
"eslint.config.cjs",
"eslint.config.mjs"
]
}

View File

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,20 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out-tsc/jest",
"types": ["jest", "node"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

View File

@ -0,0 +1,20 @@
const { NxAppWebpackPlugin } = require('@nx/webpack/app-plugin');
const { join } = require('path');
module.exports = {
output: {
path: join(__dirname, '../../dist/apps/ebitemp-api'),
},
plugins: [
new NxAppWebpackPlugin({
target: 'node',
compiler: 'tsc',
main: './src/main.ts',
tsConfig: './tsconfig.app.json',
assets: ['./src/assets'],
optimization: false,
outputHashing: 'none',
generatePackageJson: true,
}),
],
};

40
eslint.config.mjs Normal file
View File

@ -0,0 +1,40 @@
import nx from '@nx/eslint-plugin';
export default [
...nx.configs['flat/base'],
...nx.configs['flat/typescript'],
...nx.configs['flat/javascript'],
{
ignores: ['**/dist'],
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
},
],
},
],
},
},
{
files: [
'**/*.ts',
'**/*.tsx',
'**/*.js',
'**/*.jsx',
'**/*.cjs',
'**/*.mjs',
],
// Override or add rules here
rules: {},
},
];

5
jest.config.ts Normal file
View File

@ -0,0 +1,5 @@
import { getJestProjectsAsync } from '@nx/jest';
export default async () => ({
projects: await getJestProjectsAsync(),
});

3
jest.preset.js Normal file
View File

@ -0,0 +1,3 @@
const nxPreset = require('@nx/jest/preset').default;
module.exports = { ...nxPreset };

41
nx.json
View File

@ -2,7 +2,16 @@
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": ["default"],
"production": [
"default",
"!{projectRoot}/.eslintrc.json",
"!{projectRoot}/eslint.config.mjs",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/jest.config.[jt]s",
"!{projectRoot}/src/test-setup.[jt]s",
"!{projectRoot}/test-setup.[jt]s"
],
"sharedGlobals": []
},
"plugins": [
@ -19,6 +28,34 @@
"watchDepsName": "watch-deps"
}
}
},
{
"plugin": "@nx/webpack/plugin",
"options": {
"buildTargetName": "build",
"serveTargetName": "serve",
"previewTargetName": "preview",
"buildDepsTargetName": "build-deps",
"watchDepsTargetName": "watch-deps"
}
},
{
"plugin": "@nx/eslint/plugin",
"options": {
"targetName": "lint"
}
},
{
"plugin": "@nx/jest/plugin",
"options": {
"targetName": "test"
},
"exclude": ["apps/ebitemp-api-e2e/**/*"]
}
]
],
"targetDefaults": {
"test": {
"dependsOn": ["^build"]
}
}
}

View File

@ -2,17 +2,49 @@
"name": "@insiemesalute-3p/source",
"version": "0.0.0",
"license": "MIT",
"scripts": {},
"scripts": {
"start": "nx run-many --target serve",
"build": "nx run-many --target build",
"lint": "nx run-many --target lint"
},
"private": true,
"dependencies": {},
"devDependencies": {
"@eslint/js": "^9.8.0",
"@nestjs/schematics": "^10.0.1",
"@nestjs/testing": "^10.0.2",
"@nx/eslint": "20.4.0",
"@nx/eslint-plugin": "20.4.0",
"@nx/jest": "20.4.0",
"@nx/js": "20.4.0",
"@nx/nest": "20.4.0",
"@nx/node": "20.4.0",
"@nx/web": "20.4.0",
"@nx/webpack": "20.4.0",
"@swc-node/register": "~1.9.1",
"@swc/core": "~1.5.7",
"@swc/helpers": "~0.5.11",
"@swc/jest": "~0.2.36",
"@types/jest": "^29.5.12",
"@types/node": "~18.16.9",
"eslint": "^9.8.0",
"eslint-config-prettier": "^9.0.0",
"jest": "^29.7.0",
"jest-environment-node": "^29.7.0",
"nx": "20.4.0",
"prettier": "^2.6.2",
"ts-jest": "^29.1.0",
"ts-node": "10.9.1",
"tslib": "^2.3.0",
"typescript": "~5.7.2"
"typescript": "~5.7.2",
"typescript-eslint": "^8.19.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@nestjs/common": "^10.0.2",
"@nestjs/core": "^10.0.2",
"@nestjs/platform-express": "^10.0.2",
"axios": "^1.6.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0"
}
}

6114
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,2 @@
packages:
- "packages/*"
- "apps/*"

View File

@ -2,5 +2,12 @@
"extends": "./tsconfig.base.json",
"compileOnSave": false,
"files": [],
"references": []
"references": [
{
"path": "./apps/ebitemp-api-e2e"
},
{
"path": "./apps/ebitemp-api"
}
]
}