@quizbase/client 0.2.3 → 0.4.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/dist/index.d.cts CHANGED
@@ -38,7 +38,7 @@ interface paths {
38
38
  };
39
39
  /**
40
40
  * List categories
41
- * @description 24 top-level categories with localized names. Public, no API key required.
41
+ * @description 24 top-level categories with localized names.
42
42
  */
43
43
  get: {
44
44
  parameters: {
@@ -61,8 +61,17 @@ interface paths {
61
61
  "application/json": components["schemas"]["CategoriesResponse"];
62
62
  };
63
63
  };
64
- /** @description Invalid query parameters. */
65
- 400: {
64
+ /** @description Missing, malformed, invalid, or revoked API key. */
65
+ 401: {
66
+ headers: {
67
+ [name: string]: unknown;
68
+ };
69
+ content: {
70
+ "application/problem+json": components["schemas"]["ProblemDetails"];
71
+ };
72
+ };
73
+ /** @description IP not allowed (per-key allowlist). */
74
+ 403: {
66
75
  headers: {
67
76
  [name: string]: unknown;
68
77
  };
@@ -70,7 +79,7 @@ interface paths {
70
79
  "application/problem+json": components["schemas"]["ProblemDetails"];
71
80
  };
72
81
  };
73
- /** @description Rate limit exceeded. */
82
+ /** @description Rate limit exceeded. See `Retry-After` header. */
74
83
  429: {
75
84
  headers: {
76
85
  [name: string]: unknown;
@@ -107,7 +116,7 @@ interface paths {
107
116
  };
108
117
  /**
109
118
  * Aggregate dataset stats
110
- * @description Total questions, per-language, per-source, per-category counters. Public, cached.
119
+ * @description Total questions, per-language, per-source, per-category counters. Cached.
111
120
  */
112
121
  get: {
113
122
  parameters: {
@@ -130,8 +139,17 @@ interface paths {
130
139
  "application/json": components["schemas"]["StatsResponse"];
131
140
  };
132
141
  };
133
- /** @description Invalid query parameters. */
134
- 400: {
142
+ /** @description Missing, malformed, invalid, or revoked API key. */
143
+ 401: {
144
+ headers: {
145
+ [name: string]: unknown;
146
+ };
147
+ content: {
148
+ "application/problem+json": components["schemas"]["ProblemDetails"];
149
+ };
150
+ };
151
+ /** @description IP not allowed (per-key allowlist). */
152
+ 403: {
135
153
  headers: {
136
154
  [name: string]: unknown;
137
155
  };
@@ -139,7 +157,7 @@ interface paths {
139
157
  "application/problem+json": components["schemas"]["ProblemDetails"];
140
158
  };
141
159
  };
142
- /** @description Rate limit exceeded. */
160
+ /** @description Rate limit exceeded. See `Retry-After` header. */
143
161
  429: {
144
162
  headers: {
145
163
  [name: string]: unknown;
@@ -176,7 +194,7 @@ interface paths {
176
194
  };
177
195
  /**
178
196
  * Supported languages
179
- * @description Whitelist of `?lang=` values with native names and counts. Public.
197
+ * @description Whitelist of `?lang=` values with native names and counts.
180
198
  */
181
199
  get: {
182
200
  parameters: {
@@ -199,8 +217,17 @@ interface paths {
199
217
  "application/json": components["schemas"]["LanguagesResponse"];
200
218
  };
201
219
  };
202
- /** @description Invalid query parameters. */
203
- 400: {
220
+ /** @description Missing, malformed, invalid, or revoked API key. */
221
+ 401: {
222
+ headers: {
223
+ [name: string]: unknown;
224
+ };
225
+ content: {
226
+ "application/problem+json": components["schemas"]["ProblemDetails"];
227
+ };
228
+ };
229
+ /** @description IP not allowed (per-key allowlist). */
230
+ 403: {
204
231
  headers: {
205
232
  [name: string]: unknown;
206
233
  };
@@ -208,7 +235,7 @@ interface paths {
208
235
  "application/problem+json": components["schemas"]["ProblemDetails"];
209
236
  };
210
237
  };
211
- /** @description Rate limit exceeded. */
238
+ /** @description Rate limit exceeded. See `Retry-After` header. */
212
239
  429: {
213
240
  headers: {
214
241
  [name: string]: unknown;
@@ -245,7 +272,7 @@ interface paths {
245
272
  };
246
273
  /**
247
274
  * List curated topics
248
- * @description 2,184 curated topics with aliases and counts. Public, no API key required.
275
+ * @description 2,184 curated topics with aliases and counts.
249
276
  */
250
277
  get: {
251
278
  parameters: {
@@ -272,8 +299,17 @@ interface paths {
272
299
  "application/json": components["schemas"]["TopicsListResponse"];
273
300
  };
274
301
  };
275
- /** @description Invalid query parameters. */
276
- 400: {
302
+ /** @description Missing, malformed, invalid, or revoked API key. */
303
+ 401: {
304
+ headers: {
305
+ [name: string]: unknown;
306
+ };
307
+ content: {
308
+ "application/problem+json": components["schemas"]["ProblemDetails"];
309
+ };
310
+ };
311
+ /** @description IP not allowed (per-key allowlist). */
312
+ 403: {
277
313
  headers: {
278
314
  [name: string]: unknown;
279
315
  };
@@ -281,7 +317,7 @@ interface paths {
281
317
  "application/problem+json": components["schemas"]["ProblemDetails"];
282
318
  };
283
319
  };
284
- /** @description Rate limit exceeded. */
320
+ /** @description Rate limit exceeded. See `Retry-After` header. */
285
321
  429: {
286
322
  headers: {
287
323
  [name: string]: unknown;
@@ -344,8 +380,17 @@ interface paths {
344
380
  "application/json": components["schemas"]["TopicDetailResponse"];
345
381
  };
346
382
  };
347
- /** @description Invalid query parameters. */
348
- 400: {
383
+ /** @description Missing, malformed, invalid, or revoked API key. */
384
+ 401: {
385
+ headers: {
386
+ [name: string]: unknown;
387
+ };
388
+ content: {
389
+ "application/problem+json": components["schemas"]["ProblemDetails"];
390
+ };
391
+ };
392
+ /** @description IP not allowed (per-key allowlist). */
393
+ 403: {
349
394
  headers: {
350
395
  [name: string]: unknown;
351
396
  };
@@ -362,7 +407,7 @@ interface paths {
362
407
  "application/problem+json": components["schemas"]["ProblemDetails"];
363
408
  };
364
409
  };
365
- /** @description Rate limit exceeded. */
410
+ /** @description Rate limit exceeded. See `Retry-After` header. */
366
411
  429: {
367
412
  headers: {
368
413
  [name: string]: unknown;
@@ -425,8 +470,17 @@ interface paths {
425
470
  "application/json": components["schemas"]["TagsListResponse"];
426
471
  };
427
472
  };
428
- /** @description Invalid query parameters. */
429
- 400: {
473
+ /** @description Missing, malformed, invalid, or revoked API key. */
474
+ 401: {
475
+ headers: {
476
+ [name: string]: unknown;
477
+ };
478
+ content: {
479
+ "application/problem+json": components["schemas"]["ProblemDetails"];
480
+ };
481
+ };
482
+ /** @description IP not allowed (per-key allowlist). */
483
+ 403: {
430
484
  headers: {
431
485
  [name: string]: unknown;
432
486
  };
@@ -434,7 +488,7 @@ interface paths {
434
488
  "application/problem+json": components["schemas"]["ProblemDetails"];
435
489
  };
436
490
  };
437
- /** @description Rate limit exceeded. */
491
+ /** @description Rate limit exceeded. See `Retry-After` header. */
438
492
  429: {
439
493
  headers: {
440
494
  [name: string]: unknown;
@@ -497,8 +551,8 @@ interface paths {
497
551
  "application/json": components["schemas"]["SubcategoriesListResponse"];
498
552
  };
499
553
  };
500
- /** @description Invalid query parameters. */
501
- 400: {
554
+ /** @description Missing, malformed, invalid, or revoked API key. */
555
+ 401: {
502
556
  headers: {
503
557
  [name: string]: unknown;
504
558
  };
@@ -506,7 +560,16 @@ interface paths {
506
560
  "application/problem+json": components["schemas"]["ProblemDetails"];
507
561
  };
508
562
  };
509
- /** @description Rate limit exceeded. */
563
+ /** @description IP not allowed (per-key allowlist). */
564
+ 403: {
565
+ headers: {
566
+ [name: string]: unknown;
567
+ };
568
+ content: {
569
+ "application/problem+json": components["schemas"]["ProblemDetails"];
570
+ };
571
+ };
572
+ /** @description Rate limit exceeded. See `Retry-After` header. */
510
573
  429: {
511
574
  headers: {
512
575
  [name: string]: unknown;
@@ -545,7 +608,7 @@ interface paths {
545
608
  put?: never;
546
609
  /**
547
610
  * Report a problem with a question
548
- * @description Public submission for translation / factual / inappropriate / attribution / other reports. Rate-limited 5/min/IP.
611
+ * @description Anonymous submission for translation / factual / inappropriate / attribution / other reports. Rate-limited 5/min/IP. No API key required.
549
612
  */
550
613
  post: {
551
614
  parameters: {
@@ -784,7 +847,8 @@ interface paths {
784
847
  limit?: number;
785
848
  /** @description Display language for category names + slug labels (subcategories/tags) */
786
849
  lang?: "en" | "pl";
787
- updated_since?: string | null;
850
+ /** @description ISO 8601 datetime — only questions modified after this point. */
851
+ updated_since?: string;
788
852
  category?: string;
789
853
  difficulty?: "easy" | "medium" | "hard";
790
854
  type?: "multiple" | "boolean" | "text_input";
@@ -1091,6 +1155,21 @@ interface components {
1091
1155
  retryAfter?: number;
1092
1156
  /** @description URL to upgrade plan (429 only). */
1093
1157
  upgradeUrl?: string;
1158
+ /**
1159
+ * @description Rate limit ceiling that was exceeded (429 only).
1160
+ * @example 5
1161
+ */
1162
+ limit?: number;
1163
+ /**
1164
+ * @description API tier whose limit was exceeded (429 only).
1165
+ * @example free
1166
+ */
1167
+ tier?: string;
1168
+ /**
1169
+ * @description Number of requests in current window (429 only).
1170
+ * @example 100
1171
+ */
1172
+ current?: number;
1094
1173
  };
1095
1174
  Question: {
1096
1175
  /**
@@ -1540,19 +1619,15 @@ interface components {
1540
1619
  ApiKeyInfo: {
1541
1620
  /** @example 01J3KXY1ZAB7CQNR8TP4Z9EXMQ */
1542
1621
  id: string;
1543
- /** @example Default test key */
1622
+ /** @example Default key */
1544
1623
  name: string;
1545
1624
  /**
1546
1625
  * @description Masked display value.
1547
- * @example qb_test_pk_••••1234
1626
+ * @example qb_pk_••••1234
1548
1627
  */
1549
1628
  prefix: string;
1550
1629
  /**
1551
- * @example test
1552
- * @enum {string}
1553
- */
1554
- env: "test" | "live";
1555
- /**
1630
+ * @description `pk` (publishable, CORS-safe for browsers) or `sk` (secret, backend-only).
1556
1631
  * @example pk
1557
1632
  * @enum {string}
1558
1633
  */
@@ -1560,16 +1635,16 @@ interface components {
1560
1635
  };
1561
1636
  RateLimitInfo: {
1562
1637
  /**
1563
- * @description Per-minute window cap. Test keys report `Number.MAX_SAFE_INTEGER`.
1564
- * @example 60
1638
+ * @description Burst window cap (10s sliding). Shared across all active keys of the user.
1639
+ * @example 10
1565
1640
  */
1566
1641
  limit: number;
1567
- /** @example 58 */
1642
+ /** @example 8 */
1568
1643
  remaining: number;
1569
- /** @example 42 */
1644
+ /** @example 7 */
1570
1645
  resetInSeconds: number;
1571
- /** @example 60 */
1572
- perMinute: number;
1646
+ /** @example 10 */
1647
+ burstPer10s: number;
1573
1648
  /** @example 500 */
1574
1649
  perDay: number;
1575
1650
  };
@@ -1722,7 +1797,7 @@ type Schemas = components['schemas'];
1722
1797
  /** Logical endpoint identifiers — stable across path-param values, used for telemetry + per-endpoint timeouts. */
1723
1798
  type EndpointKey = 'questions.list' | 'questions.random' | 'questions.get' | 'categories.list' | 'languages.list' | 'topics.list' | 'topics.get' | 'tags.list' | 'subcategories.list' | 'stats.get' | 'me.get' | 'usage.get' | 'report.create';
1724
1799
  interface ClientOptions {
1725
- /** API key. Use `qb_test_pk_*` / `qb_test_sk_*` for development (free, unmetered) and `qb_live_*` in production. */
1800
+ /** API key `qb_pk_*` (publishable, CORS-safe for browsers) or `qb_sk_*` (secret, backend-only). Get one at https://quizbase.runriva.com/dashboard/keys. */
1726
1801
  apiKey: string;
1727
1802
  /** Override base URL. Defaults to `https://quizbase.runriva.com`. */
1728
1803
  baseUrl?: string;
@@ -1739,11 +1814,19 @@ interface ClientOptions {
1739
1814
  /** User-Agent suffix appended to the SDK identifier. */
1740
1815
  userAgent?: string;
1741
1816
  }
1817
+ type QuestionsListParams = paths['/api/v1/questions']['get']['parameters']['query'];
1818
+ type TopicsListParams = paths['/api/v1/topics']['get']['parameters']['query'];
1819
+ type TagsListParams = paths['/api/v1/tags']['get']['parameters']['query'];
1820
+ type SubcategoriesListParams = paths['/api/v1/subcategories']['get']['parameters']['query'];
1742
1821
  interface QuizbaseClient {
1743
1822
  questions: {
1744
- list(params?: paths['/api/v1/questions']['get']['parameters']['query']): Promise<Schemas['QuestionsListResponse']>;
1823
+ list(params?: QuestionsListParams): Promise<Schemas['QuestionsListResponse']>;
1745
1824
  random(params?: paths['/api/v1/questions/random']['get']['parameters']['query']): Promise<Schemas['QuestionsRandomResponse']>;
1746
1825
  get(id: string, params?: paths['/api/v1/questions/{id}']['get']['parameters']['query']): Promise<Schemas['QuestionByIdResponse']>;
1826
+ /** Iterate every page of `/questions`, auto-following `_links.next`. */
1827
+ pages(params?: QuestionsListParams): AsyncIterableIterator<Schemas['QuestionsListResponse']>;
1828
+ /** Iterate every question across all pages. */
1829
+ listAll(params?: QuestionsListParams): AsyncIterableIterator<Schemas['Question']>;
1747
1830
  };
1748
1831
  categories: {
1749
1832
  list(params?: paths['/api/v1/categories']['get']['parameters']['query']): Promise<Schemas['CategoriesResponse']>;
@@ -1752,14 +1835,26 @@ interface QuizbaseClient {
1752
1835
  list(): Promise<Schemas['LanguagesResponse']>;
1753
1836
  };
1754
1837
  topics: {
1755
- list(params?: paths['/api/v1/topics']['get']['parameters']['query']): Promise<Schemas['TopicsListResponse']>;
1838
+ list(params?: TopicsListParams): Promise<Schemas['TopicsListResponse']>;
1756
1839
  get(slug: string, params?: paths['/api/v1/topics/{slug}']['get']['parameters']['query']): Promise<Schemas['TopicDetailResponse']>;
1840
+ /** Iterate every page of `/topics`, auto-following `_links.next`. */
1841
+ pages(params?: TopicsListParams): AsyncIterableIterator<Schemas['TopicsListResponse']>;
1842
+ /** Iterate every topic across all pages. */
1843
+ listAll(params?: TopicsListParams): AsyncIterableIterator<Schemas['TopicEntry']>;
1757
1844
  };
1758
1845
  tags: {
1759
- list(params?: paths['/api/v1/tags']['get']['parameters']['query']): Promise<Schemas['TagsListResponse']>;
1846
+ list(params?: TagsListParams): Promise<Schemas['TagsListResponse']>;
1847
+ /** Iterate every page of `/tags`, auto-following `_links.next`. */
1848
+ pages(params?: TagsListParams): AsyncIterableIterator<Schemas['TagsListResponse']>;
1849
+ /** Iterate every tag across all pages. */
1850
+ listAll(params?: TagsListParams): AsyncIterableIterator<Schemas['RawSlugEntry']>;
1760
1851
  };
1761
1852
  subcategories: {
1762
- list(params?: paths['/api/v1/subcategories']['get']['parameters']['query']): Promise<Schemas['SubcategoriesListResponse']>;
1853
+ list(params?: SubcategoriesListParams): Promise<Schemas['SubcategoriesListResponse']>;
1854
+ /** Iterate every page of `/subcategories`, auto-following `_links.next`. */
1855
+ pages(params?: SubcategoriesListParams): AsyncIterableIterator<Schemas['SubcategoriesListResponse']>;
1856
+ /** Iterate every subcategory across all pages. */
1857
+ listAll(params?: SubcategoriesListParams): AsyncIterableIterator<Schemas['RawSlugEntry']>;
1763
1858
  };
1764
1859
  stats: {
1765
1860
  get(): Promise<Schemas['StatsResponse']>;