@dsh-workbench/shared 1.0.1 → 1.1.0
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/contract/protocol/bundle-install.d.ts +9 -1
- package/dist/contract/protocol/market-index.d.ts +1 -0
- package/dist/contract/protocol/market-index.js +1 -0
- package/dist/contract/unit-declaration.d.ts +11 -5
- package/dist/contract/unit-declaration.js +42 -12
- package/dist/contract/unit.d.ts +15 -1
- package/dist/contract/unit.js +8 -0
- package/dist/contract/workbench-contract.d.ts +1 -1
- package/dist/host/provision.d.ts +1 -1
- package/dist/host/provision.js +8 -2
- package/dist/host/supply-index.d.ts +4 -1
- package/dist/host/supply-index.js +18 -12
- package/dist/i18n/en.js +53 -32
- package/dist/i18n/index.d.ts +55 -34
- package/dist/i18n/zh.d.ts +54 -33
- package/dist/i18n/zh.js +54 -33
- package/dist/lib/dsh-client.d.ts +3 -1
- package/package.json +1 -1
- package/src/contract/__tests__/unit-declaration.test.ts +33 -1
- package/src/contract/protocol/bundle-install.ts +11 -1
- package/src/contract/protocol/market-index.ts +1 -0
- package/src/contract/unit-declaration.ts +52 -16
- package/src/contract/unit.ts +19 -1
- package/src/contract/workbench-contract.ts +3 -1
- package/src/host/__tests__/provision.test.ts +2 -0
- package/src/host/__tests__/supply-index.test.ts +42 -6
- package/src/host/provision.ts +6 -2
- package/src/host/supply-index.ts +40 -11
- package/src/i18n/en.ts +53 -32
- package/src/i18n/zh.ts +54 -33
- package/src/lib/dsh-client.ts +3 -1
- package/src/testing/__tests__/declaration.test.ts +6 -3
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { UnitTitle } from '../unit.js';
|
|
1
2
|
export declare const BUNDLE_REGISTRIES_ROUTE = "bundle-registries";
|
|
2
3
|
export declare const BUNDLE_INSPECT_ROUTE = "bundle-inspect";
|
|
3
4
|
export declare const BUNDLE_REGISTRY_DEFAULT = "default";
|
|
@@ -52,7 +53,6 @@ export interface WorkbenchSelfUpdate {
|
|
|
52
53
|
readonly version?: string;
|
|
53
54
|
readonly at?: string;
|
|
54
55
|
readonly tail?: string;
|
|
55
|
-
readonly migration?: 'needed';
|
|
56
56
|
}
|
|
57
57
|
export declare const RESTART_REASONS: readonly ["no-hmr", "package-moved", "host-module", "unmanaged-plugin", "module-comparison"];
|
|
58
58
|
export type RestartReason = (typeof RESTART_REASONS)[number];
|
|
@@ -115,11 +115,14 @@ export interface BundleRemovePayload {
|
|
|
115
115
|
export interface BundleCancellationPayload {
|
|
116
116
|
readonly cancellation: BundleCancellation | null;
|
|
117
117
|
}
|
|
118
|
+
export type ModuleUpdateBlock = 'needs-workbench' | 'incompatible';
|
|
118
119
|
export interface ModuleVersion {
|
|
119
120
|
readonly unit: string;
|
|
120
121
|
readonly pkg: string;
|
|
121
122
|
readonly installed: string;
|
|
123
|
+
readonly title?: UnitTitle;
|
|
122
124
|
readonly latest?: string;
|
|
125
|
+
readonly latestBlocked?: ModuleUpdateBlock;
|
|
123
126
|
readonly local?: boolean;
|
|
124
127
|
readonly refused?: readonly string[];
|
|
125
128
|
}
|
|
@@ -129,6 +132,11 @@ export interface WorkbenchVersion {
|
|
|
129
132
|
readonly latest?: string;
|
|
130
133
|
readonly running?: string;
|
|
131
134
|
readonly local?: boolean;
|
|
135
|
+
readonly followUp?: {
|
|
136
|
+
readonly id: string;
|
|
137
|
+
readonly kind: 'data-migration';
|
|
138
|
+
readonly hard: boolean;
|
|
139
|
+
};
|
|
132
140
|
}
|
|
133
141
|
export interface ModuleVersionsPayload {
|
|
134
142
|
readonly modules: readonly ModuleVersion[];
|
|
@@ -4,6 +4,7 @@ export declare const MARKET_DISCOVER_ROUTE = "panels/market-discover";
|
|
|
4
4
|
export declare const MARKET_DOC_ROUTE = "panels/market-doc";
|
|
5
5
|
export declare const MARKET_PUBLISH_PREVIEW_ROUTE = "panels/market-publish-preview";
|
|
6
6
|
export declare const MARKET_SOURCES_RESOURCE = "market-sources";
|
|
7
|
+
export declare const MARKET_SOURCES_ROUTE = "panels/market-sources";
|
|
7
8
|
export declare const MARKET_WORKBENCH_LABEL = "workbench";
|
|
8
9
|
export type MarketSourceKind = 'http' | 'git';
|
|
9
10
|
export type MarketSourcePolicy = 'artifacts-in-repo' | 'catalog-only';
|
|
@@ -4,4 +4,5 @@ export const MARKET_DISCOVER_ROUTE = 'panels/market-discover';
|
|
|
4
4
|
export const MARKET_DOC_ROUTE = 'panels/market-doc';
|
|
5
5
|
export const MARKET_PUBLISH_PREVIEW_ROUTE = 'panels/market-publish-preview';
|
|
6
6
|
export const MARKET_SOURCES_RESOURCE = 'market-sources';
|
|
7
|
+
export const MARKET_SOURCES_ROUTE = 'panels/market-sources';
|
|
7
8
|
export const MARKET_WORKBENCH_LABEL = 'workbench';
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import type { UnitHostNeeds, UnitManifest } from '../contract/unit.js';
|
|
1
|
+
import type { UnitHostNeeds, UnitManifest, UnitTitle } from '../contract/unit.js';
|
|
2
2
|
import { type Need } from './needs.js';
|
|
3
3
|
/**
|
|
4
4
|
* 声明协议当前版本;模块清单的 dsh.workbench.apiVersion 要写这个整数。
|
|
5
5
|
*/
|
|
6
|
-
export declare const WORKBENCH_API_VERSION =
|
|
6
|
+
export declare const WORKBENCH_API_VERSION = 3;
|
|
7
7
|
/**
|
|
8
8
|
* 外壳愿意认的协议版本;不在表里的模块当场被拒,不猜语义。
|
|
9
9
|
*/
|
|
10
10
|
export declare const SUPPORTED_API_VERSIONS: readonly number[];
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* 清单里那半张卡片声明:只剩排序位;卡片默认显不显示不在这里(那是运行期面板配置的事)。
|
|
13
13
|
*/
|
|
14
14
|
export interface UnitCardDeclaration {
|
|
15
|
-
readonly titleKey: string;
|
|
16
15
|
readonly order: number;
|
|
17
16
|
}
|
|
18
17
|
/**
|
|
@@ -24,11 +23,12 @@ export interface UnitToolDeclaration {
|
|
|
24
23
|
readonly key?: string;
|
|
25
24
|
}
|
|
26
25
|
/**
|
|
27
|
-
* 模块清单里 dsh.workbench 那一段的完整形状(协议版本、单元 id
|
|
26
|
+
* 模块清单里 dsh.workbench 那一段的完整形状(协议版本、单元 id、名字、卡片、工具、宿主与环境需要)。
|
|
28
27
|
*/
|
|
29
28
|
export interface UnitDeclaration {
|
|
30
29
|
readonly apiVersion: number;
|
|
31
30
|
readonly unit: string;
|
|
31
|
+
readonly title: UnitTitle;
|
|
32
32
|
readonly card: UnitCardDeclaration | null;
|
|
33
33
|
readonly tools: readonly UnitToolDeclaration[];
|
|
34
34
|
readonly host: UnitHostNeeds;
|
|
@@ -42,6 +42,12 @@ export declare const DECLARATION_KEYS: readonly string[];
|
|
|
42
42
|
* 协议要求必写的键;needs 不在其中(没有环境需要就不写)。
|
|
43
43
|
*/
|
|
44
44
|
export declare const DECLARATION_REQUIRED_KEYS: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* 读一份声明里的协议版本;不是对象或 apiVersion 不是整数时给 undefined。
|
|
47
|
+
* @param raw 清单里 dsh.workbench 那段原始值。
|
|
48
|
+
* @returns 声明声明的协议版本,读不出来时 undefined。
|
|
49
|
+
*/
|
|
50
|
+
export declare function declarationApiVersionOf(raw: unknown): number | undefined;
|
|
45
51
|
/**
|
|
46
52
|
* 查清单里 dsh.workbench 那一段的形状,回一串给人看的问题(中文,带字段路径)。
|
|
47
53
|
* @param subject 报错时用的主语,一般是包名。
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { unitTitleKey } from '../contract/unit.js';
|
|
1
2
|
import { needsProblemsOf } from './needs.js';
|
|
2
3
|
/**
|
|
3
4
|
* 声明协议当前版本;模块清单的 dsh.workbench.apiVersion 要写这个整数。
|
|
4
5
|
*/
|
|
5
|
-
export const WORKBENCH_API_VERSION =
|
|
6
|
+
export const WORKBENCH_API_VERSION = 3;
|
|
6
7
|
/**
|
|
7
8
|
* 外壳愿意认的协议版本;不在表里的模块当场被拒,不猜语义。
|
|
8
9
|
*/
|
|
@@ -13,6 +14,7 @@ export const SUPPORTED_API_VERSIONS = [WORKBENCH_API_VERSION];
|
|
|
13
14
|
export const DECLARATION_KEYS = [
|
|
14
15
|
'apiVersion',
|
|
15
16
|
'unit',
|
|
17
|
+
'title',
|
|
16
18
|
'card',
|
|
17
19
|
'tools',
|
|
18
20
|
'host',
|
|
@@ -24,11 +26,13 @@ export const DECLARATION_KEYS = [
|
|
|
24
26
|
export const DECLARATION_REQUIRED_KEYS = [
|
|
25
27
|
'apiVersion',
|
|
26
28
|
'unit',
|
|
29
|
+
'title',
|
|
27
30
|
'card',
|
|
28
31
|
'tools',
|
|
29
32
|
'host',
|
|
30
33
|
];
|
|
31
|
-
const CARD_KEYS = ['
|
|
34
|
+
const CARD_KEYS = ['order'];
|
|
35
|
+
const TITLE_KEYS = ['zh', 'en'];
|
|
32
36
|
const TOOL_KEYS = ['name', 'writes', 'key'];
|
|
33
37
|
const TOOL_KEY_SHAPE = /^[a-z][a-zA-Z0-9]*$/;
|
|
34
38
|
const HOST_KEYS = ['inject', 'optional'];
|
|
@@ -38,6 +42,17 @@ function text(value) {
|
|
|
38
42
|
function isRecord(value) {
|
|
39
43
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
40
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* 读一份声明里的协议版本;不是对象或 apiVersion 不是整数时给 undefined。
|
|
47
|
+
* @param raw 清单里 dsh.workbench 那段原始值。
|
|
48
|
+
* @returns 声明声明的协议版本,读不出来时 undefined。
|
|
49
|
+
*/
|
|
50
|
+
export function declarationApiVersionOf(raw) {
|
|
51
|
+
if (!isRecord(raw))
|
|
52
|
+
return undefined;
|
|
53
|
+
const version = raw.apiVersion;
|
|
54
|
+
return Number.isInteger(version) ? version : undefined;
|
|
55
|
+
}
|
|
41
56
|
function outsideKeys(value, allowed) {
|
|
42
57
|
return Object.keys(value).filter((key) => !allowed.includes(key));
|
|
43
58
|
}
|
|
@@ -66,10 +81,9 @@ export function declarationProblemsOf(subject, raw) {
|
|
|
66
81
|
];
|
|
67
82
|
}
|
|
68
83
|
if (!Number.isInteger(version) || !SUPPORTED_API_VERSIONS.includes(version)) {
|
|
69
|
-
const hint = version ===
|
|
70
|
-
?
|
|
71
|
-
'
|
|
72
|
-
'再把 apiVersion 改成 2'
|
|
84
|
+
const hint = version === 2
|
|
85
|
+
? ' —— v3 把卡片标题挪成了顶层 `title`(`{ "zh": "…", "en": "…" }` 字面量):' +
|
|
86
|
+
'把 `card.titleKey` 删掉、在顶层写 title,再把 apiVersion 改成 3'
|
|
73
87
|
: '';
|
|
74
88
|
return [
|
|
75
89
|
`${subject}: dsh.workbench.apiVersion 是 ${JSON.stringify(version)},这里只认 ` +
|
|
@@ -88,6 +102,23 @@ export function declarationProblemsOf(subject, raw) {
|
|
|
88
102
|
(key === 'card' ? '(这个模块没有卡片就写 `"card": null`)' : ''));
|
|
89
103
|
}
|
|
90
104
|
}
|
|
105
|
+
const title = raw.title;
|
|
106
|
+
if (title !== undefined) {
|
|
107
|
+
if (!isRecord(title)) {
|
|
108
|
+
problems.push(`${subject}: dsh.workbench.title 要是对象(中英各一份),现在是 ${JSON.stringify(title)}`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const extra = outsideKeys(title, TITLE_KEYS);
|
|
112
|
+
if (extra.length > 0) {
|
|
113
|
+
problems.push(`${subject}: dsh.workbench.title 里有不认的键 ${listOf(extra)} —— title 只有 ${listOf(TITLE_KEYS)}`);
|
|
114
|
+
}
|
|
115
|
+
for (const language of TITLE_KEYS) {
|
|
116
|
+
if (text(title[language]) === '') {
|
|
117
|
+
problems.push(`${subject}: dsh.workbench.title.${language} 要是非空字符串(市场和面板里显示的名字)`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
91
122
|
const card = raw.card;
|
|
92
123
|
if (card !== undefined && card !== null) {
|
|
93
124
|
if (!isRecord(card)) {
|
|
@@ -97,10 +128,7 @@ export function declarationProblemsOf(subject, raw) {
|
|
|
97
128
|
const extra = outsideKeys(card, CARD_KEYS);
|
|
98
129
|
if (extra.length > 0) {
|
|
99
130
|
problems.push(`${subject}: dsh.workbench.card 里有不认的键 ${listOf(extra)} —— card 只有 ${listOf(CARD_KEYS)}` +
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
if (text(card.titleKey) === '') {
|
|
103
|
-
problems.push(`${subject}: dsh.workbench.card.titleKey 要是非空字符串(面板那一格的文案键)`);
|
|
131
|
+
`(名字写在顶层的 title 里;卡片默认显不显示由运行期的面板配置决定,清单里没有这一位)`);
|
|
104
132
|
}
|
|
105
133
|
if (typeof card.order !== 'number' || !Number.isFinite(card.order)) {
|
|
106
134
|
problems.push(`${subject}: dsh.workbench.card.order 要是数字,现在是 ${JSON.stringify(card.order)}`);
|
|
@@ -193,15 +221,17 @@ export function readDeclaration(subject, raw) {
|
|
|
193
221
|
if (needsRead.errors.length > 0)
|
|
194
222
|
return { problems: needsRead.errors, warnings: needsRead.warnings };
|
|
195
223
|
const card = declaration.card;
|
|
224
|
+
const id = text(declaration.unit);
|
|
196
225
|
return {
|
|
197
226
|
declaration,
|
|
198
227
|
problems: [],
|
|
199
228
|
manifest: {
|
|
200
|
-
id
|
|
229
|
+
id,
|
|
230
|
+
title: { zh: text(declaration.title.zh), en: text(declaration.title.en) },
|
|
201
231
|
card: card === null
|
|
202
232
|
? null
|
|
203
233
|
: {
|
|
204
|
-
titleKey:
|
|
234
|
+
titleKey: unitTitleKey(id),
|
|
205
235
|
order: card.order,
|
|
206
236
|
},
|
|
207
237
|
tools: declaration.tools.map((tool) => ({
|
package/dist/contract/unit.d.ts
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import type { ExtensionNeed, LibNeed, Need } from './needs.js';
|
|
2
|
+
/**
|
|
3
|
+
* 模块的人类可读名字:中英各一份,写在 package.json 的 dsh.workbench.title 里。
|
|
4
|
+
*/
|
|
5
|
+
export interface UnitTitle {
|
|
6
|
+
readonly zh: string;
|
|
7
|
+
readonly en: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 外壳替模块名合成的词表键:模块自己不必写名字键,名字直接从清单里的 title 注册进来。
|
|
11
|
+
* @param unit 单元 id。
|
|
12
|
+
* @returns 该单元名字在词表里的键。
|
|
13
|
+
*/
|
|
14
|
+
export declare function unitTitleKey(unit: string): string;
|
|
2
15
|
/**
|
|
3
16
|
* 一张卡片在清单里的静态声明(文案键加排序位);默认显不显示由运行期面板配置定。
|
|
4
17
|
*/
|
|
@@ -28,10 +41,11 @@ export interface PluginRelease {
|
|
|
28
41
|
readonly latest?: string;
|
|
29
42
|
}
|
|
30
43
|
/**
|
|
31
|
-
* 装配期用的模块清单:单元 id
|
|
44
|
+
* 装配期用的模块清单:单元 id、名字、卡片、工具、宿主服务与环境需要,比声明少一层协议包装。
|
|
32
45
|
*/
|
|
33
46
|
export interface UnitManifest {
|
|
34
47
|
readonly id: string;
|
|
48
|
+
readonly title?: UnitTitle;
|
|
35
49
|
readonly card: UnitCard | null;
|
|
36
50
|
readonly tools: readonly UnitTool[];
|
|
37
51
|
readonly host: UnitHostNeeds;
|
package/dist/contract/unit.js
CHANGED
|
@@ -2,7 +2,7 @@ import type { NeedState } from '../contract/unit-capability.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* 供给动作的那几档(装 / 升 / 卸,模块、共用依赖与插件各一套);写口按它分派。
|
|
4
4
|
*/
|
|
5
|
-
export type ProvisionAction = 'install' | 'update' | 'uninstall' | 'update-dependency' | 'install-bundle' | 'install-version' | 'update-bundle' | 'remove-bundle' | 'cancel-install' | 'update-plugin' | 'uninstall-plugin' | 'update-workbench';
|
|
5
|
+
export type ProvisionAction = 'install' | 'update' | 'uninstall' | 'update-dependency' | 'install-bundle' | 'install-version' | 'update-bundle' | 'remove-bundle' | 'cancel-install' | 'update-plugin' | 'uninstall-plugin' | 'update-workbench' | 'migrate-workbench' | 'dismiss-followup';
|
|
6
6
|
/**
|
|
7
7
|
* 宿主对「这个单元现在能不能用」的那份读数:状态汇总加逐条 need 的细节。
|
|
8
8
|
*/
|
package/dist/host/provision.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ProvisionAction } from '../contract/workbench-contract.js';
|
|
2
2
|
export type { ProvisionAction };
|
|
3
|
-
export declare const PROVISION_ACTIONS: readonly ["install", "update", "uninstall", "install-bundle", "install-version", "update-bundle", "remove-bundle", "cancel-install", "update-dependency", "update-plugin", "uninstall-plugin", "update-workbench"];
|
|
3
|
+
export declare const PROVISION_ACTIONS: readonly ["install", "update", "uninstall", "install-bundle", "install-version", "update-bundle", "remove-bundle", "cancel-install", "update-dependency", "update-plugin", "uninstall-plugin", "update-workbench", "migrate-workbench", "dismiss-followup"];
|
|
4
4
|
export declare const DEPENDENCY_ACTIONS: readonly ["update-dependency"];
|
|
5
5
|
export declare function isDependencyAction(action: ProvisionAction): action is (typeof DEPENDENCY_ACTIONS)[number];
|
|
6
6
|
export type ProvisionTarget = 'unit' | 'id' | 'spec' | 'name' | 'requestId';
|
package/dist/host/provision.js
CHANGED
|
@@ -11,6 +11,8 @@ export const PROVISION_ACTIONS = [
|
|
|
11
11
|
'update-plugin',
|
|
12
12
|
'uninstall-plugin',
|
|
13
13
|
'update-workbench',
|
|
14
|
+
'migrate-workbench',
|
|
15
|
+
'dismiss-followup',
|
|
14
16
|
];
|
|
15
17
|
export const DEPENDENCY_ACTIONS = ['update-dependency'];
|
|
16
18
|
export function isDependencyAction(action) {
|
|
@@ -27,8 +29,10 @@ export function provisionTargetOf(action) {
|
|
|
27
29
|
return 'name';
|
|
28
30
|
if (action === 'update-plugin' || action === 'uninstall-plugin')
|
|
29
31
|
return 'name';
|
|
30
|
-
if (action === 'update-workbench')
|
|
32
|
+
if (action === 'update-workbench' || action === 'migrate-workbench')
|
|
31
33
|
return 'name';
|
|
34
|
+
if (action === 'dismiss-followup')
|
|
35
|
+
return 'id';
|
|
32
36
|
if (action === 'cancel-install')
|
|
33
37
|
return 'requestId';
|
|
34
38
|
return 'unit';
|
|
@@ -58,8 +62,10 @@ function requestOf(action, value) {
|
|
|
58
62
|
return { action, name: value };
|
|
59
63
|
if (action === 'update-plugin' || action === 'uninstall-plugin')
|
|
60
64
|
return { action, name: value };
|
|
61
|
-
if (action === 'update-workbench')
|
|
65
|
+
if (action === 'update-workbench' || action === 'migrate-workbench')
|
|
62
66
|
return { action, name: value };
|
|
67
|
+
if (action === 'dismiss-followup')
|
|
68
|
+
return { action, id: value };
|
|
63
69
|
if (action === 'cancel-install')
|
|
64
70
|
return { action, requestId: value };
|
|
65
71
|
return { action, unit: value };
|
|
@@ -3,6 +3,9 @@ export interface SupplyDeclaration {
|
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly needs?: readonly Need[];
|
|
5
5
|
}
|
|
6
|
+
export interface SupplyIndexOptions {
|
|
7
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
8
|
+
}
|
|
6
9
|
export interface SupplyEntry {
|
|
7
10
|
readonly key: string;
|
|
8
11
|
readonly kind: 'extension' | 'lib';
|
|
@@ -31,4 +34,4 @@ export interface SupplyIndex {
|
|
|
31
34
|
export declare function npmSourceOf(sources: readonly SupplySource[] | undefined): Extract<SupplySource, {
|
|
32
35
|
kind: 'npm';
|
|
33
36
|
}> | undefined;
|
|
34
|
-
export declare function buildSupplyIndex(declarations: readonly SupplyDeclaration[]): SupplyIndex;
|
|
37
|
+
export declare function buildSupplyIndex(declarations: readonly SupplyDeclaration[], options?: SupplyIndexOptions): SupplyIndex;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { npmRegistryOf } from './plugin-source.js';
|
|
1
2
|
export function npmSourceOf(sources) {
|
|
2
3
|
return sources?.find((source) => source.kind === 'npm');
|
|
3
4
|
}
|
|
@@ -29,18 +30,22 @@ function packageOf(need) {
|
|
|
29
30
|
function keyOf(kind, pkg) {
|
|
30
31
|
return `${kind}:${pkg}`;
|
|
31
32
|
}
|
|
32
|
-
function
|
|
33
|
+
function registryAddressOf(source, env) {
|
|
34
|
+
const resolved = npmRegistryOf(source, env);
|
|
35
|
+
return resolved.ok ? resolved.value : undefined;
|
|
36
|
+
}
|
|
37
|
+
function sourceCompatible(left, right, env) {
|
|
33
38
|
if (left.kind !== right.kind)
|
|
34
39
|
return false;
|
|
35
40
|
if (left.kind === 'npm' && right.kind === 'npm') {
|
|
36
41
|
if (text(left.package) !== '' && text(right.package) !== '' && text(left.package) !== text(right.package)) {
|
|
37
42
|
return false;
|
|
38
43
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return
|
|
44
|
+
const l = registryAddressOf(left, env);
|
|
45
|
+
const r = registryAddressOf(right, env);
|
|
46
|
+
if (l !== undefined && r !== undefined)
|
|
47
|
+
return l === r;
|
|
48
|
+
return text(left.registryEnv) === text(right.registryEnv);
|
|
44
49
|
}
|
|
45
50
|
if (left.kind === 'git' && right.kind === 'git')
|
|
46
51
|
return text(left.url) === text(right.url);
|
|
@@ -49,12 +54,12 @@ function sourceCompatible(left, right) {
|
|
|
49
54
|
}
|
|
50
55
|
return false;
|
|
51
56
|
}
|
|
52
|
-
function sourcesCompatible(left, right) {
|
|
57
|
+
function sourcesCompatible(left, right, env) {
|
|
53
58
|
if (left.length !== right.length)
|
|
54
59
|
return false;
|
|
55
60
|
return left.every((source, index) => {
|
|
56
61
|
const other = right[index];
|
|
57
|
-
return other !== undefined && sourceCompatible(source, other);
|
|
62
|
+
return other !== undefined && sourceCompatible(source, other, env);
|
|
58
63
|
});
|
|
59
64
|
}
|
|
60
65
|
function mergedSource(left, right) {
|
|
@@ -69,13 +74,13 @@ function mergedSource(left, right) {
|
|
|
69
74
|
}
|
|
70
75
|
return left;
|
|
71
76
|
}
|
|
72
|
-
function mergeSources(entry, sources) {
|
|
77
|
+
function mergeSources(entry, sources, env) {
|
|
73
78
|
if (!entry.declared) {
|
|
74
79
|
entry.declared = true;
|
|
75
80
|
entry.sources = [...sources];
|
|
76
81
|
return true;
|
|
77
82
|
}
|
|
78
|
-
if (!sourcesCompatible(entry.sources, sources)) {
|
|
83
|
+
if (!sourcesCompatible(entry.sources, sources, env)) {
|
|
79
84
|
entry.conflicted = true;
|
|
80
85
|
return false;
|
|
81
86
|
}
|
|
@@ -100,7 +105,8 @@ function addDeclarer(entry, unit, commands) {
|
|
|
100
105
|
if (!entry.commands.includes(command))
|
|
101
106
|
entry.commands.push(command);
|
|
102
107
|
}
|
|
103
|
-
export function buildSupplyIndex(declarations) {
|
|
108
|
+
export function buildSupplyIndex(declarations, options = {}) {
|
|
109
|
+
const env = options.env ?? {};
|
|
104
110
|
const entries = new Map();
|
|
105
111
|
const byName = new Map();
|
|
106
112
|
const conflicts = [];
|
|
@@ -138,7 +144,7 @@ export function buildSupplyIndex(declarations) {
|
|
|
138
144
|
else {
|
|
139
145
|
addDeclarer(entry, declaration.id, []);
|
|
140
146
|
}
|
|
141
|
-
const same = mergeSources(entry, need.sources ?? []);
|
|
147
|
+
const same = mergeSources(entry, need.sources ?? [], env);
|
|
142
148
|
if (!same) {
|
|
143
149
|
conflicts.push({
|
|
144
150
|
kind: 'source-mismatch',
|