dsh-graft-plugin 0.2.0 → 0.2.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 -0
- package/package.json +1 -1
- package/scripts/test-harness.mjs +36 -0
- package/src/client.js +16 -2
package/README.md
CHANGED
|
@@ -135,6 +135,7 @@ All optional, all on the plugin's row in your profile's `cordis.patch.yml`:
|
|
|
135
135
|
|---|---|
|
|
136
136
|
| `0.1.2-rc.1` – `0.1.0-rc.7` | tested, full feature set — the `graft viz` tab via `dsh-better-sidebar` |
|
|
137
137
|
| `0.1.5-rc.2` / `0.1.5` | tested — chip, tools, `/graft` and auto-rebuild all work; on `0.1.5` the `graft viz` button opens the graph in the built-in right sidebar |
|
|
138
|
+
| `0.2.0-rc.2` | needs plugin `0.2.1`+ — earlier releases fail to activate (see Troubleshooting) |
|
|
138
139
|
|
|
139
140
|
- Node 22+
|
|
140
141
|
- the `graft` CLI on PATH (`npm install -g @nanonets/graft`)
|
|
@@ -168,6 +169,8 @@ registering "dsh-graft-plugin" via __ModuleLoader__.load
|
|
|
168
169
|
|
|
169
170
|
**No chip appears and dsh started without errors.** The plugin is in the profile's `package.json` `dependencies` but not in `dsh.profile.bundles` — which happens under pnpm 10+ when the `add` ends non-zero on `ERR_PNPM_IGNORED_BUILDS`; dsh skips the bundle row in that case and starts up looking healthy. Fix: `pnpm approve-builds` in the profile directory (tick `dsh-graft-plugin`), then re-run `dsh plugin --profile web add dsh-graft-plugin`. If `pnpm approve-builds` reports nothing awaiting approval, check `pnpm-workspace.yaml` for an unanswered `dsh-graft-plugin` entry (pnpm's approval placeholder) and set its value to `true` first.
|
|
170
171
|
|
|
172
|
+
**On dsh 0.2 the plugin fails to load with `strict codec has no create() factory`, and dsh offers to remove it.** dsh 0.2 requires every strict remote codec to carry a `create()` schema factory; plugin releases before `0.2.1` only had the 0.1 `schema` key. Update to `0.2.1` or later, which carries both and so loads on 0.1 and 0.2.
|
|
173
|
+
|
|
171
174
|
**`/graft` says the graft CLI is not on PATH.** The postinstall was blocked or skipped (see Install): `npm install -g @nanonets/graft`.
|
|
172
175
|
|
|
173
176
|
## Licence
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-graft-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shows which graft index a dsh session is serving and whether it still matches the code, and gives the model graft_ask, graft_grep, graft_callers, graft_skeleton and graft_map as native tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/scripts/test-harness.mjs
CHANGED
|
@@ -256,6 +256,42 @@ check('that dependency is soft too', clientSource.includes('ctx.inject(["sidebar
|
|
|
256
256
|
check('the body reads the session from either host', clientSource.includes('props?.sessionId ?? props?.scope?.sessionId'))
|
|
257
257
|
check('the browser tab survives only as the last resort', clientSource.includes('neither sidebar'))
|
|
258
258
|
|
|
259
|
+
// The remote descriptors must survive dsh 0.2's typert codec validation, which
|
|
260
|
+
// runs inside `ctx.remote.$mount`: a strict codec needs a typeSymbol and a
|
|
261
|
+
// `create()` factory returning a schema with `parse`. The 0.1 shape (`schema`
|
|
262
|
+
// only) threw "strict codec has no create() factory", rejected apply(), and
|
|
263
|
+
// took the whole plugin down. The client may only use strict codecs for
|
|
264
|
+
// parameters. The descriptor block is lifted out of client.js and evaluated,
|
|
265
|
+
// so this tests the shipped objects, not a copy.
|
|
266
|
+
console.log('\nremote descriptors (dsh 0.2 codec contract)')
|
|
267
|
+
const descriptorBlock = /function identity\(value\) \{[\s\S]*?\r?\n const CONTRIBUTION = \{[\s\S]*?\r?\n \};/.exec(clientSource)?.[0]
|
|
268
|
+
check('descriptor block found in client.js', descriptorBlock !== undefined)
|
|
269
|
+
const CONTRIBUTION = descriptorBlock ? new Function(`${descriptorBlock}; return CONTRIBUTION;`)() : { descriptors: [] }
|
|
270
|
+
function codecProblem(codec, { parameter }) {
|
|
271
|
+
if (!codec || typeof codec !== 'object') return 'missing codec'
|
|
272
|
+
if (codec.mode === 'src-json') return parameter ? 'client parameters must be strict' : undefined
|
|
273
|
+
if (codec.mode !== 'strict') return `unknown mode ${codec.mode}`
|
|
274
|
+
if (typeof codec.typeSymbol !== 'string' || codec.typeSymbol === '') return 'empty typeSymbol'
|
|
275
|
+
if (typeof codec.create !== 'function') return 'strict codec has no create() factory'
|
|
276
|
+
const schema = codec.create()
|
|
277
|
+
if (typeof schema?.parse !== 'function') return 'create() returned no parse()'
|
|
278
|
+
if (codec.create() !== schema) return 'create() is not memoized'
|
|
279
|
+
// dsh 0.1 read `schema` directly; keep it so older hosts still load.
|
|
280
|
+
if (typeof codec.schema?.parse !== 'function') return 'no 0.1 schema fallback'
|
|
281
|
+
return undefined
|
|
282
|
+
}
|
|
283
|
+
check('declares the status and viz descriptors', CONTRIBUTION.descriptors.map((d) => d.method).join() === 'status,viz')
|
|
284
|
+
for (const d of CONTRIBUTION.descriptors) {
|
|
285
|
+
for (const p of d.parameters) {
|
|
286
|
+
const problem = codecProblem(p.codec, { parameter: true })
|
|
287
|
+
check(`${d.id} parameter ${p.name} codec is valid`, problem === undefined, problem)
|
|
288
|
+
}
|
|
289
|
+
const problem = codecProblem(d.result, { parameter: false })
|
|
290
|
+
check(`${d.id} result codec is valid`, problem === undefined, problem)
|
|
291
|
+
const sample = { ok: true, value: { root: '/r', nodeCount: 1 } }
|
|
292
|
+
check(`${d.id} result decodes as a pass-through`, d.result.create().parse(sample) === sample)
|
|
293
|
+
}
|
|
294
|
+
|
|
259
295
|
await rm(fixture, { recursive: true, force: true })
|
|
260
296
|
|
|
261
297
|
console.log(failures === 0 ? '\nALL CHECKS PASSED' : `\n${failures} CHECK(S) FAILED`)
|
package/src/client.js
CHANGED
|
@@ -50,7 +50,21 @@ window.__ModuleLoader__.load({
|
|
|
50
50
|
function identity(value) {
|
|
51
51
|
return value;
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
/*
|
|
54
|
+
* Pass-through codec carrying both codec shapes: dsh 0.2's typert
|
|
55
|
+
* validator requires a strict codec to expose a `create()` factory
|
|
56
|
+
* returning the schema (it throws "strict codec has no create() factory"
|
|
57
|
+
* otherwise, failing `$mount` and with it the whole plugin), while dsh 0.1
|
|
58
|
+
* read `schema` directly. The host still runs assertJsonValue on every
|
|
59
|
+
* decoded value, so identity is safe.
|
|
60
|
+
*/
|
|
61
|
+
const IDENTITY_SCHEMA = { parse: identity };
|
|
62
|
+
const CODEC = {
|
|
63
|
+
mode: "strict",
|
|
64
|
+
typeSymbol: "graft-status/json",
|
|
65
|
+
schema: IDENTITY_SCHEMA,
|
|
66
|
+
create: () => IDENTITY_SCHEMA,
|
|
67
|
+
};
|
|
54
68
|
const descriptor = (method, names) => ({
|
|
55
69
|
id: "graft-status#graftStatus/" + method,
|
|
56
70
|
service: "graftStatus",
|
|
@@ -58,7 +72,7 @@ window.__ModuleLoader__.load({
|
|
|
58
72
|
method,
|
|
59
73
|
invocation: { kind: "direct" },
|
|
60
74
|
parameters: names.map((name) => ({ name, wire: name, source: "json", codec: CODEC })),
|
|
61
|
-
result:
|
|
75
|
+
result: CODEC,
|
|
62
76
|
sourceLocation: { file: "graft-status/client.js", line: 1, column: 1 },
|
|
63
77
|
});
|
|
64
78
|
const CONTRIBUTION = {
|