@zivue/zuuid 0.1.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 (49) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +368 -0
  4. package/dist/client.d.ts +29 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +39 -0
  7. package/dist/entity.d.ts +106 -0
  8. package/dist/entity.d.ts.map +1 -0
  9. package/dist/entity.js +101 -0
  10. package/dist/hash.d.ts +3 -0
  11. package/dist/hash.d.ts.map +1 -0
  12. package/dist/hash.js +9 -0
  13. package/dist/identity.d.ts +14 -0
  14. package/dist/identity.d.ts.map +1 -0
  15. package/dist/identity.js +39 -0
  16. package/dist/index.d.ts +9 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +8 -0
  19. package/dist/providers/tmdb/client.d.ts +30 -0
  20. package/dist/providers/tmdb/client.d.ts.map +1 -0
  21. package/dist/providers/tmdb/client.js +92 -0
  22. package/dist/providers/tmdb/constants.d.ts +5 -0
  23. package/dist/providers/tmdb/constants.d.ts.map +1 -0
  24. package/dist/providers/tmdb/constants.js +4 -0
  25. package/dist/providers/tmdb/index.d.ts +7 -0
  26. package/dist/providers/tmdb/index.d.ts.map +1 -0
  27. package/dist/providers/tmdb/index.js +6 -0
  28. package/dist/providers/tmdb/movie.d.ts +164 -0
  29. package/dist/providers/tmdb/movie.d.ts.map +1 -0
  30. package/dist/providers/tmdb/movie.js +537 -0
  31. package/dist/providers/tmdb/person.d.ts +84 -0
  32. package/dist/providers/tmdb/person.d.ts.map +1 -0
  33. package/dist/providers/tmdb/person.js +345 -0
  34. package/dist/providers/tmdb/tv.d.ts +181 -0
  35. package/dist/providers/tmdb/tv.d.ts.map +1 -0
  36. package/dist/providers/tmdb/tv.js +522 -0
  37. package/dist/providers/tmdb/types.d.ts +36 -0
  38. package/dist/providers/tmdb/types.d.ts.map +1 -0
  39. package/dist/providers/tmdb/types.js +1 -0
  40. package/dist/source.d.ts +35 -0
  41. package/dist/source.d.ts.map +1 -0
  42. package/dist/source.js +53 -0
  43. package/dist/types.d.ts +5 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +1 -0
  46. package/dist/uuid.d.ts +3 -0
  47. package/dist/uuid.d.ts.map +1 -0
  48. package/dist/uuid.js +32 -0
  49. package/package.json +72 -0
@@ -0,0 +1,345 @@
1
+ import { createZuuidData } from "../../entity.js";
2
+ import { providerZuuid } from "../../identity.js";
3
+ import { attachSourceMetadata, createSourceRecord } from "../../source.js";
4
+ import { TMDB_POSTER_BASE_URL, TMDB_PROVIDER } from "./constants.js";
5
+ export const TMDB_PERSON_CATEGORY = "person";
6
+ export const ZUUID_PERSON_CATEGORY = "person";
7
+ export async function fetchTmdbPersonSourceRecord(provider, input) {
8
+ const id = String(input.id).trim();
9
+ if (!id) {
10
+ throw new Error("TMDB person id must not be empty");
11
+ }
12
+ if (!/^\d+$/.test(id)) {
13
+ throw new Error(`TMDB person id must be numeric: ${id}`);
14
+ }
15
+ const payload = await provider.getJson(`/person/${id}`, {
16
+ language: provider.language,
17
+ append_to_response: "combined_credits,external_ids,images"
18
+ });
19
+ if (!payload) {
20
+ return undefined;
21
+ }
22
+ return createSourceRecord({
23
+ source: { provider: TMDB_PROVIDER, category: TMDB_PERSON_CATEGORY, externalId: id },
24
+ payload: payload
25
+ });
26
+ }
27
+ export async function searchTmdbPersonSourceRecords(provider, input) {
28
+ const payload = await fetchTmdbPersonSearchResults(provider, input);
29
+ return {
30
+ results: await sourceRecordsFromSearchResults(TMDB_PERSON_CATEGORY, payload.results),
31
+ pagination: paginationFromTmdbSearchResponse(payload)
32
+ };
33
+ }
34
+ export async function searchTmdbPeople(provider, input, options = {}) {
35
+ const payload = await fetchTmdbPersonSearchResults(provider, input);
36
+ const searchResults = [];
37
+ for (const result of payload.results ?? []) {
38
+ if (!result.id) {
39
+ continue;
40
+ }
41
+ const externalId = String(result.id);
42
+ const title = stringField(result.name) ?? stringField(result.original_name);
43
+ if (!title) {
44
+ continue;
45
+ }
46
+ const zuuid = await providerZuuid({ provider: TMDB_PROVIDER, category: TMDB_PERSON_CATEGORY, externalId });
47
+ searchResults.push({
48
+ id: zuuid,
49
+ zuuid,
50
+ category: ZUUID_PERSON_CATEGORY,
51
+ title,
52
+ date: null,
53
+ cover: mediaUrl(result.profile_path ?? undefined, options.posterBaseUrl ?? TMDB_POSTER_BASE_URL) ?? null,
54
+ rating: null,
55
+ weight: typeof result.popularity === "number" ? result.popularity : null,
56
+ relationType: null,
57
+ attribute: stringField(result.known_for_department) ?? null,
58
+ order: null,
59
+ source: { source: TMDB_PROVIDER, category: TMDB_PERSON_CATEGORY, value: externalId }
60
+ });
61
+ }
62
+ return {
63
+ results: searchResults,
64
+ pagination: paginationFromTmdbSearchResponse(payload)
65
+ };
66
+ }
67
+ async function fetchTmdbPersonSearchResults(provider, input) {
68
+ const query = searchQuery(input.query, "TMDB person search query");
69
+ const payload = await provider.getJson("/search/person", {
70
+ ...searchParams(provider, input),
71
+ query
72
+ });
73
+ return payload ?? {};
74
+ }
75
+ export async function transformTmdbPerson(source, options = {}) {
76
+ if (source.source.provider !== TMDB_PROVIDER || source.source.category !== TMDB_PERSON_CATEGORY) {
77
+ throw new Error(`unsupported TMDB source: ${source.source.provider}:${source.source.category}`);
78
+ }
79
+ const payload = source.payload;
80
+ const tmdbId = tmdbPersonId(source, payload);
81
+ const name = stringField(payload.name);
82
+ if (!name) {
83
+ throw new Error("missing required TMDB person field: name");
84
+ }
85
+ const zuuid = await providerZuuid({
86
+ provider: TMDB_PROVIDER,
87
+ category: TMDB_PERSON_CATEGORY,
88
+ externalId: tmdbId
89
+ });
90
+ const data = createZuuidData({ zuuid, category: ZUUID_PERSON_CATEGORY, primaryTitle: name });
91
+ const birthday = stringField(payload.birthday ?? undefined);
92
+ if (birthday) {
93
+ validateDate(birthday, "birthday");
94
+ data.primaryDate = birthday;
95
+ }
96
+ const biography = stringField(payload.biography);
97
+ if (biography) {
98
+ data.descriptions.push({ value: biography, source: TMDB_PROVIDER });
99
+ }
100
+ for (const alias of payload.also_known_as ?? []) {
101
+ const value = stringField(alias);
102
+ if (value && value !== name && !data.aliases.some((item) => item.value === value)) {
103
+ data.aliases.push({ value, aliasType: "also_known_as", isPrimary: false, source: TMDB_PROVIDER });
104
+ }
105
+ }
106
+ addExternalIds(data, payload);
107
+ addImage(data, "profile", payload.profile_path ?? undefined, options.posterBaseUrl ?? TMDB_POSTER_BASE_URL, true);
108
+ addImages(data, payload, options);
109
+ data.cover = data.media.find((media) => media.mediaCategory === "profile")?.url;
110
+ addDetail(data, "known_for_department", payload.known_for_department);
111
+ addDetail(data, "birthday", payload.birthday ?? undefined);
112
+ addDetail(data, "deathday", payload.deathday ?? undefined);
113
+ addDetail(data, "place_of_birth", payload.place_of_birth ?? undefined);
114
+ addDetail(data, "homepage", payload.homepage ?? undefined);
115
+ addNumberDetail(data, "gender", payload.gender);
116
+ addNumberDetail(data, "popularity", payload.popularity);
117
+ addBooleanDetail(data, "adult", payload.adult);
118
+ await addCombinedCredits(data, payload, options);
119
+ return attachSourceMetadata(data, source);
120
+ }
121
+ function tmdbPersonId(source, payload) {
122
+ const sourceId = source.source.externalId.trim();
123
+ if (sourceId) {
124
+ return sourceId;
125
+ }
126
+ const payloadId = payload.id === undefined ? undefined : String(payload.id).trim();
127
+ if (payloadId) {
128
+ return payloadId;
129
+ }
130
+ throw new Error("missing required TMDB person field: id");
131
+ }
132
+ function addExternalIds(data, payload) {
133
+ const ids = payload.external_ids ?? {};
134
+ addExternalId(data, "imdb", ZUUID_PERSON_CATEGORY, stringField(ids.imdb_id ?? payload.imdb_id ?? undefined));
135
+ addExternalId(data, "wikidata", ZUUID_PERSON_CATEGORY, stringField(ids.wikidata_id ?? undefined));
136
+ addExternalId(data, "facebook", ZUUID_PERSON_CATEGORY, stringField(ids.facebook_id ?? undefined));
137
+ addExternalId(data, "instagram", ZUUID_PERSON_CATEGORY, stringField(ids.instagram_id ?? undefined));
138
+ addExternalId(data, "twitter", ZUUID_PERSON_CATEGORY, stringField(ids.twitter_id ?? undefined));
139
+ addExternalId(data, "tiktok", ZUUID_PERSON_CATEGORY, stringField(ids.tiktok_id ?? undefined));
140
+ addExternalId(data, "youtube", ZUUID_PERSON_CATEGORY, stringField(ids.youtube_id ?? undefined));
141
+ }
142
+ function addExternalId(data, source, category, value) {
143
+ if (!value || data.externalIds.some((id) => id.source === source && id.category === category && id.value === value)) {
144
+ return;
145
+ }
146
+ data.externalIds.push({ source, category, value });
147
+ }
148
+ function addImages(data, payload, options) {
149
+ for (const image of payload.images?.profiles ?? []) {
150
+ addImage(data, "profile", image.file_path, options.posterBaseUrl ?? TMDB_POSTER_BASE_URL, false, image);
151
+ }
152
+ }
153
+ function addImage(data, mediaCategory, path, baseUrl, isPrimary, image) {
154
+ const url = mediaUrl(path, baseUrl);
155
+ if (!url || data.media.some((media) => media.mediaCategory === mediaCategory && media.url === url)) {
156
+ if (isPrimary) {
157
+ const existing = data.media.find((media) => media.mediaCategory === mediaCategory && media.url === url);
158
+ if (existing) {
159
+ existing.isPrimary = true;
160
+ }
161
+ }
162
+ return;
163
+ }
164
+ data.media.push({
165
+ url,
166
+ mediaType: "image",
167
+ mediaCategory,
168
+ width: image?.width,
169
+ height: image?.height,
170
+ isPrimary,
171
+ data: compactImageData(image),
172
+ source: TMDB_PROVIDER
173
+ });
174
+ }
175
+ async function addCombinedCredits(data, payload, options) {
176
+ for (const [index, credit] of (payload.combined_credits?.cast ?? []).entries()) {
177
+ await addCreditRelation(data, credit, "appears_in", credit.character, index, options);
178
+ }
179
+ for (const [index, credit] of (payload.combined_credits?.crew ?? []).entries()) {
180
+ await addCreditRelation(data, credit, relationForCrewJob(credit.job ?? credit.department), credit.job ?? credit.department, index, options);
181
+ }
182
+ }
183
+ async function addCreditRelation(data, credit, relationType, attribute, order, options) {
184
+ if (!credit.id) {
185
+ return;
186
+ }
187
+ const category = categoryForMediaType(credit.media_type);
188
+ if (!category) {
189
+ return;
190
+ }
191
+ const title = stringField(credit.title) ?? stringField(credit.name) ?? stringField(credit.original_title) ?? stringField(credit.original_name);
192
+ if (!title) {
193
+ return;
194
+ }
195
+ const externalId = String(credit.id);
196
+ const zuuid = await providerZuuid({ provider: TMDB_PROVIDER, category: credit.media_type === "tv" ? "tv" : "movie", externalId });
197
+ const rating = typeof credit.vote_average === "number" ? credit.vote_average : null;
198
+ data.relations.push({
199
+ id: zuuid,
200
+ zuuid,
201
+ relationType,
202
+ direction: "outgoing",
203
+ title,
204
+ category,
205
+ date: stringField(credit.release_date) ?? stringField(credit.first_air_date) ?? null,
206
+ cover: mediaUrl(credit.poster_path ?? undefined, options.posterBaseUrl ?? TMDB_POSTER_BASE_URL) ?? null,
207
+ rating,
208
+ weight: rating,
209
+ source: TMDB_PROVIDER,
210
+ externalId,
211
+ attribute: stringField(attribute) ?? null,
212
+ order,
213
+ data: compactCreditData(credit)
214
+ });
215
+ }
216
+ function compactCreditData(credit) {
217
+ const value = {};
218
+ if (credit.credit_id) {
219
+ value.creditId = credit.credit_id;
220
+ }
221
+ if (credit.release_date) {
222
+ value.releaseDate = credit.release_date;
223
+ }
224
+ if (credit.first_air_date) {
225
+ value.firstAirDate = credit.first_air_date;
226
+ }
227
+ if (typeof credit.vote_average === "number") {
228
+ value.voteAverage = credit.vote_average;
229
+ }
230
+ if (typeof credit.episode_count === "number") {
231
+ value.episodeCount = credit.episode_count;
232
+ }
233
+ return Object.keys(value).length ? value : undefined;
234
+ }
235
+ function compactImageData(image) {
236
+ if (!image) {
237
+ return undefined;
238
+ }
239
+ const value = {};
240
+ if (typeof image.aspect_ratio === "number") {
241
+ value.aspectRatio = image.aspect_ratio;
242
+ }
243
+ if (typeof image.vote_average === "number") {
244
+ value.voteAverage = image.vote_average;
245
+ }
246
+ if (typeof image.vote_count === "number") {
247
+ value.voteCount = image.vote_count;
248
+ }
249
+ return Object.keys(value).length ? value : undefined;
250
+ }
251
+ function addDetail(data, key, value) {
252
+ const normalized = stringField(value);
253
+ if (normalized) {
254
+ data.details.push({ key, value: normalized, source: TMDB_PROVIDER });
255
+ }
256
+ }
257
+ function addNumberDetail(data, key, value) {
258
+ if (typeof value === "number") {
259
+ data.details.push({ key, value, source: TMDB_PROVIDER });
260
+ }
261
+ }
262
+ function addBooleanDetail(data, key, value) {
263
+ if (typeof value === "boolean") {
264
+ data.details.push({ key, value, source: TMDB_PROVIDER });
265
+ }
266
+ }
267
+ function categoryForMediaType(value) {
268
+ switch (value) {
269
+ case "movie":
270
+ return "movie";
271
+ case "tv":
272
+ return "tvshow";
273
+ default:
274
+ return undefined;
275
+ }
276
+ }
277
+ function relationForCrewJob(job) {
278
+ switch (job?.toLowerCase()) {
279
+ case "director":
280
+ return "directed";
281
+ case "writer":
282
+ case "screenplay":
283
+ case "novel":
284
+ return "authored";
285
+ case "creator":
286
+ case "executive producer":
287
+ case "producer":
288
+ return "produced";
289
+ default:
290
+ return "worked_on";
291
+ }
292
+ }
293
+ function mediaUrl(path, baseUrl) {
294
+ const value = stringField(path);
295
+ if (!value) {
296
+ return undefined;
297
+ }
298
+ if (value.startsWith("http://") || value.startsWith("https://")) {
299
+ return value;
300
+ }
301
+ return baseUrl ? `${baseUrl.replace(/\/$/, "")}/${value.replace(/^\//, "")}` : value;
302
+ }
303
+ function stringField(value) {
304
+ const normalized = value?.trim();
305
+ return normalized ? normalized : undefined;
306
+ }
307
+ function validateDate(value, field) {
308
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || Number.isNaN(Date.parse(`${value}T00:00:00.000Z`))) {
309
+ throw new Error(`invalid TMDB person field ${field}: ${value}`);
310
+ }
311
+ }
312
+ function searchQuery(value, field) {
313
+ const normalized = stringField(value);
314
+ if (!normalized) {
315
+ throw new Error(`${field} must not be empty`);
316
+ }
317
+ return normalized;
318
+ }
319
+ function searchParams(provider, input) {
320
+ return {
321
+ language: input.language ?? provider.language,
322
+ page: String(input.page ?? 1),
323
+ include_adult: String(input.includeAdult ?? false)
324
+ };
325
+ }
326
+ async function sourceRecordsFromSearchResults(category, results) {
327
+ const records = [];
328
+ for (const result of results ?? []) {
329
+ if (!result.id) {
330
+ continue;
331
+ }
332
+ records.push(await createSourceRecord({
333
+ source: { provider: TMDB_PROVIDER, category, externalId: String(result.id) },
334
+ payload: result
335
+ }));
336
+ }
337
+ return records;
338
+ }
339
+ function paginationFromTmdbSearchResponse(payload) {
340
+ return {
341
+ page: payload.page ?? 1,
342
+ totalPages: payload.total_pages ?? 0,
343
+ totalResults: payload.total_results ?? 0
344
+ };
345
+ }
@@ -0,0 +1,181 @@
1
+ import { type SearchResponse, type ZuuidData, type ZuuidSearchResult } from "../../entity.js";
2
+ import { type SourceRecord } from "../../source.js";
3
+ import type { JsonValue } from "../../types.js";
4
+ import type { TmdbProvider } from "./client.js";
5
+ import type { TmdbSearchInput, TmdbTransformOptions } from "./types.js";
6
+ export declare const TMDB_TV_CATEGORY = "tv";
7
+ export declare const ZUUID_TV_CATEGORY = "tvshow";
8
+ export type FetchTmdbTvInput = {
9
+ id: string | number;
10
+ };
11
+ export type TmdbTvPayload = {
12
+ adult?: boolean;
13
+ id?: number | string;
14
+ name?: string;
15
+ original_name?: string;
16
+ overview?: string;
17
+ first_air_date?: string;
18
+ last_air_date?: string;
19
+ vote_average?: number;
20
+ vote_count?: number;
21
+ poster_path?: string;
22
+ backdrop_path?: string;
23
+ original_language?: string;
24
+ genres?: {
25
+ name?: string;
26
+ }[];
27
+ homepage?: string;
28
+ status?: string;
29
+ type?: string;
30
+ number_of_seasons?: number;
31
+ number_of_episodes?: number;
32
+ episode_run_time?: number[];
33
+ popularity?: number;
34
+ languages?: string[];
35
+ in_production?: boolean;
36
+ tagline?: string;
37
+ softcore?: boolean;
38
+ origin_country?: string[];
39
+ production_countries?: {
40
+ iso_3166_1?: string;
41
+ name?: string;
42
+ }[];
43
+ spoken_languages?: {
44
+ english_name?: string;
45
+ iso_639_1?: string;
46
+ name?: string;
47
+ }[];
48
+ created_by?: {
49
+ id?: number;
50
+ name?: string;
51
+ profile_path?: string | null;
52
+ }[];
53
+ networks?: {
54
+ id?: number;
55
+ name?: string;
56
+ logo_path?: string | null;
57
+ origin_country?: string;
58
+ }[];
59
+ production_companies?: {
60
+ id?: number;
61
+ name?: string;
62
+ logo_path?: string | null;
63
+ origin_country?: string;
64
+ }[];
65
+ seasons?: {
66
+ id?: number;
67
+ name?: string;
68
+ season_number?: number;
69
+ episode_count?: number;
70
+ poster_path?: string | null;
71
+ air_date?: string;
72
+ }[];
73
+ external_ids?: {
74
+ imdb_id?: string | null;
75
+ tvdb_id?: number | string | null;
76
+ tvrage_id?: number | string | null;
77
+ wikidata_id?: string | null;
78
+ facebook_id?: string | null;
79
+ instagram_id?: string | null;
80
+ twitter_id?: string | null;
81
+ };
82
+ keywords?: {
83
+ results?: {
84
+ id?: number;
85
+ name?: string;
86
+ }[];
87
+ };
88
+ aggregate_credits?: {
89
+ cast?: TmdbAggregateCast[];
90
+ crew?: TmdbAggregateCrew[];
91
+ };
92
+ images?: {
93
+ posters?: TmdbTvImage[];
94
+ backdrops?: TmdbTvImage[];
95
+ logos?: TmdbTvImage[];
96
+ };
97
+ recommendations?: TmdbTvListResponse;
98
+ similar?: TmdbTvListResponse;
99
+ translations?: {
100
+ translations?: {
101
+ iso_639_1?: string;
102
+ iso_3166_1?: string;
103
+ data?: {
104
+ name?: string;
105
+ overview?: string;
106
+ homepage?: string;
107
+ };
108
+ }[];
109
+ };
110
+ watch_providers?: {
111
+ results?: Record<string, JsonValue>;
112
+ };
113
+ content_ratings?: {
114
+ results?: {
115
+ descriptors?: string[];
116
+ iso_3166_1?: string;
117
+ rating?: string;
118
+ }[];
119
+ };
120
+ last_episode_to_air?: JsonValue;
121
+ next_episode_to_air?: JsonValue;
122
+ };
123
+ export type TmdbAggregateRole = {
124
+ credit_id?: string;
125
+ character?: string;
126
+ episode_count?: number;
127
+ };
128
+ export type TmdbAggregateJob = {
129
+ credit_id?: string;
130
+ job?: string;
131
+ episode_count?: number;
132
+ };
133
+ export type TmdbAggregateCast = {
134
+ id?: number;
135
+ name?: string;
136
+ original_name?: string;
137
+ profile_path?: string | null;
138
+ roles?: TmdbAggregateRole[];
139
+ total_episode_count?: number;
140
+ };
141
+ export type TmdbAggregateCrew = {
142
+ id?: number;
143
+ name?: string;
144
+ original_name?: string;
145
+ profile_path?: string | null;
146
+ department?: string;
147
+ jobs?: TmdbAggregateJob[];
148
+ total_episode_count?: number;
149
+ };
150
+ export type TmdbTvImage = {
151
+ file_path?: string;
152
+ width?: number;
153
+ height?: number;
154
+ iso_639_1?: string | null;
155
+ vote_average?: number;
156
+ };
157
+ export type TmdbTvListResponse = {
158
+ results?: TmdbRelatedTv[];
159
+ };
160
+ export type TmdbTvSearchResult = TmdbRelatedTv & {
161
+ overview?: string;
162
+ backdrop_path?: string | null;
163
+ genre_ids?: number[];
164
+ original_language?: string;
165
+ origin_country?: string[];
166
+ popularity?: number;
167
+ vote_count?: number;
168
+ };
169
+ export type TmdbRelatedTv = {
170
+ id?: number;
171
+ name?: string;
172
+ original_name?: string;
173
+ first_air_date?: string;
174
+ poster_path?: string | null;
175
+ vote_average?: number;
176
+ };
177
+ export declare function fetchTmdbTvSourceRecord(provider: TmdbProvider, input: FetchTmdbTvInput): Promise<SourceRecord | undefined>;
178
+ export declare function searchTmdbTvSourceRecords(provider: TmdbProvider, input: TmdbSearchInput): Promise<SearchResponse<SourceRecord>>;
179
+ export declare function searchTmdbTv(provider: TmdbProvider, input: TmdbSearchInput, options?: TmdbTransformOptions): Promise<SearchResponse<ZuuidSearchResult>>;
180
+ export declare function transformTmdbTv(source: SourceRecord, options?: TmdbTransformOptions): Promise<ZuuidData>;
181
+ //# sourceMappingURL=tv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tv.d.ts","sourceRoot":"","sources":["../../../src/providers/tmdb/tv.ts"],"names":[],"mappings":"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"}