fatigue-kit 0.0.0-stage → 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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +159 -2
  3. package/README.zh-CN.md +160 -0
  4. package/dist/adapters/alipay.cjs +52 -0
  5. package/dist/adapters/alipay.cjs.map +1 -0
  6. package/dist/adapters/alipay.d.cts +27 -0
  7. package/dist/adapters/alipay.d.ts +27 -0
  8. package/dist/adapters/alipay.js +52 -0
  9. package/dist/adapters/alipay.js.map +1 -0
  10. package/dist/adapters/async-storage.cjs +93 -0
  11. package/dist/adapters/async-storage.cjs.map +1 -0
  12. package/dist/adapters/async-storage.d.cts +48 -0
  13. package/dist/adapters/async-storage.d.ts +48 -0
  14. package/dist/adapters/async-storage.js +93 -0
  15. package/dist/adapters/async-storage.js.map +1 -0
  16. package/dist/adapters/local-storage.cjs +24 -0
  17. package/dist/adapters/local-storage.cjs.map +1 -0
  18. package/dist/adapters/local-storage.d.cts +14 -0
  19. package/dist/adapters/local-storage.d.ts +14 -0
  20. package/dist/adapters/local-storage.js +24 -0
  21. package/dist/adapters/local-storage.js.map +1 -0
  22. package/dist/adapters/memory.cjs +7 -0
  23. package/dist/adapters/memory.cjs.map +1 -0
  24. package/dist/adapters/memory.d.cts +14 -0
  25. package/dist/adapters/memory.d.ts +14 -0
  26. package/dist/adapters/memory.js +7 -0
  27. package/dist/adapters/memory.js.map +1 -0
  28. package/dist/adapters/node-file.cjs +53 -0
  29. package/dist/adapters/node-file.cjs.map +1 -0
  30. package/dist/adapters/node-file.d.cts +15 -0
  31. package/dist/adapters/node-file.d.ts +15 -0
  32. package/dist/adapters/node-file.js +53 -0
  33. package/dist/adapters/node-file.js.map +1 -0
  34. package/dist/adapters/session-storage.cjs +24 -0
  35. package/dist/adapters/session-storage.cjs.map +1 -0
  36. package/dist/adapters/session-storage.d.cts +14 -0
  37. package/dist/adapters/session-storage.d.ts +14 -0
  38. package/dist/adapters/session-storage.js +24 -0
  39. package/dist/adapters/session-storage.js.map +1 -0
  40. package/dist/adapters/weapp.cjs +51 -0
  41. package/dist/adapters/weapp.cjs.map +1 -0
  42. package/dist/adapters/weapp.d.cts +23 -0
  43. package/dist/adapters/weapp.d.ts +23 -0
  44. package/dist/adapters/weapp.js +51 -0
  45. package/dist/adapters/weapp.js.map +1 -0
  46. package/dist/chunk-DABM2TVR.cjs +58 -0
  47. package/dist/chunk-DABM2TVR.cjs.map +1 -0
  48. package/dist/chunk-DM2CAKGU.js +23 -0
  49. package/dist/chunk-DM2CAKGU.js.map +1 -0
  50. package/dist/chunk-GMM2BYRQ.js +58 -0
  51. package/dist/chunk-GMM2BYRQ.js.map +1 -0
  52. package/dist/chunk-K7E4LWUL.cjs +43 -0
  53. package/dist/chunk-K7E4LWUL.cjs.map +1 -0
  54. package/dist/chunk-NBDAXDB6.cjs +23 -0
  55. package/dist/chunk-NBDAXDB6.cjs.map +1 -0
  56. package/dist/chunk-ZNIZLIUO.js +43 -0
  57. package/dist/chunk-ZNIZLIUO.js.map +1 -0
  58. package/dist/global/index.global.js +2 -0
  59. package/dist/global/index.global.js.map +1 -0
  60. package/dist/index.cjs +334 -0
  61. package/dist/index.cjs.map +1 -0
  62. package/dist/index.d.cts +17 -0
  63. package/dist/index.d.ts +17 -0
  64. package/dist/index.js +334 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/legacy.cjs +45 -0
  67. package/dist/legacy.cjs.map +1 -0
  68. package/dist/legacy.d.cts +40 -0
  69. package/dist/legacy.d.ts +40 -0
  70. package/dist/legacy.js +45 -0
  71. package/dist/legacy.js.map +1 -0
  72. package/dist/types-hDxN5bc3.d.cts +89 -0
  73. package/dist/types-hDxN5bc3.d.ts +89 -0
  74. package/dist/web-GiaS0cnX.d.cts +8 -0
  75. package/dist/web-GiaS0cnX.d.ts +8 -0
  76. package/package.json +132 -4
@@ -0,0 +1,89 @@
1
+ /** Injectable clock so tests can freeze or accelerate time. */
2
+ interface Clock {
3
+ now(): number;
4
+ }
5
+ /**
6
+ * Duration: a millisecond number, or a string like `'45s'`, `'30m'`, `'12h'`, `'7d'`.
7
+ */
8
+ type Duration = number | string;
9
+ /** At most `max` occurrences within a sliding window. */
10
+ interface SlidingWindowRule {
11
+ max: number;
12
+ window: Duration;
13
+ }
14
+ /** At most `max` occurrences per calendar period, evaluated in device local time. */
15
+ interface CalendarRule {
16
+ max: number;
17
+ every: 'day' | 'week' | 'month' | 'year';
18
+ /** Period boundary offset in local time, `'HH:mm'`. Default `'00:00'`. */
19
+ cutoff?: string;
20
+ /** First weekday: `0` = Sunday … `6` = Saturday. Default `1` (Monday). */
21
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
22
+ }
23
+ /** Two occurrences must be at least `cooldown` apart. */
24
+ interface CooldownRule {
25
+ cooldown: Duration;
26
+ }
27
+ /** At most `max` occurrences, ever. */
28
+ interface LifetimeRule {
29
+ max: number;
30
+ }
31
+ type FatigueRule = SlidingWindowRule | CalendarRule | CooldownRule | LifetimeRule;
32
+ interface ConsumeResult {
33
+ allowed: boolean;
34
+ /**
35
+ * How many more times the key may be consumed under the strictest count-based
36
+ * rule. `Infinity` when no count-based rule applies (e.g. a cooldown-only key).
37
+ */
38
+ remaining: number;
39
+ /** Earliest timestamp (ms) at which the key may be consumed again. Absent while allowed. */
40
+ nextAvailableAt?: number;
41
+ /** The first rule that caused the denial. */
42
+ deniedBy?: FatigueRule;
43
+ }
44
+ /**
45
+ * A synchronous string key-value store. Every built-in adapter implements this,
46
+ * and so can yours — this is the only contract `createFatigue` relies on.
47
+ */
48
+ interface SyncStorage {
49
+ get(key: string): string | null | undefined;
50
+ set(key: string, value: string): void;
51
+ remove(key: string): void;
52
+ /**
53
+ * Optional: list all keys known to this storage.
54
+ * Enables `fatigue.reset()` without a key.
55
+ */
56
+ keys?(): string[];
57
+ }
58
+ /** Serialized fatigue record. `hits` are ascending timestamps in ms. */
59
+ interface FatigueRecord {
60
+ /** Record format version. */
61
+ v: number;
62
+ hits: number[];
63
+ /** Total consumption count, ever. Survives pruning. */
64
+ lifetime: number;
65
+ }
66
+ interface FatigueOptions {
67
+ /** Backing storage. Defaults to an in-memory store. */
68
+ storage?: SyncStorage;
69
+ /** Clock. Defaults to the real system time. */
70
+ clock?: Clock;
71
+ /** Prefix for storage keys. Default `'fatigue-kit'`. */
72
+ namespace?: string;
73
+ /** Maximum hits kept per record; older ones are pruned on write. Default `100`. */
74
+ maxHits?: number;
75
+ }
76
+ interface Fatigue {
77
+ /** Atomically check the rules and, when allowed, consume one occurrence. */
78
+ tryConsume(key: string, rules: FatigueRule | FatigueRule[]): ConsumeResult;
79
+ /** Check the rules without consuming. */
80
+ peek(key: string, rules: FatigueRule | FatigueRule[]): ConsumeResult;
81
+ /** Drop one key, or every key when omitted (requires `storage.keys`). */
82
+ reset(key?: string): void;
83
+ /** Read the raw record of a key. `null` when absent. */
84
+ exportRecord(key: string): FatigueRecord | null;
85
+ /** Overwrite the record of a key (used for migrations and debugging). */
86
+ importRecord(key: string, record: Partial<FatigueRecord>): void;
87
+ }
88
+
89
+ export type { CalendarRule as C, Duration as D, FatigueOptions as F, LifetimeRule as L, SyncStorage as S, Fatigue as a, Clock as b, ConsumeResult as c, CooldownRule as d, FatigueRecord as e, FatigueRule as f, SlidingWindowRule as g };
@@ -0,0 +1,8 @@
1
+ interface WebStorageAdapterOptions {
2
+ /** Underlying `Storage`. Defaults to the platform global, resolved lazily. */
3
+ storage?: Storage;
4
+ /** Called when the underlying storage throws (quota, private mode, …). */
5
+ onError?: (error: unknown) => void;
6
+ }
7
+
8
+ export type { WebStorageAdapterOptions as W };
@@ -0,0 +1,8 @@
1
+ interface WebStorageAdapterOptions {
2
+ /** Underlying `Storage`. Defaults to the platform global, resolved lazily. */
3
+ storage?: Storage;
4
+ /** Called when the underlying storage throws (quota, private mode, …). */
5
+ onError?: (error: unknown) => void;
6
+ }
7
+
8
+ export type { WebStorageAdapterOptions as W };
package/package.json CHANGED
@@ -1,6 +1,134 @@
1
1
  {
2
2
  "name": "fatigue-kit",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Zero-dependency frequency capping (疲劳度控制) for popups, toasts and guides — one composable API across Web, mini-programs, React Native and Node.js.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "sideEffects": false,
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "main": "./dist/index.cjs",
12
+ "module": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "unpkg": "./dist/global/index.global.js",
15
+ "jsdelivr": "./dist/global/index.global.js",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "require": "./dist/index.cjs"
21
+ },
22
+ "./legacy": {
23
+ "types": "./dist/legacy.d.ts",
24
+ "import": "./dist/legacy.js",
25
+ "require": "./dist/legacy.cjs"
26
+ },
27
+ "./adapters/memory": {
28
+ "types": "./dist/adapters/memory.d.ts",
29
+ "import": "./dist/adapters/memory.js",
30
+ "require": "./dist/adapters/memory.cjs"
31
+ },
32
+ "./adapters/local-storage": {
33
+ "types": "./dist/adapters/local-storage.d.ts",
34
+ "import": "./dist/adapters/local-storage.js",
35
+ "require": "./dist/adapters/local-storage.cjs"
36
+ },
37
+ "./adapters/session-storage": {
38
+ "types": "./dist/adapters/session-storage.d.ts",
39
+ "import": "./dist/adapters/session-storage.js",
40
+ "require": "./dist/adapters/session-storage.cjs"
41
+ },
42
+ "./adapters/async-storage": {
43
+ "types": "./dist/adapters/async-storage.d.ts",
44
+ "import": "./dist/adapters/async-storage.js",
45
+ "require": "./dist/adapters/async-storage.cjs"
46
+ },
47
+ "./adapters/weapp": {
48
+ "types": "./dist/adapters/weapp.d.ts",
49
+ "import": "./dist/adapters/weapp.js",
50
+ "require": "./dist/adapters/weapp.cjs"
51
+ },
52
+ "./adapters/alipay": {
53
+ "types": "./dist/adapters/alipay.d.ts",
54
+ "import": "./dist/adapters/alipay.js",
55
+ "require": "./dist/adapters/alipay.cjs"
56
+ },
57
+ "./adapters/node-file": {
58
+ "types": "./dist/adapters/node-file.d.ts",
59
+ "import": "./dist/adapters/node-file.js",
60
+ "require": "./dist/adapters/node-file.cjs"
61
+ },
62
+ "./global": "./dist/global/index.global.js",
63
+ "./package.json": "./package.json"
64
+ },
65
+ "files": [
66
+ "dist"
67
+ ],
68
+ "engines": {
69
+ "node": ">=18"
70
+ },
71
+ "scripts": {
72
+ "build": "tsup",
73
+ "test": "vitest run",
74
+ "test:watch": "vitest",
75
+ "typecheck": "tsc --noEmit",
76
+ "lint": "biome check src test",
77
+ "format": "biome check --write src test",
78
+ "size": "size-limit",
79
+ "changeset": "changeset",
80
+ "prepublishOnly": "npm run build"
81
+ },
82
+ "size-limit": [
83
+ {
84
+ "name": "core",
85
+ "path": "dist/index.js",
86
+ "import": "{ createFatigue }",
87
+ "limit": "3.5 kB"
88
+ },
89
+ {
90
+ "name": "web adapter",
91
+ "path": "dist/adapters/local-storage.js",
92
+ "import": "{ localStorageAdapter }",
93
+ "limit": "4 kB"
94
+ },
95
+ {
96
+ "name": "weapp adapter",
97
+ "path": "dist/adapters/weapp.js",
98
+ "import": "{ weappAdapter }",
99
+ "limit": "4 kB"
100
+ }
101
+ ],
102
+ "keywords": [
103
+ "frequency-capping",
104
+ "fatigue",
105
+ "疲劳度",
106
+ "popup",
107
+ "toast",
108
+ "rate-limit",
109
+ "cooldown",
110
+ "mini-program",
111
+ "weapp",
112
+ "react-native",
113
+ "storage"
114
+ ],
115
+ "repository": {
116
+ "type": "git",
117
+ "url": "git+https://github.com/SoraYama/fatigue-kit.git"
118
+ },
119
+ "bugs": {
120
+ "url": "https://github.com/SoraYama/fatigue-kit/issues"
121
+ },
122
+ "homepage": "https://github.com/SoraYama/fatigue-kit#readme",
123
+ "devDependencies": {
124
+ "@biomejs/biome": "^2.0.0",
125
+ "@changesets/changelog-github": "^1.0.1",
126
+ "@changesets/cli": "^2.29.0",
127
+ "@size-limit/preset-small-lib": "^11.2.0",
128
+ "@types/node": "26.6.5",
129
+ "size-limit": "^11.2.0",
130
+ "tsup": "^8.5.0",
131
+ "typescript": "^5.9.0",
132
+ "vitest": "^3.2.0"
133
+ }
134
+ }