From fd6086f85be9d6967168a7cc9175d0ffb49430bf Mon Sep 17 00:00:00 2001 From: Shigma Date: Fri, 9 Jun 2023 18:32:57 +0800 Subject: [PATCH] feat(market): expose installer service --- plugins/config/src/node/index.ts | 2 +- plugins/market/src/browser/deps.ts | 28 +++++++++++ plugins/market/src/browser/index.ts | 10 ++-- plugins/market/src/browser/installer.ts | 54 --------------------- plugins/market/src/node/deps.ts | 33 +++++++++++++ plugins/market/src/node/index.ts | 25 ++++++---- plugins/market/src/node/installer.ts | 63 ++++++++----------------- plugins/market/src/node/market.ts | 5 +- plugins/market/src/node/utils.ts | 16 ------- plugins/market/src/shared/index.ts | 27 ++++++++++- 10 files changed, 130 insertions(+), 133 deletions(-) create mode 100644 plugins/market/src/browser/deps.ts delete mode 100644 plugins/market/src/browser/installer.ts create mode 100644 plugins/market/src/node/deps.ts delete mode 100644 plugins/market/src/node/utils.ts diff --git a/plugins/config/src/node/index.ts b/plugins/config/src/node/index.ts index 77d286ed..4513301d 100644 --- a/plugins/config/src/node/index.ts +++ b/plugins/config/src/node/index.ts @@ -6,7 +6,7 @@ import { ConfigWriter, ServiceProvider } from '../shared' export * from '../shared' export const name = 'config' -export const using = ['console', 'loader'] as const +export const using = ['console'] as const export interface Config {} diff --git a/plugins/market/src/browser/deps.ts b/plugins/market/src/browser/deps.ts new file mode 100644 index 00000000..42c5fd51 --- /dev/null +++ b/plugins/market/src/browser/deps.ts @@ -0,0 +1,28 @@ +import { Context, Dict, version } from 'koishi' +import { DataService } from '@koishijs/plugin-console' +import { Dependency } from '../shared' + +class Dependencies extends DataService> { + constructor(public ctx: Context) { + super(ctx, 'dependencies', { authority: 4 }) + } + + async get(force = false) { + const objects = this.ctx.loader.market.objects.filter(o => o.portable) + objects.push({ + name: 'koishi', + version, + versions: { + [version]: {}, + }, + } as any) + return Object.fromEntries(objects.map((object) => [object.name, { + request: object.version, + resolved: object.version, + versions: object.versions, + latest: object.version, + }])) + } +} + +export default Dependencies diff --git a/plugins/market/src/browser/index.ts b/plugins/market/src/browser/index.ts index 6d4b3d65..42a8edac 100644 --- a/plugins/market/src/browser/index.ts +++ b/plugins/market/src/browser/index.ts @@ -1,18 +1,18 @@ import { Context, Schema } from 'koishi' -import Installer from './installer' +import Dependencies from './deps' import MarketProvider from './market' -export * from './installer' +export * from './deps' export * from './market' export * from '../shared' export { - Installer, + Dependencies, MarketProvider, } export const filter = false -export const name = 'manager' +export const name = 'market' export const using = ['console'] as const export interface Config {} @@ -20,7 +20,7 @@ export interface Config {} export const Config: Schema = Schema.object({}) export function apply(ctx: Context, config: Config) { - ctx.plugin(Installer) + ctx.plugin(Dependencies) ctx.plugin(MarketProvider) ctx.console.addEntry(process.env.KOISHI_BASE ? [ diff --git a/plugins/market/src/browser/installer.ts b/plugins/market/src/browser/installer.ts deleted file mode 100644 index 76713f56..00000000 --- a/plugins/market/src/browser/installer.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Context, Dict, version } from 'koishi' -import { DataService } from '@koishijs/plugin-console' -import { PackageJson } from '@koishijs/registry' -import {} from '@koishijs/plugin-config' - -declare module '@koishijs/plugin-console' { - interface Events { - 'market/install'(deps: Dict): Promise - } -} - -export interface Dependency { - /** - * requested semver range - * @example `^1.2.3` -> `1.2.3` - */ - request: string - /** - * installed package version - * @example `1.2.5` - */ - resolved?: string - /** whether it is a workspace package */ - workspace?: boolean - /** all available versions */ - versions?: Dict> - /** latest version */ - latest?: string -} - -class Installer extends DataService> { - constructor(public ctx: Context) { - super(ctx, 'dependencies', { authority: 4 }) - } - - async get(force = false) { - const objects = this.ctx.loader.market.objects.filter(o => o.portable) - objects.push({ - name: 'koishi', - version, - versions: { - [version]: {}, - }, - } as any) - return Object.fromEntries(objects.map((object) => [object.name, { - request: object.version, - resolved: object.version, - versions: object.versions, - latest: object.version, - }])) - } -} - -export default Installer diff --git a/plugins/market/src/node/deps.ts b/plugins/market/src/node/deps.ts new file mode 100644 index 00000000..93d5a116 --- /dev/null +++ b/plugins/market/src/node/deps.ts @@ -0,0 +1,33 @@ +import { Context, Dict, Schema } from 'koishi' +import { DataService } from '@koishijs/plugin-console' +import { Dependency } from '../shared' + +declare module '@koishijs/plugin-console' { + interface Events { + 'market/install'(deps: Dict): Promise + } +} + +class Dependencies extends DataService> { + constructor(public ctx: Context, public config: Dependencies.Config) { + super(ctx, 'dependencies', { authority: 4 }) + + ctx.console.addListener('market/install', async (deps) => { + const code = await ctx.installer.installDep(deps) + this.refresh() + this.ctx.console.packages?.refresh() + return code + }, { authority: 4 }) + } + + async get(force = false) { + return this.ctx.installer.get(force) + } +} + +namespace Dependencies { + export interface Config {} + export const Config: Schema = Schema.object({}) +} + +export default Dependencies diff --git a/plugins/market/src/node/index.ts b/plugins/market/src/node/index.ts index 081db58b..9b9ea175 100644 --- a/plugins/market/src/node/index.ts +++ b/plugins/market/src/node/index.ts @@ -1,23 +1,28 @@ import { Context, Schema } from 'koishi' import { resolve } from 'path' +import Dependencies from './deps' import Installer from './installer' import MarketProvider from './market' export * from '../shared' -export { Installer } +export { Dependencies, Installer } + +declare module 'koishi' { + interface Context { + installer: Installer + } +} declare module '@koishijs/plugin-console' { namespace Console { interface Services { - dependencies: Installer + dependencies: Dependencies } } } -export const filter = false export const name = 'market' -export const using = ['console', 'loader'] as const export interface Config { registry?: Installer.Config @@ -35,10 +40,14 @@ export function apply(ctx: Context, config: Config) { } ctx.plugin(Installer, config.registry) - ctx.plugin(MarketProvider, config.search) - ctx.console.addEntry({ - dev: resolve(__dirname, '../../client/index.ts'), - prod: resolve(__dirname, '../../dist'), + ctx.using(['console', 'installer'], (ctx) => { + ctx.plugin(Dependencies) + ctx.plugin(MarketProvider, config.search) + + ctx.console.addEntry({ + dev: resolve(__dirname, '../../client/index.ts'), + prod: resolve(__dirname, '../../dist'), + }) }) } diff --git a/plugins/market/src/node/installer.ts b/plugins/market/src/node/installer.ts index d6320307..00baaee3 100644 --- a/plugins/market/src/node/installer.ts +++ b/plugins/market/src/node/installer.ts @@ -1,48 +1,31 @@ -import { Context, Dict, Logger, pick, Quester, Schema, Time, valueMap } from 'koishi' -import { DataService } from '@koishijs/plugin-console' -import { PackageJson, Registry, RemotePackage } from '@koishijs/registry' +import { Context, defineProperty, Dict, Logger, pick, Quester, Schema, Service, Time, valueMap } from 'koishi' +import { PackageJson, Registry } from '@koishijs/registry' import { resolve } from 'path' -import { promises as fsp } from 'fs' -import { loadManifest } from './utils' +import { promises as fsp, readFileSync } from 'fs' import { compare, satisfies, valid } from 'semver' +import { Dependency } from '../shared' import {} from '@koishijs/loader' import getRegistry from 'get-registry' import which from 'which-pm-runs' import spawn from 'execa' import pMap from 'p-map' -declare module '@koishijs/plugin-console' { - interface Events { - 'market/install'(deps: Dict): Promise - } -} - const logger = new Logger('market') -const depKeys = ['peerDependencies', 'peerDependenciesMeta', 'deprecated'] as const - -export interface Dependency { - /** - * requested semver range - * @example `^1.2.3` -> `1.2.3` - */ - request: string - /** - * installed package version - * @example `1.2.5` - */ - resolved?: string - /** whether it is a workspace package */ - workspace?: boolean - /** all available versions */ - versions?: Dict> - /** latest version */ - latest?: string - /** valid (unsupported) syntax */ - invalid?: boolean +export interface LocalPackage extends PackageJson { + private?: boolean + $workspace?: boolean +} + +export function loadManifest(name: string) { + const filename = require.resolve(name + '/package.json') + const meta: LocalPackage = JSON.parse(readFileSync(filename, 'utf8')) + meta.dependencies ||= {} + defineProperty(meta, '$workspace', !filename.includes('node_modules')) + return meta } -class Installer extends DataService> { +class Installer extends Service { public http: Quester public registry: string @@ -51,26 +34,20 @@ class Installer extends DataService> { private task: Promise> constructor(public ctx: Context, public config: Installer.Config) { - super(ctx, 'dependencies', { authority: 4 }) + super(ctx, 'installer') this.manifest = loadManifest(this.cwd) - - ctx.console.addListener('market/install', this.installDep, { authority: 4 }) } get cwd() { return this.ctx.baseDir } - async prepare() { + async start() { const { endpoint, timeout } = this.config this.registry = endpoint || await getRegistry() this.http = this.ctx.http.extend({ endpoint: this.registry, timeout }) } - async start() { - await this.prepare() - } - private async _get() { const result = valueMap(this.manifest.dependencies, (request) => { return { request: request.replace(/^[~^]/, '') } as Dependency @@ -92,7 +69,7 @@ class Installer extends DataService> { try { const registry = await this.http.get(`/${name}`) const entries = Object.values(registry.versions) - .map(item => [item.version, pick(item, depKeys)] as const) + .map(item => [item.version, pick(item, Dependency.keys)] as const) .sort(([a], [b]) => compare(b, a)) result[name].latest = entries[0][0] result[name].versions = Object.fromEntries(entries) @@ -176,8 +153,6 @@ class Installer extends DataService> { this.ctx.loader.fullReload() } - this.refresh() - this.ctx.console.packages?.refresh() return 0 } } diff --git a/plugins/market/src/node/market.ts b/plugins/market/src/node/market.ts index 246a12e7..b1bb9140 100644 --- a/plugins/market/src/node/market.ts +++ b/plugins/market/src/node/market.ts @@ -4,8 +4,6 @@ import { MarketProvider as BaseMarketProvider } from '../shared' import { throttle } from 'throttle-debounce' class MarketProvider extends BaseMarketProvider { - static using = ['console.dependencies'] - private http: Quester private failed: string[] = [] private scanner: Scanner @@ -22,7 +20,6 @@ class MarketProvider extends BaseMarketProvider { this.failed = [] this.fullCache = {} this.tempCache = {} - this.ctx.console.dependencies.refresh() await this.prepare() this.refresh() } @@ -43,7 +40,7 @@ class MarketProvider extends BaseMarketProvider { async collect() { const { timeout } = this.config - const registry = this.ctx.console.dependencies.http + const registry = this.ctx.installer.http this.failed = [] this.scanner = new Scanner(registry.get) diff --git a/plugins/market/src/node/utils.ts b/plugins/market/src/node/utils.ts deleted file mode 100644 index 3511663f..00000000 --- a/plugins/market/src/node/utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { readFileSync } from 'fs' -import { PackageJson } from '@koishijs/registry' -import { defineProperty } from 'koishi' - -export interface LocalPackage extends PackageJson { - private?: boolean - $workspace?: boolean -} - -export function loadManifest(name: string) { - const filename = require.resolve(name + '/package.json') - const meta: LocalPackage = JSON.parse(readFileSync(filename, 'utf8')) - meta.dependencies ||= {} - defineProperty(meta, '$workspace', !filename.includes('node_modules')) - return meta -} diff --git a/plugins/market/src/shared/index.ts b/plugins/market/src/shared/index.ts index e1ce5799..828e409e 100644 --- a/plugins/market/src/shared/index.ts +++ b/plugins/market/src/shared/index.ts @@ -1,6 +1,6 @@ import { Context, Dict, Logger, Time } from 'koishi' import { DataService } from '@koishijs/plugin-console' -import { AnalyzedPackage, MarketResult } from '@koishijs/registry' +import { AnalyzedPackage, MarketResult, RemotePackage } from '@koishijs/registry' declare module '@koishijs/plugin-console' { interface Events { @@ -14,6 +14,31 @@ declare module '@koishijs/plugin-console' { } } +export interface Dependency { + /** + * requested semver range + * @example `^1.2.3` -> `1.2.3` + */ + request: string + /** + * installed package version + * @example `1.2.5` + */ + resolved?: string + /** whether it is a workspace package */ + workspace?: boolean + /** all available versions */ + versions?: Dict> + /** latest version */ + latest?: string + /** valid (unsupported) syntax */ + invalid?: boolean +} + +export namespace Dependency { + export const keys = ['peerDependencies', 'peerDependenciesMeta', 'deprecated'] as const +} + const logger = new Logger('market') export abstract class MarketProvider extends DataService {