@windrun-huaiin/backend-core 12.0.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_commonjs-dynamic-modules.js +7 -0
- package/dist/_virtual/_commonjs-dynamic-modules.mjs +5 -0
- package/dist/_virtual/_commonjsHelpers.js +10 -0
- package/dist/_virtual/_commonjsHelpers.mjs +7 -0
- package/dist/_virtual/aes.js +5 -0
- package/dist/_virtual/aes.mjs +3 -0
- package/dist/_virtual/blowfish.js +5 -0
- package/dist/_virtual/blowfish.mjs +3 -0
- package/dist/_virtual/cipher-core.js +5 -0
- package/dist/_virtual/cipher-core.mjs +3 -0
- package/dist/_virtual/core.js +5 -0
- package/dist/_virtual/core.mjs +3 -0
- package/dist/_virtual/enc-base64.js +5 -0
- package/dist/_virtual/enc-base64.mjs +3 -0
- package/dist/_virtual/enc-base64url.js +5 -0
- package/dist/_virtual/enc-base64url.mjs +3 -0
- package/dist/_virtual/enc-utf16.js +5 -0
- package/dist/_virtual/enc-utf16.mjs +3 -0
- package/dist/_virtual/evpkdf.js +5 -0
- package/dist/_virtual/evpkdf.mjs +3 -0
- package/dist/_virtual/format-hex.js +5 -0
- package/dist/_virtual/format-hex.mjs +3 -0
- package/dist/_virtual/hmac.js +5 -0
- package/dist/_virtual/hmac.mjs +3 -0
- package/dist/_virtual/index.js +11 -0
- package/dist/_virtual/index.mjs +7 -0
- package/dist/_virtual/index2.js +5 -0
- package/dist/_virtual/index2.mjs +3 -0
- package/dist/_virtual/lib-typedarrays.js +5 -0
- package/dist/_virtual/lib-typedarrays.mjs +3 -0
- package/dist/_virtual/md5.js +5 -0
- package/dist/_virtual/md5.mjs +3 -0
- package/dist/_virtual/mode-cfb.js +5 -0
- package/dist/_virtual/mode-cfb.mjs +3 -0
- package/dist/_virtual/mode-ctr-gladman.js +5 -0
- package/dist/_virtual/mode-ctr-gladman.mjs +3 -0
- package/dist/_virtual/mode-ctr.js +5 -0
- package/dist/_virtual/mode-ctr.mjs +3 -0
- package/dist/_virtual/mode-ecb.js +5 -0
- package/dist/_virtual/mode-ecb.mjs +3 -0
- package/dist/_virtual/mode-ofb.js +5 -0
- package/dist/_virtual/mode-ofb.mjs +3 -0
- package/dist/_virtual/pad-ansix923.js +5 -0
- package/dist/_virtual/pad-ansix923.mjs +3 -0
- package/dist/_virtual/pad-iso10126.js +5 -0
- package/dist/_virtual/pad-iso10126.mjs +3 -0
- package/dist/_virtual/pad-iso97971.js +5 -0
- package/dist/_virtual/pad-iso97971.mjs +3 -0
- package/dist/_virtual/pad-nopadding.js +5 -0
- package/dist/_virtual/pad-nopadding.mjs +3 -0
- package/dist/_virtual/pad-zeropadding.js +5 -0
- package/dist/_virtual/pad-zeropadding.mjs +3 -0
- package/dist/_virtual/pbkdf2.js +5 -0
- package/dist/_virtual/pbkdf2.mjs +3 -0
- package/dist/_virtual/rabbit-legacy.js +5 -0
- package/dist/_virtual/rabbit-legacy.mjs +3 -0
- package/dist/_virtual/rabbit.js +5 -0
- package/dist/_virtual/rabbit.mjs +3 -0
- package/dist/_virtual/rc4.js +5 -0
- package/dist/_virtual/rc4.mjs +3 -0
- package/dist/_virtual/ripemd160.js +5 -0
- package/dist/_virtual/ripemd160.mjs +3 -0
- package/dist/_virtual/sha1.js +5 -0
- package/dist/_virtual/sha1.mjs +3 -0
- package/dist/_virtual/sha224.js +5 -0
- package/dist/_virtual/sha224.mjs +3 -0
- package/dist/_virtual/sha256.js +5 -0
- package/dist/_virtual/sha256.mjs +3 -0
- package/dist/_virtual/sha3.js +5 -0
- package/dist/_virtual/sha3.mjs +3 -0
- package/dist/_virtual/sha384.js +5 -0
- package/dist/_virtual/sha384.mjs +3 -0
- package/dist/_virtual/sha512.js +5 -0
- package/dist/_virtual/sha512.mjs +3 -0
- package/dist/_virtual/tripledes.js +5 -0
- package/dist/_virtual/tripledes.mjs +3 -0
- package/dist/_virtual/x64-core.js +5 -0
- package/dist/_virtual/x64-core.mjs +3 -0
- package/dist/index.js +48 -0
- package/dist/index.mjs +7 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +48 -0
- package/dist/lib/index.mjs +7 -0
- package/dist/lib/upstash/index.d.ts +7 -0
- package/dist/lib/upstash/index.d.ts.map +1 -0
- package/dist/lib/upstash/qstash.d.ts +36 -0
- package/dist/lib/upstash/qstash.d.ts.map +1 -0
- package/dist/lib/upstash/qstash.js +134 -0
- package/dist/lib/upstash/qstash.mjs +128 -0
- package/dist/lib/upstash/redis-counter.d.ts +17 -0
- package/dist/lib/upstash/redis-counter.d.ts.map +1 -0
- package/dist/lib/upstash/redis-counter.js +40 -0
- package/dist/lib/upstash/redis-counter.mjs +35 -0
- package/dist/lib/upstash/redis-favorite.d.ts +21 -0
- package/dist/lib/upstash/redis-favorite.d.ts.map +1 -0
- package/dist/lib/upstash/redis-favorite.js +60 -0
- package/dist/lib/upstash/redis-favorite.mjs +54 -0
- package/dist/lib/upstash/redis-like.d.ts +21 -0
- package/dist/lib/upstash/redis-like.d.ts.map +1 -0
- package/dist/lib/upstash/redis-like.js +60 -0
- package/dist/lib/upstash/redis-like.mjs +54 -0
- package/dist/lib/upstash/redis-lock.d.ts +13 -0
- package/dist/lib/upstash/redis-lock.d.ts.map +1 -0
- package/dist/lib/upstash/redis-lock.js +59 -0
- package/dist/lib/upstash/redis-lock.mjs +55 -0
- package/dist/lib/upstash/redis-structures.d.ts +63 -0
- package/dist/lib/upstash/redis-structures.d.ts.map +1 -0
- package/dist/lib/upstash/redis-structures.js +175 -0
- package/dist/lib/upstash/redis-structures.mjs +159 -0
- package/dist/lib/upstash-config.d.ts +19 -0
- package/dist/lib/upstash-config.d.ts.map +1 -0
- package/dist/lib/upstash-config.js +247 -0
- package/dist/lib/upstash-config.mjs +242 -0
- package/dist/node_modules/.pnpm/@upstash_qstash@2.10.1/node_modules/@upstash/qstash/chunk-35B33QW3.js +1848 -0
- package/dist/node_modules/.pnpm/@upstash_qstash@2.10.1/node_modules/@upstash/qstash/chunk-35B33QW3.mjs +1830 -0
- package/dist/node_modules/.pnpm/@upstash_redis@1.37.0/node_modules/@upstash/redis/chunk-IH7W44G6.js +5308 -0
- package/dist/node_modules/.pnpm/@upstash_redis@1.37.0/node_modules/@upstash/redis/chunk-IH7W44G6.mjs +5302 -0
- package/dist/node_modules/.pnpm/@upstash_redis@1.37.0/node_modules/@upstash/redis/nodejs.js +116 -0
- package/dist/node_modules/.pnpm/@upstash_redis@1.37.0/node_modules/@upstash/redis/nodejs.mjs +113 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/aes.js +248 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/aes.mjs +246 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/blowfish.js +485 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/blowfish.mjs +483 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/cipher-core.js +906 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/cipher-core.mjs +904 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/core.js +818 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/core.mjs +816 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-base64.js +146 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-base64.mjs +144 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-base64url.js +158 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-base64url.mjs +156 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-utf16.js +159 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/enc-utf16.mjs +157 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/evpkdf.js +146 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/evpkdf.mjs +144 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/format-hex.js +77 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/format-hex.mjs +75 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac.js +153 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/hmac.mjs +151 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/index.js +62 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/index.mjs +60 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/lib-typedarrays.js +86 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/lib-typedarrays.mjs +84 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/md5.js +278 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/md5.mjs +276 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-cfb.js +91 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-cfb.mjs +89 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ctr-gladman.js +127 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ctr-gladman.mjs +125 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ctr.js +69 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ctr.mjs +67 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ecb.js +51 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ecb.mjs +49 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ofb.js +65 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/mode-ofb.mjs +63 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-ansix923.js +60 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-ansix923.mjs +58 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-iso10126.js +55 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-iso10126.mjs +53 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-iso97971.js +51 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-iso97971.mjs +49 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-nopadding.js +41 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-nopadding.mjs +39 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-zeropadding.js +58 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pad-zeropadding.mjs +56 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pbkdf2.js +157 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/pbkdf2.mjs +155 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rabbit-legacy.js +204 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rabbit-legacy.mjs +202 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rabbit.js +206 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rabbit.mjs +204 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rc4.js +153 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/rc4.mjs +151 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/ripemd160.js +277 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/ripemd160.mjs +275 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha1.js +160 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha1.mjs +158 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha224.js +91 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha224.mjs +89 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha256.js +209 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha256.mjs +207 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha3.js +337 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha3.mjs +335 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha384.js +95 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha384.mjs +93 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha512.js +337 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/sha512.mjs +335 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/tripledes.js +793 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/tripledes.mjs +791 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/x64-core.js +314 -0
- package/dist/node_modules/.pnpm/crypto-js@4.2.0/node_modules/crypto-js/x64-core.mjs +312 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jws/compact/verify.js +26 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jws/compact/verify.mjs +24 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jws/flattened/verify.js +127 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jws/flattened/verify.mjs +125 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jwt/verify.js +20 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/jwt/verify.mjs +18 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/key/import.js +31 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/key/import.mjs +29 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/buffer_utils.js +18 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/buffer_utils.mjs +14 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/check_key_type.js +82 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/check_key_type.mjs +80 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/crypto_key.js +103 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/crypto_key.mjs +101 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/epoch.js +7 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/epoch.mjs +3 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/invalid_key_input.js +38 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/invalid_key_input.mjs +33 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_disjoint.js +27 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_disjoint.mjs +23 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_jwk.js +21 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_jwk.mjs +16 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_object.js +22 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/is_object.mjs +18 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/jwt_claims_set.js +111 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/jwt_claims_set.mjs +107 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/secs.js +61 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/secs.mjs +57 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_algorithms.js +16 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_algorithms.mjs +12 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_crit.js +40 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/lib/validate_crit.mjs +36 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/base64url.js +15 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/base64url.mjs +13 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/check_key_length.js +23 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/check_key_length.mjs +19 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/dsa_digest.js +30 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/dsa_digest.mjs +26 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_named_curve.js +60 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_named_curve.mjs +56 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_sign_verify_key.js +35 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/get_sign_verify_key.mjs +31 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/hmac_digest.js +20 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/hmac_digest.mjs +16 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_like.js +15 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_like.mjs +10 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_object.js +28 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/is_key_object.mjs +5 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/jwk_to_key.js +14 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/jwk_to_key.mjs +10 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/node_key.js +115 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/node_key.mjs +111 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/sign.js +42 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/sign.mjs +19 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/verify.js +54 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/verify.mjs +31 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/webcrypto.js +32 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/runtime/webcrypto.mjs +7 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/util/errors.js +69 -0
- package/dist/node_modules/.pnpm/jose@5.10.0/node_modules/jose/dist/node/esm/util/errors.mjs +60 -0
- package/dist/node_modules/.pnpm/neverthrow@7.2.0/node_modules/neverthrow/dist/index.es.js +422 -0
- package/dist/node_modules/.pnpm/neverthrow@7.2.0/node_modules/neverthrow/dist/index.es.mjs +415 -0
- package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.web.js +6 -0
- package/dist/node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.web.mjs +4 -0
- package/dist/prisma/prisma.d.ts +1 -1
- package/dist/prisma/prisma.d.ts.map +1 -1
- package/package.json +14 -11
- package/src/lib/index.ts +2 -0
- package/src/lib/upstash/index.ts +6 -0
- package/src/lib/upstash/qstash.ts +159 -0
- package/src/lib/upstash/redis-counter.ts +35 -0
- package/src/lib/upstash/redis-favorite.ts +56 -0
- package/src/lib/upstash/redis-like.ts +56 -0
- package/src/lib/upstash/redis-lock.ts +59 -0
- package/src/lib/upstash/redis-structures.ts +200 -0
- package/src/lib/upstash-config.ts +261 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +0 -54
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +0 -51
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +0 -44
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +0 -35
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +0 -31
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +0 -18
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +0 -587
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +0 -527
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +0 -447
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +0 -399
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +0 -245
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +0 -232
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +0 -68
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +0 -62
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +0 -39
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +0 -37
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +0 -80
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +0 -75
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +0 -101
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +0 -86
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +0 -102
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +0 -76
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +0 -56
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +0 -52
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +0 -1205
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +0 -1157
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +0 -407
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +0 -374
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +0 -9
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +0 -7
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { withRedis } from '../upstash-config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Increment a counter (e.g. views, forwards). Returns null if Redis is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
export const incrCounter = async (key: string, delta = 1): Promise<number | null> => {
|
|
7
|
+
return withRedis((redis) => redis.incrby(key, delta));
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get a counter value. Returns null if Redis is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
export const getCounter = async (key: string): Promise<number | null> => {
|
|
14
|
+
return withRedis(async (redis) => {
|
|
15
|
+
const value = await redis.get<number>(key);
|
|
16
|
+
return value ?? 0;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Increment a unique counter via SET (e.g. unique views). Returns null if Redis is unavailable.
|
|
22
|
+
*/
|
|
23
|
+
export const incrUniqueCounter = async (setKey: string, memberId: string): Promise<number | null> => {
|
|
24
|
+
return withRedis(async (redis) => {
|
|
25
|
+
await redis.sadd(setKey, memberId);
|
|
26
|
+
return redis.scard(setKey);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get unique counter value (SET cardinality). Returns null if Redis is unavailable.
|
|
32
|
+
*/
|
|
33
|
+
export const getUniqueCounter = async (setKey: string): Promise<number | null> => {
|
|
34
|
+
return withRedis((redis) => redis.scard(setKey));
|
|
35
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { withRedis } from '../upstash-config';
|
|
2
|
+
|
|
3
|
+
const favoriteTargetKey = (targetId: string): string => `favorite:target:${targetId}`;
|
|
4
|
+
const favoriteUserKey = (userId: string): string => `favorite:user:${userId}`;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Favorite a target. Returns true if added, false if already favorited, null if Redis is unavailable.
|
|
8
|
+
*/
|
|
9
|
+
export const addFavorite = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
10
|
+
return withRedis(async (redis) => {
|
|
11
|
+
const added = await redis.sadd(favoriteTargetKey(targetId), userId);
|
|
12
|
+
if (added === 1) {
|
|
13
|
+
await redis.sadd(favoriteUserKey(userId), targetId);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Remove a favorite. Returns true if removed, false if not found, null if Redis is unavailable.
|
|
22
|
+
*/
|
|
23
|
+
export const removeFavorite = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
24
|
+
return withRedis(async (redis) => {
|
|
25
|
+
const removed = await redis.srem(favoriteTargetKey(targetId), userId);
|
|
26
|
+
if (removed === 1) {
|
|
27
|
+
await redis.srem(favoriteUserKey(userId), targetId);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check whether a user has favorited a target. Returns null if Redis is unavailable.
|
|
36
|
+
*/
|
|
37
|
+
export const isFavorited = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
38
|
+
return withRedis(async (redis) => {
|
|
39
|
+
const result = await redis.sismember(favoriteTargetKey(targetId), userId);
|
|
40
|
+
return result === 1;
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get favorite count for a target. Returns null if Redis is unavailable.
|
|
46
|
+
*/
|
|
47
|
+
export const getFavoriteCount = async (targetId: string): Promise<number | null> => {
|
|
48
|
+
return withRedis((redis) => redis.scard(favoriteTargetKey(targetId)));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get target ids favorited by a user. Returns null if Redis is unavailable.
|
|
53
|
+
*/
|
|
54
|
+
export const getUserFavorites = async (userId: string): Promise<string[] | null> => {
|
|
55
|
+
return withRedis((redis) => redis.smembers<string[]>(favoriteUserKey(userId)));
|
|
56
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { withRedis } from '../upstash-config';
|
|
2
|
+
|
|
3
|
+
const likeTargetKey = (targetId: string): string => `like:target:${targetId}`;
|
|
4
|
+
const likeUserKey = (userId: string): string => `like:user:${userId}`;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Like a target. Returns true if the like was added, false if it already existed, null if Redis is unavailable.
|
|
8
|
+
*/
|
|
9
|
+
export const likeTarget = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
10
|
+
return withRedis(async (redis) => {
|
|
11
|
+
const added = await redis.sadd(likeTargetKey(targetId), userId);
|
|
12
|
+
if (added === 1) {
|
|
13
|
+
await redis.sadd(likeUserKey(userId), targetId);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Unlike a target. Returns true if removed, false if it didn't exist, null if Redis is unavailable.
|
|
22
|
+
*/
|
|
23
|
+
export const unlikeTarget = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
24
|
+
return withRedis(async (redis) => {
|
|
25
|
+
const removed = await redis.srem(likeTargetKey(targetId), userId);
|
|
26
|
+
if (removed === 1) {
|
|
27
|
+
await redis.srem(likeUserKey(userId), targetId);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check whether a user liked a target. Returns null if Redis is unavailable.
|
|
36
|
+
*/
|
|
37
|
+
export const isTargetLiked = async (targetId: string, userId: string): Promise<boolean | null> => {
|
|
38
|
+
return withRedis(async (redis) => {
|
|
39
|
+
const result = await redis.sismember(likeTargetKey(targetId), userId);
|
|
40
|
+
return result === 1;
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get like count for a target (unique by user). Returns null if Redis is unavailable.
|
|
46
|
+
*/
|
|
47
|
+
export const getTargetLikeCount = async (targetId: string): Promise<number | null> => {
|
|
48
|
+
return withRedis((redis) => redis.scard(likeTargetKey(targetId)));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get target ids liked by a user. Returns null if Redis is unavailable.
|
|
53
|
+
*/
|
|
54
|
+
export const getUserLikedTargets = async (userId: string): Promise<string[] | null> => {
|
|
55
|
+
return withRedis((redis) => redis.smembers<string[]>(likeUserKey(userId)));
|
|
56
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { withRedis } from '../upstash-config';
|
|
2
|
+
|
|
3
|
+
const unlockScript = `
|
|
4
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
5
|
+
return redis.call("del", KEYS[1])
|
|
6
|
+
else
|
|
7
|
+
return 0
|
|
8
|
+
end
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
const generateToken = (): string => {
|
|
12
|
+
try {
|
|
13
|
+
return crypto.randomUUID();
|
|
14
|
+
} catch {
|
|
15
|
+
return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Acquire a distributed lock. Returns the lock token or null when unavailable.
|
|
21
|
+
*/
|
|
22
|
+
export const acquireLock = async (key: string, ttlMs: number): Promise<string | null> => {
|
|
23
|
+
return withRedis(async (redis) => {
|
|
24
|
+
const token = generateToken();
|
|
25
|
+
const result = await redis.set(key, token, { nx: true, px: ttlMs });
|
|
26
|
+
return result === 'OK' ? token : null;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Release a distributed lock. Returns false when the lock client is unavailable.
|
|
32
|
+
*/
|
|
33
|
+
export const releaseLock = async (key: string, token: string): Promise<boolean> => {
|
|
34
|
+
const result = await withRedis(async (redis) => {
|
|
35
|
+
const released = await redis.eval(unlockScript, [key], [token]);
|
|
36
|
+
return Number(released) === 1;
|
|
37
|
+
});
|
|
38
|
+
return result ?? false;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Run a function under a distributed lock. Returns null when the lock is unavailable.
|
|
43
|
+
*/
|
|
44
|
+
export const withLock = async <T>(
|
|
45
|
+
key: string,
|
|
46
|
+
ttlMs: number,
|
|
47
|
+
fn: () => Promise<T> | T
|
|
48
|
+
): Promise<T | null> => {
|
|
49
|
+
const token = await acquireLock(key, ttlMs);
|
|
50
|
+
if (!token) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
return await fn();
|
|
56
|
+
} finally {
|
|
57
|
+
await releaseLock(key, token);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { withRedis } from '../upstash-config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Set a plain string value with optional TTL (seconds).
|
|
5
|
+
*/
|
|
6
|
+
export const setString = async (
|
|
7
|
+
key: string,
|
|
8
|
+
value: string,
|
|
9
|
+
ttlSec?: number
|
|
10
|
+
): Promise<boolean> => {
|
|
11
|
+
return withRedis(async (redis) => {
|
|
12
|
+
if (ttlSec && ttlSec > 0) {
|
|
13
|
+
await redis.set(key, value, { ex: ttlSec });
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
await redis.set(key, value);
|
|
18
|
+
return true;
|
|
19
|
+
}).then((result) => result ?? false);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get a plain string value. Returns null if Redis is unavailable or key missing.
|
|
24
|
+
*/
|
|
25
|
+
export const getString = async (key: string): Promise<string | null> => {
|
|
26
|
+
return withRedis((redis) => redis.get<string>(key));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Store an object as JSON string with optional TTL (seconds).
|
|
31
|
+
*/
|
|
32
|
+
export const setJson = async <T>(
|
|
33
|
+
key: string,
|
|
34
|
+
value: T,
|
|
35
|
+
ttlSec?: number
|
|
36
|
+
): Promise<boolean> => {
|
|
37
|
+
return withRedis(async (redis) => {
|
|
38
|
+
const payload = JSON.stringify(value);
|
|
39
|
+
if (ttlSec && ttlSec > 0) {
|
|
40
|
+
await redis.set(key, payload, { ex: ttlSec });
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
await redis.set(key, payload);
|
|
45
|
+
return true;
|
|
46
|
+
}).then((result) => result ?? false);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get an object stored as JSON string. Returns null if missing or invalid JSON.
|
|
51
|
+
*/
|
|
52
|
+
export const getJson = async <T>(key: string): Promise<T | null> => {
|
|
53
|
+
return withRedis(async (redis) => {
|
|
54
|
+
const payload = await redis.get<string>(key);
|
|
55
|
+
if (!payload) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
return JSON.parse(payload) as T;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Delete a key. Returns false if Redis is unavailable.
|
|
69
|
+
*/
|
|
70
|
+
export const deleteKey = async (key: string): Promise<boolean> => {
|
|
71
|
+
const result = await withRedis(async (redis) => {
|
|
72
|
+
const deleted = await redis.del(key);
|
|
73
|
+
return deleted > 0;
|
|
74
|
+
});
|
|
75
|
+
return result ?? false;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Set a hash field value.
|
|
80
|
+
*/
|
|
81
|
+
export const setHashField = async (key: string, field: string, value: string): Promise<boolean> => {
|
|
82
|
+
const result = await withRedis(async (redis) => {
|
|
83
|
+
const changed = await redis.hset(key, { [field]: value });
|
|
84
|
+
return changed > 0;
|
|
85
|
+
});
|
|
86
|
+
return result ?? false;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get a hash field value.
|
|
91
|
+
*/
|
|
92
|
+
export const getHashField = async (key: string, field: string): Promise<string | null> => {
|
|
93
|
+
return withRedis((redis) => redis.hget<string>(key, field));
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Store a hash field as JSON string.
|
|
98
|
+
*/
|
|
99
|
+
export const setHashJson = async <T>(
|
|
100
|
+
key: string,
|
|
101
|
+
field: string,
|
|
102
|
+
value: T
|
|
103
|
+
): Promise<boolean> => {
|
|
104
|
+
const result = await withRedis(async (redis) => {
|
|
105
|
+
const payload = JSON.stringify(value);
|
|
106
|
+
const changed = await redis.hset(key, { [field]: payload });
|
|
107
|
+
return changed > 0;
|
|
108
|
+
});
|
|
109
|
+
return result ?? false;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get a hash field stored as JSON string.
|
|
114
|
+
*/
|
|
115
|
+
export const getHashJson = async <T>(key: string, field: string): Promise<T | null> => {
|
|
116
|
+
return withRedis(async (redis) => {
|
|
117
|
+
const payload = await redis.hget<string>(key, field);
|
|
118
|
+
if (!payload) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
return JSON.parse(payload) as T;
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get all hash fields.
|
|
132
|
+
*/
|
|
133
|
+
export const getHashAll = async (key: string): Promise<Record<string, string> | null> => {
|
|
134
|
+
return withRedis(async (redis) => {
|
|
135
|
+
const result = await redis.hgetall<Record<string, string>>(key);
|
|
136
|
+
return result ?? {};
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Remove a hash field.
|
|
142
|
+
*/
|
|
143
|
+
export const deleteHashField = async (key: string, field: string): Promise<boolean> => {
|
|
144
|
+
const result = await withRedis(async (redis) => {
|
|
145
|
+
const removed = await redis.hdel(key, field);
|
|
146
|
+
return removed > 0;
|
|
147
|
+
});
|
|
148
|
+
return result ?? false;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
type ListDirection = 'left' | 'right';
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Push values to a list. Returns list length or null if Redis is unavailable.
|
|
155
|
+
*/
|
|
156
|
+
export const pushList = async (
|
|
157
|
+
key: string,
|
|
158
|
+
values: string[],
|
|
159
|
+
direction: ListDirection = 'right'
|
|
160
|
+
): Promise<number | null> => {
|
|
161
|
+
return withRedis((redis) => {
|
|
162
|
+
if (values.length === 0) {
|
|
163
|
+
return redis.llen(key);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return direction === 'left'
|
|
167
|
+
? redis.lpush(key, ...values)
|
|
168
|
+
: redis.rpush(key, ...values);
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Pop a value from a list.
|
|
174
|
+
*/
|
|
175
|
+
export const popList = async (
|
|
176
|
+
key: string,
|
|
177
|
+
direction: ListDirection = 'right'
|
|
178
|
+
): Promise<string | null> => {
|
|
179
|
+
return withRedis((redis) =>
|
|
180
|
+
direction === 'left' ? redis.lpop<string>(key) : redis.rpop<string>(key)
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Get a range from a list.
|
|
186
|
+
*/
|
|
187
|
+
export const rangeList = async (
|
|
188
|
+
key: string,
|
|
189
|
+
start = 0,
|
|
190
|
+
stop = -1
|
|
191
|
+
): Promise<string[] | null> => {
|
|
192
|
+
return withRedis((redis) => redis.lrange<string>(key, start, stop));
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get list length.
|
|
197
|
+
*/
|
|
198
|
+
export const listLength = async (key: string): Promise<number | null> => {
|
|
199
|
+
return withRedis((redis) => redis.llen(key));
|
|
200
|
+
};
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { Redis } from '@upstash/redis';
|
|
2
|
+
import { Client as QstashClient } from '@upstash/qstash';
|
|
3
|
+
|
|
4
|
+
let cachedRedis: Redis | null = null;
|
|
5
|
+
let cachedQstash: QstashClient | null = null;
|
|
6
|
+
let redisInitPromise: Promise<Redis | null> | null = null;
|
|
7
|
+
let qstashInitPromise: Promise<QstashClient | null> | null = null;
|
|
8
|
+
|
|
9
|
+
let redisWarnedMissingEnv = false;
|
|
10
|
+
let redisWarnedInvalidEnv = false;
|
|
11
|
+
let redisWarnedInitError = false;
|
|
12
|
+
let redisWarnedHealthCheck = false;
|
|
13
|
+
let redisWarnedHealthSchedule = false;
|
|
14
|
+
|
|
15
|
+
let qstashWarnedMissingEnv = false;
|
|
16
|
+
let qstashWarnedInitError = false;
|
|
17
|
+
let qstashWarnedHealthCheck = false;
|
|
18
|
+
let qstashWarnedHealthSchedule = false;
|
|
19
|
+
|
|
20
|
+
let redisHealthTimer: ReturnType<typeof setTimeout> | null = null;
|
|
21
|
+
let qstashHealthTimer: ReturnType<typeof setTimeout> | null = null;
|
|
22
|
+
|
|
23
|
+
const isNonEmpty = (value: string | undefined): value is string =>
|
|
24
|
+
typeof value === 'string' && value.trim().length > 0;
|
|
25
|
+
|
|
26
|
+
const isValidUrl = (value: string): boolean => {
|
|
27
|
+
try {
|
|
28
|
+
const parsed = new URL(value);
|
|
29
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const parseMinutes = (value: string | undefined, fallback: number): number => {
|
|
36
|
+
if (!isNonEmpty(value)) {
|
|
37
|
+
return fallback;
|
|
38
|
+
}
|
|
39
|
+
const minutes = Number(value);
|
|
40
|
+
if (!Number.isFinite(minutes) || minutes <= 0) {
|
|
41
|
+
return fallback;
|
|
42
|
+
}
|
|
43
|
+
return minutes;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const getRedisHealthIntervalMinutes = (): number =>
|
|
47
|
+
parseMinutes(process.env.UPSTASH_REDIS_HEALTHCHECK_INTERVAL_MINUTES, 10);
|
|
48
|
+
|
|
49
|
+
const getQstashHealthIntervalMinutes = (): number =>
|
|
50
|
+
parseMinutes(process.env.UPSTASH_QSTASH_HEALTHCHECK_INTERVAL_MINUTES, 10);
|
|
51
|
+
|
|
52
|
+
const getQstashHealthcheckUrl = (): string =>
|
|
53
|
+
process.env.UPSTASH_QSTASH_HEALTHCHECK_URL ?? 'https://qstash.upstash.io/v2/topics';
|
|
54
|
+
|
|
55
|
+
const scheduleRedisHealthCheck = (): void => {
|
|
56
|
+
if (redisHealthTimer || !cachedRedis) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const delayMs = getRedisHealthIntervalMinutes() * 60_000;
|
|
60
|
+
redisHealthTimer = setTimeout(async () => {
|
|
61
|
+
redisHealthTimer = null;
|
|
62
|
+
if (!cachedRedis) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await cachedRedis.ping();
|
|
67
|
+
} catch (error) {
|
|
68
|
+
cachedRedis = null;
|
|
69
|
+
if (!redisWarnedHealthCheck) {
|
|
70
|
+
redisWarnedHealthCheck = true;
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
console.warn(`[Upstash Config] Redis health check failed: ${message}`);
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
try {
|
|
76
|
+
scheduleRedisHealthCheck();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (!redisWarnedHealthSchedule) {
|
|
79
|
+
redisWarnedHealthSchedule = true;
|
|
80
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
81
|
+
console.warn(`[Upstash Config] Redis health check schedule failed: ${message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, delayMs);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const checkQstashHealth = async (token: string): Promise<void> => {
|
|
89
|
+
const response = await fetch(getQstashHealthcheckUrl(), {
|
|
90
|
+
method: 'GET',
|
|
91
|
+
headers: {
|
|
92
|
+
Authorization: `Bearer ${token}`,
|
|
93
|
+
},
|
|
94
|
+
cache: 'no-store',
|
|
95
|
+
});
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
throw new Error(`HTTP ${response.status}`);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const scheduleQstashHealthCheck = (token: string): void => {
|
|
102
|
+
if (qstashHealthTimer || !cachedQstash) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const delayMs = getQstashHealthIntervalMinutes() * 60_000;
|
|
106
|
+
qstashHealthTimer = setTimeout(async () => {
|
|
107
|
+
qstashHealthTimer = null;
|
|
108
|
+
if (!cachedQstash) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
await checkQstashHealth(token);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
cachedQstash = null;
|
|
115
|
+
if (!qstashWarnedHealthCheck) {
|
|
116
|
+
qstashWarnedHealthCheck = true;
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
console.warn(`[Upstash Config] QStash health check failed: ${message}`);
|
|
119
|
+
}
|
|
120
|
+
} finally {
|
|
121
|
+
try {
|
|
122
|
+
scheduleQstashHealthCheck(token);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (!qstashWarnedHealthSchedule) {
|
|
125
|
+
qstashWarnedHealthSchedule = true;
|
|
126
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
127
|
+
console.warn(`[Upstash Config] QStash health check schedule failed: ${message}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}, delayMs);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the Upstash Redis client. Returns null when required env vars are missing/invalid.
|
|
136
|
+
*
|
|
137
|
+
* Singleton semantics:
|
|
138
|
+
* - read-through cached instance only
|
|
139
|
+
*/
|
|
140
|
+
export const getRedis = (): Redis | null => {
|
|
141
|
+
return cachedRedis;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const ensureRedis = async (): Promise<Redis | null> => {
|
|
145
|
+
if (cachedRedis) {
|
|
146
|
+
return cachedRedis;
|
|
147
|
+
}
|
|
148
|
+
if (redisInitPromise) {
|
|
149
|
+
return redisInitPromise;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
redisInitPromise = (async () => {
|
|
153
|
+
const { UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN } = process.env;
|
|
154
|
+
if (!isNonEmpty(UPSTASH_REDIS_REST_URL) || !isNonEmpty(UPSTASH_REDIS_REST_TOKEN)) {
|
|
155
|
+
if (!redisWarnedMissingEnv) {
|
|
156
|
+
redisWarnedMissingEnv = true;
|
|
157
|
+
console.warn(
|
|
158
|
+
'[Upstash Config] Redis disabled: missing UPSTASH_REDIS_REST_URL or UPSTASH_REDIS_REST_TOKEN'
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!isValidUrl(UPSTASH_REDIS_REST_URL)) {
|
|
165
|
+
if (!redisWarnedInvalidEnv) {
|
|
166
|
+
redisWarnedInvalidEnv = true;
|
|
167
|
+
console.warn('[Upstash Config] Redis disabled: UPSTASH_REDIS_REST_URL is not a valid URL');
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const client = new Redis({
|
|
174
|
+
url: UPSTASH_REDIS_REST_URL,
|
|
175
|
+
token: UPSTASH_REDIS_REST_TOKEN,
|
|
176
|
+
});
|
|
177
|
+
await client.ping();
|
|
178
|
+
cachedRedis = client;
|
|
179
|
+
scheduleRedisHealthCheck();
|
|
180
|
+
return cachedRedis;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
if (!redisWarnedInitError) {
|
|
183
|
+
redisWarnedInitError = true;
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
console.warn(`[Upstash Config] Redis init failed: ${message}`);
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
} finally {
|
|
189
|
+
redisInitPromise = null;
|
|
190
|
+
}
|
|
191
|
+
})();
|
|
192
|
+
|
|
193
|
+
return redisInitPromise;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get the Upstash QStash client. Returns null when required env vars are missing.
|
|
198
|
+
*
|
|
199
|
+
* Singleton semantics:
|
|
200
|
+
* - read-through cached instance only
|
|
201
|
+
*/
|
|
202
|
+
export const getQstash = (): QstashClient | null => {
|
|
203
|
+
return cachedQstash;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const ensureQstash = async (): Promise<QstashClient | null> => {
|
|
207
|
+
if (cachedQstash) {
|
|
208
|
+
return cachedQstash;
|
|
209
|
+
}
|
|
210
|
+
if (qstashInitPromise) {
|
|
211
|
+
return qstashInitPromise;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
qstashInitPromise = (async () => {
|
|
215
|
+
const { QSTASH_TOKEN } = process.env;
|
|
216
|
+
if (!isNonEmpty(QSTASH_TOKEN)) {
|
|
217
|
+
if (!qstashWarnedMissingEnv) {
|
|
218
|
+
qstashWarnedMissingEnv = true;
|
|
219
|
+
console.warn('[Upstash Config] QStash disabled: missing QSTASH_TOKEN');
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
try {
|
|
225
|
+
const client = new QstashClient({ token: QSTASH_TOKEN });
|
|
226
|
+
await checkQstashHealth(QSTASH_TOKEN);
|
|
227
|
+
cachedQstash = client;
|
|
228
|
+
scheduleQstashHealthCheck(QSTASH_TOKEN);
|
|
229
|
+
return cachedQstash;
|
|
230
|
+
} catch (error) {
|
|
231
|
+
if (!qstashWarnedInitError) {
|
|
232
|
+
qstashWarnedInitError = true;
|
|
233
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
234
|
+
console.warn(`[Upstash Config] QStash init failed: ${message}`);
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
237
|
+
} finally {
|
|
238
|
+
qstashInitPromise = null;
|
|
239
|
+
}
|
|
240
|
+
})();
|
|
241
|
+
|
|
242
|
+
return qstashInitPromise;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export const withRedis = async <T>(fn: (redis: Redis) => Promise<T> | T): Promise<T | null> => {
|
|
246
|
+
const redis = await ensureRedis();
|
|
247
|
+
if (!redis) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
return fn(redis);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export const withQstash = async <T>(
|
|
254
|
+
fn: (qstash: QstashClient) => Promise<T> | T
|
|
255
|
+
): Promise<T | null> => {
|
|
256
|
+
const qstash = await ensureQstash();
|
|
257
|
+
if (!qstash) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
return fn(qstash);
|
|
261
|
+
};
|