Skip to content

Commit

Permalink
feat(manager): support change version for non-plugin deps
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed May 7, 2022
1 parent 50187bd commit b7346b2
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 37 deletions.
4 changes: 0 additions & 4 deletions packages/market/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ export interface PackageJson extends BasePackage {
optionalDependencies?: Dict<string>
}

export interface LocalPackage extends PackageJson {
private?: boolean
}

export interface RemotePackage extends PackageJson {
deprecated?: string
author: User
Expand Down
12 changes: 6 additions & 6 deletions plugins/frontend/manager/client/deps/package.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<template v-if="local">
{{ local.resolved }}
<template v-if="local.workspace">(工作区)</template>
<template v-else-if="local.resolved === remote?.versions[0].version">(最新)</template>
<template v-else-if="local.resolved === versions[0]?.version">(最新)</template>
</template>
<span v-else>-</span>
</td>
Expand All @@ -17,7 +17,7 @@
<k-button class="prefix right-adjacent" @click="prefix = matrix[prefix]">{{ prefix || '=' }}</k-button>
<el-select class="left-adjacent" v-model="value">
<el-option value="">移除依赖</el-option>
<el-option v-for="({ version }) in remote?.versions || []" :key="version" :value="version"></el-option>
<el-option v-for="({ version }) in versions" :key="version" :value="version"></el-option>
</el-select>
</template>
</td>
Expand Down Expand Up @@ -78,8 +78,8 @@ const local = computed(() => {
return store.dependencies[props.name]
})
const remote = computed(() => {
return store.market[props.name]
const versions = computed(() => {
return store.market[props.name]?.versions || []
})
</script>
Expand Down Expand Up @@ -126,11 +126,11 @@ const remote = computed(() => {
}
.k-button.action {
width: 9rem;
width: 10rem;
}
.el-select {
width: 7rem;
width: 8rem;
}
.k-button.prefix {
Expand Down
7 changes: 3 additions & 4 deletions plugins/frontend/manager/client/market/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<template v-if="Object.keys(store.market).length">
<template v-if="plugins.length">
<div class="search-box">
<k-badge type="success" v-for="(word, index) in words.slice(0, -1)" :key="index" @click="words.splice(index, 1)">{{ word }}</k-badge>
<input
Expand Down Expand Up @@ -86,13 +86,12 @@ function onQuery(word: string) {
}
const plugins = computed(() => {
return Object.values(store.market).filter((data) => {
return words.every(word => validate(data, word))
})
return Object.values(store.market).filter(data => data.shortname)
})
const packages = computed(() => {
return plugins.value
.filter(data => words.every(word => validate(data, word)))
.filter(item => config.showInstalled || !store.packages[item.name])
.sort((a, b) => b.popularity - a.popularity)
})
Expand Down
27 changes: 13 additions & 14 deletions plugins/frontend/manager/src/installer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Context, Dict, Logger } from 'koishi'
import { DataService } from '@koishijs/plugin-console'
import { PackageJson } from '@koishijs/market'
import { resolve } from 'path'
import { promises as fsp, readFileSync } from 'fs'
import { promises as fsp } from 'fs'
import { loadManifest } from './utils'
import which from 'which-pm-runs'
import spawn from 'cross-spawn'

Expand All @@ -22,17 +23,12 @@ export interface Dependency {
versions?: Partial<PackageJson>[]
}

function loadJson(path: string) {
return JSON.parse(readFileSync(path, 'utf8'))
}

class Installer extends DataService<Dict<Dependency>> {
private meta: PackageJson

constructor(public ctx: Context) {
super(ctx, 'dependencies', { authority: 4 })
this.meta = loadJson(resolve(this.cwd, 'package.json'))
this.meta.dependencies ||= {}
this.meta = loadManifest(this.cwd)

ctx.console.addListener('market/install', this.installDep, { authority: 4 })
ctx.console.addListener('market/patch', this.patchDep, { authority: 4 })
Expand All @@ -45,12 +41,15 @@ class Installer extends DataService<Dict<Dependency>> {
async get() {
const results: Dict<Dependency> = {}
for (const name in this.meta.dependencies) {
const path = require.resolve(name + '/package.json')
results[name] = {
request: this.meta.dependencies[name],
resolved: loadJson(path).version,
workspace: !path.includes('node_modules'),
}
try {
// some dependencies may be left with no local installation
const meta = loadManifest(name)
results[name] = {
request: this.meta.dependencies[name],
resolved: meta.version,
workspace: meta.$workspace,
}
} catch {}
}
return results
}
Expand Down Expand Up @@ -100,7 +99,7 @@ class Installer extends DataService<Dict<Dependency>> {
await this.override(deps)
const args: string[] = []
if (agent !== 'yarn') args.push('install')
const registry = this.ctx.console.market.config.registry
const { registry } = this.ctx.console.market.config
if (registry) args.push('--registry=' + registry)
const code = await this.exec(agent, args)
if (!code) {
Expand Down
23 changes: 19 additions & 4 deletions plugins/frontend/manager/src/market.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Context, Dict, pick, Quester, Schema } from 'koishi'
import { DataService } from '@koishijs/plugin-console'
import scan, { AnalyzedPackage, PackageJson } from '@koishijs/market'
import scan, { AnalyzedPackage, PackageJson, Registry } from '@koishijs/market'
import which from 'which-pm-runs'
import spawn from 'cross-spawn'
import { loadManifest } from './utils'

class MarketProvider extends DataService<Dict<MarketProvider.Data>> {
/** https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md */
Expand Down Expand Up @@ -30,13 +31,14 @@ class MarketProvider extends DataService<Dict<MarketProvider.Data>> {
}

async prepare() {
const cwd = this.ctx.app.baseDir
let { registry } = this.config
if (!registry) {
registry = await new Promise<string>((resolve, reject) => {
let stdout = ''
const agent = which()
const key = (agent?.name === 'yarn' && !agent?.version.startsWith('1.')) ? 'npmRegistryServer' : 'registry'
const child = spawn(agent?.name || 'npm', ['config', 'get', key], { cwd: this.ctx.app.baseDir })
const child = spawn(agent?.name || 'npm', ['config', 'get', key], { cwd })
child.on('exit', (code) => {
if (!code) return resolve(stdout)
reject(new Error(`child process failed with code ${code}`))
Expand All @@ -47,11 +49,22 @@ class MarketProvider extends DataService<Dict<MarketProvider.Data>> {
})
})
}

this.http = this.ctx.http.extend({
endpoint: registry.trim(),
})

await scan({
const meta = loadManifest(cwd)
const tasks = Object.keys(meta.dependencies).map(async (name) => {
const registry = await this.http.get<Registry>(`/${name}`)
const versions = Object.values(registry.versions)
.map(item => pick(item, ['version', 'peerDependencies']))
.reverse()
this.tempCache[name] = this.fullCache[name] = { versions } as any
this.flushData()
})

tasks.push(scan({
version: '4',
request: this.http.get,
onItem: (item) => {
Expand All @@ -62,7 +75,9 @@ class MarketProvider extends DataService<Dict<MarketProvider.Data>> {
}
this.flushData()
},
})
}))

await Promise.allSettled(tasks)
}

async get() {
Expand Down
11 changes: 6 additions & 5 deletions plugins/frontend/manager/src/packages.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Adapter, App, Context, Dict, Logger, omit, pick, Plugin, remove, Schema } from 'koishi'
import { DataService } from '@koishijs/plugin-console'
import { LocalPackage, PackageJson } from '@koishijs/market'
import { PackageJson } from '@koishijs/market'
import { promises as fsp } from 'fs'
import { dirname } from 'path'
import ns from 'ns-require'
import {} from '@koishijs/cli'
import { loadManifest } from './utils'

const logger = new Logger('market')

Expand Down Expand Up @@ -104,15 +105,15 @@ class PackageProvider extends DataService<Dict<PackageProvider.Data>> {
try {
// require.resolve(name) may be different from require.resolve(path)
// because tsconfig-paths may resolve the path differently
this.cache[require.resolve(name)] = this.parsePackage(name, path)
this.cache[require.resolve(name)] = this.parsePackage(name)
} catch (error) {
logger.warn('failed to parse %c', name)
logger.debug(error)
}
}

private parsePackage(name: string, path: string) {
const data: LocalPackage = require(path + '/package.json')
private parsePackage(name: string) {
const data = loadManifest(name)
const result = pick(data, [
'name',
'version',
Expand All @@ -121,7 +122,7 @@ class PackageProvider extends DataService<Dict<PackageProvider.Data>> {
]) as PackageProvider.Data

// workspace packages are followed by symlinks
result.workspace = !require.resolve(name).includes('node_modules')
result.workspace = data.$workspace
result.shortname = data.name.replace(/(koishi-|^@koishijs\/)plugin-/, '')

// check adapter
Expand Down
16 changes: 16 additions & 0 deletions plugins/frontend/manager/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { readFileSync } from 'fs'
import { PackageJson } from '@koishijs/market'
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
}

0 comments on commit b7346b2

Please sign in to comment.