Skip to content

Commit

Permalink
feat(market): expose installer service
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 9, 2023
1 parent 02c2d90 commit fd6086f
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 133 deletions.
2 changes: 1 addition & 1 deletion plugins/config/src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

Expand Down
28 changes: 28 additions & 0 deletions plugins/market/src/browser/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Context, Dict, version } from 'koishi'
import { DataService } from '@koishijs/plugin-console'
import { Dependency } from '../shared'

class Dependencies extends DataService<Dict<Dependency>> {
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
10 changes: 5 additions & 5 deletions plugins/market/src/browser/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
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 {}

export const Config: Schema<Config> = 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 ? [
Expand Down
54 changes: 0 additions & 54 deletions plugins/market/src/browser/installer.ts

This file was deleted.

33 changes: 33 additions & 0 deletions plugins/market/src/node/deps.ts
Original file line number Diff line number Diff line change
@@ -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<string>): Promise<number>
}
}

class Dependencies extends DataService<Dict<Dependency>> {
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<Config> = Schema.object({})
}

export default Dependencies
25 changes: 17 additions & 8 deletions plugins/market/src/node/index.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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'),
})
})
}
63 changes: 19 additions & 44 deletions plugins/market/src/node/installer.ts
Original file line number Diff line number Diff line change
@@ -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<string>): Promise<number>
}
}

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<Pick<RemotePackage, typeof depKeys[number]>>
/** 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<Dict<Dependency>> {
class Installer extends Service {
public http: Quester
public registry: string

Expand All @@ -51,26 +34,20 @@ class Installer extends DataService<Dict<Dependency>> {
private task: Promise<Dict<Dependency>>

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
Expand All @@ -92,7 +69,7 @@ class Installer extends DataService<Dict<Dependency>> {
try {
const registry = await this.http.get<Registry>(`/${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)
Expand Down Expand Up @@ -176,8 +153,6 @@ class Installer extends DataService<Dict<Dependency>> {
this.ctx.loader.fullReload()
}

this.refresh()
this.ctx.console.packages?.refresh()
return 0
}
}
Expand Down
5 changes: 1 addition & 4 deletions plugins/market/src/node/market.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,7 +20,6 @@ class MarketProvider extends BaseMarketProvider {
this.failed = []
this.fullCache = {}
this.tempCache = {}
this.ctx.console.dependencies.refresh()
await this.prepare()
this.refresh()
}
Expand All @@ -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)
Expand Down
16 changes: 0 additions & 16 deletions plugins/market/src/node/utils.ts

This file was deleted.

Loading

0 comments on commit fd6086f

Please sign in to comment.