@hoardodile/host 0.1.0 → 0.1.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/dist/index.d.ts +6 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/sandbox/fixtures/asset-plugin.mjs +8 -3
- package/src/sandbox/host.test.ts +26 -3
- package/src/sandbox/host.ts +15 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoardodile/host",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "hoardodile plugin runtime host: sandbox, hook strategy, ResourceAPI, containers and the test runner.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"file-type": "^22.0.2",
|
|
68
68
|
"yauzl": "^3.4.0",
|
|
69
69
|
"yazl": "^3.3.1",
|
|
70
|
-
"@hoardodile/sdk-types": "0.1.
|
|
70
|
+
"@hoardodile/sdk-types": "0.1.1"
|
|
71
71
|
},
|
|
72
72
|
"optionalDependencies": {
|
|
73
73
|
"@derhuerst/ffprobe-static": "^5.3.0",
|
|
74
|
-
"@hoardodile/7z-bin": "^1.1.
|
|
74
|
+
"@hoardodile/7z-bin": "^1.1.3",
|
|
75
75
|
"ffmpeg-static": "^5.3.0"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Sandbox fixture: exercises the plugin asset API within detect — reads
|
|
2
|
-
// the vault stat,
|
|
3
|
-
// the manifest permission gate and the wired
|
|
2
|
+
// the vault stat, performs a consent-gated single download and a batch
|
|
3
|
+
// download. Used to verify the manifest permission gate and the wired
|
|
4
|
+
// plugin asset handler (single in → single out, array in → array out).
|
|
4
5
|
export default {
|
|
5
6
|
detect: async (api) => {
|
|
6
7
|
const stat = await api.statAsset("runtime/a.mjs")
|
|
@@ -8,6 +9,10 @@ export default {
|
|
|
8
9
|
url: "https://example.com/runtime/a.mjs",
|
|
9
10
|
dest: "runtime/a.mjs",
|
|
10
11
|
})
|
|
11
|
-
|
|
12
|
+
const batched = await api.download([
|
|
13
|
+
{ url: "https://example.com/runtime/b.mjs", dest: "runtime/b.mjs" },
|
|
14
|
+
{ url: "https://example.com/runtime/c.mjs", dest: "runtime/c.mjs" },
|
|
15
|
+
])
|
|
16
|
+
return { ok: true, stat, downloaded, batched }
|
|
12
17
|
},
|
|
13
18
|
}
|
package/src/sandbox/host.test.ts
CHANGED
|
@@ -548,12 +548,13 @@ describe("plugin sandbox", () => {
|
|
|
548
548
|
pluginAssets: {
|
|
549
549
|
download: async (pluginId, request) => {
|
|
550
550
|
seen.push([pluginId, request])
|
|
551
|
-
|
|
552
|
-
|
|
551
|
+
const requests = Array.isArray(request) ? request : [request]
|
|
552
|
+
return requests.map((req) => ({
|
|
553
|
+
path: req.dest,
|
|
553
554
|
sizeBytes: 3,
|
|
554
555
|
sha256: "a".repeat(64),
|
|
555
556
|
cached: false,
|
|
556
|
-
}
|
|
557
|
+
}))
|
|
557
558
|
},
|
|
558
559
|
statAsset: async (pluginId, path) => {
|
|
559
560
|
seen.push([pluginId, path])
|
|
@@ -574,12 +575,27 @@ describe("plugin sandbox", () => {
|
|
|
574
575
|
await expect(plugin.detect(createStubApi())).resolves.toEqual({
|
|
575
576
|
ok: true,
|
|
576
577
|
stat: undefined,
|
|
578
|
+
// Single in → single result out, batch in → array out.
|
|
577
579
|
downloaded: {
|
|
578
580
|
path: "runtime/a.mjs",
|
|
579
581
|
sizeBytes: 3,
|
|
580
582
|
sha256: "a".repeat(64),
|
|
581
583
|
cached: false,
|
|
582
584
|
},
|
|
585
|
+
batched: [
|
|
586
|
+
{
|
|
587
|
+
path: "runtime/b.mjs",
|
|
588
|
+
sizeBytes: 3,
|
|
589
|
+
sha256: "a".repeat(64),
|
|
590
|
+
cached: false,
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
path: "runtime/c.mjs",
|
|
594
|
+
sizeBytes: 3,
|
|
595
|
+
sha256: "a".repeat(64),
|
|
596
|
+
cached: false,
|
|
597
|
+
},
|
|
598
|
+
],
|
|
583
599
|
})
|
|
584
600
|
expect(seen[0]).toEqual(["asset-allowed", "runtime/a.mjs"])
|
|
585
601
|
expect(seen[1]).toEqual([
|
|
@@ -589,6 +605,13 @@ describe("plugin sandbox", () => {
|
|
|
589
605
|
dest: "runtime/a.mjs",
|
|
590
606
|
},
|
|
591
607
|
])
|
|
608
|
+
expect(seen[2]).toEqual([
|
|
609
|
+
"asset-allowed",
|
|
610
|
+
[
|
|
611
|
+
{ url: "https://example.com/runtime/b.mjs", dest: "runtime/b.mjs" },
|
|
612
|
+
{ url: "https://example.com/runtime/c.mjs", dest: "runtime/c.mjs" },
|
|
613
|
+
],
|
|
614
|
+
])
|
|
592
615
|
})
|
|
593
616
|
|
|
594
617
|
test("a log flood exceeds the per-hook budget and fails the hook", async () => {
|
package/src/sandbox/host.ts
CHANGED
|
@@ -33,10 +33,15 @@ import { createSandboxedPlugin } from "./sandboxed-plugin.ts"
|
|
|
33
33
|
* workbench) omit it and the methods answer `UNAVAILABLE`.
|
|
34
34
|
*/
|
|
35
35
|
export type PluginAssetHandler = {
|
|
36
|
+
/**
|
|
37
|
+
* Download one request or a batch of requests. Answers with the
|
|
38
|
+
* result array (batch shape) — this adapter unwraps the single
|
|
39
|
+
* result for a single request (see {@link dispatchApi}).
|
|
40
|
+
*/
|
|
36
41
|
readonly download: (
|
|
37
42
|
pluginId: string,
|
|
38
|
-
request: PluginDownloadRequest,
|
|
39
|
-
) => Promise<PluginDownloadResult>
|
|
43
|
+
request: PluginDownloadRequest | readonly PluginDownloadRequest[],
|
|
44
|
+
) => Promise<readonly PluginDownloadResult[]>
|
|
40
45
|
readonly statAsset: (
|
|
41
46
|
pluginId: string,
|
|
42
47
|
path: string,
|
|
@@ -804,13 +809,15 @@ export function createPluginSandbox(
|
|
|
804
809
|
return
|
|
805
810
|
}
|
|
806
811
|
// RPC boundary: the child-side proxy forwards args verbatim,
|
|
807
|
-
// so the contract order is guaranteed (request object
|
|
808
|
-
// `download`, string path for the rest).
|
|
812
|
+
// so the contract order is guaranteed (request object or
|
|
813
|
+
// request array for `download`, string path for the rest).
|
|
809
814
|
if (method === "download") {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
)
|
|
815
|
+
const request = args[0] as
|
|
816
|
+
| PluginDownloadRequest
|
|
817
|
+
| readonly PluginDownloadRequest[]
|
|
818
|
+
const results = await handler.download(state.id, request)
|
|
819
|
+
// Wire rule: array in → array out, single in → single out.
|
|
820
|
+
respond(true, Array.isArray(request) ? results : results[0])
|
|
814
821
|
} else if (method === "statAsset") {
|
|
815
822
|
respond(true, await handler.statAsset(state.id, args[0] as string))
|
|
816
823
|
} else if (method === "readAsset") {
|