@pfdev/api-types 3.0.6 → 3.0.10
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/package.json +1 -1
- package/v3.ts +280 -5
package/package.json
CHANGED
package/v3.ts
CHANGED
|
@@ -7,10 +7,9 @@ import { Static, Type } from '@sinclair/typebox';
|
|
|
7
7
|
// ============= CARDS =============
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const PriceStatsSchema = Type.Object(
|
|
11
11
|
{
|
|
12
|
-
|
|
13
|
-
current_price: Type.Optional(Type.Number({ description: 'Current price for this variant' })),
|
|
12
|
+
current_price: Type.Optional(Type.Number({ description: 'Current price' })),
|
|
14
13
|
change_1d: Type.Optional(Type.Number({ description: '1-day price change as a percentage' })),
|
|
15
14
|
change_7d: Type.Optional(Type.Number({ description: '7-day price change as a percentage' })),
|
|
16
15
|
change_1m: Type.Optional(Type.Number({ description: '30-day price change as a percentage' })),
|
|
@@ -18,7 +17,7 @@ const VariantPriceSchema = Type.Object(
|
|
|
18
17
|
change_6m: Type.Optional(Type.Number({ description: '180-day price change as a percentage' })),
|
|
19
18
|
change_1y: Type.Optional(Type.Number({ description: '1-year price change as a percentage' }))
|
|
20
19
|
},
|
|
21
|
-
{ title: '
|
|
20
|
+
{ title: 'PriceStats' }
|
|
22
21
|
);
|
|
23
22
|
|
|
24
23
|
const CardImagesSchema = Type.Object(
|
|
@@ -77,6 +76,33 @@ export const CardListQuerySchema = Type.Object(
|
|
|
77
76
|
|
|
78
77
|
export type CardListQuery = Static<typeof CardListQuerySchema>;
|
|
79
78
|
|
|
79
|
+
export const CardSearchSortSchema = Type.Union([
|
|
80
|
+
Type.Literal('number_asc'),
|
|
81
|
+
Type.Literal('number_desc'),
|
|
82
|
+
Type.Literal('name_asc'),
|
|
83
|
+
Type.Literal('name_desc'),
|
|
84
|
+
Type.Literal('price_asc'),
|
|
85
|
+
Type.Literal('price_desc')
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
export type CardSearchSort = Static<typeof CardSearchSortSchema>;
|
|
89
|
+
|
|
90
|
+
export const CardSearchQuerySchema = Type.Object({
|
|
91
|
+
q: Type.String({ minLength: 1, description: 'Search query. Tokens with digits match card number; other tokens match card name.' }),
|
|
92
|
+
sort: Type.Optional(Type.Union([
|
|
93
|
+
Type.Literal('number_asc'),
|
|
94
|
+
Type.Literal('number_desc'),
|
|
95
|
+
Type.Literal('name_asc'),
|
|
96
|
+
Type.Literal('name_desc'),
|
|
97
|
+
Type.Literal('price_asc'),
|
|
98
|
+
Type.Literal('price_desc')
|
|
99
|
+
], { default: 'number_asc', description: 'Sort order. Defaults to number_asc.' })),
|
|
100
|
+
limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100, default: 25, description: 'Max results to return' })),
|
|
101
|
+
offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: 'Pagination offset' }))
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export type CardSearchQuery = Static<typeof CardSearchQuerySchema>;
|
|
105
|
+
|
|
80
106
|
export const CardDetailSchema = Type.Object(
|
|
81
107
|
{
|
|
82
108
|
cardid: Type.String({ description: 'Unique card identifier' }),
|
|
@@ -109,7 +135,16 @@ export const CardDetailSchema = Type.Object(
|
|
|
109
135
|
change_1d: Type.Optional(Type.Number({ description: '1-day price change as a percentage' })),
|
|
110
136
|
change_1d_value: Type.Optional(Type.Number({ description: '1-day price change in dollars' })),
|
|
111
137
|
variants: Type.Optional(Type.Array(Type.String(), { description: 'Available variants for this card' })),
|
|
112
|
-
variant_prices: Type.Optional(
|
|
138
|
+
variant_prices: Type.Optional(
|
|
139
|
+
Type.Record(Type.String(), PriceStatsSchema, { description: 'Prices and period changes keyed by variant name' })
|
|
140
|
+
),
|
|
141
|
+
graded_variants_prices: Type.Optional(
|
|
142
|
+
Type.Record(
|
|
143
|
+
Type.String(),
|
|
144
|
+
Type.Record(Type.String(), PriceStatsSchema),
|
|
145
|
+
{ description: 'Graded prices and period changes keyed by variant then grade' }
|
|
146
|
+
)
|
|
147
|
+
)
|
|
113
148
|
},
|
|
114
149
|
{
|
|
115
150
|
title: 'CardDetail',
|
|
@@ -125,6 +160,184 @@ export const CardDetailParamSchema = Type.Object({
|
|
|
125
160
|
|
|
126
161
|
export type CardDetailParam = Static<typeof CardDetailParamSchema>;
|
|
127
162
|
|
|
163
|
+
const PricePointSchema = Type.Object(
|
|
164
|
+
{
|
|
165
|
+
date: Type.String({ description: 'Date of the price point' }),
|
|
166
|
+
price: Type.Number({ description: 'Price on this date' }),
|
|
167
|
+
variant: Type.String({ description: 'Card variant' }),
|
|
168
|
+
grade: Type.Optional(Type.String({ description: 'Grade (graded cards only)' }))
|
|
169
|
+
},
|
|
170
|
+
{ title: 'PricePoint' }
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
export const CardPricesQuerySchema = Type.Object({
|
|
174
|
+
interval: Type.Number({ minimum: 1, maximum: 1825, default: 30, description: 'Number of days of price history to return' }),
|
|
175
|
+
variant: Type.Optional(Type.String({ description: 'Variant name. If omitted, returns all variants.' })),
|
|
176
|
+
grade: Type.Optional(Type.String({ description: 'Grade (e.g. "PSA 10", "BGS 9.5"). Omit or use "RAW" for ungraded.' })),
|
|
177
|
+
source: Type.Optional(Type.Union(
|
|
178
|
+
[Type.Literal('tcgplayer'), Type.Literal('ebay')],
|
|
179
|
+
{ description: 'Price source. Inferred from grade if omitted: RAW → tcgplayer, graded → ebay.' }
|
|
180
|
+
))
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
export type CardPricesQuery = Static<typeof CardPricesQuerySchema>;
|
|
184
|
+
|
|
185
|
+
export const CardPricesResponseSchema = Type.Object(
|
|
186
|
+
{
|
|
187
|
+
cardid: Type.String({ description: 'Card ID' }),
|
|
188
|
+
variant: Type.Optional(Type.String({ description: 'Filtered variant, if specified' })),
|
|
189
|
+
grade: Type.String({ description: 'Resolved grade used for the query' }),
|
|
190
|
+
source: Type.String({ description: 'Resolved price source used for the query' }),
|
|
191
|
+
interval: Type.Number({ description: 'Number of days of history returned' }),
|
|
192
|
+
data: Type.Array(PricePointSchema, { description: 'Price history data points, ordered by date ascending' })
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
title: 'CardPricesResponse',
|
|
196
|
+
description: 'Price history for a card, suitable for charting'
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
export type CardPricesResponse = Static<typeof CardPricesResponseSchema>;
|
|
201
|
+
|
|
202
|
+
const SaleRecordSchema = Type.Object(
|
|
203
|
+
{
|
|
204
|
+
sold_date: Type.String({ description: 'Date the card was sold' }),
|
|
205
|
+
price: Type.Number({ description: 'Sale price' }),
|
|
206
|
+
grade: Type.String({ description: 'Grade at time of sale' }),
|
|
207
|
+
variant: Type.String({ description: 'Card variant' }),
|
|
208
|
+
title: Type.Optional(Type.String({ description: 'eBay listing title' })),
|
|
209
|
+
url: Type.Optional(Type.String({ description: 'eBay listing URL' })),
|
|
210
|
+
image_url: Type.Optional(Type.String({ description: 'Listing image URL' })),
|
|
211
|
+
seller_username: Type.Optional(Type.String({ description: 'eBay seller username' }))
|
|
212
|
+
},
|
|
213
|
+
{ title: 'SaleRecord' }
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
export const CardSalesQuerySchema = Type.Object({
|
|
217
|
+
grade: Type.Optional(Type.String({ description: 'Filter by grade (e.g. "PSA 10"). Returns all grades if omitted.' })),
|
|
218
|
+
variant: Type.Optional(Type.String({ description: 'Filter by variant. Returns all variants if omitted.' })),
|
|
219
|
+
limit: Type.Optional(Type.Number({ minimum: 1, maximum: 100, default: 25, description: 'Max results to return' })),
|
|
220
|
+
offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: 'Pagination offset' }))
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
export type CardSalesQuery = Static<typeof CardSalesQuerySchema>;
|
|
224
|
+
|
|
225
|
+
export const CardSalesResponseSchema = Type.Object(
|
|
226
|
+
{
|
|
227
|
+
cardid: Type.String({ description: 'Card ID' }),
|
|
228
|
+
grade: Type.Optional(Type.String({ description: 'Filtered grade, if specified' })),
|
|
229
|
+
variant: Type.Optional(Type.String({ description: 'Filtered variant, if specified' })),
|
|
230
|
+
data: Type.Array(SaleRecordSchema, { description: 'Individual eBay sold listings, most recent first' }),
|
|
231
|
+
total: Type.Number({ description: 'Total matching sales records' }),
|
|
232
|
+
count: Type.Number({ description: 'Records returned in this response' })
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
title: 'CardSalesResponse',
|
|
236
|
+
description: 'Individual eBay sold listings for a graded card'
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
export type CardSalesResponse = Static<typeof CardSalesResponseSchema>;
|
|
241
|
+
|
|
242
|
+
// ============= SEALED =============
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
export const SealedItemSchema = Type.Object(
|
|
246
|
+
{
|
|
247
|
+
sealedid: Type.String({ format: 'uuid', description: 'Unique sealed product identifier' }),
|
|
248
|
+
name: Type.String({ description: 'Product name' }),
|
|
249
|
+
setid: Type.String({ description: 'Set this product belongs to' }),
|
|
250
|
+
set_name: Type.Optional(Type.String({ description: 'Name of the set' })),
|
|
251
|
+
product_slug: Type.Optional(Type.String({ description: 'Product URL slug' })),
|
|
252
|
+
set_slug: Type.Optional(Type.String({ description: 'Set URL slug' })),
|
|
253
|
+
image: Type.Optional(Type.String({ description: 'Product image URL' })),
|
|
254
|
+
tcgp_id: Type.Optional(Type.Number({ description: 'TCGPlayer product ID' })),
|
|
255
|
+
language: Type.Optional(Type.String({ description: 'Product language' })),
|
|
256
|
+
price: Type.Optional(Type.Number({ description: 'Current market price' })),
|
|
257
|
+
change_1d: Type.Optional(Type.Number({ description: '1-day price change %' })),
|
|
258
|
+
change_7d: Type.Optional(Type.Number({ description: '7-day price change %' })),
|
|
259
|
+
change_1m: Type.Optional(Type.Number({ description: '30-day price change %' })),
|
|
260
|
+
change_3m: Type.Optional(Type.Number({ description: '90-day price change %' })),
|
|
261
|
+
change_6m: Type.Optional(Type.Number({ description: '180-day price change %' })),
|
|
262
|
+
change_1y: Type.Optional(Type.Number({ description: '1-year price change %' })),
|
|
263
|
+
change_1d_value: Type.Optional(Type.Number({ description: '1-day price change in dollars' })),
|
|
264
|
+
change_7d_value: Type.Optional(Type.Number({ description: '7-day price change in dollars' })),
|
|
265
|
+
change_1m_value: Type.Optional(Type.Number({ description: '30-day price change in dollars' })),
|
|
266
|
+
change_3m_value: Type.Optional(Type.Number({ description: '90-day price change in dollars' })),
|
|
267
|
+
change_6m_value: Type.Optional(Type.Number({ description: '180-day price change in dollars' })),
|
|
268
|
+
change_1y_value: Type.Optional(Type.Number({ description: '1-year price change in dollars' })),
|
|
269
|
+
price_updated: Type.Optional(Type.String({ description: 'Timestamp of last price update' }))
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
title: 'SealedItem',
|
|
273
|
+
description: 'A sealed Pokemon product'
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
export type SealedItem = Static<typeof SealedItemSchema>;
|
|
278
|
+
|
|
279
|
+
export const SealedListResponseSchema = Type.Object(
|
|
280
|
+
{
|
|
281
|
+
data: Type.Array(SealedItemSchema, { description: 'Array of sealed products' }),
|
|
282
|
+
total: Type.Number({ description: 'Total number of products matching query' }),
|
|
283
|
+
count: Type.Number({ description: 'Number of products returned in this response' })
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
title: 'SealedListResponse',
|
|
287
|
+
description: 'Paginated list of sealed Pokemon products'
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
export type SealedListResponse = Static<typeof SealedListResponseSchema>;
|
|
292
|
+
|
|
293
|
+
export const SealedListQuerySchema = Type.Object(
|
|
294
|
+
{
|
|
295
|
+
setid: Type.Optional(Type.String({ description: 'Filter by set ID' })),
|
|
296
|
+
name: Type.Optional(Type.String({ description: 'Search by product name' })),
|
|
297
|
+
limit: Type.Optional(Type.Number({ minimum: 1, maximum: 250, default: 50, description: 'Max results to return' })),
|
|
298
|
+
offset: Type.Optional(Type.Number({ minimum: 0, default: 0, description: 'Pagination offset' }))
|
|
299
|
+
},
|
|
300
|
+
{ description: 'At least one of setid or name must be provided' }
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
export type SealedListQuery = Static<typeof SealedListQuerySchema>;
|
|
304
|
+
|
|
305
|
+
// Path parameters
|
|
306
|
+
export const SealedDetailParamSchema = Type.Object({
|
|
307
|
+
sealedid: Type.String({ format: 'uuid', description: 'Sealed product ID' })
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
export type SealedDetailParam = Static<typeof SealedDetailParamSchema>;
|
|
311
|
+
|
|
312
|
+
// Prices endpoint
|
|
313
|
+
const SealedPricePointSchema = Type.Object(
|
|
314
|
+
{
|
|
315
|
+
date: Type.String({ description: 'Date of the price point' }),
|
|
316
|
+
price: Type.Number({ description: 'Price on this date' })
|
|
317
|
+
},
|
|
318
|
+
{ title: 'SealedPricePoint' }
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
export const SealedPricesQuerySchema = Type.Object({
|
|
322
|
+
interval: Type.Optional(Type.Number({ minimum: 1, maximum: 1825, default: 30, description: 'Number of days of price history to return' }))
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
export type SealedPricesQuery = Static<typeof SealedPricesQuerySchema>;
|
|
326
|
+
|
|
327
|
+
export const SealedPricesResponseSchema = Type.Object(
|
|
328
|
+
{
|
|
329
|
+
sealedid: Type.String({ format: 'uuid', description: 'Sealed product ID' }),
|
|
330
|
+
interval: Type.Number({ description: 'Number of days of history returned' }),
|
|
331
|
+
data: Type.Array(SealedPricePointSchema, { description: 'Price history data points, ordered by date ascending' })
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
title: 'SealedPricesResponse',
|
|
335
|
+
description: 'Price history for a sealed product, suitable for charting'
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
export type SealedPricesResponse = Static<typeof SealedPricesResponseSchema>;
|
|
340
|
+
|
|
128
341
|
// ============= SETS =============
|
|
129
342
|
|
|
130
343
|
|
|
@@ -219,3 +432,65 @@ export const SetDetailParamSchema = Type.Object({
|
|
|
219
432
|
});
|
|
220
433
|
|
|
221
434
|
export type SetDetailParam = Static<typeof SetDetailParamSchema>;
|
|
435
|
+
|
|
436
|
+
// ============= VISION =============
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
const VariantPriceSchema = Type.Object(
|
|
440
|
+
{
|
|
441
|
+
variant: Type.String(),
|
|
442
|
+
current_price: Type.Optional(Type.Number()),
|
|
443
|
+
change_1d: Type.Optional(Type.Number()),
|
|
444
|
+
change_7d: Type.Optional(Type.Number()),
|
|
445
|
+
change_1m: Type.Optional(Type.Number()),
|
|
446
|
+
change_3m: Type.Optional(Type.Number()),
|
|
447
|
+
change_6m: Type.Optional(Type.Number()),
|
|
448
|
+
change_1y: Type.Optional(Type.Number())
|
|
449
|
+
},
|
|
450
|
+
{ title: 'VisionVariantPrice' }
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
const DetectedCardSchema = Type.Object(
|
|
454
|
+
{
|
|
455
|
+
name: Type.String({ description: 'Card name from image recognition' }),
|
|
456
|
+
number: Type.Optional(Type.String({ description: 'Card number from image recognition' })),
|
|
457
|
+
releaseName: Type.Optional(Type.String({ description: 'Set/release name from image recognition' })),
|
|
458
|
+
setName: Type.Optional(Type.String({ description: 'Sub-set name from image recognition' })),
|
|
459
|
+
year: Type.Optional(Type.String({ description: 'Release year from image recognition' })),
|
|
460
|
+
manufacturer: Type.Optional(Type.String({ description: 'Card manufacturer' }))
|
|
461
|
+
},
|
|
462
|
+
{ title: 'DetectedCard' }
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
const MatchedCardSchema = Type.Intersect(
|
|
466
|
+
[
|
|
467
|
+
CardSchema,
|
|
468
|
+
Type.Object({
|
|
469
|
+
score: Type.Number({ description: 'Fuzzy match score — higher is a better match' }),
|
|
470
|
+
variant_prices: Type.Array(VariantPriceSchema, { description: 'Per-variant prices with extended period changes' })
|
|
471
|
+
})
|
|
472
|
+
],
|
|
473
|
+
{ title: 'MatchedCard' }
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
export const VisionBodySchema = Type.Object(
|
|
477
|
+
{
|
|
478
|
+
file: Type.Any({ description: 'Card image file to identify', format: 'binary' })
|
|
479
|
+
},
|
|
480
|
+
{ title: 'VisionBody' }
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
export type VisionBody = Static<typeof VisionBodySchema>;
|
|
484
|
+
|
|
485
|
+
export const VisionResponseSchema = Type.Object(
|
|
486
|
+
{
|
|
487
|
+
detection: Type.Union([DetectedCardSchema, Type.Null()], { description: 'Raw detection result from image recognition' }),
|
|
488
|
+
cards: Type.Optional(Type.Array(MatchedCardSchema, { description: 'Matched cards from database, ordered by score descending' }))
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
title: 'VisionResponse',
|
|
492
|
+
description: 'Card image recognition result with matched database cards'
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
export type VisionResponse = Static<typeof VisionResponseSchema>;
|