@hoardodile/host 0.1.0 → 0.1.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/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { I as ImageMetadataInput, b as ImageSourceProbe, A as AvProbeOptions, E
5
5
  import { R as ResourceContainer } from './container-fKxefO7p.js';
6
6
  import { P as PluginProbeCache } from './probe-cache-BkRI7HEK.js';
7
7
  export { a as PLUGIN_PROBE_CACHE_MAX_ENTRIES, c as createProbeCache } from './probe-cache-BkRI7HEK.js';
8
+ export { p as packZipDirectory } from './pack-6IscrwYN.js';
8
9
  import { PluginCapabilityKey } from '@hoardodile/sdk-types/plugin-capabilities';
9
10
  import 'sharp';
10
11
 
@@ -143,7 +144,12 @@ type PluginRegistry = {
143
144
  * workbench) omit it and the methods answer `UNAVAILABLE`.
144
145
  */
145
146
  type PluginAssetHandler = {
146
- readonly download: (pluginId: string, request: PluginDownloadRequest) => Promise<PluginDownloadResult>;
147
+ /**
148
+ * Download one request or a batch of requests. Answers with the
149
+ * result array (batch shape) — this adapter unwraps the single
150
+ * result for a single request (see {@link dispatchApi}).
151
+ */
152
+ readonly download: (pluginId: string, request: PluginDownloadRequest | readonly PluginDownloadRequest[]) => Promise<readonly PluginDownloadResult[]>;
147
153
  readonly statAsset: (pluginId: string, path: string) => Promise<{
148
154
  readonly sizeBytes: number;
149
155
  } | undefined>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createWriteStream, createReadStream, existsSync, readFileSync, renameSync, rmSync, mkdirSync, readdirSync, cpSync, statSync, realpathSync } from 'fs';
2
- import { dirname, isAbsolute, normalize, resolve, sep, join } from 'path';
2
+ import { dirname, resolve, sep, isAbsolute, normalize, join } from 'path';
3
3
  import { pluginAssetError, fileTypeFromName, createFailingPlugin, definePlugin } from '@hoardodile/sdk-types';
4
4
  export { HOOK_NAMES, assertPluginShape, createFailingPlugin, createResourceAPIFixture, definePlugin, isDetected, isMissed, stubLogger } from '@hoardodile/sdk-types';
5
5
  import { mimeToKind, MIME_FFMPEG_INPUT_FORMAT } from '@hoardodile/sdk-types/media-exts';
@@ -14,6 +14,7 @@ import { fork, spawn } from 'child_process';
14
14
  import { createRequire } from 'module';
15
15
  import { buffer } from 'stream/consumers';
16
16
  import { createInflateRaw } from 'zlib';
17
+ import yazl from 'yazl';
17
18
  import { CAPABILITY_BY_METHOD } from '@hoardodile/sdk-types/plugin-capabilities';
18
19
  import { pathToFileURL, fileURLToPath } from 'url';
19
20
  import { pluginManifest } from '@hoardodile/sdk-types/schema';
@@ -661,16 +662,16 @@ function parseSltListing(stdout, legacyNames) {
661
662
  }
662
663
  continue;
663
664
  }
664
- const sep4 = line.indexOf(" = ");
665
- if (sep4 < 0) continue;
666
- const key = line.slice(0, sep4);
665
+ const sep5 = line.indexOf(" = ");
666
+ if (sep5 < 0) continue;
667
+ const key = line.slice(0, sep5);
667
668
  if (key === "Path") {
668
- const raw = Buffer.from(line.slice(sep4 + 3), "latin1");
669
+ const raw = Buffer.from(line.slice(sep5 + 3), "latin1");
669
670
  const decoded = legacyNames ? decodeLegacyZipName(raw) : raw.toString("utf8");
670
671
  name = decoded.replace(/\\/g, "/");
671
672
  continue;
672
673
  }
673
- const value = line.slice(sep4 + 3);
674
+ const value = line.slice(sep5 + 3);
674
675
  switch (key) {
675
676
  case "Size":
676
677
  sizeBytes = Number.parseInt(value, 10) || 0;
@@ -916,11 +917,11 @@ var globalMaterializeInflight = /* @__PURE__ */ new Map();
916
917
  // src/archive/nested-entry.ts
917
918
  var VIRTUAL_PATH_SEPARATOR = "!";
918
919
  function splitVirtualPath(path) {
919
- const sep4 = path.indexOf(VIRTUAL_PATH_SEPARATOR);
920
- if (sep4 <= 0) return void 0;
921
- const inner = path.slice(sep4 + 1);
920
+ const sep5 = path.indexOf(VIRTUAL_PATH_SEPARATOR);
921
+ if (sep5 <= 0) return void 0;
922
+ const inner = path.slice(sep5 + 1);
922
923
  if (inner.length === 0) return void 0;
923
- return { outer: path.slice(0, sep4), inner };
924
+ return { outer: path.slice(0, sep5), inner };
924
925
  }
925
926
  function createOuterArchiveSource(outer, outerName, size) {
926
927
  return {
@@ -972,7 +973,7 @@ function createNestedResolver(outer, opts = {}) {
972
973
  zip: r
973
974
  }));
974
975
  }
975
- async function resolve5(path) {
976
+ async function resolve6(path) {
976
977
  const parts = splitVirtualPath(path);
977
978
  if (parts === void 0) return { kind: "literal" };
978
979
  const { outer: outerName, inner } = parts;
@@ -999,7 +1000,7 @@ function createNestedResolver(outer, opts = {}) {
999
1000
  );
1000
1001
  return work;
1001
1002
  }
1002
- return { resolve: resolve5, list };
1003
+ return { resolve: resolve6, list };
1003
1004
  }
1004
1005
  function listedWithStream(outer, outerName, entry) {
1005
1006
  return {
@@ -1321,13 +1322,40 @@ function createNestedCdCache(opts) {
1321
1322
  }
1322
1323
  return { get, set, clear };
1323
1324
  }
1325
+ async function packZipDirectory(srcDir, zipPath) {
1326
+ const root = resolve(srcDir);
1327
+ const files = listFilesSorted(root);
1328
+ const zip = new yazl.ZipFile();
1329
+ for (const abs of files) {
1330
+ const rel = abs.slice(root.length + 1).split(sep).join("/");
1331
+ zip.addFile(abs, rel, { compress: true });
1332
+ }
1333
+ zip.end();
1334
+ await pipeline(zip.outputStream, createWriteStream(resolve(zipPath)));
1335
+ }
1336
+ function listFilesSorted(root) {
1337
+ const out = [];
1338
+ const walk = (dir) => {
1339
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
1340
+ const abs = join(dir, entry.name);
1341
+ if (entry.isDirectory()) {
1342
+ walk(abs);
1343
+ continue;
1344
+ }
1345
+ if (!entry.isFile()) continue;
1346
+ out.push(abs);
1347
+ }
1348
+ };
1349
+ walk(root);
1350
+ return out.sort();
1351
+ }
1324
1352
  var PHASH_GRID = 32;
1325
1353
  var MIN_PERCEPTUAL_STDDEV = 8;
1326
1354
  function hashStream(stream, algo) {
1327
- return new Promise((resolve5, reject) => {
1355
+ return new Promise((resolve6, reject) => {
1328
1356
  const hash = createHash(algo);
1329
1357
  stream.on("data", (chunk) => hash.update(chunk));
1330
- stream.on("end", () => resolve5(hash.digest("hex")));
1358
+ stream.on("end", () => resolve6(hash.digest("hex")));
1331
1359
  stream.on("error", reject);
1332
1360
  });
1333
1361
  }
@@ -1456,14 +1484,14 @@ function createNestedAwareContainer(base, nestedCdCache, scope, extractCacheDir)
1456
1484
  sizeBytes: entry.sizeBytes
1457
1485
  };
1458
1486
  }
1459
- async function resolve5(rel) {
1487
+ async function resolve6(rel) {
1460
1488
  const nested = await resolver.resolve(rel);
1461
1489
  if (nested.kind === "container") return nested;
1462
1490
  const materialized = await resolveMaterialized(rel);
1463
1491
  return materialized ?? nested;
1464
1492
  }
1465
1493
  async function readEntrySlice(rel, start, end) {
1466
- const resolved = await resolve5(rel);
1494
+ const resolved = await resolve6(rel);
1467
1495
  if (resolved.kind === "literal") {
1468
1496
  return base.readEntrySlice(rel, start, end);
1469
1497
  }
@@ -1473,7 +1501,7 @@ function createNestedAwareContainer(base, nestedCdCache, scope, extractCacheDir)
1473
1501
  return readVirtualSlice(() => resolved.openStream(), start, end);
1474
1502
  }
1475
1503
  async function openEntryStream(rel) {
1476
- const resolved = await resolve5(rel);
1504
+ const resolved = await resolve6(rel);
1477
1505
  if (resolved.kind === "literal") {
1478
1506
  return base.openEntryStream(rel);
1479
1507
  }
@@ -1487,7 +1515,7 @@ function createNestedAwareContainer(base, nestedCdCache, scope, extractCacheDir)
1487
1515
  return { stream: resolved.openStream(), size: resolved.entry.sizeBytes };
1488
1516
  }
1489
1517
  async function readEntry(rel) {
1490
- const resolved = await resolve5(rel);
1518
+ const resolved = await resolve6(rel);
1491
1519
  if (resolved.kind === "literal") {
1492
1520
  return base.readEntry(rel);
1493
1521
  }
@@ -1497,7 +1525,7 @@ function createNestedAwareContainer(base, nestedCdCache, scope, extractCacheDir)
1497
1525
  return buffer(resolved.openStream());
1498
1526
  }
1499
1527
  async function resolveByteRange(rel) {
1500
- const resolved = await resolve5(rel);
1528
+ const resolved = await resolve6(rel);
1501
1529
  if (resolved.kind === "literal") {
1502
1530
  return base.resolveByteRange(rel);
1503
1531
  }
@@ -1507,7 +1535,7 @@ function createNestedAwareContainer(base, nestedCdCache, scope, extractCacheDir)
1507
1535
  return { size: resolved.entry.sizeBytes };
1508
1536
  }
1509
1537
  async function resolveSeekablePath(rel) {
1510
- const resolved = await resolve5(rel);
1538
+ const resolved = await resolve6(rel);
1511
1539
  if (resolved.kind === "literal") {
1512
1540
  return base.resolveSeekablePath?.(rel);
1513
1541
  }
@@ -3004,10 +3032,9 @@ function createPluginSandbox(config = DEFAULT_SANDBOX_CONFIG) {
3004
3032
  return;
3005
3033
  }
3006
3034
  if (method === "download") {
3007
- respond(
3008
- true,
3009
- await handler.download(state.id, args[0])
3010
- );
3035
+ const request = args[0];
3036
+ const results = await handler.download(state.id, request);
3037
+ respond(true, Array.isArray(request) ? results : results[0]);
3011
3038
  } else if (method === "statAsset") {
3012
3039
  respond(true, await handler.statAsset(state.id, args[0]));
3013
3040
  } else if (method === "readAsset") {
@@ -3306,6 +3333,6 @@ function createProbeCache(maxEntries = PLUGIN_PROBE_CACHE_MAX_ENTRIES) {
3306
3333
  };
3307
3334
  }
3308
3335
 
3309
- export { DEFAULT_PLUGIN_EXTRACT_MAX_BYTES, DEFAULT_PLUGIN_EXTRACT_MAX_ENTRIES, DEFAULT_SANDBOX_CONFIG, DomainError, MIN_PERCEPTUAL_STDDEV, PERCEPTUAL_HASH_KINDS, PHASH_GRID, PLUGIN_HOOK_HARD_TIMEOUT_MS, PLUGIN_MAX_API_CALLS_PER_HOOK, PLUGIN_MAX_LOGS_PER_HOOK, PLUGIN_MAX_RESULT_BYTES, PLUGIN_PROBE_CACHE_MAX_ENTRIES, PLUGIN_WATCHDOG_TIMEOUT_MS, PLUGIN_WORKER_MAX_OLD_SPACE_MB, PLUGIN_WORKER_MAX_RESPAWNS, PLUGIN_WORKER_RESPAWN_WINDOW_MS, buildRegistry, computeDHash, computePHash, conflict, createCapabilityGuard, createDirectoryContainer, createDirectoryResourceAPI, createDirectoryResourceAPI as createImportResourceAPI, createNestedAwareContainer, createNestedCdCache, createPluginActivation, createPluginDiscovery, createPluginHooks, createPluginLoader, createPluginResourceAPI, createPluginSandbox, createProbeCache, grayStddev, invalid, listZipEntries, materializeFile, notFound, parseManifest, resolveSafeImportPath, runPluginHook, seedPlugins };
3336
+ export { DEFAULT_PLUGIN_EXTRACT_MAX_BYTES, DEFAULT_PLUGIN_EXTRACT_MAX_ENTRIES, DEFAULT_SANDBOX_CONFIG, DomainError, MIN_PERCEPTUAL_STDDEV, PERCEPTUAL_HASH_KINDS, PHASH_GRID, PLUGIN_HOOK_HARD_TIMEOUT_MS, PLUGIN_MAX_API_CALLS_PER_HOOK, PLUGIN_MAX_LOGS_PER_HOOK, PLUGIN_MAX_RESULT_BYTES, PLUGIN_PROBE_CACHE_MAX_ENTRIES, PLUGIN_WATCHDOG_TIMEOUT_MS, PLUGIN_WORKER_MAX_OLD_SPACE_MB, PLUGIN_WORKER_MAX_RESPAWNS, PLUGIN_WORKER_RESPAWN_WINDOW_MS, buildRegistry, computeDHash, computePHash, conflict, createCapabilityGuard, createDirectoryContainer, createDirectoryResourceAPI, createDirectoryResourceAPI as createImportResourceAPI, createNestedAwareContainer, createNestedCdCache, createPluginActivation, createPluginDiscovery, createPluginHooks, createPluginLoader, createPluginResourceAPI, createPluginSandbox, createProbeCache, grayStddev, invalid, listZipEntries, materializeFile, notFound, packZipDirectory, parseManifest, resolveSafeImportPath, runPluginHook, seedPlugins };
3310
3337
  //# sourceMappingURL=index.js.map
3311
3338
  //# sourceMappingURL=index.js.map