Skip to content
Snippets Groups Projects
Verified Commit d25cec02 authored by Konstantin Tsabolov's avatar Konstantin Tsabolov
Browse files

Merge branch 'main' into multitenancy

parents ef35b4a5 77473b13
No related branches found
No related tags found
No related merge requests found
Showing
with 1643 additions and 2 deletions
......@@ -24,14 +24,18 @@ FROM base AS build
ARG APP_HOME=/home/node/app
WORKDIR ${APP_HOME}
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml tsconfig.json ./
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml tsconfig*.json .swcrc ./
COPY apps/${SERVICE}/package.json ./apps/${SERVICE}/
COPY apps/shared/package.json ./apps/shared/
RUN pnpm install --frozen-lockfile
COPY apps/${SERVICE} ./apps/${SERVICE}
COPY apps/shared ./apps/shared
RUN pnpm --filter shared build
RUN pnpm --filter ${SERVICE} build:production
RUN pnpm --filter ${SERVICE} --prod deploy build
RUN pnpm --filter shared --prod deploy shared
# This is a way of keeping the generated prisma client in the build folder
RUN if [ -d ./apps/${SERVICE}/node_modules/\@prisma/client ]; then \
......@@ -55,6 +59,7 @@ CMD ["node", "dist/main.js"]
COPY --chown=node:node ./docker-entrypoint.sh ./docker-entrypoint.sh
COPY --from=build --chown=node:node ${APP_HOME}/build/dist ./dist
COPY --from=build --chown=node:node ${APP_HOME}/shared/dist ./shared
COPY --from=build --chown=node:node ${APP_HOME}/build/node_modules ./node_modules
COPY --from=build --chown=node:node ${APP_HOME}/build/package.json .
......@@ -64,4 +69,4 @@ RUN node -e "\
fs.writeFileSync('./package.json', JSON.stringify({ name, version, type }, null, 2));\
"
USER node
# USER node
HTTP_HOST=0.0.0.0
HTTP_PORT=3011
NATS_URL=nats://nats:4222
NATS_MONITORING_URL=nats://nats:8222
SSI_AGENT_URL=http://ssi:3010
This diff is collapsed.
import { readFileSync } from 'node:fs';
const swcConfig = JSON.parse(readFileSync('../../.swcrc', 'utf8'));
/** @type {import('jest').Config} */
export default {
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
transform: {
'^.+\\.(js|ts)$': [
'@swc/jest',
{
...swcConfig,
sourceMaps: false,
exclude: [],
swcrc: false,
},
],
},
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
// ESM modules require `.js` extension to be specified, but Jest doesn't work with them
// Removing `.js` extension from module imports
'^uuid$': 'uuid',
'^(.*)/(.*)\\.js$': '$1/$2',
},
collectCoverageFrom: ['src/**/*.(t|j)s'],
coverageReporters:
process.env.CI === 'true'
? ['text-summary', 'json-summary']
: ['text-summary', 'html'],
coveragePathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/test/',
'<rootDir>/coverage/',
'<rootDir>/dist/',
'<rootDir>/**/test',
'@types',
'.dto.(t|j)s',
'.enum.ts',
'.interface.ts',
'.type.ts',
'.spec.ts',
],
coverageDirectory: './coverage',
// With v8 coverage provider it's much faster, but
// with this enabled it's not possible to ignore whole files' coverage
coverageProvider: 'v8',
};
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"typeCheck": true,
"builder": {
"type": "swc",
"options": {
"swcrcPath": "../../.swcrc"
}
}
}
}
{
"name": "@ocm/credential-manager",
"version": "1.0.0",
"description": "",
"author": "Konstantin Tsabolov <konstantin.tsabolov@spherity.com>",
"contributors": [
"Konstantin Tsabolov <konstantin.tsabolov@spherity.com>"
],
"private": true,
"license": "Apache-2.0",
"type": "module",
"scripts": {
"clean": "rimraf dist coverage *.tsbuildinfo",
"prebuild": "pnpm clean",
"build": "nest build",
"prebuild:production": "pnpm clean",
"build:production": "nest build -p tsconfig.production.json",
"start": "nest start",
"start:dev": "nest start --watch --preserveWatchOutput",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest.config.js"
},
"dependencies": {
"@nestjs/axios": "^3.0.1",
"@nestjs/common": "^10.2.10",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.2.10",
"@nestjs/microservices": "^10.2.10",
"@nestjs/platform-express": "^10.2.8",
"@nestjs/swagger": "^7.1.16",
"@nestjs/terminus": "^10.1.1",
"axios": "^1.6.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"express": "^4.17.3",
"joi": "^17.11.0",
"nats": "^2.18.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@nestjs/cli": "^10.2.1",
"@nestjs/schematics": "^10.0.3",
"@nestjs/testing": "^10.2.8",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.96",
"@swc/jest": "^0.2.29",
"@types/express": "^4.17.21",
"@types/jest": "^29.5.8",
"@types/jsonwebtoken": "^9.0.5",
"@types/node": "^20.9.0",
"@types/supertest": "^2.0.16",
"dotenv-cli": "^7.3.0",
"eslint": "^8.53.0",
"jest": "^29.7.0",
"rimraf": "^5.0.5",
"typescript": "^5.3.2"
}
}
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { httpConfig } from './config/http.config.js';
import { natsConfig } from './config/nats.config.js';
import { ssiConfig } from './config/ssi.config.js';
import { validationSchema } from './config/validation.js';
import { HealthModule } from './health/health.module.js';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [httpConfig, natsConfig, ssiConfig],
cache: true,
expandVariables: true,
validationSchema,
validationOptions: {
allowUnknown: true,
abortEarly: true,
},
}),
HealthModule,
],
})
export default class AppModule {}
export const SERVICE_NAME = 'CREDENTIAL_MANAGER_SERVICE';
import { registerAs } from '@nestjs/config';
export const httpConfig = registerAs('http', () => ({
host: process.env.HOST,
port: Number(process.env.PORT),
}));
import { registerAs } from '@nestjs/config';
export const natsConfig = registerAs('nats', () => ({
url: process.env.NATS_URL,
monitoringUrl: process.env.NATS_MONITORING_URL,
}));
import { registerAs } from '@nestjs/config';
export const ssiConfig = registerAs('ssi', () => ({
agentUrl: process.env.SSI_AGENT_URL,
}));
import Joi from 'joi';
export const validationSchema = Joi.object({
HTTP_HOST: Joi.string().default('0.0.0.0'),
HTTP_PORT: Joi.number().default(3000),
NATS_URL: Joi.string().uri().default('nats://localhost:4222'),
NATS_MONITORING_URL: Joi.string().uri().default('http://localhost:8222'),
SSI_AGENT_URL: Joi.string().default('http://localhost:3010'),
});
import type { HealthIndicatorFunction } from '@nestjs/terminus';
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
HealthCheck,
HealthCheckService,
HttpHealthIndicator,
} from '@nestjs/terminus';
@Controller('health')
export class HealthController {
public constructor(
private readonly config: ConfigService,
private readonly health: HealthCheckService,
private readonly http: HttpHealthIndicator,
) {}
@Get()
@HealthCheck()
public check() {
const healthIndicators: HealthIndicatorFunction[] = [];
const natsMonitoringUrl = this.config.get('nats.monitoringUrl');
if (typeof natsMonitoringUrl === 'string') {
healthIndicators.push(() =>
this.http.pingCheck('nats', natsMonitoringUrl),
);
} else {
healthIndicators.push(() => ({ nats: { status: 'down' } }));
}
return this.health.check(healthIndicators);
}
}
import type { ConfigType } from '@nestjs/config';
import { HttpModule } from '@nestjs/axios';
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { TerminusModule } from '@nestjs/terminus';
import { SERVICE_NAME } from '../common/constants.js';
import { natsConfig } from '../config/nats.config.js';
import { HealthController } from './health.controller.js';
@Module({
imports: [
TerminusModule,
HttpModule,
ClientsModule.registerAsync({
clients: [
{
name: SERVICE_NAME,
inject: [natsConfig.KEY],
useFactory: (config: ConfigType<typeof natsConfig>) => ({
transport: Transport.NATS,
options: {
servers: [config.url as string],
},
}),
},
],
}),
],
controllers: [HealthController],
})
export class HealthModule {}
import type { MicroserviceOptions } from '@nestjs/microservices';
import { VersioningType } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { NestFactory } from '@nestjs/core';
import { Transport } from '@nestjs/microservices';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import AppModule from './app.module.js';
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);
app.enableCors();
app.connectMicroservice<MicroserviceOptions>({
transport: Transport.NATS,
options: {
servers: [configService.get('nats').url],
},
});
app.enableVersioning({
defaultVersion: ['1'],
type: VersioningType.URI,
});
const swaggerConfig = new DocumentBuilder()
.setTitle('Gaia-X OCM Credential Manager API')
.setDescription('API documentation for Gaia-X OCM Credential Manager')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, swaggerConfig);
SwaggerModule.setup('/swagger', app, document);
await app.startAllMicroservices();
await app.listen(configService.get('PORT') || 3000);
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "./dist",
"rootDir": "./src"
},
"exclude": ["node_modules", "**/test", "**/dist", "**/*spec.ts"]
}
{
"extends": "../../tsconfig.json"
}
{
"extends": "../../tsconfig.production.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "./dist",
"rootDir": "./src"
},
"exclude": ["node_modules", "**/test", "**/dist", "**/*spec.ts"]
}
This diff is collapsed.
import { readFileSync } from 'node:fs';
const swcConfig = JSON.parse(readFileSync('../../.swcrc', 'utf8'));
/** @type {import('jest').Config} */
export default {
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
transform: {
'^.+\\.(js|ts)$': [
'@swc/jest',
{
...swcConfig,
sourceMaps: false,
exclude: [],
swcrc: false,
},
],
},
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
// ESM modules require `.js` extension to be specified, but Jest doesn't work with them
// Removing `.js` extension from module imports
'^uuid$': 'uuid',
'^(.*)/(.*)\\.js$': '$1/$2',
},
collectCoverageFrom: ['src/**/*.(t|j)s'],
coverageReporters:
process.env.CI === 'true'
? ['text-summary', 'json-summary']
: ['text-summary', 'html'],
coveragePathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/test/',
'<rootDir>/coverage/',
'<rootDir>/dist/',
'<rootDir>/**/test',
'@types',
'.dto.(t|j)s',
'.enum.ts',
'.interface.ts',
'.type.ts',
'.spec.ts',
],
coverageDirectory: './coverage',
// With v8 coverage provider it's much faster, but
// with this enabled it's not possible to ignore whole files' coverage
coverageProvider: 'v8',
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment