@shisho/plugin-sdk 0.0.26 → 0.0.28
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/host-api.d.ts +22 -0
- package/manifest.d.ts +3 -1
- package/metadata.d.ts +4 -0
- package/package.json +2 -2
- package/testing/index.d.ts +13 -2
- package/testing/index.js +16 -2
- package/testing/index.ts +32 -4
package/host-api.d.ts
CHANGED
|
@@ -395,6 +395,28 @@ export interface ShishoShell {
|
|
|
395
395
|
export interface ShishoHostAPI {
|
|
396
396
|
/** Persistent data directory for this plugin. Created lazily on first access. */
|
|
397
397
|
readonly dataDir: string;
|
|
398
|
+
/**
|
|
399
|
+
* Block the plugin for the given number of milliseconds.
|
|
400
|
+
*
|
|
401
|
+
* Goja has no Promise/setTimeout support, so this is a synchronous delay
|
|
402
|
+
* backed by Go's `time.Sleep`. Use it to implement exponential backoff
|
|
403
|
+
* between retries when calling rate-limited APIs. The sleep honors the
|
|
404
|
+
* hook's deadline: if the ctx is cancelled while the plugin is sleeping,
|
|
405
|
+
* the call unblocks immediately and the hook throws.
|
|
406
|
+
*
|
|
407
|
+
* @param ms Finite non-negative milliseconds. Throws on negative, NaN, or
|
|
408
|
+
* Infinity.
|
|
409
|
+
* @example
|
|
410
|
+
* // Exponential backoff: 1s, 2s, 4s
|
|
411
|
+
* var resp;
|
|
412
|
+
* for (var attempt = 0; attempt < 3; attempt++) {
|
|
413
|
+
* resp = shisho.http.fetch(url, {});
|
|
414
|
+
* if (resp.status !== 503) return resp;
|
|
415
|
+
* shisho.sleep(1000 * Math.pow(2, attempt));
|
|
416
|
+
* }
|
|
417
|
+
* return resp; // retries exhausted — return the last 503
|
|
418
|
+
*/
|
|
419
|
+
sleep(ms: number): void;
|
|
398
420
|
log: ShishoLog;
|
|
399
421
|
config: ShishoConfig;
|
|
400
422
|
http: ShishoHTTP;
|
package/manifest.d.ts
CHANGED
package/metadata.d.ts
CHANGED
|
@@ -42,6 +42,10 @@ export interface ParsedMetadata {
|
|
|
42
42
|
publisher?: string;
|
|
43
43
|
imprint?: string;
|
|
44
44
|
url?: string;
|
|
45
|
+
/** BCP 47 language tag (e.g., "en", "en-US", "zh-Hans"). */
|
|
46
|
+
language?: string;
|
|
47
|
+
/** Whether this is an abridged edition. true=abridged, false=unabridged, undefined=unknown. */
|
|
48
|
+
abridged?: boolean;
|
|
45
49
|
/** ISO 8601 date string (e.g., "2023-06-15T00:00:00Z"). */
|
|
46
50
|
releaseDate?: string;
|
|
47
51
|
/** MIME type of cover image (e.g., "image/jpeg"). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shisho/plugin-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
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",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"directory": "packages/plugin-sdk"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"fast-xml-parser": "^5.5.
|
|
29
|
+
"fast-xml-parser": "^5.5.11",
|
|
30
30
|
"linkedom": "^0.18.12"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/testing/index.d.ts
CHANGED
|
@@ -17,10 +17,21 @@ export interface MockShishoOptions {
|
|
|
17
17
|
/**
|
|
18
18
|
* Path-based filesystem mock.
|
|
19
19
|
* - string values are returned by readTextFile/readFile
|
|
20
|
-
* - Buffer values are returned by readFile (as ArrayBuffer)
|
|
20
|
+
* - Uint8Array (or Buffer) values are returned by readFile (as ArrayBuffer)
|
|
21
21
|
* - string[] values are returned by listDir
|
|
22
22
|
*/
|
|
23
|
-
fs?: Record<string, string |
|
|
23
|
+
fs?: Record<string, string | Uint8Array | string[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Override the `sleep` implementation. Defaults to a no-op so tests asserting
|
|
26
|
+
* exponential backoff with e.g. `shisho.sleep(1000 * Math.pow(2, attempt))`
|
|
27
|
+
* don't actually block for the cumulative wall-clock time. Wrap with your
|
|
28
|
+
* test framework's spy helper (e.g. `vi.fn()`) if you want to assert the
|
|
29
|
+
* arguments each retry passed.
|
|
30
|
+
*
|
|
31
|
+
* The override is still subject to the same validation rules as production
|
|
32
|
+
* (no NaN/Infinity/negative).
|
|
33
|
+
*/
|
|
34
|
+
sleep?: (ms: number) => void;
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
26
37
|
* Create a mock `shisho` host API object for testing plugins.
|
package/testing/index.js
CHANGED
|
@@ -361,7 +361,6 @@ export function createMockShisho(options = {}) {
|
|
|
361
361
|
const encoder = new TextEncoder();
|
|
362
362
|
return encoder.encode(entry).buffer;
|
|
363
363
|
}
|
|
364
|
-
// Buffer
|
|
365
364
|
return entry.buffer.slice(entry.byteOffset, entry.byteOffset + entry.byteLength);
|
|
366
365
|
},
|
|
367
366
|
readTextFile(path) {
|
|
@@ -379,7 +378,6 @@ export function createMockShisho(options = {}) {
|
|
|
379
378
|
if (typeof entry === "string") {
|
|
380
379
|
return entry;
|
|
381
380
|
}
|
|
382
|
-
// Buffer -> string
|
|
383
381
|
const decoder = new TextDecoder();
|
|
384
382
|
return decoder.decode(entry);
|
|
385
383
|
},
|
|
@@ -418,8 +416,24 @@ export function createMockShisho(options = {}) {
|
|
|
418
416
|
throw new Error(`Mock ${api}: not implemented. Use MockShishoOptions to configure the APIs you need, ` +
|
|
419
417
|
`or provide your own mock for ${api}.`);
|
|
420
418
|
};
|
|
419
|
+
// --- sleep: validate like production, then delegate ---
|
|
420
|
+
// Defaults to a no-op because plugin tests asserting exponential backoff
|
|
421
|
+
// (`shisho.sleep(1000 * Math.pow(2, attempt))`) would otherwise add several
|
|
422
|
+
// seconds of wall-clock per retry path. Authors who want a real wait or
|
|
423
|
+
// call tracking can pass `options.sleep` (e.g. a `vi.fn()` spy).
|
|
424
|
+
const sleepImpl = options.sleep ?? (() => { });
|
|
425
|
+
const sleep = (ms) => {
|
|
426
|
+
if (typeof ms !== "number" ||
|
|
427
|
+
Number.isNaN(ms) ||
|
|
428
|
+
!Number.isFinite(ms) ||
|
|
429
|
+
ms < 0) {
|
|
430
|
+
throw new Error("shisho.sleep: ms must be a finite non-negative number");
|
|
431
|
+
}
|
|
432
|
+
sleepImpl(ms);
|
|
433
|
+
};
|
|
421
434
|
return {
|
|
422
435
|
dataDir: "/tmp/shisho-mock-data",
|
|
436
|
+
sleep,
|
|
423
437
|
log,
|
|
424
438
|
config,
|
|
425
439
|
http,
|
package/testing/index.ts
CHANGED
|
@@ -34,10 +34,21 @@ export interface MockShishoOptions {
|
|
|
34
34
|
/**
|
|
35
35
|
* Path-based filesystem mock.
|
|
36
36
|
* - string values are returned by readTextFile/readFile
|
|
37
|
-
* - Buffer values are returned by readFile (as ArrayBuffer)
|
|
37
|
+
* - Uint8Array (or Buffer) values are returned by readFile (as ArrayBuffer)
|
|
38
38
|
* - string[] values are returned by listDir
|
|
39
39
|
*/
|
|
40
|
-
fs?: Record<string, string |
|
|
40
|
+
fs?: Record<string, string | Uint8Array | string[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Override the `sleep` implementation. Defaults to a no-op so tests asserting
|
|
43
|
+
* exponential backoff with e.g. `shisho.sleep(1000 * Math.pow(2, attempt))`
|
|
44
|
+
* don't actually block for the cumulative wall-clock time. Wrap with your
|
|
45
|
+
* test framework's spy helper (e.g. `vi.fn()`) if you want to assert the
|
|
46
|
+
* arguments each retry passed.
|
|
47
|
+
*
|
|
48
|
+
* The override is still subject to the same validation rules as production
|
|
49
|
+
* (no NaN/Infinity/negative).
|
|
50
|
+
*/
|
|
51
|
+
sleep?: (ms: number) => void;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
function statusText(status: number): string {
|
|
@@ -481,7 +492,6 @@ export function createMockShisho(
|
|
|
481
492
|
const encoder = new TextEncoder();
|
|
482
493
|
return encoder.encode(entry).buffer as ArrayBuffer;
|
|
483
494
|
}
|
|
484
|
-
// Buffer
|
|
485
495
|
return entry.buffer.slice(
|
|
486
496
|
entry.byteOffset,
|
|
487
497
|
entry.byteOffset + entry.byteLength,
|
|
@@ -508,7 +518,6 @@ export function createMockShisho(
|
|
|
508
518
|
if (typeof entry === "string") {
|
|
509
519
|
return entry;
|
|
510
520
|
}
|
|
511
|
-
// Buffer -> string
|
|
512
521
|
const decoder = new TextDecoder();
|
|
513
522
|
return decoder.decode(entry);
|
|
514
523
|
},
|
|
@@ -562,8 +571,27 @@ export function createMockShisho(
|
|
|
562
571
|
);
|
|
563
572
|
};
|
|
564
573
|
|
|
574
|
+
// --- sleep: validate like production, then delegate ---
|
|
575
|
+
// Defaults to a no-op because plugin tests asserting exponential backoff
|
|
576
|
+
// (`shisho.sleep(1000 * Math.pow(2, attempt))`) would otherwise add several
|
|
577
|
+
// seconds of wall-clock per retry path. Authors who want a real wait or
|
|
578
|
+
// call tracking can pass `options.sleep` (e.g. a `vi.fn()` spy).
|
|
579
|
+
const sleepImpl = options.sleep ?? (() => {});
|
|
580
|
+
const sleep: ShishoHostAPI["sleep"] = (ms: number): void => {
|
|
581
|
+
if (
|
|
582
|
+
typeof ms !== "number" ||
|
|
583
|
+
Number.isNaN(ms) ||
|
|
584
|
+
!Number.isFinite(ms) ||
|
|
585
|
+
ms < 0
|
|
586
|
+
) {
|
|
587
|
+
throw new Error("shisho.sleep: ms must be a finite non-negative number");
|
|
588
|
+
}
|
|
589
|
+
sleepImpl(ms);
|
|
590
|
+
};
|
|
591
|
+
|
|
565
592
|
return {
|
|
566
593
|
dataDir: "/tmp/shisho-mock-data",
|
|
594
|
+
sleep,
|
|
567
595
|
log,
|
|
568
596
|
config,
|
|
569
597
|
http,
|