dsh-plugin-shop 0.8.6 → 0.8.7-beta.1
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 -3
- package/lib/client.js +548 -321
- package/lib/index.js +68 -28
- package/lib/typert.host.js +3 -1
- package/lib/typert.remote-client.js +2 -0
- package/lib/types/client/locales.d.ts +28 -0
- package/lib/types/client/present.d.ts +90 -12
- package/lib/types/host/compatibility.d.ts +29 -13
- package/lib/types/host/types.d.ts +24 -5
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { isMap, isSeq, parseDocument } from "yaml";
|
|
|
21
21
|
* both the source tree (tests) and the bundled `lib/index.js` sit exactly
|
|
22
22
|
* one level below the package root, so the same relative URL resolves in
|
|
23
23
|
* both. */
|
|
24
|
-
function ownManifest() {
|
|
24
|
+
function ownManifest$1() {
|
|
25
25
|
return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
@@ -48,7 +48,7 @@ function versionAtLoad(read) {
|
|
|
48
48
|
}
|
|
49
49
|
/** The version of the code in this process, read when the module was first
|
|
50
50
|
* evaluated — at boot, before any self-update could rewrite the file. */
|
|
51
|
-
const runningVersion = versionAtLoad(() => ownManifest().version);
|
|
51
|
+
const runningVersion = versionAtLoad(() => ownManifest$1().version);
|
|
52
52
|
/**
|
|
53
53
|
* Which run of the code this is: drawn when the module is first evaluated,
|
|
54
54
|
* fixed for the life of the process, and different in the next one.
|
|
@@ -70,7 +70,7 @@ const bootId = randomUUID();
|
|
|
70
70
|
* compare against is worth a verdict.
|
|
71
71
|
*/
|
|
72
72
|
function ownPeerRanges() {
|
|
73
|
-
const declared = ownManifest().peerDependencies;
|
|
73
|
+
const declared = ownManifest$1().peerDependencies;
|
|
74
74
|
if (declared === null || typeof declared !== "object") return {};
|
|
75
75
|
const ranges = {};
|
|
76
76
|
for (const [spec, range] of Object.entries(declared)) if (typeof range === "string") ranges[spec] = range;
|
|
@@ -649,9 +649,11 @@ const entrySchema = z.object({
|
|
|
649
649
|
profiles: z.array(z.string()).optional()
|
|
650
650
|
}).optional(),
|
|
651
651
|
dshPeers: z.record(z.string(), z.string()).optional(),
|
|
652
|
+
manifestVersion: z.string().optional(),
|
|
652
653
|
unpackedSize: z.number().int().nonnegative().optional(),
|
|
653
654
|
installSize: z.number().int().nonnegative().optional(),
|
|
654
|
-
archived: z.boolean().optional()
|
|
655
|
+
archived: z.boolean().optional(),
|
|
656
|
+
forked: z.boolean().optional()
|
|
655
657
|
}).superRefine((entry, ctx) => {
|
|
656
658
|
if (entry.source === "npm") {
|
|
657
659
|
if (!NPM_NAME.test(entry.name)) ctx.addIssue({
|
|
@@ -1249,20 +1251,35 @@ function unmetProfile(declared, running, templates) {
|
|
|
1249
1251
|
* could not tell".
|
|
1250
1252
|
*
|
|
1251
1253
|
* The rule is dsh's own (`check`, from the running app-boot), handed the
|
|
1252
|
-
* manifest dsh's installer
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1259
|
-
*
|
|
1260
|
-
*
|
|
1261
|
-
*
|
|
1262
|
-
*
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
1265
|
-
*
|
|
1254
|
+
* manifest dsh's installer judges (`ownManifest`): the name and version dsh
|
|
1255
|
+
* keys an exemption by, with the catalog's `dshPeers` for the peers. Those
|
|
1256
|
+
* are the only peers the rule reads, verbatim. Both channels are judged, each
|
|
1257
|
+
* by the manifest dsh reads for it:
|
|
1258
|
+
*
|
|
1259
|
+
* - An npm entry by its catalog `version`. dsh reads that manifest before it
|
|
1260
|
+
* installs a registry spec: `pnpm view <spec> name version
|
|
1261
|
+
* peerDependencies`, measured in dsh-plugin-manager 0.1.7-rc.2.
|
|
1262
|
+
* - A github entry by `manifestVersion`, the version of the manifest dsh
|
|
1263
|
+
* installs: at the pinned commit (a subpackage's own), or in the release
|
|
1264
|
+
* asset a rescued entry installs from. dsh skips a git or tarball spec
|
|
1265
|
+
* before pnpm and judges the installed manifest after it, rolling the
|
|
1266
|
+
* install back on a refusal (the same dsh-plugin-manager). The entry's
|
|
1267
|
+
* catalog `version` is a commit or a tag, so without `manifestVersion` it
|
|
1268
|
+
* is not judged at all: judged by its commit instead, it would miss an
|
|
1269
|
+
* exemption the profile holds under its real `name@version`, disabling an
|
|
1270
|
+
* install dsh accepts, and could offer no command, since `allow-version`
|
|
1271
|
+
* records no commit (design 2026-09-28-bundle-components-and-github-peers,
|
|
1272
|
+
* sections 6.1 and 7.3).
|
|
1273
|
+
*
|
|
1274
|
+
* dsh's key names no channel: an exemption recorded for one `name@version`
|
|
1275
|
+
* clears every entry whose manifest carries it, npm or github, here as in
|
|
1276
|
+
* dsh.
|
|
1277
|
+
*
|
|
1278
|
+
* What this cannot see errs toward silence, never toward a refusal dsh would
|
|
1279
|
+
* not make: a malformed peer range elsewhere in the manifest, which dsh
|
|
1280
|
+
* rejects only after installing, and the plugins a bundle's patch rows name,
|
|
1281
|
+
* which it checks then too. Those reach the reader as the install's own
|
|
1282
|
+
* failure (`installFailureDetail`).
|
|
1266
1283
|
*
|
|
1267
1284
|
* A throw from the check forms no verdict for that entry, as a resolver's
|
|
1268
1285
|
* throw does in `incompatibilityMap`.
|
|
@@ -1270,14 +1287,11 @@ function unmetProfile(declared, running, templates) {
|
|
|
1270
1287
|
function peerVerdictsOf(entries, check, exemptions, profile) {
|
|
1271
1288
|
const out = {};
|
|
1272
1289
|
for (const entry of entries) {
|
|
1273
|
-
|
|
1290
|
+
const manifest = ownManifest(entry);
|
|
1291
|
+
if (manifest === null) continue;
|
|
1274
1292
|
let issue;
|
|
1275
1293
|
try {
|
|
1276
|
-
issue = check.evaluate(
|
|
1277
|
-
name: entry.name,
|
|
1278
|
-
version: entry.version,
|
|
1279
|
-
peerDependencies: entry.dshPeers
|
|
1280
|
-
}, exemptions);
|
|
1294
|
+
issue = check.evaluate(manifest, exemptions);
|
|
1281
1295
|
} catch {
|
|
1282
1296
|
continue;
|
|
1283
1297
|
}
|
|
@@ -1290,6 +1304,28 @@ function peerVerdictsOf(entries, check, exemptions, profile) {
|
|
|
1290
1304
|
}
|
|
1291
1305
|
return out;
|
|
1292
1306
|
}
|
|
1307
|
+
/**
|
|
1308
|
+
* The manifest dsh judges an entry's install by, as `peerVerdictsOf` hands it
|
|
1309
|
+
* to the rule, or null when none can be formed: the entry declares no
|
|
1310
|
+
* harness peers, or it is a github entry with no `manifestVersion`. An npm
|
|
1311
|
+
* entry's catalog `version` is its manifest's; a github entry's is a commit
|
|
1312
|
+
* or a tag, so its manifest's own version is the one recorded beside its
|
|
1313
|
+
* peers, and the key is read on github entries only.
|
|
1314
|
+
*/
|
|
1315
|
+
function ownManifest(entry) {
|
|
1316
|
+
if (entry.dshPeers === void 0) return null;
|
|
1317
|
+
if (entry.source === "npm") return {
|
|
1318
|
+
name: entry.name,
|
|
1319
|
+
version: entry.version,
|
|
1320
|
+
peerDependencies: entry.dshPeers
|
|
1321
|
+
};
|
|
1322
|
+
if (entry.manifestVersion === void 0) return null;
|
|
1323
|
+
return {
|
|
1324
|
+
name: entry.name,
|
|
1325
|
+
version: entry.manifestVersion,
|
|
1326
|
+
peerDependencies: entry.dshPeers
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1293
1329
|
/** npm's package-name grammar as dsh's exemption records accept it, verbatim
|
|
1294
1330
|
* from app-boot 0.1.7-rc.2 (`PACKAGE_NAME` in profile-compatibility). */
|
|
1295
1331
|
const EXEMPTION_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
@@ -1671,10 +1707,14 @@ const REFUSAL_WARNING_TAIL = " Running it may cause crashes or data loss.";
|
|
|
1671
1707
|
/**
|
|
1672
1708
|
* dsh's own refusal of an install (0.1.7 on) as one detail, or null when the
|
|
1673
1709
|
* log holds none. The install was dsh's to refuse, not pnpm's to fail: it
|
|
1674
|
-
* refuses before pnpm runs, when it can read the manifest — a registry spec
|
|
1675
|
-
*
|
|
1676
|
-
*
|
|
1677
|
-
*
|
|
1710
|
+
* refuses before pnpm runs, when it can read the manifest — a registry spec —
|
|
1711
|
+
* and after pnpm succeeded otherwise, restoring the profile. The catalog's
|
|
1712
|
+
* peer verdict predicts the first, and the second only for a github entry's
|
|
1713
|
+
* own peers, judged by the manifest version the catalog records
|
|
1714
|
+
* (`peerVerdictsOf`). It predicts no refusal of a bundle's components, and
|
|
1715
|
+
* none of a github entry that carries no usable manifest version: dsh makes
|
|
1716
|
+
* those after pnpm all the same. Reading any refusal as a pnpm failure sent
|
|
1717
|
+
* the reader to `dsh plugin install`, which repairs nothing.
|
|
1678
1718
|
*
|
|
1679
1719
|
* The detail is what dsh refused, what it restored, and the command that
|
|
1680
1720
|
* records its exact-version exemption, rebuilt from what dsh printed through
|
package/lib/typert.host.js
CHANGED
|
@@ -50,9 +50,11 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
|
|
|
50
50
|
'profiles': z.union([z.undefined(), z.array(z.string())]).optional(),
|
|
51
51
|
})]).optional(),
|
|
52
52
|
'dshPeers': z.union([z.undefined(), z.record(z.string(), z.string())]).optional(),
|
|
53
|
+
'manifestVersion': z.union([z.undefined(), z.string()]).optional(),
|
|
53
54
|
'unpackedSize': z.union([z.undefined(), z.number()]).optional(),
|
|
54
55
|
'installSize': z.union([z.undefined(), z.number()]).optional(),
|
|
55
56
|
'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
57
|
+
'forked': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
56
58
|
})),
|
|
57
59
|
'denied': z.array(z.object({
|
|
58
60
|
'name': z.string(),
|
|
@@ -498,7 +500,7 @@ export const TYPERT = {
|
|
|
498
500
|
},
|
|
499
501
|
{
|
|
500
502
|
"name": "CatalogEntry",
|
|
501
|
-
"declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n}"
|
|
503
|
+
"declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n manifestVersion?: string;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n forked?: boolean;\n}"
|
|
502
504
|
},
|
|
503
505
|
{
|
|
504
506
|
"name": "CatalogSection",
|
|
@@ -50,9 +50,11 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
|
|
|
50
50
|
'profiles': z.union([z.undefined(), z.array(z.string())]).optional(),
|
|
51
51
|
})]).optional(),
|
|
52
52
|
'dshPeers': z.union([z.undefined(), z.record(z.string(), z.string())]).optional(),
|
|
53
|
+
'manifestVersion': z.union([z.undefined(), z.string()]).optional(),
|
|
53
54
|
'unpackedSize': z.union([z.undefined(), z.number()]).optional(),
|
|
54
55
|
'installSize': z.union([z.undefined(), z.number()]).optional(),
|
|
55
56
|
'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
57
|
+
'forked': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
56
58
|
})),
|
|
57
59
|
'denied': z.array(z.object({
|
|
58
60
|
'name': z.string(),
|
|
@@ -19,6 +19,14 @@ export declare const zh: {
|
|
|
19
19
|
all: string;
|
|
20
20
|
catalog: string;
|
|
21
21
|
catalogStats: string;
|
|
22
|
+
/** The shelf's order control, and the date each card carries under the two
|
|
23
|
+
* date orders (design 2026-10-12-shelf-orders §4). */
|
|
24
|
+
sortLabel: string;
|
|
25
|
+
sortStars: string;
|
|
26
|
+
sortAdded: string;
|
|
27
|
+
sortUpdated: string;
|
|
28
|
+
listedOn: string;
|
|
29
|
+
updatedOn: string;
|
|
22
30
|
stars: string;
|
|
23
31
|
categoryTool: string;
|
|
24
32
|
categoryProvider: string;
|
|
@@ -117,6 +125,13 @@ export declare const zh: {
|
|
|
117
125
|
nameTakenDetail: string;
|
|
118
126
|
npmSource: string;
|
|
119
127
|
githubSource: string;
|
|
128
|
+
/** The accessible name and the tooltip of a card's version, which say which
|
|
129
|
+
* of three things the printed string is (market borrowings §11): the string
|
|
130
|
+
* alone cannot tell a release tag from a version number, and a short commit
|
|
131
|
+
* printed with a `v` read as one. */
|
|
132
|
+
npmVersionLabel: string;
|
|
133
|
+
commitVersionLabel: string;
|
|
134
|
+
releaseVersionLabel: string;
|
|
120
135
|
/** The badge and the explanation for an installed github entry no catalog
|
|
121
136
|
* row claims (C10 MVP). The mechanism synthesizes a row for ANY github spec
|
|
122
137
|
* with no catalog row — shadowed by a same-named npm package, an unlisted
|
|
@@ -126,6 +141,8 @@ export declare const zh: {
|
|
|
126
141
|
shadowedBadge: string;
|
|
127
142
|
shadowedDetail: string;
|
|
128
143
|
updatableSection: string;
|
|
144
|
+
/** `{version}` is the shelf's own version text (`versionLabel`), which
|
|
145
|
+
* carries the `v` an npm version takes and no other kind does. */
|
|
129
146
|
installedVersion: string;
|
|
130
147
|
latestVersion: string;
|
|
131
148
|
update: string;
|
|
@@ -185,6 +202,14 @@ export declare const en: {
|
|
|
185
202
|
all: string;
|
|
186
203
|
catalog: string;
|
|
187
204
|
catalogStats: string;
|
|
205
|
+
/** The shelf's order control, and the date each card carries under the two
|
|
206
|
+
* date orders (design 2026-10-12-shelf-orders §4). */
|
|
207
|
+
sortLabel: string;
|
|
208
|
+
sortStars: string;
|
|
209
|
+
sortAdded: string;
|
|
210
|
+
sortUpdated: string;
|
|
211
|
+
listedOn: string;
|
|
212
|
+
updatedOn: string;
|
|
188
213
|
stars: string;
|
|
189
214
|
categoryTool: string;
|
|
190
215
|
categoryProvider: string;
|
|
@@ -259,6 +284,9 @@ export declare const en: {
|
|
|
259
284
|
nameTakenDetail: string;
|
|
260
285
|
npmSource: string;
|
|
261
286
|
githubSource: string;
|
|
287
|
+
npmVersionLabel: string;
|
|
288
|
+
commitVersionLabel: string;
|
|
289
|
+
releaseVersionLabel: string;
|
|
262
290
|
shadowedBadge: string;
|
|
263
291
|
shadowedDetail: string;
|
|
264
292
|
updatableSection: string;
|
|
@@ -134,10 +134,13 @@ export declare function readsIncompatible(blockers: readonly {
|
|
|
134
134
|
*
|
|
135
135
|
* The second is the one harness reason that blocks (design
|
|
136
136
|
* 2026-09-26-dsh-017-readiness, B1, amending "warn, never block"): dsh 0.1.7
|
|
137
|
-
* refuses the install itself, before pnpm runs
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
137
|
+
* refuses the install itself, an npm entry before pnpm runs and a github
|
|
138
|
+
* entry after it, rolling the profile back, and the shop cannot install past
|
|
139
|
+
* it. The verdict is dsh's own rule on the profile's own exemptions, whichever
|
|
140
|
+
* channel the entry comes from (design
|
|
141
|
+
* 2026-09-28-bundle-components-and-github-peers, section 7.3), so a disabled
|
|
142
|
+
* button is dsh's answer given early, never the shop's opinion — and
|
|
143
|
+
* recording the exemption the card shows is what enables it again.
|
|
141
144
|
*/
|
|
142
145
|
export declare function refusesInstall(blockers: readonly {
|
|
143
146
|
kind: BlockerKind;
|
|
@@ -174,16 +177,47 @@ export declare const ACKNOWLEDGEMENT_ZH = "\u5B89\u88C5\u540E\uFF0C\u6B64\u63D2\
|
|
|
174
177
|
/** Install rejection code → locale key, for the rejected-state code label
|
|
175
178
|
* (§7.2): every rejection the host can return has a human label here. */
|
|
176
179
|
export declare function rejectionCodeKey(code: InstallRejectionCode): ShopLocaleKey;
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
/** What a shelf version string is (market borrowings §11): a version npm
|
|
181
|
+
* serves, or the spec a profile manifest holds for one; the commit a github
|
|
182
|
+
* entry is pinned to; or the tag of the release a rescued github entry
|
|
183
|
+
* installs from. */
|
|
184
|
+
export type VersionKind = 'npm' | 'commit' | 'release';
|
|
185
|
+
export interface VersionLabel {
|
|
186
|
+
kind: VersionKind;
|
|
187
|
+
/** What the shelf prints: `v1.2.3`, `4da5ae8`, `v0.29.10`. */
|
|
188
|
+
text: string;
|
|
189
|
+
/** What the accessible name and the tooltip print after the kind's word:
|
|
190
|
+
* the same string without the `v` the shelf adds to an npm version. */
|
|
191
|
+
value: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* How a version string reads on the shelf, decided by its source and its
|
|
195
|
+
* shape alone (market borrowings §11).
|
|
196
|
+
*
|
|
197
|
+
* Shape, never the entry's `tarball`, because an installed row carries only
|
|
198
|
+
* the pin the shop recorded at install — the catalog `version` of that moment
|
|
199
|
+
* — and no `tarball`. The registry pins a commit as forty lowercase hex and a
|
|
200
|
+
* release by its tag, so the two shapes do not cross; `present.test.ts`
|
|
201
|
+
* checks that against the committed live catalog.
|
|
202
|
+
*
|
|
203
|
+
* - An npm version takes the `v` the shelf has always shown, and only before
|
|
204
|
+
* a digit: an installed row reports the manifest's spec, and a range there
|
|
205
|
+
* (`^1.2.3`) is not a version to prefix.
|
|
206
|
+
* - A commit is cut to the seven characters git abbreviates to, with no `v`:
|
|
207
|
+
* it is not a version number.
|
|
208
|
+
* - A release tag prints exactly as tagged, never cut and never prefixed:
|
|
209
|
+
* cutting `v0.29.10` to seven characters printed `v0.29.1`, another
|
|
210
|
+
* version, and the `v` this function no longer adds doubled the tag's own.
|
|
211
|
+
*/
|
|
212
|
+
export declare function versionLabel(source: 'npm' | 'github', version: string): VersionLabel;
|
|
213
|
+
/** The copy that names a version's kind, for the accessible name and the
|
|
214
|
+
* tooltip; its `{version}` takes {@link VersionLabel.value}. */
|
|
215
|
+
export declare function versionLabelKey(kind: VersionKind): ShopLocaleKey;
|
|
182
216
|
/** The hash pin a stale line names for a repo or release-rescued entry — the
|
|
183
217
|
* reviewed commit, or the reviewed release tarball sha256 (market borrowings
|
|
184
|
-
* §3.1). Shortened to 7 chars like the card
|
|
185
|
-
* hand-built fixture carrying no pin. The npm form is a version
|
|
186
|
-
*
|
|
218
|
+
* §3.1). Shortened to 7 chars like a commit on the card; '' only for a
|
|
219
|
+
* hand-built fixture carrying no pin. The npm form is a version, which
|
|
220
|
+
* {@link versionLabel} prints instead. */
|
|
187
221
|
export declare function reviewHashPin(review: NonNullable<CatalogEntry['review']>): string;
|
|
188
222
|
/**
|
|
189
223
|
* Whether the license value is the npm idiom `SEE LICENSE IN <file>` — a
|
|
@@ -321,6 +355,25 @@ export declare function nextVisibleCount(visible: number, total: number, batch:
|
|
|
321
355
|
* view is tracking — a status for an install it never started (idle) is an
|
|
322
356
|
* unrelated event and a no-op, like any other event it does not recognize. */
|
|
323
357
|
export declare function reduceInstall(state: InstallView, event: InstallEvent): InstallView;
|
|
358
|
+
/**
|
|
359
|
+
* Which order the shelf is in (design 2026-10-12-shelf-orders). `stars` is
|
|
360
|
+
* the default AND the tie-break of both date orders, so the two date orders
|
|
361
|
+
* are stable re-sorts of it rather than orders with comparators of their own.
|
|
362
|
+
*/
|
|
363
|
+
declare const SHELF_ORDER_KEYS: {
|
|
364
|
+
readonly stars: "sortStars";
|
|
365
|
+
readonly added: "sortAdded";
|
|
366
|
+
readonly updated: "sortUpdated";
|
|
367
|
+
};
|
|
368
|
+
/** The order vocabulary as a type, derived from the map above so the client
|
|
369
|
+
* never repeats the three literals. */
|
|
370
|
+
export type ShelfOrder = keyof typeof SHELF_ORDER_KEYS;
|
|
371
|
+
/** The three orders in display order (map insertion order). `readonly`: this
|
|
372
|
+
* is a shared vocabulary, and an order list a caller can push to is a bug
|
|
373
|
+
* waiting for its second caller. */
|
|
374
|
+
export declare const SHELF_ORDERS: readonly ShelfOrder[];
|
|
375
|
+
/** The locale key naming one order (the toggle's buttons). */
|
|
376
|
+
export declare function shelfOrderLocaleKey(order: ShelfOrder): ShopLocaleKey;
|
|
324
377
|
declare const CATEGORY_KEYS: {
|
|
325
378
|
readonly tool: "categoryTool";
|
|
326
379
|
readonly provider: "categoryProvider";
|
|
@@ -427,6 +480,31 @@ export declare function starsOf(entry: CatalogEntry, stars: Record<string, numbe
|
|
|
427
480
|
* (case-insensitive) on ties (spec 2026-08-26-github-stars-design.md D1).
|
|
428
481
|
* Display-time only — the catalog's own name sort is untouched. */
|
|
429
482
|
export declare function sortByStars(entries: CatalogEntry[], stars: Record<string, number>): CatalogEntry[];
|
|
483
|
+
/**
|
|
484
|
+
* The entry's sort key under a date order, or undefined when it has no usable
|
|
485
|
+
* date (design §3): absent, off-form, unparseable, or later than the catalog's
|
|
486
|
+
* own `builtAt`. Milliseconds since the epoch. `'stars'` carries no date, so
|
|
487
|
+
* this answers undefined for it.
|
|
488
|
+
*/
|
|
489
|
+
export declare function shelfTime(entry: CatalogEntry, order: ShelfOrder, builtAt: string): number | undefined;
|
|
490
|
+
/**
|
|
491
|
+
* A UTC calendar day for display: "2026-10-12". Derived from the instant the
|
|
492
|
+
* sort ranked by, so a card's label and its position cannot disagree. UTC and
|
|
493
|
+
* never a local getter: a reader in UTC+8 must see the same days the catalog
|
|
494
|
+
* was built in, the calendar the stats row already prints.
|
|
495
|
+
*/
|
|
496
|
+
export declare function utcDay(ms: number): string;
|
|
497
|
+
/**
|
|
498
|
+
* The shelf in `order` (design 2026-10-12-shelf-orders §2, §5). `'stars'`
|
|
499
|
+
* returns the array it was handed, so the default path allocates nothing and
|
|
500
|
+
* does not invalidate the memos downstream of it.
|
|
501
|
+
*
|
|
502
|
+
* Each key is computed ONCE per entry rather than inside the comparator, and
|
|
503
|
+
* the sort is stable (ES2019), so entries sharing a date keep the star order
|
|
504
|
+
* they arrived in — which is how the tie-break is defined without a second
|
|
505
|
+
* comparator that could drift from `sortByStars`.
|
|
506
|
+
*/
|
|
507
|
+
export declare function orderShelf(starOrdered: readonly CatalogEntry[], order: ShelfOrder, builtAt: string): readonly CatalogEntry[];
|
|
430
508
|
/** 999 → "999"; 1000 → "1k"; 1234 → "1.2k"; 1500 → "1.5k"; 99999 → "100k". */
|
|
431
509
|
export declare function formatStars(n: number): string;
|
|
432
510
|
/**
|
|
@@ -181,20 +181,35 @@ export declare function compatibilityMap(entries: readonly (EntryIdentity & {
|
|
|
181
181
|
* could not tell".
|
|
182
182
|
*
|
|
183
183
|
* The rule is dsh's own (`check`, from the running app-boot), handed the
|
|
184
|
-
* manifest dsh's installer
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* silence, never toward a refusal dsh would not make: a malformed peer range
|
|
189
|
-
* elsewhere in the manifest, which dsh rejects only after installing, and
|
|
190
|
-
* the plugins a bundle's patch rows name, which it checks then too. Those
|
|
191
|
-
* reach the reader as the install's own failure (`installFailureDetail`).
|
|
184
|
+
* manifest dsh's installer judges (`ownManifest`): the name and version dsh
|
|
185
|
+
* keys an exemption by, with the catalog's `dshPeers` for the peers. Those
|
|
186
|
+
* are the only peers the rule reads, verbatim. Both channels are judged, each
|
|
187
|
+
* by the manifest dsh reads for it:
|
|
192
188
|
*
|
|
193
|
-
* npm
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
189
|
+
* - An npm entry by its catalog `version`. dsh reads that manifest before it
|
|
190
|
+
* installs a registry spec: `pnpm view <spec> name version
|
|
191
|
+
* peerDependencies`, measured in dsh-plugin-manager 0.1.7-rc.2.
|
|
192
|
+
* - A github entry by `manifestVersion`, the version of the manifest dsh
|
|
193
|
+
* installs: at the pinned commit (a subpackage's own), or in the release
|
|
194
|
+
* asset a rescued entry installs from. dsh skips a git or tarball spec
|
|
195
|
+
* before pnpm and judges the installed manifest after it, rolling the
|
|
196
|
+
* install back on a refusal (the same dsh-plugin-manager). The entry's
|
|
197
|
+
* catalog `version` is a commit or a tag, so without `manifestVersion` it
|
|
198
|
+
* is not judged at all: judged by its commit instead, it would miss an
|
|
199
|
+
* exemption the profile holds under its real `name@version`, disabling an
|
|
200
|
+
* install dsh accepts, and could offer no command, since `allow-version`
|
|
201
|
+
* records no commit (design 2026-09-28-bundle-components-and-github-peers,
|
|
202
|
+
* sections 6.1 and 7.3).
|
|
203
|
+
*
|
|
204
|
+
* dsh's key names no channel: an exemption recorded for one `name@version`
|
|
205
|
+
* clears every entry whose manifest carries it, npm or github, here as in
|
|
206
|
+
* dsh.
|
|
207
|
+
*
|
|
208
|
+
* What this cannot see errs toward silence, never toward a refusal dsh would
|
|
209
|
+
* not make: a malformed peer range elsewhere in the manifest, which dsh
|
|
210
|
+
* rejects only after installing, and the plugins a bundle's patch rows name,
|
|
211
|
+
* which it checks then too. Those reach the reader as the install's own
|
|
212
|
+
* failure (`installFailureDetail`).
|
|
198
213
|
*
|
|
199
214
|
* A throw from the check forms no verdict for that entry, as a resolver's
|
|
200
215
|
* throw does in `incompatibilityMap`.
|
|
@@ -202,6 +217,7 @@ export declare function compatibilityMap(entries: readonly (EntryIdentity & {
|
|
|
202
217
|
export declare function peerVerdictsOf(entries: readonly (EntryIdentity & {
|
|
203
218
|
version: string;
|
|
204
219
|
dshPeers?: Record<string, string>;
|
|
220
|
+
manifestVersion?: string;
|
|
205
221
|
})[], check: PeerCheck, exemptions: Record<string, string[]>, profile: string): Record<string, PeerVerdict>;
|
|
206
222
|
/**
|
|
207
223
|
* The command that records dsh's exact-version exemption for one refused
|
|
@@ -78,12 +78,26 @@ export interface CatalogEntry {
|
|
|
78
78
|
/** The package's peers on the harness itself (`@deepseek-ai/dsh` and
|
|
79
79
|
* `@deepseek-ai/dsh-*`) with their ranges verbatim, optional ones and empty
|
|
80
80
|
* ranges included — what dsh 0.1.7 refuses an install on. The host hands
|
|
81
|
-
* them to the running dsh's own check (`peerVerdictsOf`)
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
81
|
+
* them to the running dsh's own check (`peerVerdictsOf`) on both channels:
|
|
82
|
+
* an npm entry is judged by its catalog `version`, a github entry by
|
|
83
|
+
* {@link manifestVersion}, because dsh keys the exemption that clears its
|
|
84
|
+
* refusal by the installed manifest's version, which a github entry's
|
|
85
|
+
* catalog version is not (registry `Entry.dshPeers`; design
|
|
86
|
+
* 2026-09-28-bundle-components-and-github-peers, section 7.3). Absent when
|
|
87
|
+
* the package declares none, or when its catalog predates the field; on a
|
|
88
|
+
* github entry also when its manifest names no usable version, since both
|
|
89
|
+
* keys drop together, and until the registry re-reads its repository under
|
|
90
|
+
* the rule that records them. */
|
|
86
91
|
dshPeers?: Record<string, string>;
|
|
92
|
+
/** A github entry's installed manifest `version` (registry
|
|
93
|
+
* `Entry.manifestVersion`): the version dsh keys an exemption by, where the
|
|
94
|
+
* entry's catalog `version` is a commit or a release tag. Present exactly
|
|
95
|
+
* when a github entry's {@link dshPeers} is. An npm entry's own `version` is
|
|
96
|
+
* its manifest's, so `peerVerdictsOf` never reads this key on one, and a
|
|
97
|
+
* github entry without it is not judged at all (design
|
|
98
|
+
* 2026-09-28-bundle-components-and-github-peers, section 7.3). Absent when
|
|
99
|
+
* the catalog predates the field. */
|
|
100
|
+
manifestVersion?: string;
|
|
87
101
|
/** Wire-compatibility key, not a field to read — see {@link installSize},
|
|
88
102
|
* which the catalog parse fills from this one. It names npm's OWN quantity
|
|
89
103
|
* (`dist.unpackedSize`), so it is npm-only and the parse REFUSES one on a
|
|
@@ -113,6 +127,11 @@ export interface CatalogEntry {
|
|
|
113
127
|
* §1.3). github entries only, additive and optional: the shelf badges it
|
|
114
128
|
* and nothing else — install, update, and enable are unchanged. */
|
|
115
129
|
archived?: boolean;
|
|
130
|
+
/** Whether GitHub reports the repository as a fork (design 2026-10-11
|
|
131
|
+
* §1.1). github entries only, additive and optional, and informative:
|
|
132
|
+
* nothing reads it here yet — it is telemetry the catalog publishes, not a
|
|
133
|
+
* gate, a badge, or an install decision. */
|
|
134
|
+
forked?: boolean;
|
|
116
135
|
}
|
|
117
136
|
export interface DeniedEntry {
|
|
118
137
|
name: string;
|
package/package.json
CHANGED