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.
- package/LICENSE +21 -0
- package/README.md +159 -2
- package/README.zh-CN.md +160 -0
- package/dist/adapters/alipay.cjs +52 -0
- package/dist/adapters/alipay.cjs.map +1 -0
- package/dist/adapters/alipay.d.cts +27 -0
- package/dist/adapters/alipay.d.ts +27 -0
- package/dist/adapters/alipay.js +52 -0
- package/dist/adapters/alipay.js.map +1 -0
- package/dist/adapters/async-storage.cjs +93 -0
- package/dist/adapters/async-storage.cjs.map +1 -0
- package/dist/adapters/async-storage.d.cts +48 -0
- package/dist/adapters/async-storage.d.ts +48 -0
- package/dist/adapters/async-storage.js +93 -0
- package/dist/adapters/async-storage.js.map +1 -0
- package/dist/adapters/local-storage.cjs +24 -0
- package/dist/adapters/local-storage.cjs.map +1 -0
- package/dist/adapters/local-storage.d.cts +14 -0
- package/dist/adapters/local-storage.d.ts +14 -0
- package/dist/adapters/local-storage.js +24 -0
- package/dist/adapters/local-storage.js.map +1 -0
- package/dist/adapters/memory.cjs +7 -0
- package/dist/adapters/memory.cjs.map +1 -0
- package/dist/adapters/memory.d.cts +14 -0
- package/dist/adapters/memory.d.ts +14 -0
- package/dist/adapters/memory.js +7 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/node-file.cjs +53 -0
- package/dist/adapters/node-file.cjs.map +1 -0
- package/dist/adapters/node-file.d.cts +15 -0
- package/dist/adapters/node-file.d.ts +15 -0
- package/dist/adapters/node-file.js +53 -0
- package/dist/adapters/node-file.js.map +1 -0
- package/dist/adapters/session-storage.cjs +24 -0
- package/dist/adapters/session-storage.cjs.map +1 -0
- package/dist/adapters/session-storage.d.cts +14 -0
- package/dist/adapters/session-storage.d.ts +14 -0
- package/dist/adapters/session-storage.js +24 -0
- package/dist/adapters/session-storage.js.map +1 -0
- package/dist/adapters/weapp.cjs +51 -0
- package/dist/adapters/weapp.cjs.map +1 -0
- package/dist/adapters/weapp.d.cts +23 -0
- package/dist/adapters/weapp.d.ts +23 -0
- package/dist/adapters/weapp.js +51 -0
- package/dist/adapters/weapp.js.map +1 -0
- package/dist/chunk-DABM2TVR.cjs +58 -0
- package/dist/chunk-DABM2TVR.cjs.map +1 -0
- package/dist/chunk-DM2CAKGU.js +23 -0
- package/dist/chunk-DM2CAKGU.js.map +1 -0
- package/dist/chunk-GMM2BYRQ.js +58 -0
- package/dist/chunk-GMM2BYRQ.js.map +1 -0
- package/dist/chunk-K7E4LWUL.cjs +43 -0
- package/dist/chunk-K7E4LWUL.cjs.map +1 -0
- package/dist/chunk-NBDAXDB6.cjs +23 -0
- package/dist/chunk-NBDAXDB6.cjs.map +1 -0
- package/dist/chunk-ZNIZLIUO.js +43 -0
- package/dist/chunk-ZNIZLIUO.js.map +1 -0
- package/dist/global/index.global.js +2 -0
- package/dist/global/index.global.js.map +1 -0
- package/dist/index.cjs +334 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +334 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy.cjs +45 -0
- package/dist/legacy.cjs.map +1 -0
- package/dist/legacy.d.cts +40 -0
- package/dist/legacy.d.ts +40 -0
- package/dist/legacy.js +45 -0
- package/dist/legacy.js.map +1 -0
- package/dist/types-hDxN5bc3.d.cts +89 -0
- package/dist/types-hDxN5bc3.d.ts +89 -0
- package/dist/web-GiaS0cnX.d.cts +8 -0
- package/dist/web-GiaS0cnX.d.ts +8 -0
- package/package.json +132 -4
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/adapters/weapp.ts
|
|
2
|
+
function weappAdapter(options = {}) {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
const client = (_a = options.client) != null ? _a : typeof wx !== "undefined" && wx !== null ? wx : void 0;
|
|
5
|
+
if (client === void 0) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
"[fatigue-kit] weappAdapter: no `wx` global found. Pass `{ client }` explicitly when not running inside WeChat."
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
const onError = (_b = options.onError) != null ? _b : ((error) => {
|
|
11
|
+
console.warn("[fatigue-kit] weapp storage operation failed:", error);
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
get(key) {
|
|
15
|
+
try {
|
|
16
|
+
const value = client.getStorageSync(key);
|
|
17
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
onError(error);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
set(key, value) {
|
|
24
|
+
try {
|
|
25
|
+
client.setStorageSync(key, value);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
onError(error);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
remove(key) {
|
|
31
|
+
try {
|
|
32
|
+
client.removeStorageSync(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
onError(error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
keys() {
|
|
38
|
+
var _a2, _b2;
|
|
39
|
+
try {
|
|
40
|
+
return (_b2 = (_a2 = client.getStorageInfoSync) == null ? void 0 : _a2.call(client).keys) != null ? _b2 : [];
|
|
41
|
+
} catch (error) {
|
|
42
|
+
onError(error);
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
exports.weappAdapter = weappAdapter;
|
|
51
|
+
//# sourceMappingURL=weapp.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fatigue-kit/fatigue-kit/dist/adapters/weapp.cjs","../../src/adapters/weapp.ts"],"names":["_a","_b"],"mappings":"AAAA;ACsBO,SAAS,YAAA,CAAa,QAAA,EAA+B,CAAC,CAAA,EAAgB;AAtB7E,EAAA,IAAA,EAAA,EAAA,EAAA;AAuBC,EAAA,MAAM,OAAA,EAAA,CAAS,GAAA,EAAA,OAAA,CAAQ,MAAA,EAAA,GAAR,KAAA,EAAA,GAAA,EAAmB,OAAO,GAAA,IAAO,YAAA,GAAe,GAAA,IAAO,KAAA,EAAO,GAAA,EAAK,KAAA,CAAA;AAClF,EAAA,GAAA,CAAI,OAAA,IAAW,KAAA,CAAA,EAAW;AACzB,IAAA,MAAM,IAAI,KAAA;AAAA,MACT;AAAA,IACD,CAAA;AAAA,EACD;AACA,EAAA,MAAM,QAAA,EAAA,CACL,GAAA,EAAA,OAAA,CAAQ,OAAA,EAAA,GAAR,KAAA,EAAA,GAAA,EAAA,CACC,CAAC,KAAA,EAAA,GAAmB;AACpB,IAAA,OAAA,CAAQ,IAAA,CAAK,+CAAA,EAAiD,KAAK,CAAA;AAAA,EACpE,CAAA,CAAA;AACD,EAAA,OAAO;AAAA,IACN,GAAA,CAAI,GAAA,EAAK;AACR,MAAA,IAAI;AACH,QAAA,MAAM,MAAA,EAAQ,MAAA,CAAO,cAAA,CAAe,GAAG,CAAA;AACvC,QAAA,OAAO,OAAO,MAAA,IAAU,SAAA,GAAY,KAAA,CAAM,OAAA,EAAS,EAAA,EAAI,MAAA,EAAQ,IAAA;AAAA,MAChE,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AACb,QAAA,OAAO,IAAA;AAAA,MACR;AAAA,IACD,CAAA;AAAA,IACA,GAAA,CAAI,GAAA,EAAK,KAAA,EAAO;AACf,MAAA,IAAI;AACH,QAAA,MAAA,CAAO,cAAA,CAAe,GAAA,EAAK,KAAK,CAAA;AAAA,MACjC,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACd;AAAA,IACD,CAAA;AAAA,IACA,MAAA,CAAO,GAAA,EAAK;AACX,MAAA,IAAI;AACH,QAAA,MAAA,CAAO,iBAAA,CAAkB,GAAG,CAAA;AAAA,MAC7B,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACd;AAAA,IACD,CAAA;AAAA,IACA,IAAA,CAAA,EAAO;AA1DT,MAAA,IAAAA,GAAAA,EAAAC,GAAAA;AA2DG,MAAA,IAAI;AACH,QAAA,OAAA,CAAOA,IAAAA,EAAAA,CAAAD,IAAAA,EAAA,MAAA,CAAO,kBAAA,EAAA,GAAP,KAAA,EAAA,KAAA,EAAA,EAAAA,GAAAA,CAAA,IAAA,CAAA,MAAA,CAAA,CAA8B,IAAA,EAAA,GAA9B,KAAA,EAAAC,IAAAA,EAAsC,CAAC,CAAA;AAAA,MAC/C,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AACb,QAAA,OAAO,CAAC,CAAA;AAAA,MACT;AAAA,IACD;AAAA,EACD,CAAA;AACD;ADpBA;AACE;AACF,oCAAC","file":"/home/runner/work/fatigue-kit/fatigue-kit/dist/adapters/weapp.cjs","sourcesContent":[null,"import type { SyncStorage } from '../types'\n\n/** WeChat mini-program storage API (positional arguments). */\nexport interface WeappStorageLike {\n\tgetStorageSync(key: string): unknown\n\tsetStorageSync(key: string, value: string): void\n\tremoveStorageSync(key: string): void\n\tgetStorageInfoSync?(): { keys?: string[] }\n}\n\nexport interface WeappAdapterOptions {\n\t/** Defaults to the `wx` global; inject explicitly in tests or abstractions. */\n\tclient?: WeappStorageLike\n\tonError?: (error: unknown) => void\n}\n\ndeclare const wx: WeappStorageLike | undefined\n\n/**\n * WeChat mini-program adapter backed by `wx.getStorageSync` & friends.\n * Synchronous native API, so it plugs straight into the sync core.\n */\nexport function weappAdapter(options: WeappAdapterOptions = {}): SyncStorage {\n\tconst client = options.client ?? (typeof wx !== 'undefined' && wx !== null ? wx : undefined)\n\tif (client === undefined) {\n\t\tthrow new Error(\n\t\t\t'[fatigue-kit] weappAdapter: no `wx` global found. Pass `{ client }` explicitly when not running inside WeChat.',\n\t\t)\n\t}\n\tconst onError =\n\t\toptions.onError ??\n\t\t((error: unknown) => {\n\t\t\tconsole.warn('[fatigue-kit] weapp storage operation failed:', error)\n\t\t})\n\treturn {\n\t\tget(key) {\n\t\t\ttry {\n\t\t\t\tconst value = client.getStorageSync(key)\n\t\t\t\treturn typeof value === 'string' && value.length > 0 ? value : null\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\tset(key, value) {\n\t\t\ttry {\n\t\t\t\tclient.setStorageSync(key, value)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tremove(key) {\n\t\t\ttry {\n\t\t\t\tclient.removeStorageSync(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tkeys() {\n\t\t\ttry {\n\t\t\t\treturn client.getStorageInfoSync?.().keys ?? []\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn []\n\t\t\t}\n\t\t},\n\t}\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { S as SyncStorage } from '../types-hDxN5bc3.cjs';
|
|
2
|
+
|
|
3
|
+
/** WeChat mini-program storage API (positional arguments). */
|
|
4
|
+
interface WeappStorageLike {
|
|
5
|
+
getStorageSync(key: string): unknown;
|
|
6
|
+
setStorageSync(key: string, value: string): void;
|
|
7
|
+
removeStorageSync(key: string): void;
|
|
8
|
+
getStorageInfoSync?(): {
|
|
9
|
+
keys?: string[];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
interface WeappAdapterOptions {
|
|
13
|
+
/** Defaults to the `wx` global; inject explicitly in tests or abstractions. */
|
|
14
|
+
client?: WeappStorageLike;
|
|
15
|
+
onError?: (error: unknown) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* WeChat mini-program adapter backed by `wx.getStorageSync` & friends.
|
|
19
|
+
* Synchronous native API, so it plugs straight into the sync core.
|
|
20
|
+
*/
|
|
21
|
+
declare function weappAdapter(options?: WeappAdapterOptions): SyncStorage;
|
|
22
|
+
|
|
23
|
+
export { type WeappAdapterOptions, type WeappStorageLike, weappAdapter };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { S as SyncStorage } from '../types-hDxN5bc3.js';
|
|
2
|
+
|
|
3
|
+
/** WeChat mini-program storage API (positional arguments). */
|
|
4
|
+
interface WeappStorageLike {
|
|
5
|
+
getStorageSync(key: string): unknown;
|
|
6
|
+
setStorageSync(key: string, value: string): void;
|
|
7
|
+
removeStorageSync(key: string): void;
|
|
8
|
+
getStorageInfoSync?(): {
|
|
9
|
+
keys?: string[];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
interface WeappAdapterOptions {
|
|
13
|
+
/** Defaults to the `wx` global; inject explicitly in tests or abstractions. */
|
|
14
|
+
client?: WeappStorageLike;
|
|
15
|
+
onError?: (error: unknown) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* WeChat mini-program adapter backed by `wx.getStorageSync` & friends.
|
|
19
|
+
* Synchronous native API, so it plugs straight into the sync core.
|
|
20
|
+
*/
|
|
21
|
+
declare function weappAdapter(options?: WeappAdapterOptions): SyncStorage;
|
|
22
|
+
|
|
23
|
+
export { type WeappAdapterOptions, type WeappStorageLike, weappAdapter };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/adapters/weapp.ts
|
|
2
|
+
function weappAdapter(options = {}) {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
const client = (_a = options.client) != null ? _a : typeof wx !== "undefined" && wx !== null ? wx : void 0;
|
|
5
|
+
if (client === void 0) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
"[fatigue-kit] weappAdapter: no `wx` global found. Pass `{ client }` explicitly when not running inside WeChat."
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
const onError = (_b = options.onError) != null ? _b : ((error) => {
|
|
11
|
+
console.warn("[fatigue-kit] weapp storage operation failed:", error);
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
get(key) {
|
|
15
|
+
try {
|
|
16
|
+
const value = client.getStorageSync(key);
|
|
17
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
onError(error);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
set(key, value) {
|
|
24
|
+
try {
|
|
25
|
+
client.setStorageSync(key, value);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
onError(error);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
remove(key) {
|
|
31
|
+
try {
|
|
32
|
+
client.removeStorageSync(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
onError(error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
keys() {
|
|
38
|
+
var _a2, _b2;
|
|
39
|
+
try {
|
|
40
|
+
return (_b2 = (_a2 = client.getStorageInfoSync) == null ? void 0 : _a2.call(client).keys) != null ? _b2 : [];
|
|
41
|
+
} catch (error) {
|
|
42
|
+
onError(error);
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
weappAdapter
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=weapp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/weapp.ts"],"sourcesContent":["import type { SyncStorage } from '../types'\n\n/** WeChat mini-program storage API (positional arguments). */\nexport interface WeappStorageLike {\n\tgetStorageSync(key: string): unknown\n\tsetStorageSync(key: string, value: string): void\n\tremoveStorageSync(key: string): void\n\tgetStorageInfoSync?(): { keys?: string[] }\n}\n\nexport interface WeappAdapterOptions {\n\t/** Defaults to the `wx` global; inject explicitly in tests or abstractions. */\n\tclient?: WeappStorageLike\n\tonError?: (error: unknown) => void\n}\n\ndeclare const wx: WeappStorageLike | undefined\n\n/**\n * WeChat mini-program adapter backed by `wx.getStorageSync` & friends.\n * Synchronous native API, so it plugs straight into the sync core.\n */\nexport function weappAdapter(options: WeappAdapterOptions = {}): SyncStorage {\n\tconst client = options.client ?? (typeof wx !== 'undefined' && wx !== null ? wx : undefined)\n\tif (client === undefined) {\n\t\tthrow new Error(\n\t\t\t'[fatigue-kit] weappAdapter: no `wx` global found. Pass `{ client }` explicitly when not running inside WeChat.',\n\t\t)\n\t}\n\tconst onError =\n\t\toptions.onError ??\n\t\t((error: unknown) => {\n\t\t\tconsole.warn('[fatigue-kit] weapp storage operation failed:', error)\n\t\t})\n\treturn {\n\t\tget(key) {\n\t\t\ttry {\n\t\t\t\tconst value = client.getStorageSync(key)\n\t\t\t\treturn typeof value === 'string' && value.length > 0 ? value : null\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\tset(key, value) {\n\t\t\ttry {\n\t\t\t\tclient.setStorageSync(key, value)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tremove(key) {\n\t\t\ttry {\n\t\t\t\tclient.removeStorageSync(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tkeys() {\n\t\t\ttry {\n\t\t\t\treturn client.getStorageInfoSync?.().keys ?? []\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn []\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":";AAsBO,SAAS,aAAa,UAA+B,CAAC,GAAgB;AAtB7E;AAuBC,QAAM,UAAS,aAAQ,WAAR,YAAmB,OAAO,OAAO,eAAe,OAAO,OAAO,KAAK;AAClF,MAAI,WAAW,QAAW;AACzB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACA,QAAM,WACL,aAAQ,YAAR,aACC,CAAC,UAAmB;AACpB,YAAQ,KAAK,iDAAiD,KAAK;AAAA,EACpE;AACD,SAAO;AAAA,IACN,IAAI,KAAK;AACR,UAAI;AACH,cAAM,QAAQ,OAAO,eAAe,GAAG;AACvC,eAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AAAA,MAChE,SAAS,OAAO;AACf,gBAAQ,KAAK;AACb,eAAO;AAAA,MACR;AAAA,IACD;AAAA,IACA,IAAI,KAAK,OAAO;AACf,UAAI;AACH,eAAO,eAAe,KAAK,KAAK;AAAA,MACjC,SAAS,OAAO;AACf,gBAAQ,KAAK;AAAA,MACd;AAAA,IACD;AAAA,IACA,OAAO,KAAK;AACX,UAAI;AACH,eAAO,kBAAkB,GAAG;AAAA,MAC7B,SAAS,OAAO;AACf,gBAAQ,KAAK;AAAA,MACd;AAAA,IACD;AAAA,IACA,OAAO;AA1DT,UAAAA,KAAAC;AA2DG,UAAI;AACH,gBAAOA,OAAAD,MAAA,OAAO,uBAAP,gBAAAA,IAAA,aAA8B,SAA9B,OAAAC,MAAsC,CAAC;AAAA,MAC/C,SAAS,OAAO;AACf,gBAAQ,KAAK;AACb,eAAO,CAAC;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;","names":["_a","_b"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/adapters/web.ts
|
|
2
|
+
function defaultOnError(error) {
|
|
3
|
+
console.warn("[fatigue-kit] storage operation failed:", error);
|
|
4
|
+
}
|
|
5
|
+
function globalStorage(name) {
|
|
6
|
+
try {
|
|
7
|
+
const candidate = globalThis[name];
|
|
8
|
+
return typeof candidate === "object" && candidate !== null ? candidate : void 0;
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function webStorageAdapter(resolve, onError = defaultOnError) {
|
|
14
|
+
return {
|
|
15
|
+
get(key) {
|
|
16
|
+
try {
|
|
17
|
+
return resolve().getItem(key);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
onError(error);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
set(key, value) {
|
|
24
|
+
try {
|
|
25
|
+
resolve().setItem(key, value);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
onError(error);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
remove(key) {
|
|
31
|
+
try {
|
|
32
|
+
resolve().removeItem(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
onError(error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
keys() {
|
|
38
|
+
try {
|
|
39
|
+
const storage = resolve();
|
|
40
|
+
const keys = [];
|
|
41
|
+
for (let i = 0; i < storage.length; i++) {
|
|
42
|
+
const key = storage.key(i);
|
|
43
|
+
if (key !== null) keys.push(key);
|
|
44
|
+
}
|
|
45
|
+
return keys;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
onError(error);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
exports.globalStorage = globalStorage; exports.webStorageAdapter = webStorageAdapter;
|
|
58
|
+
//# sourceMappingURL=chunk-DABM2TVR.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-DABM2TVR.cjs","../src/adapters/web.ts"],"names":[],"mappings":"AAAA;ACSO,SAAS,cAAA,CAAe,KAAA,EAAsB;AACpD,EAAA,OAAA,CAAQ,IAAA,CAAK,yCAAA,EAA2C,KAAK,CAAA;AAC9D;AAGO,SAAS,aAAA,CAAc,IAAA,EAA8D;AAC3F,EAAA,IAAI;AACH,IAAA,MAAM,UAAA,EAAa,UAAA,CAAuC,IAAI,CAAA;AAC9D,IAAA,OAAO,OAAO,UAAA,IAAc,SAAA,GAAY,UAAA,IAAc,KAAA,EAAQ,UAAA,EAAwB,KAAA,CAAA;AAAA,EACvF,EAAA,MAAA,CAAQ,CAAA,EAAA;AACP,IAAA,OAAO,KAAA,CAAA;AAAA,EACR;AACD;AAOO,SAAS,iBAAA,CACf,OAAA,EACA,QAAA,EAAoC,cAAA,EACtB;AACd,EAAA,OAAO;AAAA,IACN,GAAA,CAAI,GAAA,EAAK;AACR,MAAA,IAAI;AACH,QAAA,OAAO,OAAA,CAAQ,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA;AAAA,MAC7B,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AACb,QAAA,OAAO,IAAA;AAAA,MACR;AAAA,IACD,CAAA;AAAA,IACA,GAAA,CAAI,GAAA,EAAK,KAAA,EAAO;AACf,MAAA,IAAI;AACH,QAAA,OAAA,CAAQ,CAAA,CAAE,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAAA,MAC7B,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACd;AAAA,IACD,CAAA;AAAA,IACA,MAAA,CAAO,GAAA,EAAK;AACX,MAAA,IAAI;AACH,QAAA,OAAA,CAAQ,CAAA,CAAE,UAAA,CAAW,GAAG,CAAA;AAAA,MACzB,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACd;AAAA,IACD,CAAA;AAAA,IACA,IAAA,CAAA,EAAO;AACN,MAAA,IAAI;AACH,QAAA,MAAM,QAAA,EAAU,OAAA,CAAQ,CAAA;AACxB,QAAA,MAAM,KAAA,EAAiB,CAAC,CAAA;AACxB,QAAA,IAAA,CAAA,IAAS,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,OAAA,CAAQ,MAAA,EAAQ,CAAA,EAAA,EAAK;AACxC,UAAA,MAAM,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA;AACzB,UAAA,GAAA,CAAI,IAAA,IAAQ,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AAAA,QAChC;AACA,QAAA,OAAO,IAAA;AAAA,MACR,EAAA,MAAA,CAAS,KAAA,EAAO;AACf,QAAA,OAAA,CAAQ,KAAK,CAAA;AACb,QAAA,OAAO,CAAC,CAAA;AAAA,MACT;AAAA,IACD;AAAA,EACD,CAAA;AACD;ADlBA;AACA;AACE;AACA;AACF,qFAAC","file":"/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-DABM2TVR.cjs","sourcesContent":[null,"import type { SyncStorage } from '../types'\n\nexport interface WebStorageAdapterOptions {\n\t/** Underlying `Storage`. Defaults to the platform global, resolved lazily. */\n\tstorage?: Storage\n\t/** Called when the underlying storage throws (quota, private mode, …). */\n\tonError?: (error: unknown) => void\n}\n\nexport function defaultOnError(error: unknown): void {\n\tconsole.warn('[fatigue-kit] storage operation failed:', error)\n}\n\n/** Resolve a platform storage global lazily; `undefined` when absent (Node, SSR, …). */\nexport function globalStorage(name: 'localStorage' | 'sessionStorage'): Storage | undefined {\n\ttry {\n\t\tconst candidate = (globalThis as Record<string, unknown>)[name]\n\t\treturn typeof candidate === 'object' && candidate !== null ? (candidate as Storage) : undefined\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * Shared implementation for the Web `Storage` family. Failures are reported via\n * `onError` instead of thrown: a broken quota must not crash the host page —\n * it only means fatigue state degrades to per-session.\n */\nexport function webStorageAdapter(\n\tresolve: () => Storage,\n\tonError: (error: unknown) => void = defaultOnError,\n): SyncStorage {\n\treturn {\n\t\tget(key) {\n\t\t\ttry {\n\t\t\t\treturn resolve().getItem(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\tset(key, value) {\n\t\t\ttry {\n\t\t\t\tresolve().setItem(key, value)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tremove(key) {\n\t\t\ttry {\n\t\t\t\tresolve().removeItem(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tkeys() {\n\t\t\ttry {\n\t\t\t\tconst storage = resolve()\n\t\t\t\tconst keys: string[] = []\n\t\t\t\tfor (let i = 0; i < storage.length; i++) {\n\t\t\t\t\tconst key = storage.key(i)\n\t\t\t\t\tif (key !== null) keys.push(key)\n\t\t\t\t}\n\t\t\t\treturn keys\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn []\n\t\t\t}\n\t\t},\n\t}\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/adapters/memory.ts
|
|
2
|
+
function memoryAdapter(initial) {
|
|
3
|
+
const map = new Map(Object.entries(initial != null ? initial : {}));
|
|
4
|
+
return {
|
|
5
|
+
get: (key) => {
|
|
6
|
+
var _a;
|
|
7
|
+
return (_a = map.get(key)) != null ? _a : null;
|
|
8
|
+
},
|
|
9
|
+
set: (key, value) => {
|
|
10
|
+
map.set(key, value);
|
|
11
|
+
},
|
|
12
|
+
remove: (key) => {
|
|
13
|
+
map.delete(key);
|
|
14
|
+
},
|
|
15
|
+
keys: () => [...map.keys()],
|
|
16
|
+
dump: () => Object.fromEntries(map)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
memoryAdapter
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=chunk-DM2CAKGU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/memory.ts"],"sourcesContent":["import type { SyncStorage } from '../types'\n\nexport interface MemoryAdapter extends SyncStorage {\n\t/** Snapshot of the underlying map. Handy for tests and debugging. */\n\tdump(): Record<string, string>\n}\n\n/**\n * In-memory adapter. This is the default storage of `createFatigue` and the\n * right choice for unit tests, SSR and stateless Node.js scripts.\n * Data lives exactly as long as the fatigue instance (or the process) does.\n */\nexport function memoryAdapter(initial?: Record<string, string>): MemoryAdapter {\n\tconst map = new Map(Object.entries(initial ?? {}))\n\treturn {\n\t\tget: (key) => map.get(key) ?? null,\n\t\tset: (key, value) => {\n\t\t\tmap.set(key, value)\n\t\t},\n\t\tremove: (key) => {\n\t\t\tmap.delete(key)\n\t\t},\n\t\tkeys: () => [...map.keys()],\n\t\tdump: () => Object.fromEntries(map),\n\t}\n}\n"],"mappings":";AAYO,SAAS,cAAc,SAAiD;AAC9E,QAAM,MAAM,IAAI,IAAI,OAAO,QAAQ,4BAAW,CAAC,CAAC,CAAC;AACjD,SAAO;AAAA,IACN,KAAK,CAAC,QAAK;AAfb;AAegB,uBAAI,IAAI,GAAG,MAAX,YAAgB;AAAA;AAAA,IAC9B,KAAK,CAAC,KAAK,UAAU;AACpB,UAAI,IAAI,KAAK,KAAK;AAAA,IACnB;AAAA,IACA,QAAQ,CAAC,QAAQ;AAChB,UAAI,OAAO,GAAG;AAAA,IACf;AAAA,IACA,MAAM,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC;AAAA,IAC1B,MAAM,MAAM,OAAO,YAAY,GAAG;AAAA,EACnC;AACD;","names":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/adapters/web.ts
|
|
2
|
+
function defaultOnError(error) {
|
|
3
|
+
console.warn("[fatigue-kit] storage operation failed:", error);
|
|
4
|
+
}
|
|
5
|
+
function globalStorage(name) {
|
|
6
|
+
try {
|
|
7
|
+
const candidate = globalThis[name];
|
|
8
|
+
return typeof candidate === "object" && candidate !== null ? candidate : void 0;
|
|
9
|
+
} catch (e) {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function webStorageAdapter(resolve, onError = defaultOnError) {
|
|
14
|
+
return {
|
|
15
|
+
get(key) {
|
|
16
|
+
try {
|
|
17
|
+
return resolve().getItem(key);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
onError(error);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
set(key, value) {
|
|
24
|
+
try {
|
|
25
|
+
resolve().setItem(key, value);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
onError(error);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
remove(key) {
|
|
31
|
+
try {
|
|
32
|
+
resolve().removeItem(key);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
onError(error);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
keys() {
|
|
38
|
+
try {
|
|
39
|
+
const storage = resolve();
|
|
40
|
+
const keys = [];
|
|
41
|
+
for (let i = 0; i < storage.length; i++) {
|
|
42
|
+
const key = storage.key(i);
|
|
43
|
+
if (key !== null) keys.push(key);
|
|
44
|
+
}
|
|
45
|
+
return keys;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
onError(error);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
globalStorage,
|
|
56
|
+
webStorageAdapter
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=chunk-GMM2BYRQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/web.ts"],"sourcesContent":["import type { SyncStorage } from '../types'\n\nexport interface WebStorageAdapterOptions {\n\t/** Underlying `Storage`. Defaults to the platform global, resolved lazily. */\n\tstorage?: Storage\n\t/** Called when the underlying storage throws (quota, private mode, …). */\n\tonError?: (error: unknown) => void\n}\n\nexport function defaultOnError(error: unknown): void {\n\tconsole.warn('[fatigue-kit] storage operation failed:', error)\n}\n\n/** Resolve a platform storage global lazily; `undefined` when absent (Node, SSR, …). */\nexport function globalStorage(name: 'localStorage' | 'sessionStorage'): Storage | undefined {\n\ttry {\n\t\tconst candidate = (globalThis as Record<string, unknown>)[name]\n\t\treturn typeof candidate === 'object' && candidate !== null ? (candidate as Storage) : undefined\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n/**\n * Shared implementation for the Web `Storage` family. Failures are reported via\n * `onError` instead of thrown: a broken quota must not crash the host page —\n * it only means fatigue state degrades to per-session.\n */\nexport function webStorageAdapter(\n\tresolve: () => Storage,\n\tonError: (error: unknown) => void = defaultOnError,\n): SyncStorage {\n\treturn {\n\t\tget(key) {\n\t\t\ttry {\n\t\t\t\treturn resolve().getItem(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\t\tset(key, value) {\n\t\t\ttry {\n\t\t\t\tresolve().setItem(key, value)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tremove(key) {\n\t\t\ttry {\n\t\t\t\tresolve().removeItem(key)\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t}\n\t\t},\n\t\tkeys() {\n\t\t\ttry {\n\t\t\t\tconst storage = resolve()\n\t\t\t\tconst keys: string[] = []\n\t\t\t\tfor (let i = 0; i < storage.length; i++) {\n\t\t\t\t\tconst key = storage.key(i)\n\t\t\t\t\tif (key !== null) keys.push(key)\n\t\t\t\t}\n\t\t\t\treturn keys\n\t\t\t} catch (error) {\n\t\t\t\tonError(error)\n\t\t\t\treturn []\n\t\t\t}\n\t\t},\n\t}\n}\n"],"mappings":";AASO,SAAS,eAAe,OAAsB;AACpD,UAAQ,KAAK,2CAA2C,KAAK;AAC9D;AAGO,SAAS,cAAc,MAA8D;AAC3F,MAAI;AACH,UAAM,YAAa,WAAuC,IAAI;AAC9D,WAAO,OAAO,cAAc,YAAY,cAAc,OAAQ,YAAwB;AAAA,EACvF,SAAQ;AACP,WAAO;AAAA,EACR;AACD;AAOO,SAAS,kBACf,SACA,UAAoC,gBACtB;AACd,SAAO;AAAA,IACN,IAAI,KAAK;AACR,UAAI;AACH,eAAO,QAAQ,EAAE,QAAQ,GAAG;AAAA,MAC7B,SAAS,OAAO;AACf,gBAAQ,KAAK;AACb,eAAO;AAAA,MACR;AAAA,IACD;AAAA,IACA,IAAI,KAAK,OAAO;AACf,UAAI;AACH,gBAAQ,EAAE,QAAQ,KAAK,KAAK;AAAA,MAC7B,SAAS,OAAO;AACf,gBAAQ,KAAK;AAAA,MACd;AAAA,IACD;AAAA,IACA,OAAO,KAAK;AACX,UAAI;AACH,gBAAQ,EAAE,WAAW,GAAG;AAAA,MACzB,SAAS,OAAO;AACf,gBAAQ,KAAK;AAAA,MACd;AAAA,IACD;AAAA,IACA,OAAO;AACN,UAAI;AACH,cAAM,UAAU,QAAQ;AACxB,cAAM,OAAiB,CAAC;AACxB,iBAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACxC,gBAAM,MAAM,QAAQ,IAAI,CAAC;AACzB,cAAI,QAAQ,KAAM,MAAK,KAAK,GAAG;AAAA,QAChC;AACA,eAAO;AAAA,MACR,SAAS,OAAO;AACf,gBAAQ,KAAK;AACb,eAAO,CAAC;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACD;","names":[]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/record.ts
|
|
2
|
+
var RECORD_VERSION = 1;
|
|
3
|
+
function emptyRecord() {
|
|
4
|
+
return { v: RECORD_VERSION, hits: [], lifetime: 0 };
|
|
5
|
+
}
|
|
6
|
+
function decodeRecord(raw) {
|
|
7
|
+
if (!raw) return emptyRecord();
|
|
8
|
+
let parsed;
|
|
9
|
+
try {
|
|
10
|
+
parsed = JSON.parse(raw);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return emptyRecord();
|
|
13
|
+
}
|
|
14
|
+
if (parsed === null || typeof parsed !== "object") return emptyRecord();
|
|
15
|
+
const candidate = parsed;
|
|
16
|
+
if (candidate.v !== RECORD_VERSION) return emptyRecord();
|
|
17
|
+
const hits = Array.isArray(candidate.hits) ? candidate.hits.filter((hit) => typeof hit === "number" && Number.isFinite(hit)) : [];
|
|
18
|
+
hits.sort((a, b) => a - b);
|
|
19
|
+
const lifetime = typeof candidate.lifetime === "number" && Number.isFinite(candidate.lifetime) && candidate.lifetime >= 0 ? candidate.lifetime : hits.length;
|
|
20
|
+
return { v: RECORD_VERSION, hits, lifetime };
|
|
21
|
+
}
|
|
22
|
+
function encodeRecord(record) {
|
|
23
|
+
return JSON.stringify(record);
|
|
24
|
+
}
|
|
25
|
+
function pruneRecord(record, keepFrom, maxHits) {
|
|
26
|
+
let first = 0;
|
|
27
|
+
while (first < record.hits.length) {
|
|
28
|
+
const hit = record.hits[first];
|
|
29
|
+
if (hit === void 0 || hit >= keepFrom) break;
|
|
30
|
+
first++;
|
|
31
|
+
}
|
|
32
|
+
if (first > 0) record.hits.splice(0, first);
|
|
33
|
+
if (record.hits.length > maxHits) record.hits.splice(0, record.hits.length - maxHits);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
exports.RECORD_VERSION = RECORD_VERSION; exports.emptyRecord = emptyRecord; exports.decodeRecord = decodeRecord; exports.encodeRecord = encodeRecord; exports.pruneRecord = pruneRecord;
|
|
43
|
+
//# sourceMappingURL=chunk-K7E4LWUL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-K7E4LWUL.cjs","../src/record.ts"],"names":[],"mappings":"AAAA;ACEO,IAAM,eAAA,EAAiB,CAAA;AAEvB,SAAS,WAAA,CAAA,EAA6B;AAC5C,EAAA,OAAO,EAAE,CAAA,EAAG,cAAA,EAAgB,IAAA,EAAM,CAAC,CAAA,EAAG,QAAA,EAAU,EAAE,CAAA;AACnD;AAMO,SAAS,YAAA,CAAa,GAAA,EAA+C;AAC3E,EAAA,GAAA,CAAI,CAAC,GAAA,EAAK,OAAO,WAAA,CAAY,CAAA;AAC7B,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACH,IAAA,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAAA,EACxB,EAAA,MAAA,CAAQ,CAAA,EAAA;AACP,IAAA,OAAO,WAAA,CAAY,CAAA;AAAA,EACpB;AACA,EAAA,GAAA,CAAI,OAAA,IAAW,KAAA,GAAQ,OAAO,OAAA,IAAW,QAAA,EAAU,OAAO,WAAA,CAAY,CAAA;AACtE,EAAA,MAAM,UAAA,EAAY,MAAA;AAClB,EAAA,GAAA,CAAI,SAAA,CAAU,EAAA,IAAM,cAAA,EAAgB,OAAO,WAAA,CAAY,CAAA;AACvD,EAAA,MAAM,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,SAAA,CAAU,IAAI,EAAA,EACtC,SAAA,CAAU,IAAA,CAAK,MAAA,CAAO,CAAC,GAAA,EAAA,GAAuB,OAAO,IAAA,IAAQ,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,GAAG,CAAC,EAAA,EAC7F,CAAC,CAAA;AACJ,EAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAA,GAAM,EAAA,EAAI,CAAC,CAAA;AACzB,EAAA,MAAM,SAAA,EACL,OAAO,SAAA,CAAU,SAAA,IAAa,SAAA,GAC9B,MAAA,CAAO,QAAA,CAAS,SAAA,CAAU,QAAQ,EAAA,GAClC,SAAA,CAAU,SAAA,GAAY,EAAA,EACnB,SAAA,CAAU,SAAA,EACV,IAAA,CAAK,MAAA;AACT,EAAA,OAAO,EAAE,CAAA,EAAG,cAAA,EAAgB,IAAA,EAAM,SAAS,CAAA;AAC5C;AAEO,SAAS,YAAA,CAAa,MAAA,EAA+B;AAC3D,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAC7B;AAOO,SAAS,WAAA,CAAY,MAAA,EAAuB,QAAA,EAAkB,OAAA,EAAuB;AAC3F,EAAA,IAAI,MAAA,EAAQ,CAAA;AACZ,EAAA,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ;AAClC,IAAA,MAAM,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAC7B,IAAA,GAAA,CAAI,IAAA,IAAQ,KAAA,EAAA,GAAa,IAAA,GAAO,QAAA,EAAU,KAAA;AAC1C,IAAA,KAAA,EAAA;AAAA,EACD;AACA,EAAA,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,CAAA,EAAG,KAAK,CAAA;AAC1C,EAAA,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA;AACrF;ADpBA;AACA;AACE;AACA;AACA;AACA;AACA;AACF,wLAAC","file":"/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-K7E4LWUL.cjs","sourcesContent":[null,"import type { FatigueRecord } from './types'\n\nexport const RECORD_VERSION = 1\n\nexport function emptyRecord(): FatigueRecord {\n\treturn { v: RECORD_VERSION, hits: [], lifetime: 0 }\n}\n\n/**\n * Decode a raw storage value. Never throws: corrupted data or an unknown /\n * future record version decodes to an empty record (fresh start).\n */\nexport function decodeRecord(raw: string | null | undefined): FatigueRecord {\n\tif (!raw) return emptyRecord()\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(raw)\n\t} catch {\n\t\treturn emptyRecord()\n\t}\n\tif (parsed === null || typeof parsed !== 'object') return emptyRecord()\n\tconst candidate = parsed as Partial<FatigueRecord>\n\tif (candidate.v !== RECORD_VERSION) return emptyRecord()\n\tconst hits = Array.isArray(candidate.hits)\n\t\t? candidate.hits.filter((hit): hit is number => typeof hit === 'number' && Number.isFinite(hit))\n\t\t: []\n\thits.sort((a, b) => a - b)\n\tconst lifetime =\n\t\ttypeof candidate.lifetime === 'number' &&\n\t\tNumber.isFinite(candidate.lifetime) &&\n\t\tcandidate.lifetime >= 0\n\t\t\t? candidate.lifetime\n\t\t\t: hits.length\n\treturn { v: RECORD_VERSION, hits, lifetime }\n}\n\nexport function encodeRecord(record: FatigueRecord): string {\n\treturn JSON.stringify(record)\n}\n\n/**\n * Drop hits older than `keepFrom` (exclusive), then cap the array at the\n * `maxHits` newest entries. The newest hit is never dropped, so cooldown rules\n * keep working after pruning.\n */\nexport function pruneRecord(record: FatigueRecord, keepFrom: number, maxHits: number): void {\n\tlet first = 0\n\twhile (first < record.hits.length) {\n\t\tconst hit = record.hits[first]\n\t\tif (hit === undefined || hit >= keepFrom) break\n\t\tfirst++\n\t}\n\tif (first > 0) record.hits.splice(0, first)\n\tif (record.hits.length > maxHits) record.hits.splice(0, record.hits.length - maxHits)\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/adapters/memory.ts
|
|
2
|
+
function memoryAdapter(initial) {
|
|
3
|
+
const map = new Map(Object.entries(initial != null ? initial : {}));
|
|
4
|
+
return {
|
|
5
|
+
get: (key) => {
|
|
6
|
+
var _a;
|
|
7
|
+
return (_a = map.get(key)) != null ? _a : null;
|
|
8
|
+
},
|
|
9
|
+
set: (key, value) => {
|
|
10
|
+
map.set(key, value);
|
|
11
|
+
},
|
|
12
|
+
remove: (key) => {
|
|
13
|
+
map.delete(key);
|
|
14
|
+
},
|
|
15
|
+
keys: () => [...map.keys()],
|
|
16
|
+
dump: () => Object.fromEntries(map)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
exports.memoryAdapter = memoryAdapter;
|
|
23
|
+
//# sourceMappingURL=chunk-NBDAXDB6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-NBDAXDB6.cjs","../src/adapters/memory.ts"],"names":[],"mappings":"AAAA;ACYO,SAAS,aAAA,CAAc,OAAA,EAAiD;AAC9E,EAAA,MAAM,IAAA,EAAM,IAAI,GAAA,CAAI,MAAA,CAAO,OAAA,CAAQ,QAAA,GAAA,KAAA,EAAA,QAAA,EAAW,CAAC,CAAC,CAAC,CAAA;AACjD,EAAA,OAAO;AAAA,IACN,GAAA,EAAK,CAAC,GAAA,EAAA,GAAK;AAfb,MAAA,IAAA,EAAA;AAegB,MAAA,OAAA,CAAA,GAAA,EAAA,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,EAAA,GAAX,KAAA,EAAA,GAAA,EAAgB,IAAA;AAAA,IAAA,CAAA;AAAA,IAC9B,GAAA,EAAK,CAAC,GAAA,EAAK,KAAA,EAAA,GAAU;AACpB,MAAA,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,IACnB,CAAA;AAAA,IACA,MAAA,EAAQ,CAAC,GAAA,EAAA,GAAQ;AAChB,MAAA,GAAA,CAAI,MAAA,CAAO,GAAG,CAAA;AAAA,IACf,CAAA;AAAA,IACA,IAAA,EAAM,CAAA,EAAA,GAAM,CAAC,GAAG,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,IAC1B,IAAA,EAAM,CAAA,EAAA,GAAM,MAAA,CAAO,WAAA,CAAY,GAAG;AAAA,EACnC,CAAA;AACD;ADPA;AACA;AACE;AACF,sCAAC","file":"/home/runner/work/fatigue-kit/fatigue-kit/dist/chunk-NBDAXDB6.cjs","sourcesContent":[null,"import type { SyncStorage } from '../types'\n\nexport interface MemoryAdapter extends SyncStorage {\n\t/** Snapshot of the underlying map. Handy for tests and debugging. */\n\tdump(): Record<string, string>\n}\n\n/**\n * In-memory adapter. This is the default storage of `createFatigue` and the\n * right choice for unit tests, SSR and stateless Node.js scripts.\n * Data lives exactly as long as the fatigue instance (or the process) does.\n */\nexport function memoryAdapter(initial?: Record<string, string>): MemoryAdapter {\n\tconst map = new Map(Object.entries(initial ?? {}))\n\treturn {\n\t\tget: (key) => map.get(key) ?? null,\n\t\tset: (key, value) => {\n\t\t\tmap.set(key, value)\n\t\t},\n\t\tremove: (key) => {\n\t\t\tmap.delete(key)\n\t\t},\n\t\tkeys: () => [...map.keys()],\n\t\tdump: () => Object.fromEntries(map),\n\t}\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/record.ts
|
|
2
|
+
var RECORD_VERSION = 1;
|
|
3
|
+
function emptyRecord() {
|
|
4
|
+
return { v: RECORD_VERSION, hits: [], lifetime: 0 };
|
|
5
|
+
}
|
|
6
|
+
function decodeRecord(raw) {
|
|
7
|
+
if (!raw) return emptyRecord();
|
|
8
|
+
let parsed;
|
|
9
|
+
try {
|
|
10
|
+
parsed = JSON.parse(raw);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return emptyRecord();
|
|
13
|
+
}
|
|
14
|
+
if (parsed === null || typeof parsed !== "object") return emptyRecord();
|
|
15
|
+
const candidate = parsed;
|
|
16
|
+
if (candidate.v !== RECORD_VERSION) return emptyRecord();
|
|
17
|
+
const hits = Array.isArray(candidate.hits) ? candidate.hits.filter((hit) => typeof hit === "number" && Number.isFinite(hit)) : [];
|
|
18
|
+
hits.sort((a, b) => a - b);
|
|
19
|
+
const lifetime = typeof candidate.lifetime === "number" && Number.isFinite(candidate.lifetime) && candidate.lifetime >= 0 ? candidate.lifetime : hits.length;
|
|
20
|
+
return { v: RECORD_VERSION, hits, lifetime };
|
|
21
|
+
}
|
|
22
|
+
function encodeRecord(record) {
|
|
23
|
+
return JSON.stringify(record);
|
|
24
|
+
}
|
|
25
|
+
function pruneRecord(record, keepFrom, maxHits) {
|
|
26
|
+
let first = 0;
|
|
27
|
+
while (first < record.hits.length) {
|
|
28
|
+
const hit = record.hits[first];
|
|
29
|
+
if (hit === void 0 || hit >= keepFrom) break;
|
|
30
|
+
first++;
|
|
31
|
+
}
|
|
32
|
+
if (first > 0) record.hits.splice(0, first);
|
|
33
|
+
if (record.hits.length > maxHits) record.hits.splice(0, record.hits.length - maxHits);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
RECORD_VERSION,
|
|
38
|
+
emptyRecord,
|
|
39
|
+
decodeRecord,
|
|
40
|
+
encodeRecord,
|
|
41
|
+
pruneRecord
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=chunk-ZNIZLIUO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/record.ts"],"sourcesContent":["import type { FatigueRecord } from './types'\n\nexport const RECORD_VERSION = 1\n\nexport function emptyRecord(): FatigueRecord {\n\treturn { v: RECORD_VERSION, hits: [], lifetime: 0 }\n}\n\n/**\n * Decode a raw storage value. Never throws: corrupted data or an unknown /\n * future record version decodes to an empty record (fresh start).\n */\nexport function decodeRecord(raw: string | null | undefined): FatigueRecord {\n\tif (!raw) return emptyRecord()\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(raw)\n\t} catch {\n\t\treturn emptyRecord()\n\t}\n\tif (parsed === null || typeof parsed !== 'object') return emptyRecord()\n\tconst candidate = parsed as Partial<FatigueRecord>\n\tif (candidate.v !== RECORD_VERSION) return emptyRecord()\n\tconst hits = Array.isArray(candidate.hits)\n\t\t? candidate.hits.filter((hit): hit is number => typeof hit === 'number' && Number.isFinite(hit))\n\t\t: []\n\thits.sort((a, b) => a - b)\n\tconst lifetime =\n\t\ttypeof candidate.lifetime === 'number' &&\n\t\tNumber.isFinite(candidate.lifetime) &&\n\t\tcandidate.lifetime >= 0\n\t\t\t? candidate.lifetime\n\t\t\t: hits.length\n\treturn { v: RECORD_VERSION, hits, lifetime }\n}\n\nexport function encodeRecord(record: FatigueRecord): string {\n\treturn JSON.stringify(record)\n}\n\n/**\n * Drop hits older than `keepFrom` (exclusive), then cap the array at the\n * `maxHits` newest entries. The newest hit is never dropped, so cooldown rules\n * keep working after pruning.\n */\nexport function pruneRecord(record: FatigueRecord, keepFrom: number, maxHits: number): void {\n\tlet first = 0\n\twhile (first < record.hits.length) {\n\t\tconst hit = record.hits[first]\n\t\tif (hit === undefined || hit >= keepFrom) break\n\t\tfirst++\n\t}\n\tif (first > 0) record.hits.splice(0, first)\n\tif (record.hits.length > maxHits) record.hits.splice(0, record.hits.length - maxHits)\n}\n"],"mappings":";AAEO,IAAM,iBAAiB;AAEvB,SAAS,cAA6B;AAC5C,SAAO,EAAE,GAAG,gBAAgB,MAAM,CAAC,GAAG,UAAU,EAAE;AACnD;AAMO,SAAS,aAAa,KAA+C;AAC3E,MAAI,CAAC,IAAK,QAAO,YAAY;AAC7B,MAAI;AACJ,MAAI;AACH,aAAS,KAAK,MAAM,GAAG;AAAA,EACxB,SAAQ;AACP,WAAO,YAAY;AAAA,EACpB;AACA,MAAI,WAAW,QAAQ,OAAO,WAAW,SAAU,QAAO,YAAY;AACtE,QAAM,YAAY;AAClB,MAAI,UAAU,MAAM,eAAgB,QAAO,YAAY;AACvD,QAAM,OAAO,MAAM,QAAQ,UAAU,IAAI,IACtC,UAAU,KAAK,OAAO,CAAC,QAAuB,OAAO,QAAQ,YAAY,OAAO,SAAS,GAAG,CAAC,IAC7F,CAAC;AACJ,OAAK,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACzB,QAAM,WACL,OAAO,UAAU,aAAa,YAC9B,OAAO,SAAS,UAAU,QAAQ,KAClC,UAAU,YAAY,IACnB,UAAU,WACV,KAAK;AACT,SAAO,EAAE,GAAG,gBAAgB,MAAM,SAAS;AAC5C;AAEO,SAAS,aAAa,QAA+B;AAC3D,SAAO,KAAK,UAAU,MAAM;AAC7B;AAOO,SAAS,YAAY,QAAuB,UAAkB,SAAuB;AAC3F,MAAI,QAAQ;AACZ,SAAO,QAAQ,OAAO,KAAK,QAAQ;AAClC,UAAM,MAAM,OAAO,KAAK,KAAK;AAC7B,QAAI,QAAQ,UAAa,OAAO,SAAU;AAC1C;AAAA,EACD;AACA,MAAI,QAAQ,EAAG,QAAO,KAAK,OAAO,GAAG,KAAK;AAC1C,MAAI,OAAO,KAAK,SAAS,QAAS,QAAO,KAAK,OAAO,GAAG,OAAO,KAAK,SAAS,OAAO;AACrF;","names":[]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var FatigueKit=(()=>{var b=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var j=(t,n)=>{for(var e in n)b(t,e,{get:n[e],enumerable:!0})},L=(t,n,e,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of H(n))!J.call(t,i)&&i!==e&&b(t,i,{get:()=>n[i],enumerable:!(r=Y(n,i))||r.enumerable});return t};var U=t=>L(b({},"__esModule",{value:!0}),t);var Z={};j(Z,{RECORD_VERSION:()=>R,createFatigue:()=>$,memoryAdapter:()=>p});function p(t){let n=new Map(Object.entries(t!=null?t:{}));return{get:e=>{var r;return(r=n.get(e))!=null?r:null},set:(e,r)=>{n.set(e,r)},remove:e=>{n.delete(e)},keys:()=>[...n.keys()],dump:()=>Object.fromEntries(n)}}function D(t){if(t===void 0)return 0;let n=/^(\d{1,2}):(\d{2})$/.exec(t.trim());if(n===null||n[1]===void 0||n[2]===void 0)throw new TypeError(`[fatigue-kit] invalid cutoff: "${t}". Expected 'HH:mm'.`);let e=Number(n[1]),r=Number(n[2]);if(e>23||r>59)throw new TypeError(`[fatigue-kit] invalid cutoff: "${t}". Hours must be 0-23, minutes 0-59.`);return e*60+r}function E(t){let n=new Date(t);return n.setHours(0,0,0,0),n}function W(t,n){switch(n.every){case"day":return E(t).getTime();case"week":{let e=E(t),r=(e.getDay()-n.weekStartsOn+7)%7;return e.setDate(e.getDate()-r),e.getTime()}case"month":{let e=new Date(t);return new Date(e.getFullYear(),e.getMonth(),1).getTime()}case"year":{let e=new Date(t);return new Date(e.getFullYear(),0,1).getTime()}}}function q(t,n){switch(n.every){case"day":{let e=new Date(t);return e.setDate(e.getDate()-1),e.getTime()}case"week":{let e=new Date(t);return e.setDate(e.getDate()-7),e.getTime()}case"month":{let e=new Date(t);return new Date(e.getFullYear(),e.getMonth()-1,1).getTime()}case"year":{let e=new Date(t);return new Date(e.getFullYear()-1,0,1).getTime()}}}function A(t,n){let e=new Date(t);return new Date(e.getFullYear(),e.getMonth(),e.getDate(),Math.floor(n/60),n%60).getTime()}function y(t,n){let e=W(t,n),r=A(e,n.cutoffMinutes);return r<=t?r:A(q(e,n),n.cutoffMinutes)}var K={day:12*36e5,week:8*864e5,month:8*864e5,year:32*864e5};function T(t,n){let e=K[n.every],r=t;for(let i=0;i<50;i++){r+=e;let o=y(r,n);if(o>t)return o}throw new Error("[fatigue-kit] failed to compute the next calendar period")}var B={s:1e3,m:6e4,h:36e5,d:864e5};function h(t){if(typeof t=="number"){if(!Number.isFinite(t)||t<=0)throw new TypeError(`[fatigue-kit] invalid duration: ${t}`);return t}let n=/^(\d+(?:\.\d+)?)\s*([smhd])$/.exec(t.trim());if(n===null||n[1]===void 0||n[2]===void 0)throw new TypeError(`[fatigue-kit] invalid duration: "${t}". Expected a positive number of ms, or '45s' / '30m' / '12h' / '7d'.`);let e=B[n[2]];if(e===void 0)throw new TypeError(`[fatigue-kit] invalid duration: "${t}"`);let r=Number(n[1])*e;if(!(r>0))throw new TypeError(`[fatigue-kit] invalid duration: "${t}"`);return r}var R=1;function w(){return{v:1,hits:[],lifetime:0}}function x(t){if(!t)return w();let n;try{n=JSON.parse(t)}catch(o){return w()}if(n===null||typeof n!="object")return w();let e=n;if(e.v!==1)return w();let r=Array.isArray(e.hits)?e.hits.filter(o=>typeof o=="number"&&Number.isFinite(o)):[];r.sort((o,s)=>o-s);let i=typeof e.lifetime=="number"&&Number.isFinite(e.lifetime)&&e.lifetime>=0?e.lifetime:r.length;return{v:1,hits:r,lifetime:i}}function k(t){return JSON.stringify(t)}function I(t,n,e){let r=0;for(;r<t.hits.length;){let i=t.hits[r];if(i===void 0||i>=n)break;r++}r>0&&t.hits.splice(0,r),t.hits.length>e&&t.hits.splice(0,t.hits.length-e)}var X="fatigue-kit",z=100;function O(t,n){if(typeof t!="string"||t.length===0)throw new TypeError(`[fatigue-kit] ${n} must be a non-empty string`)}function F(t){if(!Number.isInteger(t)||t<1)throw new TypeError(`[fatigue-kit] rule "max" must be a positive integer, got ${t}`)}function M(t){let n=Array.isArray(t)?t:[t];if(n.length===0)throw new TypeError("[fatigue-kit] at least one rule is required");return n.map(e=>{var r;if(e===null||typeof e!="object")throw new TypeError(`[fatigue-kit] unknown rule: ${JSON.stringify(e)}`);if("window"in e)return F(e.max),{kind:"sliding",rule:e,max:e.max,windowMs:h(e.window)};if("every"in e){if(F(e.max),e.every!=="day"&&e.every!=="week"&&e.every!=="month"&&e.every!=="year")throw new TypeError(`[fatigue-kit] invalid "every": ${JSON.stringify(e.every)}`);return{kind:"calendar",rule:e,max:e.max,spec:{every:e.every,cutoffMinutes:D(e.cutoff),weekStartsOn:(r=e.weekStartsOn)!=null?r:1}}}if("cooldown"in e)return{kind:"cooldown",rule:e,cooldownMs:h(e.cooldown)};if("max"in e)return F(e.max),{kind:"lifetime",rule:e,max:e.max};throw new TypeError(`[fatigue-kit] unknown rule: ${JSON.stringify(e)}`)})}function G(t,n,e){switch(t.kind){case"sliding":{let r=e-t.windowMs,i=0,o=Number.POSITIVE_INFINITY;for(let f of n.hits)f>r&&(i++,f<o&&(o=f));let s=t.max-i;return{remaining:s,nextAvailableAt:s<=0&&o!==Number.POSITIVE_INFINITY?o+t.windowMs:void 0}}case"calendar":{let r=y(e,t.spec),i=0;for(let s of n.hits)s>=r&&i++;let o=t.max-i;return{remaining:o,nextAvailableAt:o<=0?T(e,t.spec):void 0}}case"cooldown":{let r=n.hits.length>0?n.hits[n.hits.length-1]:void 0;if(r===void 0)return{remaining:Number.POSITIVE_INFINITY};let i=r+t.cooldownMs;return{remaining:Number.POSITIVE_INFINITY,nextAvailableAt:i>e?i:void 0}}case"lifetime":return{remaining:t.max-n.lifetime}}}function _(t,n,e){let r=Number.POSITIVE_INFINITY,i,o;for(let f of n){let c=G(f,t,e);Number.isFinite(c.remaining)&&(r=Math.min(r,c.remaining)),c.nextAvailableAt!==void 0&&(i===void 0||c.nextAvailableAt>i)&&(i=c.nextAvailableAt),c.remaining>0&&(c.nextAvailableAt===void 0||c.nextAvailableAt<=e)||o!=null||(o=f.rule)}let s={allowed:o===void 0,remaining:Math.max(0,r)};return i!==void 0&&(s.nextAvailableAt=i),o!==void 0&&(s.deniedBy=o),s}function Q(t,n){let e=n;for(let r of t)r.kind==="sliding"?e=Math.min(e,n-r.windowMs):r.kind==="calendar"?e=Math.min(e,y(n,r.spec)):r.kind==="cooldown"&&(e=Math.min(e,n-r.cooldownMs));return e}function $(t={}){var v,S,N,C;let n=(v=t.storage)!=null?v:p(),e=(S=t.clock)!=null?S:{now:()=>Date.now()},r=(N=t.namespace)!=null?N:X,i=(C=t.maxHits)!=null?C:z;if(O(r,"namespace"),!Number.isInteger(i)||i<1)throw new TypeError(`[fatigue-kit] maxHits must be a positive integer, got ${i}`);let o=a=>(O(a,"key"),`${r}:${a}`),s=a=>x(n.get(o(a)));return{tryConsume:(a,u)=>{let m=M(u),g=e.now(),l=s(a),d=_(l,m,g);return d.allowed&&(Number.isFinite(d.remaining)&&(d.remaining=Math.max(0,d.remaining-1)),l.hits.push(g),l.lifetime+=1,I(l,Q(m,g),i),n.set(o(a),k(l))),d},peek:(a,u)=>{let m=M(u);return _(s(a),m,e.now())},reset:a=>{if(a!==void 0){n.remove(o(a));return}if(typeof n.keys!="function")throw new Error("[fatigue-kit] reset() without a key requires a storage adapter implementing keys()");let u=`${r}:`;for(let m of n.keys())m.startsWith(u)&&n.remove(m)},exportRecord:a=>{let u=n.get(o(a));return u?x(u):null},importRecord:(a,u)=>{var l;let m=((l=u.hits)!=null?l:[]).filter(d=>typeof d=="number"&&Number.isFinite(d)).sort((d,V)=>d-V),g=typeof u.lifetime=="number"&&Number.isFinite(u.lifetime)&&u.lifetime>=0?u.lifetime:m.length;n.set(o(a),k({v:1,hits:m,lifetime:g}))}}}return U(Z);})();
|
|
2
|
+
//# sourceMappingURL=index.global.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/adapters/memory.ts","../../src/calendar.ts","../../src/duration.ts","../../src/record.ts","../../src/engine.ts"],"sourcesContent":["export { memoryAdapter } from './adapters/memory'\nexport { createFatigue } from './engine'\nexport { RECORD_VERSION } from './record'\nexport type {\n\tCalendarRule,\n\tClock,\n\tConsumeResult,\n\tCooldownRule,\n\tDuration,\n\tFatigue,\n\tFatigueOptions,\n\tFatigueRecord,\n\tFatigueRule,\n\tLifetimeRule,\n\tSlidingWindowRule,\n\tSyncStorage,\n} from './types'\n","import type { SyncStorage } from '../types'\n\nexport interface MemoryAdapter extends SyncStorage {\n\t/** Snapshot of the underlying map. Handy for tests and debugging. */\n\tdump(): Record<string, string>\n}\n\n/**\n * In-memory adapter. This is the default storage of `createFatigue` and the\n * right choice for unit tests, SSR and stateless Node.js scripts.\n * Data lives exactly as long as the fatigue instance (or the process) does.\n */\nexport function memoryAdapter(initial?: Record<string, string>): MemoryAdapter {\n\tconst map = new Map(Object.entries(initial ?? {}))\n\treturn {\n\t\tget: (key) => map.get(key) ?? null,\n\t\tset: (key, value) => {\n\t\t\tmap.set(key, value)\n\t\t},\n\t\tremove: (key) => {\n\t\t\tmap.delete(key)\n\t\t},\n\t\tkeys: () => [...map.keys()],\n\t\tdump: () => Object.fromEntries(map),\n\t}\n}\n","export type CalendarEvery = 'day' | 'week' | 'month' | 'year'\n\nexport interface CalendarSpec {\n\tevery: CalendarEvery\n\tcutoffMinutes: number\n\tweekStartsOn: number\n}\n\n/** Parse a `'HH:mm'` cutoff into minutes after local midnight. Default (no cutoff) is `0`. */\nexport function parseCutoff(cutoff: string | undefined): number {\n\tif (cutoff === undefined) return 0\n\tconst match = /^(\\d{1,2}):(\\d{2})$/.exec(cutoff.trim())\n\tif (match === null || match[1] === undefined || match[2] === undefined) {\n\t\tthrow new TypeError(`[fatigue-kit] invalid cutoff: \"${cutoff}\". Expected 'HH:mm'.`)\n\t}\n\tconst hours = Number(match[1])\n\tconst minutes = Number(match[2])\n\tif (hours > 23 || minutes > 59) {\n\t\tthrow new TypeError(\n\t\t\t`[fatigue-kit] invalid cutoff: \"${cutoff}\". Hours must be 0-23, minutes 0-59.`,\n\t\t)\n\t}\n\treturn hours * 60 + minutes\n}\n\nfunction localMidnight(ts: number): Date {\n\tconst date = new Date(ts)\n\tdate.setHours(0, 0, 0, 0)\n\treturn date\n}\n\n/** Midnight-based start of the period containing `ts`, before applying the cutoff. */\nfunction naturalPeriodStart(ts: number, spec: CalendarSpec): number {\n\tswitch (spec.every) {\n\t\tcase 'day':\n\t\t\treturn localMidnight(ts).getTime()\n\t\tcase 'week': {\n\t\t\tconst date = localMidnight(ts)\n\t\t\tconst offset = (date.getDay() - spec.weekStartsOn + 7) % 7\n\t\t\tdate.setDate(date.getDate() - offset)\n\t\t\treturn date.getTime()\n\t\t}\n\t\tcase 'month': {\n\t\t\tconst date = new Date(ts)\n\t\t\treturn new Date(date.getFullYear(), date.getMonth(), 1).getTime()\n\t\t}\n\t\tcase 'year': {\n\t\t\tconst date = new Date(ts)\n\t\t\treturn new Date(date.getFullYear(), 0, 1).getTime()\n\t\t}\n\t}\n}\n\nfunction previousNaturalStart(naturalStart: number, spec: CalendarSpec): number {\n\tswitch (spec.every) {\n\t\tcase 'day': {\n\t\t\tconst date = new Date(naturalStart)\n\t\t\tdate.setDate(date.getDate() - 1)\n\t\t\treturn date.getTime()\n\t\t}\n\t\tcase 'week': {\n\t\t\tconst date = new Date(naturalStart)\n\t\t\tdate.setDate(date.getDate() - 7)\n\t\t\treturn date.getTime()\n\t\t}\n\t\tcase 'month': {\n\t\t\tconst date = new Date(naturalStart)\n\t\t\treturn new Date(date.getFullYear(), date.getMonth() - 1, 1).getTime()\n\t\t}\n\t\tcase 'year': {\n\t\t\tconst date = new Date(naturalStart)\n\t\t\treturn new Date(date.getFullYear() - 1, 0, 1).getTime()\n\t\t}\n\t}\n}\n\n/**\n * Local wall-clock time of `cutoffMinutes` past midnight, built from date\n * components. On DST transition days \"midnight epoch + fixed minutes\" would\n * land an hour off wall-clock time (e.g. after spring-forward a 04:00 cutoff\n * computed by addition would actually fire at 05:00), so the boundary must be\n * constructed, never added.\n */\nfunction wallClockBoundary(midnight: number, cutoffMinutes: number): number {\n\tconst date = new Date(midnight)\n\treturn new Date(\n\t\tdate.getFullYear(),\n\t\tdate.getMonth(),\n\t\tdate.getDate(),\n\t\tMath.floor(cutoffMinutes / 60),\n\t\tcutoffMinutes % 60,\n\t).getTime()\n}\n\n/**\n * Start of the calendar period containing `ts`, cutoff applied.\n * All arithmetic works on local date components (never `+ 24h`), so DST\n * transitions cannot shift a boundary.\n */\nexport function calendarPeriodStart(ts: number, spec: CalendarSpec): number {\n\tconst natural = naturalPeriodStart(ts, spec)\n\tconst boundary = wallClockBoundary(natural, spec.cutoffMinutes)\n\tif (boundary <= ts) return boundary\n\treturn wallClockBoundary(previousNaturalStart(natural, spec), spec.cutoffMinutes)\n}\n\n// Per-step cursors used to find the *next* boundary. Each jump is guaranteed to\n// be shorter than one period (so no period can be skipped) and long enough to\n// make progress; the loop simply walks forward until the boundary passes `ts`.\nconst JUMP_MS: Record<CalendarEvery, number> = {\n\tday: 12 * 3_600_000,\n\tweek: 8 * 86_400_000,\n\tmonth: 8 * 86_400_000,\n\tyear: 32 * 86_400_000,\n}\n\n/** Start of the calendar period following the one containing `ts`. Strictly greater than `ts`. */\nexport function calendarNextPeriodStart(ts: number, spec: CalendarSpec): number {\n\tconst jump = JUMP_MS[spec.every]\n\tlet cursor = ts\n\tfor (let i = 0; i < 50; i++) {\n\t\tcursor += jump\n\t\tconst start = calendarPeriodStart(cursor, spec)\n\t\tif (start > ts) return start\n\t}\n\tthrow new Error('[fatigue-kit] failed to compute the next calendar period')\n}\n","import type { Duration } from './types'\n\nconst UNITS: Record<string, number> = {\n\ts: 1_000,\n\tm: 60_000,\n\th: 3_600_000,\n\td: 86_400_000,\n}\n\n/** Parse a {@link Duration} into milliseconds. Throws `TypeError` on invalid input. */\nexport function parseDuration(duration: Duration): number {\n\tif (typeof duration === 'number') {\n\t\tif (!Number.isFinite(duration) || duration <= 0) {\n\t\t\tthrow new TypeError(`[fatigue-kit] invalid duration: ${duration}`)\n\t\t}\n\t\treturn duration\n\t}\n\tconst match = /^(\\d+(?:\\.\\d+)?)\\s*([smhd])$/.exec(duration.trim())\n\tif (match === null || match[1] === undefined || match[2] === undefined) {\n\t\tthrow new TypeError(\n\t\t\t`[fatigue-kit] invalid duration: \"${duration}\". Expected a positive number of ms, or '45s' / '30m' / '12h' / '7d'.`,\n\t\t)\n\t}\n\tconst unitMs = UNITS[match[2]]\n\tif (unitMs === undefined) {\n\t\tthrow new TypeError(`[fatigue-kit] invalid duration: \"${duration}\"`)\n\t}\n\tconst ms = Number(match[1]) * unitMs\n\tif (!(ms > 0)) {\n\t\tthrow new TypeError(`[fatigue-kit] invalid duration: \"${duration}\"`)\n\t}\n\treturn ms\n}\n","import type { FatigueRecord } from './types'\n\nexport const RECORD_VERSION = 1\n\nexport function emptyRecord(): FatigueRecord {\n\treturn { v: RECORD_VERSION, hits: [], lifetime: 0 }\n}\n\n/**\n * Decode a raw storage value. Never throws: corrupted data or an unknown /\n * future record version decodes to an empty record (fresh start).\n */\nexport function decodeRecord(raw: string | null | undefined): FatigueRecord {\n\tif (!raw) return emptyRecord()\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(raw)\n\t} catch {\n\t\treturn emptyRecord()\n\t}\n\tif (parsed === null || typeof parsed !== 'object') return emptyRecord()\n\tconst candidate = parsed as Partial<FatigueRecord>\n\tif (candidate.v !== RECORD_VERSION) return emptyRecord()\n\tconst hits = Array.isArray(candidate.hits)\n\t\t? candidate.hits.filter((hit): hit is number => typeof hit === 'number' && Number.isFinite(hit))\n\t\t: []\n\thits.sort((a, b) => a - b)\n\tconst lifetime =\n\t\ttypeof candidate.lifetime === 'number' &&\n\t\tNumber.isFinite(candidate.lifetime) &&\n\t\tcandidate.lifetime >= 0\n\t\t\t? candidate.lifetime\n\t\t\t: hits.length\n\treturn { v: RECORD_VERSION, hits, lifetime }\n}\n\nexport function encodeRecord(record: FatigueRecord): string {\n\treturn JSON.stringify(record)\n}\n\n/**\n * Drop hits older than `keepFrom` (exclusive), then cap the array at the\n * `maxHits` newest entries. The newest hit is never dropped, so cooldown rules\n * keep working after pruning.\n */\nexport function pruneRecord(record: FatigueRecord, keepFrom: number, maxHits: number): void {\n\tlet first = 0\n\twhile (first < record.hits.length) {\n\t\tconst hit = record.hits[first]\n\t\tif (hit === undefined || hit >= keepFrom) break\n\t\tfirst++\n\t}\n\tif (first > 0) record.hits.splice(0, first)\n\tif (record.hits.length > maxHits) record.hits.splice(0, record.hits.length - maxHits)\n}\n","import { memoryAdapter } from './adapters/memory'\nimport {\n\ttype CalendarSpec,\n\tcalendarNextPeriodStart,\n\tcalendarPeriodStart,\n\tparseCutoff,\n} from './calendar'\nimport { parseDuration } from './duration'\nimport { decodeRecord, encodeRecord, pruneRecord, RECORD_VERSION } from './record'\nimport type {\n\tCalendarRule,\n\tClock,\n\tConsumeResult,\n\tCooldownRule,\n\tFatigue,\n\tFatigueOptions,\n\tFatigueRecord,\n\tFatigueRule,\n\tLifetimeRule,\n\tSlidingWindowRule,\n\tSyncStorage,\n} from './types'\n\nconst DEFAULT_NAMESPACE = 'fatigue-kit'\nconst DEFAULT_MAX_HITS = 100\n\n// Rules are compiled once per call so duration strings are parsed a single time.\ntype CompiledRule =\n\t| { kind: 'sliding'; rule: SlidingWindowRule; max: number; windowMs: number }\n\t| { kind: 'calendar'; rule: CalendarRule; max: number; spec: CalendarSpec }\n\t| { kind: 'cooldown'; rule: CooldownRule; cooldownMs: number }\n\t| { kind: 'lifetime'; rule: LifetimeRule; max: number }\n\ninterface RuleOutcome {\n\tremaining: number\n\tnextAvailableAt?: number\n}\n\nfunction assertNonEmpty(value: string, label: string): void {\n\tif (typeof value !== 'string' || value.length === 0) {\n\t\tthrow new TypeError(`[fatigue-kit] ${label} must be a non-empty string`)\n\t}\n}\n\nfunction requireMax(max: number): void {\n\tif (!Number.isInteger(max) || max < 1) {\n\t\tthrow new TypeError(`[fatigue-kit] rule \"max\" must be a positive integer, got ${max}`)\n\t}\n}\n\nfunction compileRules(input: FatigueRule | FatigueRule[]): CompiledRule[] {\n\tconst list = Array.isArray(input) ? input : [input]\n\tif (list.length === 0) {\n\t\tthrow new TypeError('[fatigue-kit] at least one rule is required')\n\t}\n\treturn list.map((rule): CompiledRule => {\n\t\tif (rule === null || typeof rule !== 'object') {\n\t\t\tthrow new TypeError(`[fatigue-kit] unknown rule: ${JSON.stringify(rule)}`)\n\t\t}\n\t\tif ('window' in rule) {\n\t\t\trequireMax(rule.max)\n\t\t\treturn { kind: 'sliding', rule, max: rule.max, windowMs: parseDuration(rule.window) }\n\t\t}\n\t\tif ('every' in rule) {\n\t\t\trequireMax(rule.max)\n\t\t\tif (\n\t\t\t\trule.every !== 'day' &&\n\t\t\t\trule.every !== 'week' &&\n\t\t\t\trule.every !== 'month' &&\n\t\t\t\trule.every !== 'year'\n\t\t\t) {\n\t\t\t\tthrow new TypeError(`[fatigue-kit] invalid \"every\": ${JSON.stringify(rule.every)}`)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: 'calendar',\n\t\t\t\trule,\n\t\t\t\tmax: rule.max,\n\t\t\t\tspec: {\n\t\t\t\t\tevery: rule.every,\n\t\t\t\t\tcutoffMinutes: parseCutoff(rule.cutoff),\n\t\t\t\t\tweekStartsOn: rule.weekStartsOn ?? 1,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tif ('cooldown' in rule) {\n\t\t\treturn { kind: 'cooldown', rule, cooldownMs: parseDuration(rule.cooldown) }\n\t\t}\n\t\tif ('max' in rule) {\n\t\t\trequireMax(rule.max)\n\t\t\treturn { kind: 'lifetime', rule, max: rule.max }\n\t\t}\n\t\tthrow new TypeError(`[fatigue-kit] unknown rule: ${JSON.stringify(rule)}`)\n\t})\n}\n\nfunction outcomeFor(compiled: CompiledRule, record: FatigueRecord, now: number): RuleOutcome {\n\tswitch (compiled.kind) {\n\t\tcase 'sliding': {\n\t\t\tconst from = now - compiled.windowMs\n\t\t\tlet count = 0\n\t\t\tlet oldest = Number.POSITIVE_INFINITY\n\t\t\tfor (const hit of record.hits) {\n\t\t\t\tif (hit > from) {\n\t\t\t\t\tcount++\n\t\t\t\t\tif (hit < oldest) oldest = hit\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst remaining = compiled.max - count\n\t\t\treturn {\n\t\t\t\tremaining,\n\t\t\t\tnextAvailableAt:\n\t\t\t\t\tremaining <= 0 && oldest !== Number.POSITIVE_INFINITY\n\t\t\t\t\t\t? oldest + compiled.windowMs\n\t\t\t\t\t\t: undefined,\n\t\t\t}\n\t\t}\n\t\tcase 'calendar': {\n\t\t\tconst start = calendarPeriodStart(now, compiled.spec)\n\t\t\tlet count = 0\n\t\t\tfor (const hit of record.hits) {\n\t\t\t\tif (hit >= start) count++\n\t\t\t}\n\t\t\tconst remaining = compiled.max - count\n\t\t\treturn {\n\t\t\t\tremaining,\n\t\t\t\tnextAvailableAt: remaining <= 0 ? calendarNextPeriodStart(now, compiled.spec) : undefined,\n\t\t\t}\n\t\t}\n\t\tcase 'cooldown': {\n\t\t\tconst lastHit = record.hits.length > 0 ? record.hits[record.hits.length - 1] : undefined\n\t\t\tif (lastHit === undefined) return { remaining: Number.POSITIVE_INFINITY }\n\t\t\tconst readyAt = lastHit + compiled.cooldownMs\n\t\t\treturn {\n\t\t\t\tremaining: Number.POSITIVE_INFINITY,\n\t\t\t\tnextAvailableAt: readyAt > now ? readyAt : undefined,\n\t\t\t}\n\t\t}\n\t\tcase 'lifetime': {\n\t\t\treturn { remaining: compiled.max - record.lifetime }\n\t\t}\n\t}\n}\n\nfunction evaluate(record: FatigueRecord, compiled: CompiledRule[], now: number): ConsumeResult {\n\tlet remaining = Number.POSITIVE_INFINITY\n\tlet nextAvailableAt: number | undefined\n\tlet deniedBy: FatigueRule | undefined\n\tfor (const rule of compiled) {\n\t\tconst outcome = outcomeFor(rule, record, now)\n\t\tif (Number.isFinite(outcome.remaining)) {\n\t\t\tremaining = Math.min(remaining, outcome.remaining)\n\t\t}\n\t\tif (\n\t\t\toutcome.nextAvailableAt !== undefined &&\n\t\t\t(nextAvailableAt === undefined || outcome.nextAvailableAt > nextAvailableAt)\n\t\t) {\n\t\t\tnextAvailableAt = outcome.nextAvailableAt\n\t\t}\n\t\tconst ruleAllows =\n\t\t\toutcome.remaining > 0 &&\n\t\t\t(outcome.nextAvailableAt === undefined || outcome.nextAvailableAt <= now)\n\t\tif (!ruleAllows) deniedBy ??= rule.rule\n\t}\n\tconst result: ConsumeResult = {\n\t\tallowed: deniedBy === undefined,\n\t\tremaining: Math.max(0, remaining),\n\t}\n\tif (nextAvailableAt !== undefined) result.nextAvailableAt = nextAvailableAt\n\tif (deniedBy !== undefined) result.deniedBy = deniedBy\n\treturn result\n}\n\n/**\n * Oldest timestamp that still has to be kept to evaluate the rules. Used to\n * prune the hit list on write: anything older than this is dead weight, and the\n * `lifetime` counter keeps lifetime rules working regardless.\n */\nfunction keepFrom(compiled: CompiledRule[], now: number): number {\n\tlet keep = now\n\tfor (const rule of compiled) {\n\t\tif (rule.kind === 'sliding') keep = Math.min(keep, now - rule.windowMs)\n\t\telse if (rule.kind === 'calendar') keep = Math.min(keep, calendarPeriodStart(now, rule.spec))\n\t\telse if (rule.kind === 'cooldown') keep = Math.min(keep, now - rule.cooldownMs)\n\t}\n\treturn keep\n}\n\n/**\n * Create a fatigue (frequency capping) instance.\n *\n * ```ts\n * const fatigue = createFatigue({ storage: localStorageAdapter() })\n * const { allowed } = fatigue.tryConsume('popup', [{ max: 1, every: 'day' }])\n * ```\n */\nexport function createFatigue(options: FatigueOptions = {}): Fatigue {\n\tconst storage: SyncStorage = options.storage ?? memoryAdapter()\n\tconst clock: Clock = options.clock ?? { now: () => Date.now() }\n\tconst namespace = options.namespace ?? DEFAULT_NAMESPACE\n\tconst maxHits = options.maxHits ?? DEFAULT_MAX_HITS\n\tassertNonEmpty(namespace, 'namespace')\n\tif (!Number.isInteger(maxHits) || maxHits < 1) {\n\t\tthrow new TypeError(`[fatigue-kit] maxHits must be a positive integer, got ${maxHits}`)\n\t}\n\n\tconst storageKey = (key: string): string => {\n\t\tassertNonEmpty(key, 'key')\n\t\treturn `${namespace}:${key}`\n\t}\n\n\tconst read = (key: string): FatigueRecord => decodeRecord(storage.get(storageKey(key)))\n\n\tconst tryConsume = (key: string, rules: FatigueRule | FatigueRule[]): ConsumeResult => {\n\t\tconst compiled = compileRules(rules)\n\t\tconst now = clock.now()\n\t\tconst record = read(key)\n\t\tconst result = evaluate(record, compiled, now)\n\t\tif (result.allowed) {\n\t\t\t// `remaining` describes the state *after* the call, so `remaining === 0`\n\t\t\t// means \"this was the last allowed consumption\".\n\t\t\tif (Number.isFinite(result.remaining)) {\n\t\t\t\tresult.remaining = Math.max(0, result.remaining - 1)\n\t\t\t}\n\t\t\trecord.hits.push(now)\n\t\t\trecord.lifetime += 1\n\t\t\tpruneRecord(record, keepFrom(compiled, now), maxHits)\n\t\t\tstorage.set(storageKey(key), encodeRecord(record))\n\t\t}\n\t\treturn result\n\t}\n\n\tconst peek = (key: string, rules: FatigueRule | FatigueRule[]): ConsumeResult => {\n\t\tconst compiled = compileRules(rules)\n\t\treturn evaluate(read(key), compiled, clock.now())\n\t}\n\n\tconst reset = (key?: string): void => {\n\t\tif (key !== undefined) {\n\t\t\tstorage.remove(storageKey(key))\n\t\t\treturn\n\t\t}\n\t\tif (typeof storage.keys !== 'function') {\n\t\t\tthrow new Error(\n\t\t\t\t'[fatigue-kit] reset() without a key requires a storage adapter implementing keys()',\n\t\t\t)\n\t\t}\n\t\tconst prefix = `${namespace}:`\n\t\tfor (const storedKey of storage.keys()) {\n\t\t\tif (storedKey.startsWith(prefix)) storage.remove(storedKey)\n\t\t}\n\t}\n\n\tconst exportRecord = (key: string): FatigueRecord | null => {\n\t\tconst raw = storage.get(storageKey(key))\n\t\treturn raw ? decodeRecord(raw) : null\n\t}\n\n\tconst importRecord = (key: string, record: Partial<FatigueRecord>): void => {\n\t\tconst hits = (record.hits ?? [])\n\t\t\t.filter((hit): hit is number => typeof hit === 'number' && Number.isFinite(hit))\n\t\t\t.sort((a, b) => a - b)\n\t\tconst lifetime =\n\t\t\ttypeof record.lifetime === 'number' &&\n\t\t\tNumber.isFinite(record.lifetime) &&\n\t\t\trecord.lifetime >= 0\n\t\t\t\t? record.lifetime\n\t\t\t\t: hits.length\n\t\tstorage.set(storageKey(key), encodeRecord({ v: RECORD_VERSION, hits, lifetime }))\n\t}\n\n\treturn { tryConsume, peek, reset, exportRecord, importRecord }\n}\n"],"mappings":"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","names":["index_exports","__export","RECORD_VERSION","createFatigue","memoryAdapter","memoryAdapter","initial","map","key","_a","value","parseCutoff","cutoff","match","hours","minutes","localMidnight","ts","date","naturalPeriodStart","spec","offset","previousNaturalStart","naturalStart","wallClockBoundary","midnight","cutoffMinutes","calendarPeriodStart","natural","boundary","JUMP_MS","calendarNextPeriodStart","jump","cursor","start","UNITS","parseDuration","duration","match","unitMs","ms","RECORD_VERSION","emptyRecord","decodeRecord","raw","parsed","e","candidate","hits","hit","a","b","lifetime","encodeRecord","record","pruneRecord","keepFrom","maxHits","first","DEFAULT_NAMESPACE","DEFAULT_MAX_HITS","assertNonEmpty","value","label","requireMax","max","compileRules","input","list","rule","_a","parseDuration","parseCutoff","outcomeFor","compiled","record","now","from","count","oldest","hit","remaining","start","calendarPeriodStart","calendarNextPeriodStart","lastHit","readyAt","evaluate","nextAvailableAt","deniedBy","outcome","result","keepFrom","keep","createFatigue","options","_b","_c","_d","storage","memoryAdapter","clock","namespace","maxHits","storageKey","key","read","decodeRecord","rules","pruneRecord","encodeRecord","prefix","storedKey","raw","hits","a","b","lifetime"]}
|