@shisho/plugin-sdk 0.0.33 → 0.0.35

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/hooks.d.ts CHANGED
@@ -36,6 +36,18 @@ export interface SearchContext {
36
36
  file?: {
37
37
  /** File type extension (e.g., "epub", "cbz", "m4b", "pdf"). */
38
38
  fileType?: string;
39
+ /**
40
+ * Absolute path to the enrichment target file. The runtime grants the
41
+ * enricher scoped **read-only** access to exactly this one file, so
42
+ * `shisho.fs.readFile(context.file.filePath)` works without the plugin
43
+ * declaring the broader `fileAccess` capability. Writes to this path
44
+ * are NOT granted — a plugin that needs to modify the file must declare
45
+ * `fileAccess: { level: "readwrite" }` in its manifest. Sibling files
46
+ * (sidecars, covers) are also not included; the scope is the target
47
+ * file only. Omitted when there is no target file (e.g. a pre-scan
48
+ * enrichment with no file yet).
49
+ */
50
+ filePath?: string;
39
51
  /** Audiobook duration in seconds. */
40
52
  duration?: number;
41
53
  /** Number of pages (CBZ/PDF). */
package/host-api.d.ts CHANGED
@@ -238,6 +238,35 @@ export interface ShishoHTML {
238
238
  querySelectorAll(doc: HtmlElement, selector: string): HtmlElement[];
239
239
  }
240
240
 
241
+ /**
242
+ * YAML parsing and serialization. No capability required.
243
+ *
244
+ * Backed by Go's gopkg.in/yaml.v3, which does not instantiate arbitrary
245
+ * objects from custom tags (unlike PyYAML's full loader or Ruby's Psych),
246
+ * so parsing untrusted YAML cannot execute code. Oversized inputs are still
247
+ * bounded by the plugin hook timeout.
248
+ */
249
+ export interface ShishoYAML {
250
+ /**
251
+ * Parse a YAML string into a plain JS value (object, array, string, number, boolean, or null).
252
+ * Throws on invalid YAML.
253
+ *
254
+ * @example
255
+ * var config = shisho.yaml.parse("title: My Book\nauthor: Alice");
256
+ * config.title // "My Book"
257
+ */
258
+ parse(content: string): unknown;
259
+
260
+ /**
261
+ * Serialize a JS value to a YAML string.
262
+ *
263
+ * @example
264
+ * shisho.yaml.stringify({ title: "My Book", pages: 100 });
265
+ * // "title: My Book\npages: 100\n"
266
+ */
267
+ stringify(value: unknown): string;
268
+ }
269
+
241
270
  /** Result from shisho.ffmpeg.transcode(). */
242
271
  export interface TranscodeResult {
243
272
  /** Process exit code (0 = success). */
@@ -425,6 +454,7 @@ export interface ShishoHostAPI {
425
454
  archive: ShishoArchive;
426
455
  xml: ShishoXML;
427
456
  html: ShishoHTML;
457
+ yaml: ShishoYAML;
428
458
  ffmpeg: ShishoFFmpeg;
429
459
  shell: ShishoShell;
430
460
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shisho/plugin-sdk",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "description": "TypeScript SDK for Shisho plugin development — types, host API declarations, and test utilities",
5
5
  "homepage": "https://github.com/shishobooks/shisho/blob/master/packages/plugin-sdk/README.md",
6
6
  "types": "index.d.ts",
@@ -27,6 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "fast-xml-parser": "^5.7.1",
30
- "linkedom": "^0.18.12"
30
+ "linkedom": "^0.18.12",
31
+ "yaml": "^2.6.1"
31
32
  }
32
33
  }
@@ -37,7 +37,7 @@ export interface MockShishoOptions {
37
37
  * Create a mock `shisho` host API object for testing plugins.
38
38
  *
39
39
  * Provides mock implementations of log, config, http, url, and fs.
40
- * Provides real implementations of xml and html (backed by fast-xml-parser and linkedom).
40
+ * Provides real implementations of xml, html, and yaml (backed by fast-xml-parser, linkedom, and the `yaml` package).
41
41
  *
42
42
  * @example
43
43
  * ```ts
package/testing/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { XMLParser } from "fast-xml-parser";
2
2
  import { parseHTML } from "linkedom";
3
+ import { parse as parseYAML, stringify as stringifyYAML } from "yaml";
3
4
  function statusText(status) {
4
5
  const texts = {
5
6
  200: "OK",
@@ -230,13 +231,44 @@ function createHTMLImpl() {
230
231
  };
231
232
  }
232
233
  // ---------------------------------------------------------------------------
234
+ // YAML implementation (eemeli/yaml — real parser, matches Go's yaml.v3 shape)
235
+ //
236
+ // Both this mock and the production runtime (gopkg.in/yaml.v3) target YAML
237
+ // 1.2 semantics, so booleans like `yes`/`no`/`on`/`off` stay as strings in
238
+ // both. Divergence is still possible on edge cases — empty documents,
239
+ // non-string mapping keys, mapping-key ordering — so plugin authors should
240
+ // run the real runtime when asserting against anything subtle.
241
+ // ---------------------------------------------------------------------------
242
+ function createYAMLImpl() {
243
+ return {
244
+ parse(content) {
245
+ try {
246
+ return parseYAML(content);
247
+ }
248
+ catch (err) {
249
+ const message = err instanceof Error ? err.message : String(err);
250
+ throw new Error(`shisho.yaml.parse: ${message}`);
251
+ }
252
+ },
253
+ stringify(value) {
254
+ try {
255
+ return stringifyYAML(value);
256
+ }
257
+ catch (err) {
258
+ const message = err instanceof Error ? err.message : String(err);
259
+ throw new Error(`shisho.yaml.stringify: ${message}`);
260
+ }
261
+ },
262
+ };
263
+ }
264
+ // ---------------------------------------------------------------------------
233
265
  // Main factory
234
266
  // ---------------------------------------------------------------------------
235
267
  /**
236
268
  * Create a mock `shisho` host API object for testing plugins.
237
269
  *
238
270
  * Provides mock implementations of log, config, http, url, and fs.
239
- * Provides real implementations of xml and html (backed by fast-xml-parser and linkedom).
271
+ * Provides real implementations of xml, html, and yaml (backed by fast-xml-parser, linkedom, and the `yaml` package).
240
272
  *
241
273
  * @example
242
274
  * ```ts
@@ -447,6 +479,7 @@ export function createMockShisho(options = {}) {
447
479
  },
448
480
  xml: createXMLImpl(),
449
481
  html: createHTMLImpl(),
482
+ yaml: createYAMLImpl(),
450
483
  ffmpeg: {
451
484
  transcode: notImplemented("ffmpeg.transcode"),
452
485
  probe: notImplemented("ffmpeg.probe"),
package/testing/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { XMLParser } from "fast-xml-parser";
2
2
  import { parseHTML } from "linkedom";
3
+ import { parse as parseYAML, stringify as stringifyYAML } from "yaml";
3
4
 
4
5
  import type {
5
6
  FetchResponse,
@@ -13,6 +14,7 @@ import type {
13
14
  ShishoLog,
14
15
  ShishoURL,
15
16
  ShishoXML,
17
+ ShishoYAML,
16
18
  XMLElement,
17
19
  } from "../index";
18
20
 
@@ -337,6 +339,37 @@ function createHTMLImpl(): ShishoHTML {
337
339
  };
338
340
  }
339
341
 
342
+ // ---------------------------------------------------------------------------
343
+ // YAML implementation (eemeli/yaml — real parser, matches Go's yaml.v3 shape)
344
+ //
345
+ // Both this mock and the production runtime (gopkg.in/yaml.v3) target YAML
346
+ // 1.2 semantics, so booleans like `yes`/`no`/`on`/`off` stay as strings in
347
+ // both. Divergence is still possible on edge cases — empty documents,
348
+ // non-string mapping keys, mapping-key ordering — so plugin authors should
349
+ // run the real runtime when asserting against anything subtle.
350
+ // ---------------------------------------------------------------------------
351
+
352
+ function createYAMLImpl(): ShishoYAML {
353
+ return {
354
+ parse(content: string): unknown {
355
+ try {
356
+ return parseYAML(content);
357
+ } catch (err) {
358
+ const message = err instanceof Error ? err.message : String(err);
359
+ throw new Error(`shisho.yaml.parse: ${message}`);
360
+ }
361
+ },
362
+ stringify(value: unknown): string {
363
+ try {
364
+ return stringifyYAML(value);
365
+ } catch (err) {
366
+ const message = err instanceof Error ? err.message : String(err);
367
+ throw new Error(`shisho.yaml.stringify: ${message}`);
368
+ }
369
+ },
370
+ };
371
+ }
372
+
340
373
  // ---------------------------------------------------------------------------
341
374
  // Main factory
342
375
  // ---------------------------------------------------------------------------
@@ -345,7 +378,7 @@ function createHTMLImpl(): ShishoHTML {
345
378
  * Create a mock `shisho` host API object for testing plugins.
346
379
  *
347
380
  * Provides mock implementations of log, config, http, url, and fs.
348
- * Provides real implementations of xml and html (backed by fast-xml-parser and linkedom).
381
+ * Provides real implementations of xml, html, and yaml (backed by fast-xml-parser, linkedom, and the `yaml` package).
349
382
  *
350
383
  * @example
351
384
  * ```ts
@@ -606,6 +639,7 @@ export function createMockShisho(
606
639
  },
607
640
  xml: createXMLImpl(),
608
641
  html: createHTMLImpl(),
642
+ yaml: createYAMLImpl(),
609
643
  ffmpeg: {
610
644
  transcode: notImplemented("ffmpeg.transcode") as never,
611
645
  probe: notImplemented("ffmpeg.probe") as never,