diff --git a/index.d.ts b/index.d.ts index 1dc8550..479cd2d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -593,6 +593,121 @@ declare global { [key: string]: any } + // ── Custom Tools (Admin) ───────────────────────────────────────────────── + + /** Project config entry (`meta.tools[]`). */ + export interface AdminToolConfig { + name: string + label?: string | { [lang: string]: string } + description?: string | { [lang: string]: string } + icon?: string + group?: string + module: string | { eval: string } + permissions?: string[] + capabilities?: Array<"db" | "files" | "xlsx" | "ui" | "log" | "progress" | "state"> + settings?: Record + hidden?: boolean + } + + /** File handle handed to tools (data URL, no live Blob). */ + export interface AdminToolFile { + src: string + name: string + type?: string + size?: number + } + + /** Fail-fast batch result; no rollback. */ + export interface AdminToolBatchResult { + ok: boolean + failedIndex?: number + error?: unknown + } + + export interface AdminToolDb { + find( + collection: string, + opts?: Record + ): Promise + count(collection: string, opts?: Record): Promise + loadAll( + collection: string, + opts?: Record, + onProgress?: (done: number, total: number) => void + ): Promise + create(collection: string, data: Record): Promise + update(collection: string, id: string, data: Record): Promise> + delete(collection: string, id: string): Promise + updateMany(collection: string, items: Array<{ id: string; data: Record }>): Promise + deleteMany(collection: string, ids: string[]): Promise + } + + export interface AdminToolUi { + supports(type: string): boolean + slot(el: HTMLElement, element: any): void + styles: CSSStyleSheet[] + registerWidget(type: string, factory: (...args: any[]) => any, opts?: { replace?: boolean }): () => void + render(el: HTMLElement, widget: Record): void | (() => void) + field(opts: Record): any + form(opts: Record): any + [key: string]: any + } + + export interface AdminToolI18n { + lang: string + languages: string[] + t(key: string, vars?: Record): string + text(value: string | Record | undefined | null, vars?: Record): string + has(key: string): boolean + add(lang: string, messages: Record): () => void + add(messages: Record, lang?: string): () => void + extend(lang: string, messages: Record): () => void + extend(messages: Record, lang?: string): () => void + onChange(cb: (lang: string) => void): () => void + dispose?(): void + } + + /** Browser context handed to a tool module. `context === ctx`. */ + export interface AdminToolContext { + context: AdminToolContext + apiVersion: 1 + uiVersion: 1 + host: "tool" | "macro" | "server" + capabilities: string[] + project: ProjectInfo + tool: AdminToolConfig + auth: { id: string; username: string; role: number; permissions: string[] } | null + db: AdminToolDb + files: { get(input: File | Blob | string, name?: string): Promise } + xlsx: any + state: Map + lang: string + languages: string[] + i18n: AdminToolI18n + theme: { mode: "light" | "dark"; tokens: Record } + log(message: string, details?: unknown): void + progress(done: number, total: number, label?: string): void + signal: AbortSignal + hostData: Record + asset(specifier: string): string + ui: AdminToolUi + } + + export interface AdminToolModule { + mount( + el: HTMLElement, + ctx: AdminToolContext + ): void | (() => void) | Promise void)> + messages?: Record> + } + + export interface AdminToolException { + status?: number + msg: string + json?: any + } + + /** Represents a single audit log entry as received in audit.return hooks */ export interface AuditLogEntry { id?: string diff --git a/schemas/config/project.schema.json b/schemas/config/project.schema.json index 7564995..7f6de1d 100644 --- a/schemas/config/project.schema.json +++ b/schemas/config/project.schema.json @@ -65,6 +65,94 @@ ] } }, + "ui": { + "type": "object", + "additionalProperties": false, + "properties": { + "css": { + "type": "string" + } + } + }, + "tools": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "module" + ], + "properties": { + "name": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9-_]*$" + }, + "label": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "defs.schema.json#/definitions/i18nText" + } + ] + }, + "description": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "defs.schema.json#/definitions/i18nText" + } + ] + }, + "icon": { + "type": "string" + }, + "group": { + "type": "string" + }, + "module": { + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "defs.schema.json#/definitions/evalString" + } + ] + }, + "permissions": { + "type": "array", + "items": { + "type": "string" + } + }, + "capabilities": { + "type": "array", + "items": { + "enum": [ + "db", + "files", + "xlsx", + "ui", + "log", + "progress", + "state" + ] + } + }, + "settings": { + "type": "object" + }, + "hidden": { + "type": "boolean" + } + } + } + }, "i18n": { "type": "object", "additionalProperties": false, @@ -89,6 +177,20 @@ "code" ] } + }, + "messages": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": true + } + ] + } } }, "required": [