@ashdev/codex-plugin-metadata-mangabaka 1.9.3 → 1.10.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.js +324 -203
- package/dist/index.js.map +4 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -144,6 +144,151 @@ function createLogger(options) {
|
|
|
144
144
|
|
|
145
145
|
// node_modules/@ashdev/codex-plugin-sdk/dist/server.js
|
|
146
146
|
import { createInterface } from "node:readline";
|
|
147
|
+
|
|
148
|
+
// node_modules/@ashdev/codex-plugin-sdk/dist/storage.js
|
|
149
|
+
var StorageError = class extends Error {
|
|
150
|
+
code;
|
|
151
|
+
data;
|
|
152
|
+
constructor(message, code, data) {
|
|
153
|
+
super(message);
|
|
154
|
+
this.code = code;
|
|
155
|
+
this.data = data;
|
|
156
|
+
this.name = "StorageError";
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
var PluginStorage = class {
|
|
160
|
+
nextId = 1;
|
|
161
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
162
|
+
writeFn;
|
|
163
|
+
/**
|
|
164
|
+
* Create a new storage client.
|
|
165
|
+
*
|
|
166
|
+
* @param writeFn - Optional custom write function (defaults to process.stdout.write).
|
|
167
|
+
* Useful for testing or custom transport layers.
|
|
168
|
+
*/
|
|
169
|
+
constructor(writeFn) {
|
|
170
|
+
this.writeFn = writeFn ?? ((line) => {
|
|
171
|
+
process.stdout.write(line);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get a value by key
|
|
176
|
+
*
|
|
177
|
+
* @param key - Storage key to retrieve
|
|
178
|
+
* @returns The stored data and optional expiration, or null data if key doesn't exist
|
|
179
|
+
*/
|
|
180
|
+
async get(key) {
|
|
181
|
+
return await this.sendRequest("storage/get", { key });
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Set a value by key (upsert - creates or updates)
|
|
185
|
+
*
|
|
186
|
+
* @param key - Storage key
|
|
187
|
+
* @param data - JSON-serializable data to store
|
|
188
|
+
* @param expiresAt - Optional expiration timestamp (ISO 8601)
|
|
189
|
+
* @returns Success indicator
|
|
190
|
+
*/
|
|
191
|
+
async set(key, data, expiresAt) {
|
|
192
|
+
const params = { key, data };
|
|
193
|
+
if (expiresAt !== void 0) {
|
|
194
|
+
params.expiresAt = expiresAt;
|
|
195
|
+
}
|
|
196
|
+
return await this.sendRequest("storage/set", params);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Delete a value by key
|
|
200
|
+
*
|
|
201
|
+
* @param key - Storage key to delete
|
|
202
|
+
* @returns Whether the key existed and was deleted
|
|
203
|
+
*/
|
|
204
|
+
async delete(key) {
|
|
205
|
+
return await this.sendRequest("storage/delete", { key });
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* List all keys for this plugin instance (excluding expired)
|
|
209
|
+
*
|
|
210
|
+
* @returns List of key entries with metadata
|
|
211
|
+
*/
|
|
212
|
+
async list() {
|
|
213
|
+
return await this.sendRequest("storage/list", {});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Clear all data for this plugin instance
|
|
217
|
+
*
|
|
218
|
+
* @returns Number of entries deleted
|
|
219
|
+
*/
|
|
220
|
+
async clear() {
|
|
221
|
+
return await this.sendRequest("storage/clear", {});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Handle an incoming JSON-RPC response line from the host.
|
|
225
|
+
*
|
|
226
|
+
* Call this method from your readline handler to deliver responses
|
|
227
|
+
* back to pending storage requests.
|
|
228
|
+
*/
|
|
229
|
+
handleResponse(line) {
|
|
230
|
+
const trimmed = line.trim();
|
|
231
|
+
if (!trimmed)
|
|
232
|
+
return;
|
|
233
|
+
let parsed;
|
|
234
|
+
try {
|
|
235
|
+
parsed = JSON.parse(trimmed);
|
|
236
|
+
} catch {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const obj = parsed;
|
|
240
|
+
if (obj.method !== void 0) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const id = obj.id;
|
|
244
|
+
if (id === void 0 || id === null)
|
|
245
|
+
return;
|
|
246
|
+
const pending = this.pendingRequests.get(id);
|
|
247
|
+
if (!pending)
|
|
248
|
+
return;
|
|
249
|
+
this.pendingRequests.delete(id);
|
|
250
|
+
if ("error" in obj && obj.error) {
|
|
251
|
+
const err = obj.error;
|
|
252
|
+
pending.reject(new StorageError(err.message, err.code, err.data));
|
|
253
|
+
} else {
|
|
254
|
+
pending.resolve(obj.result);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Cancel all pending requests (e.g. on shutdown).
|
|
259
|
+
*/
|
|
260
|
+
cancelAll() {
|
|
261
|
+
for (const [, pending] of this.pendingRequests) {
|
|
262
|
+
pending.reject(new StorageError("Storage client stopped", -1));
|
|
263
|
+
}
|
|
264
|
+
this.pendingRequests.clear();
|
|
265
|
+
}
|
|
266
|
+
// ===========================================================================
|
|
267
|
+
// Internal
|
|
268
|
+
// ===========================================================================
|
|
269
|
+
sendRequest(method, params) {
|
|
270
|
+
const id = this.nextId++;
|
|
271
|
+
const request = {
|
|
272
|
+
jsonrpc: "2.0",
|
|
273
|
+
id,
|
|
274
|
+
method,
|
|
275
|
+
params
|
|
276
|
+
};
|
|
277
|
+
return new Promise((resolve, reject) => {
|
|
278
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
279
|
+
try {
|
|
280
|
+
this.writeFn(`${JSON.stringify(request)}
|
|
281
|
+
`);
|
|
282
|
+
} catch (err) {
|
|
283
|
+
this.pendingRequests.delete(id);
|
|
284
|
+
const message = err instanceof Error ? err.message : "Unknown write error";
|
|
285
|
+
reject(new StorageError(`Failed to send request: ${message}`, -1));
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// node_modules/@ashdev/codex-plugin-sdk/dist/server.js
|
|
147
292
|
function validateStringFields(params, fields) {
|
|
148
293
|
if (params === null || params === void 0) {
|
|
149
294
|
return { field: "params", message: "params is required" };
|
|
@@ -204,26 +349,22 @@ function invalidParamsError(id, error) {
|
|
|
204
349
|
}
|
|
205
350
|
};
|
|
206
351
|
}
|
|
207
|
-
function
|
|
208
|
-
const { manifest: manifest2,
|
|
352
|
+
function createPluginServer(options) {
|
|
353
|
+
const { manifest: manifest2, onInitialize, logLevel = "info", label, router } = options;
|
|
209
354
|
const logger5 = createLogger({ name: manifest2.name, level: logLevel });
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
if (contentTypes.includes("book") && !bookProvider) {
|
|
215
|
-
throw new Error("Book metadata provider is required when 'book' is in metadataProvider capabilities");
|
|
216
|
-
}
|
|
217
|
-
logger5.info(`Starting plugin: ${manifest2.displayName} v${manifest2.version}`);
|
|
355
|
+
const prefix = label ? `${label} plugin` : "plugin";
|
|
356
|
+
const storage = new PluginStorage();
|
|
357
|
+
logger5.info(`Starting ${prefix}: ${manifest2.displayName} v${manifest2.version}`);
|
|
218
358
|
const rl = createInterface({
|
|
219
359
|
input: process.stdin,
|
|
220
360
|
terminal: false
|
|
221
361
|
});
|
|
222
362
|
rl.on("line", (line) => {
|
|
223
|
-
void handleLine(line, manifest2,
|
|
363
|
+
void handleLine(line, manifest2, onInitialize, router, logger5, storage);
|
|
224
364
|
});
|
|
225
365
|
rl.on("close", () => {
|
|
226
366
|
logger5.info("stdin closed, shutting down");
|
|
367
|
+
storage.cancelAll();
|
|
227
368
|
process.exit(0);
|
|
228
369
|
});
|
|
229
370
|
process.on("uncaughtException", (error) => {
|
|
@@ -234,16 +375,33 @@ function createMetadataPlugin(options) {
|
|
|
234
375
|
logger5.error("Unhandled rejection", reason);
|
|
235
376
|
});
|
|
236
377
|
}
|
|
237
|
-
|
|
378
|
+
function isJsonRpcResponse(obj) {
|
|
379
|
+
if (obj.method !== void 0)
|
|
380
|
+
return false;
|
|
381
|
+
if (obj.id === void 0 || obj.id === null)
|
|
382
|
+
return false;
|
|
383
|
+
return "result" in obj || "error" in obj;
|
|
384
|
+
}
|
|
385
|
+
async function handleLine(line, manifest2, onInitialize, router, logger5, storage) {
|
|
238
386
|
const trimmed = line.trim();
|
|
239
387
|
if (!trimmed)
|
|
240
388
|
return;
|
|
389
|
+
let parsed;
|
|
390
|
+
try {
|
|
391
|
+
parsed = JSON.parse(trimmed);
|
|
392
|
+
} catch {
|
|
393
|
+
}
|
|
394
|
+
if (parsed && isJsonRpcResponse(parsed)) {
|
|
395
|
+
logger5.debug("Routing storage response", { id: parsed.id });
|
|
396
|
+
storage.handleResponse(trimmed);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
241
399
|
let id = null;
|
|
242
400
|
try {
|
|
243
|
-
const request = JSON.parse(trimmed);
|
|
401
|
+
const request = parsed ?? JSON.parse(trimmed);
|
|
244
402
|
id = request.id;
|
|
245
403
|
logger5.debug(`Received request: ${request.method}`, { id: request.id });
|
|
246
|
-
const response = await handleRequest(request, manifest2,
|
|
404
|
+
const response = await handleRequest(request, manifest2, onInitialize, router, logger5, storage);
|
|
247
405
|
if (response !== null) {
|
|
248
406
|
writeResponse(response);
|
|
249
407
|
}
|
|
@@ -277,203 +435,130 @@ async function handleLine(line, manifest2, provider2, bookProvider, onInitialize
|
|
|
277
435
|
}
|
|
278
436
|
}
|
|
279
437
|
}
|
|
280
|
-
async function handleRequest(request, manifest2,
|
|
438
|
+
async function handleRequest(request, manifest2, onInitialize, router, logger5, storage) {
|
|
281
439
|
const { method, params, id } = request;
|
|
282
440
|
switch (method) {
|
|
283
|
-
case "initialize":
|
|
441
|
+
case "initialize": {
|
|
442
|
+
const initParams = params ?? {};
|
|
443
|
+
initParams.storage = storage;
|
|
284
444
|
if (onInitialize) {
|
|
285
|
-
await onInitialize(
|
|
445
|
+
await onInitialize(initParams);
|
|
286
446
|
}
|
|
287
|
-
return {
|
|
288
|
-
|
|
289
|
-
id,
|
|
290
|
-
result: manifest2
|
|
291
|
-
};
|
|
447
|
+
return { jsonrpc: "2.0", id, result: manifest2 };
|
|
448
|
+
}
|
|
292
449
|
case "ping":
|
|
293
|
-
return {
|
|
294
|
-
jsonrpc: "2.0",
|
|
295
|
-
id,
|
|
296
|
-
result: "pong"
|
|
297
|
-
};
|
|
450
|
+
return { jsonrpc: "2.0", id, result: "pong" };
|
|
298
451
|
case "shutdown": {
|
|
299
452
|
logger5.info("Shutdown requested");
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
result: null
|
|
304
|
-
};
|
|
305
|
-
process.stdout.write(`${JSON.stringify(response)}
|
|
453
|
+
storage.cancelAll();
|
|
454
|
+
const response2 = { jsonrpc: "2.0", id, result: null };
|
|
455
|
+
process.stdout.write(`${JSON.stringify(response2)}
|
|
306
456
|
`, () => {
|
|
307
457
|
process.exit(0);
|
|
308
458
|
});
|
|
309
459
|
return null;
|
|
310
460
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
const validationError = validateSearchParams(params);
|
|
326
|
-
if (validationError) {
|
|
327
|
-
return invalidParamsError(id, validationError);
|
|
328
|
-
}
|
|
329
|
-
return {
|
|
330
|
-
jsonrpc: "2.0",
|
|
331
|
-
id,
|
|
332
|
-
result: await provider2.search(params)
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
case "metadata/series/get": {
|
|
336
|
-
if (!provider2) {
|
|
337
|
-
return {
|
|
338
|
-
jsonrpc: "2.0",
|
|
339
|
-
id,
|
|
340
|
-
error: {
|
|
341
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
342
|
-
message: "This plugin does not support series metadata"
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
const validationError = validateGetParams(params);
|
|
347
|
-
if (validationError) {
|
|
348
|
-
return invalidParamsError(id, validationError);
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
jsonrpc: "2.0",
|
|
352
|
-
id,
|
|
353
|
-
result: await provider2.get(params)
|
|
354
|
-
};
|
|
461
|
+
}
|
|
462
|
+
const response = await router(method, params, id);
|
|
463
|
+
if (response !== null) {
|
|
464
|
+
return response;
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
jsonrpc: "2.0",
|
|
468
|
+
id,
|
|
469
|
+
error: {
|
|
470
|
+
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
471
|
+
message: `Method not found: ${method}`
|
|
355
472
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
jsonrpc: "2.0",
|
|
370
|
-
id,
|
|
371
|
-
error: {
|
|
372
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
373
|
-
message: "This plugin does not support series match"
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
}
|
|
377
|
-
const validationError = validateMatchParams(params);
|
|
378
|
-
if (validationError) {
|
|
379
|
-
return invalidParamsError(id, validationError);
|
|
380
|
-
}
|
|
381
|
-
return {
|
|
382
|
-
jsonrpc: "2.0",
|
|
383
|
-
id,
|
|
384
|
-
result: await provider2.match(params)
|
|
385
|
-
};
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function writeResponse(response) {
|
|
476
|
+
process.stdout.write(`${JSON.stringify(response)}
|
|
477
|
+
`);
|
|
478
|
+
}
|
|
479
|
+
function methodNotFound(id, message) {
|
|
480
|
+
return {
|
|
481
|
+
jsonrpc: "2.0",
|
|
482
|
+
id,
|
|
483
|
+
error: {
|
|
484
|
+
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
485
|
+
message
|
|
386
486
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function success(id, result) {
|
|
490
|
+
return { jsonrpc: "2.0", id, result };
|
|
491
|
+
}
|
|
492
|
+
function createMetadataPlugin(options) {
|
|
493
|
+
const { manifest: manifest2, provider: provider2, bookProvider, onInitialize, logLevel } = options;
|
|
494
|
+
const contentTypes = manifest2.capabilities.metadataProvider;
|
|
495
|
+
if (contentTypes.includes("series") && !provider2) {
|
|
496
|
+
throw new Error("Series metadata provider is required when 'series' is in metadataProvider capabilities");
|
|
497
|
+
}
|
|
498
|
+
if (contentTypes.includes("book") && !bookProvider) {
|
|
499
|
+
throw new Error("Book metadata provider is required when 'book' is in metadataProvider capabilities");
|
|
500
|
+
}
|
|
501
|
+
const router = async (method, params, id) => {
|
|
502
|
+
switch (method) {
|
|
503
|
+
// Series metadata methods
|
|
504
|
+
case "metadata/series/search": {
|
|
505
|
+
if (!provider2)
|
|
506
|
+
return methodNotFound(id, "This plugin does not support series metadata");
|
|
507
|
+
const err = validateSearchParams(params);
|
|
508
|
+
if (err)
|
|
509
|
+
return invalidParamsError(id, err);
|
|
510
|
+
return success(id, await provider2.search(params));
|
|
404
511
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
if (!bookProvider) {
|
|
413
|
-
return {
|
|
414
|
-
jsonrpc: "2.0",
|
|
415
|
-
id,
|
|
416
|
-
error: {
|
|
417
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
418
|
-
message: "This plugin does not support book metadata"
|
|
419
|
-
}
|
|
420
|
-
};
|
|
512
|
+
case "metadata/series/get": {
|
|
513
|
+
if (!provider2)
|
|
514
|
+
return methodNotFound(id, "This plugin does not support series metadata");
|
|
515
|
+
const err = validateGetParams(params);
|
|
516
|
+
if (err)
|
|
517
|
+
return invalidParamsError(id, err);
|
|
518
|
+
return success(id, await provider2.get(params));
|
|
421
519
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
520
|
+
case "metadata/series/match": {
|
|
521
|
+
if (!provider2)
|
|
522
|
+
return methodNotFound(id, "This plugin does not support series metadata");
|
|
523
|
+
if (!provider2.match)
|
|
524
|
+
return methodNotFound(id, "This plugin does not support series match");
|
|
525
|
+
const err = validateMatchParams(params);
|
|
526
|
+
if (err)
|
|
527
|
+
return invalidParamsError(id, err);
|
|
528
|
+
return success(id, await provider2.match(params));
|
|
425
529
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
return {
|
|
435
|
-
jsonrpc: "2.0",
|
|
436
|
-
id,
|
|
437
|
-
error: {
|
|
438
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
439
|
-
message: "This plugin does not support book metadata"
|
|
440
|
-
}
|
|
441
|
-
};
|
|
530
|
+
// Book metadata methods
|
|
531
|
+
case "metadata/book/search": {
|
|
532
|
+
if (!bookProvider)
|
|
533
|
+
return methodNotFound(id, "This plugin does not support book metadata");
|
|
534
|
+
const err = validateBookSearchParams(params);
|
|
535
|
+
if (err)
|
|
536
|
+
return invalidParamsError(id, err);
|
|
537
|
+
return success(id, await bookProvider.search(params));
|
|
442
538
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
};
|
|
539
|
+
case "metadata/book/get": {
|
|
540
|
+
if (!bookProvider)
|
|
541
|
+
return methodNotFound(id, "This plugin does not support book metadata");
|
|
542
|
+
const err = validateGetParams(params);
|
|
543
|
+
if (err)
|
|
544
|
+
return invalidParamsError(id, err);
|
|
545
|
+
return success(id, await bookProvider.get(params));
|
|
452
546
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
547
|
+
case "metadata/book/match": {
|
|
548
|
+
if (!bookProvider)
|
|
549
|
+
return methodNotFound(id, "This plugin does not support book metadata");
|
|
550
|
+
if (!bookProvider.match)
|
|
551
|
+
return methodNotFound(id, "This plugin does not support book match");
|
|
552
|
+
const err = validateBookMatchParams(params);
|
|
553
|
+
if (err)
|
|
554
|
+
return invalidParamsError(id, err);
|
|
555
|
+
return success(id, await bookProvider.match(params));
|
|
456
556
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
id,
|
|
460
|
-
result: await bookProvider.match(params)
|
|
461
|
-
};
|
|
557
|
+
default:
|
|
558
|
+
return null;
|
|
462
559
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
jsonrpc: "2.0",
|
|
466
|
-
id,
|
|
467
|
-
error: {
|
|
468
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
469
|
-
message: `Method not found: ${method}`
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
function writeResponse(response) {
|
|
475
|
-
process.stdout.write(`${JSON.stringify(response)}
|
|
476
|
-
`);
|
|
560
|
+
};
|
|
561
|
+
createPluginServer({ manifest: manifest2, onInitialize, logLevel, router });
|
|
477
562
|
}
|
|
478
563
|
|
|
479
564
|
// src/api.ts
|
|
@@ -746,11 +831,21 @@ function mapSeriesMetadata(series) {
|
|
|
746
831
|
}
|
|
747
832
|
};
|
|
748
833
|
const externalRatings = [];
|
|
834
|
+
const externalIds = [
|
|
835
|
+
// Always include the plugin's own API ID so other plugins can cross-reference
|
|
836
|
+
{ source: "api:mangabaka", externalId: String(series.id) }
|
|
837
|
+
];
|
|
749
838
|
if (series.source) {
|
|
750
839
|
for (const [key, info] of Object.entries(series.source)) {
|
|
751
840
|
if (!info) continue;
|
|
752
841
|
const config = sourceConfig[key];
|
|
753
842
|
const ratingKey = config?.ratingKey ?? key.replace(/_/g, "");
|
|
843
|
+
if (info.id != null) {
|
|
844
|
+
externalIds.push({
|
|
845
|
+
source: `api:${ratingKey}`,
|
|
846
|
+
externalId: String(info.id)
|
|
847
|
+
});
|
|
848
|
+
}
|
|
754
849
|
if (info.id != null && config?.urlPattern) {
|
|
755
850
|
externalLinks.push({
|
|
756
851
|
url: config.urlPattern.replace("{id}", String(info.id)),
|
|
@@ -788,7 +883,8 @@ function mapSeriesMetadata(series) {
|
|
|
788
883
|
return r != null ? { score: r, source: "mangabaka" } : void 0;
|
|
789
884
|
})(),
|
|
790
885
|
externalRatings: externalRatings.length > 0 ? externalRatings : void 0,
|
|
791
|
-
externalLinks
|
|
886
|
+
externalLinks,
|
|
887
|
+
externalIds
|
|
792
888
|
};
|
|
793
889
|
}
|
|
794
890
|
|
|
@@ -802,26 +898,38 @@ async function handleGet(params, client2) {
|
|
|
802
898
|
return mapSeriesMetadata(response);
|
|
803
899
|
}
|
|
804
900
|
|
|
805
|
-
// src/
|
|
806
|
-
var logger2 = createLogger({ name: "mangabaka-match", level: "info" });
|
|
901
|
+
// src/similarity.ts
|
|
807
902
|
function similarity(a, b) {
|
|
808
903
|
const aLower = a.toLowerCase().trim();
|
|
809
904
|
const bLower = b.toLowerCase().trim();
|
|
810
905
|
if (aLower === bLower) return 1;
|
|
811
906
|
if (aLower.length === 0 || bLower.length === 0) return 0;
|
|
812
|
-
|
|
813
|
-
|
|
907
|
+
let score = 0;
|
|
908
|
+
const shorter = aLower.length <= bLower.length ? aLower : bLower;
|
|
909
|
+
const longer = aLower.length <= bLower.length ? bLower : aLower;
|
|
910
|
+
if (longer.includes(shorter)) {
|
|
911
|
+
const lengthRatio = shorter.length / longer.length;
|
|
912
|
+
score = Math.max(score, 0.8 * lengthRatio);
|
|
814
913
|
}
|
|
815
914
|
const aWords = new Set(aLower.split(/\s+/));
|
|
816
915
|
const bWords = new Set(bLower.split(/\s+/));
|
|
817
916
|
const intersection = [...aWords].filter((w) => bWords.has(w));
|
|
818
917
|
const union = /* @__PURE__ */ new Set([...aWords, ...bWords]);
|
|
819
|
-
|
|
918
|
+
if (union.size > 0) {
|
|
919
|
+
score = Math.max(score, intersection.length / union.size);
|
|
920
|
+
}
|
|
921
|
+
return score;
|
|
820
922
|
}
|
|
923
|
+
|
|
924
|
+
// src/handlers/match.ts
|
|
925
|
+
var logger2 = createLogger({ name: "mangabaka-match", level: "info" });
|
|
821
926
|
function scoreResult(result, params) {
|
|
822
927
|
let score = 0;
|
|
823
|
-
|
|
824
|
-
|
|
928
|
+
let bestTitleSimilarity = similarity(result.title, params.title);
|
|
929
|
+
for (const alt of result.alternateTitles) {
|
|
930
|
+
bestTitleSimilarity = Math.max(bestTitleSimilarity, similarity(alt, params.title));
|
|
931
|
+
}
|
|
932
|
+
score += bestTitleSimilarity * 0.6;
|
|
825
933
|
if (params.year && result.year) {
|
|
826
934
|
if (result.year === params.year) {
|
|
827
935
|
score += 0.2;
|
|
@@ -829,7 +937,9 @@ function scoreResult(result, params) {
|
|
|
829
937
|
score += 0.1;
|
|
830
938
|
}
|
|
831
939
|
}
|
|
832
|
-
|
|
940
|
+
const searchLower = params.title.toLowerCase();
|
|
941
|
+
const hasExactMatch = result.title.toLowerCase() === searchLower || result.alternateTitles.some((alt) => alt.toLowerCase() === searchLower);
|
|
942
|
+
if (hasExactMatch) {
|
|
833
943
|
score += 0.2;
|
|
834
944
|
}
|
|
835
945
|
return Math.min(1, score);
|
|
@@ -871,13 +981,24 @@ async function handleMatch(params, client2) {
|
|
|
871
981
|
|
|
872
982
|
// src/handlers/search.ts
|
|
873
983
|
var logger3 = createLogger({ name: "mangabaka-search", level: "debug" });
|
|
984
|
+
function scoreSearchResult(result, query) {
|
|
985
|
+
let best = similarity(result.title, query);
|
|
986
|
+
for (const alt of result.alternateTitles) {
|
|
987
|
+
best = Math.max(best, similarity(alt, query));
|
|
988
|
+
}
|
|
989
|
+
return best;
|
|
990
|
+
}
|
|
874
991
|
async function handleSearch(params, client2) {
|
|
875
992
|
logger3.debug("Search params received:", params);
|
|
876
993
|
const limit = params.limit ?? 20;
|
|
877
994
|
const page = params.cursor ? Number.parseInt(params.cursor, 10) : 1;
|
|
878
995
|
logger3.debug(`Searching for: "${params.query}" (page ${page}, limit ${limit})`);
|
|
879
996
|
const response = await client2.search(params.query, page, limit);
|
|
880
|
-
const results = response.data.map(
|
|
997
|
+
const results = response.data.map((series) => {
|
|
998
|
+
const result = mapSearchResult(series);
|
|
999
|
+
result.relevanceScore = scoreSearchResult(result, params.query);
|
|
1000
|
+
return result;
|
|
1001
|
+
}).sort((a, b) => (b.relevanceScore ?? 0) - (a.relevanceScore ?? 0));
|
|
881
1002
|
const hasNextPage = response.page < response.totalPages;
|
|
882
1003
|
const nextCursor = hasNextPage ? String(response.page + 1) : void 0;
|
|
883
1004
|
return {
|
|
@@ -889,7 +1010,7 @@ async function handleSearch(params, client2) {
|
|
|
889
1010
|
// package.json
|
|
890
1011
|
var package_default = {
|
|
891
1012
|
name: "@ashdev/codex-plugin-metadata-mangabaka",
|
|
892
|
-
version: "1.
|
|
1013
|
+
version: "1.10.1",
|
|
893
1014
|
description: "MangaBaka metadata provider plugin for Codex",
|
|
894
1015
|
main: "dist/index.js",
|
|
895
1016
|
bin: "dist/index.js",
|
|
@@ -928,7 +1049,7 @@ var package_default = {
|
|
|
928
1049
|
node: ">=22.0.0"
|
|
929
1050
|
},
|
|
930
1051
|
dependencies: {
|
|
931
|
-
"@ashdev/codex-plugin-sdk": "^1.
|
|
1052
|
+
"@ashdev/codex-plugin-sdk": "^1.10.1"
|
|
932
1053
|
},
|
|
933
1054
|
devDependencies: {
|
|
934
1055
|
"@biomejs/biome": "^2.3.13",
|
|
@@ -1007,7 +1128,7 @@ createMetadataPlugin({
|
|
|
1007
1128
|
if (!apiKey) {
|
|
1008
1129
|
throw new ConfigError("api_key credential is required");
|
|
1009
1130
|
}
|
|
1010
|
-
const timeout = params.
|
|
1131
|
+
const timeout = params.adminConfig?.timeout;
|
|
1011
1132
|
client = new MangaBakaClient(apiKey, { timeout });
|
|
1012
1133
|
logger4.info(`MangaBaka client initialized (timeout: ${timeout ?? "default"}s)`);
|
|
1013
1134
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../node_modules/@ashdev/codex-plugin-sdk/src/types/rpc.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/errors.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/logger.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/server.ts", "../src/api.ts", "../src/mappers.ts", "../src/handlers/get.ts", "../src/handlers/match.ts", "../src/handlers/search.ts", "../package.json", "../src/manifest.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": [null, null, null, null, "/**\n * MangaBaka API client\n * API docs: https://mangabaka.org/api\n */\n\nimport {\n ApiError,\n AuthError,\n createLogger,\n NotFoundError,\n RateLimitError,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MbGetSeriesResponse, MbSearchResponse, MbSeries } from \"./types.js\";\n\nconst BASE_URL = \"https://api.mangabaka.dev\";\nconst DEFAULT_TIMEOUT_SECONDS = 60;\nconst logger = createLogger({ name: \"mangabaka-api\", level: \"debug\" });\n\nexport interface MangaBakaClientOptions {\n /** Request timeout in seconds (default: 15) */\n timeout?: number;\n}\n\nexport class MangaBakaClient {\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n\n constructor(apiKey: string, options?: MangaBakaClientOptions) {\n if (!apiKey) {\n throw new AuthError(\"API key is required\");\n }\n this.apiKey = apiKey;\n this.timeoutMs = (options?.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000;\n logger.debug(`MangaBakaClient initialized with timeout: ${this.timeoutMs}ms`);\n }\n\n /**\n * Search for series by query\n */\n async search(\n query: string,\n page = 1,\n perPage = 20,\n ): Promise<{ data: MbSeries[]; total: number; page: number; totalPages: number }> {\n logger.debug(`Searching for: \"${query}\" (page ${page})`);\n\n const params = new URLSearchParams({\n q: query,\n page: String(page),\n limit: String(perPage),\n });\n\n const response = await this.request<MbSearchResponse>(`/v1/series/search?${params.toString()}`);\n\n return {\n data: response.data,\n total: response.pagination?.total ?? response.data.length,\n page: response.pagination?.page ?? page,\n totalPages: response.pagination?.total_pages ?? 1,\n };\n }\n\n /**\n * Get full series details by ID\n */\n async getSeries(id: number): Promise<MbSeries> {\n logger.debug(`Getting series: ${id}`);\n\n const response = await this.request<MbGetSeriesResponse>(`/v1/series/${id}`);\n\n return response.data;\n }\n\n /**\n * Make an authenticated request to the MangaBaka API\n */\n private async request<T>(path: string): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const headers: Record<string, string> = {\n \"x-api-key\": this.apiKey,\n Accept: \"application/json\",\n };\n\n // Set up timeout using AbortController\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n logger.debug(`Request: ${path} (timeout: ${this.timeoutMs}ms)`);\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const seconds = retryAfter ? Number.parseInt(retryAfter, 10) : 60;\n throw new RateLimitError(seconds);\n }\n\n // Handle auth errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthError(\"Invalid API key\");\n }\n\n // Handle not found\n if (response.status === 404) {\n throw new NotFoundError(`Resource not found: ${path}`);\n }\n\n // Handle other errors\n if (!response.ok) {\n const text = await response.text();\n logger.error(`API error: ${response.status}`, { body: text });\n throw new ApiError(`API error: ${response.status} ${response.statusText}`, response.status);\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n // Handle timeout (abort)\n if (error instanceof Error && error.name === \"AbortError\") {\n logger.error(`Request timed out after ${this.timeoutMs}ms: ${path}`);\n throw new ApiError(`Request timed out after ${this.timeoutMs / 1000}s`);\n }\n\n // Re-throw plugin errors\n if (\n error instanceof RateLimitError ||\n error instanceof AuthError ||\n error instanceof NotFoundError ||\n error instanceof ApiError\n ) {\n throw error;\n }\n\n // Wrap other errors\n const message = error instanceof Error ? error.message : \"Unknown error\";\n logger.error(\"Request failed\", error);\n throw new ApiError(`Request failed: ${message}`);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n", "/**\n * Mappers to convert MangaBaka API responses to Codex plugin protocol types\n */\n\nimport type {\n AlternateTitle,\n ExternalLink,\n ExternalRating,\n PluginSeriesMetadata,\n ReadingDirection,\n SearchResult,\n SeriesStatus,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MbContentRating, MbSeries, MbSeriesType, MbStatus } from \"./types.js\";\n\n/**\n * Strip HTML tags from text, converting <br> to newlines\n */\nfunction stripHtml(html: string | undefined | null): string | undefined {\n if (!html) return undefined;\n return html\n .replace(/<br\\s*\\/?>/gi, \"\\n\") // Convert <br> to newlines\n .replace(/<[^>]*>/g, \"\") // Strip remaining HTML tags\n .trim();\n}\n\n/**\n * Map MangaBaka status to protocol SeriesStatus\n * MangaBaka uses: cancelled, completed, hiatus, releasing, unknown, upcoming\n * Codex uses: ongoing, ended, hiatus, abandoned, unknown\n */\nfunction mapStatus(mbStatus: MbStatus): SeriesStatus {\n switch (mbStatus) {\n case \"completed\":\n return \"ended\";\n case \"releasing\":\n case \"upcoming\":\n return \"ongoing\";\n case \"hiatus\":\n return \"hiatus\";\n case \"cancelled\":\n return \"abandoned\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Format genre from snake_case to Title Case\n */\nfunction formatGenre(genre: string): string {\n return genre\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/**\n * Detect language code from country of origin\n */\nfunction detectLanguageFromCountry(country: string | null | undefined): string | undefined {\n if (!country) return undefined;\n\n const countryLower = country.toLowerCase();\n if (countryLower === \"jp\" || countryLower === \"japan\") return \"ja\";\n if (countryLower === \"kr\" || countryLower === \"korea\" || countryLower === \"south korea\")\n return \"ko\";\n if (countryLower === \"cn\" || countryLower === \"china\") return \"zh\";\n if (countryLower === \"tw\" || countryLower === \"taiwan\") return \"zh-TW\";\n\n return undefined;\n}\n\n/**\n * Map MangaBaka content rating to numeric age rating\n */\nfunction mapContentRating(rating: MbContentRating | null | undefined): number | undefined {\n if (!rating) return undefined;\n\n switch (rating) {\n case \"safe\":\n return 0; // All ages\n case \"suggestive\":\n return 13; // Teen\n case \"erotica\":\n return 16; // Mature\n case \"pornographic\":\n return 18; // Adults only\n default:\n return undefined;\n }\n}\n\n/**\n * Extract rating value from either a number or an object with bayesian/average\n */\nfunction extractRating(\n rating: number | { bayesian?: number | null; average?: number | null } | null | undefined,\n): number | undefined {\n if (rating == null) return undefined;\n if (typeof rating === \"number\") return rating;\n return rating.bayesian ?? rating.average ?? undefined;\n}\n\n/**\n * Infer reading direction from series type and country\n */\nfunction inferReadingDirection(\n seriesType: MbSeriesType,\n country: string | null | undefined,\n): ReadingDirection | undefined {\n // Manhwa (Korean) and Manhua (Chinese) are typically left-to-right\n if (seriesType === \"manhwa\" || seriesType === \"manhua\") {\n return \"ltr\";\n }\n\n // Manga (Japanese) is typically right-to-left\n if (seriesType === \"manga\") {\n return \"rtl\";\n }\n\n // OEL (Original English Language) is left-to-right\n if (seriesType === \"oel\") {\n return \"ltr\";\n }\n\n // Fall back to country-based detection\n if (country) {\n const countryLower = country.toLowerCase();\n if (countryLower === \"jp\" || countryLower === \"japan\") return \"rtl\";\n if (countryLower === \"kr\" || countryLower === \"korea\" || countryLower === \"south korea\")\n return \"ltr\";\n if (countryLower === \"cn\" || countryLower === \"china\") return \"ltr\";\n if (countryLower === \"tw\" || countryLower === \"taiwan\") return \"ltr\";\n }\n\n return undefined;\n}\n\n/**\n * Map a MangaBaka series to a protocol SearchResult\n */\nexport function mapSearchResult(series: MbSeries): SearchResult {\n // Get cover URL - prefer x250 for search results\n const coverUrl = series.cover?.x250?.x1 ?? series.cover?.raw?.url ?? undefined;\n\n // Build alternate titles array\n const alternateTitles: string[] = [];\n if (series.native_title && series.native_title !== series.title) {\n alternateTitles.push(series.native_title);\n }\n if (series.romanized_title && series.romanized_title !== series.title) {\n alternateTitles.push(series.romanized_title);\n }\n\n // Note: relevanceScore is omitted - the API already returns results in relevance order\n return {\n externalId: String(series.id),\n title: series.title,\n alternateTitles,\n year: series.year ?? undefined,\n coverUrl: coverUrl ?? undefined,\n preview: {\n status: mapStatus(series.status),\n genres: (series.genres ?? []).slice(0, 3).map(formatGenre),\n rating: extractRating(series.rating),\n description: stripHtml(series.description)?.slice(0, 200) ?? undefined,\n bookCount: series.final_volume ? Number.parseInt(series.final_volume, 10) : undefined,\n },\n };\n}\n\n/**\n * Map full series response to protocol PluginSeriesMetadata\n */\nexport function mapSeriesMetadata(series: MbSeries): PluginSeriesMetadata {\n // Build alternate titles array with language info\n const alternateTitles: AlternateTitle[] = [];\n\n // Add native title\n if (series.native_title && series.native_title !== series.title) {\n alternateTitles.push({\n title: series.native_title,\n language: detectLanguageFromCountry(series.country_of_origin),\n titleType: \"native\",\n });\n }\n\n // Add romanized title\n if (series.romanized_title && series.romanized_title !== series.title) {\n alternateTitles.push({\n title: series.romanized_title,\n language: \"en\",\n titleType: \"romaji\",\n });\n }\n\n // Add secondary titles from all languages\n if (series.secondary_titles) {\n for (const [langCode, titleList] of Object.entries(series.secondary_titles)) {\n if (titleList) {\n for (const titleEntry of titleList) {\n if (titleEntry.title !== series.title) {\n alternateTitles.push({\n title: titleEntry.title,\n language: langCode,\n });\n }\n }\n }\n }\n }\n\n // Extract authors and artists as string arrays\n const authors = series.authors ?? [];\n const artists = series.artists ?? [];\n\n // Format genres\n const genres = (series.genres ?? []).map(formatGenre);\n\n // Get cover URL - prefer raw for full metadata\n const coverUrl = series.cover?.raw?.url ?? series.cover?.x350?.x1 ?? undefined;\n\n // Build external links from sources\n // Always include MangaBaka link first\n const externalLinks: ExternalLink[] = [\n {\n url: `https://mangabaka.org/${series.id}`,\n label: \"MangaBaka\",\n linkType: \"provider\",\n },\n ];\n\n // Source configuration: display name, rating key, and URL pattern\n // URL pattern uses {id} as placeholder for the source ID\n const sourceConfig: Record<string, { label: string; ratingKey: string; urlPattern?: string }> = {\n anilist: {\n label: \"AniList\",\n ratingKey: \"anilist\",\n urlPattern: \"https://anilist.co/manga/{id}\",\n },\n my_anime_list: {\n label: \"MyAnimeList\",\n ratingKey: \"myanimelist\",\n urlPattern: \"https://myanimelist.net/manga/{id}\",\n },\n mangadex: {\n label: \"MangaDex\",\n ratingKey: \"mangadex\",\n urlPattern: \"https://mangadex.org/title/{id}\",\n },\n manga_updates: {\n label: \"MangaUpdates\",\n ratingKey: \"mangaupdates\",\n urlPattern: \"https://www.mangaupdates.com/series/{id}\",\n },\n kitsu: { label: \"Kitsu\", ratingKey: \"kitsu\", urlPattern: \"https://kitsu.app/manga/{id}\" },\n anime_planet: {\n label: \"Anime-Planet\",\n ratingKey: \"animeplanet\",\n urlPattern: \"https://www.anime-planet.com/manga/{id}\",\n },\n anime_news_network: { label: \"Anime News Network\", ratingKey: \"animenewsnetwork\" },\n shikimori: {\n label: \"Shikimori\",\n ratingKey: \"shikimori\",\n urlPattern: \"https://shikimori.one/mangas/{id}\",\n },\n };\n\n // Build external links and ratings from sources in a single pass\n const externalRatings: ExternalRating[] = [];\n\n if (series.source) {\n for (const [key, info] of Object.entries(series.source)) {\n if (!info) continue;\n\n const config = sourceConfig[key];\n // Use config if available, otherwise generate defaults from key\n const ratingKey = config?.ratingKey ?? key.replace(/_/g, \"\");\n\n // Add external link if source has an ID and URL pattern\n if (info.id != null && config?.urlPattern) {\n externalLinks.push({\n url: config.urlPattern.replace(\"{id}\", String(info.id)),\n label: config.label,\n linkType: \"provider\",\n });\n }\n\n // Add external rating if source has a normalized rating\n if (info.rating_normalized != null) {\n externalRatings.push({ score: info.rating_normalized, source: ratingKey });\n }\n }\n }\n\n // Get publisher name (pick first one if available)\n const publisher = series.publishers?.[0]?.name ?? undefined;\n\n return {\n externalId: String(series.id),\n externalUrl: `https://mangabaka.org/${series.id}`,\n title: series.title,\n alternateTitles,\n summary: stripHtml(series.description),\n status: mapStatus(series.status),\n year: series.year ?? undefined,\n // Extended metadata\n publisher,\n totalBookCount: series.final_volume ? Number.parseInt(series.final_volume, 10) : undefined,\n ageRating: mapContentRating(series.content_rating),\n readingDirection: inferReadingDirection(series.type, series.country_of_origin),\n // Taxonomy\n genres,\n tags: series.tags ?? [],\n authors,\n artists,\n coverUrl: coverUrl ?? undefined,\n rating: (() => {\n const r = extractRating(series.rating);\n return r != null ? { score: r, source: \"mangabaka\" } : undefined;\n })(),\n externalRatings: externalRatings.length > 0 ? externalRatings : undefined,\n externalLinks,\n };\n}\n", "import {\n type MetadataGetParams,\n NotFoundError,\n type PluginSeriesMetadata,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSeriesMetadata } from \"../mappers.js\";\n\nexport async function handleGet(\n params: MetadataGetParams,\n client: MangaBakaClient,\n): Promise<PluginSeriesMetadata> {\n const seriesId = Number.parseInt(params.externalId, 10);\n\n if (Number.isNaN(seriesId)) {\n throw new NotFoundError(`Invalid external ID: ${params.externalId}`);\n }\n\n const response = await client.getSeries(seriesId);\n\n return mapSeriesMetadata(response);\n}\n", "import {\n createLogger,\n type MetadataMatchParams,\n type MetadataMatchResponse,\n type SearchResult,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSearchResult } from \"../mappers.js\";\n\nconst logger = createLogger({ name: \"mangabaka-match\", level: \"info\" });\n\n/**\n * Calculate string similarity using word overlap\n * Returns a value between 0 and 1\n */\nfunction similarity(a: string, b: string): number {\n const aLower = a.toLowerCase().trim();\n const bLower = b.toLowerCase().trim();\n\n if (aLower === bLower) return 1.0;\n if (aLower.length === 0 || bLower.length === 0) return 0;\n\n // Check if one contains the other\n if (aLower.includes(bLower) || bLower.includes(aLower)) {\n return 0.8;\n }\n\n // Simple word overlap scoring\n const aWords = new Set(aLower.split(/\\s+/));\n const bWords = new Set(bLower.split(/\\s+/));\n const intersection = [...aWords].filter((w) => bWords.has(w));\n const union = new Set([...aWords, ...bWords]);\n\n return intersection.length / union.size;\n}\n\n/**\n * Score a search result against the match parameters\n * Returns a value between 0 and 1\n */\nfunction scoreResult(result: SearchResult, params: MetadataMatchParams): number {\n let score = 0;\n\n // Title similarity (up to 0.6)\n const titleScore = similarity(result.title, params.title);\n score += titleScore * 0.6;\n\n // Year match (up to 0.2)\n if (params.year && result.year) {\n if (result.year === params.year) {\n score += 0.2;\n } else if (Math.abs(result.year - params.year) <= 1) {\n score += 0.1;\n }\n }\n\n // Boost for exact title match (up to 0.2)\n if (result.title.toLowerCase() === params.title.toLowerCase()) {\n score += 0.2;\n }\n\n return Math.min(1.0, score);\n}\n\nexport async function handleMatch(\n params: MetadataMatchParams,\n client: MangaBakaClient,\n): Promise<MetadataMatchResponse> {\n logger.debug(`Matching: \"${params.title}\"`);\n\n // Search for the title\n const response = await client.search(params.title, 1, 10);\n\n if (response.data.length === 0) {\n return {\n match: null,\n confidence: 0,\n };\n }\n\n // Map and score results\n const scoredResults = response.data\n .map((series) => {\n const result = mapSearchResult(series);\n const score = scoreResult(result, params);\n return { result, score };\n })\n .sort((a, b) => b.score - a.score);\n\n const best = scoredResults[0];\n\n if (!best) {\n return {\n match: null,\n confidence: 0,\n };\n }\n\n // If confidence is low, include alternatives\n const alternatives =\n best.score < 0.8\n ? scoredResults.slice(1, 4).map((s) => ({\n ...s.result,\n relevanceScore: s.score,\n }))\n : undefined;\n\n return {\n match: {\n ...best.result,\n relevanceScore: best.score,\n },\n confidence: best.score,\n alternatives,\n };\n}\n", "import {\n createLogger,\n type MetadataSearchParams,\n type MetadataSearchResponse,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSearchResult } from \"../mappers.js\";\n\nconst logger = createLogger({ name: \"mangabaka-search\", level: \"debug\" });\n\nexport async function handleSearch(\n params: MetadataSearchParams,\n client: MangaBakaClient,\n): Promise<MetadataSearchResponse> {\n logger.debug(\"Search params received:\", params);\n\n const limit = params.limit ?? 20;\n\n // Parse cursor as page number (default to 1)\n const page = params.cursor ? Number.parseInt(params.cursor, 10) : 1;\n\n logger.debug(`Searching for: \"${params.query}\" (page ${page}, limit ${limit})`);\n\n const response = await client.search(params.query, page, limit);\n\n // Map results - API already returns them sorted by relevance\n const results = response.data.map(mapSearchResult);\n\n // Calculate next cursor (next page number) if there are more results\n const hasNextPage = response.page < response.totalPages;\n const nextCursor = hasNextPage ? String(response.page + 1) : undefined;\n\n return {\n results,\n nextCursor,\n };\n}\n", "{\n \"name\": \"@ashdev/codex-plugin-metadata-mangabaka\",\n \"version\": \"1.9.3\",\n \"description\": \"MangaBaka metadata provider plugin for Codex\",\n \"main\": \"dist/index.js\",\n \"bin\": \"dist/index.js\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/AshDevFr/codex.git\",\n \"directory\": \"plugins/metadata-mangabaka\"\n },\n \"scripts\": {\n \"build\": \"esbuild src/index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --sourcemap --banner:js='#!/usr/bin/env node'\",\n \"dev\": \"npm run build -- --watch\",\n \"clean\": \"rm -rf dist\",\n \"start\": \"node dist/index.js\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"npm run lint && npm run build\"\n },\n \"keywords\": [\n \"codex\",\n \"plugin\",\n \"mangabaka\",\n \"manga\",\n \"metadata\"\n ],\n \"author\": \"Codex\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"dependencies\": {\n \"@ashdev/codex-plugin-sdk\": \"^1.9.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.3.13\",\n \"@types/node\": \"^22.0.0\",\n \"esbuild\": \"^0.24.0\",\n \"typescript\": \"^5.7.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n", "import type { MetadataContentType, PluginManifest } from \"@ashdev/codex-plugin-sdk\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const manifest = {\n name: \"metadata-mangabaka\",\n displayName: \"MangaBaka Metadata\",\n version: packageJson.version,\n description: \"Fetch manga metadata from MangaBaka - aggregated data from multiple sources\",\n author: \"Codex\",\n homepage: \"https://mangabaka.org\",\n protocolVersion: \"1.0\",\n capabilities: {\n metadataProvider: [\"series\"] as MetadataContentType[],\n },\n requiredCredentials: [\n {\n key: \"api_key\",\n label: \"API Key\",\n description: \"Get your API key at https://mangabaka.org/settings/api (requires account)\",\n required: true,\n sensitive: true,\n type: \"password\",\n placeholder: \"mb-...\",\n },\n ],\n configSchema: {\n description: \"Optional configuration for the MangaBaka plugin\",\n fields: [\n {\n key: \"timeout\",\n label: \"Request Timeout\",\n description: \"HTTP request timeout in seconds for API calls to MangaBaka\",\n type: \"number\",\n required: false,\n default: 60,\n example: 30,\n },\n ],\n },\n} as const satisfies PluginManifest & {\n capabilities: { metadataProvider: MetadataContentType[] };\n};\n", "/**\n * MangaBaka Plugin - Fetch manga metadata from MangaBaka\n *\n * MangaBaka aggregates metadata from multiple sources (AniList, MAL, MangaDex, etc.)\n * and provides a unified API for manga/novel metadata.\n *\n * API docs: https://mangabaka.org/api\n *\n * Credentials are provided by Codex via the initialize message.\n * Required credential: api_key (get one at https://mangabaka.org/settings/api)\n */\n\nimport {\n ConfigError,\n createLogger,\n createMetadataPlugin,\n type InitializeParams,\n type MetadataProvider,\n} from \"@ashdev/codex-plugin-sdk\";\nimport { MangaBakaClient } from \"./api.js\";\nimport { handleGet } from \"./handlers/get.js\";\nimport { handleMatch } from \"./handlers/match.js\";\nimport { handleSearch } from \"./handlers/search.js\";\nimport { manifest } from \"./manifest.js\";\n\nconst logger = createLogger({ name: \"mangabaka\", level: \"info\" });\n\n// Client is initialized when we receive credentials from Codex\nlet client: MangaBakaClient | null = null;\n\nfunction getClient(): MangaBakaClient {\n if (!client) {\n throw new ConfigError(\"Plugin not initialized - missing API key\");\n }\n return client;\n}\n\n// Create the MetadataProvider implementation\nconst provider: MetadataProvider = {\n async search(params) {\n return handleSearch(params, getClient());\n },\n\n async get(params) {\n return handleGet(params, getClient());\n },\n\n async match(params) {\n return handleMatch(params, getClient());\n },\n};\n\n// Start the plugin server\ncreateMetadataPlugin({\n manifest,\n provider,\n logLevel: \"info\",\n onInitialize(params: InitializeParams) {\n const apiKey = params.credentials?.api_key;\n if (!apiKey) {\n throw new ConfigError(\"api_key credential is required\");\n }\n\n // Get optional timeout from config (in seconds)\n const timeout = params.config?.timeout as number | undefined;\n\n client = new MangaBakaClient(apiKey, { timeout });\n logger.info(`MangaBaka client initialized (timeout: ${timeout ?? \"default\"}s)`);\n },\n});\n\nlogger.info(\"MangaBaka plugin started\");\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["manifest", "
|
|
3
|
+
"sources": ["../node_modules/@ashdev/codex-plugin-sdk/src/types/rpc.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/errors.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/logger.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/server.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/storage.ts", "../src/api.ts", "../src/mappers.ts", "../src/handlers/get.ts", "../src/similarity.ts", "../src/handlers/match.ts", "../src/handlers/search.ts", "../package.json", "../src/manifest.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": [null, null, null, null, null, "/**\n * MangaBaka API client\n * API docs: https://mangabaka.org/api\n */\n\nimport {\n ApiError,\n AuthError,\n createLogger,\n NotFoundError,\n RateLimitError,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MbGetSeriesResponse, MbSearchResponse, MbSeries } from \"./types.js\";\n\nconst BASE_URL = \"https://api.mangabaka.dev\";\nconst DEFAULT_TIMEOUT_SECONDS = 60;\nconst logger = createLogger({ name: \"mangabaka-api\", level: \"debug\" });\n\nexport interface MangaBakaClientOptions {\n /** Request timeout in seconds (default: 15) */\n timeout?: number;\n}\n\nexport class MangaBakaClient {\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n\n constructor(apiKey: string, options?: MangaBakaClientOptions) {\n if (!apiKey) {\n throw new AuthError(\"API key is required\");\n }\n this.apiKey = apiKey;\n this.timeoutMs = (options?.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000;\n logger.debug(`MangaBakaClient initialized with timeout: ${this.timeoutMs}ms`);\n }\n\n /**\n * Search for series by query\n */\n async search(\n query: string,\n page = 1,\n perPage = 20,\n ): Promise<{ data: MbSeries[]; total: number; page: number; totalPages: number }> {\n logger.debug(`Searching for: \"${query}\" (page ${page})`);\n\n const params = new URLSearchParams({\n q: query,\n page: String(page),\n limit: String(perPage),\n });\n\n const response = await this.request<MbSearchResponse>(`/v1/series/search?${params.toString()}`);\n\n return {\n data: response.data,\n total: response.pagination?.total ?? response.data.length,\n page: response.pagination?.page ?? page,\n totalPages: response.pagination?.total_pages ?? 1,\n };\n }\n\n /**\n * Get full series details by ID\n */\n async getSeries(id: number): Promise<MbSeries> {\n logger.debug(`Getting series: ${id}`);\n\n const response = await this.request<MbGetSeriesResponse>(`/v1/series/${id}`);\n\n return response.data;\n }\n\n /**\n * Make an authenticated request to the MangaBaka API\n */\n private async request<T>(path: string): Promise<T> {\n const url = `${BASE_URL}${path}`;\n const headers: Record<string, string> = {\n \"x-api-key\": this.apiKey,\n Accept: \"application/json\",\n };\n\n // Set up timeout using AbortController\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n logger.debug(`Request: ${path} (timeout: ${this.timeoutMs}ms)`);\n const response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const seconds = retryAfter ? Number.parseInt(retryAfter, 10) : 60;\n throw new RateLimitError(seconds);\n }\n\n // Handle auth errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthError(\"Invalid API key\");\n }\n\n // Handle not found\n if (response.status === 404) {\n throw new NotFoundError(`Resource not found: ${path}`);\n }\n\n // Handle other errors\n if (!response.ok) {\n const text = await response.text();\n logger.error(`API error: ${response.status}`, { body: text });\n throw new ApiError(`API error: ${response.status} ${response.statusText}`, response.status);\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n // Handle timeout (abort)\n if (error instanceof Error && error.name === \"AbortError\") {\n logger.error(`Request timed out after ${this.timeoutMs}ms: ${path}`);\n throw new ApiError(`Request timed out after ${this.timeoutMs / 1000}s`);\n }\n\n // Re-throw plugin errors\n if (\n error instanceof RateLimitError ||\n error instanceof AuthError ||\n error instanceof NotFoundError ||\n error instanceof ApiError\n ) {\n throw error;\n }\n\n // Wrap other errors\n const message = error instanceof Error ? error.message : \"Unknown error\";\n logger.error(\"Request failed\", error);\n throw new ApiError(`Request failed: ${message}`);\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n", "/**\n * Mappers to convert MangaBaka API responses to Codex plugin protocol types\n */\n\nimport type {\n AlternateTitle,\n ExternalId,\n ExternalLink,\n ExternalRating,\n PluginSeriesMetadata,\n ReadingDirection,\n SearchResult,\n SeriesStatus,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MbContentRating, MbSeries, MbSeriesType, MbStatus } from \"./types.js\";\n\n/**\n * Strip HTML tags from text, converting <br> to newlines\n */\nfunction stripHtml(html: string | undefined | null): string | undefined {\n if (!html) return undefined;\n return html\n .replace(/<br\\s*\\/?>/gi, \"\\n\") // Convert <br> to newlines\n .replace(/<[^>]*>/g, \"\") // Strip remaining HTML tags\n .trim();\n}\n\n/**\n * Map MangaBaka status to protocol SeriesStatus\n * MangaBaka uses: cancelled, completed, hiatus, releasing, unknown, upcoming\n * Codex uses: ongoing, ended, hiatus, abandoned, unknown\n */\nfunction mapStatus(mbStatus: MbStatus): SeriesStatus {\n switch (mbStatus) {\n case \"completed\":\n return \"ended\";\n case \"releasing\":\n case \"upcoming\":\n return \"ongoing\";\n case \"hiatus\":\n return \"hiatus\";\n case \"cancelled\":\n return \"abandoned\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Format genre from snake_case to Title Case\n */\nfunction formatGenre(genre: string): string {\n return genre\n .split(\"_\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/**\n * Detect language code from country of origin\n */\nfunction detectLanguageFromCountry(country: string | null | undefined): string | undefined {\n if (!country) return undefined;\n\n const countryLower = country.toLowerCase();\n if (countryLower === \"jp\" || countryLower === \"japan\") return \"ja\";\n if (countryLower === \"kr\" || countryLower === \"korea\" || countryLower === \"south korea\")\n return \"ko\";\n if (countryLower === \"cn\" || countryLower === \"china\") return \"zh\";\n if (countryLower === \"tw\" || countryLower === \"taiwan\") return \"zh-TW\";\n\n return undefined;\n}\n\n/**\n * Map MangaBaka content rating to numeric age rating\n */\nfunction mapContentRating(rating: MbContentRating | null | undefined): number | undefined {\n if (!rating) return undefined;\n\n switch (rating) {\n case \"safe\":\n return 0; // All ages\n case \"suggestive\":\n return 13; // Teen\n case \"erotica\":\n return 16; // Mature\n case \"pornographic\":\n return 18; // Adults only\n default:\n return undefined;\n }\n}\n\n/**\n * Extract rating value from either a number or an object with bayesian/average\n */\nfunction extractRating(\n rating: number | { bayesian?: number | null; average?: number | null } | null | undefined,\n): number | undefined {\n if (rating == null) return undefined;\n if (typeof rating === \"number\") return rating;\n return rating.bayesian ?? rating.average ?? undefined;\n}\n\n/**\n * Infer reading direction from series type and country\n */\nfunction inferReadingDirection(\n seriesType: MbSeriesType,\n country: string | null | undefined,\n): ReadingDirection | undefined {\n // Manhwa (Korean) and Manhua (Chinese) are typically left-to-right\n if (seriesType === \"manhwa\" || seriesType === \"manhua\") {\n return \"ltr\";\n }\n\n // Manga (Japanese) is typically right-to-left\n if (seriesType === \"manga\") {\n return \"rtl\";\n }\n\n // OEL (Original English Language) is left-to-right\n if (seriesType === \"oel\") {\n return \"ltr\";\n }\n\n // Fall back to country-based detection\n if (country) {\n const countryLower = country.toLowerCase();\n if (countryLower === \"jp\" || countryLower === \"japan\") return \"rtl\";\n if (countryLower === \"kr\" || countryLower === \"korea\" || countryLower === \"south korea\")\n return \"ltr\";\n if (countryLower === \"cn\" || countryLower === \"china\") return \"ltr\";\n if (countryLower === \"tw\" || countryLower === \"taiwan\") return \"ltr\";\n }\n\n return undefined;\n}\n\n/**\n * Map a MangaBaka series to a protocol SearchResult\n */\nexport function mapSearchResult(series: MbSeries): SearchResult {\n // Get cover URL - prefer x250 for search results\n const coverUrl = series.cover?.x250?.x1 ?? series.cover?.raw?.url ?? undefined;\n\n // Build alternate titles array\n const alternateTitles: string[] = [];\n if (series.native_title && series.native_title !== series.title) {\n alternateTitles.push(series.native_title);\n }\n if (series.romanized_title && series.romanized_title !== series.title) {\n alternateTitles.push(series.romanized_title);\n }\n\n // Note: relevanceScore is omitted - the API already returns results in relevance order\n return {\n externalId: String(series.id),\n title: series.title,\n alternateTitles,\n year: series.year ?? undefined,\n coverUrl: coverUrl ?? undefined,\n preview: {\n status: mapStatus(series.status),\n genres: (series.genres ?? []).slice(0, 3).map(formatGenre),\n rating: extractRating(series.rating),\n description: stripHtml(series.description)?.slice(0, 200) ?? undefined,\n bookCount: series.final_volume ? Number.parseInt(series.final_volume, 10) : undefined,\n },\n };\n}\n\n/**\n * Map full series response to protocol PluginSeriesMetadata\n */\nexport function mapSeriesMetadata(series: MbSeries): PluginSeriesMetadata {\n // Build alternate titles array with language info\n const alternateTitles: AlternateTitle[] = [];\n\n // Add native title\n if (series.native_title && series.native_title !== series.title) {\n alternateTitles.push({\n title: series.native_title,\n language: detectLanguageFromCountry(series.country_of_origin),\n titleType: \"native\",\n });\n }\n\n // Add romanized title\n if (series.romanized_title && series.romanized_title !== series.title) {\n alternateTitles.push({\n title: series.romanized_title,\n language: \"en\",\n titleType: \"romaji\",\n });\n }\n\n // Add secondary titles from all languages\n if (series.secondary_titles) {\n for (const [langCode, titleList] of Object.entries(series.secondary_titles)) {\n if (titleList) {\n for (const titleEntry of titleList) {\n if (titleEntry.title !== series.title) {\n alternateTitles.push({\n title: titleEntry.title,\n language: langCode,\n });\n }\n }\n }\n }\n }\n\n // Extract authors and artists as string arrays\n const authors = series.authors ?? [];\n const artists = series.artists ?? [];\n\n // Format genres\n const genres = (series.genres ?? []).map(formatGenre);\n\n // Get cover URL - prefer raw for full metadata\n const coverUrl = series.cover?.raw?.url ?? series.cover?.x350?.x1 ?? undefined;\n\n // Build external links from sources\n // Always include MangaBaka link first\n const externalLinks: ExternalLink[] = [\n {\n url: `https://mangabaka.org/${series.id}`,\n label: \"MangaBaka\",\n linkType: \"provider\",\n },\n ];\n\n // Source configuration: display name, rating key, and URL pattern\n // URL pattern uses {id} as placeholder for the source ID\n const sourceConfig: Record<string, { label: string; ratingKey: string; urlPattern?: string }> = {\n anilist: {\n label: \"AniList\",\n ratingKey: \"anilist\",\n urlPattern: \"https://anilist.co/manga/{id}\",\n },\n my_anime_list: {\n label: \"MyAnimeList\",\n ratingKey: \"myanimelist\",\n urlPattern: \"https://myanimelist.net/manga/{id}\",\n },\n mangadex: {\n label: \"MangaDex\",\n ratingKey: \"mangadex\",\n urlPattern: \"https://mangadex.org/title/{id}\",\n },\n manga_updates: {\n label: \"MangaUpdates\",\n ratingKey: \"mangaupdates\",\n urlPattern: \"https://www.mangaupdates.com/series/{id}\",\n },\n kitsu: { label: \"Kitsu\", ratingKey: \"kitsu\", urlPattern: \"https://kitsu.app/manga/{id}\" },\n anime_planet: {\n label: \"Anime-Planet\",\n ratingKey: \"animeplanet\",\n urlPattern: \"https://www.anime-planet.com/manga/{id}\",\n },\n anime_news_network: { label: \"Anime News Network\", ratingKey: \"animenewsnetwork\" },\n shikimori: {\n label: \"Shikimori\",\n ratingKey: \"shikimori\",\n urlPattern: \"https://shikimori.one/mangas/{id}\",\n },\n };\n\n // Build external links, ratings, and cross-reference IDs from sources in a single pass\n const externalRatings: ExternalRating[] = [];\n const externalIds: ExternalId[] = [\n // Always include the plugin's own API ID so other plugins can cross-reference\n { source: \"api:mangabaka\", externalId: String(series.id) },\n ];\n\n if (series.source) {\n for (const [key, info] of Object.entries(series.source)) {\n if (!info) continue;\n\n const config = sourceConfig[key];\n // Use config if available, otherwise generate defaults from key\n const ratingKey = config?.ratingKey ?? key.replace(/_/g, \"\");\n\n // Add cross-reference external ID with api: prefix\n if (info.id != null) {\n externalIds.push({\n source: `api:${ratingKey}`,\n externalId: String(info.id),\n });\n }\n\n // Add external link if source has an ID and URL pattern\n if (info.id != null && config?.urlPattern) {\n externalLinks.push({\n url: config.urlPattern.replace(\"{id}\", String(info.id)),\n label: config.label,\n linkType: \"provider\",\n });\n }\n\n // Add external rating if source has a normalized rating\n if (info.rating_normalized != null) {\n externalRatings.push({ score: info.rating_normalized, source: ratingKey });\n }\n }\n }\n\n // Get publisher name (pick first one if available)\n const publisher = series.publishers?.[0]?.name ?? undefined;\n\n return {\n externalId: String(series.id),\n externalUrl: `https://mangabaka.org/${series.id}`,\n title: series.title,\n alternateTitles,\n summary: stripHtml(series.description),\n status: mapStatus(series.status),\n year: series.year ?? undefined,\n // Extended metadata\n publisher,\n totalBookCount: series.final_volume ? Number.parseInt(series.final_volume, 10) : undefined,\n ageRating: mapContentRating(series.content_rating),\n readingDirection: inferReadingDirection(series.type, series.country_of_origin),\n // Taxonomy\n genres,\n tags: series.tags ?? [],\n authors,\n artists,\n coverUrl: coverUrl ?? undefined,\n rating: (() => {\n const r = extractRating(series.rating);\n return r != null ? { score: r, source: \"mangabaka\" } : undefined;\n })(),\n externalRatings: externalRatings.length > 0 ? externalRatings : undefined,\n externalLinks,\n externalIds,\n };\n}\n", "import {\n type MetadataGetParams,\n NotFoundError,\n type PluginSeriesMetadata,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSeriesMetadata } from \"../mappers.js\";\n\nexport async function handleGet(\n params: MetadataGetParams,\n client: MangaBakaClient,\n): Promise<PluginSeriesMetadata> {\n const seriesId = Number.parseInt(params.externalId, 10);\n\n if (Number.isNaN(seriesId)) {\n throw new NotFoundError(`Invalid external ID: ${params.externalId}`);\n }\n\n const response = await client.getSeries(seriesId);\n\n return mapSeriesMetadata(response);\n}\n", "/**\n * Calculate string similarity using word overlap and containment scoring\n * Returns a value between 0 and 1\n */\nexport function similarity(a: string, b: string): number {\n const aLower = a.toLowerCase().trim();\n const bLower = b.toLowerCase().trim();\n\n if (aLower === bLower) return 1.0;\n if (aLower.length === 0 || bLower.length === 0) return 0;\n\n let score = 0;\n\n // Containment check with length-ratio penalty\n // Prevents short queries like \"Air\" from matching \"Air Gear\" too strongly\n const shorter = aLower.length <= bLower.length ? aLower : bLower;\n const longer = aLower.length <= bLower.length ? bLower : aLower;\n\n if (longer.includes(shorter)) {\n const lengthRatio = shorter.length / longer.length;\n score = Math.max(score, 0.8 * lengthRatio);\n }\n\n // Word overlap scoring (Jaccard similarity)\n const aWords = new Set(aLower.split(/\\s+/));\n const bWords = new Set(bLower.split(/\\s+/));\n const intersection = [...aWords].filter((w) => bWords.has(w));\n const union = new Set([...aWords, ...bWords]);\n\n if (union.size > 0) {\n score = Math.max(score, intersection.length / union.size);\n }\n\n return score;\n}\n", "import {\n createLogger,\n type MetadataMatchParams,\n type MetadataMatchResponse,\n type SearchResult,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSearchResult } from \"../mappers.js\";\nimport { similarity } from \"../similarity.js\";\n\nconst logger = createLogger({ name: \"mangabaka-match\", level: \"info\" });\n\n/**\n * Score a search result against the match parameters\n * Returns a value between 0 and 1\n */\nexport function scoreResult(result: SearchResult, params: MetadataMatchParams): number {\n let score = 0;\n\n // Find best title similarity across primary and alternate titles\n let bestTitleSimilarity = similarity(result.title, params.title);\n for (const alt of result.alternateTitles) {\n bestTitleSimilarity = Math.max(bestTitleSimilarity, similarity(alt, params.title));\n }\n\n // Title similarity (up to 0.6)\n score += bestTitleSimilarity * 0.6;\n\n // Year match (up to 0.2)\n if (params.year && result.year) {\n if (result.year === params.year) {\n score += 0.2;\n } else if (Math.abs(result.year - params.year) <= 1) {\n score += 0.1;\n }\n }\n\n // Boost for exact title match across primary and alternate titles (up to 0.2)\n const searchLower = params.title.toLowerCase();\n const hasExactMatch =\n result.title.toLowerCase() === searchLower ||\n result.alternateTitles.some((alt) => alt.toLowerCase() === searchLower);\n\n if (hasExactMatch) {\n score += 0.2;\n }\n\n return Math.min(1.0, score);\n}\n\nexport async function handleMatch(\n params: MetadataMatchParams,\n client: MangaBakaClient,\n): Promise<MetadataMatchResponse> {\n logger.debug(`Matching: \"${params.title}\"`);\n\n // Search for the title\n const response = await client.search(params.title, 1, 10);\n\n if (response.data.length === 0) {\n return {\n match: null,\n confidence: 0,\n };\n }\n\n // Map and score results\n const scoredResults = response.data\n .map((series) => {\n const result = mapSearchResult(series);\n const score = scoreResult(result, params);\n return { result, score };\n })\n .sort((a, b) => b.score - a.score);\n\n const best = scoredResults[0];\n\n if (!best) {\n return {\n match: null,\n confidence: 0,\n };\n }\n\n // If confidence is low, include alternatives\n const alternatives =\n best.score < 0.8\n ? scoredResults.slice(1, 4).map((s) => ({\n ...s.result,\n relevanceScore: s.score,\n }))\n : undefined;\n\n return {\n match: {\n ...best.result,\n relevanceScore: best.score,\n },\n confidence: best.score,\n alternatives,\n };\n}\n", "import {\n createLogger,\n type MetadataSearchParams,\n type MetadataSearchResponse,\n type SearchResult,\n} from \"@ashdev/codex-plugin-sdk\";\nimport type { MangaBakaClient } from \"../api.js\";\nimport { mapSearchResult } from \"../mappers.js\";\nimport { similarity } from \"../similarity.js\";\n\nconst logger = createLogger({ name: \"mangabaka-search\", level: \"debug\" });\n\n/**\n * Score a search result against the query using title similarity.\n * Checks both primary title and alternate titles, returning the best score.\n */\nexport function scoreSearchResult(result: SearchResult, query: string): number {\n let best = similarity(result.title, query);\n for (const alt of result.alternateTitles) {\n best = Math.max(best, similarity(alt, query));\n }\n return best;\n}\n\nexport async function handleSearch(\n params: MetadataSearchParams,\n client: MangaBakaClient,\n): Promise<MetadataSearchResponse> {\n logger.debug(\"Search params received:\", params);\n\n const limit = params.limit ?? 20;\n\n // Parse cursor as page number (default to 1)\n const page = params.cursor ? Number.parseInt(params.cursor, 10) : 1;\n\n logger.debug(`Searching for: \"${params.query}\" (page ${page}, limit ${limit})`);\n\n const response = await client.search(params.query, page, limit);\n\n // Map results and score by similarity to the search query\n const results = response.data\n .map((series) => {\n const result = mapSearchResult(series);\n result.relevanceScore = scoreSearchResult(result, params.query);\n return result;\n })\n .sort((a, b) => (b.relevanceScore ?? 0) - (a.relevanceScore ?? 0));\n\n // Calculate next cursor (next page number) if there are more results\n const hasNextPage = response.page < response.totalPages;\n const nextCursor = hasNextPage ? String(response.page + 1) : undefined;\n\n return {\n results,\n nextCursor,\n };\n}\n", "{\n \"name\": \"@ashdev/codex-plugin-metadata-mangabaka\",\n \"version\": \"1.10.1\",\n \"description\": \"MangaBaka metadata provider plugin for Codex\",\n \"main\": \"dist/index.js\",\n \"bin\": \"dist/index.js\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/AshDevFr/codex.git\",\n \"directory\": \"plugins/metadata-mangabaka\"\n },\n \"scripts\": {\n \"build\": \"esbuild src/index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --sourcemap --banner:js='#!/usr/bin/env node'\",\n \"dev\": \"npm run build -- --watch\",\n \"clean\": \"rm -rf dist\",\n \"start\": \"node dist/index.js\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"npm run lint && npm run build\"\n },\n \"keywords\": [\n \"codex\",\n \"plugin\",\n \"mangabaka\",\n \"manga\",\n \"metadata\"\n ],\n \"author\": \"Codex\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"dependencies\": {\n \"@ashdev/codex-plugin-sdk\": \"^1.10.1\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.3.13\",\n \"@types/node\": \"^22.0.0\",\n \"esbuild\": \"^0.24.0\",\n \"typescript\": \"^5.7.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n", "import type { MetadataContentType, PluginManifest } from \"@ashdev/codex-plugin-sdk\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const manifest = {\n name: \"metadata-mangabaka\",\n displayName: \"MangaBaka Metadata\",\n version: packageJson.version,\n description: \"Fetch manga metadata from MangaBaka - aggregated data from multiple sources\",\n author: \"Codex\",\n homepage: \"https://mangabaka.org\",\n protocolVersion: \"1.0\",\n capabilities: {\n metadataProvider: [\"series\"] as MetadataContentType[],\n },\n requiredCredentials: [\n {\n key: \"api_key\",\n label: \"API Key\",\n description: \"Get your API key at https://mangabaka.org/settings/api (requires account)\",\n required: true,\n sensitive: true,\n type: \"password\",\n placeholder: \"mb-...\",\n },\n ],\n configSchema: {\n description: \"Optional configuration for the MangaBaka plugin\",\n fields: [\n {\n key: \"timeout\",\n label: \"Request Timeout\",\n description: \"HTTP request timeout in seconds for API calls to MangaBaka\",\n type: \"number\",\n required: false,\n default: 60,\n example: 30,\n },\n ],\n },\n} as const satisfies PluginManifest & {\n capabilities: { metadataProvider: MetadataContentType[] };\n};\n", "/**\n * MangaBaka Plugin - Fetch manga metadata from MangaBaka\n *\n * MangaBaka aggregates metadata from multiple sources (AniList, MAL, MangaDex, etc.)\n * and provides a unified API for manga/novel metadata.\n *\n * API docs: https://mangabaka.org/api\n *\n * Credentials are provided by Codex via the initialize message.\n * Required credential: api_key (get one at https://mangabaka.org/settings/api)\n */\n\nimport {\n ConfigError,\n createLogger,\n createMetadataPlugin,\n type InitializeParams,\n type MetadataProvider,\n} from \"@ashdev/codex-plugin-sdk\";\nimport { MangaBakaClient } from \"./api.js\";\nimport { handleGet } from \"./handlers/get.js\";\nimport { handleMatch } from \"./handlers/match.js\";\nimport { handleSearch } from \"./handlers/search.js\";\nimport { manifest } from \"./manifest.js\";\n\nconst logger = createLogger({ name: \"mangabaka\", level: \"info\" });\n\n// Client is initialized when we receive credentials from Codex\nlet client: MangaBakaClient | null = null;\n\nfunction getClient(): MangaBakaClient {\n if (!client) {\n throw new ConfigError(\"Plugin not initialized - missing API key\");\n }\n return client;\n}\n\n// Create the MetadataProvider implementation\nconst provider: MetadataProvider = {\n async search(params) {\n return handleSearch(params, getClient());\n },\n\n async get(params) {\n return handleGet(params, getClient());\n },\n\n async match(params) {\n return handleMatch(params, getClient());\n },\n};\n\n// Start the plugin server\ncreateMetadataPlugin({\n manifest,\n provider,\n logLevel: \"info\",\n onInitialize(params: InitializeParams) {\n const apiKey = params.credentials?.api_key;\n if (!apiKey) {\n throw new ConfigError(\"api_key credential is required\");\n }\n\n // Get optional timeout from config (in seconds)\n const timeout = params.adminConfig?.timeout as number | undefined;\n\n client = new MangaBakaClient(apiKey, { timeout });\n logger.info(`MangaBaka client initialized (timeout: ${timeout ?? \"default\"}s)`);\n },\n});\n\nlogger.info(\"MangaBaka plugin started\");\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["manifest", "logger", "response", "provider", "client", "logger", "client", "logger", "client", "logger"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ashdev/codex-plugin-metadata-mangabaka",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "MangaBaka metadata provider plugin for Codex",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=22.0.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@ashdev/codex-plugin-sdk": "^1.
|
|
42
|
+
"@ashdev/codex-plugin-sdk": "^1.10.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@biomejs/biome": "^2.3.13",
|