From ab63f5fb4b19160acdc57091fc3f30c6ad94ad55 Mon Sep 17 00:00:00 2001 From: Shigma Date: Tue, 4 Jun 2024 01:39:54 +0800 Subject: [PATCH] feat(schema): add built-in plugin @cordisjs/schema --- packages/cordis/src/index.ts | 5 ++- packages/schema/package.json | 49 +++++++++++++++++++++++++++++ packages/schema/readme.md | 1 + packages/schema/src/index.ts | 58 +++++++++++++++++++++++++++++++++++ packages/schema/tsconfig.json | 10 ++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 packages/schema/package.json create mode 100644 packages/schema/readme.md create mode 100644 packages/schema/src/index.ts create mode 100644 packages/schema/tsconfig.json diff --git a/packages/cordis/src/index.ts b/packages/cordis/src/index.ts index 703a802..99a99e9 100644 --- a/packages/cordis/src/index.ts +++ b/packages/cordis/src/index.ts @@ -1,9 +1,10 @@ import * as core from '@cordisjs/core' import { Logger, LoggerService } from '@cordisjs/logger' +import { SchemaService } from '@cordisjs/schema' import { TimerService } from '@cordisjs/timer' export * from '@cordisjs/core' -export { default as Schema, default as z } from 'schemastery' +export { Schema, z } from '@cordisjs/schema' export { Logger } from '@cordisjs/logger' export { TimerService } from '@cordisjs/timer' @@ -21,9 +22,11 @@ export class Context extends core.Context { this.baseDir = globalThis.process?.cwd() || '' this.provide('logger', undefined, true) + this.provide('schema', undefined, true) this.provide('timer', undefined, true) this.plugin(LoggerService) + this.plugin(SchemaService) this.plugin(TimerService) } } diff --git a/packages/schema/package.json b/packages/schema/package.json new file mode 100644 index 0000000..8dc7841 --- /dev/null +++ b/packages/schema/package.json @@ -0,0 +1,49 @@ +{ + "name": "@cordisjs/schema", + "description": "Schema service for cordis", + "version": "0.1.0", + "type": "module", + "main": "lib/index.cjs", + "module": "lib/index.mjs", + "types": "lib/index.d.ts", + "exports": { + ".": { + "require": "./lib/index.cjs", + "import": "./lib/index.mjs", + "types": "./lib/index.d.ts" + }, + "./package.json": "./package.json" + }, + "files": [ + "lib", + "src" + ], + "author": "Shigma ", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/cordiverse/cordis.git", + "directory": "packages/schema" + }, + "bugs": { + "url": "https://github.com/cordiverse/cordis/issues" + }, + "homepage": "https://github.com/cordiverse/cordis", + "keywords": [ + "cordis", + "schema", + "service", + "plugin", + "config" + ], + "devDependencies": { + "@cordisjs/core": "^3.16.1" + }, + "peerDependencies": { + "@cordisjs/core": "^3.16.1" + }, + "dependencies": { + "cosmokit": "^1.6.2", + "schemastery": "^3.14.6" + } +} diff --git a/packages/schema/readme.md b/packages/schema/readme.md new file mode 100644 index 0000000..6fcf205 --- /dev/null +++ b/packages/schema/readme.md @@ -0,0 +1 @@ +# @cordisjs/schema diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts new file mode 100644 index 0000000..b328150 --- /dev/null +++ b/packages/schema/src/index.ts @@ -0,0 +1,58 @@ +import { Dict, remove } from 'cosmokit' +import { Context, Service } from '@cordisjs/core' +import Schema from 'schemastery' + +export { default as Schema, default as z } from 'schemastery' + +const kSchemaOrder = Symbol('cordis.schema.order') + +declare module '@cordisjs/core' { + interface Context { + schema: SchemaService + } + + interface Events { + 'internal/schema'(name: string): void + } +} + +export class SchemaService extends Service { + _data: Dict = Object.create(null) + + constructor(public ctx: Context) { + super(ctx, 'schema', true) + } + + extend(name: string, schema: Schema, order = 0) { + const caller = this[Context.current] + const target = this.get(name) + const index = target.list.findIndex(a => a[kSchemaOrder] < order) + schema[kSchemaOrder] = order + if (index >= 0) { + target.list.splice(index, 0, schema) + } else { + target.list.push(schema) + } + this.ctx.emit('internal/schema', name) + caller.on('dispose', () => { + remove(target.list, schema) + this.ctx.emit('internal/schema', name) + }) + } + + get(name: string) { + return (this._data[name] ||= Schema.intersect([])) as Schema & { list: Schema[] } + } + + set(name: string, schema: Schema) { + const caller = this[Context.current] + this._data[name] = schema + this.ctx.emit('internal/schema', name) + caller?.on('dispose', () => { + delete this._data[name] + this.ctx.emit('internal/schema', name) + }) + } +} + +export default SchemaService diff --git a/packages/schema/tsconfig.json b/packages/schema/tsconfig.json new file mode 100644 index 0000000..42cbe59 --- /dev/null +++ b/packages/schema/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + }, + "include": [ + "src", + ], +}