@mearl/preset 3.0.0-beta.0 → 3.0.0-beta.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/README.md +3 -0
- package/dist/manifest.js +22 -4
- package/dist/resolve.js +1 -0
- package/dist/types.d.ts +2 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ Node 模块快照与宿主加载合同见 [Node 能力包](../../docs/node-capab
|
|
|
49
49
|
- packages、skills、providers 按 ID 合并,子级字段覆盖同 ID 声明;数组整体替换。启用项最终必须存在 source,`enabled:false` 保留停用声明。
|
|
50
50
|
- 组件 `dependsOn` 引用同类组件 ID;检查最终继承图中的缺失、停用和循环依赖。它不表示 runtime 兼容或安装已完成。
|
|
51
51
|
- source 相对声明它的清单解析;子级只修改版本时不会改变继承 source 的基准 URL。
|
|
52
|
+
- Skill 可声明 `migrateFrom` 旧来源列表(最多 16 项),相对地址按声明清单解析;子级整体覆盖,空数组清除。安装器仅在来源收据匹配旧来源、Skill 身份有效且所有关联插件均由 setup 托管时迁移。手动注册、共享的手动别名或其他来源保留并报告冲突;来源匹配仍严格检查 ref。
|
|
52
53
|
- defaults 递归合并对象,数组、标量和 null 替换;用户覆盖单独保存,在解析结果上应用。
|
|
53
54
|
- 权限汇总去重,结果仅表示需求;必须由浏览器安装器另行取得实际授权。
|
|
54
55
|
- appProfiles 是 App ID 到实现标识的覆盖映射。具体档案是否存在、所需包是否可执行,由后续能力目录校验,解析器不宣称已验证模拟效果。
|
|
@@ -56,3 +57,5 @@ Node 模块快照与宿主加载合同见 [Node 能力包](../../docs/node-capab
|
|
|
56
57
|
- 拒绝未知字段、非 JSON 配置和原型污染键。清单总量不超过 256 Ki UTF-16 code units,defaults 最大嵌套 32 层。
|
|
57
58
|
|
|
58
59
|
本包尚不包含完整 preset 安装器、preset 锁文件持久化或 UI。浏览器宿主和 setup 需要复用同一解析结果接续资源准备、权限、注册与激活;能力包本地存储只负责已校验快照的事务替换。
|
|
60
|
+
|
|
61
|
+
Skill manager 的可选 `readSources(scope, cwd)` 返回该管理器核验过的来源收据,结构与 setup 的 `TrackedSkillSource` 一致。CLI 与 Native 安装状态共用该读取接口;管理器负责持久化、校验和失效自身补充记录,公共宿主继续核对来源、ref、清单身份与托管归属。未提供时读取标准 Skills 锁文件。
|
package/dist/manifest.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateInstallationOrigin } from './installation.js';
|
|
1
2
|
import { valid, validRange } from 'semver';
|
|
2
3
|
export class PresetError extends Error {
|
|
3
4
|
code;
|
|
@@ -70,12 +71,19 @@ export function clonePresetDefaults(value) {
|
|
|
70
71
|
object(value, 'defaults');
|
|
71
72
|
return json(value, 'defaults');
|
|
72
73
|
}
|
|
73
|
-
function component(value, path) {
|
|
74
|
-
fields(value, path, ['source', 'version', 'enabled', 'runtimes', 'dependsOn']);
|
|
74
|
+
function component(value, path, kind) {
|
|
75
|
+
fields(value, path, ['source', 'version', 'enabled', 'runtimes', 'dependsOn', 'migrateFrom']);
|
|
75
76
|
if ('source' in value)
|
|
76
77
|
text(value.source, `${path}.source`);
|
|
77
78
|
if ('version' in value)
|
|
78
79
|
range(value.version, `${path}.version`);
|
|
80
|
+
if ('migrateFrom' in value) {
|
|
81
|
+
if (kind !== 'skills')
|
|
82
|
+
invalid(`${path}.migrateFrom`, 'only Skills support source migration');
|
|
83
|
+
stringArray(value.migrateFrom, `${path}.migrateFrom`);
|
|
84
|
+
if (value.migrateFrom.length > 16)
|
|
85
|
+
invalid(`${path}.migrateFrom`, 'exceeds 16 sources');
|
|
86
|
+
}
|
|
79
87
|
if ('enabled' in value && typeof value.enabled !== 'boolean')
|
|
80
88
|
invalid(`${path}.enabled`, 'expected a boolean');
|
|
81
89
|
if ('runtimes' in value) {
|
|
@@ -120,7 +128,7 @@ export function validatePreset(value) {
|
|
|
120
128
|
object(declarations, kind);
|
|
121
129
|
result[kind] = Object.fromEntries(Object.entries(declarations).map(([key, item]) => {
|
|
122
130
|
id(key, `${kind}.${key}`);
|
|
123
|
-
return [key, component(item, `${kind}.${key}
|
|
131
|
+
return [key, component(item, `${kind}.${key}`, kind)];
|
|
124
132
|
}));
|
|
125
133
|
}
|
|
126
134
|
if ('appProfiles' in value) {
|
|
@@ -137,7 +145,17 @@ export function validatePreset(value) {
|
|
|
137
145
|
fields(value.permissions, 'permissions', ['origins']);
|
|
138
146
|
if ('origins' in value.permissions)
|
|
139
147
|
stringArray(value.permissions.origins, 'permissions.origins');
|
|
140
|
-
|
|
148
|
+
const origins = value.permissions.origins ?? [];
|
|
149
|
+
if (origins.length > 64)
|
|
150
|
+
invalid('permissions.origins', 'exceeds 64 scopes');
|
|
151
|
+
result.permissions = { origins: [...new Set(origins.map((origin, index) => {
|
|
152
|
+
try {
|
|
153
|
+
return validateInstallationOrigin(origin);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return invalid(`permissions.origins[${index}]`, 'expected an explicit HTTP host scope');
|
|
157
|
+
}
|
|
158
|
+
}))] };
|
|
141
159
|
}
|
|
142
160
|
if (JSON.stringify(result).length > 262_144)
|
|
143
161
|
invalid('preset', 'manifest exceeds 256 Ki UTF-16 code units');
|
package/dist/resolve.js
CHANGED
|
@@ -118,6 +118,7 @@ export async function resolvePreset(source, options) {
|
|
|
118
118
|
...result[kind][id],
|
|
119
119
|
...patch,
|
|
120
120
|
...(patch.source === undefined ? {} : { source: componentSource(kind, patch.source, url) }),
|
|
121
|
+
...(patch.migrateFrom === undefined ? {} : { migrateFrom: patch.migrateFrom.map(source => componentSource(kind, source, url)) }),
|
|
121
122
|
declaredBy: url,
|
|
122
123
|
};
|
|
123
124
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface PresetComponent {
|
|
|
8
8
|
/** Bundle URL for packages; installer-specific source for skills and providers. */
|
|
9
9
|
source?: string;
|
|
10
10
|
version?: string;
|
|
11
|
+
/** Previous Skill sources eligible for migration only when setup owns the installation. */
|
|
12
|
+
migrateFrom?: string[];
|
|
11
13
|
enabled?: boolean;
|
|
12
14
|
runtimes?: PresetRuntime[];
|
|
13
15
|
dependsOn?: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/preset",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.2",
|
|
4
4
|
"description": "Browser-compatible preset validation, inheritance and capability resolution for Mearl",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/semver": "^7.7.1"
|
|
32
32
|
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/F-loat/mearl.git",
|
|
36
|
+
"directory": "packages/preset"
|
|
37
|
+
},
|
|
33
38
|
"scripts": {
|
|
34
39
|
"build": "rm -rf dist/ && tsc",
|
|
35
40
|
"typecheck": "tsc --noEmit",
|