adding typeorm to api

This commit is contained in:
2025-07-24 21:11:13 -05:00
parent f94d0f7ca9
commit 25886c8498
15 changed files with 1211 additions and 117 deletions

BIN
.DS_Store vendored

Binary file not shown.

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ node_modules
.dapr .dapr
**/**/secrets.json **/**/secrets.json
.prod .prod
database

View File

@@ -22,7 +22,13 @@
FROM node:18-slim AS base FROM node:22-slim AS base
FROM base AS migrate
WORKDIR migrations
COPY ./migrations .
RUN npm i -g pnpm
RUN pnpm install
FROM base AS api FROM base AS api
WORKDIR api WORKDIR api

View File

@@ -27,6 +27,7 @@
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/passport": "^10.0.3", "@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^11.0.0",
"@noahspan/azure-database": "^3.1.2", "@noahspan/azure-database": "^3.1.2",
"@noahspan/noahspan-modules": "^1.1.5", "@noahspan/noahspan-modules": "^1.1.5",
"@schematics/angular": "^17.3.7", "@schematics/angular": "^17.3.7",
@@ -34,6 +35,8 @@
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"sqlite3": "^5.1.7",
"typeorm": "^0.3.25",
"uuid": "^10.0.0", "uuid": "^10.0.0",
"uuidv4": "^6.2.13" "uuidv4": "^6.2.13"
}, },

View File

@@ -7,6 +7,7 @@ import { HttpExceptionFilter } from './filters/http-exception.filter';
import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthGuard, AuthModule, UserModule } from '@noahspan/noahspan-modules'; import { AuthGuard, AuthModule, UserModule } from '@noahspan/noahspan-modules';
import configuration from './config/configuration'; import configuration from './config/configuration';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({ @Module({
imports: [ imports: [
@@ -27,6 +28,15 @@ import configuration from './config/configuration';
FeatureFlagModule, FeatureFlagModule,
LogModule, LogModule,
PilotModule, PilotModule,
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'sqlite',
database: configService.get<string>('dbPath'),
entities: [__dirname + "/**/*.entity{.ts,.js}"],
synchronize: false
})
}),
UserModule.registerAsync({ UserModule.registerAsync({
inject: [ConfigService], inject: [ConfigService],
imports: [ConfigModule], imports: [ConfigModule],

View File

@@ -0,0 +1,21 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
import { PilotEntity } from '../pilot/pilot.entity';
@Entity({ name: 'certificates'})
export class CertificateEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
type: string;
@Column()
number: string;
@Column()
issueDate: Date
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.certificates)
@JoinColumn({ name: 'pilotId' })
pilot: PilotEntity;
}

View File

@@ -1,5 +1,6 @@
export default () => ({ export default () => ({
azureStorageConnectionString: process.env.AZURE_STORAGE_CONNECTION_STRING, azureStorageConnectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
dbPath: process.env.DB_PATH,
clientId: process.env.CLIENT_ID, clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET, clientSecret: process.env.CLIENT_SECRET,
tenantId: process.env.TENANT_ID tenantId: process.env.TENANT_ID

View File

@@ -0,0 +1,18 @@
import { PilotEntity } from 'src/pilot/pilot.entity';
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
@Entity({ name: 'endorsements' })
export class EndorsementEntity {
@PrimaryGeneratedColumn('uuid')
id: string
@Column()
type: string;
@Column()
issueDate: Date;
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.endorsements)
@JoinColumn({ name: 'pilotId' })
pilot: PilotEntity
}

View File

@@ -27,3 +27,82 @@ export class Log {
tracks?: string[]; tracks?: string[];
notes?: string; notes?: string;
} }
import { PilotEntity } from 'src/pilot/pilot.entity';
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
@Entity({ name: 'logs' })
export class LogEntity {
@PrimaryGeneratedColumn('uuid')
id: string
@Column()
date: Date;
@Column()
aircraftMakeModel: string;
@Column()
aircraftIdentity: string;
@Column()
routeFrom: string;
@Column()
routeTo: string;
@Column()
durationOfFlight: number;
@Column()
singleEngineLand: number;
@Column()
simulatorAtd: number;
@Column()
landingsDay: number;
@Column()
landingsNight: number;
@Column()
groundTrainingReceived: number;
@Column()
flightTrainingReceived: number;
@Column()
crossCountry: number;
@Column()
night: number;
@Column()
solo: number;
@Column()
pilotInCommand: number;
@Column()
instrumentActual: number;
@Column()
instrumentSimulated: number;
@Column()
instrumentApproaches: number;
@Column()
instrumentHolds: number;
@Column()
instrumentNavTrack: number;
@Column()
notes: string;
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.logs)
@JoinColumn({ name: 'pilotId' })
pilot: PilotEntity;
}

View File

@@ -0,0 +1,18 @@
import { PilotEntity } from 'src/pilot/pilot.entity';
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
@Entity({ name: 'medical' })
export class MedicalEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
class: string;
@Column()
expirationDate: Date;
@ManyToOne(() => PilotEntity, (pilot: PilotEntity) => pilot.medical)
@JoinColumn({ name: 'pilotId' })
pilot: PilotEntity;
}

View File

@@ -1,5 +0,0 @@
export class Certificate {
type: string;
issueDate: string;
number: string;
}

View File

@@ -1,4 +0,0 @@
export class Endorsement {
type: string;
issueDate: Date;
}

View File

@@ -1,18 +1,63 @@
import { EntityString } from '@noahspan/azure-database'; // import { EntityString } from '@noahspan/azure-database';
export class Pilot { // export class Pilot {
@EntityString() partitionKey: string; // @EntityString() partitionKey: string;
@EntityString() rowKey: string; // @EntityString() rowKey: string;
@EntityString() id: string; // @EntityString() id: string;
@EntityString() name: string; // @EntityString() name: string;
@EntityString() address?: string; // @EntityString() address?: string;
@EntityString() city?: string; // @EntityString() city?: string;
@EntityString() state?: string; // @EntityString() state?: string;
@EntityString() postalCode?: string; // @EntityString() postalCode?: string;
@EntityString() email?: string; // @EntityString() email?: string;
@EntityString() phone?: string; // @EntityString() phone?: string;
@EntityString() medicalClass?: string; // @EntityString() medicalClass?: string;
@EntityString() medicalExpiration: string; // @EntityString() medicalExpiration: string;
@EntityString() certificates: string; // @EntityString() certificates: string;
@EntityString() endorsements: string; // @EntityString() endorsements: string;
// }
import { LogEntity } from 'src/log/log.entity';
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { CertificateEntity } from '../certificate/certificate.entity';
import { EndorsementEntity } from 'src/endorsement/endorsement.entity';
import { MedicalEntity } from 'src/medical/medical.entity';
@Entity({ name: 'pilots' })
export class PilotEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column()
address: string
@Column()
city: string;
@Column()
state: string;
@Column()
postalCode: string;
@Column()
email: string;
@Column()
phone: string;
@OneToMany(() => LogEntity, (log: LogEntity) => log.pilot, {onDelete: 'CASCADE', onUpdate: 'CASCADE'})
logs: LogEntity[];
@OneToMany(() => CertificateEntity, (certificate: CertificateEntity) => certificate.pilot, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
certificates: CertificateEntity[];
@OneToMany(() => EndorsementEntity, (endorsement: EndorsementEntity) => endorsement.pilot, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
endorsements: EndorsementEntity[];
@OneToMany(() => MedicalEntity, (medical: MedicalEntity) => medical.pilot, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
medical: MedicalEntity[];
} }

View File

@@ -1,34 +1,63 @@
version: '3.8' version: '3.8'
services: services:
azurite: # azurite:
container_name: azurite-flying # container_name: azurite-flying
image: mcr.microsoft.com/azure-storage/azurite # image: mcr.microsoft.com/azure-storage/azurite
ports: # ports:
- '10000:10000' # - '10000:10000'
- '10001:10001' # - '10001:10001'
- '10002:10002' # - '10002:10002'
command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck' # command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose --skipApiVersionCheck'
# volumes:
# - ./azurite-flying:/data
restore:
container_name: restore
image: litestream/litestream:0.3.13
volumes: volumes:
- ./azurite-flying:/data - ./database/flying.db:/var/lib/flying/flying.db
- ./database/litestream_dev.yml:/etc/litestream.yml
- backup:/var/lib/backup
- data:/var/lib/flying
command: restore -if-db-not-exists -if-replica-exists /var/lib/flying/flying.db
api: # api:
container_name: flying-api # container_name: flying-api
build: # build:
context: . # context: .
target: api # target: api
ports: # ports:
- '3000:3000' # - '3000:3000'
env_file: # env_file:
- ./api/.env.compose # - ./api/.env.compose
# volumes:
# - data:/var/lib/flying
# depends_on:
# migrate:
# condition: service_completed_successfully
app: # replicate:
container_name: flying-app # container_name: replicate
build: # image: litestream/litestream:0.3.13
context: . # volumes:
target: app # - ./database/litestream_dev.yml:/etc/litestream.yml
ports: # - backup:/var/lib/backup
- '8080:8080' # - data:/var/lib/flying
# command: replicate
# depends_on:
# migrate:
# condition: service_completed_successfully
# app:
# container_name: flying-app
# build:
# context: .
# target: app
# ports:
# - '8080:8080'
volumes: volumes:
azurite-flying: # azurite-flying:
backup:
data:

998
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff