@openclaw/whatsapp 2026.7.1-beta.2 → 2026.7.1-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{access-control-88UPniDc.js → access-control-DYE5dXna.js} +5 -3
- package/dist/{accounts-DgViSyJx.js → accounts-4YgwroRU.js} +1 -1
- package/dist/{action-runtime-hqza0J8B.js → action-runtime-DPahAqxV.js} +2 -2
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/{active-listener-CFwkn3ho.js → active-listener-B4SDebQ6.js} +1 -1
- package/dist/api.js +14 -13
- package/dist/{approval-handler.runtime-9_SV7vhc.js → approval-handler.runtime-DNWS4aYQ.js} +1 -1
- package/dist/auth-presence.js +1 -1
- package/dist/{auth-store-ECx4h57q.js → auth-store-Db-wfApd.js} +23 -13
- package/dist/call-tool-api.js +233 -0
- package/dist/{channel-fcXxWXic.js → channel-BWp7h1uY.js} +44 -18
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-Dgy9uUMl.js → channel-react-action-CKJHL_Wf.js} +3 -3
- package/dist/{channel.runtime-B4ThooGF.js → channel.runtime-CAssfx9p.js} +5 -5
- package/dist/{channel.setup-C_WEdyJR.js → channel.setup-CURc5rEt.js} +2 -2
- package/dist/{config-schema-CROZuhT-.js → config-schema-mBX2nmn1.js} +4 -0
- package/dist/{connection-controller-u-tfAFhJ.js → connection-controller-DkbrFSIn.js} +6 -5
- package/dist/connection-controller-registry-TSX_udJp.js +22 -0
- package/dist/contract-api.js +1 -1
- package/dist/{quoted-message-CpA_ujXK.js → group-session-key-BhC1RQOE.js} +31 -2
- package/dist/{identity-CmsTmkKR.js → identity-Dqft3mFA.js} +2 -1
- package/dist/index.js +9 -2
- package/dist/light-runtime-api.js +3 -3
- package/dist/{login-8lHwLmXj.js → login-C48y0jlx.js} +14 -7
- package/dist/{login-qr-BEZZqrTb.js → login-qr-BjId7dll.js} +7 -7
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-BqkJ4MpT.js → monitor-DD8bXohk.js} +249 -160
- package/dist/runtime-api.js +9 -9
- package/dist/{send-i8Xk5mBQ.js → send-C5CpFcBG.js} +27 -9
- package/dist/{send-api-DndiBJhN.js → send-api-DLlXl8CH.js} +6 -5
- package/dist/{session-WU4SVP8f.js → session-DriaHt7V.js} +3 -3
- package/dist/{session-errors-CbsoQqoy.js → session-errors-BAj9D2La.js} +1 -22
- package/dist/{setup-core-KjSBbWX4.js → setup-core-DH-DFPLY.js} +4 -4
- package/dist/{setup-finalize-WedNP30s.js → setup-finalize-c8dl34sO.js} +3 -3
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-IOdkbWsQ.js → setup-surface-DlWb0Z09.js} +3 -3
- package/dist/{socket-timing-DvMNkIge.js → socket-timing-DhbVFjah.js} +17 -5
- package/dist/{text-runtime-C88QkuU9.js → targets-runtime-C-GiVn6Y.js} +2 -3
- package/dist/text-runtime-DdX6-mC_.js +4 -0
- package/node_modules/@cacheable/memory/README.md +177 -0
- package/node_modules/@cacheable/memory/dist/index.cjs +867 -820
- package/node_modules/@cacheable/memory/dist/index.d.cts +382 -280
- package/node_modules/@cacheable/memory/dist/index.d.mts +412 -0
- package/node_modules/@cacheable/memory/dist/index.mjs +841 -0
- package/node_modules/@cacheable/memory/package.json +9 -9
- package/node_modules/@cacheable/utils/README.md +342 -8
- package/node_modules/@cacheable/utils/dist/index.cjs +1322 -619
- package/node_modules/@cacheable/utils/dist/index.d.cts +769 -173
- package/node_modules/@cacheable/utils/dist/index.d.mts +903 -0
- package/node_modules/@cacheable/utils/dist/index.mjs +1355 -0
- package/node_modules/@cacheable/utils/package.json +8 -8
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/assert/strict.d.ts +10 -1
- package/node_modules/@types/node/assert.d.ts +144 -17
- package/node_modules/@types/node/async_hooks.d.ts +9 -9
- package/node_modules/@types/node/buffer.d.ts +64 -30
- package/node_modules/@types/node/child_process.d.ts +17 -21
- package/node_modules/@types/node/cluster.d.ts +13 -13
- package/node_modules/@types/node/console.d.ts +1 -1
- package/node_modules/@types/node/crypto.d.ts +471 -575
- package/node_modules/@types/node/diagnostics_channel.d.ts +274 -32
- package/node_modules/@types/node/dns.d.ts +15 -15
- package/node_modules/@types/node/events.d.ts +3 -3
- package/node_modules/@types/node/ffi.d.ts +486 -0
- package/node_modules/@types/node/fs/promises.d.ts +7 -4
- package/node_modules/@types/node/fs.d.ts +24 -18
- package/node_modules/@types/node/globals.d.ts +4 -4
- package/node_modules/@types/node/http.d.ts +30 -5
- package/node_modules/@types/node/http2.d.ts +5 -1
- package/node_modules/@types/node/index.d.ts +1 -3
- package/node_modules/@types/node/inspector.d.ts +1 -1
- package/node_modules/@types/node/module.d.ts +16 -45
- package/node_modules/@types/node/net.d.ts +1 -1
- package/node_modules/@types/node/os.d.ts +2 -2
- package/node_modules/@types/node/package.json +4 -4
- package/node_modules/@types/node/perf_hooks.d.ts +1 -9
- package/node_modules/@types/node/process.d.ts +25 -12
- package/node_modules/@types/node/quic.d.ts +92 -11
- package/node_modules/@types/node/readline.d.ts +12 -11
- package/node_modules/@types/node/repl.d.ts +10 -10
- package/node_modules/@types/node/sqlite.d.ts +56 -1
- package/node_modules/@types/node/stream/iter.d.ts +150 -0
- package/node_modules/@types/node/stream/promises.d.ts +2 -2
- package/node_modules/@types/node/stream/web.d.ts +1 -1
- package/node_modules/@types/node/stream.d.ts +37 -5
- package/node_modules/@types/node/test/reporters.d.ts +1 -1
- package/node_modules/@types/node/test.d.ts +120 -10
- package/node_modules/@types/node/tls.d.ts +1 -1
- package/node_modules/@types/node/ts5.6/index.d.ts +2 -4
- package/node_modules/@types/node/ts5.7/index.d.ts +1 -3
- package/node_modules/@types/node/url.d.ts +3 -3
- package/node_modules/@types/node/util/types.d.ts +1 -1
- package/node_modules/@types/node/util.d.ts +22 -22
- package/node_modules/@types/node/v8.d.ts +85 -3
- package/node_modules/@types/node/vm.d.ts +9 -9
- package/node_modules/@types/node/web-globals/domexception.d.ts +15 -0
- package/node_modules/@types/node/worker_threads.d.ts +10 -12
- package/node_modules/@types/node/zlib.d.ts +3 -3
- package/node_modules/cacheable/README.md +309 -30
- package/node_modules/cacheable/dist/index.cjs +1307 -1153
- package/node_modules/cacheable/dist/index.d.cts +741 -469
- package/node_modules/cacheable/dist/index.d.mts +766 -0
- package/node_modules/cacheable/dist/index.mjs +1210 -0
- package/node_modules/cacheable/package.json +10 -10
- package/node_modules/content-type/README.md +32 -57
- package/node_modules/content-type/dist/index.d.ts +26 -0
- package/node_modules/content-type/dist/index.js +170 -0
- package/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/content-type/package.json +35 -25
- package/node_modules/media-typer/README.md +19 -33
- package/node_modules/media-typer/dist/index.d.ts +29 -0
- package/node_modules/media-typer/dist/index.js +64 -0
- package/node_modules/media-typer/dist/index.js.map +1 -0
- package/node_modules/media-typer/package.json +37 -22
- package/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js +2 -2
- package/node_modules/music-metadata/lib/mp4/AtomToken.js +65 -13
- package/node_modules/music-metadata/lib/wav/WaveChunk.d.ts +10 -0
- package/node_modules/music-metadata/lib/wav/WaveChunk.js +13 -3
- package/node_modules/music-metadata/lib/wav/WaveParser.d.ts +1 -0
- package/node_modules/music-metadata/lib/wav/WaveParser.js +6 -5
- package/node_modules/music-metadata/package.json +5 -5
- package/node_modules/typebox/build/compile/validator.d.mts +2 -7
- package/node_modules/typebox/build/compile/validator.mjs +6 -36
- package/node_modules/typebox/build/error/errors.d.mts +1 -7
- package/node_modules/typebox/build/format/_idna.mjs +36 -6
- package/node_modules/typebox/build/format/_puny.mjs +4 -1
- package/node_modules/typebox/build/format/uuid.d.mts +2 -2
- package/node_modules/typebox/build/format/uuid.mjs +3 -3
- package/node_modules/typebox/build/guard/emit.d.mts +0 -4
- package/node_modules/typebox/build/guard/emit.mjs +0 -8
- package/node_modules/typebox/build/guard/guard.d.mts +4 -8
- package/node_modules/typebox/build/guard/guard.mjs +5 -13
- package/node_modules/typebox/build/schema/engine/boolean.d.mts +3 -3
- package/node_modules/typebox/build/schema/engine/boolean.mjs +4 -4
- package/node_modules/typebox/build/schema/engine/index.d.mts +0 -1
- package/node_modules/typebox/build/schema/engine/index.mjs +0 -1
- package/node_modules/typebox/build/schema/engine/schema.mjs +5 -10
- package/node_modules/typebox/build/schema/engine/type.mjs +14 -18
- package/node_modules/typebox/build/schema/types/dependencies.mjs +1 -1
- package/node_modules/typebox/build/schema/types/index.d.mts +0 -1
- package/node_modules/typebox/build/schema/types/index.mjs +0 -1
- package/node_modules/typebox/build/schema/types/schema.d.mts +1 -1
- package/node_modules/typebox/build/schema/types/schema.mjs +2 -2
- package/node_modules/typebox/build/system/locale/ar_001.mjs +0 -1
- package/node_modules/typebox/build/system/locale/bn_BD.mjs +0 -1
- package/node_modules/typebox/build/system/locale/cs_CZ.mjs +0 -1
- package/node_modules/typebox/build/system/locale/de_DE.mjs +0 -1
- package/node_modules/typebox/build/system/locale/el_GR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/en_US.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_419.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_AR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_ES.mjs +0 -1
- package/node_modules/typebox/build/system/locale/es_MX.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fa_IR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fil_PH.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fr_CA.mjs +0 -1
- package/node_modules/typebox/build/system/locale/fr_FR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ha_NG.mjs +0 -1
- package/node_modules/typebox/build/system/locale/hi_IN.mjs +0 -1
- package/node_modules/typebox/build/system/locale/hu_HU.mjs +0 -1
- package/node_modules/typebox/build/system/locale/id_ID.mjs +0 -1
- package/node_modules/typebox/build/system/locale/it_IT.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ja_JP.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ko_KR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ms_MY.mjs +0 -1
- package/node_modules/typebox/build/system/locale/nl_NL.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pl_PL.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pt_BR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/pt_PT.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ro_RO.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ru_RU.mjs +0 -1
- package/node_modules/typebox/build/system/locale/sv_SE.mjs +0 -1
- package/node_modules/typebox/build/system/locale/sw_TZ.mjs +0 -1
- package/node_modules/typebox/build/system/locale/th_TH.mjs +0 -1
- package/node_modules/typebox/build/system/locale/tr_TR.mjs +0 -1
- package/node_modules/typebox/build/system/locale/uk_UA.mjs +0 -1
- package/node_modules/typebox/build/system/locale/ur_PK.mjs +0 -1
- package/node_modules/typebox/build/system/locale/vi_VN.mjs +0 -1
- package/node_modules/typebox/build/system/locale/yo_NG.mjs +0 -1
- package/node_modules/typebox/build/system/locale/zh_Hans.mjs +0 -1
- package/node_modules/typebox/build/system/locale/zh_Hant.mjs +0 -1
- package/node_modules/typebox/build/system/memory/clone.d.mts +2 -3
- package/node_modules/typebox/build/system/memory/clone.mjs +73 -26
- package/node_modules/typebox/build/system/settings/settings.d.mts +15 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +3 -1
- package/node_modules/typebox/build/type/action/_add_immutable.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_immutable.mjs +11 -0
- package/node_modules/typebox/build/type/action/_add_optional.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_optional.mjs +11 -0
- package/node_modules/typebox/build/type/action/_add_readonly.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_add_readonly.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_immutable.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_immutable.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_optional.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_optional.mjs +11 -0
- package/node_modules/typebox/build/type/action/_remove_readonly.d.mts +11 -0
- package/node_modules/typebox/build/type/action/_remove_readonly.mjs +11 -0
- package/node_modules/typebox/build/type/action/conditional.d.mts +2 -3
- package/node_modules/typebox/build/type/action/conditional.mjs +2 -1
- package/node_modules/typebox/build/type/action/index.d.mts +7 -4
- package/node_modules/typebox/build/type/action/index.mjs +7 -4
- package/node_modules/typebox/build/type/action/mapped.d.mts +2 -3
- package/node_modules/typebox/build/type/action/mapped.mjs +2 -1
- package/node_modules/typebox/build/type/action/module.d.mts +8 -7
- package/node_modules/typebox/build/type/action/module.mjs +7 -6
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +0 -5
- package/node_modules/typebox/build/type/action/readonly_object.mjs +0 -5
- package/node_modules/typebox/build/type/action/with.d.mts +11 -0
- package/node_modules/typebox/build/type/action/with.mjs +11 -0
- package/node_modules/typebox/build/type/engine/call/distribute_arguments.mjs +1 -1
- package/node_modules/typebox/build/type/engine/call/instantiate.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/call/instantiate.mjs +3 -2
- package/node_modules/typebox/build/type/engine/call/resolve_arguments.mjs +2 -2
- package/node_modules/typebox/build/type/engine/constructor_parameters/instantiate.d.mts +3 -4
- package/node_modules/typebox/build/type/engine/constructor_parameters/instantiate.mjs +2 -1
- package/node_modules/typebox/build/type/engine/cyclic/candidates.d.mts +2 -3
- package/node_modules/typebox/build/type/engine/cyclic/candidates.mjs +3 -6
- package/node_modules/typebox/build/type/engine/cyclic/check.d.mts +6 -9
- package/node_modules/typebox/build/type/engine/cyclic/check.mjs +10 -16
- package/node_modules/typebox/build/type/engine/cyclic/dependencies.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/cyclic/dependencies.mjs +9 -15
- package/node_modules/typebox/build/type/engine/cyclic/extends.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/cyclic/extends.mjs +8 -14
- package/node_modules/typebox/build/type/engine/cyclic/instantiate.d.mts +2 -5
- package/node_modules/typebox/build/type/engine/cyclic/instantiate.mjs +3 -2
- package/node_modules/typebox/build/type/engine/enum/index.d.mts +0 -1
- package/node_modules/typebox/build/type/engine/enum/index.mjs +0 -1
- package/node_modules/typebox/build/type/engine/evaluate/broaden.d.mts +1 -2
- package/node_modules/typebox/build/type/engine/evaluate/broaden.mjs +2 -6
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +10 -6
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +10 -6
- package/node_modules/typebox/build/type/engine/evaluate/distribute.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/evaluate/distribute.mjs +3 -3
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.d.mts +17 -5
- package/node_modules/typebox/build/type/engine/evaluate/evaluate.mjs +34 -8
- package/node_modules/typebox/build/type/engine/exclude/operation.d.mts +5 -6
- package/node_modules/typebox/build/type/engine/exclude/operation.mjs +11 -12
- package/node_modules/typebox/build/type/engine/extract/operation.d.mts +5 -6
- package/node_modules/typebox/build/type/engine/extract/operation.mjs +11 -12
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/index.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/index.mjs +2 -2
- package/node_modules/typebox/build/type/engine/indexable/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/indexable/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/indexable/from_enum.d.mts +3 -3
- package/node_modules/typebox/build/type/engine/indexable/from_enum.mjs +4 -4
- package/node_modules/typebox/build/type/engine/indexable/from_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/indexable/from_template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/engine/indexable/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/indexable/from_type.mjs +9 -6
- package/node_modules/typebox/build/type/engine/indexed/instantiate.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/indexed/instantiate.mjs +5 -2
- package/node_modules/typebox/build/type/engine/instantiate.d.mts +44 -31
- package/node_modules/typebox/build/type/engine/instantiate.mjs +82 -83
- package/node_modules/typebox/build/type/engine/interface/instantiate.d.mts +3 -6
- package/node_modules/typebox/build/type/engine/intrinsics/from_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/intrinsics/from_template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/engine/keyof/instantiate.d.mts +2 -1
- package/node_modules/typebox/build/type/engine/keyof/instantiate.mjs +5 -1
- package/node_modules/typebox/build/type/engine/mapped/mapped_operation.d.mts +4 -4
- package/node_modules/typebox/build/type/engine/mapped/mapped_operation.mjs +3 -3
- package/node_modules/typebox/build/type/engine/mapped/mapped_variants.d.mts +5 -4
- package/node_modules/typebox/build/type/engine/mapped/mapped_variants.mjs +10 -5
- package/node_modules/typebox/build/type/engine/module/instantiate.d.mts +7 -9
- package/node_modules/typebox/build/type/engine/module/instantiate.mjs +17 -15
- package/node_modules/typebox/build/type/engine/object/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/object/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/object/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/object/from_type.mjs +8 -5
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/optional/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/parameters/instantiate.d.mts +3 -4
- package/node_modules/typebox/build/type/engine/parameters/instantiate.mjs +2 -1
- package/node_modules/typebox/build/type/engine/partial/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/partial/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/partial/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/partial/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/partial/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/partial/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/partial/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/partial/from_type.mjs +7 -4
- package/node_modules/typebox/build/type/engine/priority/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/priority/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/priority/priority.d.mts +20 -0
- package/node_modules/typebox/build/type/engine/priority/priority.mjs +28 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +14 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_remove.d.mts +10 -0
- package/node_modules/typebox/build/type/engine/readonly/instantiate_remove.mjs +14 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_array.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_array.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/readonly_object/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/readonly_object/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_tuple.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_tuple.mjs +2 -2
- package/node_modules/typebox/build/type/engine/readonly_object/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/readonly_object/from_type.mjs +8 -5
- package/node_modules/typebox/build/type/engine/record/from_key_enum.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_enum.mjs +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_template_literal.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/record/from_key_template_literal.mjs +2 -2
- package/node_modules/typebox/build/type/engine/ref/instantiate.d.mts +3 -3
- package/node_modules/typebox/build/type/engine/ref/instantiate.mjs +6 -6
- package/node_modules/typebox/build/type/engine/required/from_dependent.d.mts +5 -0
- package/node_modules/typebox/build/type/engine/required/from_dependent.mjs +8 -0
- package/node_modules/typebox/build/type/engine/required/from_intersect.d.mts +1 -1
- package/node_modules/typebox/build/type/engine/required/from_intersect.mjs +3 -2
- package/node_modules/typebox/build/type/engine/required/from_object.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/required/from_object.mjs +2 -2
- package/node_modules/typebox/build/type/engine/required/from_type.d.mts +3 -1
- package/node_modules/typebox/build/type/engine/required/from_type.mjs +7 -4
- package/node_modules/typebox/build/type/engine/template_literal/decode.mjs +3 -3
- package/node_modules/typebox/build/type/engine/template_literal/encode.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/template_literal/encode.mjs +6 -6
- package/node_modules/typebox/build/type/engine/template_literal/is_finite.mjs +1 -1
- package/node_modules/typebox/build/type/engine/template_literal/is_pattern.mjs +1 -0
- package/node_modules/typebox/build/type/engine/this/expand_this.d.mts +1 -4
- package/node_modules/typebox/build/type/engine/this/expand_this.mjs +7 -13
- package/node_modules/typebox/build/type/engine/with/instantiate.d.mts +8 -0
- package/node_modules/typebox/build/type/engine/{options → with}/instantiate.mjs +5 -5
- package/node_modules/typebox/build/type/extends/dependent.d.mts +6 -0
- package/node_modules/typebox/build/type/extends/dependent.mjs +6 -0
- package/node_modules/typebox/build/type/extends/enum.d.mts +4 -4
- package/node_modules/typebox/build/type/extends/enum.mjs +3 -2
- package/node_modules/typebox/build/type/extends/extends_left.d.mts +5 -7
- package/node_modules/typebox/build/type/extends/extends_left.mjs +24 -27
- package/node_modules/typebox/build/type/extends/extends_right.d.mts +7 -5
- package/node_modules/typebox/build/type/extends/extends_right.mjs +20 -15
- package/node_modules/typebox/build/type/extends/inference.mjs +1 -1
- package/node_modules/typebox/build/type/extends/object.d.mts +8 -1
- package/node_modules/typebox/build/type/extends/object.mjs +25 -3
- package/node_modules/typebox/build/type/extends/parameters.mjs +2 -2
- package/node_modules/typebox/build/type/extends/record.d.mts +13 -0
- package/node_modules/typebox/build/type/extends/record.mjs +23 -0
- package/node_modules/typebox/build/type/extends/template_literal.d.mts +3 -3
- package/node_modules/typebox/build/type/extends/template_literal.mjs +3 -3
- package/node_modules/typebox/build/type/extends/tuple.d.mts +3 -6
- package/node_modules/typebox/build/type/extends/tuple.mjs +6 -5
- package/node_modules/typebox/build/type/extends/union.mjs +2 -2
- package/node_modules/typebox/build/type/script/mapping.d.mts +84 -99
- package/node_modules/typebox/build/type/script/mapping.mjs +81 -85
- package/node_modules/typebox/build/type/script/parser.d.mts +40 -40
- package/node_modules/typebox/build/type/script/parser.mjs +22 -22
- package/node_modules/typebox/build/type/script/script.d.mts +3 -4
- package/node_modules/typebox/build/type/script/script.mjs +3 -2
- package/node_modules/typebox/build/type/script/token/internal/guard.d.mts +1 -1
- package/node_modules/typebox/build/type/script/token/internal/guard.mjs +1 -1
- package/node_modules/typebox/build/type/script/token/internal/take.mjs +1 -1
- package/node_modules/typebox/build/type/script/token/until.mjs +2 -2
- package/node_modules/typebox/build/type/types/_codec.d.mts +12 -12
- package/node_modules/typebox/build/type/types/_codec.mjs +0 -1
- package/node_modules/typebox/build/type/types/_immutable.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_immutable.mjs +2 -10
- package/node_modules/typebox/build/type/types/_optional.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_optional.mjs +2 -11
- package/node_modules/typebox/build/type/types/_readonly.d.mts +2 -9
- package/node_modules/typebox/build/type/types/_readonly.mjs +2 -10
- package/node_modules/typebox/build/type/types/_refine.d.mts +8 -10
- package/node_modules/typebox/build/type/types/_refine.mjs +1 -2
- package/node_modules/typebox/build/type/types/call.d.mts +3 -3
- package/node_modules/typebox/build/type/types/call.mjs +3 -2
- package/node_modules/typebox/build/type/types/deferred.d.mts +1 -0
- package/node_modules/typebox/build/type/types/deferred.mjs +1 -1
- package/node_modules/typebox/build/type/types/dependent.d.mts +17 -0
- package/node_modules/typebox/build/type/types/dependent.mjs +24 -0
- package/node_modules/typebox/build/type/types/enum.d.mts +3 -1
- package/node_modules/typebox/build/type/types/enum.mjs +5 -0
- package/node_modules/typebox/build/type/types/index.d.mts +1 -4
- package/node_modules/typebox/build/type/types/index.mjs +1 -4
- package/node_modules/typebox/build/type/types/number.d.mts +1 -1
- package/node_modules/typebox/build/type/types/number.mjs +1 -1
- package/node_modules/typebox/build/type/types/record.d.mts +13 -7
- package/node_modules/typebox/build/type/types/record.mjs +15 -9
- package/node_modules/typebox/build/type/types/static.d.mts +2 -5
- package/node_modules/typebox/build/typebox.d.mts +4 -8
- package/node_modules/typebox/build/typebox.mjs +4 -8
- package/node_modules/typebox/build/value/clean/clean.mjs +4 -2
- package/node_modules/typebox/build/value/clean/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/value/clean/from_type.mjs +8 -10
- package/node_modules/typebox/build/value/clean/from_union.d.mts +1 -1
- package/node_modules/typebox/build/value/clean/from_union.mjs +1 -2
- package/node_modules/typebox/build/value/clone/clone.mjs +2 -73
- package/node_modules/typebox/build/value/codec/decode.mjs +4 -2
- package/node_modules/typebox/build/value/codec/encode.mjs +4 -2
- package/node_modules/typebox/build/value/codec/from_array.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_object.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_record.mjs +2 -7
- package/node_modules/typebox/build/value/codec/from_tuple.mjs +1 -4
- package/node_modules/typebox/build/value/codec/from_union.mjs +2 -3
- package/node_modules/typebox/build/value/convert/from_enum.mjs +3 -4
- package/node_modules/typebox/build/value/convert/from_template_literal.d.mts +1 -1
- package/node_modules/typebox/build/value/convert/from_template_literal.mjs +2 -3
- package/node_modules/typebox/build/value/convert/from_type.mjs +19 -21
- package/node_modules/typebox/build/value/create/from_enum.mjs +2 -2
- package/node_modules/typebox/build/value/create/from_type.mjs +23 -31
- package/node_modules/typebox/build/value/default/from_object.mjs +1 -1
- package/node_modules/typebox/build/value/default/from_type.mjs +8 -10
- package/node_modules/typebox/build/value/index.d.mts +0 -1
- package/node_modules/typebox/build/value/index.mjs +0 -1
- package/node_modules/typebox/build/value/repair/from_enum.mjs +2 -3
- package/node_modules/typebox/build/value/repair/from_type.mjs +24 -22
- package/node_modules/typebox/build/value/shared/union_priority_sort.d.mts +6 -2
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +62 -26
- package/node_modules/typebox/build/value/value.d.mts +0 -1
- package/node_modules/typebox/build/value/value.mjs +0 -1
- package/node_modules/typebox/package.json +25 -25
- package/node_modules/typebox/readme.md +97 -80
- package/node_modules/undici-types/agent.d.ts +0 -2
- package/node_modules/undici-types/client.d.ts +25 -19
- package/node_modules/undici-types/dispatcher.d.ts +7 -33
- package/node_modules/undici-types/dispatcher1-wrapper.d.ts +7 -0
- package/node_modules/undici-types/fetch.d.ts +24 -4
- package/node_modules/undici-types/h2c-client.d.ts +6 -6
- package/node_modules/undici-types/handlers.d.ts +1 -2
- package/node_modules/undici-types/header.d.ts +5 -0
- package/node_modules/undici-types/index.d.ts +3 -1
- package/node_modules/undici-types/interceptors.d.ts +1 -1
- package/node_modules/undici-types/package.json +1 -1
- package/node_modules/undici-types/pool.d.ts +0 -2
- package/node_modules/undici-types/proxy-agent.d.ts +2 -2
- package/node_modules/undici-types/round-robin-pool.d.ts +0 -2
- package/node_modules/undici-types/snapshot-agent.d.ts +4 -0
- package/node_modules/undici-types/socks5-proxy-agent.d.ts +2 -2
- package/node_modules/undici-types/webidl.d.ts +0 -1
- package/npm-shrinkwrap.json +49 -41
- package/openclaw.plugin.json +12 -0
- package/package.json +5 -5
- package/node_modules/@cacheable/memory/dist/index.d.ts +0 -310
- package/node_modules/@cacheable/memory/dist/index.js +0 -807
- package/node_modules/@cacheable/utils/dist/index.d.ts +0 -307
- package/node_modules/@cacheable/utils/dist/index.js +0 -630
- package/node_modules/@types/node/compatibility/iterators.d.ts +0 -21
- package/node_modules/cacheable/dist/index.d.ts +0 -494
- package/node_modules/cacheable/dist/index.js +0 -1141
- package/node_modules/content-type/HISTORY.md +0 -29
- package/node_modules/content-type/index.js +0 -225
- package/node_modules/media-typer/HISTORY.md +0 -50
- package/node_modules/media-typer/index.js +0 -143
- package/node_modules/typebox/build/schema/engine/_guard.d.mts +0 -6
- package/node_modules/typebox/build/schema/engine/_guard.mjs +0 -26
- package/node_modules/typebox/build/schema/types/_guard.d.mts +0 -10
- package/node_modules/typebox/build/schema/types/_guard.mjs +0 -16
- package/node_modules/typebox/build/type/action/_optional.d.mts +0 -19
- package/node_modules/typebox/build/type/action/_optional.mjs +0 -40
- package/node_modules/typebox/build/type/action/_readonly.d.mts +0 -19
- package/node_modules/typebox/build/type/action/_readonly.mjs +0 -40
- package/node_modules/typebox/build/type/action/awaited.d.mts +0 -15
- package/node_modules/typebox/build/type/action/awaited.mjs +0 -15
- package/node_modules/typebox/build/type/action/options.d.mts +0 -11
- package/node_modules/typebox/build/type/action/options.mjs +0 -11
- package/node_modules/typebox/build/type/engine/awaited/instantiate.d.mts +0 -11
- package/node_modules/typebox/build/type/engine/awaited/instantiate.mjs +0 -20
- package/node_modules/typebox/build/type/engine/enum/enum_to_union.d.mts +0 -14
- package/node_modules/typebox/build/type/engine/enum/enum_to_union.mjs +0 -24
- package/node_modules/typebox/build/type/engine/options/index.d.mts +0 -1
- package/node_modules/typebox/build/type/engine/options/index.mjs +0 -1
- package/node_modules/typebox/build/type/engine/options/instantiate.d.mts +0 -8
- package/node_modules/typebox/build/type/extends/async_iterator.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/async_iterator.mjs +0 -9
- package/node_modules/typebox/build/type/extends/iterator.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/iterator.mjs +0 -9
- package/node_modules/typebox/build/type/extends/promise.d.mts +0 -7
- package/node_modules/typebox/build/type/extends/promise.mjs +0 -9
- package/node_modules/typebox/build/type/types/async_iterator.d.mts +0 -20
- package/node_modules/typebox/build/type/types/async_iterator.mjs +0 -28
- package/node_modules/typebox/build/type/types/base.d.mts +0 -50
- package/node_modules/typebox/build/type/types/base.mjs +0 -84
- package/node_modules/typebox/build/type/types/iterator.d.mts +0 -20
- package/node_modules/typebox/build/type/types/iterator.mjs +0 -28
- package/node_modules/typebox/build/type/types/promise.d.mts +0 -21
- package/node_modules/typebox/build/type/types/promise.mjs +0 -29
- package/node_modules/typebox/build/value/clean/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/clean/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/convert/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/convert/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/create/from_async_iterator.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_async_iterator.mjs +0 -5
- package/node_modules/typebox/build/value/create/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_base.mjs +0 -4
- package/node_modules/typebox/build/value/create/from_iterator.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_iterator.mjs +0 -5
- package/node_modules/typebox/build/value/create/from_promise.d.mts +0 -2
- package/node_modules/typebox/build/value/create/from_promise.mjs +0 -5
- package/node_modules/typebox/build/value/default/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/default/from_base.mjs +0 -5
- package/node_modules/typebox/build/value/mutate/error.d.mts +0 -3
- package/node_modules/typebox/build/value/mutate/error.mjs +0 -6
- package/node_modules/typebox/build/value/mutate/from_array.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_array.mjs +0 -16
- package/node_modules/typebox/build/value/mutate/from_object.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_object.mjs +0 -40
- package/node_modules/typebox/build/value/mutate/from_unknown.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_unknown.mjs +0 -7
- package/node_modules/typebox/build/value/mutate/from_value.d.mts +0 -2
- package/node_modules/typebox/build/value/mutate/from_value.mjs +0 -12
- package/node_modules/typebox/build/value/mutate/index.d.mts +0 -1
- package/node_modules/typebox/build/value/mutate/index.mjs +0 -1
- package/node_modules/typebox/build/value/mutate/mutate.d.mts +0 -11
- package/node_modules/typebox/build/value/mutate/mutate.mjs +0 -41
- package/node_modules/typebox/build/value/repair/from_base.d.mts +0 -2
- package/node_modules/typebox/build/value/repair/from_base.mjs +0 -8
- package/dist/{approval-resolver-e1hAVRRy.js → approval-resolver-DF-lu8k5.js} +1 -1
- /package/node_modules/typebox/build/type/engine/{awaited → with}/index.d.mts +0 -0
- /package/node_modules/typebox/build/type/engine/{awaited → with}/index.mjs +0 -0
|
@@ -1,677 +1,1380 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let hashery = require("hashery");
|
|
3
|
+
let keyv = require("keyv");
|
|
4
|
+
//#region src/shorthand-time.ts
|
|
5
|
+
/**
|
|
6
|
+
* Converts a shorthand time string or number into milliseconds.
|
|
7
|
+
* The shorthand can be a string like '1s', '2m', '3h', '4d', or a number representing milliseconds.
|
|
8
|
+
* If the input is undefined, it returns undefined.
|
|
9
|
+
* If the input is a string that does not match the expected format, it throws an error.
|
|
10
|
+
* @param shorthand - A shorthand time string or number representing milliseconds.
|
|
11
|
+
* @returns The equivalent time in milliseconds or undefined.
|
|
12
|
+
*/
|
|
13
|
+
const shorthandToMilliseconds = (shorthand) => {
|
|
14
|
+
let milliseconds;
|
|
15
|
+
if (shorthand === void 0) return;
|
|
16
|
+
if (typeof shorthand === "number") milliseconds = shorthand;
|
|
17
|
+
else {
|
|
18
|
+
if (typeof shorthand !== "string") return;
|
|
19
|
+
shorthand = shorthand.trim();
|
|
20
|
+
if (Number.isNaN(Number(shorthand))) {
|
|
21
|
+
const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand);
|
|
22
|
+
if (!match) throw new Error(`Unsupported time format: "${shorthand}". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.`);
|
|
23
|
+
const [, value, unit] = match;
|
|
24
|
+
const numericValue = Number.parseFloat(value);
|
|
25
|
+
switch (unit.toLowerCase()) {
|
|
26
|
+
case "ms":
|
|
27
|
+
milliseconds = numericValue;
|
|
28
|
+
break;
|
|
29
|
+
case "s":
|
|
30
|
+
milliseconds = numericValue * 1e3;
|
|
31
|
+
break;
|
|
32
|
+
case "m":
|
|
33
|
+
milliseconds = numericValue * 1e3 * 60;
|
|
34
|
+
break;
|
|
35
|
+
case "h":
|
|
36
|
+
milliseconds = numericValue * 1e3 * 60 * 60;
|
|
37
|
+
break;
|
|
38
|
+
case "hr":
|
|
39
|
+
milliseconds = numericValue * 1e3 * 60 * 60;
|
|
40
|
+
break;
|
|
41
|
+
case "d":
|
|
42
|
+
milliseconds = numericValue * 1e3 * 60 * 60 * 24;
|
|
43
|
+
break;
|
|
44
|
+
/* v8 ignore next -- @preserve */
|
|
45
|
+
default: milliseconds = Number(shorthand);
|
|
46
|
+
}
|
|
47
|
+
} else milliseconds = Number(shorthand);
|
|
48
|
+
}
|
|
49
|
+
return milliseconds;
|
|
9
50
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Converts a shorthand time string or number into a timestamp.
|
|
53
|
+
* If the shorthand is undefined, it returns the current date's timestamp.
|
|
54
|
+
* If the shorthand is a valid time format, it adds that duration to the current date's timestamp.
|
|
55
|
+
* @param shorthand - A shorthand time string or number representing milliseconds.
|
|
56
|
+
* @param fromDate - An optional Date object to calculate from. Defaults to the current date if not provided.
|
|
57
|
+
* @returns The timestamp in milliseconds since epoch.
|
|
58
|
+
*/
|
|
59
|
+
const shorthandToTime = (shorthand, fromDate) => {
|
|
60
|
+
fromDate ??= /* @__PURE__ */ new Date();
|
|
61
|
+
const milliseconds = shorthandToMilliseconds(shorthand);
|
|
62
|
+
if (milliseconds === void 0) return fromDate.getTime();
|
|
63
|
+
return fromDate.getTime() + milliseconds;
|
|
17
64
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/cache-tags.ts
|
|
67
|
+
/**
|
|
68
|
+
* Prefix applied to every store key written by the service so its metadata cannot collide with
|
|
69
|
+
* user-supplied cache keys.
|
|
70
|
+
*/
|
|
71
|
+
const RESERVED_PREFIX = "--cacheable--tags--";
|
|
72
|
+
/** Namespace used when none is supplied to the constructor. */
|
|
73
|
+
const DEFAULT_NAMESPACE = "default";
|
|
74
|
+
/**
|
|
75
|
+
* Provides tag-based cache invalidation on top of any {@link Keyv} store. It is store-agnostic and
|
|
76
|
+
* requires no adapter changes.
|
|
77
|
+
*
|
|
78
|
+
* The service uses a lazy invalidation model rather than scanning and deleting keys. Each tag has a
|
|
79
|
+
* monotonically increasing version counter; {@link CacheTags.invalidateTag} simply increments
|
|
80
|
+
* it. When a key is tagged via {@link CacheTags.setKeyTags}, a snapshot of its tags' current
|
|
81
|
+
* versions is stored alongside it. {@link CacheTags.isKeyFresh} compares that snapshot against
|
|
82
|
+
* the live versions — if any tag has been incremented since, the key is considered stale. Stale
|
|
83
|
+
* entries are not deleted explicitly; they are expected to fall out of the cache via their TTL.
|
|
84
|
+
*
|
|
85
|
+
* This keeps invalidation constant-time regardless of how many keys reference a tag, at the cost of
|
|
86
|
+
* one additional `isKeyFresh` read per cache lookup.
|
|
87
|
+
*
|
|
88
|
+
* The service can be disabled via the `enabled` option or property so integrations pay no cost for
|
|
89
|
+
* untagged workloads: while disabled, every method is a no-op — reads return their neutral value
|
|
90
|
+
* and writes are skipped. The service must be explicitly enabled to use tags; it never enables
|
|
91
|
+
* itself, which keeps behavior consistent across distributed instances sharing a store.
|
|
92
|
+
*
|
|
93
|
+
* All metadata is written under a reserved prefix so it cannot collide with user keys:
|
|
94
|
+
* - `--cacheable--tags--:<namespace>:tag:<tag>` → integer version counter (stored without TTL).
|
|
95
|
+
* - `--cacheable--tags--:<namespace>:key:<key>` → the {@link KeyTagEntry} snapshot.
|
|
96
|
+
*
|
|
97
|
+
* Note: the read-version-then-write-snapshot sequence in `setKeyTags` is not atomic across
|
|
98
|
+
* processes. A concurrent `invalidateTag` running between the read and the write can leave a freshly
|
|
99
|
+
* written key referencing a stale version.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const cacheTags = new CacheTags({ store: new Keyv(), namespace: 'app' });
|
|
104
|
+
* await cacheTags.setKeyTags('user:42', ['users', 'org:7'], { ttl: 3600000 });
|
|
105
|
+
* await cacheTags.isKeyFresh('user:42'); // true
|
|
106
|
+
* await cacheTags.invalidateTag('users');
|
|
107
|
+
* await cacheTags.isKeyFresh('user:42'); // false
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
var CacheTags = class {
|
|
111
|
+
_store;
|
|
112
|
+
_namespace;
|
|
113
|
+
_enabled;
|
|
114
|
+
_onError;
|
|
115
|
+
/**
|
|
116
|
+
* Creates a new tag service.
|
|
117
|
+
* @param {CacheTagsOptions} options - The store, optional namespace, enabled state, and
|
|
118
|
+
* non-blocking error handler to use.
|
|
119
|
+
*/
|
|
120
|
+
constructor(options) {
|
|
121
|
+
this._store = options.store;
|
|
122
|
+
this._namespace = options.namespace ?? DEFAULT_NAMESPACE;
|
|
123
|
+
this._enabled = options.enabled ?? true;
|
|
124
|
+
this._onError = options.onError;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The Keyv store backing this service.
|
|
128
|
+
* @returns {Keyv} The store provided to the constructor.
|
|
129
|
+
*/
|
|
130
|
+
get store() {
|
|
131
|
+
return this._store;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The namespace isolating this service's tags and keys within the store.
|
|
135
|
+
* @returns {string} The configured namespace, or `"default"` if none was provided.
|
|
136
|
+
*/
|
|
137
|
+
get namespace() {
|
|
138
|
+
return this._namespace;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Whether the service is enabled. While disabled, every method is a no-op — read methods
|
|
142
|
+
* return their neutral value and writes are skipped — so integrations pay no extra store
|
|
143
|
+
* reads for untagged workloads. The service must be explicitly enabled to use tags; it never
|
|
144
|
+
* enables itself.
|
|
145
|
+
* @returns {boolean} Whether the service is enabled.
|
|
146
|
+
*/
|
|
147
|
+
get enabled() {
|
|
148
|
+
return this._enabled;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Sets whether the service is enabled.
|
|
152
|
+
* @param {boolean} enabled Whether the service is enabled.
|
|
153
|
+
*/
|
|
154
|
+
set enabled(enabled) {
|
|
155
|
+
this._enabled = enabled;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Builds the reserved store key under which a tag's version counter is stored.
|
|
159
|
+
* @param tag - The tag name.
|
|
160
|
+
* @returns {string} The namespaced store key for the tag's version.
|
|
161
|
+
*/
|
|
162
|
+
tagKey(tag) {
|
|
163
|
+
return `${RESERVED_PREFIX}:${this._namespace}:tag:${tag}`;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Builds the reserved store key under which a cache key's tag snapshot is stored.
|
|
167
|
+
* @param key - The cache key being tagged.
|
|
168
|
+
* @returns {string} The namespaced store key for the key's snapshot.
|
|
169
|
+
*/
|
|
170
|
+
keyEntryKey(key) {
|
|
171
|
+
return `${RESERVED_PREFIX}:${this._namespace}:key:${key}`;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Builds the common prefix shared by every key-snapshot entry in this namespace. Used to filter
|
|
175
|
+
* key entries when iterating the store.
|
|
176
|
+
* @returns {string} The namespaced key-entry prefix.
|
|
177
|
+
*/
|
|
178
|
+
keyPrefix() {
|
|
179
|
+
return `${RESERVED_PREFIX}:${this._namespace}:key:`;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Reads the current version of a single tag.
|
|
183
|
+
* @param tag - The tag name.
|
|
184
|
+
* @returns {Promise<number>} The tag's version, or `0` if it has never been invalidated.
|
|
185
|
+
*/
|
|
186
|
+
async getTagVersion(tag) {
|
|
187
|
+
const version = await this._store.get(this.tagKey(tag));
|
|
188
|
+
return typeof version === "number" ? version : 0;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Reads the current versions of multiple tags in a single batched store read.
|
|
192
|
+
* @param tags - The tag names to look up.
|
|
193
|
+
* @returns {Promise<number[]>} The versions in the same order as `tags`; entries that have never
|
|
194
|
+
* been invalidated resolve to `0`. Returns an empty array when `tags` is empty.
|
|
195
|
+
*/
|
|
196
|
+
async getTagVersions(tags) {
|
|
197
|
+
if (tags.length === 0) return [];
|
|
198
|
+
const tagKeys = tags.map((tag) => this.tagKey(tag));
|
|
199
|
+
const raw = await this._store.get(tagKeys);
|
|
200
|
+
return tags.map((_, i) => {
|
|
201
|
+
const value = raw?.[i];
|
|
202
|
+
return typeof value === "number" ? value : 0;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Reports a fire-and-forget failure to the `onError` handler, if one was provided.
|
|
207
|
+
* @param error - The error raised by the non-blocking operation.
|
|
208
|
+
*/
|
|
209
|
+
handleNonBlockingError(error) {
|
|
210
|
+
this._onError?.(error);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Reads the version snapshot of each tag and writes the key's tag snapshot to the store.
|
|
214
|
+
* @param key - The cache key to tag.
|
|
215
|
+
* @param tags - The tags to associate with the key.
|
|
216
|
+
* @param ttl - Time-to-live in milliseconds for the snapshot.
|
|
217
|
+
* @returns {Promise<void>} Resolves once the snapshot has been written.
|
|
218
|
+
*/
|
|
219
|
+
async writeKeyTags(key, tags, ttl) {
|
|
220
|
+
const uniqueTags = [...new Set(tags)];
|
|
221
|
+
const versions = await this.getTagVersions(uniqueTags);
|
|
222
|
+
const snapshot = {};
|
|
223
|
+
for (let i = 0; i < uniqueTags.length; i++) snapshot[uniqueTags[i]] = versions[i];
|
|
224
|
+
const entry = { tags: snapshot };
|
|
225
|
+
await this._store.set(this.keyEntryKey(key), entry, ttl);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Associates a cache key with a set of tags by recording a snapshot of each tag's current
|
|
229
|
+
* version. Call this whenever you write a fresh value to the cache. Duplicate tags are ignored.
|
|
230
|
+
* No-op while the service is disabled.
|
|
231
|
+
* @param key - The cache key to tag.
|
|
232
|
+
* @param tags - The tags to associate with the key.
|
|
233
|
+
* @param {SetKeyTagsOptions} [options] - Optional settings, such as a `ttl` for the snapshot or
|
|
234
|
+
* `nonBlocking` to fire-and-forget the write.
|
|
235
|
+
* @returns {Promise<void>} Resolves once the snapshot has been written, or immediately when
|
|
236
|
+
* `nonBlocking` is set.
|
|
237
|
+
*/
|
|
238
|
+
async setKeyTags(key, tags, options) {
|
|
239
|
+
if (!this._enabled) return;
|
|
240
|
+
const work = this.writeKeyTags(key, tags, options?.ttl);
|
|
241
|
+
if (options?.nonBlocking) {
|
|
242
|
+
work.catch((error) => {
|
|
243
|
+
this.handleNonBlockingError(error);
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
await work;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Removes a key's tag snapshot. After this, {@link CacheTags.isKeyFresh} returns `false`
|
|
251
|
+
* for the key. Use when the cached value itself is deleted. No-op while the service is
|
|
252
|
+
* disabled.
|
|
253
|
+
* @param key - The cache key whose snapshot should be removed.
|
|
254
|
+
* @param {RemoveKeysOptions} [options] - Optional settings, such as `nonBlocking` to
|
|
255
|
+
* fire-and-forget the removal.
|
|
256
|
+
* @returns {Promise<void>} Resolves once the snapshot has been deleted, or immediately when
|
|
257
|
+
* `nonBlocking` is set.
|
|
258
|
+
*/
|
|
259
|
+
async removeKey(key, options) {
|
|
260
|
+
await this.removeKeys([key], options);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Removes multiple keys' tag snapshots in a single batched store delete. After this,
|
|
264
|
+
* {@link CacheTags.isKeyFresh} returns `false` for each key. An empty list is a no-op, as is
|
|
265
|
+
* the entire call while the service is disabled.
|
|
266
|
+
* @param keys - The cache keys whose snapshots should be removed.
|
|
267
|
+
* @param {RemoveKeysOptions} [options] - Optional settings, such as `nonBlocking` to
|
|
268
|
+
* fire-and-forget the removal.
|
|
269
|
+
* @returns {Promise<void>} Resolves once the snapshots have been deleted, or immediately when
|
|
270
|
+
* `nonBlocking` is set.
|
|
271
|
+
*/
|
|
272
|
+
async removeKeys(keys, options) {
|
|
273
|
+
if (!this._enabled || keys.length === 0) return;
|
|
274
|
+
const entryKeys = keys.map((key) => this.keyEntryKey(key));
|
|
275
|
+
const work = this._store.deleteMany(entryKeys);
|
|
276
|
+
if (options?.nonBlocking) {
|
|
277
|
+
work.catch((error) => {
|
|
278
|
+
this.handleNonBlockingError(error);
|
|
279
|
+
});
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
await work;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Determines whether a key's cached value can still be trusted. A key is fresh only when a
|
|
286
|
+
* snapshot exists for it and every tag in that snapshot still has the version it had at set time.
|
|
287
|
+
* A key with no tags is trivially fresh. Call this before returning a value from your cache.
|
|
288
|
+
* Always returns `true` while the service is disabled.
|
|
289
|
+
* @param key - The cache key to check.
|
|
290
|
+
* @returns {Promise<boolean>} `true` if the key is still fresh; `false` if it is unknown or any of
|
|
291
|
+
* its tags has been invalidated since the snapshot was taken.
|
|
292
|
+
*/
|
|
293
|
+
async isKeyFresh(key) {
|
|
294
|
+
if (!this._enabled) return true;
|
|
295
|
+
const entry = await this._store.get(this.keyEntryKey(key));
|
|
296
|
+
if (!entry?.tags) return false;
|
|
297
|
+
const tags = Object.keys(entry.tags);
|
|
298
|
+
const currentVersions = await this.getTagVersions(tags);
|
|
299
|
+
for (let i = 0; i < tags.length; i++) if (currentVersions[i] !== entry.tags[tags[i]]) return false;
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Determines whether a key's cached value is known to be stale due to tag invalidation. This is
|
|
304
|
+
* the complement of {@link CacheTags.isKeyFresh} for tagged keys, but treats keys without a
|
|
305
|
+
* snapshot as not stale — making it safe to call for every cache lookup, including keys that were
|
|
306
|
+
* never tagged. Always returns `false` while the service is disabled.
|
|
307
|
+
* @param key - The cache key to check.
|
|
308
|
+
* @returns {Promise<boolean>} `true` only when a snapshot exists for the key and at least one of
|
|
309
|
+
* its tags has been invalidated since the snapshot was taken; `false` otherwise (including when
|
|
310
|
+
* the key has no snapshot).
|
|
311
|
+
*/
|
|
312
|
+
async isKeyStale(key) {
|
|
313
|
+
if (!this._enabled) return false;
|
|
314
|
+
return (await this.getStaleKeys([key])).length > 0;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Determines which of the given keys are known to be stale due to tag invalidation, using two
|
|
318
|
+
* batched store reads regardless of how many keys are checked: one for the snapshots and one for
|
|
319
|
+
* the union of their tag versions. Keys without a snapshot are not considered stale. Returns an
|
|
320
|
+
* empty array while the service is disabled.
|
|
321
|
+
* @param keys - The cache keys to check.
|
|
322
|
+
* @returns {Promise<string[]>} The subset of `keys` whose snapshot references at least one tag
|
|
323
|
+
* that has been invalidated since the snapshot was taken.
|
|
324
|
+
*/
|
|
325
|
+
async getStaleKeys(keys) {
|
|
326
|
+
if (!this._enabled || keys.length === 0) return [];
|
|
327
|
+
const entryKeys = keys.map((key) => this.keyEntryKey(key));
|
|
328
|
+
const entries = await this._store.get(entryKeys);
|
|
329
|
+
const tagSet = /* @__PURE__ */ new Set();
|
|
330
|
+
for (const entry of entries) if (entry?.tags) for (const tag of Object.keys(entry.tags)) tagSet.add(tag);
|
|
331
|
+
const tags = [...tagSet];
|
|
332
|
+
const versions = await this.getTagVersions(tags);
|
|
333
|
+
const currentVersions = /* @__PURE__ */ new Map();
|
|
334
|
+
for (let i = 0; i < tags.length; i++) currentVersions.set(tags[i], versions[i]);
|
|
335
|
+
const staleKeys = [];
|
|
336
|
+
for (const [i, entry] of entries.entries()) {
|
|
337
|
+
if (!entry?.tags) continue;
|
|
338
|
+
for (const [tag, version] of Object.entries(entry.tags)) if (currentVersions.get(tag) !== version) {
|
|
339
|
+
staleKeys.push(keys[i]);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return staleKeys;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Returns the tags currently associated with a key. Returns `undefined` while the service is
|
|
347
|
+
* disabled.
|
|
348
|
+
* @param key - The cache key to look up.
|
|
349
|
+
* @returns {Promise<string[] | undefined>} The tag names from the key's snapshot, or `undefined`
|
|
350
|
+
* if the key has no snapshot.
|
|
351
|
+
*/
|
|
352
|
+
async getTags(key) {
|
|
353
|
+
if (!this._enabled) return;
|
|
354
|
+
const entry = await this._store.get(this.keyEntryKey(key));
|
|
355
|
+
if (!entry?.tags) return;
|
|
356
|
+
return Object.keys(entry.tags);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Returns all cache keys whose snapshot references the given tag. This scans every key entry in
|
|
360
|
+
* the namespace via the Keyv iterator, making it an `O(N)` operation intended for debugging and
|
|
361
|
+
* tests rather than hot paths. Returns an empty array if the underlying store exposes no iterator
|
|
362
|
+
* or while the service is disabled.
|
|
363
|
+
* @param tag - The tag to search for.
|
|
364
|
+
* @returns {Promise<string[]>} The cache keys (with the reserved prefix stripped) referencing the tag.
|
|
365
|
+
*/
|
|
366
|
+
async getKeysByTag(tag) {
|
|
367
|
+
const result = [];
|
|
368
|
+
if (!this._enabled) return result;
|
|
369
|
+
const prefix = this.keyPrefix();
|
|
370
|
+
const iterator = this._store.iterator?.(this._store.namespace);
|
|
371
|
+
if (!iterator) return result;
|
|
372
|
+
for await (const [storedKey, value] of iterator) {
|
|
373
|
+
if (typeof storedKey !== "string" || !storedKey.startsWith(prefix)) continue;
|
|
374
|
+
const entry = value;
|
|
375
|
+
if (entry?.tags && Object.hasOwn(entry.tags, tag)) result.push(storedKey.slice(prefix.length));
|
|
376
|
+
}
|
|
377
|
+
return result;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Invalidates a single tag by incrementing its version counter. Every key whose snapshot
|
|
381
|
+
* references this tag becomes stale immediately. Runs in constant time regardless of how many
|
|
382
|
+
* keys reference the tag. No-op while the service is disabled.
|
|
383
|
+
* @param tag - The tag to invalidate.
|
|
384
|
+
* @returns {Promise<string[]>} A single-element array containing the invalidated tag, or an
|
|
385
|
+
* empty array while the service is disabled.
|
|
386
|
+
*/
|
|
387
|
+
async invalidateTag(tag) {
|
|
388
|
+
if (!this._enabled) return [];
|
|
389
|
+
const current = await this.getTagVersion(tag);
|
|
390
|
+
await this._store.set(this.tagKey(tag), current + 1);
|
|
391
|
+
return [tag];
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Invalidates multiple tags by incrementing each of their version counters in a single batched
|
|
395
|
+
* store write. Duplicate tags are bumped once. An empty list is a no-op, as is the entire call
|
|
396
|
+
* while the service is disabled.
|
|
397
|
+
* @param tags - The tags to invalidate.
|
|
398
|
+
* @returns {Promise<string[]>} The `tags` argument as provided (including any duplicates), or
|
|
399
|
+
* an empty array while the service is disabled.
|
|
400
|
+
*/
|
|
401
|
+
async invalidateTags(tags) {
|
|
402
|
+
if (!this._enabled) return [];
|
|
403
|
+
const uniqueTags = [...new Set(tags)];
|
|
404
|
+
if (uniqueTags.length === 0) return tags;
|
|
405
|
+
const versions = await this.getTagVersions(uniqueTags);
|
|
406
|
+
const kvPairs = [];
|
|
407
|
+
for (let i = 0; i < uniqueTags.length; i++) kvPairs.push({
|
|
408
|
+
key: this.tagKey(uniqueTags[i]),
|
|
409
|
+
value: versions[i] + 1
|
|
410
|
+
});
|
|
411
|
+
await this._store.setMany(kvPairs);
|
|
412
|
+
return tags;
|
|
413
|
+
}
|
|
105
414
|
};
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (milliseconds === void 0) {
|
|
110
|
-
return fromDate.getTime();
|
|
111
|
-
}
|
|
112
|
-
return fromDate.getTime() + milliseconds;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// src/coalesce-async.ts
|
|
116
|
-
var callbacks = /* @__PURE__ */ new Map();
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/coalesce-async.ts
|
|
417
|
+
const callbacks = /* @__PURE__ */ new Map();
|
|
117
418
|
function hasKey(key) {
|
|
118
|
-
|
|
419
|
+
return callbacks.has(key);
|
|
119
420
|
}
|
|
120
421
|
function addKey(key) {
|
|
121
|
-
|
|
422
|
+
callbacks.set(key, []);
|
|
122
423
|
}
|
|
123
424
|
function removeKey(key) {
|
|
124
|
-
|
|
425
|
+
callbacks.delete(key);
|
|
125
426
|
}
|
|
126
427
|
function addCallbackToKey(key, callback) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
428
|
+
const stash = getCallbacksByKey(key);
|
|
429
|
+
stash.push(callback);
|
|
430
|
+
callbacks.set(key, stash);
|
|
130
431
|
}
|
|
131
432
|
function getCallbacksByKey(key) {
|
|
132
|
-
|
|
433
|
+
/* v8 ignore next -- @preserve */
|
|
434
|
+
return callbacks.get(key) ?? [];
|
|
133
435
|
}
|
|
134
436
|
async function enqueue(key) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
437
|
+
return new Promise((resolve, reject) => {
|
|
438
|
+
addCallbackToKey(key, {
|
|
439
|
+
resolve,
|
|
440
|
+
reject
|
|
441
|
+
});
|
|
442
|
+
});
|
|
139
443
|
}
|
|
140
444
|
function dequeue(key) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
445
|
+
const stash = getCallbacksByKey(key);
|
|
446
|
+
removeKey(key);
|
|
447
|
+
return stash;
|
|
144
448
|
}
|
|
145
449
|
function coalesce(options) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
450
|
+
const { key, error, result } = options;
|
|
451
|
+
for (const callback of dequeue(key))
|
|
452
|
+
/* c8 ignore next 1 */
|
|
453
|
+
if (error)
|
|
454
|
+
/* c8 ignore next 3 */
|
|
455
|
+
callback.reject(error);
|
|
456
|
+
else callback.resolve(result);
|
|
154
457
|
}
|
|
458
|
+
/**
|
|
459
|
+
* Enqueue a promise for the group identified by `key`.
|
|
460
|
+
*
|
|
461
|
+
* All requests received for the same key while a request for that key
|
|
462
|
+
* is already being executed will wait. Once the running request settles
|
|
463
|
+
* then all the waiting requests in the group will settle, too.
|
|
464
|
+
* This minimizes how many times the function itself runs at the same time.
|
|
465
|
+
* This function resolves or rejects according to the given function argument.
|
|
466
|
+
*
|
|
467
|
+
* @url https://github.com/douglascayers/promise-coalesce
|
|
468
|
+
*/
|
|
155
469
|
async function coalesceAsync(key, fnc) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
470
|
+
if (!hasKey(key)) {
|
|
471
|
+
addKey(key);
|
|
472
|
+
try {
|
|
473
|
+
const result = await Promise.resolve(fnc());
|
|
474
|
+
coalesce({
|
|
475
|
+
key,
|
|
476
|
+
result
|
|
477
|
+
});
|
|
478
|
+
return result;
|
|
479
|
+
} catch (error) {
|
|
480
|
+
/* c8 ignore next 5 */
|
|
481
|
+
coalesce({
|
|
482
|
+
key,
|
|
483
|
+
error
|
|
484
|
+
});
|
|
485
|
+
throw error;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return enqueue(key);
|
|
168
489
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
490
|
+
//#endregion
|
|
491
|
+
//#region src/hash.ts
|
|
492
|
+
let HashAlgorithm = /* @__PURE__ */ function(HashAlgorithm) {
|
|
493
|
+
HashAlgorithm["SHA256"] = "SHA-256";
|
|
494
|
+
HashAlgorithm["SHA384"] = "SHA-384";
|
|
495
|
+
HashAlgorithm["SHA512"] = "SHA-512";
|
|
496
|
+
HashAlgorithm["DJB2"] = "djb2";
|
|
497
|
+
HashAlgorithm["FNV1"] = "fnv1";
|
|
498
|
+
HashAlgorithm["MURMER"] = "murmer";
|
|
499
|
+
HashAlgorithm["CRC32"] = "crc32";
|
|
500
|
+
return HashAlgorithm;
|
|
501
|
+
}({});
|
|
502
|
+
/**
|
|
503
|
+
* Hashes an object asynchronously using the specified cryptographic algorithm.
|
|
504
|
+
* This method should be used for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
505
|
+
* For non-cryptographic algorithms, use hashSync() for better performance.
|
|
506
|
+
* @param object The object to hash
|
|
507
|
+
* @param options The hash options to use
|
|
508
|
+
* @returns {Promise<string>} The hash of the object
|
|
509
|
+
*/
|
|
182
510
|
async function hash(object, options = {
|
|
183
|
-
|
|
184
|
-
|
|
511
|
+
algorithm: "SHA-256",
|
|
512
|
+
serialize: JSON.stringify
|
|
185
513
|
}) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const hashery = new import_hashery.Hashery();
|
|
190
|
-
return hashery.toHash(objectString, { algorithm });
|
|
514
|
+
const algorithm = options?.algorithm ?? "SHA-256";
|
|
515
|
+
const objectString = (options?.serialize ?? JSON.stringify)(object);
|
|
516
|
+
return new hashery.Hashery().toHash(objectString, { algorithm });
|
|
191
517
|
}
|
|
518
|
+
/**
|
|
519
|
+
* Hashes an object synchronously using the specified non-cryptographic algorithm.
|
|
520
|
+
* This method should be used for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
521
|
+
* For cryptographic algorithms, use hash() instead.
|
|
522
|
+
* @param object The object to hash
|
|
523
|
+
* @param options The hash options to use
|
|
524
|
+
* @returns {string} The hash of the object
|
|
525
|
+
*/
|
|
192
526
|
function hashSync(object, options = {
|
|
193
|
-
|
|
194
|
-
|
|
527
|
+
algorithm: "djb2",
|
|
528
|
+
serialize: JSON.stringify
|
|
195
529
|
}) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const hashery = new import_hashery.Hashery();
|
|
200
|
-
return hashery.toHashSync(objectString, { algorithm });
|
|
530
|
+
const algorithm = options?.algorithm ?? "djb2";
|
|
531
|
+
const objectString = (options?.serialize ?? JSON.stringify)(object);
|
|
532
|
+
return new hashery.Hashery().toHashSync(objectString, { algorithm });
|
|
201
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Hashes an object asynchronously and converts it to a number within a specified range.
|
|
536
|
+
* This method should be used for cryptographic algorithms (SHA-256, SHA-384, SHA-512).
|
|
537
|
+
* For non-cryptographic algorithms, use hashToNumberSync() for better performance.
|
|
538
|
+
* @param object The object to hash
|
|
539
|
+
* @param options The hash options to use including min/max range
|
|
540
|
+
* @returns {Promise<number>} A number within the specified range
|
|
541
|
+
*/
|
|
202
542
|
async function hashToNumber(object, options = {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
543
|
+
min: 0,
|
|
544
|
+
max: 10,
|
|
545
|
+
algorithm: "SHA-256",
|
|
546
|
+
serialize: JSON.stringify
|
|
207
547
|
}) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
algorithm,
|
|
222
|
-
min,
|
|
223
|
-
max,
|
|
224
|
-
hashLength
|
|
225
|
-
});
|
|
548
|
+
const min = options?.min ?? 0;
|
|
549
|
+
const max = options?.max ?? 10;
|
|
550
|
+
const algorithm = options?.algorithm ?? "SHA-256";
|
|
551
|
+
const serialize = options?.serialize ?? JSON.stringify;
|
|
552
|
+
const hashLength = options?.hashLength ?? 16;
|
|
553
|
+
if (min >= max) throw new Error(`Invalid range: min (${min}) must be less than max (${max})`);
|
|
554
|
+
const objectString = serialize(object);
|
|
555
|
+
return new hashery.Hashery().toNumber(objectString, {
|
|
556
|
+
algorithm,
|
|
557
|
+
min,
|
|
558
|
+
max,
|
|
559
|
+
hashLength
|
|
560
|
+
});
|
|
226
561
|
}
|
|
562
|
+
/**
|
|
563
|
+
* Hashes an object synchronously and converts it to a number within a specified range.
|
|
564
|
+
* This method should be used for non-cryptographic algorithms (DJB2, FNV1, MURMER, CRC32).
|
|
565
|
+
* For cryptographic algorithms, use hashToNumber() instead.
|
|
566
|
+
* @param object The object to hash
|
|
567
|
+
* @param options The hash options to use including min/max range
|
|
568
|
+
* @returns {number} A number within the specified range
|
|
569
|
+
*/
|
|
227
570
|
function hashToNumberSync(object, options = {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
571
|
+
min: 0,
|
|
572
|
+
max: 10,
|
|
573
|
+
algorithm: "djb2",
|
|
574
|
+
serialize: JSON.stringify
|
|
232
575
|
}) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
algorithm,
|
|
247
|
-
min,
|
|
248
|
-
max,
|
|
249
|
-
hashLength
|
|
250
|
-
});
|
|
576
|
+
const min = options?.min ?? 0;
|
|
577
|
+
const max = options?.max ?? 10;
|
|
578
|
+
const algorithm = options?.algorithm ?? "djb2";
|
|
579
|
+
const serialize = options?.serialize ?? JSON.stringify;
|
|
580
|
+
const hashLength = options?.hashLength ?? 16;
|
|
581
|
+
if (min >= max) throw new Error(`Invalid range: min (${min}) must be less than max (${max})`);
|
|
582
|
+
const objectString = serialize(object);
|
|
583
|
+
return new hashery.Hashery().toNumberSync(objectString, {
|
|
584
|
+
algorithm,
|
|
585
|
+
min,
|
|
586
|
+
max,
|
|
587
|
+
hashLength
|
|
588
|
+
});
|
|
251
589
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
"clear",
|
|
273
|
-
"disconnect",
|
|
274
|
-
"serialize",
|
|
275
|
-
"deserialize"
|
|
276
|
-
];
|
|
277
|
-
return keyvMethods.every((method) => typeof keyv[method] === "function");
|
|
590
|
+
//#endregion
|
|
591
|
+
//#region src/is-keyv-instance.ts
|
|
592
|
+
function isKeyvInstance(keyv$1) {
|
|
593
|
+
if (keyv$1 === null || keyv$1 === void 0) return false;
|
|
594
|
+
if (keyv$1 instanceof keyv.Keyv) return true;
|
|
595
|
+
return [
|
|
596
|
+
"generateIterator",
|
|
597
|
+
"get",
|
|
598
|
+
"getMany",
|
|
599
|
+
"set",
|
|
600
|
+
"setMany",
|
|
601
|
+
"delete",
|
|
602
|
+
"deleteMany",
|
|
603
|
+
"has",
|
|
604
|
+
"hasMany",
|
|
605
|
+
"clear",
|
|
606
|
+
"disconnect",
|
|
607
|
+
"serialize",
|
|
608
|
+
"deserialize"
|
|
609
|
+
].every((method) => typeof keyv$1[method] === "function");
|
|
278
610
|
}
|
|
279
|
-
|
|
280
|
-
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/is-object.ts
|
|
281
613
|
function isObject(value) {
|
|
282
|
-
|
|
614
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
283
615
|
}
|
|
284
|
-
|
|
285
|
-
|
|
616
|
+
//#endregion
|
|
617
|
+
//#region src/less-than.ts
|
|
286
618
|
function lessThan(number1, number2) {
|
|
287
|
-
|
|
619
|
+
return typeof number1 === "number" && typeof number2 === "number" ? number1 < number2 : false;
|
|
288
620
|
}
|
|
289
|
-
|
|
290
|
-
|
|
621
|
+
//#endregion
|
|
622
|
+
//#region src/memoize.ts
|
|
291
623
|
function wrapSync(function_, options) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
cache.set(cacheKey, error, ttl);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return value;
|
|
314
|
-
};
|
|
624
|
+
const { ttl, keyPrefix, cache, serialize } = options;
|
|
625
|
+
return (...arguments_) => {
|
|
626
|
+
let cacheKey = createWrapKey(function_, arguments_, {
|
|
627
|
+
keyPrefix,
|
|
628
|
+
serialize
|
|
629
|
+
});
|
|
630
|
+
if (options.createKey) cacheKey = options.createKey(function_, arguments_, options);
|
|
631
|
+
let value = cache.get(cacheKey);
|
|
632
|
+
if (value === void 0) try {
|
|
633
|
+
value = function_(...arguments_);
|
|
634
|
+
cache.set(cacheKey, value, ttl);
|
|
635
|
+
} catch (error) {
|
|
636
|
+
cache.emit("error", error);
|
|
637
|
+
if (options.cacheErrors) cache.set(cacheKey, error, ttl);
|
|
638
|
+
}
|
|
639
|
+
return value;
|
|
640
|
+
};
|
|
315
641
|
}
|
|
316
642
|
async function getOrSet(key, function_, options) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
643
|
+
const keyString = typeof key === "function" ? key(options) : key;
|
|
644
|
+
let value;
|
|
645
|
+
try {
|
|
646
|
+
value = await options.cache.get(keyString);
|
|
647
|
+
} catch (error) {
|
|
648
|
+
options.cache.emit("error", error);
|
|
649
|
+
if (options.throwErrors === true || options.throwErrors === "store") throw error;
|
|
650
|
+
}
|
|
651
|
+
if (value === void 0) value = await coalesceAsync(`${options.cacheId ?? "default"}::${keyString}`, async () => {
|
|
652
|
+
let result;
|
|
653
|
+
try {
|
|
654
|
+
try {
|
|
655
|
+
result = await function_();
|
|
656
|
+
} catch (error) {
|
|
657
|
+
throw new ErrorEnvelope(error, "function");
|
|
658
|
+
}
|
|
659
|
+
try {
|
|
660
|
+
await options.cache.set(keyString, result, options.ttl);
|
|
661
|
+
} catch (error) {
|
|
662
|
+
throw new ErrorEnvelope(error, "store");
|
|
663
|
+
}
|
|
664
|
+
return result;
|
|
665
|
+
} catch (caught) {
|
|
666
|
+
const errorType = caught instanceof ErrorEnvelope ? caught.context : void 0;
|
|
667
|
+
const error = caught instanceof ErrorEnvelope ? caught.error : caught;
|
|
668
|
+
options.cache.emit("error", error);
|
|
669
|
+
if (options.cacheErrors && errorType === "function") try {
|
|
670
|
+
await options.cache.set(keyString, error, options.ttl);
|
|
671
|
+
} catch (storeError) {
|
|
672
|
+
options.cache.emit("error", storeError);
|
|
673
|
+
}
|
|
674
|
+
if (options.throwErrors === true || options.throwErrors === errorType) throw error;
|
|
675
|
+
}
|
|
676
|
+
return result;
|
|
677
|
+
});
|
|
678
|
+
return value;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Synchronous counterpart to {@link getOrSet}. Reads `key` from the cache and, on a miss, computes
|
|
682
|
+
* the value with `function_`, stores it, and returns it.
|
|
683
|
+
*
|
|
684
|
+
* Unlike {@link getOrSet} there is no request coalescing: synchronous code runs to completion
|
|
685
|
+
* without interleaving, so concurrent callers cannot stampede the setter the way they can with an
|
|
686
|
+
* async cache.
|
|
687
|
+
*
|
|
688
|
+
* Error handling mirrors {@link getOrSet}: errors are emitted on the cache's `error` event, can be
|
|
689
|
+
* cached when `cacheErrors` is set, and can be rethrown selectively via `throwErrors` (`true` for
|
|
690
|
+
* any error, `"function"` for setter errors, `"store"` for cache read/write errors).
|
|
691
|
+
*
|
|
692
|
+
* @param key - The cache key, or a function that derives it from the resolved options.
|
|
693
|
+
* @param function_ - The setter invoked on a cache miss to compute the value.
|
|
694
|
+
* @param options - The {@link GetOrSetSyncOptions} including the target synchronous cache.
|
|
695
|
+
* @returns The cached or freshly computed value, or `undefined`.
|
|
696
|
+
*/
|
|
697
|
+
function getOrSetSync(key, function_, options) {
|
|
698
|
+
const keyString = typeof key === "function" ? key(options) : key;
|
|
699
|
+
let value;
|
|
700
|
+
try {
|
|
701
|
+
value = options.cache.get(keyString);
|
|
702
|
+
} catch (error) {
|
|
703
|
+
options.cache.emit("error", error);
|
|
704
|
+
if (options.throwErrors === true || options.throwErrors === "store") throw error;
|
|
705
|
+
}
|
|
706
|
+
if (value === void 0) try {
|
|
707
|
+
try {
|
|
708
|
+
value = function_();
|
|
709
|
+
} catch (error) {
|
|
710
|
+
throw new ErrorEnvelope(error, "function");
|
|
711
|
+
}
|
|
712
|
+
try {
|
|
713
|
+
options.cache.set(keyString, value, options.ttl);
|
|
714
|
+
} catch (error) {
|
|
715
|
+
throw new ErrorEnvelope(error, "store");
|
|
716
|
+
}
|
|
717
|
+
} catch (caught) {
|
|
718
|
+
const errorType = caught instanceof ErrorEnvelope ? caught.context : void 0;
|
|
719
|
+
const error = caught instanceof ErrorEnvelope ? caught.error : caught;
|
|
720
|
+
options.cache.emit("error", error);
|
|
721
|
+
if (options.cacheErrors && errorType === "function") try {
|
|
722
|
+
options.cache.set(keyString, error, options.ttl);
|
|
723
|
+
} catch (storeError) {
|
|
724
|
+
options.cache.emit("error", storeError);
|
|
725
|
+
}
|
|
726
|
+
if (options.throwErrors === true || options.throwErrors === errorType) throw error;
|
|
727
|
+
}
|
|
728
|
+
return value;
|
|
365
729
|
}
|
|
366
730
|
function wrap(function_, options) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
return getOrSet(
|
|
377
|
-
cacheKey,
|
|
378
|
-
async () => function_(...arguments_),
|
|
379
|
-
options
|
|
380
|
-
);
|
|
381
|
-
};
|
|
731
|
+
const { keyPrefix, serialize } = options;
|
|
732
|
+
return async (...arguments_) => {
|
|
733
|
+
let cacheKey = createWrapKey(function_, arguments_, {
|
|
734
|
+
keyPrefix,
|
|
735
|
+
serialize
|
|
736
|
+
});
|
|
737
|
+
if (options.createKey) cacheKey = options.createKey(function_, arguments_, options);
|
|
738
|
+
return getOrSet(cacheKey, async () => function_(...arguments_), options);
|
|
739
|
+
};
|
|
382
740
|
}
|
|
383
741
|
function createWrapKey(function_, arguments_, options) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
return `${keyPrefix}::${function_.name}::${hashSync(arguments_, { serialize })}`;
|
|
742
|
+
const { keyPrefix, serialize } = options || {};
|
|
743
|
+
if (!keyPrefix) return `${function_.name}::${hashSync(arguments_, { serialize })}`;
|
|
744
|
+
return `${keyPrefix}::${function_.name}::${hashSync(arguments_, { serialize })}`;
|
|
389
745
|
}
|
|
390
746
|
var ErrorEnvelope = class {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
747
|
+
error;
|
|
748
|
+
context;
|
|
749
|
+
constructor(error, context) {
|
|
750
|
+
this.error = error;
|
|
751
|
+
this.context = context;
|
|
752
|
+
}
|
|
395
753
|
};
|
|
396
|
-
|
|
397
|
-
|
|
754
|
+
//#endregion
|
|
755
|
+
//#region src/run-if-fn.ts
|
|
398
756
|
function runIfFn(valueOrFunction, ...arguments_) {
|
|
399
|
-
|
|
757
|
+
return typeof valueOrFunction === "function" ? valueOrFunction(...arguments_) : valueOrFunction;
|
|
400
758
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
759
|
+
//#endregion
|
|
760
|
+
//#region src/sleep.ts
|
|
761
|
+
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
762
|
+
//#endregion
|
|
763
|
+
//#region src/stats.ts
|
|
764
|
+
/**
|
|
765
|
+
* Event map for `@cacheable/node-cache` instances. node-cache emits with
|
|
766
|
+
* positional arguments (e.g. `set(key, value)`), and emits each lifecycle
|
|
767
|
+
* event exactly once, so the counts map cleanly. `flush` clears the cache data
|
|
768
|
+
* and `flush_stats` resets the stats counters, mirroring node-cache's
|
|
769
|
+
* `flushAll()` / `flushStats()` lifecycle.
|
|
770
|
+
*
|
|
771
|
+
* Presets for `cacheable` and `cache-manager` are intentionally not provided:
|
|
772
|
+
* their event streams emit per-store probes (and, for cache-manager, do not
|
|
773
|
+
* emit an event on a normal miss), so a simple map cannot faithfully reproduce
|
|
774
|
+
* their imperative stats. Wire those up with a custom map or imperative calls.
|
|
775
|
+
*/
|
|
776
|
+
const nodeCacheStatsEventMap = {
|
|
777
|
+
set: (stats, key) => {
|
|
778
|
+
stats.increment("sets");
|
|
779
|
+
if (typeof key === "string" || typeof key === "number") stats.recordKey(String(key), "sets");
|
|
780
|
+
},
|
|
781
|
+
del: (stats, key) => {
|
|
782
|
+
stats.increment("deletes");
|
|
783
|
+
if (typeof key === "string" || typeof key === "number") stats.recordKey(String(key), "deletes");
|
|
784
|
+
},
|
|
785
|
+
flush: "clears",
|
|
786
|
+
flush_stats: (stats) => {
|
|
787
|
+
stats.reset();
|
|
788
|
+
}
|
|
789
|
+
};
|
|
406
790
|
var Stats = class {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
791
|
+
_counters = {
|
|
792
|
+
hits: 0,
|
|
793
|
+
misses: 0,
|
|
794
|
+
gets: 0,
|
|
795
|
+
sets: 0,
|
|
796
|
+
deletes: 0,
|
|
797
|
+
clears: 0,
|
|
798
|
+
count: 0
|
|
799
|
+
};
|
|
800
|
+
_vsize = 0;
|
|
801
|
+
_ksize = 0;
|
|
802
|
+
_enabled = false;
|
|
803
|
+
_lastUpdated;
|
|
804
|
+
_lastReset;
|
|
805
|
+
_subscriptions = [];
|
|
806
|
+
/** Backing store for the public {@link trackedKeys} read-only view. */
|
|
807
|
+
_trackedKeys = /* @__PURE__ */ new Map();
|
|
808
|
+
_trackKeys = false;
|
|
809
|
+
_maxTrackedKeys;
|
|
810
|
+
constructor(options) {
|
|
811
|
+
if (options?.enabled) this._enabled = options.enabled;
|
|
812
|
+
if (options?.trackKeys) this._trackKeys = options.trackKeys;
|
|
813
|
+
if (options?.maxTrackedKeys !== void 0) this._maxTrackedKeys = options.maxTrackedKeys;
|
|
814
|
+
if (options?.emitter && options?.eventMap) this.subscribe(options.emitter, options.eventMap);
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* @returns {boolean} - Whether the stats are enabled
|
|
818
|
+
*/
|
|
819
|
+
get enabled() {
|
|
820
|
+
return this._enabled;
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* @param {boolean} enabled - Whether to enable the stats
|
|
824
|
+
*/
|
|
825
|
+
set enabled(enabled) {
|
|
826
|
+
this._enabled = enabled;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* @returns {boolean} - Whether per-key statistics are tracked
|
|
830
|
+
*/
|
|
831
|
+
get trackKeys() {
|
|
832
|
+
return this._trackKeys;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* @param {boolean} trackKeys - Whether to track per-key statistics
|
|
836
|
+
*/
|
|
837
|
+
set trackKeys(trackKeys) {
|
|
838
|
+
this._trackKeys = trackKeys;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* @returns {number | undefined} - The cap on unique keys tracked, or
|
|
842
|
+
* `undefined` when unbounded
|
|
843
|
+
*/
|
|
844
|
+
get maxTrackedKeys() {
|
|
845
|
+
return this._maxTrackedKeys;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* @param {number | undefined} maxTrackedKeys - The cap on unique keys
|
|
849
|
+
* tracked. Set `undefined` for unbounded.
|
|
850
|
+
*/
|
|
851
|
+
set maxTrackedKeys(maxTrackedKeys) {
|
|
852
|
+
this._maxTrackedKeys = maxTrackedKeys;
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Per-key statistics, keyed by cache key, holding each key's raw
|
|
856
|
+
* `hits`/`misses`/`gets`/`sets`/`deletes` counters. Populated by
|
|
857
|
+
* {@link recordKey} when {@link trackKeys} is enabled; read `trackedKeys.size`
|
|
858
|
+
* for the number of unique keys currently tracked. The returned map is a
|
|
859
|
+
* read-only view — mutate per-key stats via {@link recordKey} /
|
|
860
|
+
* {@link clearKeys} / {@link reset}.
|
|
861
|
+
* @returns {ReadonlyMap<string, Readonly<KeyCounters>>}
|
|
862
|
+
* @readonly
|
|
863
|
+
*/
|
|
864
|
+
get trackedKeys() {
|
|
865
|
+
return this._trackedKeys;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* @returns {number} - The number of hits
|
|
869
|
+
* @readonly
|
|
870
|
+
*/
|
|
871
|
+
get hits() {
|
|
872
|
+
return this._counters.hits;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* @returns {number} - The number of misses
|
|
876
|
+
* @readonly
|
|
877
|
+
*/
|
|
878
|
+
get misses() {
|
|
879
|
+
return this._counters.misses;
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* @returns {number} - The number of gets
|
|
883
|
+
* @readonly
|
|
884
|
+
*/
|
|
885
|
+
get gets() {
|
|
886
|
+
return this._counters.gets;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* @returns {number} - The number of sets
|
|
890
|
+
* @readonly
|
|
891
|
+
*/
|
|
892
|
+
get sets() {
|
|
893
|
+
return this._counters.sets;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* @returns {number} - The number of deletes
|
|
897
|
+
* @readonly
|
|
898
|
+
*/
|
|
899
|
+
get deletes() {
|
|
900
|
+
return this._counters.deletes;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* @returns {number} - The number of clears
|
|
904
|
+
* @readonly
|
|
905
|
+
*/
|
|
906
|
+
get clears() {
|
|
907
|
+
return this._counters.clears;
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* @returns {number} - The vsize (value size) of the cache instance
|
|
911
|
+
* @readonly
|
|
912
|
+
*/
|
|
913
|
+
get vsize() {
|
|
914
|
+
return this._vsize;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* @returns {number} - The ksize (key size) of the cache instance
|
|
918
|
+
* @readonly
|
|
919
|
+
*/
|
|
920
|
+
get ksize() {
|
|
921
|
+
return this._ksize;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* @returns {number} - The count of the cache instance
|
|
925
|
+
* @readonly
|
|
926
|
+
*/
|
|
927
|
+
get count() {
|
|
928
|
+
return this._counters.count;
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* The ratio of hits to total lookups (hits + misses). Returns `0` when there
|
|
932
|
+
* have been no lookups.
|
|
933
|
+
* @returns {number} - A value between 0 and 1
|
|
934
|
+
* @readonly
|
|
935
|
+
*/
|
|
936
|
+
get hitRate() {
|
|
937
|
+
const total = this._counters.hits + this._counters.misses;
|
|
938
|
+
return total === 0 ? 0 : this._counters.hits / total;
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* The ratio of misses to total lookups (hits + misses). Returns `0` when
|
|
942
|
+
* there have been no lookups.
|
|
943
|
+
* @returns {number} - A value between 0 and 1
|
|
944
|
+
* @readonly
|
|
945
|
+
*/
|
|
946
|
+
get missRate() {
|
|
947
|
+
const total = this._counters.hits + this._counters.misses;
|
|
948
|
+
return total === 0 ? 0 : this._counters.misses / total;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* The timestamp (ms since epoch) of the last mutation while enabled, or
|
|
952
|
+
* `undefined` if there have been none since the last reset.
|
|
953
|
+
* @returns {number | undefined}
|
|
954
|
+
* @readonly
|
|
955
|
+
*/
|
|
956
|
+
get lastUpdated() {
|
|
957
|
+
return this._lastUpdated;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* The timestamp (ms since epoch) of the last {@link reset}/{@link clear}, or
|
|
961
|
+
* `undefined` if it has never been reset.
|
|
962
|
+
* @returns {number | undefined}
|
|
963
|
+
* @readonly
|
|
964
|
+
*/
|
|
965
|
+
get lastReset() {
|
|
966
|
+
return this._lastReset;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Increment a counter field by `amount` (default `1`). No-op when disabled.
|
|
970
|
+
* @param {StatField} field - The counter to increment
|
|
971
|
+
* @param {number} amount - The amount to add (default 1)
|
|
972
|
+
*/
|
|
973
|
+
increment(field, amount = 1) {
|
|
974
|
+
if (!this._enabled) return;
|
|
975
|
+
this._counters[field] += amount;
|
|
976
|
+
this.touch();
|
|
977
|
+
}
|
|
978
|
+
/**
|
|
979
|
+
* Decrement a counter field by `amount` (default `1`). No-op when disabled.
|
|
980
|
+
* @param {StatField} field - The counter to decrement
|
|
981
|
+
* @param {number} amount - The amount to subtract (default 1)
|
|
982
|
+
*/
|
|
983
|
+
decrement(field, amount = 1) {
|
|
984
|
+
if (!this._enabled) return;
|
|
985
|
+
this._counters[field] -= amount;
|
|
986
|
+
this.touch();
|
|
987
|
+
}
|
|
988
|
+
incrementHits(amount = 1) {
|
|
989
|
+
this.increment("hits", amount);
|
|
990
|
+
}
|
|
991
|
+
incrementMisses(amount = 1) {
|
|
992
|
+
this.increment("misses", amount);
|
|
993
|
+
}
|
|
994
|
+
incrementGets(amount = 1) {
|
|
995
|
+
this.increment("gets", amount);
|
|
996
|
+
}
|
|
997
|
+
incrementSets(amount = 1) {
|
|
998
|
+
this.increment("sets", amount);
|
|
999
|
+
}
|
|
1000
|
+
incrementDeletes(amount = 1) {
|
|
1001
|
+
this.increment("deletes", amount);
|
|
1002
|
+
}
|
|
1003
|
+
incrementClears(amount = 1) {
|
|
1004
|
+
this.increment("clears", amount);
|
|
1005
|
+
}
|
|
1006
|
+
incrementVSize(value) {
|
|
1007
|
+
if (!this._enabled) return;
|
|
1008
|
+
this._vsize += this.roughSizeOfObject(value);
|
|
1009
|
+
this.touch();
|
|
1010
|
+
}
|
|
1011
|
+
decreaseVSize(value) {
|
|
1012
|
+
if (!this._enabled) return;
|
|
1013
|
+
this._vsize = Math.max(0, this._vsize - this.roughSizeOfObject(value));
|
|
1014
|
+
this.touch();
|
|
1015
|
+
}
|
|
1016
|
+
incrementKSize(key) {
|
|
1017
|
+
if (!this._enabled) return;
|
|
1018
|
+
this._ksize += this.roughSizeOfString(key);
|
|
1019
|
+
this.touch();
|
|
1020
|
+
}
|
|
1021
|
+
decreaseKSize(key) {
|
|
1022
|
+
if (!this._enabled) return;
|
|
1023
|
+
this._ksize = Math.max(0, this._ksize - this.roughSizeOfString(key));
|
|
1024
|
+
this.touch();
|
|
1025
|
+
}
|
|
1026
|
+
incrementCount(amount = 1) {
|
|
1027
|
+
this.increment("count", amount);
|
|
1028
|
+
}
|
|
1029
|
+
decreaseCount(amount = 1) {
|
|
1030
|
+
if (!this._enabled) return;
|
|
1031
|
+
this._counters.count = Math.max(0, this._counters.count - amount);
|
|
1032
|
+
this.touch();
|
|
1033
|
+
}
|
|
1034
|
+
setCount(count) {
|
|
1035
|
+
if (!this._enabled) return;
|
|
1036
|
+
this._counters.count = count;
|
|
1037
|
+
this.touch();
|
|
1038
|
+
}
|
|
1039
|
+
roughSizeOfString(value) {
|
|
1040
|
+
return value.length * 2;
|
|
1041
|
+
}
|
|
1042
|
+
roughSizeOfObject(object) {
|
|
1043
|
+
const objectList = [];
|
|
1044
|
+
const stack = [object];
|
|
1045
|
+
let bytes = 0;
|
|
1046
|
+
while (stack.length > 0) {
|
|
1047
|
+
const value = stack.pop();
|
|
1048
|
+
if (typeof value === "boolean") bytes += 4;
|
|
1049
|
+
else if (typeof value === "string") bytes += value.length * 2;
|
|
1050
|
+
else if (typeof value === "number") bytes += 8;
|
|
1051
|
+
else {
|
|
1052
|
+
if (value === null || value === void 0) {
|
|
1053
|
+
bytes += 4;
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
if (objectList.includes(value)) continue;
|
|
1057
|
+
objectList.push(value);
|
|
1058
|
+
for (const key in value) {
|
|
1059
|
+
bytes += key.length * 2;
|
|
1060
|
+
stack.push(value[key]);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
return bytes;
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Enable stat tracking. Equivalent to setting {@link enabled} to `true`.
|
|
1068
|
+
*/
|
|
1069
|
+
enable() {
|
|
1070
|
+
this._enabled = true;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Disable stat tracking. Equivalent to setting {@link enabled} to `false`.
|
|
1074
|
+
*/
|
|
1075
|
+
disable() {
|
|
1076
|
+
this._enabled = false;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Reset all counters to zero and record the reset timestamp. Alias of
|
|
1080
|
+
* {@link reset}.
|
|
1081
|
+
*/
|
|
1082
|
+
clear() {
|
|
1083
|
+
this.reset();
|
|
1084
|
+
}
|
|
1085
|
+
reset() {
|
|
1086
|
+
this._counters = {
|
|
1087
|
+
hits: 0,
|
|
1088
|
+
misses: 0,
|
|
1089
|
+
gets: 0,
|
|
1090
|
+
sets: 0,
|
|
1091
|
+
deletes: 0,
|
|
1092
|
+
clears: 0,
|
|
1093
|
+
count: 0
|
|
1094
|
+
};
|
|
1095
|
+
this._vsize = 0;
|
|
1096
|
+
this._ksize = 0;
|
|
1097
|
+
this._trackedKeys.clear();
|
|
1098
|
+
this._lastReset = Date.now();
|
|
1099
|
+
this._lastUpdated = void 0;
|
|
1100
|
+
}
|
|
1101
|
+
resetStoreValues() {
|
|
1102
|
+
this._vsize = 0;
|
|
1103
|
+
this._ksize = 0;
|
|
1104
|
+
this._counters.count = 0;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* @returns {StatsSnapshot} - A plain-object snapshot of the current stats,
|
|
1108
|
+
* including computed `hitRate`/`missRate` and timestamps.
|
|
1109
|
+
*/
|
|
1110
|
+
toJSON() {
|
|
1111
|
+
return {
|
|
1112
|
+
enabled: this._enabled,
|
|
1113
|
+
hits: this._counters.hits,
|
|
1114
|
+
misses: this._counters.misses,
|
|
1115
|
+
gets: this._counters.gets,
|
|
1116
|
+
sets: this._counters.sets,
|
|
1117
|
+
deletes: this._counters.deletes,
|
|
1118
|
+
clears: this._counters.clears,
|
|
1119
|
+
vsize: this._vsize,
|
|
1120
|
+
ksize: this._ksize,
|
|
1121
|
+
count: this._counters.count,
|
|
1122
|
+
hitRate: this.hitRate,
|
|
1123
|
+
missRate: this.missRate,
|
|
1124
|
+
trackedKeys: this._trackedKeys.size,
|
|
1125
|
+
lastUpdated: this._lastUpdated,
|
|
1126
|
+
lastReset: this._lastReset
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* @returns {StatsSnapshot} - A plain-object snapshot of the current stats.
|
|
1131
|
+
* Alias of {@link toJSON}.
|
|
1132
|
+
*/
|
|
1133
|
+
snapshot() {
|
|
1134
|
+
return this.toJSON();
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Record an operation against a specific key for per-key statistics. No-op
|
|
1138
|
+
* unless both {@link enabled} and {@link trackKeys} are `true`.
|
|
1139
|
+
* @param {string} key - The cache key the operation touched
|
|
1140
|
+
* @param {KeyStatField} field - The per-key counter to increment
|
|
1141
|
+
* @param {number} amount - The amount to add (default 1)
|
|
1142
|
+
*/
|
|
1143
|
+
recordKey(key, field, amount = 1) {
|
|
1144
|
+
if (!this._enabled || !this._trackKeys) return;
|
|
1145
|
+
let counters = this._trackedKeys.get(key);
|
|
1146
|
+
if (!counters) {
|
|
1147
|
+
counters = {
|
|
1148
|
+
hits: 0,
|
|
1149
|
+
misses: 0,
|
|
1150
|
+
gets: 0,
|
|
1151
|
+
sets: 0,
|
|
1152
|
+
deletes: 0
|
|
1153
|
+
};
|
|
1154
|
+
this._trackedKeys.set(key, counters);
|
|
1155
|
+
this.pruneTrackedKeys(key);
|
|
1156
|
+
}
|
|
1157
|
+
counters[field] += amount;
|
|
1158
|
+
this.touch();
|
|
1159
|
+
}
|
|
1160
|
+
/**
|
|
1161
|
+
* The most-used keys, sorted descending. Sorts by total recorded operations,
|
|
1162
|
+
* or by a single field when `field` is provided. Ties order by key.
|
|
1163
|
+
* @param {number} limit - Maximum entries to return (default 100)
|
|
1164
|
+
* @param {KeyStatField} [field] - Optionally rank by one counter (e.g. "hits")
|
|
1165
|
+
* @returns {StatsKeyEntry[]}
|
|
1166
|
+
*/
|
|
1167
|
+
mostUsedKeys(limit = 100, field) {
|
|
1168
|
+
return this.sortedKeyEntries(field, "desc").slice(0, limit);
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* The least-used keys, sorted ascending. Sorts by total recorded operations,
|
|
1172
|
+
* or by a single field when `field` is provided. Ties order by key. Note:
|
|
1173
|
+
* only keys that have been recorded at least once can be ranked, and when
|
|
1174
|
+
* {@link maxTrackedKeys} pruning has occurred the true least-used keys may
|
|
1175
|
+
* have been evicted.
|
|
1176
|
+
* @param {number} limit - Maximum entries to return (default 100)
|
|
1177
|
+
* @param {KeyStatField} [field] - Optionally rank by one counter (e.g. "gets")
|
|
1178
|
+
* @returns {StatsKeyEntry[]}
|
|
1179
|
+
*/
|
|
1180
|
+
leastUsedKeys(limit = 100, field) {
|
|
1181
|
+
return this.sortedKeyEntries(field, "asc").slice(0, limit);
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* @param {string} key - The key to look up
|
|
1185
|
+
* @returns {StatsKeyEntry | undefined} - The per-key statistics, or
|
|
1186
|
+
* `undefined` if the key has not been recorded
|
|
1187
|
+
*/
|
|
1188
|
+
keyStats(key) {
|
|
1189
|
+
const counters = this._trackedKeys.get(key);
|
|
1190
|
+
return counters ? this.toKeyEntry(key, counters) : void 0;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Clear all per-key statistics without touching the aggregate counters.
|
|
1194
|
+
*/
|
|
1195
|
+
clearKeys() {
|
|
1196
|
+
this._trackedKeys.clear();
|
|
1197
|
+
}
|
|
1198
|
+
totalOf(counters) {
|
|
1199
|
+
return counters.hits + counters.misses + counters.gets + counters.sets + counters.deletes;
|
|
1200
|
+
}
|
|
1201
|
+
toKeyEntry(key, counters) {
|
|
1202
|
+
const lookups = counters.hits + counters.misses;
|
|
1203
|
+
return {
|
|
1204
|
+
key,
|
|
1205
|
+
count: this.totalOf(counters),
|
|
1206
|
+
hits: counters.hits,
|
|
1207
|
+
misses: counters.misses,
|
|
1208
|
+
gets: counters.gets,
|
|
1209
|
+
sets: counters.sets,
|
|
1210
|
+
deletes: counters.deletes,
|
|
1211
|
+
hitRate: lookups === 0 ? 0 : counters.hits / lookups
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
sortedKeyEntries(field, direction) {
|
|
1215
|
+
const entries = [];
|
|
1216
|
+
for (const [key, counters] of this._trackedKeys) entries.push(this.toKeyEntry(key, counters));
|
|
1217
|
+
const sign = direction === "asc" ? 1 : -1;
|
|
1218
|
+
entries.sort((a, b) => {
|
|
1219
|
+
const valueA = field ? a[field] : a.count;
|
|
1220
|
+
const valueB = field ? b[field] : b.count;
|
|
1221
|
+
if (valueA !== valueB) return (valueA - valueB) * sign;
|
|
1222
|
+
return a.key < b.key ? -1 : 1;
|
|
1223
|
+
});
|
|
1224
|
+
return entries;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* When over {@link maxTrackedKeys}, prune the lowest-count keys down to 90%
|
|
1228
|
+
* of the cap (batched so the sort cost amortizes across inserts). The key
|
|
1229
|
+
* that was just recorded is never pruned.
|
|
1230
|
+
*/
|
|
1231
|
+
pruneTrackedKeys(protectedKey) {
|
|
1232
|
+
if (this._maxTrackedKeys === void 0 || this._trackedKeys.size <= this._maxTrackedKeys) return;
|
|
1233
|
+
const target = Math.max(1, Math.floor(this._maxTrackedKeys * .9));
|
|
1234
|
+
const sorted = [...this._trackedKeys.entries()].sort((a, b) => this.totalOf(a[1]) - this.totalOf(b[1]));
|
|
1235
|
+
for (const [key] of sorted) {
|
|
1236
|
+
if (this._trackedKeys.size <= target) break;
|
|
1237
|
+
if (key === protectedKey) continue;
|
|
1238
|
+
this._trackedKeys.delete(key);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Subscribe to an emitter so that matching events automatically update the
|
|
1243
|
+
* stats. Counting is gated by {@link enabled}, so you may subscribe first and
|
|
1244
|
+
* toggle enablement later. Call {@link unsubscribe} to detach.
|
|
1245
|
+
* @param {StatsEmitter} emitter - The emitter to listen on
|
|
1246
|
+
* @param {StatsEventMap} eventMap - The event-to-stat mapping (e.g.
|
|
1247
|
+
* {@link nodeCacheStatsEventMap} or a custom map)
|
|
1248
|
+
*/
|
|
1249
|
+
subscribe(emitter, eventMap) {
|
|
1250
|
+
for (const [event, action] of Object.entries(eventMap)) {
|
|
1251
|
+
const listener = (...args) => {
|
|
1252
|
+
this.applyEvent(action, args);
|
|
1253
|
+
};
|
|
1254
|
+
emitter.on(event, listener);
|
|
1255
|
+
this._subscriptions.push({
|
|
1256
|
+
emitter,
|
|
1257
|
+
event,
|
|
1258
|
+
listener
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Detach listeners previously attached via {@link subscribe}. When `emitter`
|
|
1264
|
+
* is provided, only that emitter's listeners are removed; otherwise all are.
|
|
1265
|
+
* @param {StatsEmitter} [emitter] - The emitter to detach from
|
|
1266
|
+
*/
|
|
1267
|
+
unsubscribe(emitter) {
|
|
1268
|
+
const remaining = [];
|
|
1269
|
+
for (const sub of this._subscriptions) {
|
|
1270
|
+
if (emitter && sub.emitter !== emitter) {
|
|
1271
|
+
remaining.push(sub);
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
(sub.emitter.off ?? sub.emitter.removeListener)?.call(sub.emitter, sub.event, sub.listener);
|
|
1275
|
+
}
|
|
1276
|
+
this._subscriptions = remaining;
|
|
1277
|
+
}
|
|
1278
|
+
applyEvent(action, args) {
|
|
1279
|
+
if (!this._enabled) return;
|
|
1280
|
+
if (typeof action === "function") {
|
|
1281
|
+
action(this, ...args);
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
if (Array.isArray(action)) {
|
|
1285
|
+
for (const field of action) this.increment(field);
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
this.increment(action);
|
|
1289
|
+
}
|
|
1290
|
+
touch() {
|
|
1291
|
+
this._lastUpdated = Date.now();
|
|
1292
|
+
}
|
|
623
1293
|
};
|
|
624
|
-
|
|
625
|
-
|
|
1294
|
+
//#endregion
|
|
1295
|
+
//#region src/ttl.ts
|
|
1296
|
+
/**
|
|
1297
|
+
* Normalizes a TTL input into per-store milliseconds. When given an object it resolves the
|
|
1298
|
+
* `primary` and `secondary` fields independently; when given a number or shorthand string it
|
|
1299
|
+
* applies the same value to both stores. Undefined fields (or undefined input) resolve to
|
|
1300
|
+
* `undefined` so the caller can fall back to its own default TTL.
|
|
1301
|
+
* @param ttl - The TTL input: a number (ms), a shorthand string, or a {@link PerStoreTtl} object.
|
|
1302
|
+
* @returns {{ primary?: number; secondary?: number }} The resolved per-store TTLs in milliseconds.
|
|
1303
|
+
*/
|
|
1304
|
+
function resolvePerStoreTtl(ttl) {
|
|
1305
|
+
if (ttl === void 0 || ttl === null) return {
|
|
1306
|
+
primary: void 0,
|
|
1307
|
+
secondary: void 0
|
|
1308
|
+
};
|
|
1309
|
+
if (typeof ttl === "object") return {
|
|
1310
|
+
primary: shorthandToMilliseconds(ttl.primary),
|
|
1311
|
+
secondary: shorthandToMilliseconds(ttl.secondary)
|
|
1312
|
+
};
|
|
1313
|
+
const milliseconds = shorthandToMilliseconds(ttl);
|
|
1314
|
+
return {
|
|
1315
|
+
primary: milliseconds,
|
|
1316
|
+
secondary: milliseconds
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* Converts a exspires value to a TTL value.
|
|
1321
|
+
* @param expires - The expires value to convert.
|
|
1322
|
+
* @returns {number | undefined} The TTL value in milliseconds, or undefined if the expires value is not valid.
|
|
1323
|
+
*/
|
|
626
1324
|
function getTtlFromExpires(expires) {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
if (expires < now) {
|
|
632
|
-
return void 0;
|
|
633
|
-
}
|
|
634
|
-
return expires - now;
|
|
1325
|
+
if (expires === void 0 || expires === null) return;
|
|
1326
|
+
const now = Date.now();
|
|
1327
|
+
if (expires < now) return;
|
|
1328
|
+
return expires - now;
|
|
635
1329
|
}
|
|
1330
|
+
/**
|
|
1331
|
+
* Get the TTL value from the cacheableTtl, primaryTtl, and secondaryTtl values.
|
|
1332
|
+
* @param cacheableTtl - The cacheableTtl value to use.
|
|
1333
|
+
* @param primaryTtl - The primaryTtl value to use.
|
|
1334
|
+
* @param secondaryTtl - The secondaryTtl value to use.
|
|
1335
|
+
* @returns {number | undefined} The TTL value in milliseconds, or undefined if all values are undefined.
|
|
1336
|
+
*/
|
|
636
1337
|
function getCascadingTtl(cacheableTtl, primaryTtl, secondaryTtl) {
|
|
637
|
-
|
|
1338
|
+
return secondaryTtl ?? primaryTtl ?? shorthandToMilliseconds(cacheableTtl);
|
|
638
1339
|
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Calculate the TTL value from the expires value. If the ttl is undefined, it will be set to the expires value. If the
|
|
1342
|
+
* expires value is undefined, it will be set to the ttl value. If both values are defined, the smaller of the two will be used.
|
|
1343
|
+
* @param ttl
|
|
1344
|
+
* @param expires
|
|
1345
|
+
* @returns
|
|
1346
|
+
*/
|
|
639
1347
|
function calculateTtlFromExpiration(ttl, expires) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return ttlFromExpires;
|
|
647
|
-
}
|
|
648
|
-
if (expires && expires > expiresFromTtl) {
|
|
649
|
-
return ttl;
|
|
650
|
-
}
|
|
651
|
-
return ttlFromExpires;
|
|
1348
|
+
const ttlFromExpires = getTtlFromExpires(expires);
|
|
1349
|
+
const expiresFromTtl = ttl ? Date.now() + ttl : void 0;
|
|
1350
|
+
if (ttlFromExpires === void 0) return ttl;
|
|
1351
|
+
if (expiresFromTtl === void 0) return ttlFromExpires;
|
|
1352
|
+
if (expires && expires > expiresFromTtl) return ttl;
|
|
1353
|
+
return ttlFromExpires;
|
|
652
1354
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
1355
|
+
//#endregion
|
|
1356
|
+
exports.CacheTags = CacheTags;
|
|
1357
|
+
exports.HashAlgorithm = HashAlgorithm;
|
|
1358
|
+
exports.Stats = Stats;
|
|
1359
|
+
exports.calculateTtlFromExpiration = calculateTtlFromExpiration;
|
|
1360
|
+
exports.coalesceAsync = coalesceAsync;
|
|
1361
|
+
exports.createWrapKey = createWrapKey;
|
|
1362
|
+
exports.getCascadingTtl = getCascadingTtl;
|
|
1363
|
+
exports.getOrSet = getOrSet;
|
|
1364
|
+
exports.getOrSetSync = getOrSetSync;
|
|
1365
|
+
exports.getTtlFromExpires = getTtlFromExpires;
|
|
1366
|
+
exports.hash = hash;
|
|
1367
|
+
exports.hashSync = hashSync;
|
|
1368
|
+
exports.hashToNumber = hashToNumber;
|
|
1369
|
+
exports.hashToNumberSync = hashToNumberSync;
|
|
1370
|
+
exports.isKeyvInstance = isKeyvInstance;
|
|
1371
|
+
exports.isObject = isObject;
|
|
1372
|
+
exports.lessThan = lessThan;
|
|
1373
|
+
exports.nodeCacheStatsEventMap = nodeCacheStatsEventMap;
|
|
1374
|
+
exports.resolvePerStoreTtl = resolvePerStoreTtl;
|
|
1375
|
+
exports.runIfFn = runIfFn;
|
|
1376
|
+
exports.shorthandToMilliseconds = shorthandToMilliseconds;
|
|
1377
|
+
exports.shorthandToTime = shorthandToTime;
|
|
1378
|
+
exports.sleep = sleep;
|
|
1379
|
+
exports.wrap = wrap;
|
|
1380
|
+
exports.wrapSync = wrapSync;
|