@zivue/zuuid 0.1.0 → 0.2.0

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.
Files changed (203) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/README.md +210 -227
  3. package/dist/client.d.ts +16 -3
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +22 -0
  6. package/dist/entity.d.ts.map +1 -1
  7. package/dist/entity.js +9 -0
  8. package/dist/index.d.ts +11 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +11 -0
  11. package/dist/providers/comicvine/character.d.ts +2 -0
  12. package/dist/providers/comicvine/character.d.ts.map +1 -0
  13. package/dist/providers/comicvine/character.js +1 -0
  14. package/dist/providers/comicvine/constants.d.ts +8 -0
  15. package/dist/providers/comicvine/constants.d.ts.map +1 -0
  16. package/dist/providers/comicvine/constants.js +7 -0
  17. package/dist/providers/comicvine/index.d.ts +9 -0
  18. package/dist/providers/comicvine/index.d.ts.map +1 -0
  19. package/dist/providers/comicvine/index.js +8 -0
  20. package/dist/providers/comicvine/issue.d.ts +2 -0
  21. package/dist/providers/comicvine/issue.d.ts.map +1 -0
  22. package/dist/providers/comicvine/issue.js +1 -0
  23. package/dist/providers/comicvine/person.d.ts +2 -0
  24. package/dist/providers/comicvine/person.d.ts.map +1 -0
  25. package/dist/providers/comicvine/person.js +1 -0
  26. package/dist/providers/comicvine/publisher.d.ts +2 -0
  27. package/dist/providers/comicvine/publisher.d.ts.map +1 -0
  28. package/dist/providers/comicvine/publisher.js +1 -0
  29. package/dist/providers/comicvine/story-arc.d.ts +2 -0
  30. package/dist/providers/comicvine/story-arc.d.ts.map +1 -0
  31. package/dist/providers/comicvine/story-arc.js +1 -0
  32. package/dist/providers/comicvine/transform.d.ts +4 -0
  33. package/dist/providers/comicvine/transform.d.ts.map +1 -0
  34. package/dist/providers/comicvine/transform.js +63 -0
  35. package/dist/providers/comicvine/volume.d.ts +2 -0
  36. package/dist/providers/comicvine/volume.d.ts.map +1 -0
  37. package/dist/providers/comicvine/volume.js +1 -0
  38. package/dist/providers/common.d.ts +23 -0
  39. package/dist/providers/common.d.ts.map +1 -0
  40. package/dist/providers/common.js +132 -0
  41. package/dist/providers/gamesdb/constants.d.ts +4 -0
  42. package/dist/providers/gamesdb/constants.d.ts.map +1 -0
  43. package/dist/providers/gamesdb/constants.js +3 -0
  44. package/dist/providers/gamesdb/game.d.ts +7 -0
  45. package/dist/providers/gamesdb/game.d.ts.map +1 -0
  46. package/dist/providers/gamesdb/game.js +59 -0
  47. package/dist/providers/gamesdb/index.d.ts +4 -0
  48. package/dist/providers/gamesdb/index.d.ts.map +1 -0
  49. package/dist/providers/gamesdb/index.js +3 -0
  50. package/dist/providers/gamesdb/platform.d.ts +4 -0
  51. package/dist/providers/gamesdb/platform.d.ts.map +1 -0
  52. package/dist/providers/gamesdb/platform.js +23 -0
  53. package/dist/providers/jikan/anime.d.ts +2 -0
  54. package/dist/providers/jikan/anime.d.ts.map +1 -0
  55. package/dist/providers/jikan/anime.js +1 -0
  56. package/dist/providers/jikan/character.d.ts +2 -0
  57. package/dist/providers/jikan/character.d.ts.map +1 -0
  58. package/dist/providers/jikan/character.js +1 -0
  59. package/dist/providers/jikan/constants.d.ts +8 -0
  60. package/dist/providers/jikan/constants.d.ts.map +1 -0
  61. package/dist/providers/jikan/constants.js +7 -0
  62. package/dist/providers/jikan/index.d.ts +9 -0
  63. package/dist/providers/jikan/index.d.ts.map +1 -0
  64. package/dist/providers/jikan/index.js +8 -0
  65. package/dist/providers/jikan/magazine.d.ts +2 -0
  66. package/dist/providers/jikan/magazine.d.ts.map +1 -0
  67. package/dist/providers/jikan/magazine.js +1 -0
  68. package/dist/providers/jikan/manga.d.ts +2 -0
  69. package/dist/providers/jikan/manga.d.ts.map +1 -0
  70. package/dist/providers/jikan/manga.js +1 -0
  71. package/dist/providers/jikan/person.d.ts +2 -0
  72. package/dist/providers/jikan/person.d.ts.map +1 -0
  73. package/dist/providers/jikan/person.js +1 -0
  74. package/dist/providers/jikan/producer.d.ts +2 -0
  75. package/dist/providers/jikan/producer.d.ts.map +1 -0
  76. package/dist/providers/jikan/producer.js +1 -0
  77. package/dist/providers/jikan/transform.d.ts +8 -0
  78. package/dist/providers/jikan/transform.d.ts.map +1 -0
  79. package/dist/providers/jikan/transform.js +125 -0
  80. package/dist/providers/musicbrainz/artist.d.ts +4 -0
  81. package/dist/providers/musicbrainz/artist.d.ts.map +1 -0
  82. package/dist/providers/musicbrainz/artist.js +28 -0
  83. package/dist/providers/musicbrainz/constants.d.ts +10 -0
  84. package/dist/providers/musicbrainz/constants.d.ts.map +1 -0
  85. package/dist/providers/musicbrainz/constants.js +9 -0
  86. package/dist/providers/musicbrainz/helpers.d.ts +15 -0
  87. package/dist/providers/musicbrainz/helpers.d.ts.map +1 -0
  88. package/dist/providers/musicbrainz/helpers.js +71 -0
  89. package/dist/providers/musicbrainz/index.d.ts +8 -0
  90. package/dist/providers/musicbrainz/index.d.ts.map +1 -0
  91. package/dist/providers/musicbrainz/index.js +7 -0
  92. package/dist/providers/musicbrainz/label.d.ts +4 -0
  93. package/dist/providers/musicbrainz/label.d.ts.map +1 -0
  94. package/dist/providers/musicbrainz/label.js +28 -0
  95. package/dist/providers/musicbrainz/recording.d.ts +4 -0
  96. package/dist/providers/musicbrainz/recording.d.ts.map +1 -0
  97. package/dist/providers/musicbrainz/recording.js +41 -0
  98. package/dist/providers/musicbrainz/release-group.d.ts +7 -0
  99. package/dist/providers/musicbrainz/release-group.d.ts.map +1 -0
  100. package/dist/providers/musicbrainz/release-group.js +28 -0
  101. package/dist/providers/musicbrainz/release.d.ts +7 -0
  102. package/dist/providers/musicbrainz/release.d.ts.map +1 -0
  103. package/dist/providers/musicbrainz/release.js +50 -0
  104. package/dist/providers/musicbrainz/work.d.ts +4 -0
  105. package/dist/providers/musicbrainz/work.d.ts.map +1 -0
  106. package/dist/providers/musicbrainz/work.js +40 -0
  107. package/dist/providers/openfoodfacts/constants.d.ts +3 -0
  108. package/dist/providers/openfoodfacts/constants.d.ts.map +1 -0
  109. package/dist/providers/openfoodfacts/constants.js +2 -0
  110. package/dist/providers/openfoodfacts/index.d.ts +3 -0
  111. package/dist/providers/openfoodfacts/index.d.ts.map +1 -0
  112. package/dist/providers/openfoodfacts/index.js +2 -0
  113. package/dist/providers/openfoodfacts/product.d.ts +4 -0
  114. package/dist/providers/openfoodfacts/product.d.ts.map +1 -0
  115. package/dist/providers/openfoodfacts/product.js +29 -0
  116. package/dist/providers/openlibrary/author.d.ts +65 -0
  117. package/dist/providers/openlibrary/author.d.ts.map +1 -0
  118. package/dist/providers/openlibrary/author.js +228 -0
  119. package/dist/providers/openlibrary/book.d.ts +138 -0
  120. package/dist/providers/openlibrary/book.d.ts.map +1 -0
  121. package/dist/providers/openlibrary/book.js +535 -0
  122. package/dist/providers/openlibrary/client.d.ts +22 -0
  123. package/dist/providers/openlibrary/client.d.ts.map +1 -0
  124. package/dist/providers/openlibrary/client.js +61 -0
  125. package/dist/providers/openlibrary/constants.d.ts +4 -0
  126. package/dist/providers/openlibrary/constants.d.ts.map +1 -0
  127. package/dist/providers/openlibrary/constants.js +3 -0
  128. package/dist/providers/openlibrary/index.d.ts +6 -0
  129. package/dist/providers/openlibrary/index.d.ts.map +1 -0
  130. package/dist/providers/openlibrary/index.js +5 -0
  131. package/dist/providers/openlibrary/types.d.ts +23 -0
  132. package/dist/providers/openlibrary/types.d.ts.map +1 -0
  133. package/dist/providers/openlibrary/types.js +1 -0
  134. package/dist/providers/openstreetmap/constants.d.ts +6 -0
  135. package/dist/providers/openstreetmap/constants.d.ts.map +1 -0
  136. package/dist/providers/openstreetmap/constants.js +5 -0
  137. package/dist/providers/openstreetmap/index.d.ts +4 -0
  138. package/dist/providers/openstreetmap/index.d.ts.map +1 -0
  139. package/dist/providers/openstreetmap/index.js +3 -0
  140. package/dist/providers/openstreetmap/place.d.ts +4 -0
  141. package/dist/providers/openstreetmap/place.d.ts.map +1 -0
  142. package/dist/providers/openstreetmap/place.js +65 -0
  143. package/dist/providers/openstreetmap/venue.d.ts +2 -0
  144. package/dist/providers/openstreetmap/venue.d.ts.map +1 -0
  145. package/dist/providers/openstreetmap/venue.js +1 -0
  146. package/dist/providers/podcast/constants.d.ts +3 -0
  147. package/dist/providers/podcast/constants.d.ts.map +1 -0
  148. package/dist/providers/podcast/constants.js +2 -0
  149. package/dist/providers/podcast/index.d.ts +3 -0
  150. package/dist/providers/podcast/index.d.ts.map +1 -0
  151. package/dist/providers/podcast/index.js +2 -0
  152. package/dist/providers/podcast/podcast.d.ts +4 -0
  153. package/dist/providers/podcast/podcast.d.ts.map +1 -0
  154. package/dist/providers/podcast/podcast.js +30 -0
  155. package/dist/providers/setlistfm/artist.d.ts +2 -0
  156. package/dist/providers/setlistfm/artist.d.ts.map +1 -0
  157. package/dist/providers/setlistfm/artist.js +1 -0
  158. package/dist/providers/setlistfm/constants.d.ts +5 -0
  159. package/dist/providers/setlistfm/constants.d.ts.map +1 -0
  160. package/dist/providers/setlistfm/constants.js +4 -0
  161. package/dist/providers/setlistfm/index.d.ts +6 -0
  162. package/dist/providers/setlistfm/index.d.ts.map +1 -0
  163. package/dist/providers/setlistfm/index.js +5 -0
  164. package/dist/providers/setlistfm/setlist.d.ts +2 -0
  165. package/dist/providers/setlistfm/setlist.d.ts.map +1 -0
  166. package/dist/providers/setlistfm/setlist.js +1 -0
  167. package/dist/providers/setlistfm/transform.d.ts +7 -0
  168. package/dist/providers/setlistfm/transform.d.ts.map +1 -0
  169. package/dist/providers/setlistfm/transform.js +122 -0
  170. package/dist/providers/setlistfm/venue.d.ts +2 -0
  171. package/dist/providers/setlistfm/venue.d.ts.map +1 -0
  172. package/dist/providers/setlistfm/venue.js +1 -0
  173. package/dist/providers/ticketmaster/attraction.d.ts +2 -0
  174. package/dist/providers/ticketmaster/attraction.d.ts.map +1 -0
  175. package/dist/providers/ticketmaster/attraction.js +1 -0
  176. package/dist/providers/ticketmaster/constants.d.ts +5 -0
  177. package/dist/providers/ticketmaster/constants.d.ts.map +1 -0
  178. package/dist/providers/ticketmaster/constants.js +4 -0
  179. package/dist/providers/ticketmaster/event.d.ts +2 -0
  180. package/dist/providers/ticketmaster/event.d.ts.map +1 -0
  181. package/dist/providers/ticketmaster/event.js +1 -0
  182. package/dist/providers/ticketmaster/index.d.ts +6 -0
  183. package/dist/providers/ticketmaster/index.d.ts.map +1 -0
  184. package/dist/providers/ticketmaster/index.js +5 -0
  185. package/dist/providers/ticketmaster/transform.d.ts +7 -0
  186. package/dist/providers/ticketmaster/transform.d.ts.map +1 -0
  187. package/dist/providers/ticketmaster/transform.js +89 -0
  188. package/dist/providers/ticketmaster/venue.d.ts +2 -0
  189. package/dist/providers/ticketmaster/venue.d.ts.map +1 -0
  190. package/dist/providers/ticketmaster/venue.js +1 -0
  191. package/dist/providers/wger/constants.d.ts +4 -0
  192. package/dist/providers/wger/constants.d.ts.map +1 -0
  193. package/dist/providers/wger/constants.js +3 -0
  194. package/dist/providers/wger/equipment.d.ts +4 -0
  195. package/dist/providers/wger/equipment.d.ts.map +1 -0
  196. package/dist/providers/wger/equipment.js +22 -0
  197. package/dist/providers/wger/exercise.d.ts +4 -0
  198. package/dist/providers/wger/exercise.d.ts.map +1 -0
  199. package/dist/providers/wger/exercise.js +42 -0
  200. package/dist/providers/wger/index.d.ts +4 -0
  201. package/dist/providers/wger/index.d.ts.map +1 -0
  202. package/dist/providers/wger/index.js +3 -0
  203. package/package.json +201 -5
package/CHANGELOG.md CHANGED
@@ -1,6 +1,15 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0
3
+ ## 0.2.0 - 2026-05-24
4
+
5
+ - Added Open Library provider support for books and authors.
6
+ - Added transformer providers for ComicVine, GamesDB, Jikan, MusicBrainz, OpenFoodFacts, OpenStreetMap, podcast, Setlist.fm, Ticketmaster, and Wger.
7
+ - Added category subpath exports for new provider transformers.
8
+ - Added MusicBrainz transformers for releases, release groups, recordings, artists, labels, and works.
9
+ - Added fixture-backed fetch examples for transformer-only providers.
10
+ - Expanded category grouping for additional read, listen, play, visit, and people entity categories.
11
+
12
+ ## 0.1.0 - 2026-05-23
4
13
 
5
14
  - Added provider-stable ZUUID generation using UUID v5.
6
15
  - Added flat `ZuuidData` model with source metadata and provenance.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # @zivue/zuuid
2
2
 
3
- TypeScript helpers for fetching, searching, and transforming Zuuid datasets.
3
+ Search, fetch, and normalize media metadata from external providers into a shared Zivue/Zuuid data shape.
4
4
 
5
- Zuuid is the metadata, search, and indexing substrate for Zivue/Stareto. This package focuses on the client-side model: provider-stable UUIDs, source records, and normalized Zuuid datasets.
5
+ This package is meant to be used by apps that need provider-backed lookup and transformation, but do not want provider-specific response shapes leaking through the app. It currently supports TMDB movies, TV shows, and people, plus Open Library books and authors.
6
6
 
7
- Storage, caching, object keys, and persistence belong in a layer outside this package.
7
+ Storage, caching, indexing, review state, object-store keys, and persistence belong in a layer outside this package.
8
8
 
9
9
  ## Install
10
10
 
@@ -21,6 +21,9 @@ const zuuid = createZuuidClient({
21
21
  providers: {
22
22
  tmdb: {
23
23
  bearerToken: process.env.TMDB_BEARER_TOKEN!
24
+ },
25
+ openlibrary: {
26
+ // Open Library does not require credentials.
24
27
  }
25
28
  }
26
29
  });
@@ -29,98 +32,83 @@ const search = await zuuid.movie.tmdb?.search({ query: "Fight Club" });
29
32
  const selected = search?.results[0];
30
33
  const movie = selected ? await zuuid.movie.tmdb?.fetch({ id: selected.source.value }) : undefined;
31
34
 
32
- console.log(movie?.zuuid);
35
+ console.log(movie?.primaryTitle);
36
+ // Fight Club
33
37
  ```
34
38
 
35
- ## Generate A ZUUID
39
+ ## What You Get
36
40
 
37
- Zuuid generation is UUID v5:
41
+ The package has two main output shapes:
38
42
 
39
- ```txt
40
- uuid_v5(provider_namespace, "<normalized-category>:<external_id>")
41
- ```
42
-
43
- ```ts
44
- import { providerZuuid } from "@zivue/zuuid";
45
-
46
- const zuuid = await providerZuuid({
47
- provider: "tmdb",
48
- category: "movie",
49
- externalId: "550"
50
- });
51
-
52
- console.log(zuuid);
53
- // 1706d641-d381-5618-9425-d8cd8b35f898
54
- ```
43
+ - `SearchResponse<ZuuidSearchResult>` for search/list screens.
44
+ - `ZuuidData` for full fetched and transformed datasets.
55
45
 
56
- `category` is trimmed and lowercased. `externalId` is trimmed but otherwise preserved.
57
-
58
- ## Zuuid Dataset
46
+ Search is lightweight and paginated. Fetch returns the full normalized dataset for a selected provider ID.
59
47
 
60
48
  ```ts
61
- import { createZuuidData } from "@zivue/zuuid";
62
-
63
- const dataset = createZuuidData({
64
- zuuid: "1706d641-d381-5618-9425-d8cd8b35f898",
65
- category: "movie",
66
- primaryTitle: "Fight Club"
67
- });
68
- ```
49
+ const movies = await zuuid.movie.tmdb?.search({ query: "Fight Club" });
69
50
 
70
- The dataset shape is intentionally flat:
51
+ console.log(movies?.pagination);
52
+ // { page: 1, totalPages: 10, totalResults: 190 }
71
53
 
72
- ```ts
73
- type ZuuidData = {
74
- zuuid: string;
75
- kind: EntityKind;
76
- category: string;
77
- primaryTitle: string;
78
- primaryDate?: string;
79
- rating?: number;
80
- cover?: string;
81
- aliases: Alias[];
82
- descriptions: Description[];
83
- details: Detail[];
84
- media: MediaAsset[];
85
- relations: EntityRelation[];
86
- recommendations: RecommendationEdge[];
87
- tags: string[];
88
- externalIds: ExternalId[];
89
- provenance: Provenance[];
90
- };
54
+ console.log(movies?.results[0]);
55
+ // {
56
+ // id: "1706d641-d381-5618-9425-d8cd8b35f898",
57
+ // zuuid: "1706d641-d381-5618-9425-d8cd8b35f898",
58
+ // category: "movie",
59
+ // title: "Fight Club",
60
+ // date: "1999-10-15",
61
+ // cover: "https://image.tmdb.org/t/p/w500/...",
62
+ // rating: 8.4,
63
+ // weight: 20.0,
64
+ // relationType: null,
65
+ // attribute: null,
66
+ // order: null,
67
+ // source: { source: "tmdb", category: "movie", value: "550" }
68
+ // }
91
69
  ```
92
70
 
93
- Search results, relations, and recommendations use the same lightweight list item fields: `id`, `zuuid`, `category`, `title`, `date`, `cover`, `rating`, `weight`, `relationType`, `attribute`, and `order`. That lets transformed datasets and search results carry useful related-entity context before those related entities are fetched as full Zuuid datasets.
94
-
95
- Backend-only concerns such as record versions, flags, review state, index state, and object-store metadata are intentionally not part of this package's dataset shape.
96
-
97
- ## Source Metadata
98
-
99
- Source records are provider records before they are transformed into canonical entities. They carry the external provider key, raw JSON payload, content hash, and observation timestamps.
71
+ The full fetched dataset is flat and provider-normalized:
100
72
 
101
73
  ```ts
102
- import { attachSourceMetadata, createSourceRecord } from "@zivue/zuuid";
74
+ const movie = await zuuid.movie.tmdb?.fetch({ id: "550" });
103
75
 
104
- const source = await createSourceRecord({
105
- source: { provider: "tmdb", category: "movie", externalId: "550" },
106
- payload: { title: "Fight Club" },
107
- observedAt: "2026-05-21T00:00:00.000Z"
108
- });
109
-
110
- const withSource = attachSourceMetadata(dataset, source);
76
+ console.log(movie);
77
+ // {
78
+ // zuuid,
79
+ // kind: "watch",
80
+ // category: "movie",
81
+ // primaryTitle: "Fight Club",
82
+ // primaryDate: "1999-10-15",
83
+ // rating,
84
+ // cover,
85
+ // aliases,
86
+ // descriptions,
87
+ // details,
88
+ // media,
89
+ // relations,
90
+ // recommendations,
91
+ // tags,
92
+ // externalIds,
93
+ // provenance
94
+ // }
111
95
  ```
112
96
 
113
- `attachSourceMetadata` returns a new dataset with `externalIds` and `provenance` updated.
114
-
115
- ## TMDB Movies, TV, And People
97
+ Search results, relations, and recommendations share the same lightweight list item fields: `id`, `zuuid`, `category`, `title`, `date`, `cover`, `rating`, `weight`, `relationType`, `attribute`, and `order`.
116
98
 
117
- The first provider module supports fetching and transforming TMDB movies, TV shows, and people.
99
+ ## Supported Providers
118
100
 
119
101
  | Provider | Category | Search | Fetch | Transform |
120
102
  | --- | --- | --- | --- | --- |
121
103
  | TMDB | movie | yes | yes | yes |
122
104
  | TMDB | tv | yes | yes | yes |
123
105
  | TMDB | person | yes | yes | yes |
106
+ | Open Library | book | yes | yes | yes |
107
+ | Open Library | author | yes | yes | yes |
108
+
109
+ ## TMDB Credentials
110
+
111
+ `TmdbProvider` accepts either a TMDB API Read Access Token or a v3 API key:
124
112
 
125
113
  ```ts
126
114
  import { TmdbProvider } from "@zivue/zuuid/providers/tmdb";
@@ -129,240 +117,235 @@ const tmdb = new TmdbProvider({
129
117
  bearerToken: process.env.TMDB_BEARER_TOKEN!
130
118
  });
131
119
 
132
- const movie = await tmdb.fetchMovie({ id: 550 });
133
- const tv = await tmdb.fetchTv({ id: 1399 });
134
- const person = await tmdb.fetchPerson({ id: 287 });
135
-
136
- console.log(movie?.zuuid);
137
- // 1706d641-d381-5618-9425-d8cd8b35f898
120
+ // or
121
+ const tmdbWithApiKey = new TmdbProvider({
122
+ apiKey: process.env.TMDB_API_KEY!
123
+ });
138
124
  ```
139
125
 
140
- You can also split fetching from transformation:
141
-
142
- ```ts
143
- import { TmdbProvider, transformTmdbMovie, transformTmdbPerson, transformTmdbTv } from "@zivue/zuuid/providers/tmdb";
126
+ TMDB bearer tokens usually start with `eyJ...`; v3 API keys are shorter hex-like strings.
144
127
 
145
- const source = await tmdb.fetchMovieSourceRecord({ id: 550 });
146
- const movie = source ? await transformTmdbMovie(source) : undefined;
128
+ ## Search
147
129
 
148
- const tvSource = await tmdb.fetchTvSourceRecord({ id: 1399 });
149
- const tv = tvSource ? await transformTmdbTv(tvSource) : undefined;
130
+ Use the category-first client facade when your app may have several providers:
150
131
 
151
- const personSource = await tmdb.fetchPersonSourceRecord({ id: 287 });
152
- const person = personSource ? await transformTmdbPerson(personSource) : undefined;
132
+ ```ts
133
+ const movies = await zuuid.movie.tmdb?.search({ query: "Fight Club" });
134
+ const tvShows = await zuuid.tv.tmdb?.search({ query: "Game of Thrones" });
135
+ const people = await zuuid.people.tmdb?.search({ query: "Brad Pitt" });
136
+ const books = await zuuid.read.openlibrary?.search({ query: "The Lord of the Rings" });
137
+ const authors = await zuuid.people.openlibrary?.search({ query: "J. K. Rowling" });
153
138
  ```
154
139
 
155
- Search returns unified lightweight candidates. Use search to find candidate IDs, then fetch the selected item for the full transformed dataset:
140
+ Provider methods are also available directly:
156
141
 
157
142
  ```ts
158
143
  const movies = await tmdb.searchMovies({ query: "Fight Club" });
159
144
  const tvShows = await tmdb.searchTv({ query: "Game of Thrones" });
160
145
  const people = await tmdb.searchPeople({ query: "Brad Pitt" });
146
+ ```
161
147
 
162
- console.log(movies.pagination);
163
- // { page: 1, totalPages: 10, totalResults: 190 }
164
-
165
- const selectedMovie = movies.results[0];
166
- console.log(selectedMovie);
167
- // {
168
- // id: "1706d641-d381-5618-9425-d8cd8b35f898",
169
- // zuuid: "1706d641-d381-5618-9425-d8cd8b35f898",
170
- // category: "movie",
171
- // title: "Fight Club",
172
- // date: "1999-10-15",
173
- // cover: "https://image.tmdb.org/t/p/w500/...",
174
- // rating: 8.4,
175
- // weight: 20.0,
176
- // relationType: null,
177
- // attribute: null,
178
- // order: null,
179
- // source: { source: "tmdb", category: "movie", value: "550" }
180
- // }
148
+ ```ts
149
+ import { OpenLibraryProvider } from "@zivue/zuuid/providers/openlibrary";
181
150
 
182
- const fullMovie = selectedMovie ? await tmdb.fetchMovie({ id: selectedMovie.source.value }) : undefined;
151
+ const openlibrary = new OpenLibraryProvider();
152
+ const books = await openlibrary.searchBooks({ query: "The Lord of the Rings" });
153
+ const authors = await openlibrary.searchAuthors({ query: "J. K. Rowling" });
183
154
  ```
184
155
 
185
- Raw search source records are also available:
156
+ Search options include pagination and common TMDB filters:
186
157
 
187
158
  ```ts
188
- const rawMovies = await tmdb.searchMovieSourceRecords({ query: "Fight Club" });
159
+ const movies = await tmdb.searchMovies({
160
+ query: "Fight Club",
161
+ page: 2,
162
+ includeAdult: false,
163
+ primaryReleaseYear: 1999
164
+ });
189
165
  ```
190
166
 
191
- Category-specific imports are also available:
167
+ If you need the raw TMDB search payload wrapped as source records:
192
168
 
193
169
  ```ts
194
- import { transformTmdbMovie } from "@zivue/zuuid/providers/tmdb/movie";
195
- import { transformTmdbTv } from "@zivue/zuuid/providers/tmdb/tv";
196
- import { transformTmdbPerson } from "@zivue/zuuid/providers/tmdb/person";
170
+ const rawMovies = await tmdb.searchMovieSourceRecords({ query: "Fight Club" });
197
171
  ```
198
172
 
199
- `TmdbProvider` accepts either `{ bearerToken }` or `{ apiKey }`. TMDB bearer tokens are API Read Access Tokens and usually start with `eyJ...`; v3 API keys are shorter hex-like strings.
173
+ ## Fetch
200
174
 
201
- ## Client Instantiation
202
-
203
- For applications with multiple providers, use `createZuuidClient` to wire provider config once:
175
+ Fetch returns transformed `ZuuidData`:
204
176
 
205
177
  ```ts
206
- import { createZuuidClient } from "@zivue/zuuid";
207
-
208
- const zuuid = createZuuidClient({
209
- providers: {
210
- tmdb: {
211
- bearerToken: process.env.TMDB_BEARER_TOKEN!
212
- }
213
- // Future movie providers can sit beside tmdb, e.g. omdb.
214
- }
215
- });
216
-
217
178
  const movie = await zuuid.movie.tmdb?.fetch({ id: 550 });
218
179
  const tv = await zuuid.tv.tmdb?.fetch({ id: 1399 });
219
180
  const person = await zuuid.people.tmdb?.fetch({ id: 287 });
181
+ const book = await zuuid.read.openlibrary?.fetch({ id: "OL82563W" });
182
+ const author = await zuuid.people.openlibrary?.fetch({ id: "OL23919A" });
220
183
  ```
221
184
 
222
- The config is provider-keyed because apps usually manage credentials per provider. The client facade is category-first, so multiple movie providers can live under `zuuid.movie`:
185
+ Direct provider methods are equivalent:
223
186
 
224
187
  ```ts
225
- zuuid.movie.tmdb?.fetch({ id: 550 });
226
- zuuid.tv.tmdb?.fetch({ id: 1399 });
227
- zuuid.people.tmdb?.fetch({ id: 287 });
188
+ const movie = await tmdb.fetchMovie({ id: 550 });
189
+ const tv = await tmdb.fetchTv({ id: 1399 });
190
+ const person = await tmdb.fetchPerson({ id: 287 });
228
191
 
229
- zuuid.movie.tmdb?.search({ query: "Fight Club" });
230
- zuuid.tv.tmdb?.search({ query: "Game of Thrones" });
231
- zuuid.people.tmdb?.search({ query: "Brad Pitt" });
232
- // later: zuuid.movie.omdb?.fetch(...)
192
+ const book = await openlibrary.fetchBook({ id: "OL82563W" });
193
+ const author = await openlibrary.fetchAuthor({ id: "OL23919A" });
233
194
  ```
234
195
 
235
- The client is stateless: it does not cache, persist, schedule, or read environment variables. It only closes over provider configuration and exposes category/provider methods.
236
-
237
- ## API
238
-
239
- ## Package Structure
240
-
241
- The source is split by Zuuid responsibility:
242
-
243
- - `identity.ts`: provider namespaces and UUID v5 ZUUID generation
244
- - `entity.ts`: flat Zuuid data types and category helpers
245
- - `client.ts`: stateless package instantiator for configured providers
246
- - `providers/<provider>/index.ts`: provider module barrel
247
- - `providers/<provider>/client.ts`: shared provider client/config
248
- - `providers/<provider>/<category>.ts`: category-specific fetch and transform helpers
249
- - `providers/tmdb/movie.ts`: TMDB movie fetch and transform helpers
250
- - `providers/tmdb/tv.ts`: TMDB TV fetch and transform helpers
251
- - `providers/tmdb/person.ts`: TMDB person fetch and transform helpers
252
- - `source.ts`: source records, external IDs, and provenance
253
- - `hash.ts`: stable payload hashing
254
- - `uuid.ts`: UUID parsing/normalization and UUID v5 internals
255
- - `types.ts`: shared JSON value types
256
- - `index.ts`: public barrel exports
196
+ ## Raw Source Records And Transform
257
197
 
258
- ### `providerZuuid(input)`
198
+ For debugging, caching in your own layer, or custom transform timing, split fetch from transform:
259
199
 
260
- Generates a deterministic ZUUID for a provider/category/external ID.
261
-
262
- ### `providerNamespace(provider)`
200
+ ```ts
201
+ import { transformTmdbMovie } from "@zivue/zuuid/providers/tmdb";
263
202
 
264
- Returns the UUID namespace configured for a known provider.
203
+ const source = await tmdb.fetchMovieSourceRecord({ id: 550 });
204
+ const movie = source ? await transformTmdbMovie(source, tmdb.transformOptions()) : undefined;
205
+ ```
265
206
 
266
- ### `createZuuidData(input)`
207
+ Category-specific imports are available:
267
208
 
268
- Creates a normalized Zuuid dataset.
209
+ ```ts
210
+ import { transformTmdbMovie } from "@zivue/zuuid/providers/tmdb/movie";
211
+ import { transformTmdbTv } from "@zivue/zuuid/providers/tmdb/tv";
212
+ import { transformTmdbPerson } from "@zivue/zuuid/providers/tmdb/person";
213
+ import { transformOpenLibraryBook } from "@zivue/zuuid/providers/openlibrary/book";
214
+ import { transformOpenLibraryAuthor } from "@zivue/zuuid/providers/openlibrary/author";
215
+ ```
269
216
 
270
- ### `createSourceRecord(input)`
217
+ ## Data Model
271
218
 
272
- Creates a source record and computes the SHA-256 payload hash used for provenance.
219
+ `ZuuidData` is the full normalized dataset:
273
220
 
274
- ### `attachSourceMetadata(dataset, sourceRecord, confidence?)`
221
+ ```ts
222
+ type ZuuidData = {
223
+ zuuid: string;
224
+ kind: EntityKind;
225
+ category: string;
226
+ primaryTitle: string;
227
+ primaryDate?: string;
228
+ rating?: number;
229
+ cover?: string;
230
+ aliases: Alias[];
231
+ descriptions: Description[];
232
+ details: Detail[];
233
+ media: MediaAsset[];
234
+ relations: EntityRelation[];
235
+ recommendations: RecommendationEdge[];
236
+ tags: string[];
237
+ externalIds: ExternalId[];
238
+ provenance: Provenance[];
239
+ };
240
+ ```
275
241
 
276
- Returns a new dataset with external ID and provenance attached.
242
+ `Detail.value` can be any JSON value, so details can hold strings, numbers, booleans, arrays, or structured objects without duplicating `value` and `data` fields.
277
243
 
278
- ### `TmdbProvider`
244
+ ## ZUUIDs
279
245
 
280
- Fetches TMDB source records and transforms them into `ZuuidData`.
246
+ Every fetched dataset and unified search result includes a `zuuid`. This is a deterministic UUID v5 generated from the provider namespace, category, and external ID. It gives your app a stable cross-provider identifier while the provider's own ID remains available in `source` or `externalIds`.
281
247
 
282
- ### `transformTmdbMovie(sourceRecord, options?)`
248
+ ```ts
249
+ import { providerZuuid } from "@zivue/zuuid";
283
250
 
284
- Transforms an already-fetched TMDB movie source record into `ZuuidData`.
251
+ const zuuid = await providerZuuid({
252
+ provider: "tmdb",
253
+ category: "movie",
254
+ externalId: "550"
255
+ });
256
+ ```
285
257
 
286
- ### `transformTmdbTv(sourceRecord, options?)`
258
+ Most applications do not need to call `providerZuuid` directly; search and fetch do it internally.
287
259
 
288
- Transforms an already-fetched TMDB TV source record into `ZuuidData`.
260
+ ## Client Design
289
261
 
290
- ### `transformTmdbPerson(sourceRecord, options?)`
262
+ The client is stateless. It does not cache, persist, schedule, read environment variables, or write files. It only closes over provider configuration and exposes category/provider methods:
291
263
 
292
- Transforms an already-fetched TMDB person source record into `ZuuidData`.
264
+ ```ts
265
+ zuuid.movie.tmdb?.search({ query: "Fight Club" });
266
+ zuuid.movie.tmdb?.fetch({ id: 550 });
293
267
 
294
- ### `categoryFor(value)`
268
+ zuuid.tv.tmdb?.search({ query: "Game of Thrones" });
269
+ zuuid.tv.tmdb?.fetch({ id: 1399 });
295
270
 
296
- Normalizes a category and derives its entity kind.
271
+ zuuid.people.tmdb?.search({ query: "Brad Pitt" });
272
+ zuuid.people.tmdb?.fetch({ id: 287 });
273
+ zuuid.people.openlibrary?.search({ query: "J. K. Rowling" });
274
+ zuuid.people.openlibrary?.fetch({ id: "OL23919A" });
297
275
 
298
- ### `kindForCategory(category)`
276
+ zuuid.read.openlibrary?.search({ query: "The Lord of the Rings" });
277
+ zuuid.read.openlibrary?.fetch({ id: "OL82563W" });
278
+ ```
299
279
 
300
- Maps categories such as `movie`, `book`, `game`, `restaurant`, and `person` to broad kinds such as `watch`, `read`, `play`, `visit`, and `people`.
280
+ ## CLI Examples
301
281
 
302
- ## Development
282
+ The examples read `.env` from the repo root:
303
283
 
304
284
  ```sh
305
- npm install
306
- npm test
285
+ TMDB_BEARER_TOKEN=...
286
+ # or
287
+ TMDB_READ_ACCESS_TOKEN=...
288
+ # or
289
+ TMDB_API_KEY=...
307
290
  ```
308
291
 
309
- ## Try It
310
-
311
- Fetch and transform TMDB movie `550`:
292
+ Search a provider and print unified search results:
312
293
 
313
294
  ```sh
314
- TMDB_BEARER_TOKEN=... npm run example:tmdb-fetch -- movie 550
295
+ npm run example:search -- movie "Fight Club"
296
+ npm run example:search -- tv "Game of Thrones"
297
+ npm run example:search -- people "Brad Pitt"
298
+ npm run example:search -- book "The Lord of the Rings"
299
+ npm run example:search -- author "J. K. Rowling"
315
300
  ```
316
301
 
317
- or:
302
+ Fetch and transform a selected provider ID:
318
303
 
319
304
  ```sh
320
- TMDB_API_KEY=... npm run example:tmdb-fetch -- movie 550
305
+ npm run example:fetch -- movie 550
306
+ npm run example:fetch -- tv 1399
307
+ npm run example:fetch -- people 287
308
+ npm run example:fetch -- book OL82563W
309
+ npm run example:fetch -- author OL23919A
321
310
  ```
322
311
 
323
- Fetch and transform TMDB TV show `1399`:
312
+ The examples write debug output to `data/tmdb/...` or `data/openlibrary/...`.
324
313
 
325
- ```sh
326
- TMDB_BEARER_TOKEN=... npm run example:tmdb-fetch -- tv 1399
327
- ```
314
+ ## API Reference
328
315
 
329
- Fetch and transform TMDB person `287`:
316
+ Core exports:
330
317
 
331
- ```sh
332
- TMDB_BEARER_TOKEN=... npm run example:tmdb-fetch -- people 287
333
- ```
318
+ - `createZuuidClient(config)`
319
+ - `providerZuuid(input)`
320
+ - `providerNamespace(provider)`
321
+ - `categoryFor(value)`
322
+ - `kindForCategory(category)`
323
+ - `createSourceRecord(input)`
324
+ - `attachSourceMetadata(dataset, sourceRecord, confidence?)`
334
325
 
335
- Search TMDB and print unified search results:
326
+ Provider exports:
336
327
 
337
- ```sh
338
- npm run example:tmdb-search -- movie "Fight Club"
339
- npm run example:tmdb-search -- tv "Game of Thrones"
340
- npm run example:tmdb-search -- people "Brad Pitt"
341
- ```
328
+ - `TmdbProvider`
329
+ - `OpenLibraryProvider`
330
+ - `transformTmdbMovie(sourceRecord, options?)`
331
+ - `transformTmdbTv(sourceRecord, options?)`
332
+ - `transformTmdbPerson(sourceRecord, options?)`
333
+ - `transformOpenLibraryBook(sourceRecord, options?)`
334
+ - `transformOpenLibraryAuthor(sourceRecord, options?)`
335
+ - `searchTmdbMovies(provider, input, options?)`
336
+ - `searchTmdbTv(provider, input, options?)`
337
+ - `searchTmdbPeople(provider, input, options?)`
338
+ - `searchOpenLibraryBooks(provider, input, options?)`
339
+ - `searchOpenLibraryAuthors(provider, input, options?)`
342
340
 
343
- The example also reads `.env` from the repo root:
341
+ ## Development
344
342
 
345
343
  ```sh
346
- TMDB_BEARER_TOKEN=...
347
- # or
348
- TMDB_READ_ACCESS_TOKEN=...
349
- # or
350
- TMDB_API_KEY=...
344
+ npm install
345
+ npm test
346
+ npm pack --dry-run
351
347
  ```
352
348
 
353
- If both token and API key are present, the example uses the bearer token first. TMDB's API Read Access Token usually starts with `eyJ...`; the v3 API key is a shorter hex-like string.
354
-
355
- If `TMDB_API_KEY` accidentally contains a token starting with `eyJ`, the example treats it as a bearer token and sends it as `Authorization: Bearer ...`.
349
+ ## Package Boundary
356
350
 
357
- The example writes debug output to:
358
-
359
- ```txt
360
- data/tmdb/movie/550.raw.json
361
- data/tmdb/movie/550.zuuid.json
362
- data/tmdb/tv/1399.raw.json
363
- data/tmdb/tv/1399.zuuid.json
364
- data/tmdb/people/287.raw.json
365
- data/tmdb/people/287.zuuid.json
366
- data/tmdb/search/movie/fight-club.zuuid-search.json
367
- data/tmdb/search/movie/fight-club.raw-search.json
368
- ```
351
+ This package intentionally does not include storage, caching, object-store metadata, record versions, review state, index state, or backend flags. Those concerns should live in the consuming application or service.
package/dist/client.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { SearchResponse, ZuuidData, ZuuidSearchResult } from "./entity.js";
2
+ import { type FetchOpenLibraryAuthorInput, type FetchOpenLibraryBookInput, type OpenLibraryProviderOptions, type OpenLibrarySearchInput } from "./providers/openlibrary/index.js";
2
3
  import { type FetchTmdbMovieInput, type FetchTmdbPersonInput, type FetchTmdbTvInput, type TmdbProviderOptions, type TmdbSearchInput } from "./providers/tmdb/index.js";
3
4
  import type { SourceRecord } from "./source.js";
4
5
  export type ProviderConfigs = {
6
+ openlibrary?: OpenLibraryProviderOptions;
5
7
  tmdb?: TmdbProviderOptions;
6
8
  };
7
9
  export type ZuuidClientConfig = {
@@ -14,15 +16,26 @@ export type MovieProviderClient<TFetchInput> = {
14
16
  searchSourceRecords(input: TmdbSearchInput): Promise<SearchResponse<SourceRecord>>;
15
17
  transform(source: SourceRecord): Promise<ZuuidData>;
16
18
  };
19
+ export type ProviderClient<TFetchInput, TSearchInput> = {
20
+ fetch(input: TFetchInput): Promise<ZuuidData | undefined>;
21
+ fetchSourceRecord(input: TFetchInput): Promise<SourceRecord | undefined>;
22
+ search(input: TSearchInput): Promise<SearchResponse<ZuuidSearchResult>>;
23
+ searchSourceRecords(input: TSearchInput): Promise<SearchResponse<SourceRecord>>;
24
+ transform(source: SourceRecord): Promise<ZuuidData>;
25
+ };
17
26
  export type ZuuidClient = {
18
27
  movie: {
19
- tmdb?: MovieProviderClient<FetchTmdbMovieInput>;
28
+ tmdb?: ProviderClient<FetchTmdbMovieInput, TmdbSearchInput>;
20
29
  };
21
30
  tv: {
22
- tmdb?: MovieProviderClient<FetchTmdbTvInput>;
31
+ tmdb?: ProviderClient<FetchTmdbTvInput, TmdbSearchInput>;
23
32
  };
24
33
  people: {
25
- tmdb?: MovieProviderClient<FetchTmdbPersonInput>;
34
+ tmdb?: ProviderClient<FetchTmdbPersonInput, TmdbSearchInput>;
35
+ openlibrary?: ProviderClient<FetchOpenLibraryAuthorInput, OpenLibrarySearchInput>;
36
+ };
37
+ read: {
38
+ openlibrary?: ProviderClient<FetchOpenLibraryBookInput, OpenLibrarySearchInput>;
26
39
  };
27
40
  };
28
41
  export declare function createZuuidClient(config?: ZuuidClientConfig): ZuuidClient;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,WAAW,IAAI;IAC7C,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC1D,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3E,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IACnF,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;KACjD,CAAC;IACF,EAAE,EAAE;QACF,IAAI,CAAC,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;KAC9C,CAAC;IACF,MAAM,EAAE;QACN,IAAI,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;KAClD,CAAC;CACH,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,iBAAsB,GAAG,WAAW,CAsC7E"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,CAAC,EAAE,0BAA0B,CAAC;IACzC,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,WAAW,IAAI;IAC7C,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC1D,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC3E,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IACnF,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,cAAc,CAAC,WAAW,EAAE,YAAY,IAAI;IACtD,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC1D,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACxE,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAChF,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,cAAc,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;KAC7D,CAAC;IACF,EAAE,EAAE;QACF,IAAI,CAAC,EAAE,cAAc,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;KAC1D,CAAC;IACF,MAAM,EAAE;QACN,IAAI,CAAC,EAAE,cAAc,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;QAC7D,WAAW,CAAC,EAAE,cAAc,CAAC,2BAA2B,EAAE,sBAAsB,CAAC,CAAC;KACnF,CAAC;IACF,IAAI,EAAE;QACJ,WAAW,CAAC,EAAE,cAAc,CAAC,yBAAyB,EAAE,sBAAsB,CAAC,CAAC;KACjF,CAAC;CACH,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,iBAAsB,GAAG,WAAW,CA2D7E"}