@shisho/plugin-sdk 0.0.21
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 +119 -0
- package/global.d.ts +9 -0
- package/hooks.d.ts +130 -0
- package/host-api.d.ts +408 -0
- package/index.d.ts +6 -0
- package/manifest.d.ts +166 -0
- package/metadata.d.ts +77 -0
- package/package.json +32 -0
- package/testing/index.d.ts +44 -0
- package/testing/index.js +443 -0
- package/testing/index.ts +583 -0
- package/testing/tsconfig.json +14 -0
package/manifest.d.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/** Input converter capability declaration. */
|
|
2
|
+
export interface InputConverterCap {
|
|
3
|
+
description?: string;
|
|
4
|
+
/** File extensions this converter accepts (e.g., ["mobi"]). */
|
|
5
|
+
sourceTypes: string[];
|
|
6
|
+
/** MIME types this converter accepts. */
|
|
7
|
+
mimeTypes?: string[];
|
|
8
|
+
/** Target file type to convert to (e.g., "epub"). */
|
|
9
|
+
targetType: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** File parser capability declaration. */
|
|
13
|
+
export interface FileParserCap {
|
|
14
|
+
description?: string;
|
|
15
|
+
/** File extensions this parser handles (e.g., ["pdf"]). */
|
|
16
|
+
types: string[];
|
|
17
|
+
/** MIME types this parser handles (e.g., ["application/pdf"]). */
|
|
18
|
+
mimeTypes?: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Output generator capability declaration. */
|
|
22
|
+
export interface OutputGeneratorCap {
|
|
23
|
+
description?: string;
|
|
24
|
+
/** Unique format identifier (e.g., "mobi"). */
|
|
25
|
+
id: string;
|
|
26
|
+
/** Display name (e.g., "MOBI"). */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Source file types this generator can convert from. */
|
|
29
|
+
sourceTypes: string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Valid metadata field names for enricher declarations. */
|
|
33
|
+
export type MetadataField =
|
|
34
|
+
| "title"
|
|
35
|
+
| "subtitle"
|
|
36
|
+
| "authors"
|
|
37
|
+
| "narrators"
|
|
38
|
+
| "series"
|
|
39
|
+
| "seriesNumber"
|
|
40
|
+
| "genres"
|
|
41
|
+
| "tags"
|
|
42
|
+
| "description"
|
|
43
|
+
| "publisher"
|
|
44
|
+
| "imprint"
|
|
45
|
+
| "url"
|
|
46
|
+
| "releaseDate"
|
|
47
|
+
| "cover"
|
|
48
|
+
| "identifiers";
|
|
49
|
+
|
|
50
|
+
/** Metadata enricher capability declaration. */
|
|
51
|
+
export interface MetadataEnricherCap {
|
|
52
|
+
description?: string;
|
|
53
|
+
/** File types this enricher applies to (e.g., ["epub", "cbz"]). */
|
|
54
|
+
fileTypes?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Metadata fields this enricher may set.
|
|
57
|
+
* Required for enrichers - if omitted, the enricher hook is disabled.
|
|
58
|
+
*/
|
|
59
|
+
fields: MetadataField[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Custom identifier type declaration. */
|
|
63
|
+
export interface IdentifierTypeCap {
|
|
64
|
+
/** Unique identifier type ID (e.g., "goodreads"). */
|
|
65
|
+
id: string;
|
|
66
|
+
/** Display name (e.g., "Goodreads"). */
|
|
67
|
+
name: string;
|
|
68
|
+
/** URL template with {value} placeholder. */
|
|
69
|
+
urlTemplate?: string;
|
|
70
|
+
/** Regex pattern for validation. */
|
|
71
|
+
pattern?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** HTTP access capability declaration. */
|
|
75
|
+
export interface HTTPAccessCap {
|
|
76
|
+
description?: string;
|
|
77
|
+
/** Allowed domains for HTTP requests. */
|
|
78
|
+
domains: string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** File access capability declaration. */
|
|
82
|
+
export interface FileAccessCap {
|
|
83
|
+
/** Access level: "read" or "readwrite". */
|
|
84
|
+
level: "read" | "readwrite";
|
|
85
|
+
description?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** FFmpeg access capability declaration. */
|
|
89
|
+
export interface FFmpegAccessCap {
|
|
90
|
+
description?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Shell access capability declaration. */
|
|
94
|
+
export interface ShellAccessCap {
|
|
95
|
+
description?: string;
|
|
96
|
+
/** Allowed commands (e.g., ["convert", "magick", "identify"]). */
|
|
97
|
+
commands: string[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** All plugin capabilities. */
|
|
101
|
+
export interface Capabilities {
|
|
102
|
+
inputConverter?: InputConverterCap;
|
|
103
|
+
fileParser?: FileParserCap;
|
|
104
|
+
outputGenerator?: OutputGeneratorCap;
|
|
105
|
+
metadataEnricher?: MetadataEnricherCap;
|
|
106
|
+
identifierTypes?: IdentifierTypeCap[];
|
|
107
|
+
httpAccess?: HTTPAccessCap;
|
|
108
|
+
fileAccess?: FileAccessCap;
|
|
109
|
+
ffmpegAccess?: FFmpegAccessCap;
|
|
110
|
+
shellAccess?: ShellAccessCap;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Option for select-type config fields. */
|
|
114
|
+
export interface SelectOption {
|
|
115
|
+
value: string;
|
|
116
|
+
label: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** A single configuration field definition. */
|
|
120
|
+
export interface ConfigField {
|
|
121
|
+
/** Field type. */
|
|
122
|
+
type: "string" | "boolean" | "number" | "select" | "textarea";
|
|
123
|
+
/** Display label. */
|
|
124
|
+
label: string;
|
|
125
|
+
/** Help text description. */
|
|
126
|
+
description?: string;
|
|
127
|
+
/** Whether this field is required. */
|
|
128
|
+
required?: boolean;
|
|
129
|
+
/** Whether this field contains sensitive data. */
|
|
130
|
+
secret?: boolean;
|
|
131
|
+
/** Default value. */
|
|
132
|
+
default?: string | number | boolean;
|
|
133
|
+
/** Minimum value (number fields). */
|
|
134
|
+
min?: number;
|
|
135
|
+
/** Maximum value (number fields). */
|
|
136
|
+
max?: number;
|
|
137
|
+
/** Options (select fields). */
|
|
138
|
+
options?: SelectOption[];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Configuration schema mapping field keys to definitions. */
|
|
142
|
+
export interface ConfigSchema {
|
|
143
|
+
[key: string]: ConfigField;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Complete plugin manifest (manifest.json). */
|
|
147
|
+
export interface PluginManifest {
|
|
148
|
+
/** Must be 1. */
|
|
149
|
+
manifestVersion: 1;
|
|
150
|
+
/** Plugin identifier (e.g., "goodreads-metadata"). */
|
|
151
|
+
id: string;
|
|
152
|
+
/** Display name. */
|
|
153
|
+
name: string;
|
|
154
|
+
/** Semver version string. */
|
|
155
|
+
version: string;
|
|
156
|
+
/** Short one-liner overview (separate from longer description). */
|
|
157
|
+
overview?: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
author?: string;
|
|
160
|
+
homepage?: string;
|
|
161
|
+
license?: string;
|
|
162
|
+
/** Minimum Shisho version required. */
|
|
163
|
+
minShishoVersion?: string;
|
|
164
|
+
capabilities?: Capabilities;
|
|
165
|
+
configSchema?: ConfigSchema;
|
|
166
|
+
}
|
package/metadata.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** An author with optional role information. */
|
|
2
|
+
export interface ParsedAuthor {
|
|
3
|
+
/** Author name. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Role (empty for generic author, or one of: writer, penciller, inker, colorist, letterer, cover_artist, editor, translator). */
|
|
6
|
+
role?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** An identifier parsed from file metadata. */
|
|
10
|
+
export interface ParsedIdentifier {
|
|
11
|
+
/** Identifier type (e.g., isbn_10, isbn_13, asin, uuid, goodreads, google, other). */
|
|
12
|
+
type: string;
|
|
13
|
+
/** The identifier value. */
|
|
14
|
+
value: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A chapter parsed from file metadata. */
|
|
18
|
+
export interface ParsedChapter {
|
|
19
|
+
/** Chapter title. */
|
|
20
|
+
title: string;
|
|
21
|
+
/** CBZ: 0-indexed page number. */
|
|
22
|
+
startPage?: number;
|
|
23
|
+
/** M4B: milliseconds from start. */
|
|
24
|
+
startTimestampMs?: number;
|
|
25
|
+
/** EPUB: content document href. */
|
|
26
|
+
href?: string;
|
|
27
|
+
/** Nested child chapters (EPUB nesting only). */
|
|
28
|
+
children?: ParsedChapter[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Full metadata object returned by file parsers and metadata enrichers. */
|
|
32
|
+
export interface ParsedMetadata {
|
|
33
|
+
title?: string;
|
|
34
|
+
subtitle?: string;
|
|
35
|
+
authors?: ParsedAuthor[];
|
|
36
|
+
narrators?: string[];
|
|
37
|
+
series?: string;
|
|
38
|
+
seriesNumber?: number;
|
|
39
|
+
genres?: string[];
|
|
40
|
+
tags?: string[];
|
|
41
|
+
description?: string;
|
|
42
|
+
publisher?: string;
|
|
43
|
+
imprint?: string;
|
|
44
|
+
url?: string;
|
|
45
|
+
/** ISO 8601 date string (e.g., "2023-06-15T00:00:00Z"). */
|
|
46
|
+
releaseDate?: string;
|
|
47
|
+
/** MIME type of cover image (e.g., "image/jpeg"). */
|
|
48
|
+
coverMimeType?: string;
|
|
49
|
+
/**
|
|
50
|
+
* URL to download the cover image from. The server handles downloading and validates
|
|
51
|
+
* the domain against the plugin's httpAccess.domains. This is the recommended way for
|
|
52
|
+
* enricher plugins to provide covers.
|
|
53
|
+
*/
|
|
54
|
+
coverUrl?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Raw cover image data as an ArrayBuffer. Use this for file parsers that extract
|
|
57
|
+
* embedded covers, or enrichers that generate/composite images. If both coverData
|
|
58
|
+
* and coverUrl are set, coverData takes precedence (no download occurs).
|
|
59
|
+
*/
|
|
60
|
+
coverData?: ArrayBuffer;
|
|
61
|
+
/** 0-indexed page number for CBZ cover. */
|
|
62
|
+
coverPage?: number;
|
|
63
|
+
/** Duration in seconds (float, M4B files). */
|
|
64
|
+
duration?: number;
|
|
65
|
+
/** Audio bitrate in bits per second (M4B files). */
|
|
66
|
+
bitrateBps?: number;
|
|
67
|
+
/** Number of pages (CBZ files). */
|
|
68
|
+
pageCount?: number;
|
|
69
|
+
identifiers?: ParsedIdentifier[];
|
|
70
|
+
chapters?: ParsedChapter[];
|
|
71
|
+
/**
|
|
72
|
+
* Confidence score (0-1) indicating how well this result matches the search query.
|
|
73
|
+
* Used by the scan pipeline to decide whether to auto-apply enrichment.
|
|
74
|
+
* If omitted, the result is always applied (backwards compatible).
|
|
75
|
+
*/
|
|
76
|
+
confidence?: number;
|
|
77
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shisho/plugin-sdk",
|
|
3
|
+
"version": "0.0.21",
|
|
4
|
+
"description": "TypeScript SDK for Shisho plugin development — types, host API declarations, and test utilities",
|
|
5
|
+
"homepage": "https://github.com/shishobooks/shisho/blob/master/packages/plugin-sdk/README.md",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.d.ts",
|
|
9
|
+
"./testing": {
|
|
10
|
+
"types": "./testing/index.d.ts",
|
|
11
|
+
"import": "./testing/index.js",
|
|
12
|
+
"require": "./testing/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"*.d.ts",
|
|
17
|
+
"testing/"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "cd testing && npx tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/shishobooks/shisho.git",
|
|
26
|
+
"directory": "packages/plugin-sdk"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"fast-xml-parser": "^5.5.9",
|
|
30
|
+
"linkedom": "^0.18.12"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ShishoHostAPI } from "../index";
|
|
2
|
+
/** Configuration for a mock fetch response. */
|
|
3
|
+
export interface MockFetchResponse {
|
|
4
|
+
/** HTTP status code (default: 200). */
|
|
5
|
+
status?: number;
|
|
6
|
+
/** Response body as string (default: ""). */
|
|
7
|
+
body?: string;
|
|
8
|
+
/** Response headers (default: {}). */
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
/** Options for createMockShisho(). */
|
|
12
|
+
export interface MockShishoOptions {
|
|
13
|
+
/** Route-based fetch mock. Keys are URL strings, values are mock responses. */
|
|
14
|
+
fetch?: Record<string, MockFetchResponse>;
|
|
15
|
+
/** Config key-value pairs returned by shisho.config. */
|
|
16
|
+
config?: Record<string, string>;
|
|
17
|
+
/**
|
|
18
|
+
* Path-based filesystem mock.
|
|
19
|
+
* - string values are returned by readTextFile/readFile
|
|
20
|
+
* - Buffer values are returned by readFile (as ArrayBuffer)
|
|
21
|
+
* - string[] values are returned by listDir
|
|
22
|
+
*/
|
|
23
|
+
fs?: Record<string, string | Buffer | string[]>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a mock `shisho` host API object for testing plugins.
|
|
27
|
+
*
|
|
28
|
+
* Provides mock implementations of log, config, http, url, and fs.
|
|
29
|
+
* Provides real implementations of xml and html (backed by fast-xml-parser and linkedom).
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const shisho = createMockShisho({
|
|
34
|
+
* fetch: {
|
|
35
|
+
* "https://api.example.com/search?q=test": {
|
|
36
|
+
* status: 200,
|
|
37
|
+
* body: JSON.stringify({ results: [] }),
|
|
38
|
+
* },
|
|
39
|
+
* },
|
|
40
|
+
* config: { apiKey: "test-key" },
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function createMockShisho(options?: MockShishoOptions): ShishoHostAPI;
|