Skip to content

Commit

Permalink
feat(market): support plugin shortname and update --self
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 14, 2023
1 parent 12044ae commit 1f24954
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 43 deletions.
14 changes: 9 additions & 5 deletions packages/registry/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,20 @@ export default class Scanner {
this.total = this.objects.length
}

static isCompatible(range: string, remote: RemotePackage) {
const { peerDependencies = {} } = remote
const declaredVersion = peerDependencies['koishi']
try {
return declaredVersion && intersects(range, declaredVersion)
} catch {}
}

public async process(object: SearchObject, range: string, onRegistry: AnalyzeConfig['onRegistry']) {
const { name } = object.package
const official = name.startsWith('@koishijs/plugin-')
const registry = await this.request<Registry>(`/${name}`)
const compatible = Object.values(registry.versions).filter((remote) => {
const { peerDependencies = {} } = remote
const declaredVersion = peerDependencies['koishi']
try {
return declaredVersion && intersects(range, declaredVersion)
} catch {}
return Scanner.isCompatible(range, remote)
})

await onRegistry?.(registry, compatible)
Expand Down
60 changes: 37 additions & 23 deletions plugins/market/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Context, Logger, pick, Schema } from 'koishi'
import { Registry } from '@koishijs/registry'
import { Context, pick, Schema } from 'koishi'
import { gt } from 'semver'
import { resolve } from 'path'
import Dependencies from './deps'
Expand All @@ -24,8 +23,6 @@ declare module '@koishijs/plugin-console' {
}
}

const logger = new Logger('market')

export const name = 'market'

export interface Config {
Expand All @@ -50,24 +47,27 @@ export function apply(ctx: Context, config: Config) {
ctx.plugin(Installer, config.registry)

ctx.using(['installer'], (ctx) => {
ctx.command('plugin.install [name]', { authority: 4 })
ctx.command('plugin.install <name>', { authority: 4 })
.alias('.i')
.action(async ({ session }, name) => {
if (!name) return session.text('.expect-name')

// check local dependencies
const names = ctx.installer.resolveName(name)
const deps = await ctx.installer.get()
if (deps[name]) return session.text('.already-installed')
let registry: Registry
try {
registry = await ctx.installer.getRegistry(name)
} catch (error) {
logger.warn(error)
return session.text('.unknown-error')
}
name = names.find((name) => deps[name])
if (name) return session.text('.already-installed')

// find proper version
const result = await ctx.installer.findVersion(names)
if (!result) return session.text('.not-found')

// set restart message
ctx.envData.message = {
...pick(session, ['sid', 'channelId', 'guildId', 'subtype']),
content: session.text('.success'),
}
await ctx.installer.install({ [name]: registry.version })
await ctx.installer.install(result)
ctx.envData.message = null
return session.text('.success')
})
Expand All @@ -76,28 +76,41 @@ export function apply(ctx: Context, config: Config) {
.alias('.r')
.action(async ({ session }, name) => {
if (!name) return session.text('.expect-name')

// check local dependencies
const names = ctx.installer.resolveName(name)
const deps = await ctx.installer.get()
if (!deps[name]) return session.text('.not-installed')
ctx.envData.message = {
...pick(session, ['sid', 'channelId', 'guildId', 'subtype']),
content: session.text('.success'),
}
name = names.find((name) => deps[name])
if (!name) return session.text('.not-installed')

await ctx.installer.install({ [name]: null })
ctx.envData.message = null
return session.text('.success')
})

ctx.command('plugin.upgrade', { authority: 4 })
ctx.command('plugin.upgrade [name...]', { authority: 4 })
.alias('.update', '.up')
.action(async ({ session }) => {
.option('self', '-s, --koishi')
.action(async ({ session, options }, ...names) => {
async function getPackages(names: string[]) {
if (!names.length) return Object.keys(deps)
names = names.map((name) => {
const names = ctx.installer.resolveName(name)
return names.find((name) => deps[name])
}).filter(Boolean)
if (options.self) names.push('koishi')
return names
}

const deps = await ctx.installer.get()
const names = Object.keys(deps).filter((name) => {
names = await getPackages(names)
names = names.filter((name) => {
const { latest, resolved, invalid } = deps[name]
try {
return !invalid && gt(latest, resolved)
} catch {}
})
if (!names.length) return session.text('.all-updated')

const output = names.map((name) => {
const { latest, resolved } = deps[name]
return `${name}: ${resolved} -> ${latest}`
Expand All @@ -109,6 +122,7 @@ export function apply(ctx: Context, config: Config) {
if (!['Y', 'y'].includes(result?.trim())) {
return session.text('.cancelled')
}

ctx.envData.message = {
...pick(session, ['sid', 'channelId', 'guildId', 'subtype']),
content: session.text('.success'),
Expand Down
29 changes: 25 additions & 4 deletions plugins/market/src/node/installer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Context, defineProperty, Dict, Logger, pick, Quester, Schema, Service, Time, valueMap } from 'koishi'
import { PackageJson, Registry } from '@koishijs/registry'
import Scanner, { PackageJson, Registry } from '@koishijs/registry'
import { resolve } from 'path'
import { promises as fsp, readFileSync } from 'fs'
import { compare, satisfies, valid } from 'semver'
Expand Down Expand Up @@ -48,8 +48,29 @@ class Installer extends Service {
this.http = this.ctx.http.extend({ endpoint: this.registry, timeout })
}

getRegistry(name: string) {
return this.http.get<Registry>(`/${name}`)
resolveName(name: string) {
if (name.startsWith('@koishijs/plugin-')) return [name]
if (name.match(/(^|\/)koishi-plugin-/)) return [name]
if (name[0] === '@') {
const [left, right] = name.split('/')
return [`${left}/koishi-plugin-${right}`]
} else {
return [`@koishijs/plugin-${name}`, `koishi-plugin-${name}`]
}
}

async findVersion(names: string[]) {
const entries = await Promise.all(names.map(async (name) => {
try {
const registry = await this.http.get<Registry>(`/${name}`)
const versions = Object.values(registry.versions).filter((remote) => {
return !remote.deprecated && Scanner.isCompatible('4', remote)
}).sort((a, b) => compare(b.version, a.version))
if (!versions.length) return
return { [name]: versions[0].version }
} catch (e) {}
}))
return entries.find(Boolean)
}

private async _get() {
Expand All @@ -71,7 +92,7 @@ class Installer extends Service {
}

try {
const registry = await this.getRegistry(name)
const registry = await this.http.get<Registry>(`/${name}`)
const entries = Object.values(registry.versions)
.map(item => [item.version, pick(item, Dependency.keys)] as const)
.sort(([a], [b]) => compare(b, a))
Expand Down
22 changes: 11 additions & 11 deletions plugins/market/src/node/locales/message.zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ commands.plugin:
description: 插件管理

commands.plugin.install:
description: 安装依赖
description: 安装插件
messages:
expect-name: 请输入依赖名
already-installed: 该依赖已安装
unknown-error: 遇到未知错误
expect-name: 请输入插件名
already-installed: 该插件已安装
not-found: 未找到该插件
success: 安装成功!

commands.plugin.uninstall:
description: 卸载依赖
description: 卸载插件
messages:
expect-name: 请输入依赖名。
not-installed: 该依赖未安装。
unknown-error: 遇到未知错误。
expect-name: 请输入插件名。
not-installed: 该插件未安装。
success: 卸载成功!

commands.plugin.upgrade:
description: 升级依赖
description: 升级插件
options:
self: 升级 Koishi 本体
messages:
all-updated: 所有依赖已是最新版本
all-updated: 所有插件已是最新版本
available: 有可用的依赖更新:
prompt: 输入「Y」升级全部依赖,输入「N」取消操作。
cancelled: 已取消操作。
unknown-error: 遇到未知错误。
success: 升级成功!

0 comments on commit 1f24954

Please sign in to comment.