feat(update): support safe plugin bundle reload
这个提交包含在:
父节点
c8a6d88ab9
当前提交
e7b31d7fc6
@ -108,6 +108,8 @@ pnpm --dir packages/update test
|
||||
- alpha 版本号改为取源码现有序号与 Nexus 远端序号的最大值后加一,禁止版本倒退和重复发布。
|
||||
- `#49` 被 Jenkins CPS 的不可序列化正则 Matcher 阻断;算法改为只保留整数,并从 Nexus group 读标签、向 hosted 写制品。
|
||||
- `#50` 证明旧 Jenkins 工作树仍保留 CRLF;主检出由 `CleanBeforeCheckout` 改为 `WipeWorkspace`,确保 `.gitattributes` 在全新工作树生效。
|
||||
- `XuqmRuntime.activate` 增加显式 `reloadBundle`:buz-only release 可替换旧定义并热加载;含 common 的 release 仍由宿主冷启动。
|
||||
- `#51` 通过换行、格式和类型门禁后,暴露 pack 校验脚本硬编码 Unix `npm`;现改为 `fileURLToPath` 与 Windows `cmd.exe/npm.cmd` 分支。
|
||||
|
||||
### 2026-07-17 / common 第一轮
|
||||
|
||||
|
||||
@ -37,6 +37,10 @@ apply from: file("../../node_modules/@xuqm/rn-update/android/xuqm-bundles.gradle
|
||||
|
||||
## 运行时规则
|
||||
|
||||
安装仅包含 buz 的 release set 后,使用
|
||||
`XuqmRuntime.activate(moduleId, { reloadBundle: true })` 重新求值并激活新 bundle。若 release set
|
||||
包含 common,宿主必须冷启动,不能在同一 JavaScript VM 中混用新旧 common。
|
||||
|
||||
```ts
|
||||
import { UpdateSDK, XuqmRuntime } from '@xuqm/rn-update'
|
||||
|
||||
|
||||
@ -4,15 +4,26 @@ import { execFileSync } from 'node:child_process'
|
||||
import { readFileSync, rmSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const cwd = new URL('..', import.meta.url).pathname
|
||||
const result = JSON.parse(
|
||||
execFileSync('npm', ['pack', '--json', '--ignore-scripts'], {
|
||||
const cwd = fileURLToPath(new URL('..', import.meta.url))
|
||||
const packOutput =
|
||||
process.platform === 'win32'
|
||||
? execFileSync(
|
||||
process.env.ComSpec ?? 'cmd.exe',
|
||||
['/d', '/s', '/c', 'npm.cmd pack --json --ignore-scripts'],
|
||||
{
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
env: { ...process.env, npm_config_cache: path.join(tmpdir(), 'xuqm-rn-npm-cache') },
|
||||
}),
|
||||
)[0]
|
||||
},
|
||||
)
|
||||
: execFileSync('npm', ['pack', '--json', '--ignore-scripts'], {
|
||||
cwd,
|
||||
encoding: 'utf8',
|
||||
env: { ...process.env, npm_config_cache: path.join(tmpdir(), 'xuqm-rn-npm-cache') },
|
||||
})
|
||||
const result = JSON.parse(packOutput)[0]
|
||||
const required = [
|
||||
'android/src/main/AndroidManifest.xml',
|
||||
'android/src/main/java/com/xuqm/update/XuqmBundleModule.java',
|
||||
|
||||
@ -19,6 +19,11 @@ export interface XuqmRuntimeOptions {
|
||||
checkUpdatesOnStart?: boolean
|
||||
}
|
||||
|
||||
export interface XuqmPluginActivationOptions {
|
||||
/** Re-evaluate the active bundle after a buz-only release was installed. */
|
||||
reloadBundle?: boolean
|
||||
}
|
||||
|
||||
const definitions = new Map<string, XuqmPluginDefinition>()
|
||||
|
||||
/** Called by a plugin bundle when it is evaluated. */
|
||||
@ -55,9 +60,19 @@ export const XuqmRuntime = (() => {
|
||||
return { kind: 'none' as const }
|
||||
},
|
||||
|
||||
async activate(moduleId: string): Promise<void> {
|
||||
async activate(
|
||||
moduleId: string,
|
||||
activationOptions: XuqmPluginActivationOptions = {},
|
||||
): Promise<void> {
|
||||
if (!options) throw new Error('[XuqmRuntime] configure() must be called before activate()')
|
||||
if (active.has(moduleId)) return
|
||||
if (active.has(moduleId) && !activationOptions.reloadBundle) return
|
||||
|
||||
if (activationOptions.reloadBundle) {
|
||||
const previous = definitions.get(moduleId)
|
||||
if (previous?.deactivate) await previous.deactivate()
|
||||
active.delete(moduleId)
|
||||
definitions.delete(moduleId)
|
||||
}
|
||||
|
||||
let definition = definitions.get(moduleId)
|
||||
if (!definition) {
|
||||
|
||||
@ -20,4 +20,9 @@ export type {
|
||||
ReleaseSetPlan,
|
||||
} from './releaseSet'
|
||||
export { XuqmRuntime, definePlugin } from './PluginRuntime'
|
||||
export type { XuqmPluginContext, XuqmPluginDefinition, XuqmRuntimeOptions } from './PluginRuntime'
|
||||
export type {
|
||||
XuqmPluginActivationOptions,
|
||||
XuqmPluginContext,
|
||||
XuqmPluginDefinition,
|
||||
XuqmRuntimeOptions,
|
||||
} from './PluginRuntime'
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户