mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
11
projects/sandbox/.dockerignore
Normal file
11
projects/sandbox/.dockerignore
Normal file
@@ -0,0 +1,11 @@
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
node_modules
|
||||
npm-debug.log
|
||||
README.md
|
||||
.next
|
||||
.git
|
||||
|
||||
.yalc/
|
||||
yalc.lock
|
||||
testApi/
|
25
projects/sandbox/.eslintrc.js
Normal file
25
projects/sandbox/.eslintrc.js
Normal file
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: ['plugin:@typescript-eslint/recommended'],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true
|
||||
},
|
||||
ignorePatterns: ['.eslintrc.js'],
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/no-var-requires': 'off'
|
||||
}
|
||||
};
|
34
projects/sandbox/.gitignore
vendored
Normal file
34
projects/sandbox/.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# dependencies
|
||||
node_modules/
|
||||
# next.js
|
||||
.next/
|
||||
out/
|
||||
# production
|
||||
build/
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
platform.json
|
||||
testApi/
|
||||
local/
|
||||
.husky/
|
||||
data/*.local.*
|
||||
|
||||
storage/
|
50
projects/sandbox/Dockerfile
Normal file
50
projects/sandbox/Dockerfile
Normal file
@@ -0,0 +1,50 @@
|
||||
# --------- install dependence -----------
|
||||
FROM python:3.11-alpine AS python_base
|
||||
|
||||
# 安装make和g++
|
||||
RUN apk add --no-cache make g++
|
||||
|
||||
FROM node:20.13-alpine AS install
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ARG proxy
|
||||
RUN [ -z "$proxy" ] || sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
||||
RUN apk add --no-cache make g++
|
||||
|
||||
# copy py3.11
|
||||
COPY --from=python_base /usr/local /usr/local
|
||||
|
||||
RUN npm install -g pnpm@8.6.2
|
||||
RUN [ -z "$proxy" ] || pnpm config set registry https://registry.npmmirror.com
|
||||
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||
COPY ./projects/sandbox/package.json ./projects/sandbox/package.json
|
||||
|
||||
RUN [ -f pnpm-lock.yaml ] || (echo "Lockfile not found." && exit 1)
|
||||
|
||||
RUN pnpm i
|
||||
|
||||
# --------- builder -----------
|
||||
FROM node:20.13-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-workspace.yaml /app
|
||||
COPY --from=install /app/node_modules /app/node_modules
|
||||
COPY ./projects/sandbox /app/projects/sandbox
|
||||
COPY --from=install /app/projects/sandbox /app/projects/sandbox
|
||||
|
||||
RUN npm install -g pnpm@8.6.2
|
||||
RUN pnpm --filter=sandbox build
|
||||
|
||||
# --------- runner -----------
|
||||
FROM node:20.13-alpine AS runner
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /app/node_modules /app/node_modules
|
||||
COPY --from=builder /app/projects/sandbox /app/projects/sandbox
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
CMD ["node", "projects/sandbox/dist/main.js"]
|
73
projects/sandbox/README.md
Normal file
73
projects/sandbox/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<p align="center">
|
||||
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
|
||||
</p>
|
||||
|
||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||
|
||||
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
||||
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
||||
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
|
||||
</p>
|
||||
<!--[](https://opencollective.com/nest#backer)
|
||||
[](https://opencollective.com/nest#sponsor)-->
|
||||
|
||||
## Description
|
||||
|
||||
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ pnpm install
|
||||
```
|
||||
|
||||
## Running the app
|
||||
|
||||
```bash
|
||||
# development
|
||||
$ pnpm run start
|
||||
|
||||
# watch mode
|
||||
$ pnpm run start:dev
|
||||
|
||||
# production mode
|
||||
$ pnpm run start:prod
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
# unit tests
|
||||
$ pnpm run test
|
||||
|
||||
# e2e tests
|
||||
$ pnpm run test:e2e
|
||||
|
||||
# test coverage
|
||||
$ pnpm run test:cov
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||
|
||||
## Stay in touch
|
||||
|
||||
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
|
||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||
|
||||
## License
|
||||
|
||||
Nest is [MIT licensed](LICENSE).
|
9
projects/sandbox/nest-cli.json
Normal file
9
projects/sandbox/nest-cli.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true,
|
||||
"plugins": ["@nestjs/swagger"]
|
||||
}
|
||||
}
|
69
projects/sandbox/package.json
Normal file
69
projects/sandbox/package.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"name": "sandbox",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"build": "nest build",
|
||||
"start": "nest start",
|
||||
"dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"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-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/static": "^7.0.4",
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/platform-fastify": "^10.3.8",
|
||||
"@nestjs/swagger": "^7.3.1",
|
||||
"fastify": "^4.27.0",
|
||||
"isolated-vm": "^4.7.2",
|
||||
"node-gyp": "^10.1.0",
|
||||
"reflect-metadata": "^0.2.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@nestjs/testing": "^10.0.0",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/node": "^20.3.1",
|
||||
"@types/supertest": "^6.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"eslint": "^8.42.0",
|
||||
"jest": "^29.5.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^6.3.3",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-loader": "^9.4.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
10
projects/sandbox/src/app.module.ts
Normal file
10
projects/sandbox/src/app.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { SandboxController } from './sandbox/sandbox.controller';
|
||||
import { SandboxService } from './sandbox/sandbox.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [SandboxController],
|
||||
providers: [SandboxService]
|
||||
})
|
||||
export class AppModule {}
|
18
projects/sandbox/src/http-exception.filter.ts
Normal file
18
projects/sandbox/src/http-exception.filter.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
|
||||
import { FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { getErrText } from './utils';
|
||||
|
||||
@Catch()
|
||||
export class HttpExceptionFilter implements ExceptionFilter {
|
||||
catch(error: any, host: ArgumentsHost) {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<FastifyReply>();
|
||||
const request = ctx.getRequest<FastifyRequest>();
|
||||
|
||||
response.status(500).send({
|
||||
success: false,
|
||||
time: new Date(),
|
||||
msg: getErrText(error)
|
||||
});
|
||||
}
|
||||
}
|
38
projects/sandbox/src/main.ts
Normal file
38
projects/sandbox/src/main.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { AppModule } from './app.module';
|
||||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
||||
import { HttpExceptionFilter } from './http-exception.filter';
|
||||
import { ResponseInterceptor } from './response';
|
||||
|
||||
async function bootstrap(port: number) {
|
||||
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
|
||||
|
||||
// 使用全局异常过滤器
|
||||
app.useGlobalFilters(new HttpExceptionFilter());
|
||||
|
||||
app.useGlobalInterceptors(new ResponseInterceptor());
|
||||
|
||||
const config = new DocumentBuilder()
|
||||
.setTitle('Cats example')
|
||||
.setDescription('The cats API description')
|
||||
.setVersion('1.0')
|
||||
.addTag('cats')
|
||||
.build();
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
SwaggerModule.setup('api', app, document);
|
||||
|
||||
try {
|
||||
await app.listen(port, '0.0.0.0');
|
||||
console.log(`Application is running on: ${await app.getUrl()}`);
|
||||
} catch (error) {
|
||||
if (error.code === 'EADDRINUSE') {
|
||||
console.warn(`Port ${port} is already in use, trying next port...`);
|
||||
await bootstrap(port + 1);
|
||||
} else {
|
||||
console.error(`Failed to start application: ${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
bootstrap(3000);
|
15
projects/sandbox/src/response.ts
Normal file
15
projects/sandbox/src/response.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class ResponseInterceptor implements NestInterceptor {
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
||||
return next.handle().pipe(
|
||||
map((data) => ({
|
||||
success: true,
|
||||
data
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
4
projects/sandbox/src/sandbox/dto/create-sandbox.dto.ts
Normal file
4
projects/sandbox/src/sandbox/dto/create-sandbox.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export class RunCodeDto {
|
||||
code: string;
|
||||
variables: object;
|
||||
}
|
20
projects/sandbox/src/sandbox/sandbox.controller.spec.ts
Normal file
20
projects/sandbox/src/sandbox/sandbox.controller.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { SandboxController } from './sandbox.controller';
|
||||
import { SandboxService } from './sandbox.service';
|
||||
|
||||
describe('SandboxController', () => {
|
||||
let controller: SandboxController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [SandboxController],
|
||||
providers: [SandboxService]
|
||||
}).compile();
|
||||
|
||||
controller = module.get<SandboxController>(SandboxController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
15
projects/sandbox/src/sandbox/sandbox.controller.ts
Normal file
15
projects/sandbox/src/sandbox/sandbox.controller.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Controller, Post, Body, HttpCode } from '@nestjs/common';
|
||||
import { SandboxService } from './sandbox.service';
|
||||
import { RunCodeDto } from './dto/create-sandbox.dto';
|
||||
import { WorkerNameEnum, runWorker } from 'src/worker/utils';
|
||||
|
||||
@Controller('sandbox')
|
||||
export class SandboxController {
|
||||
constructor(private readonly sandboxService: SandboxService) {}
|
||||
|
||||
@Post('/js')
|
||||
@HttpCode(200)
|
||||
runJs(@Body() codeProps: RunCodeDto) {
|
||||
return runWorker(WorkerNameEnum.runJs, codeProps);
|
||||
}
|
||||
}
|
9
projects/sandbox/src/sandbox/sandbox.module.ts
Normal file
9
projects/sandbox/src/sandbox/sandbox.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { SandboxService } from './sandbox.service';
|
||||
import { SandboxController } from './sandbox.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [SandboxController],
|
||||
providers: [SandboxService]
|
||||
})
|
||||
export class SandboxModule {}
|
18
projects/sandbox/src/sandbox/sandbox.service.spec.ts
Normal file
18
projects/sandbox/src/sandbox/sandbox.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { SandboxService } from './sandbox.service';
|
||||
|
||||
describe('SandboxService', () => {
|
||||
let service: SandboxService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [SandboxService]
|
||||
}).compile();
|
||||
|
||||
service = module.get<SandboxService>(SandboxService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
10
projects/sandbox/src/sandbox/sandbox.service.ts
Normal file
10
projects/sandbox/src/sandbox/sandbox.service.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { RunCodeDto } from './dto/create-sandbox.dto';
|
||||
import { WorkerNameEnum, runWorker } from 'src/worker/utils';
|
||||
|
||||
@Injectable()
|
||||
export class SandboxService {
|
||||
runJs(params: RunCodeDto) {
|
||||
return runWorker(WorkerNameEnum.runJs, params);
|
||||
}
|
||||
}
|
14
projects/sandbox/src/utils.ts
Normal file
14
projects/sandbox/src/utils.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export const replaceSensitiveText = (text: string) => {
|
||||
// 1. http link
|
||||
text = text.replace(/(?<=https?:\/\/)[^\s]+/g, 'xxx');
|
||||
// 2. nx-xxx 全部替换成xxx
|
||||
text = text.replace(/ns-[\w-]+/g, 'xxx');
|
||||
|
||||
return text;
|
||||
};
|
||||
|
||||
export const getErrText = (err: any, def = '') => {
|
||||
const msg: string = typeof err === 'string' ? err : err?.message ?? def;
|
||||
msg && console.log('error =>', msg);
|
||||
return replaceSensitiveText(msg);
|
||||
};
|
38
projects/sandbox/src/worker/runJs.ts
Normal file
38
projects/sandbox/src/worker/runJs.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { RunCodeDto } from 'src/sandbox/dto/create-sandbox.dto';
|
||||
import { parentPort } from 'worker_threads';
|
||||
import { workerResponse } from './utils';
|
||||
|
||||
// @ts-ignore
|
||||
const ivm = require('isolated-vm');
|
||||
|
||||
parentPort?.on('message', ({ code, variables = {} }: RunCodeDto) => {
|
||||
const resolve = (data: any) => workerResponse({ parentPort, type: 'success', data });
|
||||
const reject = (error: any) => workerResponse({ parentPort, type: 'error', data: error });
|
||||
|
||||
const isolate = new ivm.Isolate({ memoryLimit: 32 });
|
||||
const context = isolate.createContextSync();
|
||||
const jail = context.global;
|
||||
|
||||
// custom log function
|
||||
jail.setSync('responseData', function (args: any): any {
|
||||
if (typeof args === 'object') {
|
||||
resolve(args);
|
||||
} else {
|
||||
reject('Not an invalid response');
|
||||
}
|
||||
});
|
||||
|
||||
// Add global variables
|
||||
jail.setSync('variables', new ivm.ExternalCopy(variables).copyInto());
|
||||
|
||||
try {
|
||||
const scriptCode = `
|
||||
${code}
|
||||
responseData(main(variables))`;
|
||||
context.evalSync(scriptCode, { timeout: 6000 });
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
});
|
47
projects/sandbox/src/worker/utils.ts
Normal file
47
projects/sandbox/src/worker/utils.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { type MessagePort, Worker } from 'worker_threads';
|
||||
import * as path from 'path';
|
||||
|
||||
export enum WorkerNameEnum {
|
||||
runJs = 'runJs',
|
||||
runPy = 'runPy'
|
||||
}
|
||||
|
||||
type WorkerResponseType = { type: 'success' | 'error'; data: any };
|
||||
|
||||
export const getWorker = (name: WorkerNameEnum) => {
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === 'production' ? 'projects/sandbox/dist/worker' : 'dist/worker';
|
||||
const workerPath = path.join(process.cwd(), baseUrl, `${name}.js`);
|
||||
return new Worker(workerPath);
|
||||
};
|
||||
|
||||
export const runWorker = <T = any>(name: WorkerNameEnum, params?: Record<string, any>) => {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
const worker = getWorker(name);
|
||||
|
||||
worker.postMessage(params);
|
||||
|
||||
worker.on('message', (msg: WorkerResponseType) => {
|
||||
if (msg.type === 'error') return reject(msg.data);
|
||||
|
||||
resolve(msg.data);
|
||||
worker.terminate();
|
||||
});
|
||||
|
||||
worker.on('error', (err) => {
|
||||
reject(err);
|
||||
worker.terminate();
|
||||
});
|
||||
worker.on('messageerror', (err) => {
|
||||
reject(err);
|
||||
worker.terminate();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const workerResponse = ({
|
||||
parentPort,
|
||||
...data
|
||||
}: WorkerResponseType & { parentPort?: MessagePort }) => {
|
||||
parentPort?.postMessage(data);
|
||||
};
|
21
projects/sandbox/test/app.e2e-spec.ts
Normal file
21
projects/sandbox/test/app.e2e-spec.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from './../src/app.module';
|
||||
|
||||
describe('AppController (e2e)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||
imports: [AppModule]
|
||||
}).compile();
|
||||
|
||||
app = moduleFixture.createNestApplication();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('/ (GET)', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(200).expect('Hello World!');
|
||||
});
|
||||
});
|
9
projects/sandbox/test/jest-e2e.json
Normal file
9
projects/sandbox/test/jest-e2e.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"rootDir": ".",
|
||||
"testEnvironment": "node",
|
||||
"testRegex": ".e2e-spec.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
}
|
||||
}
|
4
projects/sandbox/tsconfig.build.json
Normal file
4
projects/sandbox/tsconfig.build.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
}
|
21
projects/sandbox/tsconfig.json
Normal file
21
projects/sandbox/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"noFallthroughCasesInSwitch": false
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user