@aalis/plugin-package-manager 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { type ProcessService } from '@aalis/api-process';
1
2
  import type { Context } from '@aalis/core';
2
- import { type ProcessService } from '@aalis/plugin-process-api';
3
3
  export declare const name = "@aalis/plugin-package-manager";
4
4
  export declare const displayName = "\u5305\u7BA1\u7406\u5668";
5
5
  export declare const subsystem = "system";
@@ -8,34 +8,82 @@ export declare const inject: {
8
8
  required: string[];
9
9
  };
10
10
  /**
11
- * 包管理服务:从 npm 安装/卸载插件到 packages/ 目录
11
+ * 包管理服务:在项目根 `dependencies` 里装卸插件。
12
12
  *
13
13
  * 通过 `ctx.getService<PackageManagerService>('package-manager')` 消费。
14
14
  *
15
- * 这些操作涉及子进程(npm/tar/pnpm/rm),不属于 core 内核职责,
16
- * 因此从 App 抽出到独立插件;底层子进程统一走 plugin-process-api。
15
+ * 根 `dependencies` 是加载器**唯一**的发现来源,所以装卸都落在那里——不再有「解包到
16
+ * packages/ 目录」那条路径(它按 `pnpm-workspace.yaml` 猜部署形态,而那个文件与真正
17
+ * 生效的加载器无因果关系,猜错时会把包装进加载器永不查看的地方并静默失败)。
18
+ *
19
+ * 这些操作涉及子进程(npm),不属于 core 内核职责,因此从 App 抽出到独立插件;
20
+ * 底层子进程统一走 api-process。
17
21
  */
18
22
  export interface PackageManagerService {
19
- /** 从 npm 安装插件到 packages/ 并触发 rescanPlugins */
23
+ /** 装进根 `dependencies` + node_modules,随后 rescan 让加载器发现它 */
20
24
  install(npmPkg: string): Promise<{
21
25
  ok: boolean;
22
26
  message: string;
23
27
  }>;
24
- /** 停用并删除 packages/ 下对应目录 */
28
+ /** 从根 `dependencies` 摘掉并 npm uninstall;只接受插件与前端界面包(见 uninstallOne 的两道闸) */
25
29
  uninstall(pluginName: string): Promise<{
26
30
  ok: boolean;
27
31
  message: string;
28
32
  }>;
33
+ /**
34
+ * 批量更新到指定版本,随后重启进程接管。
35
+ *
36
+ * **必须整批提交**,不能每个包各调一次:
37
+ * - peer 冲突只有对整张版本映射一次预检才能发现(A@new 要 core>=0.10、B@new 要
38
+ * core<0.10,逐个预检各自都过,一起装才冲突);
39
+ * - 更新是文件系统操作而进程只在启动那一刻读文件系统,所以重启次数恒为 1,
40
+ * 与改了多少个包无关。逐个更新 = 重启 N 次,且中间态是半新半旧。
41
+ *
42
+ * 返回 `ok: true` 表示已提交安装并即将重启——此时 HTTP 响应要抢在进程退出前发出。
43
+ */
44
+ update(targets: UpdateTarget[]): Promise<UpdateResult>;
45
+ }
46
+ /** 一个待更新目标:包名 + 目标版本(不带范围符,由调用方从市场卡片取 npm latest)。 */
47
+ export interface UpdateTarget {
48
+ name: string;
49
+ version: string;
50
+ }
51
+ export interface UpdateResult {
52
+ ok: boolean;
53
+ message: string;
54
+ /** 预检失败时的逐条冲突说明(npm dry-run 的报告摘要),供前端直接展示。 */
55
+ conflicts?: string[];
56
+ /** 本次是否会重启进程。ok 且 restarting 时前端应进入「等待重连」状态。 */
57
+ restarting?: boolean;
29
58
  }
30
59
  /**
31
- * 解析 `npm pack --json` 的输出 → 产物 {filename, name}。
32
- * npm pack --json 输出形如 `[{"filename":"scope-foo-1.2.3.tgz","name":"@scope/foo",...}]`。
33
- * 部分 npm 版本会在 JSON 前混入 notice,故定位首个 `[` 起截取。纯函数,便于单测。
60
+ * 根依赖里是否含 `workspace:` 协议。
61
+ *
62
+ * 这是 standalone 分支跑 `npm install` 前的**硬护栏**:npm 遇到该协议会
63
+ * `EUNSUPPORTEDPROTOCOL` 硬失败;但若哪天根依赖恰好没有该协议,`npm install` 会在
64
+ * pnpm 仓库根写出 `package-lock.json` 与扁平 `node_modules`,把整个工作区搅坏。
65
+ * 故不能指望 npm 兜底,必须自己先判。纯函数,便于单测。
34
66
  */
35
- export declare function parsePackInfo(jsonOut: string): {
36
- filename: string;
37
- name: string;
38
- } | undefined;
67
+ export declare function hasWorkspaceProtocol(pkgJson: Record<string, unknown> | undefined): boolean;
68
+ /**
69
+ * 包是否声明自己是可加载插件(与两个加载器同一判据:纯 `aalis-plugin` 关键词正向门)。
70
+ *
71
+ * 用途是把「装完没发现新插件」分成两种情形:目标本就不是插件(如 `aalis-interface`
72
+ * 前端包)→ 正常;目标声明了自己是插件却没被发现 → **静默假成功**,必须报失败。
73
+ * 纯函数,便于单测。
74
+ */
75
+ export declare function declaresPlugin(pkgJson: Record<string, unknown> | undefined): boolean;
76
+ /**
77
+ * 校验单个包 spec,合法返回 `undefined`、非法返回可读理由。
78
+ *
79
+ * 放在**服务层**:本服务经 `ctx.provide` 公开,任何插件都能绕过 HTTP 路由直接调用。
80
+ * 这与 `buildUpdateSpecs` 是同一条纪律——路由只做「是不是字符串」的形状检查,安全校验
81
+ * 收在所有调用方的必经之路上。**argv 面只有这一份实现**(两份正则漂移是本仓栽过的坑);
82
+ * URL 路径段另有一份不含版本段的(webui-server 的 depgraph 端点,见那里的注释)——
83
+ * 两者挡的东西不同,不是同一份的拷贝,别再把它们合并成一条。
84
+ * 纯函数,便于单测。
85
+ */
86
+ export declare function validatePackageSpec(spec: unknown): string | undefined;
39
87
  /** install/uninstall 的显式依赖(从 ctx/网关解耦,便于集成测试) */
40
88
  export interface PackageManagerDeps {
41
89
  proc: ProcessService;
@@ -43,14 +91,75 @@ export interface PackageManagerDeps {
43
91
  info(msg: string): void;
44
92
  error(msg: string): void;
45
93
  };
46
- /** 真实插件目录绝对路径(= `<cwd>/packages`,与 FS 加载器一致) */
47
- packagesDir(): string;
94
+ /** 项目根绝对路径(= `<cwd>`):形态探测、根 package.json 读取、npm 的 cwd。 */
95
+ projectRoot(): string;
96
+ /** 读文本文件;不存在或读失败返回 undefined。注入以便单测。 */
97
+ readText(absPath: string): Promise<string | undefined>;
48
98
  rescanPlugins(): Promise<string[]>;
99
+ /**
100
+ * 目标插件此刻是否已在运行时注册表里。
101
+ *
102
+ * 这是判定「本次安装是否就位」的**唯一正确判据**。不能用 `rescanPlugins()` 的返回值:
103
+ * 它是全局副作用的产物——core 的 rescan 对已注册插件直接跳过,返回的是「本次扫描新
104
+ * 加载的**全部**插件」,与本次目标无对应关系。用它会在两个场景下给出错误结论:
105
+ * 重装已注册插件时恒返回空(误报失败);两个安装并发时先跑完的那个会把对方的战果
106
+ * 一并算作自己的(谎报),后跑的则拿到空数组(误报失败)。
107
+ */
108
+ isPluginRegistered(name: string): boolean;
49
109
  /** 彻底卸载插件(dispose + 从注册表移除)。plugins 服务缺席则 no-op。 */
50
110
  unloadPlugin(name: string): Promise<void>;
111
+ /**
112
+ * 当前**承载撤销通道**的服务提供者包名列表(去重)。卸掉其中任何一个,用户就只能开
113
+ * shell 恢复——与内核/宿主同一条判据。见 uninstallOne 的闸一之二。
114
+ */
115
+ recoveryChannelProviders?(): string[];
51
116
  /** 卸载后清理残留配置(删配置块 + 解除禁用标记 + 持久化)。可选:缺省则不清理。 */
52
117
  cleanupConfig?(name: string): void;
118
+ /** 重启进程并交付回滚凭据(新实例起不来时由重启策略消费)。缺省则 update 不可用。 */
119
+ restartApp?(rollback: {
120
+ reason: string;
121
+ /** `deleteIfEmpty` 表示该文件更新前并不存在,回滚时应删除而非写空(见 runtime 的 RestartRollback)。 */
122
+ restore: Array<{
123
+ path: string;
124
+ content: string;
125
+ deleteIfEmpty?: boolean;
126
+ }>;
127
+ postRestore?: {
128
+ cmd: string;
129
+ args: string[];
130
+ cwd: string;
131
+ };
132
+ }): void;
53
133
  }
134
+ /** `@scope/foo@1.2.3` → `@scope/foo`(剥掉版本后缀,保留 scope)。 */
135
+ export declare function stripVersion(spec: string): string;
136
+ /**
137
+ * 校验一批更新目标,产出可直接交给 npm 的 `name@version` spec。
138
+ *
139
+ * 拒绝而非净化:这些值最终作为独立 argv 交给 npm,任何一条可疑就整批停下,
140
+ * 不猜用户意图。纯函数,便于单测。
141
+ */
142
+ export declare function buildUpdateSpecs(targets: readonly UpdateTarget[]): {
143
+ specs?: string[];
144
+ error?: string;
145
+ };
146
+ /**
147
+ * 从 npm 的失败输出里摘出冲突要点,供前端直接展示。纯函数,便于单测。
148
+ */
149
+ export declare function extractPeerConflicts(output: string): string[];
150
+ /**
151
+ * 从 **成功**(exit 0)的 dry-run 输出里找出因本次目标而无法满足的 peer 依赖。
152
+ *
153
+ * 为什么不能只靠退出码——已实测(npm 10.9.2):
154
+ * - 「装一个新包、其 peer 不满足」→ npm 本就 exit 1,`--strict-peer-deps` 无增量价值;
155
+ * - 「**改一个已被别人 peer 依赖的包的版本**」(正是更新 core 的形状)→ npm 把命令行上
156
+ * 显式指定的 spec 当作用户意图,**只打 warn 且 exit 0**,`--strict-peer-deps` 同样不生效,
157
+ * 把目标版本先写进 package.json 再裸装也一样。
158
+ *
159
+ * 而它确实会在 stderr 打出 `peer <name>@"<range>" from <dependent>`。只认**提到本次目标**
160
+ * 的那些行:工程里原有的、与本次无关的未满足 peer 不该阻断更新。
161
+ */
162
+ export declare function findUnmetPeers(output: string, targetNames: readonly string[]): string[];
54
163
  /**
55
164
  * 包管理核心:install/uninstall 的纯依赖实现(不碰 ctx/网关,可单测)。
56
165
  * 所有文件操作走 process 网关(子进程:npm/tar/mkdir/rm/test),目标是真实
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,OAAO,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAyC,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIvG,eAAO,MAAM,IAAI,kCAAkC,CAAC;AACpD,eAAO,MAAM,WAAW,6BAAS,CAAC;AAClC,eAAO,MAAM,SAAS,WAAW,CAAC;AAClC,eAAO,MAAM,QAAQ,UAAsB,CAAC;AAC5C,eAAO,MAAM,MAAM;;CAElB,CAAC;AAIF;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,4BAA4B;IAC5B,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAW7F;AA6DD,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE;QAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC3D,gDAAgD;IAChD,WAAW,IAAI,MAAM,CAAC;IACtB,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,oDAAoD;IACpD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,gDAAgD;IAChD,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,qBAAqB,CAqFpF;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAIzE;AAGD,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,cAAc;QACtB,iBAAiB,EAAE,qBAAqB,CAAC;KAC1C;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import { createProcessGateway } from '@aalis/plugin-process-api';
1
+ import { createProcessGateway } from '@aalis/api-process';
2
+ import { classifyDepSpec, isRegistryDep, isUpgrade } from '@aalis/util-dep-spec';
2
3
  // ===== 插件元数据 =====
3
4
  export const name = '@aalis/plugin-package-manager';
4
5
  export const displayName = '包管理器';
@@ -8,30 +9,26 @@ export const inject = {
8
9
  required: ['process'],
9
10
  };
10
11
  // ===== 实现 =====
12
+ /** 短命令(mkdir/tar/rm/test/npm pack)的超时。 */
13
+ const QUICK_TIMEOUT_MS = 120_000;
11
14
  /**
12
- * 解析 `npm pack --json` 的输出 → 产物 {filename, name}。
13
- * npm pack --json 输出形如 `[{"filename":"scope-foo-1.2.3.tgz","name":"@scope/foo",...}]`。
14
- * 部分 npm 版本会在 JSON 前混入 notice,故定位首个 `[` 起截取。纯函数,便于单测。
15
+ * 安装类命令的超时。`npm install` 要装全依赖树 + 原生编译(better-sqlite3、puppeteer
16
+ * 都在脚手架默认依赖里),快机快网下已达 95 秒量级,而超时行为是 SIGKILL——留足余量,
17
+ * 否则会在半装状态下被杀。
15
18
  */
16
- export function parsePackInfo(jsonOut) {
17
- try {
18
- const start = jsonOut.indexOf('[');
19
- if (start < 0)
20
- return undefined;
21
- const arr = JSON.parse(jsonOut.slice(start));
22
- const first = arr?.[0];
23
- if (!first?.filename || !first?.name)
24
- return undefined;
25
- return { filename: first.filename, name: first.name };
26
- }
27
- catch {
28
- return undefined;
29
- }
19
+ const INSTALL_TIMEOUT_MS = 600_000;
20
+ async function execProc(proc, cmd, args, cwd, timeout = QUICK_TIMEOUT_MS) {
21
+ return (await execProcBoth(proc, cmd, args, cwd, timeout)).stdout;
30
22
  }
31
- async function execProc(proc, cmd, args, cwd) {
23
+ /** 同 {@link execProc},但同时给出 stderr——npm 的诊断(含 peer 告警)都写在 stderr。 */
24
+ async function execProcBoth(proc, cmd, args, cwd, timeout = QUICK_TIMEOUT_MS, extraEnv) {
32
25
  try {
33
- const result = await proc.execFile(cmd, args, { cwd, timeout: 120_000 });
34
- return result.stdout;
26
+ const result = await proc.execFile(cmd, args, {
27
+ cwd,
28
+ timeout,
29
+ ...(extraEnv ? { env: { ...process.env, ...extraEnv } } : {}),
30
+ });
31
+ return { stdout: result.stdout, stderr: result.stderr ?? '' };
35
32
  }
36
33
  catch (err) {
37
34
  const withResult = err;
@@ -39,6 +36,66 @@ async function execProc(proc, cmd, args, cwd) {
39
36
  throw new Error(stderr || withResult.message);
40
37
  }
41
38
  }
39
+ /**
40
+ * 根依赖里是否含 `workspace:` 协议。
41
+ *
42
+ * 这是 standalone 分支跑 `npm install` 前的**硬护栏**:npm 遇到该协议会
43
+ * `EUNSUPPORTEDPROTOCOL` 硬失败;但若哪天根依赖恰好没有该协议,`npm install` 会在
44
+ * pnpm 仓库根写出 `package-lock.json` 与扁平 `node_modules`,把整个工作区搅坏。
45
+ * 故不能指望 npm 兜底,必须自己先判。纯函数,便于单测。
46
+ */
47
+ export function hasWorkspaceProtocol(pkgJson) {
48
+ if (!pkgJson)
49
+ return false;
50
+ for (const field of ['dependencies', 'devDependencies', 'optionalDependencies']) {
51
+ const block = pkgJson[field];
52
+ if (!block || typeof block !== 'object')
53
+ continue;
54
+ for (const v of Object.values(block)) {
55
+ if (typeof v === 'string' && v.startsWith('workspace:'))
56
+ return true;
57
+ }
58
+ }
59
+ return false;
60
+ }
61
+ /**
62
+ * 包是否声明自己是可加载插件(与两个加载器同一判据:纯 `aalis-plugin` 关键词正向门)。
63
+ *
64
+ * 用途是把「装完没发现新插件」分成两种情形:目标本就不是插件(如 `aalis-interface`
65
+ * 前端包)→ 正常;目标声明了自己是插件却没被发现 → **静默假成功**,必须报失败。
66
+ * 纯函数,便于单测。
67
+ */
68
+ export function declaresPlugin(pkgJson) {
69
+ const kw = pkgJson?.keywords;
70
+ return Array.isArray(kw) && kw.includes('aalis-plugin');
71
+ }
72
+ /**
73
+ * 合法 npm 包 spec:包名(可选 scope)+ 可选 `@version` 后缀。
74
+ *
75
+ * 名段与版本段的首字符**都**必须是字母数字。该值最终作为一个 argv 传给 npm,而 npm 会:
76
+ * - 把以 `-` 开头的 token 当命令行标志(`--force`、`--ignore-scripts` 都是 npm 上真实存在的可发布包名);
77
+ * - 把 `.` / `..` / `./x` 当本地目录 spec —— **`foo@.` 与 `@a/b@..` 同样是目录 spec**,
78
+ * 只锚名段挡不住;实测这条能让 npm 转去打包宿主工作目录并执行其 prepack/prepare 生命周期脚本。
79
+ * 两段各自锚住首字符,即封死目录 spec 与标志注入两条面。
80
+ */
81
+ const PKG_SPEC_RE = /^(@[a-z0-9][a-z0-9\-_.]*\/)?[a-z0-9][a-z0-9\-_.]*(@[a-z0-9][a-z0-9.-]*)?$/i;
82
+ /**
83
+ * 校验单个包 spec,合法返回 `undefined`、非法返回可读理由。
84
+ *
85
+ * 放在**服务层**:本服务经 `ctx.provide` 公开,任何插件都能绕过 HTTP 路由直接调用。
86
+ * 这与 `buildUpdateSpecs` 是同一条纪律——路由只做「是不是字符串」的形状检查,安全校验
87
+ * 收在所有调用方的必经之路上。**argv 面只有这一份实现**(两份正则漂移是本仓栽过的坑);
88
+ * URL 路径段另有一份不含版本段的(webui-server 的 depgraph 端点,见那里的注释)——
89
+ * 两者挡的东西不同,不是同一份的拷贝,别再把它们合并成一条。
90
+ * 纯函数,便于单测。
91
+ */
92
+ export function validatePackageSpec(spec) {
93
+ if (typeof spec !== 'string' || spec.length === 0)
94
+ return '包名必须是非空字符串';
95
+ if (!PKG_SPEC_RE.test(spec))
96
+ return `非法包名: ${JSON.stringify(spec)}`;
97
+ return undefined;
98
+ }
42
99
  function createService(ctx, config) {
43
100
  const log = ctx.logger;
44
101
  const proc = createProcessGateway(ctx);
@@ -48,29 +105,68 @@ function createService(ctx, config) {
48
105
  throw new Error('app 服务不可用,无法执行包管理操作');
49
106
  return app;
50
107
  }
51
- /**
52
- * 真实插件目录的绝对路径。
53
- *
54
- * 必须与 core 的 createFsPluginLoader 一致——后者扫描 `<cwd>/packages`。
55
- * 关键:**不能**走 storage 的 `workspace:` 根(那是 agent 沙盒 `<cwd>/workspace`,
56
- * 与插件目录 `<cwd>/packages` 不是同一处),否则装到/找错地方(历史 bug:
57
- * 卸载报"目录不存在")。可用插件配置 `packagesDir` 覆盖(相对 cwd 或绝对路径)。
58
- */
59
- function packagesDir() {
60
- const override = config.packagesDir;
61
- const base = process.cwd();
108
+ /** 把配置里的相对/绝对路径归一成绝对路径;未配置则用 fallback。 */
109
+ function resolveConfigured(key, fallback) {
110
+ const override = config[key];
62
111
  if (typeof override === 'string' && override.length > 0) {
63
- return override.startsWith('/') ? override : `${base}/${override.replace(/^\.?\/+/, '')}`;
112
+ return override.startsWith('/') ? override : `${process.cwd()}/${override.replace(/^\.?\/+/, '')}`;
64
113
  }
65
- return `${base}/packages`;
114
+ return fallback;
115
+ }
116
+ function projectRoot() {
117
+ return resolveConfigured('projectRoot', process.cwd());
66
118
  }
67
119
  return createPackageManager({
68
120
  proc,
69
121
  log,
70
- packagesDir,
122
+ // 项目根:默认 cwd,与 createNodeModulesPluginLoader(projectDir = process.cwd()) 的
123
+ // 默认值同源——两者必须指同一处,否则「我们写的 package.json」与「加载器读的
124
+ // package.json」是两份,装了永远不加载。
125
+ // 宿主若给 startAalis 传了非 cwd 的 projectDir(公开选项),必须用本配置项对齐。
126
+ projectRoot,
127
+ // 经 process 网关的 readExternalFile 读,而非 node:fs:目标(项目根 package.json、
128
+ // lockfile、node_modules/<pkg>/package.json)在 storage 沙盒之外,而 readExternalFile
129
+ // 正是文档给这一场景指定的「OS 直通读外部路径」通道——本插件也不在 biome 的 node:* 例外清单里。
130
+ readText: async (absPath) => {
131
+ try {
132
+ return new TextDecoder().decode(await proc.readExternalFile(absPath));
133
+ }
134
+ catch {
135
+ return undefined;
136
+ }
137
+ },
71
138
  rescanPlugins: () => getApp().rescanPlugins(),
139
+ // 判据取运行时注册表而非 rescan 返回值(理由见 PackageManagerDeps.isPluginRegistered)。
140
+ // plugins 服务缺席时保守返回 false——宁可让「声明为插件却没加载」的诊断多报一次,
141
+ // 也不要在真没装上时谎报成功。
142
+ isPluginRegistered: name => ctx
143
+ .getService('plugins')
144
+ ?.getStatus()
145
+ .some(p => p.name === name) ?? false,
146
+ // 重启并交付回滚凭据。core 只透传 rollback(不解释形状),由 runtime 的重启策略
147
+ // 在「新实例 ready 前夭折」时消费——触发者与执行者同为父进程,全程内存不落盘。
148
+ //
149
+ // `restart(opts)` 收参数是 core **0.10.0** 才有的;0.9.x 的 `restart()` 不收参数,
150
+ // 多传的对象被静默丢弃 —— 不报错、不告警,只是更新失败后重启起来的是坏版本,
151
+ // 回滚安全网整个不存在。故 peerDependencies 下界必须是 `>=0.10.0`,不能沿用 0.2.0。
152
+ restartApp: rollback => getApp().restart({ rollback }),
72
153
  // 彻底卸载:dispose 上下文并从注册表移除(plugins 服务缺席则 no-op)。
73
154
  // 区别于 disablePlugin(仅置禁用态,仍滞留在插件列表里)。
155
+ // 撤销通道 = 市场页能用所依赖的三样:页面本身 / 托管它的服务端 / 装卸能力本身。
156
+ // 取每个服务当前生效的 provider(`getAllServices` 首个即是),contextId 就是包名
157
+ // (插件以包名做 ctx.id,webui-server 也用包名做前端候选的 fork id)。
158
+ // 服务缺席时该项自然不在列表里——不启用 WebUI 的部署不受影响。
159
+ // contextId 直接就是包名,**不要**再切分:包名带 scope(`@aalis/plugin-webui-client`)时
160
+ // `split('/')[0]` 会把它截成 `@aalis`,与下游 `lifeline.includes(pluginName)` 永不相等,
161
+ // 整道闸对全部 scoped 包恒不触发(实测三个目标全放行)。这三个服务都以 `ctx.fork(包名)`
162
+ // 或插件自身 ctx 注册,contextId 不含 entryId 后缀;真出现多实例后缀要靠 module 声明
163
+ // `reusable`,而这三个都没有,故也不需要为此加解析。
164
+ recoveryChannelProviders: () => [
165
+ ...new Set(['webui-client', 'webui-server', 'package-manager'].flatMap(n => {
166
+ const id = ctx.getAllServices(n)[0]?.contextId;
167
+ return id ? [id] : [];
168
+ })),
169
+ ],
74
170
  unloadPlugin: async (name) => {
75
171
  const pm = ctx.getService('plugins');
76
172
  if (pm)
@@ -85,6 +181,142 @@ function createService(ctx, config) {
85
181
  },
86
182
  });
87
183
  }
184
+ /** `@scope/foo@1.2.3` → `@scope/foo`(剥掉版本后缀,保留 scope)。 */
185
+ export function stripVersion(spec) {
186
+ const at = spec.lastIndexOf('@');
187
+ return at > 0 ? spec.slice(0, at) : spec;
188
+ }
189
+ /**
190
+ * 合法 npm 包名(可选 scope),**不含**版本后缀。
191
+ *
192
+ * 首字符锚死字母数字:npm 会把 `-` 开头的 token 当命令行标志,把 `.` / `..` / `./x`
193
+ * 当本地目录 spec(`foo@.` 能让 npm 转去打包宿主工作目录并执行其 prepack 脚本)。
194
+ * 版本段单独用 {@link isSafeVersion} 校验,两段各自锚住首字符才封得死。
195
+ */
196
+ const PKG_NAME_ONLY_RE = /^(@[a-z0-9][a-z0-9\-_.]*\/)?[a-z0-9][a-z0-9\-_.]*$/i;
197
+ /** 精确版本号:只收字母数字打头、不含路径与标志字符的形态。 */
198
+ const VERSION_RE = /^[a-z0-9][a-z0-9.\-+]*$/i;
199
+ /**
200
+ * 读 npm 的隐藏锁 `node_modules/.package-lock.json`,得到「此刻树上装的是哪些版本」。
201
+ *
202
+ * 这是 npm 自己维护的、对**实际 node_modules 树**的记录,比 package.json 的范围声明精确,
203
+ * 也比逐个读 `node_modules/<name>/package.json` 便宜(一次读盘拿全树)。
204
+ *
205
+ * 只取顶层条目(`node_modules/<name>`):嵌套安装(`node_modules/a/node_modules/b`)的 b 与
206
+ * 顶层的 b 不是一回事,把它按裸名钉在顶层会装错位置。
207
+ *
208
+ * 文件不存在(pnpm/yarn 装的工程,它们不写这个文件)或坏 JSON 时返回空 Map,调用方退化为
209
+ * 「只钉被点名的包」——不如全树精确,但不会更糟。
210
+ */
211
+ async function readInstalledTree(deps, root) {
212
+ const out = new Map();
213
+ const text = await deps.readText(`${root}/node_modules/.package-lock.json`);
214
+ if (text === undefined)
215
+ return out;
216
+ try {
217
+ const parsed = JSON.parse(text);
218
+ for (const [path, entry] of Object.entries(parsed.packages ?? {})) {
219
+ if (!path.startsWith('node_modules/'))
220
+ continue;
221
+ const name = path.slice('node_modules/'.length);
222
+ if (name.includes('/node_modules/'))
223
+ continue; // 嵌套安装,不是顶层那一份
224
+ if (typeof entry?.version === 'string')
225
+ out.set(name, entry.version);
226
+ }
227
+ }
228
+ catch {
229
+ /* 坏 JSON:当作读不到 */
230
+ }
231
+ return out;
232
+ }
233
+ /**
234
+ * 一批更新目标拼成 argv 后允许的总字节数。
235
+ *
236
+ * 约束的来源是 `execve(2)` 的 `ARG_MAX`:exec 要把 argv 与 envp 从旧地址空间复制到新地址
237
+ * 空间,内核必须在拆掉旧映像前把这些字节暂存下来,故这块缓冲有界——否则任何非特权进程
238
+ * 都能靠 execve 让内核任意分配内存。实测本机 `kern.argmax` = 1048576(macOS);Linux 自
239
+ * 2.6.23 起改为跟 `RLIMIT_STACK/4` 挂钩,默认 8MB 栈 → 约 2MiB,故 1MiB 是跨平台的下界。
240
+ *
241
+ * **按字节而不是按包数**:包名长度差着数量级(`ms@2.0.0` 8 字节 vs
242
+ * `@aalis/api-session-manager@0.9.1` 38 字节),拿个数近似字节等于用一个与约束无关的
243
+ * 量设闸——曾经这里是「最多 50 个包」,比真实约束低了约 600 倍,把本仓 99 个包的协调发版
244
+ * 场景直接挡死。
245
+ *
246
+ * 128 KiB 只占 ARG_MAX 的 1/8,余下留给 envp(它与 argv 共享同一预算)与 npm 的固定参数;
247
+ * 按最长的 @aalis 包名算仍容得下三千余个包,任何真实实例都够不到。
248
+ */
249
+ const SPEC_ARGV_BUDGET = 128 * 1024;
250
+ /**
251
+ * 校验一批更新目标,产出可直接交给 npm 的 `name@version` spec。
252
+ *
253
+ * 拒绝而非净化:这些值最终作为独立 argv 交给 npm,任何一条可疑就整批停下,
254
+ * 不猜用户意图。纯函数,便于单测。
255
+ */
256
+ export function buildUpdateSpecs(targets) {
257
+ if (!Array.isArray(targets) || targets.length === 0)
258
+ return { error: '未指定更新目标' };
259
+ const specs = [];
260
+ const seen = new Set();
261
+ let bytes = 0;
262
+ for (const t of targets) {
263
+ const name = typeof t?.name === 'string' ? t.name : '';
264
+ const version = typeof t?.version === 'string' ? t.version : '';
265
+ if (!PKG_NAME_ONLY_RE.test(name))
266
+ return { error: `非法包名: ${JSON.stringify(name)}` };
267
+ if (!VERSION_RE.test(version))
268
+ return { error: `非法版本号: ${name}@${JSON.stringify(version)}` };
269
+ // 同名多版本会让 npm 取最后一个,静默丢弃前面的选择——宁可让用户重选。
270
+ if (seen.has(name))
271
+ return { error: `同一包被指定了多次: ${name}` };
272
+ seen.add(name);
273
+ const spec = `${name}@${version}`;
274
+ // 按**字节**计而非按个数:这些 spec 逐条成为 argv,而 execve 的约束是参数块的总字节数,
275
+ // 与包数无关(`ms@2.0.0` 8 字节,`@aalis/api-session-manager@0.9.1` 38 字节)。
276
+ // 超限即整批停下,与本函数其余校验同一策略:不猜、不截断。
277
+ bytes += Buffer.byteLength(spec) + 1; // +1 = argv 之间的 NUL 分隔
278
+ if (bytes > SPEC_ARGV_BUDGET) {
279
+ return { error: `更新目标过多:参数总长已超 ${SPEC_ARGV_BUDGET} 字节,请分批提交` };
280
+ }
281
+ specs.push(spec);
282
+ }
283
+ return { specs };
284
+ }
285
+ /**
286
+ * 从 npm 的失败输出里摘出冲突要点,供前端直接展示。纯函数,便于单测。
287
+ */
288
+ export function extractPeerConflicts(output) {
289
+ const lines = output.split('\n');
290
+ const picked = lines.filter(l => /ERESOLVE|peer |Conflicting peer|Found:|Could not resolve/i.test(l));
291
+ return picked.map(l => l.replace(/^npm (ERR!|error|warn)\s*/i, '').trim()).filter(l => l.length > 0);
292
+ }
293
+ /**
294
+ * 从 **成功**(exit 0)的 dry-run 输出里找出因本次目标而无法满足的 peer 依赖。
295
+ *
296
+ * 为什么不能只靠退出码——已实测(npm 10.9.2):
297
+ * - 「装一个新包、其 peer 不满足」→ npm 本就 exit 1,`--strict-peer-deps` 无增量价值;
298
+ * - 「**改一个已被别人 peer 依赖的包的版本**」(正是更新 core 的形状)→ npm 把命令行上
299
+ * 显式指定的 spec 当作用户意图,**只打 warn 且 exit 0**,`--strict-peer-deps` 同样不生效,
300
+ * 把目标版本先写进 package.json 再裸装也一样。
301
+ *
302
+ * 而它确实会在 stderr 打出 `peer <name>@"<range>" from <dependent>`。只认**提到本次目标**
303
+ * 的那些行:工程里原有的、与本次无关的未满足 peer 不该阻断更新。
304
+ */
305
+ export function findUnmetPeers(output, targetNames) {
306
+ const names = new Set(targetNames);
307
+ // npm 会把同一条 peer 冲突在不同上下文里重复打印,去重后再给用户。
308
+ const out = new Set();
309
+ for (const raw of output.split('\n')) {
310
+ const line = raw.replace(/^npm (ERR!|error|warn)\s*/i, '').trim();
311
+ const m = /^peer\s+(\S+?)@"([^"]+)"\s+from\s+(.+)$/.exec(line);
312
+ if (!m)
313
+ continue;
314
+ if (!names.has(m[1]))
315
+ continue;
316
+ out.add(`${m[3]} 需要 ${m[1]}@${m[2]}`);
317
+ }
318
+ return [...out];
319
+ }
88
320
  /**
89
321
  * 包管理核心:install/uninstall 的纯依赖实现(不碰 ctx/网关,可单测)。
90
322
  * 所有文件操作走 process 网关(子进程:npm/tar/mkdir/rm/test),目标是真实
@@ -93,84 +325,424 @@ function createService(ctx, config) {
93
325
  */
94
326
  export function createPackageManager(deps) {
95
327
  const { proc, log } = deps;
96
- // 目录存在性:`test -d <abs>`(不存在/非目录 → exit 1 → 抛 → false)。绝对路径,cwd 无关。
97
- async function dirExists(absPath) {
328
+ /**
329
+ * 当前占用的操作描述;`null` = 空闲。
330
+ *
331
+ * install / uninstall / update 三者都会改**同一个**根 `package.json`,而 npm 的写法是
332
+ * 「读整份 → 改内存 → 整份写回」。并行时是经典的丢失更新:A 与 B 各自读到同一份旧内容,
333
+ * 后写者整份覆盖,先写者新增的那条依赖消失——包的文件却已经落进 node_modules。而
334
+ * `createNodeModulesPluginLoader` **只遍历根依赖的键、从不扫 node_modules 目录**,
335
+ * 于是那个包永远不会被加载:装成功了,重启后插件不见了,用户无从判断。
336
+ *
337
+ * 锁必须在**服务层**:本服务经 `ctx.provide` 公开,任何插件都能绕过 HTTP 路由直接调,
338
+ * 加在路由或前端都不算数。
339
+ */
340
+ let inflight = null;
341
+ /**
342
+ * 进程即将重启(update 成功后置位),此后**永不释放**锁。
343
+ *
344
+ * 重启不是立刻发生的(延迟 500ms + stop + spawn),这段窗口里若放新操作进来,
345
+ * 它会被 `process.exit` 腰斩在半路,留下半装状态。
346
+ */
347
+ let terminal = false;
348
+ /**
349
+ * 串行闸:占用中直接**拒绝**而非排队。
350
+ *
351
+ * 拒绝而非排队的决定性理由:update 成功后进程立即重启,排在它后面的操作必然被腰斩。
352
+ * 排队在这里是错的语义——「一次一个」才是这三个操作的真实约束,只是此前没人强制它。
353
+ */
354
+ async function exclusive(what, run) {
355
+ if (inflight) {
356
+ return { ok: false, message: `有包管理操作正在进行中(${inflight}),请稍候重试` };
357
+ }
358
+ inflight = what;
98
359
  try {
99
- await proc.execFile('test', ['-d', absPath], { cwd: process.cwd(), timeout: 10_000 });
360
+ return await run();
361
+ }
362
+ finally {
363
+ if (!terminal)
364
+ inflight = null;
365
+ }
366
+ }
367
+ /** 路径存在性:`test -d|-f <abs>`(不存在 → exit 1 → 抛 → false)。绝对路径,cwd 无关。 */
368
+ async function pathExists(absPath, kind) {
369
+ try {
370
+ await proc.execFile('test', [`-${kind}`, absPath], { cwd: process.cwd(), timeout: 10_000 });
100
371
  return true;
101
372
  }
102
373
  catch {
103
374
  return false;
104
375
  }
105
376
  }
106
- return {
107
- async install(npmPkg) {
108
- const packagesDir = deps.packagesDir();
109
- // 分离包名与可选版本:@scope/foo@1.2.3 → dirName=foo(去 scope、去版本)
110
- const dirName = npmPkg.replace(/^@[^/]+\//, '').replace(/@[^@]+$/, '');
111
- const targetDir = `${packagesDir}/${dirName}`;
112
- if (await dirExists(targetDir)) {
113
- return { ok: false, message: `目录 ${dirName} 已存在` };
377
+ /** 读 JSON;不存在或解析失败一律 undefined(调用方按「读不到」处理,不区分原因)。 */
378
+ async function readJson(absPath) {
379
+ const text = await deps.readText(absPath);
380
+ if (text === undefined)
381
+ return undefined;
382
+ try {
383
+ return JSON.parse(text);
384
+ }
385
+ catch {
386
+ return undefined;
387
+ }
388
+ }
389
+ /**
390
+ * 装完的统一判定:rescan 出新插件即成功;没出新插件时按目标是否**声明自己是插件**分流。
391
+ * 「声明了插件却没被发现」正是那条静默假成功——必须报失败,否则用户看到 ok 却什么也没装上。
392
+ */
393
+ async function settleInstall(npmPkg, installedPkgJsonPath, where) {
394
+ const target = stripVersion(npmPkg);
395
+ // rescan 只当副作用用(让加载器发现新包),**不看返回值**——判据是目标自身是否就位。
396
+ await deps.rescanPlugins();
397
+ if (deps.isPluginRegistered(target))
398
+ return { ok: true, message: `已安装并加载: ${target}` };
399
+ const meta = await readJson(installedPkgJsonPath);
400
+ if (declaresPlugin(meta)) {
401
+ return { ok: false, message: `已装到 ${where},但它声明为插件却未被加载——请检查其 keywords 与入口导出` };
402
+ }
403
+ return { ok: true, message: `已安装 ${target}(非插件包,不进入插件列表)` };
404
+ }
405
+ /**
406
+ * 安装:写根 `dependencies` —— 加载器**唯一**的发现来源。
407
+ *
408
+ * 不再按「项目形态」分叉。旧实现在检测到 `pnpm-workspace.yaml` 时会把 npm 包解包成
409
+ * `packages/<dir>` 源码,而那个文件与真正生效的加载器**没有因果关系**——加载器是入口
410
+ * 文件传给 `startAalis` 的(默认读根依赖,本仓显式传 fs 加载器扫 packages/)。于是一个
411
+ * 用 pnpm 工作区但走默认 `startAalis()` 的用户,包会被装进加载器永远不看的地方,静默失败。
412
+ *
413
+ * 现在只有一条路径。真正的 monorepo 由下面的 `hasWorkspaceProtocol` 守卫拦住并说清
414
+ * 该用什么工具——那才是开发者场景,不该用市场往自己仓里塞源码。
415
+ */
416
+ async function installTo(npmPkg) {
417
+ const root = deps.projectRoot();
418
+ const rootPkg = await readJson(`${root}/package.json`);
419
+ if (hasWorkspaceProtocol(rootPkg)) {
420
+ return {
421
+ ok: false,
422
+ message: '根依赖含 workspace: 协议,拒绝在此运行 npm install(会写出 package-lock.json 并搅坏 pnpm 工作区)',
423
+ };
424
+ }
425
+ log.info(`正在安装: ${npmPkg} → 根依赖 + node_modules`);
426
+ // **刻意不加 `--ignore-scripts`**:依赖树的 preinstall/install/postinstall 会照常执行。
427
+ // 三条理由:脚手架自身就是裸 `npm install`(其生成的 README 也教用户裸装),加了会让
428
+ // 「同一个包、同一个用户、两条途径」行为分叉;会打穿 plugin-memory-sqlite
429
+ // (better-sqlite3,脚手架默认勾选)与 plugin-tool-browser(puppeteer);而真正的增量
430
+ // 风险只有传递依赖的 install 脚本这一片——入口是 owner 级、包名由用户自己点选、包本体
431
+ // 反正会被动态 import 执行(插件与内核同进程同权限,见 docs/concepts/security-model.md §1)。
432
+ await execProc(proc, 'npm', ['install', npmPkg, '--no-audit', '--no-fund'], root, INSTALL_TIMEOUT_MS);
433
+ const bare = stripVersion(npmPkg);
434
+ return settleInstall(npmPkg, `${root}/node_modules/${bare}/package.json`, 'node_modules');
435
+ }
436
+ /**
437
+ * 在**项目副本**里预检整组目标版本;返回冲突要点,`undefined` = 通过。
438
+ *
439
+ * 为什么必须隔离到副本,而不是在 live tree 上跑 `--dry-run`(实测 npm 10.9.2):
440
+ * 1. `--dry-run` **有副作用**——它不碰 `package.json` 与 `package-lock.json`,却会把
441
+ * `node_modules/.package-lock.json`(npm 的隐藏 lockfile)重写成「目标版本已装」。
442
+ * 紧接着的真装读到它就判定树已就绪,直接 `up to date` 什么都不做:于是声明成了新版、
443
+ * node_modules 里仍是旧代码,而旧代码起得来 → 重启成功 → 回滚永不触发 → 整次更新
444
+ * 空转却报成功。副本里跑则 live tree 分毫未动,无需事后补救。
445
+ * 2. 用户 `.npmrc` 里的 `legacy-peer-deps=true`(React 生态常见 workaround)会让 npm
446
+ * **完全不报** peer 告警,唯一的护栏静默失效。副本在项目树之外,天然不继承项目级
447
+ * 配置;再用 `npm_config_legacy_peer_deps=false` 压掉用户级与全局配置(已实测:
448
+ * 即便副本里放了 `legacy-peer-deps=true` 的 `.npmrc`,该环境变量也能翻回来)。
449
+ *
450
+ * **不要把项目 `.npmrc` cp 进副本**(试过,已回退)。动机是对的——不带它,私有源用户的
451
+ * 预检会跑去公共源解析(包只在私有源上就 404/401 → 更新被永久挡住且报错文不对题)。但
452
+ * 实做后被 `test/integration/install-chain.test.ts` 的真实 npm 用例推翻:带上 `.npmrc` 后
453
+ * 上面第 2 条护栏失效,而隔离复现里 env 明明压得过项目级 `.npmrc`,**机制未查清**。
454
+ * 要重做的话先解释清楚这个矛盾,别直接再 cp 一次。
455
+ *
456
+ * 判据只能是解析告警文本:`--dry-run --json` 实测只给 `{added, removed, changed,
457
+ * audited, funding}`,无任何冲突信息;退出码在本场景恒为 0(npm 把命令行显式 spec
458
+ * 视为用户意图,只 warn 就放行),`--strict-peer-deps` 在副本里同样不改变这一点,
459
+ * 故不再传它——留着只会让人误以为有额外保障。
460
+ */
461
+ async function preflightInSandbox(specs, root) {
462
+ const tmp = await proc.makeTempDir('preflight');
463
+ try {
464
+ // 直接 cp 现有文件,不重新写内容——与本插件其余文件操作同一路子(走 proc 网关的
465
+ // POSIX 命令),也省掉一个只为此处存在的写原语。
466
+ await execProc(proc, 'cp', [`${root}/package.json`, `${tmp.path}/package.json`], tmp.path);
467
+ const lock = `${root}/package-lock.json`;
468
+ if (await pathExists(lock, 'f')) {
469
+ await execProc(proc, 'cp', [lock, `${tmp.path}/package-lock.json`], tmp.path);
114
470
  }
115
- log.info(`正在安装插件: ${npmPkg} → packages/${dirName}`);
116
- let tgzPath;
471
+ const { stdout, stderr } = await execProcBoth(proc, 'npm', ['install', ...specs, '--dry-run', '--no-audit', '--no-fund'], tmp.path, INSTALL_TIMEOUT_MS, { npm_config_legacy_peer_deps: 'false' });
472
+ const unmet = findUnmetPeers(`${stderr}\n${stdout}`, specs.map(stripVersion));
473
+ return unmet.length > 0 ? unmet : undefined;
474
+ }
475
+ catch (err) {
476
+ // 非零退出 = npm 自己判定无解(ERESOLVE 等)。原样上报,不猜。
477
+ const raw = err instanceof Error ? err.message : String(err);
478
+ const conflicts = extractPeerConflicts(raw);
479
+ return conflicts.length > 0 ? conflicts : [raw.slice(0, 2000)];
480
+ }
481
+ finally {
482
+ await tmp.cleanup().catch(() => { });
483
+ }
484
+ }
485
+ /**
486
+ * 批量更新。形状是「一次算全量 → 整组预检 → 一次 install → 一次重启」,
487
+ * 重启次数恒为 1,与改了多少个包无关(语义见 {@link PackageManagerService.update})。
488
+ */
489
+ async function updateAll(targets) {
490
+ const { specs, error } = buildUpdateSpecs(targets);
491
+ if (!specs)
492
+ return { ok: false, message: error ?? '参数非法' };
493
+ if (!deps.restartApp)
494
+ return { ok: false, message: '当前宿主未提供重启能力,无法完成更新' };
495
+ const root = deps.projectRoot();
496
+ // 没有「项目形态」这一层判断了:能不能更新是**每个包自己的来源**说了算(下面的
497
+ // isRegistryDep 闸),不是整个项目的属性。旧写法拿 `pnpm-workspace.yaml` 是否存在
498
+ // 当整体开关,既挡掉了工作区项目里合法的 npm 依赖,也与真正生效的加载器无因果关系。
499
+ const rootPkgPath = `${root}/package.json`;
500
+ const rootPkgText = await deps.readText(rootPkgPath);
501
+ if (rootPkgText === undefined)
502
+ return { ok: false, message: `读不到根 package.json: ${rootPkgPath}` };
503
+ const rootPkg = await readJson(rootPkgPath);
504
+ if (hasWorkspaceProtocol(rootPkg)) {
505
+ return { ok: false, message: '根依赖含 workspace: 协议,拒绝在此运行 npm install' };
506
+ }
507
+ // 只允许更新「根依赖里以 semver 范围声明」的包。闸放在服务层而非 HTTP 路由——
508
+ // 本服务经 ctx.provide 公开,任何插件都能绕过路由直接调用(理由见 isRegistryDep)。
509
+ const rootDependencies = (rootPkg?.dependencies ?? {});
510
+ const notUpdatable = targets.filter(t => !isRegistryDep(rootDependencies[t.name]));
511
+ if (notUpdatable.length > 0) {
512
+ return {
513
+ ok: false,
514
+ message: '以下包不在根依赖中(由其它插件带入)或不是 registry 来源,单独更新只会装出第二份副本;' +
515
+ `请改为更新带入它们的插件:${notUpdatable.map(t => t.name).join('、')}`,
516
+ };
517
+ }
518
+ // ── 读取每个目标的当前实装版本 ──
519
+ // 两处都要用:(a) 降级守卫;(b) 回滚凭据钉精确旧版。两者都不能靠根 package.json 的
520
+ // 声明——那是**范围**,回滚时按范围重解析只会又解到刚崩掉的新版。
521
+ const installedVersions = new Map();
522
+ for (const t of targets) {
523
+ const text = await deps.readText(`${root}/node_modules/${t.name}/package.json`);
524
+ if (text === undefined)
525
+ continue;
117
526
  try {
118
- await execProc(proc, 'mkdir', ['-p', packagesDir], process.cwd()); // 确保 packages/ 存在
119
- // npm pack --json 精确返回产物 {filename, name},避免 includes 误匹配
120
- // (装 foo 时命中 foo-bar-*.tgz);name 是精确包名,供 pnpm --filter 用。
121
- const packOut = await execProc(proc, 'npm', ['pack', npmPkg, '--pack-destination', packagesDir, '--json'], process.cwd());
122
- const packInfo = parsePackInfo(packOut);
123
- if (!packInfo)
124
- return { ok: false, message: '下载包失败: 未能解析 npm pack 产物' };
125
- tgzPath = `${packagesDir}/${packInfo.filename}`;
126
- await execProc(proc, 'mkdir', ['-p', targetDir], process.cwd());
127
- await execProc(proc, 'tar', ['xzf', tgzPath, '-C', targetDir, '--strip-components=1'], process.cwd());
128
- await execProc(proc, 'rm', ['-f', tgzPath], process.cwd()); // 清理 tgz
129
- tgzPath = undefined; // 已删,回滚时不再尝试
130
- // --filter 用精确包名(npm pack 回报的 name,无版本后缀)链接新 workspace 包
131
- await execProc(proc, 'pnpm', ['install', '--filter', packInfo.name], process.cwd());
132
- const newPlugins = await deps.rescanPlugins();
133
- return newPlugins.length > 0
134
- ? { ok: true, message: `已安装并加载: ${newPlugins.join(', ')}` }
135
- : { ok: true, message: `已安装到 packages/${dirName},但未发现新插件` };
136
- }
137
- catch (err) {
138
- const message = err instanceof Error ? err.message : String(err);
139
- log.error(`安装插件 "${npmPkg}" 失败: ${message}`);
140
- // 回滚:清理半成品 targetDir 与残留 tgz,避免占位导致下次"目录已存在"
141
- await execProc(proc, 'rm', ['-rf', targetDir], process.cwd()).catch(() => { });
142
- if (tgzPath)
143
- await execProc(proc, 'rm', ['-f', tgzPath], process.cwd()).catch(() => { });
144
- return { ok: false, message };
527
+ const v = JSON.parse(text).version;
528
+ if (typeof v === 'string')
529
+ installedVersions.set(t.name, v);
145
530
  }
146
- },
147
- async uninstall(pluginName) {
148
- const dirName = pluginName.replace(/^@[^/]+\//, '');
149
- // 安全闸:dirName 必须是合法 npm 包段名——杜绝路径穿越(如 `../../x`)导致
150
- // `rm -rf packages/../../x` 删到 packages 外的任意目录。
151
- if (!/^[a-z0-9][a-z0-9._-]*$/i.test(dirName)) {
152
- return { ok: false, message: `非法插件名(疑似路径穿越): ${pluginName}` };
531
+ catch {
532
+ /* 坏 JSON:当作读不到,由下面的守卫拒掉 */
153
533
  }
154
- const packagesDir = deps.packagesDir();
155
- const targetDir = `${packagesDir}/${dirName}`;
156
- const existed = await dirExists(targetDir);
534
+ }
535
+ // ── 降级守卫 ──
536
+ // 闸放在服务层而非 HTTP 路由:本服务经 ctx.provide 公开,任何插件都能绕过路由直接调用。
537
+ // 拒绝而非放行的理由:registry 的 dist-tags.latest 可以**低于**本地已装版本(发布事故后
538
+ // `npm dist-tag add pkg@旧版 latest` 回滚,或用户曾装过预发布版),此时「更新」会静默降级;
539
+ // 读不到已装版本同样拒——无从判断方向就不动,用户可显式卸载重装。
540
+ const notUpgrade = targets.filter(t => !isUpgrade(installedVersions.get(t.name), t.version));
541
+ if (notUpgrade.length > 0) {
542
+ return {
543
+ ok: false,
544
+ message: '以下目标版本不高于本地已装版本(或本地版本号读不到),更新会变成降级,已拒绝:' +
545
+ notUpgrade
546
+ .map(t => `${t.name}(本地 ${installedVersions.get(t.name) ?? '未知'} → 目标 ${t.version})`)
547
+ .join('、'),
548
+ };
549
+ }
550
+ // ── 预检:整组一次,不逐个 ──
551
+ // 逐个预检发现不了「A@new 要 core>=0.10、B@new 要 core<0.10」这类只在合并时冲突的组合。
552
+ log.info(`更新预检: ${specs.join(' ')}`);
553
+ const reject = (conflicts) => ({
554
+ ok: false,
555
+ message: '依赖预检未通过,未改动任何文件。若是 peer 版本要求,请把被依赖方一并勾选后重试。',
556
+ conflicts,
557
+ });
558
+ const verdict = await preflightInSandbox(specs, root);
559
+ if (verdict)
560
+ return reject(verdict);
561
+ // ── 快照:预检过了才有必要 ──
562
+ // lockfile 与 package.json 必须一起回退,否则还原后的树是「声明旧版、锁定新版」。
563
+ const restore = [
564
+ { path: rootPkgPath, content: rootPkgText },
565
+ ];
566
+ const lockPath = `${root}/package-lock.json`;
567
+ const lockText = await deps.readText(lockPath);
568
+ if (lockText !== undefined) {
569
+ restore.push({ path: lockPath, content: lockText });
570
+ }
571
+ else {
572
+ // 原本没有 lockfile(pnpm/yarn 装的工程),而 npm install 会**新建**一个锁到新版。
573
+ // 回滚只能写回文件、不能删除新增文件,留着它会让 postRestore 判定新版仍满足还原后的
574
+ // 范围 → `up to date` → node_modules 纹丝不动。用空内容占位不行(会得到坏 JSON),
575
+ // 故记为「回滚时删掉它」,把工程还原成它原本无锁的样子。
576
+ restore.push({ path: lockPath, content: '', deleteIfEmpty: true });
577
+ }
578
+ // 装之前记下整棵树的实装版本。回滚不能只钉被点名的包:npm 会顺带把**传递依赖**升上去
579
+ // (新版把某个依赖的下界抬高了),而回滚时 `npm install <被点名的包>@<旧版>` 只会
580
+ // `changed 1 package` —— 被顺带升上去的那个仍满足旧版声明的范围,npm 不动它,于是它
581
+ // 永久停在新版。有 lockfile 时不会(还原锁即还原全树),这是**无锁形态专有**的残留。
582
+ //
583
+ // 这条正落在本仓自己的依赖形状上:包间依赖写 `>=<当前版本> <1.0.0`,api 每 bump 一个
584
+ // minor,下一版插件的下界就抬一格 —— plugin@old 要 `>=0.9.0`、plugin@new 要 `>=0.10.0`,
585
+ // 更新把 api 拉到 0.10.0,回滚把插件退回 old,而 0.10.0 仍满足 `>=0.9.0`。若崩溃本来
586
+ // 就是这次 api 升级引起的,回滚等于没做,进程 crash loop 而用户被告知已回滚。
587
+ const treeBefore = await readInstalledTree(deps, root);
588
+ // ── 提交 ──
589
+ // 预检在副本里做,live tree 此刻**未被任何 dry-run 触碰**,可以直接装。
590
+ try {
591
+ await execProc(proc, 'npm', ['install', ...specs, '--no-audit', '--no-fund'], root, INSTALL_TIMEOUT_MS);
592
+ }
593
+ catch (err) {
594
+ const message = err instanceof Error ? err.message : String(err);
595
+ log.error(`更新安装失败: ${message}`);
596
+ return { ok: false, message: `安装失败(工程未重启,可重试): ${message}` };
597
+ }
598
+ // ── 重启接管 ──
599
+ // 回滚凭据交给重启策略:只有它能观察到「新实例 ready 前夭折」。插件级失败不在此列
600
+ // ——插件起不来会停在 error 态且 WebUI 可见,自动回滚反而会掩盖问题。
601
+ log.info(`更新完成,正在重启接管: ${specs.join(' ')}`);
602
+ // 置位后锁不再释放:重启是延迟发生的,这段窗口放新操作进来会被 process.exit 腰斩。
603
+ terminal = true;
604
+ // postRestore 钉**精确旧版**,不用裸 `npm install`。
605
+ // 裸 install 只能按还原后的 package.json 重解析,而声明通常是 caret 范围(`^1.0.0`),
606
+ // 刚崩掉的新版(1.1.0)本身就满足它——于是 npm 又把它装回来,node_modules 分毫未变,
607
+ // 而重启策略照样打印「已回滚并重新启动旧版本」。实测:有锁时正常,无锁时静默失效。
608
+ // `--no-save` 保证 package.json 维持 restore 写回的原样,不被 npm 改写成 `^旧版`。
609
+ // 降级守卫已保证每个 target 都有已装版本(读不到的在那里就被拒了),此处的 undefined
610
+ // 过滤只是让类型收窄,不承担逻辑。
611
+ const pinned = targets
612
+ .map(t => {
613
+ const v = installedVersions.get(t.name);
614
+ return v === undefined ? undefined : `${t.name}@${v}`;
615
+ })
616
+ .filter((s) => s !== undefined);
617
+ // 再把「被这次安装顺带改了版本」的包一并钉回旧版(理由见上面 treeBefore 处的注释)。
618
+ // 只回退**本来就在**的包:新增的包钉不回去(它更新前不存在),留给 npm 的 extraneous。
619
+ const named = new Set(targets.map(t => t.name));
620
+ const treeAfter = await readInstalledTree(deps, root);
621
+ for (const [name, before] of treeBefore) {
622
+ if (named.has(name))
623
+ continue;
624
+ const after = treeAfter.get(name);
625
+ if (after !== undefined && after !== before)
626
+ pinned.push(`${name}@${before}`);
627
+ }
628
+ deps.restartApp({
629
+ reason: `marketplace-update:${specs.join(',')}`,
630
+ restore,
631
+ postRestore: { cmd: 'npm', args: ['install', ...pinned, '--no-save', '--no-audit', '--no-fund'], cwd: root },
632
+ });
633
+ return { ok: true, restarting: true, message: `已更新 ${specs.join('、')},正在重启…` };
634
+ }
635
+ return {
636
+ update: t => exclusive(`更新 ${t.map(x => x.name).join('、')}`, () => updateAll(t)),
637
+ install: npmPkg => exclusive(`安装 ${npmPkg}`, async () => {
638
+ const bad = validatePackageSpec(npmPkg);
639
+ if (bad)
640
+ return { ok: false, message: bad };
157
641
  try {
158
- if (existed)
159
- await execProc(proc, 'rm', ['-rf', targetDir], process.cwd()); // 删目录,不再回来
160
- await deps.unloadPlugin(pluginName); // 从运行时注册表彻底移除(dispose + delete),幂等
161
- deps.cleanupConfig?.(pluginName); // 清残留配置
162
- log.info(existed ? `已删除插件目录: packages/${dirName}` : `插件 ${pluginName} 目录原不存在,已从运行时移除`);
163
- return {
164
- ok: true,
165
- message: existed ? `插件 ${pluginName} 已卸载并删除` : `插件 ${pluginName} 已从运行时移除(目录原不存在)`,
166
- };
642
+ return await installTo(npmPkg);
167
643
  }
168
644
  catch (err) {
169
645
  const message = err instanceof Error ? err.message : String(err);
646
+ log.error(`安装 "${npmPkg}" 失败: ${message}`);
170
647
  return { ok: false, message };
171
648
  }
172
- },
649
+ }),
650
+ uninstall: pluginName => exclusive(`卸载 ${pluginName}`, () => uninstallOne(pluginName)),
173
651
  };
652
+ /**
653
+ * 卸载:两道服务层闸 + npm uninstall。
654
+ *
655
+ * 闸放服务层而非 HTTP 路由——本服务经 `ctx.provide` 公开,任何插件都能绕过路由直接调
656
+ * (与 `buildUpdateSpecs`、`isRegistryDep` 同一理由)。前端早就有正确策略
657
+ * (只给 plugin/interface 卡片渲染卸载按钮),但那只是客户端校验,服务端不设防。
658
+ */
659
+ async function uninstallOne(pluginName) {
660
+ const bad = validatePackageSpec(pluginName);
661
+ if (bad)
662
+ return { ok: false, message: bad };
663
+ const root = deps.projectRoot();
664
+ const meta = await readJson(`${root}/node_modules/${pluginName}/package.json`);
665
+ if (!meta) {
666
+ return { ok: false, message: `读不到 ${pluginName} 的 package.json,无法确认它是什么,已拒绝卸载` };
667
+ }
668
+ // ── 闸一:类型 ──
669
+ // 市场管的是**插件**。core / runtime / api / schema / util 不是插件,不在本工具职权内。
670
+ // 这不是「权限不够」——owner 权限很高,走 `npm uninstall` 随时能删。这道闸拦的是
671
+ // 「**这个操作会把你用来撤销它的那条通道一起销毁**」:卸掉插件,实例照常跑、市场里点
672
+ // 一下就能装回来(带内可恢复);卸掉内核或宿主,实例起不来、市场随之消失,只能开
673
+ // shell 修(带外)。更新不在此列——它保留实例且失败会自动回滚。
674
+ const kw = Array.isArray(meta.keywords) ? meta.keywords : [];
675
+ // 走 declaresPlugin 而非再内联一次 `kw.includes('aalis-plugin')`:同一文件里维护两份
676
+ // 同义判据,正是本仓已出事四次的形态(依赖来源判据、定级数学、包名正则、关键词分类)。
677
+ const isPlugin = declaresPlugin(meta);
678
+ const isInterface = kw.includes('aalis-interface');
679
+ if (!isPlugin && !isInterface) {
680
+ const kind = kw.includes('aalis-core')
681
+ ? '内核'
682
+ : kw.includes('aalis-runtime')
683
+ ? '宿主'
684
+ : kw.includes('aalis-api')
685
+ ? '服务契约'
686
+ : kw.includes('aalis-schema')
687
+ ? '数据规范'
688
+ : kw.includes('aalis-util')
689
+ ? '工具库'
690
+ : '非插件包';
691
+ return {
692
+ ok: false,
693
+ message: `${pluginName} 是${kind},不是可装卸的插件,市场不负责它的卸载。` +
694
+ (kw.includes('aalis-core') || kw.includes('aalis-runtime')
695
+ ? '删掉它实例将无法启动、市场也随之消失,只能在终端里恢复;确需如此请手动执行 npm uninstall。'
696
+ : '它随依赖它的插件被 npm 自动剪枝;确需单独删除请手动执行 npm uninstall。'),
697
+ };
698
+ }
699
+ // ── 闸一之二:承载「撤销通道」的服务提供者不能被卸掉 ──
700
+ //
701
+ // 与内核/宿主同一条判据的另一半:**这个操作会把你用来撤销它的通道一起销毁**。
702
+ // 市场页要能用,靠三样东西同时在:`webui-client`(页面本身)、`webui-server`(托管它
703
+ // 并提供 HTTP 面)、`package-manager`(装卸能力本身)。少任何一样,用户就只能开 shell。
704
+ //
705
+ // 判据是**「谁在提供我此刻依赖的服务」而不是包名**——第三方换个实现照样受保护,
706
+ // 而 `getAllServices` 的首个条目即当前生效者(偏好 > 优先级 > 注册顺序),
707
+ // webui-server 与 package-manager 都是用包名做 ctx.id 的插件。
708
+ //
709
+ // 只拦「当前生效的那个」:想换实现的正常路径是「装新的 → 切过去 → 再卸旧的」,
710
+ // 那时它已不是提供者,本闸自然放行。
711
+ const lifeline = deps.recoveryChannelProviders?.() ?? [];
712
+ if (lifeline.includes(pluginName)) {
713
+ return {
714
+ ok: false,
715
+ message: `${pluginName} 正在承载市场/管理界面本身,卸掉它这个页面会立刻不可用,` +
716
+ '只能在终端里恢复。若确要更换实现,请先装上替代者并在「服务」页切换过去,再回来卸载它。',
717
+ };
718
+ }
719
+ // ── 闸二:来源 ──
720
+ // 只有根依赖里以 semver 范围声明的才归市场管。workspace: 是用户自己的源码(删了不可逆,
721
+ // 且多半在 git 里);file:/link: 指向本地目录;git/URL 是外部源;不在根依赖里的是传递依赖。
722
+ const rootPkg = await readJson(`${root}/package.json`);
723
+ const request = (rootPkg?.dependencies ?? {})[pluginName];
724
+ if (!isRegistryDep(request)) {
725
+ const origin = classifyDepSpec(request);
726
+ const why = {
727
+ workspace: '它是工作区里的本地源码包,删除请走 git',
728
+ link: '它由 file:/link: 指向本地目录,删除请改那份源码与依赖声明',
729
+ git: '它由 git/URL/user-repo 简写安装,删除请改依赖声明',
730
+ alias: '它由 npm: 别名指向另一个包,删除请改依赖声明',
731
+ transitive: '它不在根依赖里(由其它插件带入),会随带入它的插件被 npm 自动剪枝',
732
+ };
733
+ return { ok: false, message: `${pluginName} 不是经市场安装的:${why[origin] ?? '来源不明'}。` };
734
+ }
735
+ try {
736
+ await execProc(proc, 'npm', ['uninstall', pluginName, '--no-audit', '--no-fund'], root, INSTALL_TIMEOUT_MS);
737
+ await deps.unloadPlugin(pluginName); // 从运行时注册表彻底移除(dispose + delete),幂等
738
+ deps.cleanupConfig?.(pluginName); // 清残留配置
739
+ log.info(`${pluginName}: 已从根依赖与 node_modules 移除`);
740
+ return { ok: true, message: `插件 ${pluginName} 已卸载(已从根依赖与 node_modules 移除)` };
741
+ }
742
+ catch (err) {
743
+ return { ok: false, message: err instanceof Error ? err.message : String(err) };
744
+ }
745
+ }
174
746
  }
175
747
  export function apply(ctx, config) {
176
748
  ctx.provide('package-manager', createService(ctx, config), {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAwC,MAAM,oBAAoB,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjF,oBAAoB;AAEpB,MAAM,CAAC,MAAM,IAAI,GAAG,+BAA+B,CAAC;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAClC,MAAM,CAAC,MAAM,SAAS,GAAG,QAAQ,CAAC;AAClC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE,CAAC,SAAS,CAAC;CACtB,CAAC;AAkDF,iBAAiB;AAEjB,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACjC;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC,KAAK,UAAU,QAAQ,CACrB,IAAoB,EACpB,GAAW,EACX,IAAc,EACd,GAAW,EACX,UAAkB,gBAAgB;IAElC,OAAO,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AACpE,CAAC;AAED,qEAAqE;AACrE,KAAK,UAAU,YAAY,CACzB,IAAoB,EACpB,GAAW,EACX,IAAc,EACd,GAAW,EACX,UAAkB,gBAAgB,EAClC,QAAiC;IAEjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAe,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE;YACxD,GAAG;YACH,OAAO;YACP,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;IAChE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,GAAsC,CAAC;QAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA4C;IAC/E,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,CAAC,cAAc,EAAE,iBAAiB,EAAE,sBAAsB,CAAC,EAAE,CAAC;QAChF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QAClD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC,EAAE,CAAC;YAChE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC;gBAAE,OAAO,IAAI,CAAC;QACvE,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAA4C;IACzE,MAAM,EAAE,GAAG,OAAO,EAAE,QAAQ,CAAC;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,4EAA4E,CAAC;AAEjG;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa;IAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC;IACvE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IACpE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,GAAY,EAAE,MAA+B;IAClE,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAEvC,SAAS,MAAM;QACb,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAa,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACjD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,0CAA0C;IAC1C,SAAS,iBAAiB,CAAC,GAAkB,EAAE,QAAgB;QAC7D,MAAM,QAAQ,GAAI,MAAkC,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC;QACrG,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,SAAS,WAAW;QAClB,OAAO,iBAAiB,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,oBAAoB,CAAC;QAC1B,IAAI;QACJ,GAAG;QACH,2EAA2E;QAC3E,+CAA+C;QAC/C,4BAA4B;QAC5B,wDAAwD;QACxD,WAAW;QACX,mEAAmE;QACnE,6EAA6E;QAC7E,2DAA2D;QAC3D,QAAQ,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;YACxB,IAAI,CAAC;gBACH,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;YACxE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QACD,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,aAAa,EAAE;QAC7C,qEAAqE;QACrE,kDAAkD;QAClD,iBAAiB;QACjB,kBAAkB,EAAE,IAAI,CAAC,EAAE,CACzB,GAAG;aACA,UAAU,CAA2C,SAAS,CAAC;YAChE,EAAE,SAAS,EAAE;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK;QACxC,qDAAqD;QACrD,6CAA6C;QAC7C,EAAE;QACF,qEAAqE;QACrE,0CAA0C;QAC1C,6DAA6D;QAC7D,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;QACtD,gDAAgD;QAChD,sCAAsC;QACtC,8CAA8C;QAC9C,4DAA4D;QAC5D,mDAAmD;QACnD,qCAAqC;QACrC,sEAAsE;QACtE,2EAA2E;QAC3E,wDAAwD;QACxD,4DAA4D;QAC5D,iCAAiC;QACjC,wBAAwB,EAAE,GAAG,EAAE,CAAC;YAC9B,GAAG,IAAI,GAAG,CACR,CAAC,cAAc,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAC9D,MAAM,EAAE,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;gBAC/C,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxB,CAAC,CAAC,CACH;SACF;QAED,YAAY,EAAE,KAAK,EAAC,IAAI,EAAC,EAAE;YACzB,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAuC,SAAS,CAAC,CAAC;YAC3E,IAAI,EAAE;gBAAE,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,uDAAuD;QACvD,gCAAgC;QAChC,aAAa,EAAE,IAAI,CAAC,EAAE;YACpB,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACpC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAuCD,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,qDAAqD,CAAC;AAC/E,mCAAmC;AACnC,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,iBAAiB,CAC9B,IAA0C,EAC1C,IAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,kCAAkC,CAAC,CAAC;IAC5E,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyD,CAAC;QACxF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;YAClE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC;gBAAE,SAAS;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YAChD,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAAE,SAAS,CAAC,eAAe;YAC9D,IAAI,OAAO,KAAK,EAAE,OAAO,KAAK,QAAQ;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,gBAAgB,GAAG,GAAG,GAAG,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgC;IAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACjF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACpF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,UAAU,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAC7F,wCAAwC;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,cAAc,IAAI,EAAE,EAAE,CAAC;QAC3D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;QAClC,yDAAyD;QACzD,mEAAmE;QACnE,+BAA+B;QAC/B,KAAK,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,uBAAuB;QAC7D,IAAI,KAAK,GAAG,gBAAgB,EAAE,CAAC;YAC7B,OAAO,EAAE,KAAK,EAAE,iBAAiB,gBAAgB,WAAW,EAAE,CAAC;QACjE,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,2DAA2D,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,WAA8B;IAC3E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACnC,wCAAwC;IACxC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,CAAC,GAAG,yCAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAC/B,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAwB;IAC3D,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAE3B;;;;;;;;;;;OAWG;IACH,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC;;;;;OAKG;IACH,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB;;;;;OAKG;IACH,KAAK,UAAU,SAAS,CACtB,IAAY,EACZ,GAAqB;QAErB,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,QAAQ,SAAS,EAAO,CAAC;QACvE,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,MAAM,GAAG,EAAE,CAAC;QACrB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ;gBAAE,QAAQ,GAAG,IAAI,CAAC;QACjC,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,IAAe;QACxD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5F,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,KAAK,UAAU,QAAQ,CAAC,OAAe;QACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,UAAU,aAAa,CAC1B,MAAc,EACd,oBAA4B,EAC5B,KAAa;QAEb,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACpC,kDAAkD;QAClD,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,MAAM,EAAE,EAAE,CAAC;QACvF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAClD,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,oCAAoC,EAAE,CAAC;QAClF,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,MAAM,gBAAgB,EAAE,CAAC;IAC9D,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,UAAU,SAAS,CAAC,MAAc;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;QACvD,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,2EAA2E;aACrF,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,SAAS,MAAM,uBAAuB,CAAC,CAAC;QACjD,yEAAyE;QACzE,uDAAuD;QACvD,iDAAiD;QACjD,kEAAkE;QAClE,qDAAqD;QACrD,sEAAsE;QACtE,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACtG,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,aAAa,CAAC,MAAM,EAAE,GAAG,IAAI,iBAAiB,IAAI,eAAe,EAAE,cAAc,CAAC,CAAC;IAC5F,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,KAAK,UAAU,kBAAkB,CAAC,KAAe,EAAE,IAAY;QAC7D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,+CAA+C;YAC/C,6BAA6B;YAC7B,MAAM,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,eAAe,EAAE,GAAG,GAAG,CAAC,IAAI,eAAe,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3F,MAAM,IAAI,GAAG,GAAG,IAAI,oBAAoB,CAAC;YACzC,IAAI,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBAChC,MAAM,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,oBAAoB,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAC3C,IAAI,EACJ,KAAK,EACL,CAAC,SAAS,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,EAC7D,GAAG,CAAC,IAAI,EACR,kBAAkB,EAClB,EAAE,2BAA2B,EAAE,OAAO,EAAE,CACzC,CAAC;YACF,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;YAC9E,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,yCAAyC;YACzC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC;gBAAS,CAAC;YACT,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,UAAU,SAAS,CAAC,OAAuB;QAC9C,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;QAE1E,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,2CAA2C;QAC3C,6DAA6D;QAC7D,8CAA8C;QAC9C,MAAM,WAAW,GAAG,GAAG,IAAI,eAAe,CAAC;QAC3C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,WAAW,EAAE,EAAE,CAAC;QAClG,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,uCAAuC,EAAE,CAAC;QACzE,CAAC;QACD,gDAAgD;QAChD,yDAAyD;QACzD,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAA2B,CAAC;QACjF,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,kDAAkD;oBAClD,gBAAgB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;aAC5D,CAAC;QACJ,CAAC;QAED,sBAAsB;QACtB,sDAAsD;QACtD,qCAAqC;QACrC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC;YAChF,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS;YACjC,IAAI,CAAC;gBACH,MAAM,CAAC,GAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC,OAAO,CAAC;gBAC9D,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC9D,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC;QAED,aAAa;QACb,uDAAuD;QACvD,6DAA6D;QAC7D,+DAA+D;QAC/D,mCAAmC;QACnC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7F,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,yCAAyC;oBACzC,UAAU;yBACP,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC;yBACpF,IAAI,CAAC,GAAG,CAAC;aACf,CAAC;QACJ,CAAC;QAED,oBAAoB;QACpB,8DAA8D;QAC9D,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,CAAC,SAAmB,EAAgB,EAAE,CAAC,CAAC;YACrD,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,6CAA6C;YACtD,SAAS;SACV,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,OAAO;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpC,oBAAoB;QACpB,sDAAsD;QACtD,MAAM,OAAO,GAAsE;YACjF,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE;SAC5C,CAAC;QACF,MAAM,QAAQ,GAAG,GAAG,IAAI,oBAAoB,CAAC;QAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,kDAAkD;YAClD,6DAA6D;YAC7D,8BAA8B;YAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,gDAAgD;QAChD,qDAAqD;QACrD,yDAAyD;QACzD,mDAAmD;QACnD,EAAE;QACF,wDAAwD;QACxD,wEAAwE;QACxE,6DAA6D;QAC7D,iDAAiD;QACjD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAEvD,WAAW;QACX,iDAAiD;QACjD,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAC1G,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,GAAG,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;YAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,OAAO,EAAE,EAAE,CAAC;QAC/D,CAAC;QAED,aAAa;QACb,8CAA8C;QAC9C,4CAA4C;QAC5C,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5C,kDAAkD;QAClD,QAAQ,GAAG,IAAI,CAAC;QAChB,2CAA2C;QAC3C,gEAAgE;QAChE,wDAAwD;QACxD,2CAA2C;QAC3C,iEAAiE;QACjE,qDAAqD;QACrD,mBAAmB;QACnB,MAAM,MAAM,GAAG,OAAO;aACnB,GAAG,CAAC,CAAC,CAAC,EAAE;YACP,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACxC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;QACxD,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;QAC/C,kDAAkD;QAClD,uDAAuD;QACvD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YACxC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC9B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,MAAM;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,UAAU,CAAC;YACd,MAAM,EAAE,sBAAsB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC/C,OAAO;YACP,WAAW,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE;SAC7G,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IACjF,CAAC;IAED,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAEhF,OAAO,EAAE,MAAM,CAAC,EAAE,CAChB,SAAS,CAAC,MAAM,MAAM,EAAE,EAAE,KAAK,IAAI,EAAE;YACnC,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,OAAO,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,GAAG,CAAC,KAAK,CAAC,OAAO,MAAM,SAAS,OAAO,EAAE,CAAC,CAAC;gBAC3C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;YAChC,CAAC;QACH,CAAC,CAAC;QAEJ,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;KACvF,CAAC;IAEF;;;;;;OAMG;IACH,KAAK,UAAU,YAAY,CAAC,UAAkB;QAC5C,MAAM,GAAG,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,GAAG;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAE5C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,IAAI,iBAAiB,UAAU,eAAe,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,UAAU,gCAAgC,EAAE,CAAC;QACnF,CAAC;QAED,cAAc;QACd,kEAAkE;QAClE,sDAAsD;QACtD,8CAA8C;QAC9C,0CAA0C;QAC1C,qCAAqC;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,QAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,mEAAmE;QACnE,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;gBACpC,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;oBAC5B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;wBACxB,CAAC,CAAC,MAAM;wBACR,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;4BAC3B,CAAC,CAAC,MAAM;4BACR,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;gCACzB,CAAC,CAAC,KAAK;gCACP,CAAC,CAAC,MAAM,CAAC;YACnB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,GAAG,UAAU,KAAK,IAAI,sBAAsB;oBAC5C,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;wBACxD,CAAC,CAAC,sDAAsD;wBACxD,CAAC,CAAC,+CAA+C,CAAC;aACvD,CAAC;QACJ,CAAC;QAED,iCAAiC;QACjC,EAAE;QACF,2CAA2C;QAC3C,0DAA0D;QAC1D,4DAA4D;QAC5D,EAAE;QACF,4CAA4C;QAC5C,mDAAmD;QACnD,oDAAoD;QACpD,EAAE;QACF,4CAA4C;QAC5C,oBAAoB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,CAAC;QACzD,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EACL,GAAG,UAAU,+BAA+B;oBAC5C,6CAA6C;aAChD,CAAC;QACJ,CAAC;QAED,cAAc;QACd,uDAAuD;QACvD,4DAA4D;QAC5D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;QACvD,MAAM,OAAO,GAAI,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAA4B,CAAC,UAAU,CAAC,CAAC;QACtF,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,GAAG,GAA2B;gBAClC,SAAS,EAAE,uBAAuB;gBAClC,IAAI,EAAE,qCAAqC;gBAC3C,GAAG,EAAE,oCAAoC;gBACzC,KAAK,EAAE,2BAA2B;gBAClC,UAAU,EAAE,qCAAqC;aAClD,CAAC;YACF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,UAAU,aAAa,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,EAAE,CAAC;QACpF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,kBAAkB,CAAC,CAAC;YAC5G,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,mCAAmC;YACxE,IAAI,CAAC,aAAa,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ;YAC1C,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,0BAA0B,CAAC,CAAC;YAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,UAAU,8BAA8B,EAAE,CAAC;QAC/E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAA+B;IACjE,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE;QACzD,KAAK,EAAE,iBAAiB;KACzB,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,17 @@
1
1
  {
2
2
  "name": "@aalis/plugin-package-manager",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/AalisLabs/Aalis.git",
8
+ "directory": "packages/plugin-package-manager"
9
+ },
10
+ "author": "Ace Nyan <ace@acenyan.com>",
11
+ "bugs": {
12
+ "url": "https://github.com/AalisLabs/Aalis/issues"
13
+ },
14
+ "homepage": "https://github.com/AalisLabs/Aalis#readme",
5
15
  "description": "插件包管理:从 npm 安装/卸载插件到 packages/",
6
16
  "type": "module",
7
17
  "keywords": [
@@ -14,15 +24,16 @@
14
24
  "dist"
15
25
  ],
16
26
  "dependencies": {
17
- "@aalis/plugin-process-api": "^0.5.0"
27
+ "@aalis/api-process": ">=0.5.0 <1.0.0",
28
+ "@aalis/util-dep-spec": ">=0.1.0 <1.0.0"
18
29
  },
19
30
  "devDependencies": {
20
31
  "@types/node": "^22.0.0",
21
32
  "typescript": "^5.7.0",
22
- "@aalis/core": "0.5.0"
33
+ "@aalis/core": "0.10.0"
23
34
  },
24
35
  "peerDependencies": {
25
- "@aalis/core": ">=0.2.0 <1.0.0"
36
+ "@aalis/core": ">=0.10.0 <1.0.0"
26
37
  },
27
38
  "aalis": {
28
39
  "service": {