server side asset rendering example, totp challenge start
This commit is contained in:
parent
ae51916e06
commit
048775899b
@ -3,19 +3,35 @@ import { AuthService } from './services/auth.service';
|
||||
import { MessagePattern } from '@nestjs/microservices';
|
||||
import { LoginRequest } from './interfaces/auth.interface';
|
||||
import { UserInfo } from '@freeblox/shared';
|
||||
import { AuthChallenge } from './enums/challenge.enum';
|
||||
|
||||
@Controller()
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@MessagePattern('auth.login')
|
||||
login({ body }: { body: LoginRequest }) {
|
||||
return this.authService.login(body);
|
||||
login({ body, ip }: { body: LoginRequest; ip: string }) {
|
||||
return this.authService.login(body, ip);
|
||||
}
|
||||
|
||||
@MessagePattern('auth.loginByRefreshToken')
|
||||
loginByRefreshToken({ token }: { token: string }) {
|
||||
return this.authService.loginByRefreshToken(token);
|
||||
loginByRefreshToken({ token, ip }: { token: string; ip: string }) {
|
||||
return this.authService.loginByRefreshToken(token, ip);
|
||||
}
|
||||
|
||||
@MessagePattern('auth.loginByChallenge')
|
||||
loginByChallenge({
|
||||
challenge,
|
||||
secret,
|
||||
body,
|
||||
ip,
|
||||
}: {
|
||||
challenge: AuthChallenge;
|
||||
secret: string;
|
||||
body: Record<string, string>;
|
||||
ip: string;
|
||||
}) {
|
||||
return this.authService.loginByChallenge(challenge, secret, body, ip);
|
||||
}
|
||||
|
||||
@MessagePattern('auth.verify')
|
||||
|
@ -2,7 +2,13 @@ import { Module, OnModuleInit } from '@nestjs/common';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './services/auth.service';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { makeKnex, makeTypeOrm, natsClient } from '@freeblox/shared';
|
||||
import {
|
||||
getCacheManager,
|
||||
getTypeOrm,
|
||||
makeKnex,
|
||||
makeTypeOrm,
|
||||
natsClient,
|
||||
} from '@freeblox/shared';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import knex from 'knex';
|
||||
@ -33,14 +39,8 @@ const entities = [
|
||||
ignoreEnvFile: process.env.NODE_ENV === 'development',
|
||||
load: [makeKnex('auth', __dirname), makeTypeOrm('auth'), security],
|
||||
}),
|
||||
TypeOrmModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (config: ConfigService) => ({
|
||||
...config.get('typeorm'),
|
||||
entities,
|
||||
}),
|
||||
}),
|
||||
getTypeOrm(entities),
|
||||
getCacheManager(),
|
||||
TypeOrmModule.forFeature(entities),
|
||||
ClientsModule.register([natsClient('auth')]),
|
||||
],
|
||||
|
3
apps/auth/src/enums/challenge.enum.ts
Normal file
3
apps/auth/src/enums/challenge.enum.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export enum AuthChallenge {
|
||||
OTP = 'OTP',
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { LoginRequest } from '../interfaces/auth.interface';
|
||||
import { JWTService } from './jwt.service';
|
||||
import { ILike, Repository } from 'typeorm';
|
||||
@ -11,12 +11,15 @@ import { BanService } from './ban.service';
|
||||
import {
|
||||
BadRequestRpcException,
|
||||
ForbiddenRpcException,
|
||||
PreconditionFailedRpcException,
|
||||
UserInfo,
|
||||
generateString,
|
||||
} from '@freeblox/shared';
|
||||
import { RoleService } from './role.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { RefreshService } from './refresh.service';
|
||||
import { AuthChallenge } from '../enums/challenge.enum';
|
||||
import { CACHE_MANAGER } from '@nestjs/cache-manager';
|
||||
import { Cache } from 'cache-manager';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
@ -29,6 +32,7 @@ export class AuthService {
|
||||
@InjectRepository(UserEntity)
|
||||
private readonly userRepository: Repository<UserEntity>,
|
||||
private readonly config: ConfigService,
|
||||
@Inject(CACHE_MANAGER) private cache: Cache,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -36,7 +40,7 @@ export class AuthService {
|
||||
* @param body Username/email and password
|
||||
* @returns JWT token
|
||||
*/
|
||||
async login(body: LoginRequest) {
|
||||
async login(body: LoginRequest, ip: string) {
|
||||
if (!body.email || !body.password) {
|
||||
throw new BadRequestRpcException('Invalid username or password');
|
||||
}
|
||||
@ -68,20 +72,9 @@ export class AuthService {
|
||||
}
|
||||
|
||||
// Check TOTP
|
||||
const userOTPToken = await this.otpService.getUserTOTP(userEntity);
|
||||
const userOTPToken = await this.otpService.userHasTOTP(userEntity);
|
||||
if (userOTPToken) {
|
||||
if (!body.totpToken) {
|
||||
throw new PreconditionFailedRpcException('TOTP Token required');
|
||||
}
|
||||
|
||||
const validate = this.otpService.validateTOTP(
|
||||
userOTPToken.token,
|
||||
body.totpToken,
|
||||
);
|
||||
|
||||
if (!validate) {
|
||||
throw new ForbiddenRpcException('Invalid TOTP Token');
|
||||
}
|
||||
return this.createOTPChallenge(userEntity);
|
||||
}
|
||||
|
||||
// Issue access token
|
||||
@ -100,13 +93,104 @@ export class AuthService {
|
||||
);
|
||||
|
||||
return {
|
||||
challenge: null,
|
||||
challengeSecret: null,
|
||||
authResult: {
|
||||
token: issuedToken,
|
||||
refresh: refreshToken,
|
||||
expires_in: exp,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async loginByRefreshToken(token: string) {
|
||||
/**
|
||||
* Login by challenge.
|
||||
* @param challenge Challenge type
|
||||
* @param token Challenge secret
|
||||
* @param response Challenge response from user
|
||||
* @returns Authentication result or another challenge
|
||||
*/
|
||||
async loginByChallenge(
|
||||
challenge: AuthChallenge,
|
||||
token: string,
|
||||
response: Record<string, string>,
|
||||
ip: string,
|
||||
) {
|
||||
const decrypted = await this.jwtService.decrypt(token);
|
||||
const tokenKey = `chlg:${challenge}:${decrypted.token}`;
|
||||
const challengeSubject = await this.cache.get<string>(tokenKey);
|
||||
|
||||
// Invalid token
|
||||
if (!challengeSubject) {
|
||||
throw new ForbiddenRpcException('Invalid challenge response');
|
||||
}
|
||||
|
||||
// Wrong subject, somehow..
|
||||
if (challengeSubject !== decrypted.sub) {
|
||||
await this.cache.del(tokenKey);
|
||||
throw new ForbiddenRpcException('Invalid challenge response');
|
||||
}
|
||||
|
||||
const loginUser = await this.userRepository.findOneByOrFail({
|
||||
id: challengeSubject,
|
||||
});
|
||||
|
||||
// TOTP verification login
|
||||
if (challenge === AuthChallenge.OTP) {
|
||||
// If no code is provided, assume request is incorrect
|
||||
// and delete the challenge from cache.
|
||||
if (!response.code) {
|
||||
await this.cache.del(tokenKey);
|
||||
throw new ForbiddenRpcException('Invalid challenge response');
|
||||
}
|
||||
|
||||
const userOTPToken = await this.otpService.getUserTOTP(loginUser);
|
||||
|
||||
// User does not actually have TOTP?
|
||||
if (!userOTPToken) {
|
||||
await this.cache.del(tokenKey);
|
||||
throw new ForbiddenRpcException('Invalid challenge response');
|
||||
}
|
||||
|
||||
const validate = this.otpService.validateTOTP(
|
||||
userOTPToken.token,
|
||||
response.code,
|
||||
);
|
||||
|
||||
// Here we do not delete from the cache, let the user retry.
|
||||
if (!validate) {
|
||||
throw new ForbiddenRpcException('Invalid challenge response');
|
||||
}
|
||||
} else {
|
||||
await this.cache.del(tokenKey);
|
||||
throw new ForbiddenRpcException('Invalid challenge');
|
||||
}
|
||||
|
||||
await this.cache.del(tokenKey);
|
||||
|
||||
// Issue access and refresh token
|
||||
const exp = this.config.get('security.jwtTokenExpiry');
|
||||
const issuedToken = await this.issueAccessToken(loginUser);
|
||||
const refreshToken = await this.refreshService.issueRefreshToken(loginUser);
|
||||
|
||||
// Set login time to now
|
||||
await this.userRepository.update(
|
||||
{ id: loginUser.id },
|
||||
{ loginAt: new Date() },
|
||||
);
|
||||
|
||||
return {
|
||||
challenge: null,
|
||||
challengeSecret: null,
|
||||
authResult: {
|
||||
token: issuedToken,
|
||||
refresh: refreshToken,
|
||||
expires_in: exp,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async loginByRefreshToken(token: string, ip: string) {
|
||||
const refreshToken = await this.refreshService.useRefreshToken(token);
|
||||
const userEntity = refreshToken.user;
|
||||
|
||||
@ -121,9 +205,13 @@ export class AuthService {
|
||||
);
|
||||
|
||||
return {
|
||||
challenge: null,
|
||||
challengeSecret: null,
|
||||
authResult: {
|
||||
token: issuedToken,
|
||||
refresh: refreshToken.token,
|
||||
expires_in: exp,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -193,21 +281,51 @@ export class AuthService {
|
||||
(privileges, ban) => [...privileges, ...(ban.privileges || [])],
|
||||
[],
|
||||
);
|
||||
const privileges = await this.roleService.getUserPrivileges(
|
||||
|
||||
const userPrivileges = await this.roleService.getUserPrivileges(
|
||||
user,
|
||||
bannedPrivileges,
|
||||
);
|
||||
|
||||
// If we only have privilege bans, only restrict those privileges.
|
||||
// If we have a system ban, only return the web privilege.
|
||||
const privileges =
|
||||
!banned || bans.every((ban) => ban.privilegeBan)
|
||||
? userPrivileges
|
||||
: ['web'];
|
||||
|
||||
// Issue new token
|
||||
return this.jwtService.sign({
|
||||
sub: user.id,
|
||||
username: user.username,
|
||||
display_name: user.displayName,
|
||||
language: user.language,
|
||||
banned: banned,
|
||||
privileges: banned
|
||||
? []
|
||||
: privileges.map((privilege) => privilege.privilege),
|
||||
banned,
|
||||
privileges,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create OTP challenge for user's login.
|
||||
* @private
|
||||
* @param userEntity User
|
||||
* @returns Challenge response
|
||||
*/
|
||||
async createOTPChallenge(userEntity: UserEntity) {
|
||||
// Create challenge for auth.
|
||||
const challengeToken = generateString(256);
|
||||
const tokenKey = `chlg:${AuthChallenge.OTP}:${challengeToken}`;
|
||||
const encryptedToken = await this.jwtService.encrypt({
|
||||
token: challengeToken,
|
||||
sub: userEntity.id,
|
||||
});
|
||||
|
||||
// Challenge is only valid for 5 minutes.
|
||||
await this.cache.set(tokenKey, userEntity.id, 300000);
|
||||
return {
|
||||
challenge: AuthChallenge.OTP,
|
||||
challengeSecret: encryptedToken,
|
||||
authResult: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,15 @@ import { AuthModule } from './services/auth/auth.module';
|
||||
import { CatalogModule } from './services/catalog/catalog.module';
|
||||
import { UserMiddleware } from './middleware/user.middleware';
|
||||
import { AssetsModule } from './services/assets/assets.module';
|
||||
import { ThrottlerModule } from '@nestjs/throttler';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([natsClient('auth')]),
|
||||
ThrottlerModule.forRoot({
|
||||
ttl: 60,
|
||||
limit: 10,
|
||||
}),
|
||||
AuthModule,
|
||||
CatalogModule,
|
||||
AssetsModule,
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
Controller,
|
||||
Get,
|
||||
Inject,
|
||||
Ip,
|
||||
Post,
|
||||
UseGuards,
|
||||
UseInterceptors,
|
||||
@ -21,8 +22,10 @@ import { UserInfo } from '@freeblox/shared';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { AuthGuard } from '../../guards/auth.guard';
|
||||
import { UserDto } from './dtos/user.dto';
|
||||
import { LoginResponseDto } from './dtos/login-response.dto';
|
||||
import { ChallengeResponseDto } from './dtos/challenge-response.dto';
|
||||
import { LoginByRefreshTokenDto } from './dtos/login-refresh-token.dto';
|
||||
import { ChallengeRequestDto } from './dtos/challenge-request.dto';
|
||||
import { Throttle } from '@nestjs/throttler';
|
||||
|
||||
@Controller({
|
||||
version: '1',
|
||||
@ -35,17 +38,35 @@ export class AuthController {
|
||||
constructor(@Inject('auth') private auth: ClientProxy) {}
|
||||
|
||||
@Post('login')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({ summary: 'Login by username or email and password' })
|
||||
@ApiOkResponse({ type: LoginResponseDto })
|
||||
async login(@Body() body: LoginDto) {
|
||||
return this.auth.send('auth.login', { body });
|
||||
@ApiOkResponse({ type: ChallengeResponseDto })
|
||||
async login(@Body() body: LoginDto, @Ip() ip: string) {
|
||||
return this.auth.send('auth.login', { body, ip });
|
||||
}
|
||||
|
||||
@Post('challenge')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({ summary: 'Login by challenge' })
|
||||
@ApiOkResponse({ type: ChallengeResponseDto })
|
||||
async challenge(@Body() body: ChallengeRequestDto, @Ip() ip: string) {
|
||||
return this.auth.send('auth.loginByChallenge', {
|
||||
challenge: body.challenge,
|
||||
secret: body.secret,
|
||||
body: body.body,
|
||||
ip,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('refresh')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({ summary: 'Login by refresh token' })
|
||||
@ApiOkResponse({ type: LoginResponseDto })
|
||||
async refresh(@Body() body: LoginByRefreshTokenDto) {
|
||||
return this.auth.send('auth.loginByRefreshToken', { token: body.token });
|
||||
@ApiOkResponse({ type: ChallengeResponseDto })
|
||||
async refresh(@Body() body: LoginByRefreshTokenDto, @Ip() ip: string) {
|
||||
return this.auth.send('auth.loginByRefreshToken', {
|
||||
token: body.token,
|
||||
ip,
|
||||
});
|
||||
}
|
||||
|
||||
@Get('me')
|
||||
|
@ -0,0 +1,13 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { AuthChallenge } from 'apps/auth/src/enums/challenge.enum';
|
||||
|
||||
export class ChallengeRequestDto {
|
||||
@ApiProperty({ type: String, enum: AuthChallenge })
|
||||
challenge: AuthChallenge;
|
||||
|
||||
@ApiProperty()
|
||||
secret: string;
|
||||
|
||||
@ApiProperty()
|
||||
body: Record<string, string>;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { AuthChallenge } from '../../../../../auth/src/enums/challenge.enum';
|
||||
|
||||
export class AuthResultResponse {
|
||||
@ApiProperty()
|
||||
token: string;
|
||||
|
||||
@ApiProperty()
|
||||
refresh: string;
|
||||
|
||||
@ApiProperty()
|
||||
expires_in: number;
|
||||
}
|
||||
|
||||
export class ChallengeResponseDto {
|
||||
@ApiProperty({ type: String, enum: AuthChallenge, nullable: true })
|
||||
challenge: AuthChallenge;
|
||||
|
||||
@ApiProperty({ nullable: true })
|
||||
challengeSecret: string;
|
||||
|
||||
@ApiProperty({ type: AuthResultResponse, nullable: true })
|
||||
authResult: AuthResultResponse;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class LoginResponseDto {
|
||||
@ApiProperty()
|
||||
token: string;
|
||||
|
||||
@ApiProperty()
|
||||
refresh: string;
|
||||
|
||||
@ApiProperty()
|
||||
expires_in: number;
|
||||
}
|
@ -24,6 +24,7 @@ import { lastValueFrom } from 'rxjs';
|
||||
import { CategoryResponseDto } from './dtos/category-response.dto';
|
||||
import { ContentAssetDto } from './dtos/content-asset.dto';
|
||||
import { RequirePrivileges } from '../../decorators/require-privileges.decorator';
|
||||
import { Throttle } from '@nestjs/throttler';
|
||||
|
||||
@Controller({
|
||||
version: '1',
|
||||
@ -42,6 +43,7 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Post('content')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({ summary: 'Create new content' })
|
||||
@ApiOkResponse({ type: ContentResponseDto })
|
||||
@RequirePrivileges('create:*', 'contentedit')
|
||||
@ -83,6 +85,7 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Patch('content/:id')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({ summary: 'Update content details' })
|
||||
@ApiOkResponse({ type: ContentResponseDto })
|
||||
@RequirePrivileges('create:*', 'contentedit')
|
||||
@ -95,6 +98,7 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Post('content/:id/revision')
|
||||
@Throttle(3, 60)
|
||||
@ApiOperation({
|
||||
summary: 'Create a new revision (upload new content for item)',
|
||||
})
|
||||
@ -115,6 +119,7 @@ export class CatalogController {
|
||||
}
|
||||
|
||||
@Patch('content/:id/publish')
|
||||
@Throttle(3, 60)
|
||||
@ApiOkResponse({ type: ContentResponseDto })
|
||||
@ApiOperation({
|
||||
summary: 'Publish content',
|
||||
@ -129,4 +134,9 @@ export class CatalogController {
|
||||
user,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('test')
|
||||
async test() {
|
||||
return this.catalog.send('render.assetid', {});
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { RenderService } from './services/render.service';
|
||||
import { MessagePattern } from '@nestjs/microservices';
|
||||
|
||||
@Controller()
|
||||
export class RenderController {
|
||||
constructor(private readonly renderService: RenderService) {}
|
||||
|
||||
@MessagePattern('render.assetid')
|
||||
async renderAsset({ id }: { id: string }) {
|
||||
return this.renderService.render();
|
||||
}
|
||||
}
|
||||
|
48
apps/render/src/renderer/index.ts
Normal file
48
apps/render/src/renderer/index.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import {
|
||||
Engine,
|
||||
EngineEvents,
|
||||
EnvironmentComponent,
|
||||
EventEmitter,
|
||||
LevelComponent,
|
||||
ViewportComponent,
|
||||
WebGLRenderer,
|
||||
instanceCharacterObject,
|
||||
} from '@freeblox/engine';
|
||||
import { Vector2, Vector3 } from 'three';
|
||||
|
||||
export class BarebonesRenderer extends Engine {
|
||||
public events = new EventEmitter<EngineEvents>();
|
||||
override mount(element: HTMLElement): void {
|
||||
this.element = element;
|
||||
this.render = new WebGLRenderer(element, new Vector2(800, 800), {
|
||||
alpha: true,
|
||||
});
|
||||
this.render.renderer.autoClear = false;
|
||||
this.use(ViewportComponent);
|
||||
this.use(EnvironmentComponent);
|
||||
this.use(LevelComponent);
|
||||
this.getComponent(ViewportComponent).setSize(800, 800);
|
||||
}
|
||||
}
|
||||
|
||||
(async function () {
|
||||
const engine = new BarebonesRenderer();
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
document.body.style.margin = '0';
|
||||
document.body.style.padding = '0';
|
||||
engine.mount(div);
|
||||
|
||||
const level = engine.getComponent(LevelComponent);
|
||||
const viewport = engine.getComponent(ViewportComponent);
|
||||
|
||||
const char = await instanceCharacterObject('test');
|
||||
level.world.add(char);
|
||||
|
||||
viewport.camera.position.set(2, 6, 5);
|
||||
viewport.camera.lookAt(new Vector3(0, 3.5, 0));
|
||||
|
||||
engine.render.renderer.setClearColor(0x000000, 0);
|
||||
engine.render.render();
|
||||
engine.stop();
|
||||
})();
|
@ -1,4 +1,53 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
@Injectable()
|
||||
export class RenderService {}
|
||||
export class RenderService {
|
||||
private logger = new Logger(RenderService.name);
|
||||
|
||||
async render() {
|
||||
const file = readFileSync(join(__dirname, 'renderer.js'), 'utf-8');
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
headless: true,
|
||||
args: [
|
||||
'--use-gl=swiftshader',
|
||||
'--no-sandbox',
|
||||
'--enable-surface-synchronization',
|
||||
],
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 800, height: 800 });
|
||||
|
||||
page
|
||||
.on('console', (message) =>
|
||||
this.logger.log(`${message.type().toUpperCase()} ${message.text()}`),
|
||||
)
|
||||
.on('pageerror', ({ message }) => this.logger.log(message))
|
||||
.on('response', (response) =>
|
||||
this.logger.log(`${response.status()} ${response.url()}`),
|
||||
)
|
||||
.on('requestfailed', (request) =>
|
||||
this.logger.log(`${request.failure().errorText} ${request.url()}`),
|
||||
);
|
||||
|
||||
await page.setContent(
|
||||
`<html><body><script type="application/javascript">${file}</script></body></html>`,
|
||||
{
|
||||
waitUntil: ['load', 'networkidle0'],
|
||||
},
|
||||
);
|
||||
|
||||
const picture = await page.screenshot({
|
||||
encoding: 'base64',
|
||||
omitBackground: true,
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
|
||||
return picture;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,13 @@ services:
|
||||
- ./docker/postgres:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- fblx
|
||||
redis:
|
||||
container_name: fblx-redis
|
||||
image: redis:7-alpine
|
||||
volumes:
|
||||
- fblx-redis:/data
|
||||
networks:
|
||||
- fblx
|
||||
auth:
|
||||
container_name: fblx-auth
|
||||
build:
|
||||
@ -28,6 +35,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=auth
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -49,6 +60,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=catalog
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -66,6 +81,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=game
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -83,6 +102,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=player
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -100,6 +123,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=server
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -117,6 +144,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=session
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -134,6 +165,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=bank
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -151,6 +186,10 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=assets
|
||||
depends_on:
|
||||
- nats
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -171,6 +210,9 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.render.dev
|
||||
depends_on:
|
||||
- nats
|
||||
- redis
|
||||
networks:
|
||||
- fblx
|
||||
environment:
|
||||
@ -185,6 +227,8 @@ services:
|
||||
dockerfile: Dockerfile.dev
|
||||
args:
|
||||
- SERVICE=freeblox-web-service
|
||||
depends_on:
|
||||
- nats
|
||||
networks:
|
||||
- fblx
|
||||
ports:
|
||||
@ -224,3 +268,4 @@ networks:
|
||||
fblx:
|
||||
volumes:
|
||||
fblx-pgadmin:
|
||||
fblx-redis:
|
||||
|
14
libs/shared/src/cache/cache-manager.ts
vendored
Normal file
14
libs/shared/src/cache/cache-manager.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { CacheModule } from '@nestjs/cache-manager';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { redisConfig } from './redis.provider';
|
||||
import * as redisStore from 'cache-manager-redis-store';
|
||||
|
||||
export const getCacheManager = () =>
|
||||
CacheModule.registerAsync({
|
||||
imports: [ConfigModule, ConfigModule.forFeature(redisConfig)],
|
||||
useFactory: (config) => ({
|
||||
store: redisStore,
|
||||
...config.get('redis'),
|
||||
}),
|
||||
inject: [ConfigService],
|
||||
});
|
6
libs/shared/src/cache/redis.provider.ts
vendored
Normal file
6
libs/shared/src/cache/redis.provider.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export const redisConfig = registerAs('redis', () => ({
|
||||
host: String(process.env.REDIS_HOST || 'redis'),
|
||||
port: Number(process.env.REDIS_PORT) || 6379,
|
||||
}));
|
@ -1,5 +1,5 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
import { ConfigModule, ConfigService, registerAs } from '@nestjs/config';
|
||||
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||
|
||||
export const makeTypeOrm = (database: string) =>
|
||||
registerAs(
|
||||
@ -14,3 +14,13 @@ export const makeTypeOrm = (database: string) =>
|
||||
database,
|
||||
} as TypeOrmModuleOptions),
|
||||
);
|
||||
|
||||
export const getTypeOrm = (entities?: any[]) =>
|
||||
TypeOrmModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (config: ConfigService) => ({
|
||||
...config.get('typeorm'),
|
||||
entities,
|
||||
}),
|
||||
});
|
||||
|
@ -12,3 +12,5 @@ export * from './types/userinfo';
|
||||
export * from './types/page-query.interface';
|
||||
export * from './exception/rpc.exception';
|
||||
export * from './filters/rpc-exception.filter';
|
||||
export * from './cache/redis.provider';
|
||||
export * from './cache/cache-manager';
|
||||
|
10
package.json
10
package.json
@ -28,16 +28,22 @@
|
||||
"@aws-sdk/s3-request-presigner": "^3.375.0",
|
||||
"@aws-sdk/url-parser": "^3.374.0",
|
||||
"@aws-sdk/util-format-url": "^3.370.0",
|
||||
"@freeblox/engine": "^0.0.4",
|
||||
"@nestjs/axios": "^3.0.0",
|
||||
"@nestjs/cache-manager": "^2.1.0",
|
||||
"@nestjs/common": "^10.0.3",
|
||||
"@nestjs/config": "^3.0.0",
|
||||
"@nestjs/core": "^10.0.3",
|
||||
"@nestjs/microservices": "^10.0.3",
|
||||
"@nestjs/platform-express": "^10.0.3",
|
||||
"@nestjs/schedule": "^3.0.1",
|
||||
"@nestjs/swagger": "^7.0.11",
|
||||
"@nestjs/throttler": "^4.2.1",
|
||||
"@nestjs/typeorm": "^10.0.0",
|
||||
"axios": "^1.4.0",
|
||||
"bcrypt": "^5.1.0",
|
||||
"cache-manager": "^5.2.3",
|
||||
"cache-manager-redis-store": "^3.0.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.0",
|
||||
"jose": "^4.14.4",
|
||||
@ -53,13 +59,15 @@
|
||||
"rxjs": "^7.8.1",
|
||||
"three": "^0.154.0",
|
||||
"typeorm": "^0.3.17",
|
||||
"uuid": "^9.0.0"
|
||||
"uuid": "^9.0.0",
|
||||
"webpack-merge": "^5.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.5",
|
||||
"@nestjs/schematics": "^10.0.1",
|
||||
"@nestjs/testing": "^10.0.3",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/cron": "^2.0.1",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/multer": "^1.4.7",
|
||||
|
272
pnpm-lock.yaml
272
pnpm-lock.yaml
@ -26,9 +26,15 @@ dependencies:
|
||||
'@aws-sdk/util-format-url':
|
||||
specifier: ^3.370.0
|
||||
version: 3.370.0
|
||||
'@freeblox/engine':
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
'@nestjs/axios':
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0(@nestjs/common@10.0.3)(axios@1.4.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/cache-manager':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/common':
|
||||
specifier: ^10.0.3
|
||||
version: 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
@ -40,13 +46,19 @@ dependencies:
|
||||
version: 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/microservices':
|
||||
specifier: ^10.0.3
|
||||
version: 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
version: 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/platform-express':
|
||||
specifier: ^10.0.3
|
||||
version: 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)
|
||||
'@nestjs/schedule':
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13)
|
||||
'@nestjs/swagger':
|
||||
specifier: ^7.0.11
|
||||
version: 7.0.11(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)
|
||||
'@nestjs/throttler':
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13)
|
||||
'@nestjs/typeorm':
|
||||
specifier: ^10.0.0
|
||||
version: 10.0.0(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17)
|
||||
@ -56,6 +68,12 @@ dependencies:
|
||||
bcrypt:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
cache-manager:
|
||||
specifier: ^5.2.3
|
||||
version: 5.2.3
|
||||
cache-manager-redis-store:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
class-transformer:
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.1
|
||||
@ -104,6 +122,9 @@ dependencies:
|
||||
uuid:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0
|
||||
webpack-merge:
|
||||
specifier: ^5.9.0
|
||||
version: 5.9.0
|
||||
|
||||
devDependencies:
|
||||
'@nestjs/cli':
|
||||
@ -118,6 +139,9 @@ devDependencies:
|
||||
'@types/bcrypt':
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
'@types/cron':
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
@ -1300,6 +1324,10 @@ packages:
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
|
||||
/@dimforge/rapier3d@0.11.2:
|
||||
resolution: {integrity: sha512-B+AKkPmtJxED3goMTGU8v0ju8hUAUQGLgghzCos4G4OeN9X+mJ5lfN2xtNA0n8tJRJk2YfsMk9BOj/6AN89Acg==}
|
||||
dev: false
|
||||
|
||||
/@eslint-community/eslint-utils@4.4.0(eslint@8.43.0):
|
||||
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@ -1337,6 +1365,17 @@ packages:
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/@freeblox/engine@0.0.4:
|
||||
resolution: {integrity: sha512-faxtovSxW6hHNgpOdPeRTYuZk01LiHt8hZA8Vp6cBkdbBMP8jmXBXX/ADFTLv/v9GBXK2DBLbmeZhZ0R46imwg==, tarball: https://git.icynet.eu/api/packages/freeblox/npm/%40freeblox%2Fengine/-/0.0.4/engine-0.0.4.tgz}
|
||||
dependencies:
|
||||
'@dimforge/rapier3d': 0.11.2
|
||||
buffer: 6.0.3
|
||||
reflect-metadata: 0.1.13
|
||||
smart-buffer: 4.2.0
|
||||
three: 0.153.0
|
||||
uuid: 9.0.0
|
||||
dev: false
|
||||
|
||||
/@humanwhocodes/config-array@0.11.10:
|
||||
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
|
||||
engines: {node: '>=10.10.0'}
|
||||
@ -1683,6 +1722,22 @@ packages:
|
||||
rxjs: 7.8.1
|
||||
dev: false
|
||||
|
||||
/@nestjs/cache-manager@2.1.0(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(reflect-metadata@0.1.13)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-9kep3a8Mq5cMuXN/anGhSYc0P48CRBXk5wyJJRBFxhNkCH8AIzZF4CASGVDIEMmm3OjVcEUHojjyJwCODS17Qw==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^9.0.0 || ^10.0.0
|
||||
'@nestjs/core': ^9.0.0 || ^10.0.0
|
||||
cache-manager: <=5
|
||||
reflect-metadata: ^0.1.12
|
||||
rxjs: ^7.0.0
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
cache-manager: 5.2.3
|
||||
reflect-metadata: 0.1.13
|
||||
rxjs: 7.8.1
|
||||
dev: false
|
||||
|
||||
/@nestjs/cli@10.0.5:
|
||||
resolution: {integrity: sha512-Btc1lzAkm4j+af9YA0Kv+6N2x7vDneEhsozzEp87kHZrONYNS8zg/SBFTRx5b/e6g0MJshv6vP56PVrdNZy3kA==}
|
||||
engines: {node: '>= 16'}
|
||||
@ -1778,7 +1833,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/microservices': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/microservices': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/platform-express': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)
|
||||
'@nuxtjs/opencollective': 0.3.2
|
||||
fast-safe-stringify: 2.1.1
|
||||
@ -1810,7 +1865,7 @@ packages:
|
||||
reflect-metadata: 0.1.13
|
||||
dev: false
|
||||
|
||||
/@nestjs/microservices@10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1):
|
||||
/@nestjs/microservices@10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-ySAdASLA2FLD0ScEmAHObNsg/IdnG4pYXWxQKLO3co3CAAwHCjF0D4kI2SeegBx89KU0D1wPLvLYzRI0pXh4jQ==}
|
||||
peerDependencies:
|
||||
'@grpc/grpc-js': '*'
|
||||
@ -1848,6 +1903,7 @@ packages:
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
cache-manager: 5.2.3
|
||||
iterare: 1.2.1
|
||||
nats: 2.15.1
|
||||
reflect-metadata: 0.1.13
|
||||
@ -1870,6 +1926,20 @@ packages:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/@nestjs/schedule@3.0.1(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13):
|
||||
resolution: {integrity: sha512-4CAFu4rE/QPYnz/icRg3GiuLmY1bXopG8bWTJ9d7bXzaHBaPKIjGvZ20wsK8P+MncrVCkmK0iYhQrNj0cwX9+A==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||
'@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||
reflect-metadata: ^0.1.12
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
cron: 2.3.1
|
||||
reflect-metadata: 0.1.13
|
||||
uuid: 9.0.0
|
||||
dev: false
|
||||
|
||||
/@nestjs/schematics@10.0.1(chokidar@3.5.3)(typescript@5.1.3):
|
||||
resolution: {integrity: sha512-buxpYtSwOmWyf0nUJWJCkCkYITwbOfIEKHTnGS7sDbcfaajrOFXb5pPAGD2E1CUb3C1+NkQIURPKzs0IouZTQg==}
|
||||
peerDependencies:
|
||||
@ -1929,11 +1999,24 @@ packages:
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/microservices': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/microservices': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(cache-manager@5.2.3)(nats@2.15.1)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/platform-express': 10.0.3(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)
|
||||
tslib: 2.5.3
|
||||
dev: true
|
||||
|
||||
/@nestjs/throttler@4.2.1(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13):
|
||||
resolution: {integrity: sha512-wVPMuIyr0KdrK1RVVQceWVNesogCm9IgYC1V5EkaTZ+usIE4qxEyzdwU5IqQLgOO/Loiq98MLwReDxazX7i9Uw==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||
'@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0
|
||||
reflect-metadata: ^0.1.13
|
||||
dependencies:
|
||||
'@nestjs/common': 10.0.3(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.0.3(@nestjs/common@10.0.3)(@nestjs/microservices@10.0.3)(@nestjs/platform-express@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)
|
||||
md5: 2.3.0
|
||||
reflect-metadata: 0.1.13
|
||||
dev: false
|
||||
|
||||
/@nestjs/typeorm@10.0.0(@nestjs/common@10.0.3)(@nestjs/core@10.0.3)(reflect-metadata@0.1.13)(rxjs@7.8.1)(typeorm@0.3.17):
|
||||
resolution: {integrity: sha512-WQU4HCDTz4UavsFzvGUKDHqi0MO5K47yFoPXdmh+Z/hCNO7SHCMmV9jLiLukM8n5nKUqJ3jDqiljkWBcZPdCtA==}
|
||||
peerDependencies:
|
||||
@ -2044,6 +2127,55 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@redis/bloom@1.2.0(@redis/client@1.5.8):
|
||||
resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==}
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': 1.5.8
|
||||
dev: false
|
||||
|
||||
/@redis/client@1.5.8:
|
||||
resolution: {integrity: sha512-xzElwHIO6rBAqzPeVnCzgvrnBEcFL1P0w8P65VNLRkdVW8rOE58f52hdj0BDgmsdOm4f1EoXPZtH4Fh7M/qUpw==}
|
||||
engines: {node: '>=14'}
|
||||
dependencies:
|
||||
cluster-key-slot: 1.1.2
|
||||
generic-pool: 3.9.0
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/@redis/graph@1.1.0(@redis/client@1.5.8):
|
||||
resolution: {integrity: sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==}
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': 1.5.8
|
||||
dev: false
|
||||
|
||||
/@redis/json@1.0.4(@redis/client@1.5.8):
|
||||
resolution: {integrity: sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==}
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': 1.5.8
|
||||
dev: false
|
||||
|
||||
/@redis/search@1.1.3(@redis/client@1.5.8):
|
||||
resolution: {integrity: sha512-4Dg1JjvCevdiCBTZqjhKkGoC5/BcB7k9j99kdMnaXFXg8x4eyOIVg9487CMv7/BUVkFLZCaIh8ead9mU15DNng==}
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': 1.5.8
|
||||
dev: false
|
||||
|
||||
/@redis/time-series@1.0.4(@redis/client@1.5.8):
|
||||
resolution: {integrity: sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==}
|
||||
peerDependencies:
|
||||
'@redis/client': ^1.0.0
|
||||
dependencies:
|
||||
'@redis/client': 1.5.8
|
||||
dev: false
|
||||
|
||||
/@sinclair/typebox@0.25.24:
|
||||
resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==}
|
||||
dev: true
|
||||
@ -2554,6 +2686,13 @@ packages:
|
||||
resolution: {integrity: sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==}
|
||||
dev: true
|
||||
|
||||
/@types/cron@2.0.1:
|
||||
resolution: {integrity: sha512-WHa/1rtNtD2Q/H0+YTTZoty+/5rcE66iAFX2IY+JuUoOACsevYyFkSYu/2vdw+G5LrmO7Lxowrqm0av4k3qWNQ==}
|
||||
dependencies:
|
||||
'@types/luxon': 3.3.1
|
||||
'@types/node': 20.3.2
|
||||
dev: true
|
||||
|
||||
/@types/eslint-scope@3.7.4:
|
||||
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
|
||||
dependencies:
|
||||
@ -2627,6 +2766,10 @@ packages:
|
||||
resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
|
||||
dev: true
|
||||
|
||||
/@types/luxon@3.3.1:
|
||||
resolution: {integrity: sha512-XOS5nBcgEeP2PpcqJHjCWhUCAzGfXIU8ILOSLpx2FhxqMW9KdxgCGXNOEKGVBfveKtIpztHzKK5vSRVLyW/NqA==}
|
||||
dev: true
|
||||
|
||||
/@types/mime@1.3.2:
|
||||
resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==}
|
||||
dev: true
|
||||
@ -3427,6 +3570,19 @@ packages:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
/cache-manager-redis-store@3.0.1:
|
||||
resolution: {integrity: sha512-o560kw+dFqusC9lQJhcm6L2F2fMKobJ5af+FoR2PdnMVdpQ3f3Bz6qzvObTGyvoazQJxjQNWgMQeChP4vRTuXQ==}
|
||||
engines: {node: '>= 16.18.0'}
|
||||
dependencies:
|
||||
redis: 4.6.7
|
||||
dev: false
|
||||
|
||||
/cache-manager@5.2.3:
|
||||
resolution: {integrity: sha512-9OErI8fksFkxAMJ8Mco0aiZSdphyd90HcKiOMJQncSlU1yq/9lHHxrT8PDayxrmr9IIIZPOAEfXuGSD7g29uog==}
|
||||
dependencies:
|
||||
lodash.clonedeep: 4.5.0
|
||||
lru-cache: 9.1.2
|
||||
|
||||
/call-bind@1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
dependencies:
|
||||
@ -3475,6 +3631,10 @@ packages:
|
||||
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
|
||||
dev: true
|
||||
|
||||
/charenc@0.0.2:
|
||||
resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==}
|
||||
dev: false
|
||||
|
||||
/chokidar@3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
@ -3583,11 +3743,25 @@ packages:
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
/clone-deep@4.0.1:
|
||||
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
is-plain-object: 2.0.4
|
||||
kind-of: 6.0.3
|
||||
shallow-clone: 3.0.1
|
||||
dev: false
|
||||
|
||||
/clone@1.0.4:
|
||||
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
|
||||
engines: {node: '>=0.8'}
|
||||
dev: true
|
||||
|
||||
/cluster-key-slot@1.1.2:
|
||||
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/co@4.6.0:
|
||||
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
|
||||
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
|
||||
@ -3740,6 +3914,12 @@ packages:
|
||||
/create-require@1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
|
||||
/cron@2.3.1:
|
||||
resolution: {integrity: sha512-1eRRlIT0UfIqauwbG9pkg3J6CX9A6My2ytJWqAXoK0T9oJnUZTzGBNPxao0zjodIbPgf8UQWjE62BMb9eVllSQ==}
|
||||
dependencies:
|
||||
luxon: 3.3.0
|
||||
dev: false
|
||||
|
||||
/cross-fetch@4.0.0:
|
||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
||||
dependencies:
|
||||
@ -3756,6 +3936,10 @@ packages:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
/crypt@0.0.2:
|
||||
resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
|
||||
dev: false
|
||||
|
||||
/data-uri-to-buffer@5.0.1:
|
||||
resolution: {integrity: sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg==}
|
||||
engines: {node: '>= 14'}
|
||||
@ -4484,6 +4668,11 @@ packages:
|
||||
wide-align: 1.1.5
|
||||
dev: false
|
||||
|
||||
/generic-pool@3.9.0:
|
||||
resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==}
|
||||
engines: {node: '>= 4'}
|
||||
dev: false
|
||||
|
||||
/gensync@1.0.0-beta.2:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@ -4839,6 +5028,10 @@ packages:
|
||||
binary-extensions: 2.2.0
|
||||
dev: true
|
||||
|
||||
/is-buffer@1.1.6:
|
||||
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
|
||||
dev: false
|
||||
|
||||
/is-core-module@2.12.1:
|
||||
resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==}
|
||||
dependencies:
|
||||
@ -4880,6 +5073,13 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-plain-object@2.0.4:
|
||||
resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
isobject: 3.0.1
|
||||
dev: false
|
||||
|
||||
/is-stream@2.0.1:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -4896,6 +5096,11 @@ packages:
|
||||
/isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
/isobject@3.0.1:
|
||||
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/istanbul-lib-coverage@3.2.0:
|
||||
resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -5464,6 +5669,11 @@ packages:
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/kind-of@6.0.3:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/kleur@3.0.3:
|
||||
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
|
||||
engines: {node: '>=6'}
|
||||
@ -5558,6 +5768,9 @@ packages:
|
||||
p-locate: 5.0.0
|
||||
dev: true
|
||||
|
||||
/lodash.clonedeep@4.5.0:
|
||||
resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==}
|
||||
|
||||
/lodash.memoize@4.1.2:
|
||||
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||
dev: true
|
||||
@ -5598,6 +5811,15 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/lru-cache@9.1.2:
|
||||
resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==}
|
||||
engines: {node: 14 || >=16.14}
|
||||
|
||||
/luxon@3.3.0:
|
||||
resolution: {integrity: sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/macos-release@2.5.1:
|
||||
resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==}
|
||||
engines: {node: '>=6'}
|
||||
@ -5625,6 +5847,14 @@ packages:
|
||||
tmpl: 1.0.5
|
||||
dev: true
|
||||
|
||||
/md5@2.3.0:
|
||||
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
|
||||
dependencies:
|
||||
charenc: 0.0.2
|
||||
crypt: 0.0.2
|
||||
is-buffer: 1.1.6
|
||||
dev: false
|
||||
|
||||
/media-typer@0.3.0:
|
||||
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -6464,6 +6694,17 @@ packages:
|
||||
resolve: 1.22.2
|
||||
dev: false
|
||||
|
||||
/redis@4.6.7:
|
||||
resolution: {integrity: sha512-KrkuNJNpCwRm5vFJh0tteMxW8SaUzkm5fBH7eL5hd/D0fAkzvapxbfGPP/r+4JAXdQuX7nebsBkBqA2RHB7Usw==}
|
||||
dependencies:
|
||||
'@redis/bloom': 1.2.0(@redis/client@1.5.8)
|
||||
'@redis/client': 1.5.8
|
||||
'@redis/graph': 1.1.0(@redis/client@1.5.8)
|
||||
'@redis/json': 1.0.4(@redis/client@1.5.8)
|
||||
'@redis/search': 1.1.3(@redis/client@1.5.8)
|
||||
'@redis/time-series': 1.0.4(@redis/client@1.5.8)
|
||||
dev: false
|
||||
|
||||
/reflect-metadata@0.1.13:
|
||||
resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==}
|
||||
|
||||
@ -6645,6 +6886,13 @@ packages:
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/shallow-clone@3.0.1:
|
||||
resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
kind-of: 6.0.3
|
||||
dev: false
|
||||
|
||||
/shebang-command@2.0.0:
|
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
||||
engines: {node: '>=8'}
|
||||
@ -7024,6 +7272,10 @@ packages:
|
||||
engines: {node: '>=0.2.6'}
|
||||
dev: false
|
||||
|
||||
/three@0.153.0:
|
||||
resolution: {integrity: sha512-OCP2/uQR6GcDpSLnJt/3a4mdS0kNWcbfUXIwLoEMgLzEUIVIYsSDwskpmOii/AkDM+BBwrl6+CKgrjX9+E2aWg==}
|
||||
dev: false
|
||||
|
||||
/three@0.154.0:
|
||||
resolution: {integrity: sha512-Uzz8C/5GesJzv8i+Y2prEMYUwodwZySPcNhuJUdsVMH2Yn4Nm8qlbQe6qRN5fOhg55XB0WiLfTPBxVHxpE60ug==}
|
||||
dev: false
|
||||
@ -7416,6 +7668,14 @@ packages:
|
||||
/webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
|
||||
/webpack-merge@5.9.0:
|
||||
resolution: {integrity: sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
clone-deep: 4.0.1
|
||||
wildcard: 2.0.1
|
||||
dev: false
|
||||
|
||||
/webpack-node-externals@3.0.0:
|
||||
resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==}
|
||||
engines: {node: '>=6'}
|
||||
@ -7525,6 +7785,10 @@ packages:
|
||||
string-width: 4.2.3
|
||||
dev: false
|
||||
|
||||
/wildcard@2.0.1:
|
||||
resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
|
||||
dev: false
|
||||
|
||||
/windows-release@4.0.0:
|
||||
resolution: {integrity: sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -12,8 +12,10 @@ const writeGlobEntry = (pattern, to) => {
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = function (config) {
|
||||
const appName = process.argv[process.argv.length - 1];
|
||||
|
||||
const configs = [
|
||||
function (config) {
|
||||
config.entry = {
|
||||
main: path.join(__dirname, 'apps', appName, 'src', 'main.ts'),
|
||||
...writeGlobEntry(
|
||||
@ -30,5 +32,31 @@ module.exports = function (config) {
|
||||
filename: '[name].js',
|
||||
libraryTarget: 'commonjs',
|
||||
};
|
||||
|
||||
return config;
|
||||
},
|
||||
];
|
||||
|
||||
if (appName === 'render') {
|
||||
const config2 = {
|
||||
entry: {
|
||||
renderer:
|
||||
appName === 'render'
|
||||
? path.resolve('apps', appName, 'src', 'renderer', 'index.ts')
|
||||
: undefined,
|
||||
},
|
||||
target: 'web',
|
||||
externalsPresets: {},
|
||||
externals: {
|
||||
'@dimforge/rapier3d': 'RAPIER',
|
||||
},
|
||||
output: {
|
||||
path: `${__dirname}/dist/apps/${appName}`,
|
||||
filename: '[name].js',
|
||||
libraryTarget: '',
|
||||
},
|
||||
};
|
||||
configs.push(config2);
|
||||
}
|
||||
|
||||
module.exports = configs;
|
||||
|
Loading…
Reference in New Issue
Block a user