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
|
@@ -6,8 +6,10 @@ export declare const zh: {
|
|
|
6
6
|
error: string;
|
|
7
7
|
retry: string;
|
|
8
8
|
search: string;
|
|
9
|
+
all: string;
|
|
9
10
|
catalog: string;
|
|
10
11
|
catalogStats: string;
|
|
12
|
+
stars: string;
|
|
11
13
|
categoryTool: string;
|
|
12
14
|
categoryProvider: string;
|
|
13
15
|
categoryUi: string;
|
|
@@ -46,6 +48,12 @@ export declare const zh: {
|
|
|
46
48
|
installedVersion: string;
|
|
47
49
|
latestVersion: string;
|
|
48
50
|
update: string;
|
|
51
|
+
installed: string;
|
|
52
|
+
uninstall: string;
|
|
53
|
+
uninstalling: string;
|
|
54
|
+
uninstallFailed: string;
|
|
55
|
+
uninstallTransportFailed: string;
|
|
56
|
+
uninstalledRestartNotice: string;
|
|
49
57
|
enabledSwitch: string;
|
|
50
58
|
toggleFailed: string;
|
|
51
59
|
hotApplyNote: string;
|
|
@@ -59,8 +67,10 @@ export declare const en: {
|
|
|
59
67
|
error: string;
|
|
60
68
|
retry: string;
|
|
61
69
|
search: string;
|
|
70
|
+
all: string;
|
|
62
71
|
catalog: string;
|
|
63
72
|
catalogStats: string;
|
|
73
|
+
stars: string;
|
|
64
74
|
categoryTool: string;
|
|
65
75
|
categoryProvider: string;
|
|
66
76
|
categoryUi: string;
|
|
@@ -99,6 +109,12 @@ export declare const en: {
|
|
|
99
109
|
installedVersion: string;
|
|
100
110
|
latestVersion: string;
|
|
101
111
|
update: string;
|
|
112
|
+
installed: string;
|
|
113
|
+
uninstall: string;
|
|
114
|
+
uninstalling: string;
|
|
115
|
+
uninstallFailed: string;
|
|
116
|
+
uninstallTransportFailed: string;
|
|
117
|
+
uninstalledRestartNotice: string;
|
|
102
118
|
enabledSwitch: string;
|
|
103
119
|
toggleFailed: string;
|
|
104
120
|
hotApplyNote: string;
|
|
@@ -81,6 +81,28 @@ export declare function reduceInstall(state: InstallView, event: InstallEvent):
|
|
|
81
81
|
* it matches other people's package names, not ours.
|
|
82
82
|
*/
|
|
83
83
|
export declare function isShopLike(name: string): boolean;
|
|
84
|
+
declare const CATEGORY_KEYS: {
|
|
85
|
+
readonly tool: "categoryTool";
|
|
86
|
+
readonly provider: "categoryProvider";
|
|
87
|
+
readonly ui: "categoryUi";
|
|
88
|
+
readonly workflow: "categoryWorkflow";
|
|
89
|
+
readonly integration: "categoryIntegration";
|
|
90
|
+
readonly other: "categoryOther";
|
|
91
|
+
};
|
|
84
92
|
/** The locale key for one entry's category — derived entries read as `other`
|
|
85
93
|
* (§6.1: a derived listing has no declared category). */
|
|
86
94
|
export declare function categoryKey(entry: CatalogEntry): ShopLocaleKey;
|
|
95
|
+
/** The category vocabulary as a type, derived from the map above so the
|
|
96
|
+
* client never repeats the six literals. */
|
|
97
|
+
export type Category = keyof typeof CATEGORY_KEYS;
|
|
98
|
+
/** The six categories in display order (map insertion order). */
|
|
99
|
+
export declare const CATEGORY_ORDER: Category[];
|
|
100
|
+
/** The locale key for one bare category value (the filter buttons). */
|
|
101
|
+
export declare function categoryLocaleKey(category: Category): ShopLocaleKey;
|
|
102
|
+
/** Sort the shelf: stars descending, un-starred entries last, name ascending
|
|
103
|
+
* (case-insensitive) on ties (spec 2026-08-26-github-stars-design.md D1).
|
|
104
|
+
* Display-time only — the catalog's own name sort is untouched. */
|
|
105
|
+
export declare function sortByStars(entries: CatalogEntry[], stars: Record<string, number>): CatalogEntry[];
|
|
106
|
+
/** 999 → "999"; 1000 → "1k"; 1234 → "1.2k"; 1500 → "1.5k"; 99999 → "100k". */
|
|
107
|
+
export declare function formatStars(n: number): string;
|
|
108
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Install driving hook for one entry: start, poll to terminal, reset. */
|
|
2
|
+
import { type Dispatch, type SetStateAction } from 'react';
|
|
2
3
|
import { type InstallView } from './present.ts';
|
|
3
4
|
import type { InstallArgs, ShopInstallResult, ShopInstallStatusResult } from '../host/index.ts';
|
|
4
5
|
export interface UseInstallResult {
|
|
@@ -6,6 +7,14 @@ export interface UseInstallResult {
|
|
|
6
7
|
start: (args: InstallArgs) => Promise<void>;
|
|
7
8
|
reset: () => void;
|
|
8
9
|
}
|
|
10
|
+
/** The poll loop shared by the install and uninstall drivers: while the view
|
|
11
|
+
* is `running`, poll once per second and fold each status through the
|
|
12
|
+
* reducer. A poll failure is transient — the host retains the record, so the
|
|
13
|
+
* next tick finds it. The rejection handler must be present: an unhandled
|
|
14
|
+
* rejection here would escape the poll loop. */
|
|
15
|
+
export declare function usePollStatus(view: InstallView, setView: Dispatch<SetStateAction<InstallView>>, installStatus: (args: {
|
|
16
|
+
installId: string;
|
|
17
|
+
}) => Promise<ShopInstallStatusResult>): void;
|
|
9
18
|
/** Drive one install: rejections, the polling loop at INSTALL_POLL_MS, and
|
|
10
19
|
* terminal states. The interval is cleared on unmount and whenever the view
|
|
11
20
|
* leaves `running`, so a done/failed/rejected install never polls again. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Uninstall driving hook for one entry: start, poll to terminal. Shares the
|
|
2
|
+
* install view machine and poll loop; the only difference is the start
|
|
3
|
+
* mapping — an uninstall business failure (not in the catalog / not
|
|
4
|
+
* installed) lands in the `failed` view with the host's published detail,
|
|
5
|
+
* never in the install `rejected` codes, which belong to the install gate
|
|
6
|
+
* (§7.2). */
|
|
7
|
+
import type { ShopInstallStatusResult, ShopUninstallResult } from '../host/index.ts';
|
|
8
|
+
import type { InstallView } from './present.ts';
|
|
9
|
+
export interface UseUninstallResult {
|
|
10
|
+
view: InstallView;
|
|
11
|
+
start: (args: {
|
|
12
|
+
name: string;
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/** Drive one uninstall: the host's business union, the shared polling loop,
|
|
16
|
+
* and terminal states. The `rejected` install state never occurs here. */
|
|
17
|
+
export declare function useUninstall(uninstall: (args: {
|
|
18
|
+
name: string;
|
|
19
|
+
}) => Promise<ShopUninstallResult>, installStatus: (args: {
|
|
20
|
+
installId: string;
|
|
21
|
+
}) => Promise<ShopInstallStatusResult>): UseUninstallResult;
|
|
@@ -7,6 +7,9 @@ export interface CatalogSnapshot {
|
|
|
7
7
|
builtAt: string;
|
|
8
8
|
entries: CatalogEntry[];
|
|
9
9
|
denied: DeniedEntry[];
|
|
10
|
+
/** GitHub star counts by package name; {} when the pointer names no
|
|
11
|
+
* sidecar or the sidecar could not be fetched/verified (spec §5). */
|
|
12
|
+
stars: Record<string, number>;
|
|
10
13
|
}
|
|
11
14
|
export interface CatalogResult {
|
|
12
15
|
snapshot: CatalogSnapshot;
|
|
@@ -32,6 +35,8 @@ export interface LoadCatalogOptions {
|
|
|
32
35
|
* only when the transport itself failed — the fetch threw or returned a
|
|
33
36
|
* non-2xx (§10). A schemaVersion higher than this build supports, a malformed
|
|
34
37
|
* pointer or data file, an absolute data URL, or a sha256 mismatch — fresh or
|
|
35
|
-
* cached — throws even when a cache exists; never silently degraded.
|
|
38
|
+
* cached — throws even when a cache exists; never silently degraded. The stars
|
|
39
|
+
* sidecar is the sole exception: any irregularity there, a refused url
|
|
40
|
+
* included, degrades to no stars (spec §5).
|
|
36
41
|
*/
|
|
37
42
|
export declare function loadCatalog(options: LoadCatalogOptions): Promise<CatalogResult>;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Plugin-command executor: spawn the dsh CLI, stream its output, serialize
|
|
2
|
+
* per profile. One implementation drives both `dsh plugin add` (install) and
|
|
3
|
+
* `dsh plugin remove` (uninstall); the only differences are the verb and the
|
|
4
|
+
* post-exit manifest confirmation. */
|
|
2
5
|
export type InstallState = 'running' | 'done' | 'failed';
|
|
3
6
|
export interface InstallStatus {
|
|
4
7
|
state: InstallState;
|
|
@@ -13,11 +16,6 @@ interface RunningInstall {
|
|
|
13
16
|
}
|
|
14
17
|
/**
|
|
15
18
|
* Run one `dsh plugin --profile <profile> add <spec>` and track it.
|
|
16
|
-
* Never rolls back; a failure surfaces stderr verbatim plus the recovery hint
|
|
17
|
-
* (§10). The shop never passes build-script flags: `allowBuilds` stays the
|
|
18
|
-
* user's explicit decision in the CLI (§7.2).
|
|
19
|
-
* The child inherits the current environment unless `env` is given — the
|
|
20
|
-
* real-install test pins DSH_HOME to a temporary directory this way.
|
|
21
19
|
* When `expectedName` is given, a zero exit is confirmed against the profile
|
|
22
20
|
* manifest (§7.2 step 6) before the install reports `done`.
|
|
23
21
|
*/
|
|
@@ -29,4 +27,18 @@ export declare function startInstall(options: {
|
|
|
29
27
|
expectedName?: string;
|
|
30
28
|
onStatus?: (status: InstallStatus) => void;
|
|
31
29
|
}): RunningInstall;
|
|
30
|
+
/**
|
|
31
|
+
* Run one `dsh plugin --profile <profile> remove <name>` and track it.
|
|
32
|
+
* When `expectedName` is given, a zero exit is confirmed against the profile
|
|
33
|
+
* manifest — the bundle must actually have LEFT `dsh.profile.bundles` — before
|
|
34
|
+
* the uninstall reports `done`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function startUninstall(options: {
|
|
37
|
+
profile: string;
|
|
38
|
+
name: string;
|
|
39
|
+
dshBin?: string;
|
|
40
|
+
env?: NodeJS.ProcessEnv;
|
|
41
|
+
expectedName?: string;
|
|
42
|
+
onStatus?: (status: InstallStatus) => void;
|
|
43
|
+
}): RunningInstall;
|
|
32
44
|
export {};
|
|
@@ -49,11 +49,25 @@ export interface ShopSetEnabledResult {
|
|
|
49
49
|
ok: boolean;
|
|
50
50
|
detail?: string;
|
|
51
51
|
}
|
|
52
|
-
/** `shop/
|
|
53
|
-
|
|
52
|
+
/** `shop/uninstallStart` result (§7.3): a name outside the catalog or not
|
|
53
|
+
* installed is a typed wire value with an author-readable `detail`, not a
|
|
54
|
+
* thrown RPC error. */
|
|
55
|
+
export type ShopUninstallResult = {
|
|
56
|
+
ok: true;
|
|
57
|
+
installId: string;
|
|
58
|
+
} | {
|
|
59
|
+
ok: false;
|
|
60
|
+
detail: string;
|
|
61
|
+
};
|
|
62
|
+
/** `shop/installed` entry (§7.3): one installed catalog plugin. `installed`
|
|
63
|
+
* is the profile manifest's dependency spec verbatim (a range, a tag, or
|
|
64
|
+
* `workspace:*`); `outdated` is the Host's verdict that the installed version
|
|
65
|
+
* sits behind the catalog's — the client never does version math. */
|
|
66
|
+
export interface ShopInstalledEntry {
|
|
54
67
|
name: string;
|
|
55
68
|
installed: string;
|
|
56
69
|
latest: string;
|
|
70
|
+
outdated: boolean;
|
|
57
71
|
}
|
|
58
72
|
/** `shop/catalog` result (§7.3), plus the denied list for the install gate's UI. */
|
|
59
73
|
export interface ShopCatalogResult {
|
|
@@ -62,6 +76,9 @@ export interface ShopCatalogResult {
|
|
|
62
76
|
stale: boolean;
|
|
63
77
|
plugins: CatalogEntry[];
|
|
64
78
|
denied: DeniedEntry[];
|
|
79
|
+
/** GitHub star counts by package name; {} when the pointer names no sidecar
|
|
80
|
+
* or the sidecar could not be fetched/verified (§5). */
|
|
81
|
+
stars: Record<string, number>;
|
|
65
82
|
}
|
|
66
83
|
/** Remote-only service exposing the shop Remote methods of §7.3.
|
|
67
84
|
*
|
|
@@ -124,7 +141,24 @@ export declare class ShopGateway extends TypertRemoteService {
|
|
|
124
141
|
installStatus(args: {
|
|
125
142
|
installId: string;
|
|
126
143
|
}): ShopInstallStatusResult;
|
|
127
|
-
/** Installed plugins
|
|
128
|
-
|
|
144
|
+
/** Installed catalog plugins (§7.3): every entry of the snapshot the profile
|
|
145
|
+
* manifest declares as a dependency, with the Host's `outdated` verdict
|
|
146
|
+
* attached. The tab's shelf cards and its installed section both derive
|
|
147
|
+
* from this one list. */
|
|
148
|
+
installed(): Promise<ShopInstalledEntry[]>;
|
|
149
|
+
/** Whether an installed dependency spec sits behind the catalog's version.
|
|
150
|
+
* A spec identical to the catalog version is current by definition; a
|
|
151
|
+
* pnpm-written non-semver spec like `workspace:*` is not reportable and
|
|
152
|
+
* reads as current rather than killing the RPC. */
|
|
153
|
+
private isBehind;
|
|
154
|
+
/** Uninstall one installed catalog plugin from the profile (§7.3 follow-up
|
|
155
|
+
* amendment). Removing revokes privilege rather than granting it, so there
|
|
156
|
+
* is no acknowledgement gate. The name must be a catalog entry the profile
|
|
157
|
+
* manifest declares as a dependency — the RPC cannot remove profile
|
|
158
|
+
* dependencies the shop does not manage (the base bundle, the shop
|
|
159
|
+
* itself). The same install records/polling serve the client. */
|
|
160
|
+
uninstall(args: {
|
|
161
|
+
name: string;
|
|
162
|
+
}): Promise<ShopUninstallResult>;
|
|
129
163
|
}
|
|
130
164
|
export default ShopGateway;
|
package/package.json
CHANGED