Skip to content

Commit

Permalink
feat(manager): trigger full reload after update
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed May 7, 2022
1 parent b7346b2 commit d794f7a
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 27 deletions.
2 changes: 1 addition & 1 deletion packages/cli/src/worker/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default class Loader extends ConfigLoader<App.Config> {
this.app.logger('diagnostic').warn('plugin %c is missing required service %c', name, missing.join(', '))
}

fullReload() {
fullReload(): never {
logger.info('trigger full reload')
process.exit(51)
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/frontend/console/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class HttpService extends DataService<string[]> {
})
}

async get() {
get() {
const { devMode, uiPath } = this.config
const filenames: string[] = []
for (const key in this.data) {
Expand Down
4 changes: 2 additions & 2 deletions plugins/frontend/console/src/service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, Service } from 'koishi'
import { Awaitable, Context, Service } from 'koishi'
import Console from '.'

export namespace DataService {
Expand All @@ -21,7 +21,7 @@ export abstract class DataService<T = never> extends Service {
})
}

public get(forced?: boolean): Promise<T> {
public get(forced?: boolean): Awaitable<T> {
return null
}

Expand Down
16 changes: 11 additions & 5 deletions plugins/frontend/manager/client/deps/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@

<script lang="ts" setup>
import { computed } from 'vue'
import { store, send } from '@koishijs/client'
import { computed, watch } from 'vue'
import { store, send, socket } from '@koishijs/client'
import { config, overrideCount } from '../utils'
import { message, loading } from '@koishijs/client'
import PackageView from './package.vue'
Expand All @@ -60,16 +60,22 @@ async function install() {
const instance = loading({
text: '正在更新依赖……',
})
const dispose = watch(socket, () => {
message.success('安装成功!')
dispose()
instance.close()
})
try {
const code = await send('market/install', config.override)
if (code === 0) {
message.success('安装成功!')
} else {
if (code) {
message.error('安装失败!')
} else {
message.success('安装成功!')
}
} catch (err) {
message.error('安装超时!')
} finally {
dispose()
instance.close()
}
}
Expand Down
45 changes: 28 additions & 17 deletions plugins/frontend/manager/src/installer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Context, Dict, Logger } from 'koishi'
import { Context, defineProperty, Dict, Logger } from 'koishi'
import { DataService } from '@koishijs/plugin-console'
import { PackageJson } from '@koishijs/market'
import { resolve } from 'path'
import { promises as fsp } from 'fs'
import { loadManifest } from './utils'
import {} from '@koishijs/cli'
import which from 'which-pm-runs'
import spawn from 'cross-spawn'

Expand All @@ -19,16 +20,17 @@ const logger = new Logger('market')
export interface Dependency {
request: string
resolved: string
workspace?: boolean
versions?: Partial<PackageJson>[]
workspace: boolean
active?: boolean
}

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

constructor(public ctx: Context) {
super(ctx, 'dependencies', { authority: 4 })
this.meta = loadManifest(this.cwd)
this.manifest = loadManifest(this.cwd)

ctx.console.addListener('market/install', this.installDep, { authority: 4 })
ctx.console.addListener('market/patch', this.patchDep, { authority: 4 })
Expand All @@ -38,20 +40,22 @@ class Installer extends DataService<Dict<Dependency>> {
return this.ctx.app.baseDir
}

async get() {
get(force = false) {
if (!force && this._payload) return this._payload
const results: Dict<Dependency> = {}
for (const name in this.meta.dependencies) {
for (const name in this.manifest.dependencies) {
try {
// some dependencies may be left with no local installation
const meta = loadManifest(name)
results[name] = {
request: this.meta.dependencies[name],
request: this.manifest.dependencies[name],
resolved: meta.version,
workspace: meta.$workspace,
}
defineProperty(results[name], 'active', require.resolve(name) in require.cache)
} catch {}
}
return results
return this._payload = results
}

async exec(command: string, args: string[]) {
Expand Down Expand Up @@ -80,13 +84,13 @@ class Installer extends DataService<Dict<Dependency>> {
const filename = resolve(this.cwd, 'package.json')
for (const key in deps) {
if (deps[key]) {
this.meta.dependencies[key] = deps[key]
this.manifest.dependencies[key] = deps[key]
} else {
delete this.meta.dependencies[key]
delete this.manifest.dependencies[key]
}
}
this.meta.dependencies = Object.fromEntries(Object.entries(this.meta.dependencies).sort((a, b) => a[0].localeCompare(b[0])))
await fsp.writeFile(filename, JSON.stringify(this.meta, null, 2))
this.manifest.dependencies = Object.fromEntries(Object.entries(this.manifest.dependencies).sort((a, b) => a[0].localeCompare(b[0])))
await fsp.writeFile(filename, JSON.stringify(this.manifest, null, 2))
}

patchDep = async (name: string, version: string) => {
Expand All @@ -96,17 +100,24 @@ class Installer extends DataService<Dict<Dependency>> {

installDep = async (deps: Dict<string>) => {
const agent = which()?.name || 'npm'
const oldPayload = this.get()
await this.override(deps)
const args: string[] = []
if (agent !== 'yarn') args.push('install')
const { registry } = this.ctx.console.market.config
if (registry) args.push('--registry=' + registry)
const code = await this.exec(agent, args)
if (!code) {
this.refresh()
this.ctx.console.packages.refresh()
if (code) return code
await this.refresh()
const newPayload = this.get()
for (const name in oldPayload) {
const { active, resolved, workspace } = oldPayload[name]
if (workspace || !active) continue
if (newPayload[name].resolved === resolved) continue
this.ctx.loader.fullReload()
}
return code
this.ctx.console.packages.refresh()
return 0
}
}

Expand Down
7 changes: 6 additions & 1 deletion plugins/frontend/manager/src/packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ const logger = new Logger('market')
/** require without affecting the dependency tree */
function getExports(id: string) {
const path = require.resolve(id)
const keys = Object.keys(require.cache)
let result = require.cache[path]
if (!result) {
require(path)
result = require.cache[path]
remove(module.children, result)
delete require.cache[path]
for (const key in require.cache) {
if (!keys.includes(key)) {
delete require.cache[key]
}
}
}
return ns.unwrapExports(result.exports)
}
Expand Down

0 comments on commit d794f7a

Please sign in to comment.