chore: generate portal-shell and portal-bff apps per ADR-0004 / ADR-0005
Add the @nx/angular, @nx/nest, @nx/vite, @nx/eslint plugins, then generate the two apps. Adjust the empty-template tsconfig.base.json to be Angular-compatible (drop project references and customConditions that the empty-template defaults to but Angular doesn't support; keep the strict-TS extensions from ADR-0004). apps/portal-shell (Angular 21): - standalone APIs, routing, SCSS, esbuild - vitest-angular as unitTestRunner, playwright for e2e - strict mode - tags scope:portal-shell, type:app - app.config.ts wired with provideZonelessChangeDetection() per ADR-0004 (Angular 21 + Nx 22 generates without zone.js by default) apps/portal-bff (NestJS 11): - Express adapter (default per ADR-0005) - Jest as unitTestRunner - tags scope:portal-bff, type:app - main.ts wired with a global ValidationPipe configured whitelist + forbidNonWhitelisted + transform per ADR-0005 - Phase-2 security additions (helmet, CORS, sessions, CSRF, rate limit, auth guards, error filter) deferred to their respective ADRs - placeholder comment in main.ts Workspace dependencies: class-validator + class-transformer added (required by NestJS ValidationPipe at runtime). Nx-generated .gitignore additions (.angular, __screenshots__) merged into ours. .vscode/extensions.json and launch.json added by Nx are kept (do not override our existing settings.json).
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
export default {
|
||||
displayName: 'portal-bff-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.spec.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/portal-bff-e2e',
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "portal-bff-e2e",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"implicitDependencies": ["portal-bff"],
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"e2e": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/portal-bff-e2e/jest.config.cts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"dependsOn": ["portal-bff:build", "portal-bff:serve"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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' });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { waitForPortOpen } from '@nx/node/utils';
|
||||
|
||||
/* 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');
|
||||
|
||||
const host = process.env.HOST ?? 'localhost';
|
||||
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
|
||||
await waitForPortOpen(port, { host });
|
||||
|
||||
// Hint: Use `globalThis` to pass variables to global teardown.
|
||||
globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { killPort } from '@nx/node/utils';
|
||||
/* 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.
|
||||
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
|
||||
await killPort(port);
|
||||
console.log(globalThis.__TEARDOWN_MESSAGE__);
|
||||
};
|
||||
@@ -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}`;
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.ts", "src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user