@arcjet/cache
Advanced tools
| //#region src/index.d.ts | ||
| /** | ||
| * Interface for a cache. | ||
| */ | ||
| interface Cache<T = unknown> { | ||
| /** | ||
| * Retrieve a value from the cache; | ||
| * it will be returned with the remaining time-to-live (in seconds) if it exists. | ||
| * | ||
| * @param namespace | ||
| * Isolated segment of the cache where keys are tracked. | ||
| * @param key | ||
| * Key. | ||
| * @returns | ||
| * Promise for a tuple with the value and TTL in seconds; | ||
| * value will be `undefined` and TTL will be `0` if not found. | ||
| */ | ||
| get(namespace: string, key: string): Promise<[T | undefined, number]>; | ||
| /** | ||
| * Store a value in the cache. | ||
| * | ||
| * @param namespace | ||
| * Isolated segment of the cache where keys are tracked. | ||
| * @param key | ||
| * Key. | ||
| * @param value | ||
| * Value. | ||
| * @param ttl | ||
| * Number of seconds the entry stays valid. | ||
| * @returns | ||
| * Nothing. | ||
| */ | ||
| set(namespace: string, key: string, value: T, ttl: number): void; | ||
| } | ||
| declare class Bucket<T> { | ||
| expires: Map<string, number>; | ||
| data: Map<string, T>; | ||
| constructor(); | ||
| get(key: string): [T | undefined, number]; | ||
| set(key: string, value: T, ttl: number): void; | ||
| } | ||
| /** | ||
| * In-memory cache. | ||
| */ | ||
| declare class MemoryCache<T> implements Cache<T> { | ||
| /** | ||
| * Data. | ||
| */ | ||
| namespaces: Map<string, Bucket<T>>; | ||
| /** | ||
| * Create a new in-memory cache. | ||
| */ | ||
| constructor(); | ||
| get(namespace: string, key: string): Promise<[T | undefined, number]>; | ||
| set(namespace: string, key: string, value: T, ttl: number): void; | ||
| } | ||
| //#endregion | ||
| export { Cache, MemoryCache }; |
| //#region src/index.ts | ||
| function nowInSeconds() { | ||
| return Math.floor(Date.now() / 1e3); | ||
| } | ||
| var Bucket = class { | ||
| expires; | ||
| data; | ||
| constructor() { | ||
| this.expires = /* @__PURE__ */ new Map(); | ||
| this.data = /* @__PURE__ */ new Map(); | ||
| } | ||
| get(key) { | ||
| const now = nowInSeconds(); | ||
| const ttl = (this.expires.get(key) ?? now) - now; | ||
| if (ttl > 0) return [this.data.get(key), ttl]; | ||
| else { | ||
| this.expires.delete(key); | ||
| this.data.delete(key); | ||
| return [void 0, 0]; | ||
| } | ||
| } | ||
| set(key, value, ttl) { | ||
| const expiresAt = nowInSeconds() + ttl; | ||
| this.expires.set(key, expiresAt); | ||
| this.data.set(key, value); | ||
| } | ||
| }; | ||
| /** | ||
| * In-memory cache. | ||
| */ | ||
| var MemoryCache = class { | ||
| /** | ||
| * Data. | ||
| */ | ||
| namespaces; | ||
| /** | ||
| * Create a new in-memory cache. | ||
| */ | ||
| constructor() { | ||
| this.namespaces = /* @__PURE__ */ new Map(); | ||
| } | ||
| async get(namespace, key) { | ||
| if (typeof namespace !== "string") throw new Error("`namespace` must be a string"); | ||
| if (typeof key !== "string") throw new Error("`key` must be a string"); | ||
| const namespaceCache = this.namespaces.get(namespace); | ||
| if (typeof namespaceCache === "undefined") return [void 0, 0]; | ||
| return namespaceCache.get(key); | ||
| } | ||
| set(namespace, key, value, ttl) { | ||
| if (typeof namespace !== "string") throw new Error("`namespace` must be a string"); | ||
| if (typeof key !== "string") throw new Error("`key` must be a string"); | ||
| const namespaceCache = this.namespaces.get(namespace) ?? new Bucket(); | ||
| namespaceCache.set(key, value, ttl); | ||
| this.namespaces.set(namespace, namespaceCache); | ||
| } | ||
| }; | ||
| //#endregion | ||
| export { MemoryCache }; |
+32
-29
| { | ||
| "name": "@arcjet/cache", | ||
| "version": "1.7.0", | ||
| "version": "1.8.0-rc.0", | ||
| "description": "Arcjet cache interface and implementations", | ||
@@ -8,12 +8,6 @@ "keywords": [ | ||
| "cache", | ||
| "utility", | ||
| "util" | ||
| "util", | ||
| "utility" | ||
| ], | ||
| "license": "Apache-2.0", | ||
| "homepage": "https://arcjet.com", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/arcjet/arcjet-js.git", | ||
| "directory": "cache" | ||
| }, | ||
| "bugs": { | ||
@@ -23,2 +17,3 @@ "url": "https://github.com/arcjet/arcjet-js/issues", | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "author": { | ||
@@ -29,31 +24,39 @@ "name": "Arcjet", | ||
| }, | ||
| "engines": { | ||
| "node": ">=22.21.0 <23 || >=24.5.0" | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/arcjet/arcjet-js.git", | ||
| "directory": "cache" | ||
| }, | ||
| "type": "module", | ||
| "main": "./index.js", | ||
| "types": "./index.d.ts", | ||
| "files": [ | ||
| "index.d.ts", | ||
| "index.js" | ||
| "dist" | ||
| ], | ||
| "type": "module", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "default": "./dist/index.js" | ||
| }, | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public", | ||
| "tag": "latest" | ||
| }, | ||
| "scripts": { | ||
| "build": "rollup --config rollup.config.js", | ||
| "lint": "eslint .", | ||
| "test-api": "node --test -- test/*.test.js", | ||
| "test-coverage": "node --experimental-test-coverage --test -- test/*.test.js", | ||
| "test": "npm run build && npm run lint && npm run test-coverage" | ||
| "build": "tsdown", | ||
| "typecheck": "tsgo --noEmit", | ||
| "test-api": "node --test -- test/*.test.ts", | ||
| "test-coverage": "node --experimental-test-coverage --test -- test/*.test.ts", | ||
| "test": "npm run build && npm run test-coverage" | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": { | ||
| "@arcjet/eslint-config": "1.7.0", | ||
| "@arcjet/rollup-config": "1.7.0", | ||
| "@rollup/wasm-node": "4.62.2", | ||
| "eslint": "9.39.4", | ||
| "typescript": "5.9.3" | ||
| "tsdown": "0.22.3", | ||
| "typescript": "6.0.3" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public", | ||
| "tag": "latest" | ||
| "engines": { | ||
| "node": ">=22.21.0 <23 || >=24.5.0" | ||
| } | ||
| } |
-56
| /** | ||
| * Interface for a cache. | ||
| */ | ||
| export interface Cache<T = unknown> { | ||
| /** | ||
| * Retrieve a value from the cache; | ||
| * it will be returned with the remaining time-to-live (in seconds) if it exists. | ||
| * | ||
| * @param namespace | ||
| * Isolated segment of the cache where keys are tracked. | ||
| * @param key | ||
| * Key. | ||
| * @returns | ||
| * Promise for a tuple with the value and TTL in seconds; | ||
| * value will be `undefined` and TTL will be `0` if not found. | ||
| */ | ||
| get(namespace: string, key: string): Promise<[T | undefined, number]>; | ||
| /** | ||
| * Store a value in the cache. | ||
| * | ||
| * @param namespace | ||
| * Isolated segment of the cache where keys are tracked. | ||
| * @param key | ||
| * Key. | ||
| * @param value | ||
| * Value. | ||
| * @param ttl | ||
| * Number of seconds the entry stays valid. | ||
| * @returns | ||
| * Nothing. | ||
| */ | ||
| set(namespace: string, key: string, value: T, ttl: number): void; | ||
| } | ||
| declare class Bucket<T> { | ||
| expires: Map<string, number>; | ||
| data: Map<string, T>; | ||
| constructor(); | ||
| get(key: string): [T | undefined, number]; | ||
| set(key: string, value: T, ttl: number): void; | ||
| } | ||
| /** | ||
| * In-memory cache. | ||
| */ | ||
| export declare class MemoryCache<T> implements Cache<T> { | ||
| /** | ||
| * Data. | ||
| */ | ||
| namespaces: Map<string, Bucket<T>>; | ||
| /** | ||
| * Create a new in-memory cache. | ||
| */ | ||
| constructor(); | ||
| get(namespace: string, key: string): Promise<[T | undefined, number]>; | ||
| set(namespace: string, key: string, value: T, ttl: number): void; | ||
| } | ||
| export {}; |
-71
| function nowInSeconds() { | ||
| return Math.floor(Date.now() / 1000); | ||
| } | ||
| class Bucket { | ||
| expires; | ||
| data; | ||
| constructor() { | ||
| this.expires = new Map(); | ||
| this.data = new Map(); | ||
| } | ||
| get(key) { | ||
| const now = nowInSeconds(); | ||
| const expiresAt = this.expires.get(key) ?? now; | ||
| const ttl = expiresAt - now; | ||
| if (ttl > 0) { | ||
| return [this.data.get(key), ttl]; | ||
| } | ||
| else { | ||
| // Cleanup if expired | ||
| this.expires.delete(key); | ||
| this.data.delete(key); | ||
| return [undefined, 0]; | ||
| } | ||
| } | ||
| set(key, value, ttl) { | ||
| const expiresAt = nowInSeconds() + ttl; | ||
| this.expires.set(key, expiresAt); | ||
| this.data.set(key, value); | ||
| } | ||
| } | ||
| /** | ||
| * In-memory cache. | ||
| */ | ||
| class MemoryCache { | ||
| /** | ||
| * Data. | ||
| */ | ||
| namespaces; | ||
| /** | ||
| * Create a new in-memory cache. | ||
| */ | ||
| constructor() { | ||
| this.namespaces = new Map(); | ||
| } | ||
| async get(namespace, key) { | ||
| if (typeof namespace !== "string") { | ||
| throw new Error("`namespace` must be a string"); | ||
| } | ||
| if (typeof key !== "string") { | ||
| throw new Error("`key` must be a string"); | ||
| } | ||
| const namespaceCache = this.namespaces.get(namespace); | ||
| if (typeof namespaceCache === "undefined") { | ||
| return [undefined, 0]; | ||
| } | ||
| return namespaceCache.get(key); | ||
| } | ||
| set(namespace, key, value, ttl) { | ||
| if (typeof namespace !== "string") { | ||
| throw new Error("`namespace` must be a string"); | ||
| } | ||
| if (typeof key !== "string") { | ||
| throw new Error("`key` must be a string"); | ||
| } | ||
| const namespaceCache = this.namespaces.get(namespace) ?? new Bucket(); | ||
| namespaceCache.set(key, value, ttl); | ||
| this.namespaces.set(namespace, namespaceCache); | ||
| } | ||
| } | ||
| export { MemoryCache }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
2
-60%18359
-2.26%115
-8.73%1
Infinity%