@zephyr424/wb-sdk 0.1.1 → 0.2.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/.github/workflows/deploy.yml +41 -0
- package/README.md +2 -2
- package/data/top5000.json +55002 -0
- package/docs/.vitepress/config.mjs +112 -0
- package/docs/api/review.md +155 -0
- package/docs/api/types.md +0 -0
- package/docs/api/word.md +189 -0
- package/docs/blog/designing-api.md +30 -0
- package/docs/blog/index.md +19 -0
- package/docs/blog/publishing-to-npm.md +36 -0
- package/docs/blog/why-sm2.md +26 -0
- package/docs/contributors.md +16 -0
- package/docs/en/api/word.md +189 -0
- package/docs/en/blog/index.md +0 -0
- package/docs/en/guide/index.md +28 -0
- package/docs/en/index.md +25 -0
- package/docs/guide/index.md +100 -0
- package/docs/index.md +39 -0
- package/docs/package-lock.json +2564 -0
- package/docs/package.json +19 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/scripts/build-wordlist.js +26 -0
- package/src/wordBank.js +19 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { defineConfig } from 'vitepress'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
title: "wb-sdk",
|
|
5
|
+
description: "A spaced repetition engine for vocabulary building",
|
|
6
|
+
|
|
7
|
+
// 网站图标
|
|
8
|
+
head: [
|
|
9
|
+
['link', { rel: 'icon', href: '/logo.png' }],
|
|
10
|
+
// Google Analytics(替换为你的 GA ID)
|
|
11
|
+
['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX' }],
|
|
12
|
+
['script', {}, `
|
|
13
|
+
window.dataLayer = window.dataLayer || [];
|
|
14
|
+
function gtag(){dataLayer.push(arguments);}
|
|
15
|
+
gtag('js', new Date());
|
|
16
|
+
gtag('config', 'G-XXXXXXXXXX');
|
|
17
|
+
`]
|
|
18
|
+
],
|
|
19
|
+
|
|
20
|
+
// 深浅主题(默认已支持)
|
|
21
|
+
appearance: true,
|
|
22
|
+
|
|
23
|
+
themeConfig: {
|
|
24
|
+
// 搜索
|
|
25
|
+
search: {
|
|
26
|
+
provider: 'local'
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// 导航栏
|
|
30
|
+
nav: [
|
|
31
|
+
{ text: 'Home', link: '/' },
|
|
32
|
+
{ text: 'Guide', link: '/guide/' },
|
|
33
|
+
{ text: 'API', link: '/api/word' },
|
|
34
|
+
{ text: 'Blog', link: '/blog/' },
|
|
35
|
+
{ text: 'GitHub', link: 'https://github.com/Zephyr424/wb-sdk' },
|
|
36
|
+
{ text: 'npm', link: 'https://www.npmjs.com/package/@zephyr424/wb-sdk' }
|
|
37
|
+
],
|
|
38
|
+
|
|
39
|
+
// 侧边栏
|
|
40
|
+
sidebar: {
|
|
41
|
+
'/guide/': [
|
|
42
|
+
{
|
|
43
|
+
text: 'Guide',
|
|
44
|
+
items: [
|
|
45
|
+
{ text: 'Getting Started', link: '/guide/' },
|
|
46
|
+
{ text: 'Core Concepts', link: '/guide/core-concepts' }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
'/api/': [
|
|
51
|
+
{
|
|
52
|
+
text: 'API Reference',
|
|
53
|
+
items: [
|
|
54
|
+
{ text: 'Word Management', link: '/api/word' },
|
|
55
|
+
{ text: 'Review Scheduling', link: '/api/review' },
|
|
56
|
+
{ text: 'Types', link: '/api/types' }
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
'/blog/': [
|
|
61
|
+
{
|
|
62
|
+
text: 'Blog',
|
|
63
|
+
items: [
|
|
64
|
+
{ text: 'Why SM-2 Algorithm', link: '/blog/why-sm2' },
|
|
65
|
+
{ text: 'Designing wb.word API', link: '/blog/designing-api' },
|
|
66
|
+
{ text: 'How I Published to npm', link: '/blog/publishing-to-npm' }
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// 社交链接
|
|
73
|
+
socialLinks: [
|
|
74
|
+
{ icon: 'github', link: 'https://github.com/Zephyr424/wb-sdk' }
|
|
75
|
+
],
|
|
76
|
+
|
|
77
|
+
// 页脚
|
|
78
|
+
footer: {
|
|
79
|
+
message: 'Released under the MIT License',
|
|
80
|
+
copyright: 'Copyright © 2026 Zephyr424'
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// 上次更新时间
|
|
84
|
+
lastUpdated: {
|
|
85
|
+
text: 'Last updated'
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// 贡献者展示(需要 GitHub API 支持,先配置)
|
|
89
|
+
contributors: {
|
|
90
|
+
avatarSize: 32
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// 编辑链接(指向 GitHub)
|
|
94
|
+
editLink: {
|
|
95
|
+
pattern: 'https://github.com/Zephyr424/wb-sdk/edit/main/docs/:path',
|
|
96
|
+
text: 'Edit this page on GitHub'
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// 多语言支持 (i18n)
|
|
101
|
+
locales: {
|
|
102
|
+
root: {
|
|
103
|
+
label: '简体中文',
|
|
104
|
+
lang: 'zh-CN'
|
|
105
|
+
},
|
|
106
|
+
en: {
|
|
107
|
+
label: 'English',
|
|
108
|
+
lang: 'en',
|
|
109
|
+
link: '/en/'
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
})
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Review Scheduling API
|
|
2
|
+
|
|
3
|
+
The `wb.review` module handles all spaced repetition logic — determining which words are due, recording review performance, and forecasting future workload.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `wb.review.getDue([today])`
|
|
8
|
+
|
|
9
|
+
Returns all words that are due for review on a given date.
|
|
10
|
+
|
|
11
|
+
**Parameters:**
|
|
12
|
+
|
|
13
|
+
| Parameter | Type | Required | Description |
|
|
14
|
+
| :--- | :--- | :--- | :--- |
|
|
15
|
+
| `today` | `Date` | ❌ No | The date to check (defaults to `new Date()`). |
|
|
16
|
+
|
|
17
|
+
**Returns:** `Word[]` — an array of `Word` objects that are due.
|
|
18
|
+
|
|
19
|
+
**Example:**
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
// Get words due today
|
|
23
|
+
const dueToday = wb.review.getDue();
|
|
24
|
+
console.log(`📚 ${dueToday.length} words due today`);
|
|
25
|
+
|
|
26
|
+
// Get words due on a specific date
|
|
27
|
+
const christmasDue = wb.review.getDue(new Date('2026-12-25'));
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## `wb.review.submit(id, quality)`
|
|
33
|
+
|
|
34
|
+
Records a review attempt for a specific word and updates its SM‑2 state (interval, repetitions, ease factor, and last reviewed date).
|
|
35
|
+
|
|
36
|
+
**Parameters:**
|
|
37
|
+
|
|
38
|
+
| Parameter | Type | Required | Description |
|
|
39
|
+
| :--- | :--- | :--- | :--- |
|
|
40
|
+
| `id` | `string` | ✅ Yes | The ID of the word being reviewed. |
|
|
41
|
+
| `quality` | `number` | ✅ Yes | Self‑rated recall quality from `0` (completely forgot) to `5` (perfect recall). |
|
|
42
|
+
|
|
43
|
+
**Returns:** `Word` — the updated `Word` object.
|
|
44
|
+
|
|
45
|
+
**Quality Scale:**
|
|
46
|
+
|
|
47
|
+
| Score | Meaning |
|
|
48
|
+
| :--- | :--- |
|
|
49
|
+
| `5` | Perfect recall |
|
|
50
|
+
| `4` | Good recall, slight hesitation |
|
|
51
|
+
| `3` | Recalled with difficulty |
|
|
52
|
+
| `2` | Forgot, but recognized |
|
|
53
|
+
| `1` | Almost forgot |
|
|
54
|
+
| `0` | Completely forgot |
|
|
55
|
+
|
|
56
|
+
**Example:**
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
// Review the word with ID 'apple' and rate it as 4/5
|
|
60
|
+
const updated = wb.review.submit('apple', 4);
|
|
61
|
+
console.log(`Next review in ${updated.interval} days`);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## `wb.review.forecast([days])`
|
|
67
|
+
|
|
68
|
+
Predicts how many words will become due for each day over the next N days, based on current word states.
|
|
69
|
+
|
|
70
|
+
**Parameters:**
|
|
71
|
+
|
|
72
|
+
| Parameter | Type | Required | Description |
|
|
73
|
+
| :--- | :--- | :--- | :--- |
|
|
74
|
+
| `days` | `number` | ❌ No | Number of days to forecast (default: `7`). |
|
|
75
|
+
|
|
76
|
+
**Returns:** `Object` — a dictionary where keys are date strings (`YYYY-MM-DD`) and values are the number of words due on that day.
|
|
77
|
+
|
|
78
|
+
**Example:**
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
const forecast = wb.review.forecast(7);
|
|
82
|
+
console.log(forecast);
|
|
83
|
+
// {
|
|
84
|
+
// '2026-09-01': 5,
|
|
85
|
+
// '2026-09-02': 8,
|
|
86
|
+
// '2026-09-03': 3,
|
|
87
|
+
// '2026-09-04': 0,
|
|
88
|
+
// '2026-09-05': 2,
|
|
89
|
+
// '2026-09-06': 4,
|
|
90
|
+
// '2026-09-07': 1
|
|
91
|
+
// }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## `wb.review.progress()`
|
|
97
|
+
|
|
98
|
+
Returns an overview of your overall learning status — total words, mastered, remaining, and estimated days to mastery.
|
|
99
|
+
|
|
100
|
+
**Returns:** `Object` with the following fields:
|
|
101
|
+
|
|
102
|
+
| Field | Type | Description |
|
|
103
|
+
| :--- | :--- | :--- |
|
|
104
|
+
| `total` | `number` | Total number of words in the bank. |
|
|
105
|
+
| `mastered` | `number` | Number of words with an interval ≥ 30 days. |
|
|
106
|
+
| `remaining` | `number` | Words not yet mastered (`total - mastered`). |
|
|
107
|
+
| `daysToMaster` | `number` | Estimated days until all words are mastered (based on an assumed rate of 5 new words mastered per day). |
|
|
108
|
+
|
|
109
|
+
**Example:**
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
const stats = wb.review.progress();
|
|
113
|
+
console.log(stats);
|
|
114
|
+
// { total: 5000, mastered: 1200, remaining: 3800, daysToMaster: 760 }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Understanding the SM‑2 Algorithm
|
|
120
|
+
|
|
121
|
+
The `submit` method implements the **SM‑2** algorithm, which works as follows:
|
|
122
|
+
|
|
123
|
+
- If `quality < 3` (failed recall):
|
|
124
|
+
- The word's `repetitions` counter is reset to `0`.
|
|
125
|
+
- The `interval` is set to `1` day (review again tomorrow).
|
|
126
|
+
- The `easeFactor` remains unchanged.
|
|
127
|
+
|
|
128
|
+
- If `quality >= 3` (successful recall):
|
|
129
|
+
- The `interval` is updated based on the current `repetitions` count:
|
|
130
|
+
- `repetitions == 0` → interval = `1` day
|
|
131
|
+
- `repetitions == 1` → interval = `6` days
|
|
132
|
+
- `repetitions >= 2` → interval = `round(interval * easeFactor)`
|
|
133
|
+
- The `repetitions` count is incremented.
|
|
134
|
+
- The `easeFactor` is adjusted using the formula:
|
|
135
|
+
```
|
|
136
|
+
ease += 0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02)
|
|
137
|
+
```
|
|
138
|
+
The result is clamped between `1.3` and `2.5`.
|
|
139
|
+
|
|
140
|
+
This dynamic adjustment ensures that words you find difficult appear more frequently, while easy words are spaced out over longer intervals.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Summary of `wb.review` Methods
|
|
145
|
+
|
|
146
|
+
| Method | Description |
|
|
147
|
+
| :--- | :--- |
|
|
148
|
+
| `getDue([today])` | Get words due for review today (or on a custom date). |
|
|
149
|
+
| `submit(id, quality)` | Record a review and update the word's SM‑2 state. |
|
|
150
|
+
| `forecast([days])` | Predict how many words will be due each day for the next N days. |
|
|
151
|
+
| `progress()` | Get overall learning statistics (total, mastered, remaining, days to mastery). |
|
|
152
|
+
|
|
153
|
+
For word management methods (`list`, `get`, `add`, `remove`, `search`, `top`), see the [Word Management API](/api/word).
|
|
154
|
+
|
|
155
|
+
---
|
|
Binary file
|
package/docs/api/word.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Word Management API
|
|
2
|
+
|
|
3
|
+
The `wb.word` module provides methods for managing your word bank — adding, retrieving, searching, and deleting words.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `wb.word.list()`
|
|
8
|
+
|
|
9
|
+
Returns all words currently stored in the bank.
|
|
10
|
+
|
|
11
|
+
**Returns:** `Word[]` — an array of `Word` objects.
|
|
12
|
+
|
|
13
|
+
**Example:**
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const allWords = wb.word.list();
|
|
17
|
+
console.log(allWords);
|
|
18
|
+
// [
|
|
19
|
+
// Word { id: '1', word: 'apple', definition: 'a fruit', ... },
|
|
20
|
+
// Word { id: '2', word: 'book', definition: 'a set of pages', ... }
|
|
21
|
+
// ]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## `wb.word.get(id)`
|
|
27
|
+
|
|
28
|
+
Retrieves a single word by its unique identifier.
|
|
29
|
+
|
|
30
|
+
**Parameters:**
|
|
31
|
+
|
|
32
|
+
| Parameter | Type | Required | Description |
|
|
33
|
+
| :--- | :--- | :--- | :--- |
|
|
34
|
+
| `id` | `string` | ✅ Yes | The unique ID of the word |
|
|
35
|
+
|
|
36
|
+
**Returns:** `Word | null` — the word object if found, otherwise `null`.
|
|
37
|
+
|
|
38
|
+
**Example:**
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const word = wb.word.get('apple');
|
|
42
|
+
if (word) {
|
|
43
|
+
console.log(word.definition); // "a fruit"
|
|
44
|
+
} else {
|
|
45
|
+
console.log('Word not found');
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## `wb.word.add(data)`
|
|
52
|
+
|
|
53
|
+
Adds a new word to the bank. If a word with the same ID already exists, it will be overwritten.
|
|
54
|
+
|
|
55
|
+
**Parameters:**
|
|
56
|
+
|
|
57
|
+
| Parameter | Type | Required | Description |
|
|
58
|
+
| :--- | :--- | :--- | :--- |
|
|
59
|
+
| `data.id` | `string` | ✅ Yes | Unique identifier |
|
|
60
|
+
| `data.word` | `string` | ✅ Yes | The word itself |
|
|
61
|
+
| `data.definition` | `string` | ✅ Yes | Meaning or translation |
|
|
62
|
+
| `data.repetitions` | `number` | ❌ No | Default: `0` |
|
|
63
|
+
| `data.interval` | `number` | ❌ No | Default: `0` (days) |
|
|
64
|
+
| `data.easeFactor` | `number` | ❌ No | Default: `2.5` (range 1.3–2.5) |
|
|
65
|
+
| `data.lastReviewed` | `string \| Date \| null` | ❌ No | Default: `null` (ISO string or Date object) |
|
|
66
|
+
|
|
67
|
+
**Returns:** `Word` — the newly created (or updated) word object.
|
|
68
|
+
|
|
69
|
+
**Example:**
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// Add a simple word
|
|
73
|
+
wb.word.add({
|
|
74
|
+
id: 'grok',
|
|
75
|
+
word: 'grok',
|
|
76
|
+
definition: 'to understand intuitively'
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Add a word with explicit SM‑2 state (e.g., when importing data)
|
|
80
|
+
wb.word.add({
|
|
81
|
+
id: 'serendipity',
|
|
82
|
+
word: 'serendipity',
|
|
83
|
+
definition: 'the occurrence of events by chance in a happy way',
|
|
84
|
+
repetitions: 3,
|
|
85
|
+
interval: 15,
|
|
86
|
+
easeFactor: 2.3,
|
|
87
|
+
lastReviewed: '2026-08-15T10:00:00.000Z'
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## `wb.word.remove(id)`
|
|
94
|
+
|
|
95
|
+
Permanently deletes a word from the bank by its ID.
|
|
96
|
+
|
|
97
|
+
**Parameters:**
|
|
98
|
+
|
|
99
|
+
| Parameter | Type | Required | Description |
|
|
100
|
+
| :--- | :--- | :--- | :--- |
|
|
101
|
+
| `id` | `string` | ✅ Yes | The unique ID of the word to remove |
|
|
102
|
+
|
|
103
|
+
**Returns:** `void`
|
|
104
|
+
|
|
105
|
+
**Example:**
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
wb.word.remove('grok');
|
|
109
|
+
// Now 'grok' is no longer in the bank
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## `wb.word.search(keyword)`
|
|
115
|
+
|
|
116
|
+
Searches for words whose **word** or **definition** contains the given keyword (case‑insensitive).
|
|
117
|
+
|
|
118
|
+
**Parameters:**
|
|
119
|
+
|
|
120
|
+
| Parameter | Type | Required | Description |
|
|
121
|
+
| :--- | :--- | :--- | :--- |
|
|
122
|
+
| `keyword` | `string` | ✅ Yes | The search term (case‑insensitive) |
|
|
123
|
+
|
|
124
|
+
**Returns:** `Word[]` — an array of matching words (empty if none found).
|
|
125
|
+
|
|
126
|
+
**Example:**
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
const results = wb.word.search('bene');
|
|
130
|
+
// Returns words like "benevolent", "beneficial", "benefit"
|
|
131
|
+
results.forEach(w => console.log(`${w.word}: ${w.definition}`));
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## `wb.word.top(n)`
|
|
137
|
+
|
|
138
|
+
Returns the top `n` words with the **highest repetition count** — i.e., the words you have reviewed most often.
|
|
139
|
+
|
|
140
|
+
**Parameters:**
|
|
141
|
+
|
|
142
|
+
| Parameter | Type | Required | Description |
|
|
143
|
+
| :--- | :--- | :--- | :--- |
|
|
144
|
+
| `n` | `number` | ✅ Yes | Number of top words to return |
|
|
145
|
+
|
|
146
|
+
**Returns:** `Word[]` — an array of the top `n` words (sorted descending by repetitions).
|
|
147
|
+
|
|
148
|
+
**Example:**
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
const mostPracticed = wb.word.top(10);
|
|
152
|
+
console.log('Your top 10 most practiced words:');
|
|
153
|
+
mostPracticed.forEach(w => console.log(`${w.word} (${w.repetitions} reviews)`));
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Data Type: `Word`
|
|
159
|
+
|
|
160
|
+
The `Word` object contains the following fields:
|
|
161
|
+
|
|
162
|
+
| Field | Type | Description |
|
|
163
|
+
| :--- | :--- | :--- |
|
|
164
|
+
| `id` | `string` | Unique identifier |
|
|
165
|
+
| `word` | `string` | The word itself |
|
|
166
|
+
| `definition` | `string` | Meaning or translation |
|
|
167
|
+
| `repetitions` | `number` | Number of successful reviews |
|
|
168
|
+
| `interval` | `number` | Current interval in days |
|
|
169
|
+
| `easeFactor` | `number` | Difficulty factor (1.3 – 2.5) |
|
|
170
|
+
| `lastReviewed` | `Date \| null` | Timestamp of the last review (Date object or null) |
|
|
171
|
+
| `isDue(today?: Date)` | `function` | Returns `true` if the word is due for review on the given date (default: today) |
|
|
172
|
+
| `toJSON()` | `function` | Returns a plain object suitable for serialization (e.g., to store in JSON) |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Summary of `wb.word` Methods
|
|
177
|
+
|
|
178
|
+
| Method | Description |
|
|
179
|
+
| :--- | :--- |
|
|
180
|
+
| `list()` | Get all words |
|
|
181
|
+
| `get(id)` | Get a word by ID |
|
|
182
|
+
| `add(data)` | Add or update a word |
|
|
183
|
+
| `remove(id)` | Delete a word |
|
|
184
|
+
| `search(keyword)` | Search words by word or definition |
|
|
185
|
+
| `top(n)` | Get the most frequently reviewed words |
|
|
186
|
+
|
|
187
|
+
For the review‑scheduling methods, see the [Review Scheduling API](/api/review).
|
|
188
|
+
|
|
189
|
+
---
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Designing wb.word API
|
|
2
|
+
|
|
3
|
+
The **API design** is the most important part of any library. A well-designed API makes developers want to use your library — and a bad one makes them run away.
|
|
4
|
+
|
|
5
|
+
## Design principles
|
|
6
|
+
|
|
7
|
+
1. **Intuitive**: Developers should guess how to use it without reading the docs.
|
|
8
|
+
2. **Chainable**: Group related methods under clear namespaces.
|
|
9
|
+
3. **Minimal**: Don't expose internal complexity.
|
|
10
|
+
|
|
11
|
+
## Why wb.word and wb.review?
|
|
12
|
+
|
|
13
|
+
I wanted developers to write code that reads like English:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
wb.word.add({ id: '1', word: 'apple', definition: 'a fruit' });
|
|
17
|
+
const due = wb.review.getDue();
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This is **self-documenting code** — you don't need comments to understand what it does.
|
|
21
|
+
|
|
22
|
+
## What I learned
|
|
23
|
+
|
|
24
|
+
- **Simplicity wins**: Remove unnecessary options and configurations.
|
|
25
|
+
- **Document everything**: Even the most intuitive API needs examples.
|
|
26
|
+
- **Listen to users**: The first user feedback I got helped me improve the design.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
*Written on September 1, 2026*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Blog
|
|
2
|
+
|
|
3
|
+
Welcome to the wb-sdk blog! Here I share my thoughts, learnings, and updates about the project.
|
|
4
|
+
|
|
5
|
+
## Latest Posts
|
|
6
|
+
|
|
7
|
+
- [Why SM-2 Algorithm](./why-sm2) — Understanding the science behind spaced repetition
|
|
8
|
+
- [Designing wb.word API](./designing-api) — How I designed the word management interface
|
|
9
|
+
- [How I Published to npm](./publishing-to-npm) — The journey from local code to global package
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## All Posts
|
|
14
|
+
|
|
15
|
+
| Date | Title | Description |
|
|
16
|
+
| :--- | :--- | :--- |
|
|
17
|
+
| 2026-09-01 | [Why SM-2 Algorithm](./why-sm2) | Why I chose SM-2 over other algorithms |
|
|
18
|
+
| 2026-09-01 | [Designing wb.word API](./designing-api) | The design principles behind the API |
|
|
19
|
+
| 2026-08-31 | [How I Published to npm](./publishing-to-npm) | A step-by-step guide to npm publishing |
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# How I Published to npm
|
|
2
|
+
|
|
3
|
+
Publishing my first npm package was harder than writing the code itself.
|
|
4
|
+
|
|
5
|
+
## The challenges
|
|
6
|
+
|
|
7
|
+
1. **2FA setup**: npm requires two-factor authentication, and I had to generate tokens properly.
|
|
8
|
+
2. **Scoped package name**: wb-sdk was too similar to ws-sdk, so I had to use @zephyr424/wb-sdk.
|
|
9
|
+
3. **GitHub integration**: Configuring the repository link and GitHub Pages deployment.
|
|
10
|
+
|
|
11
|
+
## Step-by-step guide
|
|
12
|
+
|
|
13
|
+
\\\ash
|
|
14
|
+
# 1. Login to npm
|
|
15
|
+
npm login
|
|
16
|
+
|
|
17
|
+
# 2. Build and test locally
|
|
18
|
+
npm run test
|
|
19
|
+
|
|
20
|
+
# 3. Bump version
|
|
21
|
+
npm version patch
|
|
22
|
+
|
|
23
|
+
# 4. Publish to npm
|
|
24
|
+
npm publish --access public
|
|
25
|
+
\\\
|
|
26
|
+
|
|
27
|
+
## Lessons learned
|
|
28
|
+
|
|
29
|
+
- **Read the error messages**: npm tells you exactly what's wrong.
|
|
30
|
+
- **Test before publishing**: Always test with
|
|
31
|
+
pm link first.
|
|
32
|
+
- **Use a .npmignore file**: Control which files get published.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
*Written on August 31, 2026*
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Why SM-2 Algorithm
|
|
2
|
+
|
|
3
|
+
The **SM-2** algorithm, developed by Piotr Woźniak in the 1980s, is the foundation of **spaced repetition** — a technique that optimizes memory retention by scheduling reviews at increasing intervals.
|
|
4
|
+
|
|
5
|
+
## Why I chose SM-2
|
|
6
|
+
|
|
7
|
+
1. **Proven track record**: SM-2 is the algorithm behind Anki, the most popular flashcard app.
|
|
8
|
+
2. **Simple implementation**: The algorithm is elegant and easy to code.
|
|
9
|
+
3. **Highly effective**: Research shows spaced repetition can boost retention by over 200%.
|
|
10
|
+
|
|
11
|
+
## How it works
|
|
12
|
+
|
|
13
|
+
When you rate your recall quality from 0 to 5:
|
|
14
|
+
|
|
15
|
+
- **Quality < 3**: You forgot the word → reset interval to 1 day.
|
|
16
|
+
- **Quality ≥ 3**: You remembered it → increase the interval and adjust the ease factor.
|
|
17
|
+
|
|
18
|
+
This dynamic adjustment ensures you spend time on words you're about to forget.
|
|
19
|
+
|
|
20
|
+
## Future plans
|
|
21
|
+
|
|
22
|
+
I'm planning to add **FSRS** support in a future version — a more advanced algorithm that uses machine learning to optimize intervals.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
*Written on September 1, 2026*
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Contributors
|
|
2
|
+
|
|
3
|
+
Thank you to everyone who has contributed to \wb-sdk\!
|
|
4
|
+
|
|
5
|
+
## Core Contributors
|
|
6
|
+
|
|
7
|
+
- [@Zephyr424](https://github.com/Zephyr424) — Creator and maintainer
|
|
8
|
+
|
|
9
|
+
## How to Contribute
|
|
10
|
+
|
|
11
|
+
Want to join this list? Check out the [GitHub repository](https://github.com/Zephyr424/wb-sdk) and submit a pull request!
|
|
12
|
+
|
|
13
|
+
- 🐛 Found a bug? Open an issue.
|
|
14
|
+
- 💡 Have an idea? Start a discussion.
|
|
15
|
+
- 📝 Want to improve docs? Send a PR.
|
|
16
|
+
- 🧪 Want to add a feature? Fork and contribute!
|