feat(metadata): add Aladin Korean book metadata provider (#351)

* feat(metadata): add Aladin Korean book metadata provider

Add support for fetching Korean book metadata from Aladin OpenAPI.
Includes search by title/author/ISBN and lookup by ISBN-10/13.

- Add ALADIN to MetadataProviderKey in @bookorbit/types
- Add AladinProviderConfig to ProviderConfigurations
- Create AladinProvider with IdentifiableProvider interface
- Add mapper for Aladin API response to MetadataCandidate
- Register provider in MetadataFetchModule
- Add provider config merge, validation, and connection test
- Include 24 unit tests (provider + mapper)

* feat(client): add Aladin provider UI integration

* refactor(metadata): use 'Aladin' label and favicon-based icon

* feat(metadata): complete Aladin provider end-to-end wiring

Persist the Aladin ItemId across fetch, scoring, locks, and file metadata round-trip, and update the affected tests.

Co-authored-by: Kyungwook Park <288273+kyungw00k@users.noreply.github.com>

---------

Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
Co-authored-by: Kyungwook Park <288273+kyungw00k@users.noreply.github.com>
This commit is contained in:
Kyungwook Park
2026-06-18 04:33:35 +09:00
committed by GitHub
parent 9afddc34d2
commit 6677f2f5ea
63 changed files with 11843 additions and 12 deletions
+1
View File
@@ -177,6 +177,7 @@ export type BookMetadataRefreshPreviewFields = {
comicvineId?: string | null;
ranobedbId?: string | null;
lubimyczytacId?: string | null;
aladinId?: string | null;
audioMetadata?: {
narrators?: string[];
durationSeconds?: number | null;
+2
View File
@@ -25,6 +25,7 @@ export const COMMON_PROVIDER_BOOK_FILE_WRITE_FIELDS = [
"ranobedbId",
"koboId",
"lubimyczytacId",
"aladinId",
] as const;
export const COMIC_BOOK_FILE_WRITE_FIELDS = [
@@ -77,6 +78,7 @@ export const BOOK_FILE_WRITE_FIELD_LABELS = {
ranobedbId: "RanobeDB ID",
koboId: "Kobo ID",
lubimyczytacId: "LubimyCzytac ID",
aladinId: "Aladin ID",
comicIssueNumber: "Issue number",
comicVolumeName: "Volume",
comicPencillers: "Pencillers",
+1
View File
@@ -13,6 +13,7 @@ export const MetadataProviderKey = {
RANOBEDB: "ranobedb",
KOBO: "kobo",
LUBIMYCZYTAC: "lubimyczytac",
ALADIN: "aladin",
} as const;
export interface ComicMetadataFields {
+2
View File
@@ -28,6 +28,7 @@ export const BOOK_METADATA_LOCK_FIELDS = [
"comicvineId",
"ranobedbId",
"lubimyczytacId",
"aladinId",
"comicIssueNumber",
"comicVolumeName",
"comicStoryArcs",
@@ -88,6 +89,7 @@ export const BOOK_METADATA_LOCK_GROUPS: BookMetadataLockGroup[] = [
"comicvineId",
"ranobedbId",
"lubimyczytacId",
"aladinId",
],
},
{
@@ -115,6 +115,11 @@ export interface KoboProviderConfig {
language: string;
}
export interface AladinProviderConfig {
enabled: boolean;
ttbKey: string;
}
export interface ProviderConfigurations {
google: GoogleProviderConfig;
amazon: AmazonProviderConfig;
@@ -128,6 +133,7 @@ export interface ProviderConfigurations {
ranobedb: SimpleProviderConfig;
kobo: KoboProviderConfig;
lubimyczytac: SimpleProviderConfig;
aladin: AladinProviderConfig;
}
export interface ProviderStatus {
+3 -1
View File
@@ -21,7 +21,8 @@ export type MetadataScoreField =
| "hardcoverId"
| "openLibraryId"
| "itunesId"
| "koboId";
| "koboId"
| "aladinId";
export type MetadataScoreGroup = "core" | "publishing" | "classification" | "enrichment" | "providers";
@@ -55,6 +56,7 @@ export const METADATA_SCORE_FIELDS: Record<MetadataScoreField, MetadataScoreFiel
openLibraryId: { group: "providers", label: "Open Library ID", defaultWeight: 1 },
itunesId: { group: "providers", label: "iTunes ID", defaultWeight: 1 },
koboId: { group: "providers", label: "Kobo ID", defaultWeight: 1 },
aladinId: { group: "providers", label: "Aladin ID", defaultWeight: 1 },
};
export const METADATA_SCORE_GROUP_LABELS: Record<MetadataScoreGroup, string> = {