@carddb/core 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.
- package/README.md +85 -0
- package/dist/index.cjs +1177 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +840 -0
- package/dist/index.d.ts +840 -0
- package/dist/index.js +1123 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for CardDB JavaScript clients
|
|
3
|
+
*/
|
|
4
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
5
|
+
type ResourceType = 'publishers' | 'games' | 'datasets' | 'records' | 'decks';
|
|
6
|
+
interface Logger {
|
|
7
|
+
debug(message: string, ...args: unknown[]): void;
|
|
8
|
+
info(message: string, ...args: unknown[]): void;
|
|
9
|
+
warn(message: string, ...args: unknown[]): void;
|
|
10
|
+
error(message: string, ...args: unknown[]): void;
|
|
11
|
+
}
|
|
12
|
+
interface Cache {
|
|
13
|
+
get<T>(key: string): T | null | Promise<T | null>;
|
|
14
|
+
set<T>(key: string, value: T, ttl?: number): void | Promise<void>;
|
|
15
|
+
delete(key: string): void | Promise<void>;
|
|
16
|
+
clear?(): void | Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
interface CardDBConfig {
|
|
19
|
+
/** API key for authentication (increases rate limits) */
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
/** GraphQL endpoint URL (defaults to production) */
|
|
22
|
+
endpoint?: string;
|
|
23
|
+
/** Request timeout in milliseconds */
|
|
24
|
+
timeout?: number;
|
|
25
|
+
/** Connection open timeout in milliseconds */
|
|
26
|
+
openTimeout?: number;
|
|
27
|
+
/** Default publisher slug for queries */
|
|
28
|
+
defaultPublisher?: string;
|
|
29
|
+
/** Default game key for queries */
|
|
30
|
+
defaultGame?: string;
|
|
31
|
+
/** Allowed publisher slugs (undefined = all allowed) */
|
|
32
|
+
allowedPublishers?: string[];
|
|
33
|
+
/** Map of publisher slug to allowed game keys */
|
|
34
|
+
allowedGames?: Record<string, string[]>;
|
|
35
|
+
/** Logger instance for debug output */
|
|
36
|
+
logger?: Logger;
|
|
37
|
+
/** Log level threshold */
|
|
38
|
+
logLevel?: LogLevel;
|
|
39
|
+
/** Whether to automatically retry on rate limit errors */
|
|
40
|
+
retryOnRateLimit?: boolean;
|
|
41
|
+
/** Maximum number of retries on rate limit */
|
|
42
|
+
maxRetries?: number;
|
|
43
|
+
/** Whether to automatically retry on network errors (connection, timeout) */
|
|
44
|
+
retryOnNetworkError?: boolean;
|
|
45
|
+
/** Maximum number of retries for network errors */
|
|
46
|
+
maxNetworkRetries?: number;
|
|
47
|
+
/** Base delay in milliseconds for exponential backoff (default: 1000) */
|
|
48
|
+
retryBaseDelay?: number;
|
|
49
|
+
/** Maximum delay in milliseconds for exponential backoff (default: 30000) */
|
|
50
|
+
retryMaxDelay?: number;
|
|
51
|
+
/** Cache instance (must implement Cache interface) */
|
|
52
|
+
cache?: Cache;
|
|
53
|
+
/** Default cache TTL in seconds */
|
|
54
|
+
cacheTtl?: number;
|
|
55
|
+
/** Per-resource cache TTLs in seconds */
|
|
56
|
+
cacheTtls?: Partial<Record<ResourceType, number>>;
|
|
57
|
+
}
|
|
58
|
+
interface PageInfo {
|
|
59
|
+
hasNextPage: boolean;
|
|
60
|
+
hasPreviousPage: boolean;
|
|
61
|
+
startCursor: string | null;
|
|
62
|
+
endCursor: string | null;
|
|
63
|
+
}
|
|
64
|
+
interface Edge<T> {
|
|
65
|
+
cursor: string;
|
|
66
|
+
node: T;
|
|
67
|
+
}
|
|
68
|
+
interface Connection<T> {
|
|
69
|
+
totalCount: number;
|
|
70
|
+
pageInfo: PageInfo;
|
|
71
|
+
edges: Edge<T>[];
|
|
72
|
+
}
|
|
73
|
+
interface FileInfo {
|
|
74
|
+
id: string;
|
|
75
|
+
url: string;
|
|
76
|
+
}
|
|
77
|
+
type PublisherStatus = 'ACTIVE' | 'DEACTIVATED';
|
|
78
|
+
interface Publisher {
|
|
79
|
+
id: string;
|
|
80
|
+
name: string;
|
|
81
|
+
slug: string;
|
|
82
|
+
status: PublisherStatus;
|
|
83
|
+
description: string | null;
|
|
84
|
+
website: string | null;
|
|
85
|
+
logoFile: FileInfo | null;
|
|
86
|
+
bannerFile: FileInfo | null;
|
|
87
|
+
createdAt: string;
|
|
88
|
+
updatedAt: string;
|
|
89
|
+
}
|
|
90
|
+
interface PublisherRef {
|
|
91
|
+
id: string;
|
|
92
|
+
name: string;
|
|
93
|
+
slug: string;
|
|
94
|
+
}
|
|
95
|
+
interface Game {
|
|
96
|
+
id: string;
|
|
97
|
+
publisherId: string;
|
|
98
|
+
key: string;
|
|
99
|
+
name: string;
|
|
100
|
+
description: string | null;
|
|
101
|
+
website: string | null;
|
|
102
|
+
visibility: string;
|
|
103
|
+
isArchived: boolean;
|
|
104
|
+
publisher: PublisherRef | null;
|
|
105
|
+
logoFile: FileInfo | null;
|
|
106
|
+
coverFile: FileInfo | null;
|
|
107
|
+
createdAt: string;
|
|
108
|
+
updatedAt: string;
|
|
109
|
+
}
|
|
110
|
+
interface GameRef {
|
|
111
|
+
id: string;
|
|
112
|
+
key: string;
|
|
113
|
+
name: string;
|
|
114
|
+
}
|
|
115
|
+
interface Dataset {
|
|
116
|
+
id: string;
|
|
117
|
+
publisherId: string;
|
|
118
|
+
gameId: string;
|
|
119
|
+
key: string;
|
|
120
|
+
name: string;
|
|
121
|
+
description: string | null;
|
|
122
|
+
purpose: 'DATA' | 'RULES';
|
|
123
|
+
visibility: string;
|
|
124
|
+
isArchived: boolean;
|
|
125
|
+
publisher: PublisherRef | null;
|
|
126
|
+
game: GameRef | null;
|
|
127
|
+
schema: DatasetSchema | null;
|
|
128
|
+
createdAt: string;
|
|
129
|
+
updatedAt: string;
|
|
130
|
+
}
|
|
131
|
+
interface DatasetRef {
|
|
132
|
+
id: string;
|
|
133
|
+
key: string;
|
|
134
|
+
name: string;
|
|
135
|
+
gameId: string;
|
|
136
|
+
publisherId: string;
|
|
137
|
+
}
|
|
138
|
+
interface DatasetRecord {
|
|
139
|
+
id: string;
|
|
140
|
+
datasetId: string;
|
|
141
|
+
data: Record<string, unknown>;
|
|
142
|
+
dataset: DatasetRef | null;
|
|
143
|
+
resolvedLinks?: ResolvedLink[];
|
|
144
|
+
createdAt: string;
|
|
145
|
+
updatedAt: string;
|
|
146
|
+
}
|
|
147
|
+
type DeckVisibility = 'PRIVATE' | 'UNLISTED' | 'PUBLIC';
|
|
148
|
+
interface Deck {
|
|
149
|
+
id: string;
|
|
150
|
+
accountId: string;
|
|
151
|
+
apiApplicationId: string | null;
|
|
152
|
+
gameId: string;
|
|
153
|
+
game: Game;
|
|
154
|
+
title: string;
|
|
155
|
+
description: string | null;
|
|
156
|
+
formatKey: string | null;
|
|
157
|
+
visibility: DeckVisibility;
|
|
158
|
+
externalRef: string | null;
|
|
159
|
+
sourceUrl: string | null;
|
|
160
|
+
metadata: Record<string, unknown>;
|
|
161
|
+
entries: DeckEntry[];
|
|
162
|
+
createdAt: string;
|
|
163
|
+
updatedAt: string;
|
|
164
|
+
}
|
|
165
|
+
interface DeckEntry {
|
|
166
|
+
id: string;
|
|
167
|
+
datasetId: string;
|
|
168
|
+
recordId: string | null;
|
|
169
|
+
identifier: string;
|
|
170
|
+
quantity: number;
|
|
171
|
+
section: string;
|
|
172
|
+
sortOrder: number;
|
|
173
|
+
annotations: Record<string, unknown>;
|
|
174
|
+
record: DatasetRecord | null;
|
|
175
|
+
}
|
|
176
|
+
interface DeckEntryInput {
|
|
177
|
+
datasetKey: string;
|
|
178
|
+
identifier: string;
|
|
179
|
+
quantity: number;
|
|
180
|
+
section?: string;
|
|
181
|
+
sortOrder?: number;
|
|
182
|
+
annotations?: Record<string, unknown>;
|
|
183
|
+
}
|
|
184
|
+
interface DeckCreateInput {
|
|
185
|
+
publisherSlug: string;
|
|
186
|
+
gameKey: string;
|
|
187
|
+
title: string;
|
|
188
|
+
description?: string;
|
|
189
|
+
formatKey?: string;
|
|
190
|
+
visibility?: DeckVisibility;
|
|
191
|
+
externalRef?: string;
|
|
192
|
+
sourceUrl?: string;
|
|
193
|
+
metadata?: Record<string, unknown>;
|
|
194
|
+
entries: DeckEntryInput[];
|
|
195
|
+
}
|
|
196
|
+
interface DeckUpdateInput {
|
|
197
|
+
title?: string;
|
|
198
|
+
description?: string;
|
|
199
|
+
formatKey?: string;
|
|
200
|
+
visibility?: DeckVisibility;
|
|
201
|
+
externalRef?: string;
|
|
202
|
+
sourceUrl?: string;
|
|
203
|
+
metadata?: Record<string, unknown>;
|
|
204
|
+
entries?: DeckEntryInput[];
|
|
205
|
+
}
|
|
206
|
+
interface HydrateDeckEntryInput {
|
|
207
|
+
identifier: string;
|
|
208
|
+
quantity: number;
|
|
209
|
+
section?: string;
|
|
210
|
+
sortOrder?: number;
|
|
211
|
+
annotations?: Record<string, unknown>;
|
|
212
|
+
}
|
|
213
|
+
interface HydratedDeckEntry extends HydrateDeckEntryInput {
|
|
214
|
+
record: DatasetRecord | null;
|
|
215
|
+
}
|
|
216
|
+
interface ResolvedRecord {
|
|
217
|
+
id: string;
|
|
218
|
+
datasetId: string;
|
|
219
|
+
data: Record<string, unknown>;
|
|
220
|
+
}
|
|
221
|
+
interface ResolvedLink {
|
|
222
|
+
field: string;
|
|
223
|
+
linkFieldKey: string;
|
|
224
|
+
values: string[];
|
|
225
|
+
records: (ResolvedRecord | null)[];
|
|
226
|
+
}
|
|
227
|
+
type FieldType = 'STRING' | 'INTEGER' | 'FLOAT' | 'BOOLEAN' | 'DATE' | 'DATETIME' | 'URL' | 'IMAGE' | 'LINK' | 'ARRAY' | 'HASH';
|
|
228
|
+
interface FieldInfo {
|
|
229
|
+
key: string;
|
|
230
|
+
label: string | null;
|
|
231
|
+
description: string | null;
|
|
232
|
+
type: FieldType;
|
|
233
|
+
isRequired: boolean;
|
|
234
|
+
filterable: boolean;
|
|
235
|
+
searchable: boolean;
|
|
236
|
+
isIdentifier: boolean;
|
|
237
|
+
itemType: FieldType | null;
|
|
238
|
+
displayFormat: string | null;
|
|
239
|
+
allowedValues: string[] | null;
|
|
240
|
+
nestedFields: FieldInfo[] | null;
|
|
241
|
+
}
|
|
242
|
+
interface LinkFieldInfo {
|
|
243
|
+
key: string;
|
|
244
|
+
label: string | null;
|
|
245
|
+
targetDatasetKey: string;
|
|
246
|
+
targetDatasetName: string | null;
|
|
247
|
+
targetDatasetId: string;
|
|
248
|
+
}
|
|
249
|
+
interface DatasetSchema {
|
|
250
|
+
fields: FieldInfo[];
|
|
251
|
+
filterableFields: string[];
|
|
252
|
+
searchableFields: string[];
|
|
253
|
+
linkFields: LinkFieldInfo[];
|
|
254
|
+
}
|
|
255
|
+
interface APIApplication {
|
|
256
|
+
id: string;
|
|
257
|
+
name: string;
|
|
258
|
+
description: string | null;
|
|
259
|
+
environment: string;
|
|
260
|
+
apiKeyPrefix: string;
|
|
261
|
+
allowedOrigins: string[] | null;
|
|
262
|
+
allowedIps: string[] | null;
|
|
263
|
+
createdAt: string;
|
|
264
|
+
updatedAt: string;
|
|
265
|
+
lastUsedAt: string | null;
|
|
266
|
+
}
|
|
267
|
+
interface APIAccount {
|
|
268
|
+
id: string;
|
|
269
|
+
displayName: string;
|
|
270
|
+
createdAt: string;
|
|
271
|
+
}
|
|
272
|
+
interface APIKeyInfo {
|
|
273
|
+
application: APIApplication;
|
|
274
|
+
account: APIAccount;
|
|
275
|
+
}
|
|
276
|
+
type FilterOperatorValue = {
|
|
277
|
+
eq: unknown;
|
|
278
|
+
} | {
|
|
279
|
+
neq: unknown;
|
|
280
|
+
} | {
|
|
281
|
+
gt: number;
|
|
282
|
+
} | {
|
|
283
|
+
gte: number;
|
|
284
|
+
} | {
|
|
285
|
+
lt: number;
|
|
286
|
+
} | {
|
|
287
|
+
lte: number;
|
|
288
|
+
} | {
|
|
289
|
+
in: unknown[];
|
|
290
|
+
} | {
|
|
291
|
+
nin: unknown[];
|
|
292
|
+
} | {
|
|
293
|
+
contains: unknown;
|
|
294
|
+
} | {
|
|
295
|
+
like: string;
|
|
296
|
+
} | {
|
|
297
|
+
ilike: string;
|
|
298
|
+
} | {
|
|
299
|
+
is_null: boolean;
|
|
300
|
+
};
|
|
301
|
+
type FilterValue = unknown | FilterOperatorValue;
|
|
302
|
+
interface FilterCondition {
|
|
303
|
+
[field: string]: FilterValue | FilterCondition | FilterCondition[];
|
|
304
|
+
}
|
|
305
|
+
type FilterInput = FilterCondition | ((builder: FilterBuilderInterface) => void);
|
|
306
|
+
interface FilterBuilderInterface {
|
|
307
|
+
where(field: string, value: FilterValue): this;
|
|
308
|
+
where(conditions: Record<string, FilterValue>): this;
|
|
309
|
+
any(callback: (builder: FilterBuilderInterface) => void): this;
|
|
310
|
+
whereLink(field: string, conditions: Record<string, FilterValue>): this;
|
|
311
|
+
whereAny(field: string, conditions: Record<string, FilterValue>): this;
|
|
312
|
+
build(): FilterCondition;
|
|
313
|
+
}
|
|
314
|
+
interface RateLimitInfo {
|
|
315
|
+
limit: number | null;
|
|
316
|
+
remaining: number | null;
|
|
317
|
+
reset: number | null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Error classes for CardDB clients
|
|
322
|
+
*/
|
|
323
|
+
interface GraphQLErrorInfo {
|
|
324
|
+
message: string;
|
|
325
|
+
path?: string[];
|
|
326
|
+
extensions?: Record<string, unknown>;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Base error class for all CardDB errors
|
|
330
|
+
*/
|
|
331
|
+
declare class CardDBError extends Error {
|
|
332
|
+
/** The full response body if available */
|
|
333
|
+
readonly response?: unknown;
|
|
334
|
+
constructor(message: string, response?: unknown);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Raised when authentication fails (invalid API key or token)
|
|
338
|
+
*/
|
|
339
|
+
declare class AuthenticationError extends CardDBError {
|
|
340
|
+
constructor(message?: string, response?: unknown);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Raised when rate limits are exceeded
|
|
344
|
+
*/
|
|
345
|
+
declare class RateLimitError extends CardDBError {
|
|
346
|
+
/** Seconds until rate limit resets */
|
|
347
|
+
readonly retryAfter: number | null;
|
|
348
|
+
/** Maximum requests allowed */
|
|
349
|
+
readonly limit: number | null;
|
|
350
|
+
/** Remaining requests in window */
|
|
351
|
+
readonly remaining: number | null;
|
|
352
|
+
/** Time when the rate limit resets */
|
|
353
|
+
readonly resetAt: Date | null;
|
|
354
|
+
constructor(message?: string, options?: {
|
|
355
|
+
retryAfter?: number | null;
|
|
356
|
+
limit?: number | null;
|
|
357
|
+
remaining?: number | null;
|
|
358
|
+
resetAt?: Date | null;
|
|
359
|
+
response?: unknown;
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Raised when a requested resource is not found
|
|
364
|
+
*/
|
|
365
|
+
declare class NotFoundError extends CardDBError {
|
|
366
|
+
constructor(message?: string, response?: unknown);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Raised when request validation fails
|
|
370
|
+
*/
|
|
371
|
+
declare class ValidationError extends CardDBError {
|
|
372
|
+
/** List of validation errors */
|
|
373
|
+
readonly errors: GraphQLErrorInfo[];
|
|
374
|
+
constructor(message?: string, options?: {
|
|
375
|
+
errors?: GraphQLErrorInfo[];
|
|
376
|
+
response?: unknown;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Raised when accessing a restricted publisher or game
|
|
381
|
+
*/
|
|
382
|
+
declare class RestrictedError extends CardDBError {
|
|
383
|
+
constructor(message: string, response?: unknown);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Raised for GraphQL-level errors
|
|
387
|
+
*/
|
|
388
|
+
declare class GraphQLError extends CardDBError {
|
|
389
|
+
/** List of GraphQL errors */
|
|
390
|
+
readonly errors: GraphQLErrorInfo[];
|
|
391
|
+
constructor(message?: string, options?: {
|
|
392
|
+
errors?: GraphQLErrorInfo[];
|
|
393
|
+
response?: unknown;
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Raised for network/connection issues
|
|
398
|
+
*/
|
|
399
|
+
declare class ConnectionError extends CardDBError {
|
|
400
|
+
constructor(message?: string, response?: unknown);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Raised when request times out
|
|
404
|
+
*/
|
|
405
|
+
declare class TimeoutError extends ConnectionError {
|
|
406
|
+
constructor(message?: string, response?: unknown);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Raised when the server returns an unexpected response
|
|
410
|
+
*/
|
|
411
|
+
declare class ServerError extends CardDBError {
|
|
412
|
+
/** HTTP status code */
|
|
413
|
+
readonly status: number | null;
|
|
414
|
+
constructor(message?: string, options?: {
|
|
415
|
+
status?: number | null;
|
|
416
|
+
response?: unknown;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Information about a failed link resolution
|
|
421
|
+
*/
|
|
422
|
+
interface LinkResolutionFailure {
|
|
423
|
+
/** The link field key that failed */
|
|
424
|
+
field: string;
|
|
425
|
+
/** The value that couldn't be resolved */
|
|
426
|
+
value: string | null;
|
|
427
|
+
/** The reason for the failure */
|
|
428
|
+
reason: 'not_found' | 'invalid' | 'permission_denied' | 'unknown';
|
|
429
|
+
/** Optional error message from the server */
|
|
430
|
+
message?: string;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Raised when link resolution fails for one or more links
|
|
434
|
+
*
|
|
435
|
+
* This is a warning-level error that contains the partial results along with
|
|
436
|
+
* information about which links failed to resolve. The application can choose
|
|
437
|
+
* to handle this gracefully or treat it as a fatal error.
|
|
438
|
+
*/
|
|
439
|
+
declare class LinkResolutionError extends CardDBError {
|
|
440
|
+
/** List of link resolution failures */
|
|
441
|
+
readonly failures: LinkResolutionFailure[];
|
|
442
|
+
/** Partial results that were successfully resolved */
|
|
443
|
+
readonly partialResults?: unknown;
|
|
444
|
+
constructor(message?: string, options?: {
|
|
445
|
+
failures?: LinkResolutionFailure[];
|
|
446
|
+
partialResults?: unknown;
|
|
447
|
+
response?: unknown;
|
|
448
|
+
});
|
|
449
|
+
/**
|
|
450
|
+
* Get failures for a specific field
|
|
451
|
+
*/
|
|
452
|
+
getFailuresForField(field: string): LinkResolutionFailure[];
|
|
453
|
+
/**
|
|
454
|
+
* Check if a specific field had resolution failures
|
|
455
|
+
*/
|
|
456
|
+
hasFailuresForField(field: string): boolean;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Filter operator helper functions
|
|
461
|
+
*
|
|
462
|
+
* These functions create operator objects that can be used in filters.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* // With filter builder
|
|
466
|
+
* filter: (f) => f
|
|
467
|
+
* .where('hp', gte(100))
|
|
468
|
+
* .where('types', contains('Pokemon'))
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* // With object literal
|
|
472
|
+
* filter: {
|
|
473
|
+
* hp: gte(100),
|
|
474
|
+
* types: contains('Pokemon')
|
|
475
|
+
* }
|
|
476
|
+
*/
|
|
477
|
+
|
|
478
|
+
/** Equality operator */
|
|
479
|
+
declare function eq(value: unknown): FilterOperatorValue;
|
|
480
|
+
/** Not equal operator */
|
|
481
|
+
declare function neq(value: unknown): FilterOperatorValue;
|
|
482
|
+
/** Greater than operator */
|
|
483
|
+
declare function gt(value: number): FilterOperatorValue;
|
|
484
|
+
/** Greater than or equal operator */
|
|
485
|
+
declare function gte(value: number): FilterOperatorValue;
|
|
486
|
+
/** Less than operator */
|
|
487
|
+
declare function lt(value: number): FilterOperatorValue;
|
|
488
|
+
/** Less than or equal operator */
|
|
489
|
+
declare function lte(value: number): FilterOperatorValue;
|
|
490
|
+
/** Value in array operator */
|
|
491
|
+
declare function within(values: unknown[]): FilterOperatorValue;
|
|
492
|
+
/** Value not in array operator */
|
|
493
|
+
declare function notWithin(values: unknown[]): FilterOperatorValue;
|
|
494
|
+
/** Array contains value operator */
|
|
495
|
+
declare function contains(value: unknown): FilterOperatorValue;
|
|
496
|
+
/** Case-sensitive pattern match (SQL LIKE) */
|
|
497
|
+
declare function like(pattern: string): FilterOperatorValue;
|
|
498
|
+
/** Case-insensitive pattern match (SQL ILIKE) */
|
|
499
|
+
declare function ilike(pattern: string): FilterOperatorValue;
|
|
500
|
+
/** Is null operator */
|
|
501
|
+
declare function isNull(): FilterOperatorValue;
|
|
502
|
+
/** Is not null operator */
|
|
503
|
+
declare function isNotNull(): FilterOperatorValue;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Filter builder for constructing complex filter queries
|
|
507
|
+
*
|
|
508
|
+
* Supports both builder pattern and object literal styles:
|
|
509
|
+
*
|
|
510
|
+
* @example Builder pattern
|
|
511
|
+
* filter: (f) => f
|
|
512
|
+
* .where('hp', gte(100))
|
|
513
|
+
* .where('types', contains('Pokemon'))
|
|
514
|
+
* .any(or => or
|
|
515
|
+
* .where('rarity', 'rare')
|
|
516
|
+
* .where('rarity', 'mythic')
|
|
517
|
+
* )
|
|
518
|
+
*
|
|
519
|
+
* @example Object literal
|
|
520
|
+
* filter: {
|
|
521
|
+
* hp: { gte: 100 },
|
|
522
|
+
* types: { contains: 'Pokemon' },
|
|
523
|
+
* $or: [
|
|
524
|
+
* { rarity: 'rare' },
|
|
525
|
+
* { rarity: 'mythic' }
|
|
526
|
+
* ]
|
|
527
|
+
* }
|
|
528
|
+
*/
|
|
529
|
+
|
|
530
|
+
declare class FilterBuilder {
|
|
531
|
+
private conditions;
|
|
532
|
+
private orGroups;
|
|
533
|
+
/**
|
|
534
|
+
* Add a condition to the filter
|
|
535
|
+
*
|
|
536
|
+
* @example Single field
|
|
537
|
+
* .where('name', 'Pikachu')
|
|
538
|
+
* .where('hp', gte(100))
|
|
539
|
+
*
|
|
540
|
+
* @example Multiple fields (object)
|
|
541
|
+
* .where({ name: 'Pikachu', hp: gte(100) })
|
|
542
|
+
*/
|
|
543
|
+
where(field: string, value: FilterValue): this;
|
|
544
|
+
where(conditions: Record<string, FilterValue>): this;
|
|
545
|
+
/**
|
|
546
|
+
* Add an OR group (any of the conditions must match)
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* .where('type', 'creature')
|
|
550
|
+
* .any(or => or
|
|
551
|
+
* .where('color', 'red')
|
|
552
|
+
* .where('color', 'blue')
|
|
553
|
+
* )
|
|
554
|
+
*/
|
|
555
|
+
any(callback: (builder: FilterBuilder) => void): this;
|
|
556
|
+
/**
|
|
557
|
+
* Add a link filter condition (filter on linked records)
|
|
558
|
+
*
|
|
559
|
+
* @example
|
|
560
|
+
* .whereLink('set_id', { code: 'DMU' })
|
|
561
|
+
* .whereLink('set_id', { name: ilike('%dominaria%') })
|
|
562
|
+
*/
|
|
563
|
+
whereLink(field: string, conditions: Record<string, FilterValue>): this;
|
|
564
|
+
/**
|
|
565
|
+
* Add an array element filter (for ARRAY of HASH fields)
|
|
566
|
+
* Matches if any element in the array matches all conditions
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* .whereAny('attacks', { damage: gte(50) })
|
|
570
|
+
* .whereAny('attacks', { name: ilike('%thunder%') })
|
|
571
|
+
*/
|
|
572
|
+
whereAny(field: string, conditions: Record<string, FilterValue>): this;
|
|
573
|
+
/**
|
|
574
|
+
* Get the conditions array (used internally for OR groups)
|
|
575
|
+
*/
|
|
576
|
+
getConditions(): FilterCondition[];
|
|
577
|
+
/**
|
|
578
|
+
* Build the final filter object
|
|
579
|
+
*/
|
|
580
|
+
build(): FilterCondition;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Resolve a filter input to a filter condition object
|
|
584
|
+
*
|
|
585
|
+
* Handles both builder functions and object literals
|
|
586
|
+
*/
|
|
587
|
+
declare function resolveFilter(input: FilterInput | undefined): FilterCondition | undefined;
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* GraphQL query builder for CardDB API
|
|
591
|
+
*/
|
|
592
|
+
|
|
593
|
+
interface SearchPublishersParams {
|
|
594
|
+
search?: string;
|
|
595
|
+
first?: number;
|
|
596
|
+
after?: string;
|
|
597
|
+
}
|
|
598
|
+
interface SearchGamesParams {
|
|
599
|
+
publisherSlug?: string;
|
|
600
|
+
search?: string;
|
|
601
|
+
first?: number;
|
|
602
|
+
after?: string;
|
|
603
|
+
}
|
|
604
|
+
interface SearchDatasetsParams {
|
|
605
|
+
publisherSlug?: string;
|
|
606
|
+
gameKey?: string;
|
|
607
|
+
search?: string;
|
|
608
|
+
purpose?: 'DATA' | 'RULES';
|
|
609
|
+
first?: number;
|
|
610
|
+
after?: string;
|
|
611
|
+
}
|
|
612
|
+
interface SearchRecordsParams {
|
|
613
|
+
publisherSlug: string;
|
|
614
|
+
gameKey: string;
|
|
615
|
+
datasetKey: string;
|
|
616
|
+
filter?: FilterCondition;
|
|
617
|
+
search?: string;
|
|
618
|
+
orderBy?: string;
|
|
619
|
+
resolveLinks?: string[];
|
|
620
|
+
first?: number;
|
|
621
|
+
after?: string;
|
|
622
|
+
validateSchema?: boolean;
|
|
623
|
+
}
|
|
624
|
+
interface ListDecksParams {
|
|
625
|
+
first?: number;
|
|
626
|
+
after?: string;
|
|
627
|
+
}
|
|
628
|
+
declare const QueryBuilder: {
|
|
629
|
+
searchPublishers(params?: SearchPublishersParams): {
|
|
630
|
+
query: string;
|
|
631
|
+
variables: Record<string, unknown>;
|
|
632
|
+
};
|
|
633
|
+
fetchPublisherById(): {
|
|
634
|
+
query: string;
|
|
635
|
+
};
|
|
636
|
+
fetchPublisherBySlug(): {
|
|
637
|
+
query: string;
|
|
638
|
+
};
|
|
639
|
+
fetchPublishers(): {
|
|
640
|
+
query: string;
|
|
641
|
+
};
|
|
642
|
+
searchGames(params?: SearchGamesParams): {
|
|
643
|
+
query: string;
|
|
644
|
+
variables: Record<string, unknown>;
|
|
645
|
+
};
|
|
646
|
+
fetchGameById(): {
|
|
647
|
+
query: string;
|
|
648
|
+
};
|
|
649
|
+
fetchGameByKeys(): {
|
|
650
|
+
query: string;
|
|
651
|
+
};
|
|
652
|
+
fetchGames(): {
|
|
653
|
+
query: string;
|
|
654
|
+
};
|
|
655
|
+
searchDatasets(params?: SearchDatasetsParams): {
|
|
656
|
+
query: string;
|
|
657
|
+
variables: Record<string, unknown>;
|
|
658
|
+
};
|
|
659
|
+
fetchDatasetById(): {
|
|
660
|
+
query: string;
|
|
661
|
+
};
|
|
662
|
+
fetchDatasetByKeys(): {
|
|
663
|
+
query: string;
|
|
664
|
+
};
|
|
665
|
+
fetchDatasets(): {
|
|
666
|
+
query: string;
|
|
667
|
+
};
|
|
668
|
+
searchRecords(params: SearchRecordsParams): {
|
|
669
|
+
query: string;
|
|
670
|
+
variables: Record<string, unknown>;
|
|
671
|
+
};
|
|
672
|
+
fetchRecordById(): {
|
|
673
|
+
query: string;
|
|
674
|
+
};
|
|
675
|
+
fetchRecordByIdentifier(): {
|
|
676
|
+
query: string;
|
|
677
|
+
};
|
|
678
|
+
fetchRecordsByIdentifier(): {
|
|
679
|
+
query: string;
|
|
680
|
+
};
|
|
681
|
+
fetchRecords(): {
|
|
682
|
+
query: string;
|
|
683
|
+
};
|
|
684
|
+
listMyDecks(params?: ListDecksParams): {
|
|
685
|
+
query: string;
|
|
686
|
+
variables: Record<string, unknown>;
|
|
687
|
+
};
|
|
688
|
+
fetchDeckById(): {
|
|
689
|
+
query: string;
|
|
690
|
+
};
|
|
691
|
+
fetchDeckByExternalRef(): {
|
|
692
|
+
query: string;
|
|
693
|
+
};
|
|
694
|
+
createDeck(): {
|
|
695
|
+
query: string;
|
|
696
|
+
};
|
|
697
|
+
updateDeck(): {
|
|
698
|
+
query: string;
|
|
699
|
+
};
|
|
700
|
+
deleteDeck(): {
|
|
701
|
+
query: string;
|
|
702
|
+
};
|
|
703
|
+
deckCreateVariables(input: DeckCreateInput): Record<string, unknown>;
|
|
704
|
+
deckUpdateVariables(id: string, input: DeckUpdateInput): Record<string, unknown>;
|
|
705
|
+
fetchMe(): {
|
|
706
|
+
query: string;
|
|
707
|
+
};
|
|
708
|
+
};
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Collection class for paginated results with async iteration support
|
|
712
|
+
*/
|
|
713
|
+
|
|
714
|
+
type NextPageLoader<T> = (cursor: string) => Promise<Collection<T>>;
|
|
715
|
+
/**
|
|
716
|
+
* Represents a paginated collection of results from the API.
|
|
717
|
+
* Implements AsyncIterable for easy iteration through all pages.
|
|
718
|
+
*/
|
|
719
|
+
declare class Collection<T> implements AsyncIterable<T> {
|
|
720
|
+
/** Total count of matching records across all pages */
|
|
721
|
+
readonly totalCount: number;
|
|
722
|
+
/** Pagination info */
|
|
723
|
+
readonly pageInfo: PageInfo;
|
|
724
|
+
/** Items in the current page */
|
|
725
|
+
readonly items: T[];
|
|
726
|
+
/** Function to load the next page */
|
|
727
|
+
private nextPageLoader?;
|
|
728
|
+
constructor(data: Connection<T>, options?: {
|
|
729
|
+
nextPageLoader?: NextPageLoader<T>;
|
|
730
|
+
itemTransformer?: (node: T) => T;
|
|
731
|
+
});
|
|
732
|
+
/** Check if there are more pages */
|
|
733
|
+
get hasNextPage(): boolean;
|
|
734
|
+
/** Check if there are previous pages */
|
|
735
|
+
get hasPreviousPage(): boolean;
|
|
736
|
+
/** Get the cursor for the next page */
|
|
737
|
+
get endCursor(): string | null;
|
|
738
|
+
/** Get the cursor for the previous page */
|
|
739
|
+
get startCursor(): string | null;
|
|
740
|
+
/** Number of items in the current page */
|
|
741
|
+
get length(): number;
|
|
742
|
+
/** Check if the current page is empty */
|
|
743
|
+
get isEmpty(): boolean;
|
|
744
|
+
/** Get the first item */
|
|
745
|
+
get first(): T | undefined;
|
|
746
|
+
/** Get the last item */
|
|
747
|
+
get last(): T | undefined;
|
|
748
|
+
/**
|
|
749
|
+
* Fetch the next page of results
|
|
750
|
+
*
|
|
751
|
+
* @returns The next page collection, or null if no more pages
|
|
752
|
+
* @throws Error if no next page loader is configured
|
|
753
|
+
*/
|
|
754
|
+
nextPage(): Promise<Collection<T> | null>;
|
|
755
|
+
/**
|
|
756
|
+
* Async iterator that automatically paginates through all results
|
|
757
|
+
*
|
|
758
|
+
* @example
|
|
759
|
+
* for await (const record of collection) {
|
|
760
|
+
* console.log(record.name)
|
|
761
|
+
* }
|
|
762
|
+
*
|
|
763
|
+
* @example
|
|
764
|
+
* const allRecords = []
|
|
765
|
+
* for await (const record of collection) {
|
|
766
|
+
* allRecords.push(record)
|
|
767
|
+
* }
|
|
768
|
+
*/
|
|
769
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
770
|
+
/**
|
|
771
|
+
* Iterate through all results, calling a callback for each item
|
|
772
|
+
* Similar to Array.forEach but async and auto-paginating
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* await collection.forEach(async (record) => {
|
|
776
|
+
* await processRecord(record)
|
|
777
|
+
* })
|
|
778
|
+
*/
|
|
779
|
+
forEach(callback: (item: T, index: number) => void | Promise<void>): Promise<void>;
|
|
780
|
+
/**
|
|
781
|
+
* Map over all results, returning a new array
|
|
782
|
+
* Auto-paginates through all pages
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* const names = await collection.map(record => record.name)
|
|
786
|
+
*/
|
|
787
|
+
map<U>(callback: (item: T, index: number) => U | Promise<U>): Promise<U[]>;
|
|
788
|
+
/**
|
|
789
|
+
* Filter results, returning items that match the predicate
|
|
790
|
+
* Auto-paginates through all pages
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* const rareCards = await collection.filter(card => card.rarity === 'rare')
|
|
794
|
+
*/
|
|
795
|
+
filter(predicate: (item: T, index: number) => boolean | Promise<boolean>): Promise<T[]>;
|
|
796
|
+
/**
|
|
797
|
+
* Find the first item matching a predicate
|
|
798
|
+
* Stops iterating once found
|
|
799
|
+
*
|
|
800
|
+
* @example
|
|
801
|
+
* const pikachu = await collection.find(card => card.name === 'Pikachu')
|
|
802
|
+
*/
|
|
803
|
+
find(predicate: (item: T, index: number) => boolean | Promise<boolean>): Promise<T | undefined>;
|
|
804
|
+
/**
|
|
805
|
+
* Take the first n items
|
|
806
|
+
* Stops fetching pages once n items are collected
|
|
807
|
+
*
|
|
808
|
+
* @example
|
|
809
|
+
* const first100 = await collection.take(100)
|
|
810
|
+
*/
|
|
811
|
+
take(n: number): Promise<T[]>;
|
|
812
|
+
/**
|
|
813
|
+
* Collect all items into an array
|
|
814
|
+
* Auto-paginates through all pages
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* const allRecords = await collection.toArray()
|
|
818
|
+
*/
|
|
819
|
+
toArray(): Promise<T[]>;
|
|
820
|
+
/**
|
|
821
|
+
* Iterate in batches (similar to Rails find_in_batches)
|
|
822
|
+
*
|
|
823
|
+
* @example
|
|
824
|
+
* for await (const batch of collection.batches()) {
|
|
825
|
+
* await processBatch(batch)
|
|
826
|
+
* }
|
|
827
|
+
*/
|
|
828
|
+
batches(): AsyncGenerator<T[]>;
|
|
829
|
+
/**
|
|
830
|
+
* Iterate one item at a time with batched fetching (similar to Rails find_each)
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* for await (const item of collection.each()) {
|
|
834
|
+
* await processItem(item)
|
|
835
|
+
* }
|
|
836
|
+
*/
|
|
837
|
+
each(): AsyncIterable<T>;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
export { type APIAccount, type APIApplication, type APIKeyInfo, AuthenticationError, type Cache, type CardDBConfig, CardDBError, Collection, type Connection, ConnectionError, type Dataset, type DatasetRecord, type DatasetRef, type DatasetSchema, type Deck, type DeckCreateInput, type DeckEntry, type DeckEntryInput, type DeckUpdateInput, type DeckVisibility, type Edge, type FieldInfo, type FieldType, type FileInfo, FilterBuilder, type FilterBuilderInterface, type FilterCondition, type FilterInput, type FilterOperatorValue, type FilterValue, type Game, type GameRef, GraphQLError, type GraphQLErrorInfo, type HydrateDeckEntryInput, type HydratedDeckEntry, type LinkFieldInfo, LinkResolutionError, type LinkResolutionFailure, type ListDecksParams, type LogLevel, type Logger, type NextPageLoader, NotFoundError, type PageInfo, type Publisher, type PublisherRef, type PublisherStatus, QueryBuilder, RateLimitError, type RateLimitInfo, type ResolvedLink, type ResourceType, RestrictedError, type SearchDatasetsParams, type SearchGamesParams, type SearchPublishersParams, type SearchRecordsParams, ServerError, TimeoutError, ValidationError, contains, eq, gt, gte, ilike, isNotNull, isNull, like, lt, lte, neq, notWithin, resolveFilter, within };
|