dsh-plugin-toolkit 0.8.2 → 0.8.4
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/CHANGELOG.md +20 -0
- package/README.md +29 -2
- package/lib/cli.mjs +2 -1
- package/lib/doctor.mjs +10 -4
- package/lib/verify.mjs +41 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 0.8.4
|
|
2
|
+
|
|
3
|
+
- README: `## When the panel does not appear` — the five checks that explain a
|
|
4
|
+
successful install with nothing on screen (restart, root export, tarball,
|
|
5
|
+
patch row, a bundle that throws). Each one is a failure this tool has already
|
|
6
|
+
hit. A test keeps the section from losing a step.
|
|
7
|
+
- `doctor` table lists the new `root export` check; the verify example no longer
|
|
8
|
+
pins an old version in its own docs.
|
|
9
|
+
|
|
10
|
+
## 0.8.3
|
|
11
|
+
|
|
12
|
+
`verify` now imports the host half it just installed.
|
|
13
|
+
|
|
14
|
+
- After installing the tarball, `verify` imports the module the loader will
|
|
15
|
+
import (`exports["."]`, else `main`) and requires an `apply` function. A root
|
|
16
|
+
module that throws on import — which `doctor`'s static read cannot see — is
|
|
17
|
+
now a failure: `the installed index.js does not import: boom`.
|
|
18
|
+
- `--no-mount` skips the DOM, not the install, so the host half is checked in
|
|
19
|
+
both modes. The success line says which half ran.
|
|
20
|
+
|
|
1
21
|
## 0.8.2
|
|
2
22
|
|
|
3
23
|
`doctor` now refuses the failure that shipped in 0.8.0.
|
package/README.md
CHANGED
|
@@ -247,6 +247,7 @@ latest release.
|
|
|
247
247
|
| `patch file` | The path declared above must be a real file |
|
|
248
248
|
| `client entry` | If `dsh.client` is declared, the bundle has to be there |
|
|
249
249
|
| `files list` | Every path `package.json` points at (`exports`, patch, client) must be covered by `files` |
|
|
250
|
+
| `root export` | The loader imports the bare package name; if that module is the CLI (or exports no `apply`), the row mounts nothing while the install reports success |
|
|
250
251
|
|
|
251
252
|
Exit code is `0` when the plugin can be installed and `1` when it cannot, so it drops into CI unchanged.
|
|
252
253
|
|
|
@@ -255,7 +256,7 @@ Exit code is `0` when the plugin can be installed and `1` when it cannot, so it
|
|
|
255
256
|
`doctor` reads your working copy. Users install the tarball, and a `files` list can ship everything except the panel — `doctor` will not notice.
|
|
256
257
|
|
|
257
258
|
```sh
|
|
258
|
-
$ npx dsh-plugin-toolkit
|
|
259
|
+
$ npx dsh-plugin-toolkit verify .
|
|
259
260
|
ok packed 5 file(s), installed the tarball, mounted the panel
|
|
260
261
|
My panel This panel came from dsh-plugin init. Clicks: 0
|
|
261
262
|
```
|
|
@@ -263,11 +264,37 @@ ok packed 5 file(s), installed the tarball, mounted the panel
|
|
|
263
264
|
It packs, installs that tarball into a throwaway directory, then mounts the bundle **from the installed copy**. When the `files` list drops the panel:
|
|
264
265
|
|
|
265
266
|
```sh
|
|
266
|
-
$ npx dsh-plugin-toolkit
|
|
267
|
+
$ npx dsh-plugin-toolkit verify .
|
|
267
268
|
dsh-plugin verify: stopped at pack
|
|
268
269
|
✗ pack: the tarball does not contain client.js, so the installed plugin has no panel
|
|
269
270
|
```
|
|
270
271
|
|
|
272
|
+
## When the panel does not appear
|
|
273
|
+
|
|
274
|
+
The install reports success and nothing shows up. In this order:
|
|
275
|
+
|
|
276
|
+
1. **Did the host restart?** Client bundles are read at startup. `dsh plugin add`
|
|
277
|
+
writes the profile; the running window still has the old bundle.
|
|
278
|
+
2. **Is the root export the plugin?**
|
|
279
|
+
```sh
|
|
280
|
+
node -e "import('my-plugin').then((m) => console.log(typeof m.apply))"
|
|
281
|
+
```
|
|
282
|
+
`function` is what the loader needs. `undefined` means `exports["."]` points
|
|
283
|
+
at the CLI — `0.8.0` of this tool shipped exactly that.
|
|
284
|
+
3. **Does the tarball ship the panel?** `dsh-plugin verify .` installs what users
|
|
285
|
+
get and mounts it. `doctor` cannot see this.
|
|
286
|
+
4. **Is the patch row shaped right?** `cordis.patch.yml` needs one `- insert:`
|
|
287
|
+
entry with `id` and `name`:
|
|
288
|
+
```yaml
|
|
289
|
+
- insert:
|
|
290
|
+
- id: my-plugin
|
|
291
|
+
name: my-plugin
|
|
292
|
+
config: {}
|
|
293
|
+
```
|
|
294
|
+
5. **Did the client bundle throw?** The host logs the loader error with the
|
|
295
|
+
plugin id; a bundle that throws at factory time looks identical to one that
|
|
296
|
+
never loaded.
|
|
297
|
+
|
|
271
298
|
## What `release` does
|
|
272
299
|
|
|
273
300
|
`release` runs the sequence in the order that fails cheapest first:
|
package/lib/cli.mjs
CHANGED
|
@@ -108,7 +108,8 @@ export async function run(argv, io = console) {
|
|
|
108
108
|
if (command === 'verify') {
|
|
109
109
|
const result = await verify({ dir, mount: options.noMount !== true });
|
|
110
110
|
if (result.ok === true) {
|
|
111
|
-
|
|
111
|
+
const what = result.stage === 'mount' ? 'installed the tarball, mounted the panel' : 'installed the tarball and imported its host half';
|
|
112
|
+
io.log(`ok packed ${result.files.length} file(s), ${what}`);
|
|
112
113
|
if (typeof result.text === 'string') io.log(` ${result.text}`);
|
|
113
114
|
return 0;
|
|
114
115
|
}
|
package/lib/doctor.mjs
CHANGED
|
@@ -143,14 +143,20 @@ export function checkFilesList(manifest) {
|
|
|
143
143
|
* ships both a CLI and a panel is one `exports` edit away from having its root
|
|
144
144
|
* point at the CLI — the row then mounts nothing, and pnpm reports success.
|
|
145
145
|
*/
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
/** The module the loader imports when it starts the bare package name. */
|
|
147
|
+
export function rootEntry(manifest) {
|
|
148
148
|
const root = typeof manifest.exports === 'object' && manifest.exports !== null ? manifest.exports['.'] : undefined;
|
|
149
149
|
const entry = typeof root === 'string' ? root : manifest.main;
|
|
150
|
-
// A bundle that inserts a subpath plugin needs no root module at all.
|
|
151
150
|
if (typeof entry !== 'string') return null;
|
|
151
|
+
return entry.replace(/^\.\//, '');
|
|
152
|
+
}
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
export function checkRootExport(dir, manifest) {
|
|
155
|
+
if (manifest.dsh === undefined || manifest.dsh === null) return null;
|
|
156
|
+
const target = rootEntry(manifest);
|
|
157
|
+
// A bundle that inserts a subpath plugin needs no root module at all.
|
|
158
|
+
if (target === null) return null;
|
|
159
|
+
const entry = target;
|
|
154
160
|
const bins = Object.values(manifest.bin ?? {}).filter((value) => typeof value === 'string');
|
|
155
161
|
if (bins.some((bin) => bin.replace(/^\.\//, '') === target) === true) {
|
|
156
162
|
return `exports["."] points at the CLI (${entry}), so the loader's row has no plugin to apply; point it at the module that exports apply`;
|
package/lib/verify.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import path from 'node:path';
|
|
|
12
12
|
|
|
13
13
|
import { doctor, declaredPaths } from './doctor.mjs';
|
|
14
14
|
import { resolveEntry } from './dev.mjs';
|
|
15
|
+
import { rootEntry } from './doctor.mjs';
|
|
15
16
|
import { run } from './exec.mjs';
|
|
16
17
|
|
|
17
18
|
function packJson(dir) {
|
|
@@ -78,7 +79,6 @@ export async function verify({ dir, mount = true }) {
|
|
|
78
79
|
|
|
79
80
|
if (failures.length > 0) return { ok: false, stage: 'pack', failures, files: packed.files };
|
|
80
81
|
|
|
81
|
-
if (mount === false) return { ok: true, stage: 'pack', failures: [], files: packed.files, size: packed.size };
|
|
82
82
|
|
|
83
83
|
const scratch = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-plugin-verify-'));
|
|
84
84
|
let installed;
|
|
@@ -108,6 +108,46 @@ export async function verify({ dir, mount = true }) {
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
// The loader starts the host half by importing the bare package name. Doing
|
|
112
|
+
// the same import here is the only way to know the row will have an apply —
|
|
113
|
+
// 0.8.0 shipped a package whose root export was the CLI, installed cleanly,
|
|
114
|
+
// and mounted nothing.
|
|
115
|
+
const rootFile = rootEntry(report.manifest);
|
|
116
|
+
if (rootFile !== null) {
|
|
117
|
+
const absolute = path.join(installed, rootFile);
|
|
118
|
+
if (fs.existsSync(absolute) === false) {
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
stage: 'install',
|
|
122
|
+
failures: [{ check: 'root export', message: `the tarball does not ship ${rootFile}, which package.json points the loader at` }],
|
|
123
|
+
files: packed.files,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const { pathToFileURL } = await import('node:url');
|
|
128
|
+
const loaded = await import(pathToFileURL(absolute).href);
|
|
129
|
+
if (typeof loaded.apply !== 'function') {
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
stage: 'install',
|
|
133
|
+
failures: [{ check: 'root export', message: `the installed ${rootFile} exports no apply, so the loader's row mounts nothing` }],
|
|
134
|
+
files: packed.files,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
stage: 'install',
|
|
141
|
+
failures: [{ check: 'root export', message: `the installed ${rootFile} does not import: ${error.message}` }],
|
|
142
|
+
files: packed.files,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// `--no-mount` skips the DOM, not the install: the host half is the half
|
|
148
|
+
// that silently fails, and importing it needs nothing but Node.
|
|
149
|
+
if (mount === false) return { ok: true, stage: 'pack', failures: [], files: packed.files, size: packed.size };
|
|
150
|
+
|
|
111
151
|
// Same convention the host uses: dsh.client.entry, then client.js.
|
|
112
152
|
const entryFile = resolveEntry(installed, report.manifest);
|
|
113
153
|
if (entryFile !== null) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-toolkit",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "Preflight, release and test DeepSeek Harness plugins: checks what the host needs, waits for npm to actually serve the version, and keeps the market index honest.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|