From ccf6cfbbecac326e7a7dd34fd02ed4f939d030d3 Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 29 Apr 2024 21:29:26 +0800 Subject: [PATCH] feat(registry): add manifest typings --- packages/registry/src/local.ts | 14 +++--- packages/registry/src/types.ts | 31 ++++++++---- packages/registry/src/utils.ts | 87 ++++++++++++++++++---------------- plugins/config/client/index.ts | 3 +- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/packages/registry/src/local.ts b/packages/registry/src/local.ts index 158becb..ffb0d22 100644 --- a/packages/registry/src/local.ts +++ b/packages/registry/src/local.ts @@ -7,8 +7,11 @@ import { readdir, readFile } from 'node:fs/promises' import { PackageJson, SearchObject, SearchResult } from './types' import { conclude } from './utils' -interface LocalObject extends Pick { - package: Pick +const LocalKeys = ['name', 'version', 'peerDependencies', 'peerDependenciesMeta'] as const +type LocalKeys = typeof LocalKeys[number] + +interface LocalObject extends Pick { + package: Pick } export interface LocalScanner extends SearchResult, LocalScanner.Options {} @@ -88,12 +91,7 @@ export class LocalScanner { workspace, manifest: conclude(meta), shortname: meta.name.replace(/(cordis-|^@cordisjs\/)plugin-/, ''), - package: pick(meta, [ - 'name', - 'version', - 'peerDependencies', - 'peerDependenciesMeta', - ]), + package: pick(meta, LocalKeys), } this.cache[name] = object await this.onSuccess?.(object) diff --git a/packages/registry/src/types.ts b/packages/registry/src/types.ts index e3a573b..ab41182 100644 --- a/packages/registry/src/types.ts +++ b/packages/registry/src/types.ts @@ -23,7 +23,7 @@ export interface PackageJson extends BasePackage, Partial scripts?: Dict exports?: PackageJson.Exports - cordis?: Partial + cordis?: Manifest keywords: string[] engines?: Dict os?: string[] @@ -47,25 +47,35 @@ export interface IconSvg { pathData: string } -export interface Manifest { +export interface Manifest extends Manifest.Base { icon?: IconSvg hidden?: boolean preview?: boolean insecure?: boolean - browser?: boolean category?: string public?: string[] - exports?: Dict - description: string | Dict - service: Manifest.Service - locales: string[] + exports?: Dict + ecosystem?: Manifest.Ecosystem } export namespace Manifest { + export interface Base { + browser?: boolean + description?: string | Dict + service?: Manifest.Service + resources?: Dict + } + export interface Service { - required: string[] - optional: string[] - implements: string[] + required?: string[] + optional?: string[] + implements?: string[] + } + + export interface Ecosystem { + inject?: string[] + pattern?: string[] + keywords?: string[] } } @@ -115,6 +125,7 @@ export interface SearchPackage extends DatedPackage, Pick { (value: any): T | undefined - (value: any, fallback: T): T } export namespace Ensure { - export const array: Ensure = (value: any, fallback?: any) => { - if (!Array.isArray(value)) return fallback + export const array: Ensure = (value: any) => { + if (!Array.isArray(value)) return return value.filter(x => typeof x === 'string') } - export const dict: Ensure> = (value: any, fallback?: any) => { - if (typeof value !== 'object' || value === null) return fallback - return Object.entries(value).reduce>((dict, [key, value]) => { - if (typeof value === 'string') dict[key] = value + export const dict = (value: any, callback?: (value: T) => T): Dict | undefined => { + if (typeof value !== 'object' || value === null) return + return Object.entries(value).reduce((dict, [key, value]: [string, any]) => { + value = callback ? callback(value) : value + if (value !== undefined) dict[key] = value return dict }, {}) } + export const object = (value: any, callback?: (value: T) => T): T | undefined => { + if (typeof value !== 'object' || value === null) return + return callback ? callback(value) : value + } + // https://github.com/microsoft/TypeScript/issues/15713#issuecomment-499474386 const primitive = (type: string): Ensure => (value: any, fallback?: T) => { if (typeof value !== type) return fallback @@ -31,45 +36,47 @@ export namespace Ensure { export const string = primitive('string') } +function concludeBase(base?: Manifest.Base | null, description?: string) { + if (typeof base !== 'object') return + if (!base) return null + + const result: Manifest.Base = { + browser: Ensure.boolean(base.browser), + description: Ensure.dict(base.description) ?? Ensure.string(description), + service: Ensure.object(base.service, (service) => ({ + required: Ensure.array(service.required), + optional: Ensure.array(service.optional), + implements: Ensure.array(service.implements), + })), + resources: Ensure.dict(base.resources), + } + + if (typeof result.description === 'string') { + result.description = result.description.slice(0, 1024) + } else if (result.description) { + for (const key in result.description) { + result.description[key] = result.description[key].slice(0, 1024) + } + } + + return result +} + export function conclude(meta: PackageJson) { - const manifest: Manifest = { + const result: Manifest = { + ...concludeBase(meta.cordis, meta.description), hidden: Ensure.boolean(meta.cordis?.hidden), preview: Ensure.boolean(meta.cordis?.preview), insecure: Ensure.boolean(meta.cordis?.insecure), - browser: Ensure.boolean(meta.cordis?.browser), category: Ensure.string(meta.cordis?.category), public: Ensure.array(meta.cordis?.public), - description: Ensure.dict(meta.cordis?.description) || Ensure.string(meta.description, ''), - locales: Ensure.array(meta.cordis?.locales, []), - service: { - required: Ensure.array(meta.cordis?.service?.required, []), - optional: Ensure.array(meta.cordis?.service?.optional, []), - implements: Ensure.array(meta.cordis?.service?.implements, []), - }, + ecosystem: Ensure.object(meta.cordis?.ecosystem, (ecosystem) => ({ + inject: Ensure.array(ecosystem.inject), + pattern: Ensure.array(ecosystem.pattern), + keywords: Ensure.array(ecosystem.keywords), + })), + exports: Ensure.dict(meta.cordis?.exports, concludeBase), } - if (typeof manifest.description === 'string') { - manifest.description = manifest.description.slice(0, 1024) - } else if (manifest.description) { - for (const key in manifest.description) { - manifest.description[key] = manifest.description[key].slice(0, 1024) - } - } - - meta.keywords = Ensure.array(meta.keywords, []).filter((keyword) => { - if (!keyword.includes(':')) return true - if (keyword === 'market:hidden') { - manifest.hidden = true - } else if (keyword.startsWith('required:')) { - manifest.service.required.push(keyword.slice(9)) - } else if (keyword.startsWith('optional:')) { - manifest.service.optional.push(keyword.slice(9)) - } else if (keyword.startsWith('impl:')) { - manifest.service.implements.push(keyword.slice(5)) - } else if (keyword.startsWith('locale:')) { - manifest.locales.push(keyword.slice(7)) - } - }) - - return manifest + return result } diff --git a/plugins/config/client/index.ts b/plugins/config/client/index.ts index dadcdc9..775ad34 100644 --- a/plugins/config/client/index.ts +++ b/plugins/config/client/index.ts @@ -255,8 +255,7 @@ export default class Manager extends Service { } // check implementations - for (const name of local.manifest.service.implements) { - if (name === 'adapter') continue + for (const name of local.manifest.service?.implements || []) { result.impl.push(name) }