@quizbase/client 0.4.0 → 0.4.1
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 +56 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ const client = createClient({
|
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
const random = await client.questions.random({ category: 'science-and-nature', lang: 'en' });
|
|
31
|
-
console.log(random.data.
|
|
31
|
+
console.log(random.data[0].text);
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Get a key at [quizbase.runriva.com/dashboard/keys](https://quizbase.runriva.com/dashboard/keys). The free tier is **500 requests/day across all your keys** against full production data — enough to ship a real app. Paid tiers at [/pricing](https://quizbase.runriva.com/pricing).
|
|
@@ -58,6 +58,8 @@ client.report.create({ questionId, kind, comment });
|
|
|
58
58
|
|
|
59
59
|
Full parameter docs: [docs.quizbase.runriva.com/docs](https://quizbase.runriva.com/docs) and the interactive [API Reference](https://quizbase.runriva.com/docs/api-reference).
|
|
60
60
|
|
|
61
|
+
> **Tip:** every question has a stable UUID `id` that never changes. Save it client-side and compose it into multi-language quizzes, daily challenges, anti-cheat, and more — see [Client patterns](#client-patterns-with-stable-ids) below.
|
|
62
|
+
|
|
61
63
|
## Pagination
|
|
62
64
|
|
|
63
65
|
`questions`, `topics`, `tags`, and `subcategories` are cursor-paginated. Use `listAll()` to iterate every item, or `pages()` to iterate page-by-page — both auto-follow `_links.next` and preserve filters across pages.
|
|
@@ -76,6 +78,58 @@ for await (const page of client.topics.pages({ lang: 'en' })) {
|
|
|
76
78
|
|
|
77
79
|
Need manual control? `list()` still exposes `_links.next` and a `cursor` query param.
|
|
78
80
|
|
|
81
|
+
## Client patterns with stable IDs
|
|
82
|
+
|
|
83
|
+
Every question carries a stable UUID v7 `id` that never changes after import. The SDK is intentionally **thin** — no `?seed=`, no `?daily=`, no built-in deduplication. The stable id is the primitive you compose into mechanics. Six patterns cover most real apps:
|
|
84
|
+
|
|
85
|
+
### Same question across languages
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
const en = await client.questions.random({ lang: 'en' });
|
|
89
|
+
const id = en.data[0].id;
|
|
90
|
+
const pl = await client.questions.get(id, { lang: 'pl' });
|
|
91
|
+
const es = await client.questions.get(id, { lang: 'es' });
|
|
92
|
+
// Same canonical question, three languages — UUID is the link.
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Don't repeat — exclude seen questions
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const seen = new Set<string>();
|
|
99
|
+
const batch = await client.questions.random({
|
|
100
|
+
category: 'science-and-nature',
|
|
101
|
+
amount: 20,
|
|
102
|
+
exclude: [...seen]
|
|
103
|
+
});
|
|
104
|
+
batch.data.forEach((q) => seen.add(q.id));
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`exclude` accepts up to 250 UUIDs. For longer histories keep `seen` client-side and filter after the fetch.
|
|
108
|
+
|
|
109
|
+
### Daily challenge — same question for everyone today
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const day = new Date().toISOString().slice(0, 10); // "2026-05-19"
|
|
113
|
+
const idx = [...day].reduce((h, c) => (h * 31 + c.charCodeAt(0)) | 0, 7);
|
|
114
|
+
const pool = await client.questions.list({ category: 'history', limit: 50 });
|
|
115
|
+
const todays = pool.data[Math.abs(idx) % pool.data.length];
|
|
116
|
+
// Persist `todays.id` server-side so retries serve the same question.
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Multiplayer sync — both players see the same question
|
|
120
|
+
|
|
121
|
+
Your matchmaker picks one `id` (via `random` or `list`), broadcasts to both clients, and both clients call `questions.get(id, { lang })`. Same UUID, per-player language preference. Zero state on QuizBase — your matchmaker owns the round.
|
|
122
|
+
|
|
123
|
+
### Server-side anti-cheat — never ship `correctAnswer` to the client
|
|
124
|
+
|
|
125
|
+
Use `qb_sk_*` (secret key) from your server to fetch full questions including `correctAnswer`. Forward only `id` + `text` + a shuffled `[correctAnswer, ...incorrectAnswers]` to the client. Validate the submitted answer server-side by re-fetching with the same `id`. Browsers cannot reach `qb_sk_*` — CORS blocks it.
|
|
126
|
+
|
|
127
|
+
### Stable Anki / Quizlet flashcards across updates
|
|
128
|
+
|
|
129
|
+
Save `{id, lang}` as your card key. When the upstream question changes (typo fix, distractor swap, translation refresh), `questions.get(id, { lang })` returns the updated content under the same id — your card auto-updates without re-import. Soft-deleted questions return 404; treat that as "card removed upstream".
|
|
130
|
+
|
|
131
|
+
Full code samples and edge cases at [/docs/api/questions-by-id § What you can do with a stable id](https://quizbase.runriva.com/docs/api/questions-by-id). For MCP agents, the same playbook is exposed as the `client_mechanics_patterns` prompt.
|
|
132
|
+
|
|
79
133
|
## Errors
|
|
80
134
|
|
|
81
135
|
Every non-2xx response throws `QuizbaseError` carrying the parsed [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457):
|
|
@@ -164,7 +218,7 @@ All responses are typed from the OpenAPI spec. Hover over `client.questions.rand
|
|
|
164
218
|
- **GitHub:** [maciejdzierzek/quizbase-sdk-ts](https://github.com/maciejdzierzek/quizbase-sdk-ts)
|
|
165
219
|
- **Issues / feedback:** [GitHub Issues](https://github.com/maciejdzierzek/quizbase-sdk-ts/issues)
|
|
166
220
|
- **Releases:** automated by [release-please](https://github.com/googleapis/release-please) from conventional commits
|
|
167
|
-
- **Drift guard:** the
|
|
221
|
+
- **Drift guard:** every release is verified against the live OpenAPI spec at [quizbase.runriva.com/openapi.json](https://quizbase.runriva.com/openapi.json) — types reflect the current API surface.
|
|
168
222
|
|
|
169
223
|
## License
|
|
170
224
|
|
package/package.json
CHANGED