dsh-plugin-shop 0.4.0 → 0.4.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 -3
- package/lib/client.js +348 -60
- package/lib/index.js +144 -36
- package/lib/typert.host.js +76 -28
- package/lib/typert.remote-client.d.ts +5 -3
- package/lib/typert.remote-client.js +57 -20
- package/lib/types/client/ShopTab.d.ts +5 -2
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/locales.d.ts +16 -0
- package/lib/types/client/present.d.ts +22 -0
- package/lib/types/client/useInstall.d.ts +9 -0
- package/lib/types/client/useUninstall.d.ts +21 -0
- package/lib/types/host/catalog.d.ts +6 -1
- package/lib/types/host/executor.d.ts +18 -6
- package/lib/types/host/index.d.ts +38 -4
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -256,7 +256,10 @@ function validateInstall(snapshot, args) {
|
|
|
256
256
|
}
|
|
257
257
|
//#endregion
|
|
258
258
|
//#region src/host/executor.ts
|
|
259
|
-
/**
|
|
259
|
+
/** Plugin-command executor: spawn the dsh CLI, stream its output, serialize
|
|
260
|
+
* per profile. One implementation drives both `dsh plugin add` (install) and
|
|
261
|
+
* `dsh plugin remove` (uninstall); the only differences are the verb and the
|
|
262
|
+
* post-exit manifest confirmation. */
|
|
260
263
|
const MAX_LOG_LINES = 200;
|
|
261
264
|
const MAX_LOG_BYTES = 65536;
|
|
262
265
|
const profileQueues = /* @__PURE__ */ new Map();
|
|
@@ -265,8 +268,7 @@ function chain(profile, task) {
|
|
|
265
268
|
profileQueues.set(profile, next.catch(() => {}));
|
|
266
269
|
return next;
|
|
267
270
|
}
|
|
268
|
-
/**
|
|
269
|
-
* The §7.2 step-6 confirm: after a zero exit, re-read the profile manifest and
|
|
271
|
+
/** The §7.2 step-6 confirm: after a zero exit, re-read the profile manifest and
|
|
270
272
|
* verify the bundle actually landed in `dsh.profile.bundles`. Exit 0 alone is
|
|
271
273
|
* not success — a library-that-looked-like-a-plugin, or a stale catalog,
|
|
272
274
|
* exits 0 while changing nothing (§10). The shop cannot force a client
|
|
@@ -285,18 +287,31 @@ function confirmBundleActivation(profile, home, expectedName) {
|
|
|
285
287
|
return `installed but the profile manifest could not be read (${join(profileDir, "package.json")}) — the catalog may be stale; refresh it`;
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
|
-
/**
|
|
289
|
-
*
|
|
290
|
+
/** The uninstall mirror of §7.2 step 6: after a zero exit, re-read the profile
|
|
291
|
+
* manifest and verify the bundle actually left `dsh.profile.bundles`. A zero
|
|
292
|
+
* exit that changed nothing must not read as success. */
|
|
293
|
+
function confirmBundleRemoval(profile, home, expectedName) {
|
|
294
|
+
const profileDir = resolveProfileDir(profile, home);
|
|
295
|
+
try {
|
|
296
|
+
if (!readProfileManifest("dsh-plugin-shop", profileDir).dsh?.profile?.bundles?.includes(expectedName)) return null;
|
|
297
|
+
return "removed but dsh.profile.bundles did not change — re-run the uninstall";
|
|
298
|
+
} catch {
|
|
299
|
+
return `removed but the profile manifest could not be read (${join(profileDir, "package.json")}) — re-run the uninstall`;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/** Run one `dsh plugin --profile <profile> <verb> <target>` and track it.
|
|
290
303
|
* Never rolls back; a failure surfaces stderr verbatim plus the recovery hint
|
|
291
304
|
* (§10). The shop never passes build-script flags: `allowBuilds` stays the
|
|
292
305
|
* user's explicit decision in the CLI (§7.2).
|
|
293
306
|
* The child inherits the current environment unless `env` is given — the
|
|
294
307
|
* real-install test pins DSH_HOME to a temporary directory this way.
|
|
295
|
-
* When `
|
|
296
|
-
* manifest (§7.2 step 6
|
|
297
|
-
*/
|
|
298
|
-
function
|
|
299
|
-
const { profile,
|
|
308
|
+
* When `confirm` is given, a zero exit is checked against the profile
|
|
309
|
+
* manifest before the command reports `done` (§7.2 step 6 and its uninstall
|
|
310
|
+
* mirror). */
|
|
311
|
+
function spawnPluginCli(options) {
|
|
312
|
+
const { profile, argv, dshBin, env, confirm, onStatus } = options;
|
|
313
|
+
const target = argv[1];
|
|
314
|
+
if (target === void 0 || target.startsWith("-")) throw new Error(`dsh-plugin-shop: refusing to spawn with a flag-like operand: ${target ?? "(none)"}`);
|
|
300
315
|
const installId = randomUUID();
|
|
301
316
|
const log = [];
|
|
302
317
|
let logBytes = 0;
|
|
@@ -325,8 +340,7 @@ function startInstall(options) {
|
|
|
325
340
|
"plugin",
|
|
326
341
|
"--profile",
|
|
327
342
|
profile,
|
|
328
|
-
|
|
329
|
-
spec
|
|
343
|
+
...argv
|
|
330
344
|
], {
|
|
331
345
|
stdio: [
|
|
332
346
|
"ignore",
|
|
@@ -352,8 +366,8 @@ function startInstall(options) {
|
|
|
352
366
|
if (state !== "running") return;
|
|
353
367
|
if (exitCode === 0) {
|
|
354
368
|
state = "done";
|
|
355
|
-
if (
|
|
356
|
-
const confirmDetail =
|
|
369
|
+
if (confirm !== void 0) {
|
|
370
|
+
const confirmDetail = confirm(env?.DSH_HOME);
|
|
357
371
|
if (confirmDetail !== null) {
|
|
358
372
|
state = "failed";
|
|
359
373
|
detail = confirmDetail;
|
|
@@ -370,6 +384,39 @@ function startInstall(options) {
|
|
|
370
384
|
}))
|
|
371
385
|
};
|
|
372
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Run one `dsh plugin --profile <profile> add <spec>` and track it.
|
|
389
|
+
* When `expectedName` is given, a zero exit is confirmed against the profile
|
|
390
|
+
* manifest (§7.2 step 6) before the install reports `done`.
|
|
391
|
+
*/
|
|
392
|
+
function startInstall(options) {
|
|
393
|
+
const { profile, spec, dshBin = "dsh", env, expectedName, onStatus } = options;
|
|
394
|
+
return spawnPluginCli({
|
|
395
|
+
profile,
|
|
396
|
+
argv: ["add", spec],
|
|
397
|
+
dshBin,
|
|
398
|
+
env,
|
|
399
|
+
confirm: expectedName !== void 0 ? (home) => confirmBundleActivation(profile, home, expectedName) : void 0,
|
|
400
|
+
onStatus
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Run one `dsh plugin --profile <profile> remove <name>` and track it.
|
|
405
|
+
* When `expectedName` is given, a zero exit is confirmed against the profile
|
|
406
|
+
* manifest — the bundle must actually have LEFT `dsh.profile.bundles` — before
|
|
407
|
+
* the uninstall reports `done`.
|
|
408
|
+
*/
|
|
409
|
+
function startUninstall(options) {
|
|
410
|
+
const { profile, name, dshBin = "dsh", env, expectedName, onStatus } = options;
|
|
411
|
+
return spawnPluginCli({
|
|
412
|
+
profile,
|
|
413
|
+
argv: ["remove", name],
|
|
414
|
+
dshBin,
|
|
415
|
+
env,
|
|
416
|
+
confirm: expectedName !== void 0 ? (home) => confirmBundleRemoval(profile, home, expectedName) : void 0,
|
|
417
|
+
onStatus
|
|
418
|
+
});
|
|
419
|
+
}
|
|
373
420
|
//#endregion
|
|
374
421
|
//#region src/host/profile.ts
|
|
375
422
|
/** Profile directory discovery and user-layer writes (§8: hot enable/disable). */
|
|
@@ -494,7 +541,8 @@ let ShopGateway = (() => {
|
|
|
494
541
|
let _catalog_decorators;
|
|
495
542
|
let _install_decorators;
|
|
496
543
|
let _installStatus_decorators;
|
|
497
|
-
let
|
|
544
|
+
let _installed_decorators;
|
|
545
|
+
let _uninstall_decorators;
|
|
498
546
|
return class ShopGateway extends _classSuper {
|
|
499
547
|
static {
|
|
500
548
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
@@ -502,7 +550,8 @@ let ShopGateway = (() => {
|
|
|
502
550
|
_catalog_decorators = [Remote("catalog")];
|
|
503
551
|
_install_decorators = [Remote("installStart")];
|
|
504
552
|
_installStatus_decorators = [Remote("installStatus")];
|
|
505
|
-
|
|
553
|
+
_installed_decorators = [Remote("installed")];
|
|
554
|
+
_uninstall_decorators = [Remote("uninstallStart")];
|
|
506
555
|
__esDecorate(this, null, _setEnabled_decorators, {
|
|
507
556
|
kind: "method",
|
|
508
557
|
name: "setEnabled",
|
|
@@ -547,14 +596,25 @@ let ShopGateway = (() => {
|
|
|
547
596
|
},
|
|
548
597
|
metadata: _metadata
|
|
549
598
|
}, null, _instanceExtraInitializers);
|
|
550
|
-
__esDecorate(this, null,
|
|
599
|
+
__esDecorate(this, null, _installed_decorators, {
|
|
551
600
|
kind: "method",
|
|
552
|
-
name: "
|
|
601
|
+
name: "installed",
|
|
553
602
|
static: false,
|
|
554
603
|
private: false,
|
|
555
604
|
access: {
|
|
556
|
-
has: (obj) => "
|
|
557
|
-
get: (obj) => obj.
|
|
605
|
+
has: (obj) => "installed" in obj,
|
|
606
|
+
get: (obj) => obj.installed
|
|
607
|
+
},
|
|
608
|
+
metadata: _metadata
|
|
609
|
+
}, null, _instanceExtraInitializers);
|
|
610
|
+
__esDecorate(this, null, _uninstall_decorators, {
|
|
611
|
+
kind: "method",
|
|
612
|
+
name: "uninstall",
|
|
613
|
+
static: false,
|
|
614
|
+
private: false,
|
|
615
|
+
access: {
|
|
616
|
+
has: (obj) => "uninstall" in obj,
|
|
617
|
+
get: (obj) => obj.uninstall
|
|
558
618
|
},
|
|
559
619
|
metadata: _metadata
|
|
560
620
|
}, null, _instanceExtraInitializers);
|
|
@@ -727,8 +787,11 @@ let ShopGateway = (() => {
|
|
|
727
787
|
...running.status()
|
|
728
788
|
};
|
|
729
789
|
}
|
|
730
|
-
/** Installed plugins
|
|
731
|
-
|
|
790
|
+
/** Installed catalog plugins (§7.3): every entry of the snapshot the profile
|
|
791
|
+
* manifest declares as a dependency, with the Host's `outdated` verdict
|
|
792
|
+
* attached. The tab's shelf cards and its installed section both derive
|
|
793
|
+
* from this one list. */
|
|
794
|
+
async installed() {
|
|
732
795
|
if (this.lastSnapshot === null) {
|
|
733
796
|
const { catalogUrl, cacheDir } = this.rowConfig();
|
|
734
797
|
const { snapshot } = await (this.options.loadCatalog ?? loadCatalog)({
|
|
@@ -738,24 +801,69 @@ let ShopGateway = (() => {
|
|
|
738
801
|
this.lastSnapshot = snapshot;
|
|
739
802
|
}
|
|
740
803
|
const dependencies = readProfileManifest("dsh-plugin-shop", this.profileDirResolved()).dependencies ?? {};
|
|
741
|
-
const
|
|
804
|
+
const installed = [];
|
|
742
805
|
for (const entry of this.lastSnapshot.entries) {
|
|
743
|
-
const
|
|
744
|
-
if (
|
|
745
|
-
|
|
746
|
-
if (installed === entry.version) floor = installed;
|
|
747
|
-
else try {
|
|
748
|
-
floor = minVersion(installed)?.version ?? null;
|
|
749
|
-
} catch {
|
|
750
|
-
floor = null;
|
|
751
|
-
}
|
|
752
|
-
if (floor !== null && lt(floor, entry.version)) outdated.push({
|
|
806
|
+
const spec = dependencies[entry.name];
|
|
807
|
+
if (spec === void 0) continue;
|
|
808
|
+
installed.push({
|
|
753
809
|
name: entry.name,
|
|
754
|
-
installed,
|
|
755
|
-
latest: entry.version
|
|
810
|
+
installed: spec,
|
|
811
|
+
latest: entry.version,
|
|
812
|
+
outdated: this.isBehind(spec, entry.version)
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
return installed;
|
|
816
|
+
}
|
|
817
|
+
/** Whether an installed dependency spec sits behind the catalog's version.
|
|
818
|
+
* A spec identical to the catalog version is current by definition; a
|
|
819
|
+
* pnpm-written non-semver spec like `workspace:*` is not reportable and
|
|
820
|
+
* reads as current rather than killing the RPC. */
|
|
821
|
+
isBehind(spec, latest) {
|
|
822
|
+
if (spec === latest) return false;
|
|
823
|
+
let floor;
|
|
824
|
+
try {
|
|
825
|
+
floor = minVersion(spec)?.version ?? null;
|
|
826
|
+
} catch {
|
|
827
|
+
floor = null;
|
|
828
|
+
}
|
|
829
|
+
return floor !== null && lt(floor, latest);
|
|
830
|
+
}
|
|
831
|
+
/** Uninstall one installed catalog plugin from the profile (§7.3 follow-up
|
|
832
|
+
* amendment). Removing revokes privilege rather than granting it, so there
|
|
833
|
+
* is no acknowledgement gate. The name must be a catalog entry the profile
|
|
834
|
+
* manifest declares as a dependency — the RPC cannot remove profile
|
|
835
|
+
* dependencies the shop does not manage (the base bundle, the shop
|
|
836
|
+
* itself). The same install records/polling serve the client. */
|
|
837
|
+
async uninstall(args) {
|
|
838
|
+
if (this.lastSnapshot === null) {
|
|
839
|
+
const { catalogUrl, cacheDir } = this.rowConfig();
|
|
840
|
+
const { snapshot } = await (this.options.loadCatalog ?? loadCatalog)({
|
|
841
|
+
baseUrl: catalogUrl,
|
|
842
|
+
cacheDir
|
|
756
843
|
});
|
|
844
|
+
this.lastSnapshot = snapshot;
|
|
757
845
|
}
|
|
758
|
-
return
|
|
846
|
+
if (!this.lastSnapshot.entries.some((entry) => entry.name === args.name)) return {
|
|
847
|
+
ok: false,
|
|
848
|
+
detail: `dsh-plugin-shop: ${args.name} is not in the catalog`
|
|
849
|
+
};
|
|
850
|
+
if ((readProfileManifest("dsh-plugin-shop", this.profileDirResolved()).dependencies ?? {})[args.name] === void 0) return {
|
|
851
|
+
ok: false,
|
|
852
|
+
detail: `dsh-plugin-shop: ${args.name} is not installed`
|
|
853
|
+
};
|
|
854
|
+
const running = startUninstall({
|
|
855
|
+
profile: this.profile,
|
|
856
|
+
name: args.name,
|
|
857
|
+
dshBin: this.dshBin,
|
|
858
|
+
expectedName: args.name
|
|
859
|
+
});
|
|
860
|
+
this.installs.set(running.installId, running);
|
|
861
|
+
this.installOrder.push(running.installId);
|
|
862
|
+
this.evictFinishedInstalls();
|
|
863
|
+
return {
|
|
864
|
+
ok: true,
|
|
865
|
+
installId: running.installId
|
|
866
|
+
};
|
|
759
867
|
}
|
|
760
868
|
};
|
|
761
869
|
})();
|
package/lib/typert.host.js
CHANGED
|
@@ -38,6 +38,12 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
|
|
|
38
38
|
})),
|
|
39
39
|
'stars': z.record(z.string(), z.number()),
|
|
40
40
|
})
|
|
41
|
+
const dsh_plugin_shop_shop_installed_result$schema = z.array(z.object({
|
|
42
|
+
'name': z.string(),
|
|
43
|
+
'installed': z.string(),
|
|
44
|
+
'latest': z.string(),
|
|
45
|
+
'outdated': z.boolean(),
|
|
46
|
+
}))
|
|
41
47
|
const dsh_plugin_shop_shop_installStart_parameter_0$schema = z.object({
|
|
42
48
|
'name': z.string(),
|
|
43
49
|
'version': z.string(),
|
|
@@ -61,11 +67,6 @@ const dsh_plugin_shop_shop_installStatus_result$schema = z.object({
|
|
|
61
67
|
'needsRestart': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
62
68
|
'detail': z.union([z.undefined(), z.string()]).optional(),
|
|
63
69
|
})
|
|
64
|
-
const dsh_plugin_shop_shop_outdated_result$schema = z.array(z.object({
|
|
65
|
-
'name': z.string(),
|
|
66
|
-
'installed': z.string(),
|
|
67
|
-
'latest': z.string(),
|
|
68
|
-
}))
|
|
69
70
|
const dsh_plugin_shop_shop_setEnabled_parameter_0$schema = z.object({
|
|
70
71
|
'name': z.string(),
|
|
71
72
|
'enabled': z.boolean(),
|
|
@@ -74,6 +75,16 @@ const dsh_plugin_shop_shop_setEnabled_result$schema = z.object({
|
|
|
74
75
|
'ok': z.boolean(),
|
|
75
76
|
'detail': z.union([z.undefined(), z.string()]).optional(),
|
|
76
77
|
})
|
|
78
|
+
const dsh_plugin_shop_shop_uninstallStart_parameter_0$schema = z.object({
|
|
79
|
+
'name': z.string(),
|
|
80
|
+
})
|
|
81
|
+
const dsh_plugin_shop_shop_uninstallStart_result$schema = z.union([z.object({
|
|
82
|
+
'ok': z.literal(true),
|
|
83
|
+
'installId': z.string(),
|
|
84
|
+
}), z.object({
|
|
85
|
+
'ok': z.literal(false),
|
|
86
|
+
'detail': z.string(),
|
|
87
|
+
})])
|
|
77
88
|
|
|
78
89
|
export const TYPERT = {
|
|
79
90
|
package: 'dsh-plugin-shop',
|
|
@@ -105,7 +116,22 @@ export const TYPERT = {
|
|
|
105
116
|
typeSymbol: 'dsh-plugin-shop/types#ShopCatalogResult',
|
|
106
117
|
schema: dsh_plugin_shop_shop_catalog_result$schema,
|
|
107
118
|
},
|
|
108
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
119
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":190,"column":9},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'dsh-plugin-shop#shop/installed',
|
|
123
|
+
service: 'shop',
|
|
124
|
+
namespace: 'shop',
|
|
125
|
+
method: 'installed',
|
|
126
|
+
invocation: { kind: 'direct' },
|
|
127
|
+
parameters: [
|
|
128
|
+
],
|
|
129
|
+
result: {
|
|
130
|
+
mode: 'strict',
|
|
131
|
+
typeSymbol: 'dsh-plugin-shop#shop/installed:result',
|
|
132
|
+
schema: dsh_plugin_shop_shop_installed_result$schema,
|
|
133
|
+
},
|
|
134
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":265,"column":9},
|
|
109
135
|
},
|
|
110
136
|
{
|
|
111
137
|
id: 'dsh-plugin-shop#shop/installStart',
|
|
@@ -131,7 +157,7 @@ export const TYPERT = {
|
|
|
131
157
|
typeSymbol: 'dsh-plugin-shop/types#ShopInstallResult',
|
|
132
158
|
schema: dsh_plugin_shop_shop_installStart_result$schema,
|
|
133
159
|
},
|
|
134
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
160
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":216,"column":9},
|
|
135
161
|
},
|
|
136
162
|
{
|
|
137
163
|
id: 'dsh-plugin-shop#shop/installStatus',
|
|
@@ -156,28 +182,39 @@ export const TYPERT = {
|
|
|
156
182
|
typeSymbol: 'dsh-plugin-shop/types#ShopInstallStatusResult',
|
|
157
183
|
schema: dsh_plugin_shop_shop_installStatus_result$schema,
|
|
158
184
|
},
|
|
159
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
185
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":254,"column":3},
|
|
160
186
|
},
|
|
161
187
|
{
|
|
162
|
-
id: 'dsh-plugin-shop#shop/
|
|
188
|
+
id: 'dsh-plugin-shop#shop/setEnabled',
|
|
163
189
|
service: 'shop',
|
|
164
190
|
namespace: 'shop',
|
|
165
|
-
method: '
|
|
191
|
+
method: 'setEnabled',
|
|
166
192
|
invocation: { kind: 'direct' },
|
|
167
193
|
parameters: [
|
|
194
|
+
{
|
|
195
|
+
name: 'args',
|
|
196
|
+
wire: 'args',
|
|
197
|
+
source: 'json',
|
|
198
|
+
codec: {
|
|
199
|
+
mode: 'strict',
|
|
200
|
+
typeSymbol: 'dsh-plugin-shop#shop/setEnabled:args',
|
|
201
|
+
schema: dsh_plugin_shop_shop_setEnabled_parameter_0$schema,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
168
204
|
],
|
|
169
205
|
result: {
|
|
170
206
|
mode: 'strict',
|
|
171
|
-
typeSymbol: 'dsh-plugin-shop#
|
|
172
|
-
schema:
|
|
207
|
+
typeSymbol: 'dsh-plugin-shop/types#ShopSetEnabledResult',
|
|
208
|
+
schema: dsh_plugin_shop_shop_setEnabled_result$schema,
|
|
173
209
|
},
|
|
174
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
210
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":159,"column":3},
|
|
175
211
|
},
|
|
176
212
|
{
|
|
177
|
-
id: 'dsh-plugin-shop#shop/
|
|
213
|
+
id: 'dsh-plugin-shop#shop/uninstallStart',
|
|
178
214
|
service: 'shop',
|
|
179
215
|
namespace: 'shop',
|
|
180
|
-
method: '
|
|
216
|
+
method: 'uninstallStart',
|
|
217
|
+
implementation: 'uninstall',
|
|
181
218
|
invocation: { kind: 'direct' },
|
|
182
219
|
parameters: [
|
|
183
220
|
{
|
|
@@ -186,17 +223,17 @@ export const TYPERT = {
|
|
|
186
223
|
source: 'json',
|
|
187
224
|
codec: {
|
|
188
225
|
mode: 'strict',
|
|
189
|
-
typeSymbol: 'dsh-plugin-shop#shop/
|
|
190
|
-
schema:
|
|
226
|
+
typeSymbol: 'dsh-plugin-shop#shop/uninstallStart:args',
|
|
227
|
+
schema: dsh_plugin_shop_shop_uninstallStart_parameter_0$schema,
|
|
191
228
|
},
|
|
192
229
|
},
|
|
193
230
|
],
|
|
194
231
|
result: {
|
|
195
232
|
mode: 'strict',
|
|
196
|
-
typeSymbol: 'dsh-plugin-shop/types#
|
|
197
|
-
schema:
|
|
233
|
+
typeSymbol: 'dsh-plugin-shop/types#ShopUninstallResult',
|
|
234
|
+
schema: dsh_plugin_shop_shop_uninstallStart_result$schema,
|
|
198
235
|
},
|
|
199
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
236
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":305,"column":9},
|
|
200
237
|
},
|
|
201
238
|
],
|
|
202
239
|
model: {
|
|
@@ -245,10 +282,17 @@ export const TYPERT = {
|
|
|
245
282
|
},
|
|
246
283
|
{
|
|
247
284
|
"kind": "method",
|
|
248
|
-
"name": "
|
|
249
|
-
"signature": "@Remote('
|
|
250
|
-
"summary": "Installed plugins
|
|
251
|
-
"jsDoc": "/** Installed plugins
|
|
285
|
+
"name": "installed",
|
|
286
|
+
"signature": "@Remote('installed') async installed(): Promise<ShopInstalledEntry[]>",
|
|
287
|
+
"summary": "Installed catalog plugins (§7.3): every entry of the snapshot the profile manifest declares as a dependency, with the Host's `outdated` verdict attached.",
|
|
288
|
+
"jsDoc": "/** Installed catalog plugins (§7.3): every entry of the snapshot the profile\n * manifest declares as a dependency, with the Host's `outdated` verdict\n * attached. The tab's shelf cards and its installed section both derive\n * from this one list. */"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"kind": "method",
|
|
292
|
+
"name": "uninstall",
|
|
293
|
+
"signature": "@Remote('uninstallStart') async uninstall(args: { name: string }): Promise<ShopUninstallResult>",
|
|
294
|
+
"summary": "Uninstall one installed catalog plugin from the profile (§7.3 follow-up amendment).",
|
|
295
|
+
"jsDoc": "/** Uninstall one installed catalog plugin from the profile (§7.3 follow-up\n * amendment). Removing revokes privilege rather than granting it, so there\n * is no acknowledgement gate. The name must be a catalog entry the profile\n * manifest declares as a dependency — the RPC cannot remove profile\n * dependencies the shop does not manage (the base bundle, the shop\n * itself). The same install records/polling serve the client. */"
|
|
252
296
|
}
|
|
253
297
|
],
|
|
254
298
|
"types": [
|
|
@@ -288,6 +332,10 @@ export const TYPERT = {
|
|
|
288
332
|
"name": "ShopCatalogResult",
|
|
289
333
|
"declaration": "export interface ShopCatalogResult {\n schemaVersion: number;\n builtAt: string;\n stale: boolean;\n plugins: CatalogEntry[];\n denied: DeniedEntry[];\n stars: Record<string, number>;\n}"
|
|
290
334
|
},
|
|
335
|
+
{
|
|
336
|
+
"name": "ShopInstalledEntry",
|
|
337
|
+
"declaration": "export interface ShopInstalledEntry {\n name: string;\n installed: string;\n latest: string;\n outdated: boolean;\n}"
|
|
338
|
+
},
|
|
291
339
|
{
|
|
292
340
|
"name": "ShopInstallResult",
|
|
293
341
|
"declaration": "export type ShopInstallResult = { ok: true; installId: string; } | { ok: false; code: InstallRejectionCode; detail: string; };"
|
|
@@ -296,13 +344,13 @@ export const TYPERT = {
|
|
|
296
344
|
"name": "ShopInstallStatusResult",
|
|
297
345
|
"declaration": "export interface ShopInstallStatusResult extends InstallStatus {\n found: boolean;\n}"
|
|
298
346
|
},
|
|
299
|
-
{
|
|
300
|
-
"name": "ShopOutdatedEntry",
|
|
301
|
-
"declaration": "export interface ShopOutdatedEntry {\n name: string;\n installed: string;\n latest: string;\n}"
|
|
302
|
-
},
|
|
303
347
|
{
|
|
304
348
|
"name": "ShopSetEnabledResult",
|
|
305
349
|
"declaration": "export interface ShopSetEnabledResult {\n ok: boolean;\n detail?: string;\n}"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"name": "ShopUninstallResult",
|
|
353
|
+
"declaration": "export type ShopUninstallResult = { ok: true; installId: string; } | { ok: false; detail: string; };"
|
|
306
354
|
}
|
|
307
355
|
]
|
|
308
356
|
}
|
|
@@ -3,22 +3,24 @@ import type {
|
|
|
3
3
|
RemoteResult,
|
|
4
4
|
TypertRemoteContribution,
|
|
5
5
|
} from '@deepseek-ai/dsh-typert-protocol'
|
|
6
|
-
import type { InstallArgs, ShopCatalogResult, ShopInstallResult, ShopInstallStatusResult,
|
|
6
|
+
import type { InstallArgs, ShopCatalogResult, ShopInstalledEntry, ShopInstallResult, ShopInstallStatusResult, ShopSetEnabledResult, ShopUninstallResult } from 'dsh-plugin-shop/types'
|
|
7
7
|
|
|
8
8
|
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
9
9
|
interface TypertRemoteNamespace$73686f70 {
|
|
10
10
|
catalog: (args?: { refresh?: boolean; }) => Promise<RemoteResult<ShopCatalogResult>>
|
|
11
|
+
installed: () => Promise<RemoteResult<ShopInstalledEntry[]>>
|
|
11
12
|
installStart: (args: InstallArgs) => Promise<RemoteResult<ShopInstallResult>>
|
|
12
13
|
installStatus: (args: { installId: string; }) => Promise<RemoteResult<ShopInstallStatusResult>>
|
|
13
|
-
outdated: () => Promise<RemoteResult<ShopOutdatedEntry[]>>
|
|
14
14
|
setEnabled: (args: { name: string; enabled: boolean; }) => Promise<RemoteResult<ShopSetEnabledResult>>
|
|
15
|
+
uninstallStart: (args: { name: string; }) => Promise<RemoteResult<ShopUninstallResult>>
|
|
15
16
|
}
|
|
16
17
|
interface TypertRemoteMap {
|
|
17
18
|
'shop/catalog': (args?: { refresh?: boolean; }) => Promise<RemoteResult<ShopCatalogResult>>
|
|
19
|
+
'shop/installed': () => Promise<RemoteResult<ShopInstalledEntry[]>>
|
|
18
20
|
'shop/installStart': (args: InstallArgs) => Promise<RemoteResult<ShopInstallResult>>
|
|
19
21
|
'shop/installStatus': (args: { installId: string; }) => Promise<RemoteResult<ShopInstallStatusResult>>
|
|
20
|
-
'shop/outdated': () => Promise<RemoteResult<ShopOutdatedEntry[]>>
|
|
21
22
|
'shop/setEnabled': (args: { name: string; enabled: boolean; }) => Promise<RemoteResult<ShopSetEnabledResult>>
|
|
23
|
+
'shop/uninstallStart': (args: { name: string; }) => Promise<RemoteResult<ShopUninstallResult>>
|
|
22
24
|
}
|
|
23
25
|
interface TypertRemoteNamespaceMap {
|
|
24
26
|
'shop': TypertRemoteNamespace$73686f70
|
|
@@ -38,6 +38,12 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
|
|
|
38
38
|
})),
|
|
39
39
|
'stars': z.record(z.string(), z.number()),
|
|
40
40
|
})
|
|
41
|
+
const dsh_plugin_shop_shop_installed_result$schema = z.array(z.object({
|
|
42
|
+
'name': z.string(),
|
|
43
|
+
'installed': z.string(),
|
|
44
|
+
'latest': z.string(),
|
|
45
|
+
'outdated': z.boolean(),
|
|
46
|
+
}))
|
|
41
47
|
const dsh_plugin_shop_shop_installStart_parameter_0$schema = z.object({
|
|
42
48
|
'name': z.string(),
|
|
43
49
|
'version': z.string(),
|
|
@@ -61,11 +67,6 @@ const dsh_plugin_shop_shop_installStatus_result$schema = z.object({
|
|
|
61
67
|
'needsRestart': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
|
|
62
68
|
'detail': z.union([z.undefined(), z.string()]).optional(),
|
|
63
69
|
})
|
|
64
|
-
const dsh_plugin_shop_shop_outdated_result$schema = z.array(z.object({
|
|
65
|
-
'name': z.string(),
|
|
66
|
-
'installed': z.string(),
|
|
67
|
-
'latest': z.string(),
|
|
68
|
-
}))
|
|
69
70
|
const dsh_plugin_shop_shop_setEnabled_parameter_0$schema = z.object({
|
|
70
71
|
'name': z.string(),
|
|
71
72
|
'enabled': z.boolean(),
|
|
@@ -74,6 +75,16 @@ const dsh_plugin_shop_shop_setEnabled_result$schema = z.object({
|
|
|
74
75
|
'ok': z.boolean(),
|
|
75
76
|
'detail': z.union([z.undefined(), z.string()]).optional(),
|
|
76
77
|
})
|
|
78
|
+
const dsh_plugin_shop_shop_uninstallStart_parameter_0$schema = z.object({
|
|
79
|
+
'name': z.string(),
|
|
80
|
+
})
|
|
81
|
+
const dsh_plugin_shop_shop_uninstallStart_result$schema = z.union([z.object({
|
|
82
|
+
'ok': z.literal(true),
|
|
83
|
+
'installId': z.string(),
|
|
84
|
+
}), z.object({
|
|
85
|
+
'ok': z.literal(false),
|
|
86
|
+
'detail': z.string(),
|
|
87
|
+
})])
|
|
77
88
|
|
|
78
89
|
export const TYPERT_REMOTE = {
|
|
79
90
|
package: 'dsh-plugin-shop',
|
|
@@ -102,7 +113,22 @@ export const TYPERT_REMOTE = {
|
|
|
102
113
|
typeSymbol: 'dsh-plugin-shop/types#ShopCatalogResult',
|
|
103
114
|
schema: dsh_plugin_shop_shop_catalog_result$schema,
|
|
104
115
|
},
|
|
105
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
116
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":190,"column":9},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'dsh-plugin-shop#shop/installed',
|
|
120
|
+
service: 'shop',
|
|
121
|
+
namespace: 'shop',
|
|
122
|
+
method: 'installed',
|
|
123
|
+
invocation: { kind: 'direct' },
|
|
124
|
+
parameters: [
|
|
125
|
+
],
|
|
126
|
+
result: {
|
|
127
|
+
mode: 'strict',
|
|
128
|
+
typeSymbol: 'dsh-plugin-shop#shop/installed:result',
|
|
129
|
+
schema: dsh_plugin_shop_shop_installed_result$schema,
|
|
130
|
+
},
|
|
131
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":265,"column":9},
|
|
106
132
|
},
|
|
107
133
|
{
|
|
108
134
|
id: 'dsh-plugin-shop#shop/installStart',
|
|
@@ -128,7 +154,7 @@ export const TYPERT_REMOTE = {
|
|
|
128
154
|
typeSymbol: 'dsh-plugin-shop/types#ShopInstallResult',
|
|
129
155
|
schema: dsh_plugin_shop_shop_installStart_result$schema,
|
|
130
156
|
},
|
|
131
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
157
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":216,"column":9},
|
|
132
158
|
},
|
|
133
159
|
{
|
|
134
160
|
id: 'dsh-plugin-shop#shop/installStatus',
|
|
@@ -153,28 +179,39 @@ export const TYPERT_REMOTE = {
|
|
|
153
179
|
typeSymbol: 'dsh-plugin-shop/types#ShopInstallStatusResult',
|
|
154
180
|
schema: dsh_plugin_shop_shop_installStatus_result$schema,
|
|
155
181
|
},
|
|
156
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
182
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":254,"column":3},
|
|
157
183
|
},
|
|
158
184
|
{
|
|
159
|
-
id: 'dsh-plugin-shop#shop/
|
|
185
|
+
id: 'dsh-plugin-shop#shop/setEnabled',
|
|
160
186
|
service: 'shop',
|
|
161
187
|
namespace: 'shop',
|
|
162
|
-
method: '
|
|
188
|
+
method: 'setEnabled',
|
|
163
189
|
invocation: { kind: 'direct' },
|
|
164
190
|
parameters: [
|
|
191
|
+
{
|
|
192
|
+
name: 'args',
|
|
193
|
+
wire: 'args',
|
|
194
|
+
source: 'json',
|
|
195
|
+
codec: {
|
|
196
|
+
mode: 'strict',
|
|
197
|
+
typeSymbol: 'dsh-plugin-shop#shop/setEnabled:args',
|
|
198
|
+
schema: dsh_plugin_shop_shop_setEnabled_parameter_0$schema,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
165
201
|
],
|
|
166
202
|
result: {
|
|
167
203
|
mode: 'strict',
|
|
168
|
-
typeSymbol: 'dsh-plugin-shop#
|
|
169
|
-
schema:
|
|
204
|
+
typeSymbol: 'dsh-plugin-shop/types#ShopSetEnabledResult',
|
|
205
|
+
schema: dsh_plugin_shop_shop_setEnabled_result$schema,
|
|
170
206
|
},
|
|
171
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
207
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":159,"column":3},
|
|
172
208
|
},
|
|
173
209
|
{
|
|
174
|
-
id: 'dsh-plugin-shop#shop/
|
|
210
|
+
id: 'dsh-plugin-shop#shop/uninstallStart',
|
|
175
211
|
service: 'shop',
|
|
176
212
|
namespace: 'shop',
|
|
177
|
-
method: '
|
|
213
|
+
method: 'uninstallStart',
|
|
214
|
+
implementation: 'uninstall',
|
|
178
215
|
invocation: { kind: 'direct' },
|
|
179
216
|
parameters: [
|
|
180
217
|
{
|
|
@@ -183,17 +220,17 @@ export const TYPERT_REMOTE = {
|
|
|
183
220
|
source: 'json',
|
|
184
221
|
codec: {
|
|
185
222
|
mode: 'strict',
|
|
186
|
-
typeSymbol: 'dsh-plugin-shop#shop/
|
|
187
|
-
schema:
|
|
223
|
+
typeSymbol: 'dsh-plugin-shop#shop/uninstallStart:args',
|
|
224
|
+
schema: dsh_plugin_shop_shop_uninstallStart_parameter_0$schema,
|
|
188
225
|
},
|
|
189
226
|
},
|
|
190
227
|
],
|
|
191
228
|
result: {
|
|
192
229
|
mode: 'strict',
|
|
193
|
-
typeSymbol: 'dsh-plugin-shop/types#
|
|
194
|
-
schema:
|
|
230
|
+
typeSymbol: 'dsh-plugin-shop/types#ShopUninstallResult',
|
|
231
|
+
schema: dsh_plugin_shop_shop_uninstallStart_result$schema,
|
|
195
232
|
},
|
|
196
|
-
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":
|
|
233
|
+
sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":305,"column":9},
|
|
197
234
|
},
|
|
198
235
|
],
|
|
199
236
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* §11.3.4): no render path here may ever use dangerouslySetInnerHTML. */
|
|
6
6
|
import { type ReactNode } from 'react';
|
|
7
7
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
8
|
-
import type { InstallArgs, ShopCatalogResult, ShopInstallResult, ShopInstallStatusResult,
|
|
8
|
+
import type { InstallArgs, ShopCatalogResult, ShopInstalledEntry, ShopInstallResult, ShopInstallStatusResult, ShopSetEnabledResult, ShopUninstallResult } from '../host/index.ts';
|
|
9
9
|
/** The tab's Remote face: the Host result types, already unwrapped from the
|
|
10
10
|
* wire envelope by `index.ts`; `catalog` throws on a wire error so the tab's
|
|
11
11
|
* error state renders. */
|
|
@@ -21,7 +21,10 @@ export interface ShopTabInjected {
|
|
|
21
21
|
name: string;
|
|
22
22
|
enabled: boolean;
|
|
23
23
|
}) => Promise<ShopSetEnabledResult>;
|
|
24
|
-
|
|
24
|
+
installed: () => Promise<ShopInstalledEntry[]>;
|
|
25
|
+
uninstall: (args: {
|
|
26
|
+
name: string;
|
|
27
|
+
}) => Promise<ShopUninstallResult>;
|
|
25
28
|
}
|
|
26
29
|
/** Full component props assembled by the Settings slot renderer. */
|
|
27
30
|
export type ShopTabProps = PropsRuntime<'settings.plugins.tab'> & PropsLocale<'settings.shop'> & InjectFace<ShopTabInjected>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shop settings surface, browser half — one tab in `settings.plugins.tab`
|
|
3
3
|
* that browses the catalog, installs with acknowledgement, toggles
|
|
4
|
-
* enablement, and lists
|
|
4
|
+
* enablement, and lists installed plugins. Mounts the shop Remote itself
|
|
5
5
|
* (the assembly does not know this package) and holds no privilege beyond
|
|
6
6
|
* the five `shop/*` methods (§5.3).
|
|
7
7
|
*/
|