Feature/33 api fails when no pilots or logbook entries #35
@@ -1 +1,6 @@
|
||||
node_modules
|
||||
node_modules
|
||||
.git
|
||||
.gitignore
|
||||
*.md
|
||||
infrastructure
|
||||
test
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,4 +4,5 @@ node_modules
|
||||
**/.env.*
|
||||
.DS_Store
|
||||
.dapr
|
||||
**/**/secrets.json
|
||||
**/**/secrets.json
|
||||
.prod
|
||||
43
Dockerfile
43
Dockerfile
@@ -1,18 +1,39 @@
|
||||
FROM --platform=linux/amd64 node:18-alpine AS base
|
||||
# FROM --platform=linux/amd64 node:18-alpine AS base
|
||||
# ENV PNPM_HOME="/pnpm"
|
||||
# ENV PATH="$PNPM_HOME:$PATH"
|
||||
# RUN corepack enable
|
||||
|
||||
# FROM base AS api
|
||||
# COPY /api/dist /app/dist
|
||||
# COPY /api/node_modules /app/node_modules
|
||||
# WORKDIR /app
|
||||
# EXPOSE 3000
|
||||
# # CMD ["node", "dist/main.js"]
|
||||
# ENTRYPOINT ["tail", "-f", "/dev/null"]
|
||||
|
||||
# FROM base AS app
|
||||
# COPY /app/dist /app/dist
|
||||
# WORKDIR /app
|
||||
# RUN npm i -g serve
|
||||
# EXPOSE 8080
|
||||
# CMD [ "serve", "-s", "/dist", "-p", "8080" ]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FROM node:18-slim AS base
|
||||
|
||||
FROM base AS api
|
||||
COPY ./api/dist ./api/dist
|
||||
COPY ./api/node_modules ./api/node_modules
|
||||
WORKDIR api
|
||||
COPY ./.prod/api .
|
||||
EXPOSE 3000
|
||||
CMD ["node", "/api/dist/main.js"]
|
||||
CMD ["node", "dist/main.js"]
|
||||
# ENTRYPOINT ["tail", "-f", "/dev/null"]
|
||||
|
||||
FROM base AS app
|
||||
WORKDIR /app
|
||||
COPY ./.prod/app .
|
||||
RUN npm i -g serve
|
||||
# WORKDIR ./app
|
||||
COPY ./app/dist ./app/dist
|
||||
# COPY ./app .
|
||||
# RUN npm install
|
||||
EXPOSE 8080
|
||||
CMD [ "serve", "-s", "app/dist", "-p", "8080" ]
|
||||
# CMD ["npm", "run", "dev"]
|
||||
# ENTRYPOINT ["tail", "-f", "/dev/null"]
|
||||
CMD [ "serve", "-s", "dist", "-p", "8080" ]
|
||||
8766
api/package-lock.json
generated
8766
api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -30,10 +30,10 @@
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/passport": "^10.0.3",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"@noahspan/azure-database": "^3.1.0",
|
||||
"@noahspan/noahspan-modules": "^0.5.2",
|
||||
"@noahspan/azure-database": "^3.1.2",
|
||||
"@schematics/angular": "^17.3.7",
|
||||
"dotenv": "^16.4.7",
|
||||
"express-jwt": "^8.5.1",
|
||||
"passport-azure-ad": "^4.3.5",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "^7.8.1",
|
||||
@@ -57,6 +57,9 @@
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
|
||||
@@ -3,14 +3,17 @@ import {
|
||||
Get,
|
||||
Headers,
|
||||
Query,
|
||||
StreamableFile
|
||||
StreamableFile,
|
||||
UseGuards
|
||||
} from '@nestjs/common';
|
||||
import { Client as MsGraphClient } from '@microsoft/microsoft-graph-client';
|
||||
import { MsGraphService, Public } from '@noahspan/noahspan-modules';
|
||||
import { MsGraphService } from './msGraph/ms-graph.service'
|
||||
import { Person } from '@microsoft/microsoft-graph-types';
|
||||
import { AppService } from './app.service';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@Controller()
|
||||
@UseGuards(AuthGuard('azure-ad'))
|
||||
export class AppController {
|
||||
constructor(
|
||||
private readonly appService: AppService,
|
||||
@@ -72,7 +75,6 @@ export class AppController {
|
||||
}
|
||||
}
|
||||
|
||||
@Public()
|
||||
@Get('hello')
|
||||
async getHello(): Promise<string> {
|
||||
return this.appService.getHello();
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { AuthGuard, AuthModule } from '@noahspan/noahspan-modules';
|
||||
import { MsGraphModule } from '@noahspan/noahspan-modules';
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { MsGraphModule } from './msGraph/ms-graph.module';
|
||||
import { FeatureFlagModule } from './featureFlag/feature-flag.module'
|
||||
import { LogModule } from './log/log.module';
|
||||
import { PilotModule } from './pilot/pilot.module';
|
||||
@@ -45,10 +44,6 @@ import configuration from './config/configuration';
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: AuthGuard
|
||||
},
|
||||
{
|
||||
provide: APP_FILTER,
|
||||
useClass: HttpExceptionFilter
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
// import { MsGraphService, MsGraphClient } from '@noahspan/noahspan-modules';
|
||||
import { Client as MsGraphClient } from '@microsoft/microsoft-graph-client';
|
||||
import { MsGraphService } from '@noahspan/noahspan-modules';
|
||||
import { MsGraphService } from './msGraph/ms-graph.service';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
|
||||
5
api/src/auth/auth.interface.ts
Normal file
5
api/src/auth/auth.interface.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface AuthModuleOptions {
|
||||
tenantId: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
}
|
||||
4
api/src/auth/auth.module-definition.ts
Normal file
4
api/src/auth/auth.module-definition.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ConfigurableModuleBuilder } from '@nestjs/common';
|
||||
import { AuthModuleOptions } from './auth.interface';
|
||||
|
||||
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder<AuthModuleOptions>().build()
|
||||
14
api/src/auth/auth.module.ts
Normal file
14
api/src/auth/auth.module.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { AzureAdStrategy } from './auth.strategy';
|
||||
import { ConfigurableModuleClass } from './auth.module-definition';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PassportModule.register({
|
||||
defaultStrategy: 'azure-ad'
|
||||
})
|
||||
],
|
||||
providers: [AzureAdStrategy]
|
||||
})
|
||||
export class AuthModule extends ConfigurableModuleClass {}
|
||||
26
api/src/auth/auth.strategy.ts
Normal file
26
api/src/auth/auth.strategy.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { PassportStrategy } from "@nestjs/passport";
|
||||
import { AuthModuleOptions } from './auth.interface'
|
||||
import { MODULE_OPTIONS_TOKEN } from "./auth.module-definition";
|
||||
import { BearerStrategy } from 'passport-azure-ad'
|
||||
|
||||
@Injectable()
|
||||
export class AzureAdStrategy extends PassportStrategy(
|
||||
BearerStrategy,
|
||||
'azure-ad'
|
||||
) {
|
||||
constructor(@Inject(MODULE_OPTIONS_TOKEN) authModuleOptions: AuthModuleOptions) {
|
||||
console.log(authModuleOptions)
|
||||
super({
|
||||
identityMetadata: `https://login.microsoftonline.com/${authModuleOptions.tenantId}/.well-known/openid-configuration`,
|
||||
clientID: authModuleOptions.clientId,
|
||||
audience: `api://${authModuleOptions.clientId}`,
|
||||
loggingLevel: 'info',
|
||||
loggingNoPII: false
|
||||
})
|
||||
}
|
||||
|
||||
async validate(data: any): Promise<any> {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
9
api/src/error/customError.ts
Normal file
9
api/src/error/customError.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export class CustomError extends Error {
|
||||
statusCode: number;
|
||||
|
||||
constructor(message, name, statusCode) {
|
||||
super(message);
|
||||
this.name = name;
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,18 @@ import {
|
||||
Get,
|
||||
HttpException,
|
||||
Param,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { FeatureFlagService } from './feature-flag.service';
|
||||
import { CustomError, Public } from '@noahspan/noahspan-modules';
|
||||
import { CustomError } from '../error/customError';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@Controller('featureFlags')
|
||||
@UseGuards(AuthGuard('azure-ad'))
|
||||
export class FeatureFlagController {
|
||||
constructor(private readonly featureFlagService: FeatureFlagService) {}
|
||||
|
||||
@Get(':partitionKey/:rowKey')
|
||||
@Public()
|
||||
async find(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
@@ -27,7 +29,6 @@ export class FeatureFlagController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Public()
|
||||
async findAll() {
|
||||
try {
|
||||
return await this.featureFlagService.findAll();
|
||||
|
||||
@@ -6,14 +6,18 @@ import {
|
||||
HttpException,
|
||||
Param,
|
||||
Post,
|
||||
Put
|
||||
Put,
|
||||
UseGuards
|
||||
} from '@nestjs/common';
|
||||
import { LogDto } from './log.dto';
|
||||
import { Log } from './log.entity';
|
||||
import { LogService } from './log.service';
|
||||
import { CustomError } from '@noahspan/noahspan-modules';
|
||||
import { CustomError } from '../error/customError';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
|
||||
@Controller('logs')
|
||||
@UseGuards(AuthGuard('azure-ad'))
|
||||
export class LogController {
|
||||
constructor(private readonly logService: LogService) {}
|
||||
|
||||
@@ -31,6 +35,7 @@ export class LogController {
|
||||
}
|
||||
}
|
||||
|
||||
// @Public()
|
||||
@Get()
|
||||
async findAll(): Promise<Log[]> {
|
||||
try {
|
||||
|
||||
@@ -3,13 +3,16 @@ import { AppModule } from './app.module';
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { HttpExceptionFilter } from './filters/http-exception.filter';
|
||||
import { InternalServerErrorException } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
async function bootstrap() {
|
||||
const httpService = new HttpService();
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
app.enableCors();
|
||||
app.setGlobalPrefix('api');
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
|
||||
httpService.axiosRef.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
@@ -20,7 +23,7 @@ async function bootstrap() {
|
||||
throw new InternalServerErrorException();
|
||||
}
|
||||
);
|
||||
app.enableCors();
|
||||
|
||||
|
||||
await app.listen(3000);
|
||||
}
|
||||
|
||||
5
api/src/msGraph/ms-graph.interface.ts
Normal file
5
api/src/msGraph/ms-graph.interface.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface MsGraphModuleOptions {
|
||||
tenantId: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
}
|
||||
4
api/src/msGraph/ms-graph.module-definition.ts
Normal file
4
api/src/msGraph/ms-graph.module-definition.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ConfigurableModuleBuilder } from '@nestjs/common';
|
||||
import { MsGraphModuleOptions } from './ms-graph.interface';
|
||||
|
||||
export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder<MsGraphModuleOptions>().build()
|
||||
9
api/src/msGraph/ms-graph.module.ts
Normal file
9
api/src/msGraph/ms-graph.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MsGraphService } from './ms-graph.service';
|
||||
import { ConfigurableModuleClass } from './ms-graph.module-definition';
|
||||
|
||||
@Module({
|
||||
providers: [MsGraphService],
|
||||
exports: [MsGraphService]
|
||||
})
|
||||
export class MsGraphModule extends ConfigurableModuleClass {}
|
||||
41
api/src/msGraph/ms-graph.service.ts
Normal file
41
api/src/msGraph/ms-graph.service.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { MsGraphModuleOptions } from './ms-graph.interface';
|
||||
import { Client } from '@microsoft/microsoft-graph-client';
|
||||
import { AuthenticationResult, ConfidentialClientApplication, OnBehalfOfRequest } from '@azure/msal-node';
|
||||
import { MODULE_OPTIONS_TOKEN } from './ms-graph.module-definition';
|
||||
|
||||
@Injectable()
|
||||
export class MsGraphService {
|
||||
constructor(@Inject(MODULE_OPTIONS_TOKEN) private msGraphModuleOptions: MsGraphModuleOptions) {}
|
||||
|
||||
async getMsGraphAuth(accessToken: string, scopes: string[]): Promise<string> {
|
||||
try {
|
||||
const oboRequest: OnBehalfOfRequest = {
|
||||
oboAssertion: accessToken,
|
||||
scopes: scopes
|
||||
}
|
||||
const cca = new ConfidentialClientApplication({
|
||||
auth: {
|
||||
clientId: this.msGraphModuleOptions.clientId,
|
||||
clientSecret: this.msGraphModuleOptions.clientSecret,
|
||||
authority: `https://login.microsoftonline.com/${this.msGraphModuleOptions.tenantId}`
|
||||
}
|
||||
});
|
||||
const authenticationResult: AuthenticationResult = await cca.acquireTokenOnBehalfOf(oboRequest);
|
||||
|
||||
return authenticationResult.accessToken
|
||||
} catch (error) {
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
async getMsGraphClientDelegated(accessToken): Promise<Client> {
|
||||
const client = await Client.init({
|
||||
authProvider: (done) => {
|
||||
done(null, accessToken);
|
||||
}
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
@@ -7,21 +7,20 @@ import {
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
UseInterceptors
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { PilotDto } from './pilot.dto';
|
||||
import { Pilot } from './pilot.entity';
|
||||
import { PilotService } from './pilot.service';
|
||||
import { CustomError, Public } from '@noahspan/noahspan-modules';
|
||||
import { PilotInterceptor } from './interceptors/pilot.interceptor';
|
||||
import { CustomError } from '../error/customError';
|
||||
import { AuthGuard } from '@nestjs/passport'
|
||||
|
||||
@Controller('pilots')
|
||||
@UseGuards(AuthGuard('azure-ad'))
|
||||
export class PilotController {
|
||||
constructor(private readonly pilotService: PilotService) {}
|
||||
|
||||
@Get(':partitionKey/:rowKey')
|
||||
@Public()
|
||||
@UseInterceptors(PilotInterceptor)
|
||||
async find(
|
||||
@Param('partitionKey') partitionKey: string,
|
||||
@Param('rowKey') rowKey: string
|
||||
@@ -36,8 +35,6 @@ export class PilotController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Public()
|
||||
@UseInterceptors(PilotInterceptor)
|
||||
async findAll() {
|
||||
try {
|
||||
return await this.pilotService.findAll();
|
||||
|
||||
8237
app/package-lock.json
generated
8237
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -31,5 +31,8 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -137,35 +137,35 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
// useEffect(() => {
|
||||
// const setUserProfile = async () => {
|
||||
// try {
|
||||
// setLoading(true);
|
||||
useEffect(() => {
|
||||
const setUserProfile = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
// const accessToken: string = await getAccessToken();
|
||||
// const userProfile = await getUserProfile(accessToken);
|
||||
// const userPhoto = await getUserPhoto(accessToken);
|
||||
const accessToken: string = await getAccessToken();
|
||||
const userProfile = await getUserProfile(accessToken);
|
||||
const userPhoto = await getUserPhoto(accessToken);
|
||||
|
||||
// setUserPhoto(userPhoto);
|
||||
setUserPhoto(userPhoto);
|
||||
|
||||
// appContext.dispatch({
|
||||
// type: 'SET_USER_PROFILE',
|
||||
// payload: userProfile
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// } finally {
|
||||
// setLoading(false);
|
||||
// }
|
||||
// };
|
||||
appContext.dispatch({
|
||||
type: 'SET_USER_PROFILE',
|
||||
payload: userProfile
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// if (
|
||||
// isAuthenticated &&
|
||||
// Object.keys(appContext.state.userProfile).length === 0
|
||||
// ) {
|
||||
// setUserProfile();
|
||||
// }
|
||||
// }, [isAuthenticated]);
|
||||
if (
|
||||
isAuthenticated &&
|
||||
Object.keys(appContext.state.userProfile).length === 0
|
||||
) {
|
||||
setUserProfile();
|
||||
}
|
||||
}, [isAuthenticated]);
|
||||
|
||||
return (
|
||||
<Navbar
|
||||
|
||||
@@ -10,28 +10,29 @@ import { MsalProvider } from '@azure/msal-react';
|
||||
import { msalConfig } from './auth/msalConfig';
|
||||
|
||||
const msalInstance: PublicClientApplication = new PublicClientApplication(msalConfig);
|
||||
const accounts = msalInstance.getAllAccounts();
|
||||
|
||||
console.log({ accounts, msalInstance });
|
||||
msalInstance.initialize().then(() => {
|
||||
const accounts = msalInstance.getAllAccounts();
|
||||
|
||||
if (accounts.length > 0) {
|
||||
msalInstance.setActiveAccount(accounts[0]);
|
||||
}
|
||||
|
||||
msalInstance.addEventCallback((event: EventMessage) => {
|
||||
if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
|
||||
const payload = event.payload as AuthenticationResult;
|
||||
const account = payload.account;
|
||||
msalInstance.setActiveAccount(account);
|
||||
if (accounts.length > 0) {
|
||||
msalInstance.setActiveAccount(accounts[0]);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
{/* <AppContextProvider> */}
|
||||
<BrowserRouter>
|
||||
<App pca={msalInstance} />
|
||||
</BrowserRouter>
|
||||
{/* </AppContextProvider> */}
|
||||
</React.StrictMode>
|
||||
);
|
||||
msalInstance.addEventCallback((event: EventMessage) => {
|
||||
if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
|
||||
const payload = event.payload as AuthenticationResult;
|
||||
const account = payload.account;
|
||||
msalInstance.setActiveAccount(account);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<AppContextProvider>
|
||||
<BrowserRouter>
|
||||
<App pca={msalInstance} />
|
||||
</BrowserRouter>
|
||||
</AppContextProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
})
|
||||
@@ -11,17 +11,23 @@ services:
|
||||
command: 'azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --loose'
|
||||
|
||||
api:
|
||||
container_name: api
|
||||
container_name: flying-api
|
||||
build:
|
||||
context: ./api
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
target: api
|
||||
ports:
|
||||
- '7071:3000'
|
||||
- '3000:3000'
|
||||
env_file:
|
||||
- ./api/.env
|
||||
|
||||
# swa:
|
||||
# image: swacli/static-web-apps-cli
|
||||
# ports:
|
||||
# - "4280:4280"
|
||||
# command: "swa start "
|
||||
app:
|
||||
container_name: flying-app
|
||||
build:
|
||||
context: .
|
||||
target: app
|
||||
ports:
|
||||
- '8080:8080'
|
||||
# env_file:
|
||||
# - ./app/.env
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
"start": "concurrently 'npm run start:azure -w api' 'wait-on tcp:0.0.0.0:7071 && npm run dev -w app'",
|
||||
"format": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\"",
|
||||
"lint": "npm run lint -w api && npm run lint -w app",
|
||||
"prepare": "husky || true"
|
||||
"prepare": "husky || true",
|
||||
"preprod": "rimraf ./.prod && pnpm --filter api build && pnpm --filter app build",
|
||||
"prod": "pnpm --filter api --prod deploy ./.prod/api && pnpm --filter app --prod deploy ./.prod/app"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
||||
@@ -18,6 +20,7 @@
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.2",
|
||||
"prettier": "3.2.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"wait-on": "^7.2.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
11879
pnpm-lock.yaml
generated
Normal file
11879
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
3
pnpm-workspace.yaml
Normal file
3
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
packages:
|
||||
- 'api'
|
||||
- 'app'
|
||||
Reference in New Issue
Block a user