diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7d0e4fd7..dcfe853d 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -100,6 +100,7 @@ export interface Context { [Context.config]: Context.Config [Context.events]: Events [Context.session]: Session + baseDir: string http: Quester } @@ -129,6 +130,7 @@ export class Context extends cordis.Context { constructor(config: Context.Config = {}) { super(config) + this.baseDir = globalThis.process?.cwd() || '' this.http = new Quester(config.request) this.on('internal/warning', function (format, ...args) { diff --git a/packages/server-proxy/src/index.ts b/packages/server-proxy/src/index.ts index be9d979f..54f03676 100644 --- a/packages/server-proxy/src/index.ts +++ b/packages/server-proxy/src/index.ts @@ -1,17 +1,17 @@ -import { Context, Quester, Schema } from '@satorijs/core' +import { Context, Quester, Schema } from '@satorijs/satori' import {} from '@satorijs/router' import internal from 'stream' declare module '@satorijs/core' { interface Context { - 'server\.proxy': ProxyService + 'server.proxy': ProxyServer } } -class ProxyService { +class ProxyServer { static inject = ['router'] - constructor(protected ctx: Context, public config: ProxyService.Config) { + constructor(protected ctx: Context, public config: ProxyServer.Config) { const logger = ctx.logger('proxy') ctx.router.get(config.path + '/:url(.*)', async (koa) => { @@ -26,11 +26,11 @@ class ProxyService { } }) - ctx.root.provide('server\.proxy', this) + ctx.root.provide('server.proxy', this) } } -namespace ProxyService { +namespace ProxyServer { export interface Config { path?: string } @@ -40,4 +40,4 @@ namespace ProxyService { }) } -export default ProxyService +export default ProxyServer diff --git a/packages/server-temp/.npmignore b/packages/server-temp/.npmignore new file mode 100644 index 00000000..7e5fcbc1 --- /dev/null +++ b/packages/server-temp/.npmignore @@ -0,0 +1,2 @@ +.DS_Store +tsconfig.tsbuildinfo diff --git a/packages/server-temp/package.json b/packages/server-temp/package.json new file mode 100644 index 00000000..92ccc178 --- /dev/null +++ b/packages/server-temp/package.json @@ -0,0 +1,33 @@ +{ + "name": "@satorijs/server-temp", + "description": "Temp server plugin for cordis", + "version": "1.0.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "files": [ + "lib", + "src" + ], + "author": "Shigma ", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/satorijs/satori.git", + "directory": "packages/server-temp" + }, + "bugs": { + "url": "https://github.com/satorijs/satori/issues" + }, + "homepage": "https://github.com/satorijs/satori/tree/master/packages/temp", + "keywords": [ + "cordis", + "router", + "http", + "temporary", + "server", + "service" + ], + "peerDependencies": { + "@satorijs/satori": "^3.2.0" + } +} diff --git a/packages/server-temp/src/index.ts b/packages/server-temp/src/index.ts new file mode 100644 index 00000000..317c2c2a --- /dev/null +++ b/packages/server-temp/src/index.ts @@ -0,0 +1,81 @@ +import { Context, Dict, Schema, Time } from '@satorijs/satori' +import {} from '@satorijs/router' +import { createReadStream } from 'fs' +import { mkdir, rm, writeFile } from 'fs/promises' +import internal from 'stream' + +declare module '@satorijs/core' { + interface Context { + 'server.temp': TempServer + } +} + +interface Entry { + path: string + url: string + dispose?: () => void +} + +class TempServer { + static inject = ['router'] + + public baseDir!: string + public entries: Dict = Object.create(null) + + constructor(protected ctx: Context, public config: TempServer.Config) { + const logger = ctx.logger('temp') + + ctx.router.get(config.path + '/:name', async (koa) => { + logger.debug(koa.params.name) + const entry = this.entries[koa.params.name] + if (!entry) return koa.status = 404 + koa.body = createReadStream(entry.path) + }) + + ctx.on('ready', () => this.start()) + ctx.on('dispose', () => this.start()) + } + + async start() { + this.baseDir = this.ctx.baseDir + '/temp/' + Math.random().toString(36).slice(2) + '/' + await mkdir(this.baseDir, { recursive: true }) + this.ctx.root.provide('server.temp', this) + } + + async stop() { + await rm(this.baseDir, { recursive: true }) + } + + async create(data: string | Buffer | internal.Readable) { + const name = Math.random().toString(36).slice(2) + const url = this.ctx.router.selfUrl + this.config.path + '/' + name + let path: string + if (typeof data === 'string') { + path = data + } else { + path = this.baseDir + name + await writeFile(path, data) + } + const dispose = this[Context.current]?.collect('server.temp', async () => { + clearTimeout(timer) + delete this.entries[name] + if (path.startsWith(this.baseDir)) await rm(path) + }) + const timer = dispose && setTimeout(() => dispose(), this.config.maxAge) + return this.entries[name] = { path, url, dispose } + } +} + +namespace TempServer { + export interface Config { + path?: string + maxAge?: number + } + + export const Config: Schema = Schema.object({ + path: Schema.string().default('/temp'), + maxAge: Schema.number().default(Time.minute * 5), + }) +} + +export default TempServer diff --git a/packages/server-temp/tsconfig.json b/packages/server-temp/tsconfig.json new file mode 100644 index 00000000..6f11f324 --- /dev/null +++ b/packages/server-temp/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + "strict": true, + "noImplicitAny": false, + }, + "include": [ + "src", + ], +}