@dee-wan/cache 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/chunk-OQRNVGQE.js +21 -0
- package/dist/chunk-OQRNVGQE.js.map +1 -0
- package/dist/cloudflare/index.d.ts +26 -0
- package/dist/cloudflare/index.js +406 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/generator/config.d.ts +30 -0
- package/dist/generator/config.js +71 -0
- package/dist/generator/config.js.map +1 -0
- package/dist/generator/index.d.ts +1 -0
- package/dist/generator/index.js +91 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +618 -0
- package/dist/index.js.map +1 -0
- package/dist/types-DwtU0KpX.d.ts +120 -0
- package/docs/cache-contract.md +242 -0
- package/package.json +95 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cloudflare/coordinator-core.ts","../../src/cloudflare/coordinator.ts","../../src/cloudflare/retry.ts","../../src/cloudflare/store-options.ts","../../src/cloudflare/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n BeginWriteRequest,\n EndWriteRequest,\n ReadRequest,\n ReadResponse,\n ReleaseRequest,\n WriteRequest,\n WriteResult,\n} from \"../core/types\";\n\nimport { GLOBAL_FENCE } from \"../core/fences\";\nimport {\n MAX_COORDINATOR_GENERATION_LENGTH,\n MAX_LEASE_MS,\n MAX_LOCK_MS,\n MAX_TTL_MS,\n MAX_VALUE_BYTES,\n} from \"../core/limits\";\n\nexport type SqlValue = ArrayBuffer | null | number | string;\n\nexport type Row = Record<string, SqlValue>;\n\nexport interface SqlLike {\n exec(query: string, ...bindings: SqlValue[]): { toArray(): Row[] };\n}\n\nexport type Transact = <T>(run: () => T) => T;\n\nexport interface CoordinatorLimits {\n maxStoredBytes?: number;\n}\n\nexport { MAX_LEASE_MS, MAX_LOCK_MS, MAX_TTL_MS };\nexport const FENCE_RETENTION_MS = 2 * MAX_LOCK_MS;\nexport const SWEEP_LIMIT = 50;\nexport const FENCE_COLLECT_LIMIT = 100;\nexport const PURGE_LIMIT = 500;\nexport const EVICTION_BATCH = 50;\nexport const MAX_EVICTION_ROUNDS = 20;\nexport const MAX_STORED_BYTES = 1024 * 1024 * 1024;\nexport const MAX_KEY_LENGTH = 1024;\nexport const MAX_TOKEN_LENGTH = 128;\nexport const MAX_FENCE_LENGTH = 512;\nexport const MAX_FENCES_PER_REQUEST = 5000;\n\nconst MAX_BOUND_PARAMETERS = 90;\n\nexport const MIGRATIONS: readonly string[] = [\n `\nCREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value INTEGER NOT NULL);\nINSERT OR IGNORE INTO meta (key, value) VALUES ('sequence', 0);\nCREATE TABLE IF NOT EXISTS fences (fence TEXT PRIMARY KEY, epoch INTEGER NOT NULL, updated_at INTEGER NOT NULL);\nCREATE INDEX IF NOT EXISTS fences_by_updated ON fences (updated_at);\nCREATE TABLE IF NOT EXISTS leases (token TEXT NOT NULL, fence TEXT NOT NULL, expires_at INTEGER NOT NULL, PRIMARY KEY (token, fence));\nCREATE INDEX IF NOT EXISTS leases_by_fence ON leases (fence, expires_at);\nCREATE INDEX IF NOT EXISTS leases_by_expiry ON leases (expires_at);\nCREATE TABLE IF NOT EXISTS locks (key TEXT PRIMARY KEY, token TEXT NOT NULL, expires_at INTEGER NOT NULL);\nCREATE INDEX IF NOT EXISTS locks_by_expiry ON locks (expires_at);\nCREATE TABLE IF NOT EXISTS entries (key TEXT PRIMARY KEY, value TEXT NOT NULL, snapshot TEXT NOT NULL, soft_expires_at INTEGER NOT NULL, expires_at INTEGER NOT NULL);\nCREATE INDEX IF NOT EXISTS entries_by_expiry ON entries (expires_at);\nCREATE TABLE IF NOT EXISTS entry_fences (fence TEXT NOT NULL, key TEXT NOT NULL, PRIMARY KEY (fence, key));\nCREATE INDEX IF NOT EXISTS entry_fences_by_key ON entry_fences (key);\n`,\n `\nCREATE TABLE IF NOT EXISTS generation (id INTEGER PRIMARY KEY CHECK (id = 1), value TEXT NOT NULL);\n`,\n `\nALTER TABLE locks ADD COLUMN seq INTEGER NOT NULL DEFAULT 0;\nALTER TABLE locks ADD COLUMN kind TEXT NOT NULL DEFAULT 'fill';\nALTER TABLE locks ADD COLUMN acquired_at INTEGER NOT NULL DEFAULT 0;\nALTER TABLE entries ADD COLUMN size INTEGER NOT NULL DEFAULT 0;\nINSERT OR IGNORE INTO meta (key, value) VALUES ('gc_watermark', 0);\nINSERT OR IGNORE INTO meta (key, value) VALUES ('entry_bytes', 0);\nCREATE TABLE IF NOT EXISTS gc_cursor (id INTEGER PRIMARY KEY CHECK (id = 1), updated_at INTEGER NOT NULL, fence TEXT NOT NULL);\nINSERT OR IGNORE INTO gc_cursor (id, updated_at, fence) VALUES (1, -1, '');\nCREATE INDEX IF NOT EXISTS fences_by_updated_fence ON fences (updated_at, fence);\n`,\n];\n\nfunction chunks<T>(items: T[]): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += MAX_BOUND_PARAMETERS) out.push(items.slice(i, i + MAX_BOUND_PARAMETERS));\n return out;\n}\n\nconst placeholders = (count: number): string => Array.from({ length: count }, () => \"?\").join(\",\");\n\nconst clamp = (value: number, max: number): number => Math.min(Math.max(Math.trunc(value), 1), max);\n\nfunction assertRequest(condition: boolean, message: string): asserts condition {\n if (!condition) throw new TypeError(`cache coordinator: ${message}`);\n}\n\nconst isKey = (value: unknown): value is string => typeof value === \"string\" && value.length > 0 && value.length <= MAX_KEY_LENGTH;\n\nconst isFenceList = (value: unknown): value is string[] =>\n Array.isArray(value) &&\n value.length <= MAX_FENCES_PER_REQUEST &&\n value.every((fence) => typeof fence === \"string\" && fence.length > 0 && fence.length <= MAX_FENCE_LENGTH);\n\nconst isSnapshot = (value: unknown): value is Record<string, number> =>\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.keys(value).length <= MAX_FENCES_PER_REQUEST &&\n Object.values(value).every((epoch) => Number.isSafeInteger(epoch));\n\nconst isGeneration = (value: unknown): value is string | undefined =>\n value === undefined ||\n (typeof value === \"string\" && value.length > 0 && value.length <= MAX_COORDINATOR_GENERATION_LENGTH);\n\nconst isToken = (value: unknown): value is string =>\n typeof value === \"string\" && value.length > 0 && value.length <= MAX_TOKEN_LENGTH;\n\nconst isDuration = (value: unknown): value is number => typeof value === \"number\" && Number.isFinite(value) && value > 0;\n\nconst byteLength = (text: string): number => new TextEncoder().encode(text).byteLength;\n\nfunction parseSnapshot(text: string): Record<string, number> | null {\n try {\n const parsed: unknown = JSON.parse(text);\n return isSnapshot(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nexport function migrate(sql: SqlLike, transact: Transact): void {\n transact(() => {\n sql.exec(\"CREATE TABLE IF NOT EXISTS schema_version (id INTEGER PRIMARY KEY CHECK (id = 1), version INTEGER NOT NULL)\");\n const current = Number(sql.exec(\"SELECT version FROM schema_version WHERE id = 1\").toArray()[0]?.version ?? 0);\n if (current > MIGRATIONS.length) {\n throw new Error(`cache coordinator: storage schema ${current} is newer than this code (${MIGRATIONS.length})`);\n }\n if (current === MIGRATIONS.length) return;\n MIGRATIONS.slice(current).forEach((migration) => sql.exec(migration));\n sql.exec(\"INSERT OR REPLACE INTO schema_version (id, version) VALUES (1, ?)\", MIGRATIONS.length);\n });\n}\n\nexport function createCoordinatorCore(sql: SqlLike, newToken: () => string, transact: Transact, limits: CoordinatorLimits = {}) {\n const maxStoredBytes = limits.maxStoredBytes ?? MAX_STORED_BYTES;\n const rows = (query: string, ...bindings: SqlValue[]): Row[] => sql.exec(query, ...bindings).toArray();\n\n const metaValue = (key: string): number => Number(rows(\"SELECT value FROM meta WHERE key = ?\", key)[0]?.value ?? 0);\n\n function epochs(fences: string[]): Record<string, number> {\n const out: Record<string, number> = Object.fromEntries(fences.map((fence) => [fence, 0]));\n for (const chunk of chunks([...new Set(fences)])) {\n for (const row of rows(`SELECT fence, epoch FROM fences WHERE fence IN (${placeholders(chunk.length)})`, ...chunk)) {\n out[String(row.fence)] = Number(row.epoch);\n }\n }\n return out;\n }\n\n const matches = (snapshot: Record<string, number>, current: Record<string, number>): boolean => {\n const fences = Object.keys(snapshot);\n return fences.length > 0 && fences.every((fence) => current[fence] === snapshot[fence]);\n };\n\n const pending = (fences: string[], now: number): boolean =>\n chunks([...new Set(fences)]).some(\n (chunk) => rows(`SELECT 1 FROM leases WHERE expires_at > ? AND fence IN (${placeholders(chunk.length)}) LIMIT 1`, now, ...chunk).length > 0,\n );\n\n function writeLock(key: string, lockMs: number, now: number, kind: \"fill\" | \"refresh\"): string {\n const token = newToken();\n sql.exec(\n \"INSERT OR REPLACE INTO locks (key, token, expires_at, seq, kind, acquired_at) VALUES (?, ?, ?, ?, ?, ?)\",\n key,\n token,\n now + clamp(lockMs, MAX_LOCK_MS),\n metaValue(\"sequence\"),\n kind,\n now,\n );\n return token;\n }\n\n function deleteEntries(keys: string[]): void {\n for (const chunk of chunks(keys)) {\n const bytes = Number(rows(`SELECT COALESCE(SUM(size), 0) AS bytes FROM entries WHERE key IN (${placeholders(chunk.length)})`, ...chunk)[0]?.bytes ?? 0);\n sql.exec(`DELETE FROM entry_fences WHERE key IN (${placeholders(chunk.length)})`, ...chunk);\n sql.exec(`DELETE FROM entries WHERE key IN (${placeholders(chunk.length)})`, ...chunk);\n if (bytes > 0) sql.exec(\"UPDATE meta SET value = MAX(0, value - ?) WHERE key = 'entry_bytes'\", bytes);\n }\n }\n\n function makeRoom(size: number): boolean {\n for (let round = 0; round < MAX_EVICTION_ROUNDS; round++) {\n const overflow = metaValue(\"entry_bytes\") + size - maxStoredBytes;\n if (overflow <= 0) return true;\n const candidates = rows(\"SELECT key, size FROM entries ORDER BY expires_at LIMIT ?\", EVICTION_BATCH);\n if (candidates.length === 0) break;\n let freed = 0;\n const victims = candidates.filter((row) => {\n if (freed >= overflow) return false;\n freed += Number(row.size);\n return true;\n });\n deleteEntries(victims.map((row) => String(row.key)));\n }\n return metaValue(\"entry_bytes\") + size <= maxStoredBytes;\n }\n\n function bump(fences: string[], now: number): void {\n for (const fence of new Set(fences)) {\n const next = Number(rows(\"UPDATE meta SET value = value + 1 WHERE key = 'sequence' RETURNING value\")[0]?.value);\n sql.exec(\n \"INSERT INTO fences (fence, epoch, updated_at) VALUES (?, ?, ?) ON CONFLICT (fence) DO UPDATE SET epoch = excluded.epoch, updated_at = excluded.updated_at\",\n fence,\n next,\n now,\n );\n }\n }\n\n function purge(fences: string[]): void {\n let budget = PURGE_LIMIT;\n for (const chunk of chunks([...new Set(fences)])) {\n if (budget <= 0) return;\n const keys = rows(\n `SELECT DISTINCT key FROM entry_fences WHERE fence IN (${placeholders(chunk.length)}) LIMIT ?`,\n ...chunk,\n budget,\n );\n deleteEntries(keys.map((row) => String(row.key)));\n budget -= keys.length;\n }\n }\n\n function collectFences(now: number): void {\n const cursor = rows(\"SELECT updated_at, fence FROM gc_cursor WHERE id = 1\")[0];\n const after = Number(cursor?.updated_at ?? -1);\n const afterFence = String(cursor?.fence ?? \"\");\n const batch = rows(\n `SELECT fence, updated_at, epoch,\n EXISTS (SELECT 1 FROM entry_fences WHERE entry_fences.fence = fences.fence) AS in_entries,\n EXISTS (SELECT 1 FROM leases WHERE leases.fence = fences.fence) AS in_leases\n FROM fences\n WHERE (updated_at, fence) > (?, ?) AND updated_at <= ? AND fence >= ? AND fence < ?\n ORDER BY updated_at, fence LIMIT ?`,\n after,\n afterFence,\n now - FENCE_RETENTION_MS,\n \"e:\",\n \"e;\",\n FENCE_COLLECT_LIMIT,\n );\n const deletable = batch.filter((row) => Number(row.in_entries) === 0 && Number(row.in_leases) === 0);\n for (const chunk of chunks(deletable.map((row) => String(row.fence)))) {\n sql.exec(`DELETE FROM fences WHERE fence IN (${placeholders(chunk.length)})`, ...chunk);\n }\n const highestDeletedEpoch = Math.max(0, ...deletable.map((row) => Number(row.epoch)));\n if (highestDeletedEpoch > 0) {\n sql.exec(\"UPDATE meta SET value = MAX(value, ?) WHERE key = 'gc_watermark'\", highestDeletedEpoch);\n }\n const last = batch[batch.length - 1];\n const [nextAt, nextFence] = batch.length < FENCE_COLLECT_LIMIT || !last ? [-1, \"\"] : [Number(last.updated_at), String(last.fence)];\n if (nextAt !== after || nextFence !== afterFence) {\n sql.exec(\"UPDATE gc_cursor SET updated_at = ?, fence = ? WHERE id = 1\", nextAt, nextFence);\n }\n }\n\n function sweep(now: number): void {\n const expired = rows(\"SELECT key FROM entries WHERE expires_at <= ? LIMIT ?\", now, SWEEP_LIMIT);\n deleteEntries(expired.map((row) => String(row.key)));\n sql.exec(\"DELETE FROM leases WHERE rowid IN (SELECT rowid FROM leases WHERE expires_at <= ? LIMIT ?)\", now, SWEEP_LIMIT);\n sql.exec(\"DELETE FROM locks WHERE rowid IN (SELECT rowid FROM locks WHERE expires_at <= ? LIMIT ?)\", now, SWEEP_LIMIT);\n collectFences(now);\n }\n\n function observeGeneration(generation: string | undefined, now: number): void {\n if (generation === undefined) return;\n const current = rows(\"SELECT value FROM generation WHERE id = 1\")[0]?.value;\n if (current === generation) return;\n bump([GLOBAL_FENCE], now);\n sql.exec(\"INSERT OR REPLACE INTO generation (id, value) VALUES (1, ?)\", generation);\n }\n\n function snapshotValid(snapshot: Record<string, number> | null): snapshot is Record<string, number> {\n return snapshot !== null && matches(snapshot, epochs(Object.keys(snapshot)));\n }\n\n return {\n beginWrite(request: BeginWriteRequest, now: number): void {\n assertRequest(\n isFenceList(request.fences) && isDuration(request.leaseMs) && isGeneration(request.generation) && isToken(request.token),\n \"invalid beginWrite request\",\n );\n transact(() => {\n observeGeneration(request.generation, now);\n bump(request.fences, now);\n const expiresAt = now + clamp(request.leaseMs, MAX_LEASE_MS);\n for (const fence of new Set(request.fences)) {\n sql.exec(\"INSERT OR REPLACE INTO leases (token, fence, expires_at) VALUES (?, ?, ?)\", request.token, fence, expiresAt);\n }\n });\n },\n\n endWrite(request: EndWriteRequest, now: number): void {\n assertRequest(isFenceList(request.fences) && isToken(request.token), \"invalid endWrite request\");\n transact(() => {\n bump(request.fences, now);\n sql.exec(\"DELETE FROM leases WHERE token = ?\", request.token);\n purge(request.fences);\n sweep(now);\n });\n },\n\n invalidate(fences: string[], now: number): void {\n assertRequest(isFenceList(fences), \"invalid invalidate request\");\n transact(() => {\n bump(fences, now);\n purge(fences);\n sweep(now);\n });\n },\n\n read(request: ReadRequest, now: number): ReadResponse {\n assertRequest(\n isKey(request.key) && isFenceList(request.fences) && isDuration(request.lockMs) && isGeneration(request.generation),\n \"invalid read request\",\n );\n return transact((): ReadResponse => {\n observeGeneration(request.generation, now);\n const entry = rows(\"SELECT value, snapshot, soft_expires_at, expires_at FROM entries WHERE key = ?\", request.key)[0];\n const lock = rows(\"SELECT expires_at, kind, acquired_at FROM locks WHERE key = ?\", request.key)[0];\n const lockLive = lock !== undefined && Number(lock.expires_at) > now;\n if (entry && Number(entry.expires_at) > now) {\n const snapshot = parseSnapshot(String(entry.snapshot));\n const current = epochs([...request.fences, ...Object.keys(snapshot ?? {})]);\n if (snapshot && matches(snapshot, current)) {\n const refreshable =\n request.refresh === true && now >= Number(entry.soft_expires_at) && !lockLive && !pending(request.fences, now);\n return {\n epochs: Object.fromEntries(request.fences.map((fence) => [fence, current[fence] ?? 0])),\n kind: \"hit\",\n refreshToken: refreshable ? writeLock(request.key, request.lockMs, now, \"refresh\") : null,\n value: String(entry.value),\n };\n }\n }\n if (entry) deleteEntries([request.key]);\n const isPending = pending(request.fences, now);\n const heldByFill = lockLive && lock.kind !== \"refresh\";\n const lockToken = isPending || heldByFill ? null : writeLock(request.key, request.lockMs, now, \"fill\");\n return {\n epochs: epochs(request.fences),\n kind: \"miss\",\n lockHeldForMs: heldByFill ? Math.max(0, now - Number(lock.acquired_at)) : null,\n lockToken,\n pending: isPending,\n };\n });\n },\n\n release(request: ReleaseRequest): void {\n assertRequest(isKey(request.key) && isToken(request.lockToken), \"invalid release request\");\n transact(() => sql.exec(\"DELETE FROM locks WHERE key = ? AND token = ?\", request.key, request.lockToken));\n },\n\n write(request: WriteRequest, now: number): WriteResult {\n assertRequest(\n typeof request.key === \"string\" &&\n typeof request.lockToken === \"string\" &&\n typeof request.value === \"string\" &&\n isSnapshot(request.snapshot) &&\n isDuration(request.ttlMs) &&\n isDuration(request.softTtlMs),\n \"invalid write request\",\n );\n return transact((): WriteResult => {\n const lock = rows(\"SELECT token, expires_at, seq FROM locks WHERE key = ?\", request.key)[0];\n if (!lock || lock.token !== request.lockToken || Number(lock.expires_at) <= now) return { ok: false, reason: \"lock\" };\n sql.exec(\"DELETE FROM locks WHERE key = ?\", request.key);\n const snapshotText = JSON.stringify(request.snapshot);\n const size = byteLength(request.value) + snapshotText.length + request.key.length;\n const oversize = !isKey(request.key) || request.ttlMs > MAX_TTL_MS || byteLength(request.value) > MAX_VALUE_BYTES;\n if (oversize) return { ok: false, reason: \"invalid\" };\n const capturedMissing = Object.values(request.snapshot).some((epoch) => epoch === 0);\n if (capturedMissing && Number(lock.seq) < metaValue(\"gc_watermark\")) return { ok: false, reason: \"fence\" };\n if (!snapshotValid(request.snapshot)) return { ok: false, reason: \"fence\" };\n deleteEntries([request.key]);\n if (!makeRoom(size)) return { ok: false, reason: \"full\" };\n sql.exec(\n \"INSERT INTO entries (key, value, snapshot, soft_expires_at, expires_at, size) VALUES (?, ?, ?, ?, ?, ?)\",\n request.key,\n request.value,\n snapshotText,\n now + Math.min(request.softTtlMs, request.ttlMs),\n now + request.ttlMs,\n size,\n );\n sql.exec(\"UPDATE meta SET value = value + ? WHERE key = 'entry_bytes'\", size);\n for (const fence of Object.keys(request.snapshot)) {\n sql.exec(\"INSERT INTO entry_fences (fence, key) VALUES (?, ?)\", fence, request.key);\n }\n sweep(now);\n return { ok: true };\n });\n },\n };\n}\n\nexport type CoordinatorCore = ReturnType<typeof createCoordinatorCore>;\n","import { DurableObject } from \"cloudflare:workers\";\n\nimport type {\n BeginWriteRequest,\n EndWriteRequest,\n ReadRequest,\n ReadResponse,\n ReleaseRequest,\n WriteRequest,\n WriteResult,\n} from \"../core/types\";\n\nimport { type CoordinatorCore, createCoordinatorCore, migrate, type Transact } from \"./coordinator-core\";\n\nexport class CacheCoordinator<Env = unknown> extends DurableObject<Env> {\n private readonly core: CoordinatorCore;\n\n constructor(ctx: DurableObjectState, env: Env) {\n super(ctx, env);\n const transact: Transact = (run) => ctx.storage.transactionSync(run);\n migrate(ctx.storage.sql, transact);\n this.core = createCoordinatorCore(ctx.storage.sql, () => crypto.randomUUID(), transact);\n }\n\n read(request: ReadRequest): ReadResponse {\n return this.core.read(request, Date.now());\n }\n\n write(request: WriteRequest): WriteResult {\n return this.core.write(request, Date.now());\n }\n\n release(request: ReleaseRequest): void {\n this.core.release(request);\n }\n\n beginWrite(request: BeginWriteRequest): void {\n this.core.beginWrite(request, Date.now());\n }\n\n endWrite(request: EndWriteRequest): void {\n this.core.endWrite(request, Date.now());\n }\n\n invalidate(fences: string[]): void {\n this.core.invalidate(fences, Date.now());\n }\n}\n","const BASE_BACKOFF_MS = 50;\n\nexport const isRetryable = (error: unknown): boolean =>\n !!error && typeof error === \"object\" && Reflect.get(error, \"retryable\") === true && Reflect.get(error, \"overloaded\") !== true;\n\nexport async function retryTransient<T>(call: () => Promise<T>, attempts: number, sleep: (ms: number) => Promise<void>): Promise<T> {\n for (let attempt = 0; ; attempt++) {\n try {\n return await call();\n } catch (error) {\n if (attempt + 1 >= attempts || !isRetryable(error)) throw error;\n await sleep(BASE_BACKOFF_MS * Math.random() * 2 ** attempt);\n }\n }\n}\n","export const WRITE_PATH_ATTEMPTS = 3;\nexport const MAX_COORDINATOR_NAME_LENGTH = 256;\n\nexport const LOCATION_HINTS = [\"wnam\", \"enam\", \"sam\", \"weur\", \"eeur\", \"apac\", \"oc\", \"afr\", \"me\"] as const;\n\nexport type CoordinatorLocationHint = (typeof LOCATION_HINTS)[number];\n\nexport interface DurableObjectStoreOptions {\n attempts?: number;\n locationHint?: CoordinatorLocationHint;\n name: string;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface ResolvedStoreOptions {\n attempts: number;\n locationHint?: CoordinatorLocationHint;\n name: string;\n sleep: (ms: number) => Promise<void>;\n}\n\nconst isLocationHint = (value: unknown): value is CoordinatorLocationHint =>\n LOCATION_HINTS.some((hint) => hint === value);\n\nexport function resolveStoreOptions(options: DurableObjectStoreOptions): ResolvedStoreOptions {\n const { attempts = WRITE_PATH_ATTEMPTS, locationHint, name } = options;\n const problems = [\n !(typeof name === \"string\" && name.length > 0 && name.length <= MAX_COORDINATOR_NAME_LENGTH) &&\n `name must be 1..${MAX_COORDINATOR_NAME_LENGTH} characters and identify one D1 database`,\n !(Number.isInteger(attempts) && attempts >= 1 && attempts <= 10) && \"attempts must be an integer in 1..10\",\n locationHint !== undefined && !isLocationHint(locationHint) && `locationHint must be one of ${LOCATION_HINTS.join(\", \")}`,\n ].filter((problem): problem is string => typeof problem === \"string\");\n if (problems.length > 0) throw new TypeError(`cache store: ${problems.join(\"; \")}`);\n return {\n attempts,\n name,\n sleep: options.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms))),\n ...(locationHint ? { locationHint } : {}),\n };\n}\n","import type { CacheStore } from \"../core/types\";\nimport type { CacheCoordinator } from \"./coordinator\";\n\nimport { retryTransient } from \"./retry\";\nimport { type DurableObjectStoreOptions, resolveStoreOptions } from \"./store-options\";\n\nexport function createDurableObjectStore<Env>(\n namespace: DurableObjectNamespace<CacheCoordinator<Env>>,\n options: DurableObjectStoreOptions,\n): CacheStore {\n const { attempts, locationHint, name, sleep } = resolveStoreOptions(options);\n const stub = () => namespace.get(namespace.idFromName(name), locationHint ? { locationHint } : undefined);\n const withRetry = <T>(call: (coordinator: ReturnType<typeof stub>) => Promise<T>): Promise<T> =>\n retryTransient(() => call(stub()), attempts, sleep);\n\n return {\n beginWrite: (request) => withRetry(async (coordinator) => void (await coordinator.beginWrite(request))),\n endWrite: (request) => withRetry(async (coordinator) => void (await coordinator.endWrite(request))),\n invalidate: (fences) => withRetry(async (coordinator) => void (await coordinator.invalidate(fences))),\n read: async (request) => stub().read(request),\n release: async (request) => void (await stub().release(request)),\n write: async (request) => stub().write(request),\n };\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
|
|
3
|
+
interface RelationInfo {
|
|
4
|
+
fieldName: string;
|
|
5
|
+
foreignFields: string[];
|
|
6
|
+
isList: boolean;
|
|
7
|
+
localFields: string[];
|
|
8
|
+
oneToOne: boolean;
|
|
9
|
+
relationName?: string;
|
|
10
|
+
targetModel: string;
|
|
11
|
+
}
|
|
12
|
+
interface GeneratedCacheConfig {
|
|
13
|
+
cacheVersion: string;
|
|
14
|
+
cacheableByModel: Record<string, boolean>;
|
|
15
|
+
configFormat: number;
|
|
16
|
+
hasDecimalFields: boolean;
|
|
17
|
+
modelNames: string[];
|
|
18
|
+
primaryKeyFieldsByModel: Record<string, string[]>;
|
|
19
|
+
primaryKeyNameByModel: Record<string, string>;
|
|
20
|
+
relationGraph: Record<string, RelationInfo[]>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare const CACHE_CONFIG_SALT = "cf-1";
|
|
24
|
+
declare const SKIP_DIRECTIVE = "@cache.skip";
|
|
25
|
+
type Model = DMMF.Datamodel["models"][number];
|
|
26
|
+
declare const isSkipped: (model: Model) => boolean;
|
|
27
|
+
declare function buildCacheConfig(datamodel: DMMF.Datamodel, excludeModels?: string[]): GeneratedCacheConfig;
|
|
28
|
+
declare function renderCacheConfig(config: GeneratedCacheConfig, importFrom: string): string;
|
|
29
|
+
|
|
30
|
+
export { CACHE_CONFIG_SALT, SKIP_DIRECTIVE, buildCacheConfig, isSkipped, renderCacheConfig };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/generator/config.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
|
|
4
|
+
// src/core/limits.ts
|
|
5
|
+
var MAX_TTL_MS = 366 * 24 * 60 * 60 * 1e3;
|
|
6
|
+
var TTL_JITTER_RATIO = 0.1;
|
|
7
|
+
var MAX_SHAPE_TTL_SECONDS = Math.floor(MAX_TTL_MS / 1e3 / (1 + TTL_JITTER_RATIO));
|
|
8
|
+
var CONFIG_FORMAT = 2;
|
|
9
|
+
|
|
10
|
+
// src/generator/config.ts
|
|
11
|
+
var CACHE_CONFIG_SALT = "cf-1";
|
|
12
|
+
var SKIP_DIRECTIVE = "@cache.skip";
|
|
13
|
+
function relationsOf(model, models) {
|
|
14
|
+
return model.fields.filter((field) => field.kind === "object").map((field) => {
|
|
15
|
+
const opposite = models.find((candidate) => candidate.name === field.type)?.fields.find((other) => other.kind === "object" && other.relationName === field.relationName && other !== field);
|
|
16
|
+
return {
|
|
17
|
+
fieldName: field.name,
|
|
18
|
+
foreignFields: [...field.relationToFields ?? []],
|
|
19
|
+
isList: field.isList,
|
|
20
|
+
localFields: [...field.relationFromFields ?? []],
|
|
21
|
+
oneToOne: !field.isList && opposite !== void 0 && !opposite.isList,
|
|
22
|
+
...field.relationName ? { relationName: field.relationName } : {},
|
|
23
|
+
targetModel: field.type
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function primaryKeyOf(model) {
|
|
28
|
+
const idFields = model.fields.filter((field) => field.isId).map((field) => field.name);
|
|
29
|
+
if (idFields.length > 0) return { fields: idFields };
|
|
30
|
+
if (model.primaryKey) return { fields: [...model.primaryKey.fields], ...model.primaryKey.name ? { name: model.primaryKey.name } : {} };
|
|
31
|
+
const uniqueIndex = model.uniqueIndexes[0];
|
|
32
|
+
if (uniqueIndex) return { fields: [...uniqueIndex.fields], ...uniqueIndex.name ? { name: uniqueIndex.name } : {} };
|
|
33
|
+
const uniqueField = model.fields.find((field) => field.isUnique);
|
|
34
|
+
if (uniqueField) return { fields: [uniqueField.name] };
|
|
35
|
+
throw new Error(`cache generator: model ${model.name} has no primary key or unique constraint`);
|
|
36
|
+
}
|
|
37
|
+
var isSkipped = (model) => (model.documentation ?? "").split(/\r?\n/).some((line) => line.trim() === SKIP_DIRECTIVE);
|
|
38
|
+
function buildCacheConfig(datamodel, excludeModels = []) {
|
|
39
|
+
const excluded = new Set(excludeModels);
|
|
40
|
+
const unknown = excludeModels.filter((name) => !datamodel.models.some((model) => model.name === name));
|
|
41
|
+
if (unknown.length > 0) throw new Error(`cache generator: unknown models in exclude: ${unknown.join(", ")}`);
|
|
42
|
+
const cacheVersion = createHash("sha256").update(JSON.stringify(datamodel) + CACHE_CONFIG_SALT).digest("hex").slice(0, 12);
|
|
43
|
+
const keys = datamodel.models.map((model) => [model.name, primaryKeyOf(model)]);
|
|
44
|
+
const named = keys.flatMap(([name, key]) => key.name ? [[name, key.name]] : []);
|
|
45
|
+
return {
|
|
46
|
+
cacheVersion,
|
|
47
|
+
configFormat: CONFIG_FORMAT,
|
|
48
|
+
cacheableByModel: Object.fromEntries(datamodel.models.map((model) => [model.name, !isSkipped(model) && !excluded.has(model.name)])),
|
|
49
|
+
hasDecimalFields: datamodel.models.some((model) => model.fields.some((field) => field.type === "Decimal")),
|
|
50
|
+
modelNames: datamodel.models.map((model) => model.name),
|
|
51
|
+
primaryKeyFieldsByModel: Object.fromEntries(keys.map(([name, key]) => [name, key.fields])),
|
|
52
|
+
primaryKeyNameByModel: Object.fromEntries(named),
|
|
53
|
+
relationGraph: Object.fromEntries(
|
|
54
|
+
datamodel.models.map((model) => [model.name, relationsOf(model, datamodel.models)]).filter(([, relations]) => relations.length > 0)
|
|
55
|
+
)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function renderCacheConfig(config, importFrom) {
|
|
59
|
+
return `import type { GeneratedCacheConfig } from "${importFrom}";
|
|
60
|
+
|
|
61
|
+
export const cacheConfig: GeneratedCacheConfig = ${JSON.stringify(config, null, 2)};
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
CACHE_CONFIG_SALT,
|
|
66
|
+
SKIP_DIRECTIVE,
|
|
67
|
+
buildCacheConfig,
|
|
68
|
+
isSkipped,
|
|
69
|
+
renderCacheConfig
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/config.ts","../../src/core/limits.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport type { DMMF } from \"@prisma/generator-helper\";\n\nimport type { GeneratedCacheConfig, RelationInfo } from \"../core/types\";\n\nimport { CONFIG_FORMAT } from \"../core/limits\";\n\nexport const CACHE_CONFIG_SALT = \"cf-1\";\nexport const SKIP_DIRECTIVE = \"@cache.skip\";\n\ntype Model = DMMF.Datamodel[\"models\"][number];\n\nfunction relationsOf(model: Model, models: readonly Model[]): RelationInfo[] {\n return model.fields\n .filter((field) => field.kind === \"object\")\n .map((field) => {\n const opposite = models\n .find((candidate) => candidate.name === field.type)\n ?.fields.find((other) => other.kind === \"object\" && other.relationName === field.relationName && other !== field);\n return {\n fieldName: field.name,\n foreignFields: [...(field.relationToFields ?? [])],\n isList: field.isList,\n localFields: [...(field.relationFromFields ?? [])],\n oneToOne: !field.isList && opposite !== undefined && !opposite.isList,\n ...(field.relationName ? { relationName: field.relationName } : {}),\n targetModel: field.type,\n };\n });\n}\n\ninterface PrimaryKey {\n fields: string[];\n name?: string;\n}\n\nfunction primaryKeyOf(model: Model): PrimaryKey {\n const idFields = model.fields.filter((field) => field.isId).map((field) => field.name);\n if (idFields.length > 0) return { fields: idFields };\n if (model.primaryKey) return { fields: [...model.primaryKey.fields], ...(model.primaryKey.name ? { name: model.primaryKey.name } : {}) };\n const uniqueIndex = model.uniqueIndexes[0];\n if (uniqueIndex) return { fields: [...uniqueIndex.fields], ...(uniqueIndex.name ? { name: uniqueIndex.name } : {}) };\n const uniqueField = model.fields.find((field) => field.isUnique);\n if (uniqueField) return { fields: [uniqueField.name] };\n throw new Error(`cache generator: model ${model.name} has no primary key or unique constraint`);\n}\n\nexport const isSkipped = (model: Model): boolean =>\n (model.documentation ?? \"\").split(/\\r?\\n/).some((line) => line.trim() === SKIP_DIRECTIVE);\n\nexport function buildCacheConfig(datamodel: DMMF.Datamodel, excludeModels: string[] = []): GeneratedCacheConfig {\n const excluded = new Set(excludeModels);\n const unknown = excludeModels.filter((name) => !datamodel.models.some((model) => model.name === name));\n if (unknown.length > 0) throw new Error(`cache generator: unknown models in exclude: ${unknown.join(\", \")}`);\n const cacheVersion = createHash(\"sha256\")\n .update(JSON.stringify(datamodel) + CACHE_CONFIG_SALT)\n .digest(\"hex\")\n .slice(0, 12);\n const keys = datamodel.models.map((model) => [model.name, primaryKeyOf(model)] as const);\n const named = keys.flatMap(([name, key]) => (key.name ? [[name, key.name] as const] : []));\n return {\n cacheVersion,\n configFormat: CONFIG_FORMAT,\n cacheableByModel: Object.fromEntries(datamodel.models.map((model) => [model.name, !isSkipped(model) && !excluded.has(model.name)])),\n hasDecimalFields: datamodel.models.some((model) => model.fields.some((field) => field.type === \"Decimal\")),\n modelNames: datamodel.models.map((model) => model.name),\n primaryKeyFieldsByModel: Object.fromEntries(keys.map(([name, key]) => [name, key.fields])),\n primaryKeyNameByModel: Object.fromEntries(named),\n relationGraph: Object.fromEntries(\n datamodel.models\n .map((model) => [model.name, relationsOf(model, datamodel.models)] as const)\n .filter(([, relations]) => relations.length > 0),\n ),\n };\n}\n\nexport function renderCacheConfig(config: GeneratedCacheConfig, importFrom: string): string {\n return `import type { GeneratedCacheConfig } from \"${importFrom}\";\n\nexport const cacheConfig: GeneratedCacheConfig = ${JSON.stringify(config, null, 2)};\n`;\n}\n","export const MAX_LOCK_MS = 300_000;\nexport const MAX_LEASE_MS = 600_000;\nexport const MAX_VALUE_BYTES = 1_900_000;\nexport const MAX_GENERATION_LENGTH = 256;\nexport const MAX_COORDINATOR_GENERATION_LENGTH = 512;\nexport const MAX_TTL_MS = 366 * 24 * 60 * 60 * 1000;\nexport const TTL_JITTER_RATIO = 0.1;\nexport const MAX_SHAPE_TTL_SECONDS = Math.floor(MAX_TTL_MS / 1000 / (1 + TTL_JITTER_RATIO));\nexport const CONFIG_FORMAT = 2;\nexport const PLANNER_VERSION = 2;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/generator/index.ts
|
|
4
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import helper from "@prisma/generator-helper";
|
|
7
|
+
|
|
8
|
+
// src/generator/config.ts
|
|
9
|
+
import { createHash } from "crypto";
|
|
10
|
+
|
|
11
|
+
// src/core/limits.ts
|
|
12
|
+
var MAX_TTL_MS = 366 * 24 * 60 * 60 * 1e3;
|
|
13
|
+
var TTL_JITTER_RATIO = 0.1;
|
|
14
|
+
var MAX_SHAPE_TTL_SECONDS = Math.floor(MAX_TTL_MS / 1e3 / (1 + TTL_JITTER_RATIO));
|
|
15
|
+
var CONFIG_FORMAT = 2;
|
|
16
|
+
|
|
17
|
+
// src/generator/config.ts
|
|
18
|
+
var CACHE_CONFIG_SALT = "cf-1";
|
|
19
|
+
var SKIP_DIRECTIVE = "@cache.skip";
|
|
20
|
+
function relationsOf(model, models) {
|
|
21
|
+
return model.fields.filter((field) => field.kind === "object").map((field) => {
|
|
22
|
+
const opposite = models.find((candidate) => candidate.name === field.type)?.fields.find((other) => other.kind === "object" && other.relationName === field.relationName && other !== field);
|
|
23
|
+
return {
|
|
24
|
+
fieldName: field.name,
|
|
25
|
+
foreignFields: [...field.relationToFields ?? []],
|
|
26
|
+
isList: field.isList,
|
|
27
|
+
localFields: [...field.relationFromFields ?? []],
|
|
28
|
+
oneToOne: !field.isList && opposite !== void 0 && !opposite.isList,
|
|
29
|
+
...field.relationName ? { relationName: field.relationName } : {},
|
|
30
|
+
targetModel: field.type
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function primaryKeyOf(model) {
|
|
35
|
+
const idFields = model.fields.filter((field) => field.isId).map((field) => field.name);
|
|
36
|
+
if (idFields.length > 0) return { fields: idFields };
|
|
37
|
+
if (model.primaryKey) return { fields: [...model.primaryKey.fields], ...model.primaryKey.name ? { name: model.primaryKey.name } : {} };
|
|
38
|
+
const uniqueIndex = model.uniqueIndexes[0];
|
|
39
|
+
if (uniqueIndex) return { fields: [...uniqueIndex.fields], ...uniqueIndex.name ? { name: uniqueIndex.name } : {} };
|
|
40
|
+
const uniqueField = model.fields.find((field) => field.isUnique);
|
|
41
|
+
if (uniqueField) return { fields: [uniqueField.name] };
|
|
42
|
+
throw new Error(`cache generator: model ${model.name} has no primary key or unique constraint`);
|
|
43
|
+
}
|
|
44
|
+
var isSkipped = (model) => (model.documentation ?? "").split(/\r?\n/).some((line) => line.trim() === SKIP_DIRECTIVE);
|
|
45
|
+
function buildCacheConfig(datamodel, excludeModels = []) {
|
|
46
|
+
const excluded = new Set(excludeModels);
|
|
47
|
+
const unknown = excludeModels.filter((name) => !datamodel.models.some((model) => model.name === name));
|
|
48
|
+
if (unknown.length > 0) throw new Error(`cache generator: unknown models in exclude: ${unknown.join(", ")}`);
|
|
49
|
+
const cacheVersion = createHash("sha256").update(JSON.stringify(datamodel) + CACHE_CONFIG_SALT).digest("hex").slice(0, 12);
|
|
50
|
+
const keys = datamodel.models.map((model) => [model.name, primaryKeyOf(model)]);
|
|
51
|
+
const named = keys.flatMap(([name, key]) => key.name ? [[name, key.name]] : []);
|
|
52
|
+
return {
|
|
53
|
+
cacheVersion,
|
|
54
|
+
configFormat: CONFIG_FORMAT,
|
|
55
|
+
cacheableByModel: Object.fromEntries(datamodel.models.map((model) => [model.name, !isSkipped(model) && !excluded.has(model.name)])),
|
|
56
|
+
hasDecimalFields: datamodel.models.some((model) => model.fields.some((field) => field.type === "Decimal")),
|
|
57
|
+
modelNames: datamodel.models.map((model) => model.name),
|
|
58
|
+
primaryKeyFieldsByModel: Object.fromEntries(keys.map(([name, key]) => [name, key.fields])),
|
|
59
|
+
primaryKeyNameByModel: Object.fromEntries(named),
|
|
60
|
+
relationGraph: Object.fromEntries(
|
|
61
|
+
datamodel.models.map((model) => [model.name, relationsOf(model, datamodel.models)]).filter(([, relations]) => relations.length > 0)
|
|
62
|
+
)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function renderCacheConfig(config, importFrom) {
|
|
66
|
+
return `import type { GeneratedCacheConfig } from "${importFrom}";
|
|
67
|
+
|
|
68
|
+
export const cacheConfig: GeneratedCacheConfig = ${JSON.stringify(config, null, 2)};
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/generator/index.ts
|
|
73
|
+
var PACKAGE_NAME = "@dee-wan/cache";
|
|
74
|
+
function listOption(value) {
|
|
75
|
+
const items = Array.isArray(value) ? value : (value ?? "").split(",");
|
|
76
|
+
return items.map((item) => item.trim()).filter((item) => item.length > 0);
|
|
77
|
+
}
|
|
78
|
+
helper.generatorHandler({
|
|
79
|
+
onGenerate(options) {
|
|
80
|
+
const output = options.generator.output?.value;
|
|
81
|
+
if (!output) throw new Error("cache generator: output is required");
|
|
82
|
+
const config = buildCacheConfig(options.dmmf.datamodel, listOption(options.generator.config.exclude));
|
|
83
|
+
mkdirSync(output, { recursive: true });
|
|
84
|
+
writeFileSync(join(output, "cache-config.ts"), renderCacheConfig(config, PACKAGE_NAME));
|
|
85
|
+
return Promise.resolve();
|
|
86
|
+
},
|
|
87
|
+
onManifest() {
|
|
88
|
+
return { defaultOutput: "./generated/cache", prettyName: "Dee Wan cache config" };
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/generator/index.ts","../../src/generator/config.ts","../../src/core/limits.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport helper from \"@prisma/generator-helper\";\n\nimport { buildCacheConfig, renderCacheConfig } from \"./config\";\n\nconst PACKAGE_NAME = \"@dee-wan/cache\";\n\nfunction listOption(value: string | string[] | undefined): string[] {\n const items = Array.isArray(value) ? value : (value ?? \"\").split(\",\");\n return items.map((item) => item.trim()).filter((item) => item.length > 0);\n}\n\nhelper.generatorHandler({\n onGenerate(options) {\n const output = options.generator.output?.value;\n if (!output) throw new Error(\"cache generator: output is required\");\n const config = buildCacheConfig(options.dmmf.datamodel, listOption(options.generator.config.exclude));\n mkdirSync(output, { recursive: true });\n writeFileSync(join(output, \"cache-config.ts\"), renderCacheConfig(config, PACKAGE_NAME));\n return Promise.resolve();\n },\n onManifest() {\n return { defaultOutput: \"./generated/cache\", prettyName: \"Dee Wan cache config\" };\n },\n});\n","import { createHash } from \"node:crypto\";\n\nimport type { DMMF } from \"@prisma/generator-helper\";\n\nimport type { GeneratedCacheConfig, RelationInfo } from \"../core/types\";\n\nimport { CONFIG_FORMAT } from \"../core/limits\";\n\nexport const CACHE_CONFIG_SALT = \"cf-1\";\nexport const SKIP_DIRECTIVE = \"@cache.skip\";\n\ntype Model = DMMF.Datamodel[\"models\"][number];\n\nfunction relationsOf(model: Model, models: readonly Model[]): RelationInfo[] {\n return model.fields\n .filter((field) => field.kind === \"object\")\n .map((field) => {\n const opposite = models\n .find((candidate) => candidate.name === field.type)\n ?.fields.find((other) => other.kind === \"object\" && other.relationName === field.relationName && other !== field);\n return {\n fieldName: field.name,\n foreignFields: [...(field.relationToFields ?? [])],\n isList: field.isList,\n localFields: [...(field.relationFromFields ?? [])],\n oneToOne: !field.isList && opposite !== undefined && !opposite.isList,\n ...(field.relationName ? { relationName: field.relationName } : {}),\n targetModel: field.type,\n };\n });\n}\n\ninterface PrimaryKey {\n fields: string[];\n name?: string;\n}\n\nfunction primaryKeyOf(model: Model): PrimaryKey {\n const idFields = model.fields.filter((field) => field.isId).map((field) => field.name);\n if (idFields.length > 0) return { fields: idFields };\n if (model.primaryKey) return { fields: [...model.primaryKey.fields], ...(model.primaryKey.name ? { name: model.primaryKey.name } : {}) };\n const uniqueIndex = model.uniqueIndexes[0];\n if (uniqueIndex) return { fields: [...uniqueIndex.fields], ...(uniqueIndex.name ? { name: uniqueIndex.name } : {}) };\n const uniqueField = model.fields.find((field) => field.isUnique);\n if (uniqueField) return { fields: [uniqueField.name] };\n throw new Error(`cache generator: model ${model.name} has no primary key or unique constraint`);\n}\n\nexport const isSkipped = (model: Model): boolean =>\n (model.documentation ?? \"\").split(/\\r?\\n/).some((line) => line.trim() === SKIP_DIRECTIVE);\n\nexport function buildCacheConfig(datamodel: DMMF.Datamodel, excludeModels: string[] = []): GeneratedCacheConfig {\n const excluded = new Set(excludeModels);\n const unknown = excludeModels.filter((name) => !datamodel.models.some((model) => model.name === name));\n if (unknown.length > 0) throw new Error(`cache generator: unknown models in exclude: ${unknown.join(\", \")}`);\n const cacheVersion = createHash(\"sha256\")\n .update(JSON.stringify(datamodel) + CACHE_CONFIG_SALT)\n .digest(\"hex\")\n .slice(0, 12);\n const keys = datamodel.models.map((model) => [model.name, primaryKeyOf(model)] as const);\n const named = keys.flatMap(([name, key]) => (key.name ? [[name, key.name] as const] : []));\n return {\n cacheVersion,\n configFormat: CONFIG_FORMAT,\n cacheableByModel: Object.fromEntries(datamodel.models.map((model) => [model.name, !isSkipped(model) && !excluded.has(model.name)])),\n hasDecimalFields: datamodel.models.some((model) => model.fields.some((field) => field.type === \"Decimal\")),\n modelNames: datamodel.models.map((model) => model.name),\n primaryKeyFieldsByModel: Object.fromEntries(keys.map(([name, key]) => [name, key.fields])),\n primaryKeyNameByModel: Object.fromEntries(named),\n relationGraph: Object.fromEntries(\n datamodel.models\n .map((model) => [model.name, relationsOf(model, datamodel.models)] as const)\n .filter(([, relations]) => relations.length > 0),\n ),\n };\n}\n\nexport function renderCacheConfig(config: GeneratedCacheConfig, importFrom: string): string {\n return `import type { GeneratedCacheConfig } from \"${importFrom}\";\n\nexport const cacheConfig: GeneratedCacheConfig = ${JSON.stringify(config, null, 2)};\n`;\n}\n","export const MAX_LOCK_MS = 300_000;\nexport const MAX_LEASE_MS = 600_000;\nexport const MAX_VALUE_BYTES = 1_900_000;\nexport const MAX_GENERATION_LENGTH = 256;\nexport const MAX_COORDINATOR_GENERATION_LENGTH = 512;\nexport const MAX_TTL_MS = 366 * 24 * 60 * 60 * 1000;\nexport const TTL_JITTER_RATIO = 0.1;\nexport const MAX_SHAPE_TTL_SECONDS = Math.floor(MAX_TTL_MS / 1000 / (1 + TTL_JITTER_RATIO));\nexport const CONFIG_FORMAT = 2;\nexport const PLANNER_VERSION = 2;\n"],"mappings":";;;AACA,SAAS,WAAW,qBAAqB;AACzC,SAAS,YAAY;AAErB,OAAO,YAAY;;;ACJnB,SAAS,kBAAkB;;;ACKpB,IAAM,aAAa,MAAM,KAAK,KAAK,KAAK;AACxC,IAAM,mBAAmB;AACzB,IAAM,wBAAwB,KAAK,MAAM,aAAa,OAAQ,IAAI,iBAAiB;AACnF,IAAM,gBAAgB;;;ADAtB,IAAM,oBAAoB;AAC1B,IAAM,iBAAiB;AAI9B,SAAS,YAAY,OAAc,QAA0C;AAC3E,SAAO,MAAM,OACV,OAAO,CAAC,UAAU,MAAM,SAAS,QAAQ,EACzC,IAAI,CAAC,UAAU;AACd,UAAM,WAAW,OACd,KAAK,CAAC,cAAc,UAAU,SAAS,MAAM,IAAI,GAChD,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,YAAY,MAAM,iBAAiB,MAAM,gBAAgB,UAAU,KAAK;AAClH,WAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,eAAe,CAAC,GAAI,MAAM,oBAAoB,CAAC,CAAE;AAAA,MACjD,QAAQ,MAAM;AAAA,MACd,aAAa,CAAC,GAAI,MAAM,sBAAsB,CAAC,CAAE;AAAA,MACjD,UAAU,CAAC,MAAM,UAAU,aAAa,UAAa,CAAC,SAAS;AAAA,MAC/D,GAAI,MAAM,eAAe,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC;AAAA,MACjE,aAAa,MAAM;AAAA,IACrB;AAAA,EACF,CAAC;AACL;AAOA,SAAS,aAAa,OAA0B;AAC9C,QAAM,WAAW,MAAM,OAAO,OAAO,CAAC,UAAU,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,MAAM,IAAI;AACrF,MAAI,SAAS,SAAS,EAAG,QAAO,EAAE,QAAQ,SAAS;AACnD,MAAI,MAAM,WAAY,QAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,WAAW,MAAM,GAAG,GAAI,MAAM,WAAW,OAAO,EAAE,MAAM,MAAM,WAAW,KAAK,IAAI,CAAC,EAAG;AACvI,QAAM,cAAc,MAAM,cAAc,CAAC;AACzC,MAAI,YAAa,QAAO,EAAE,QAAQ,CAAC,GAAG,YAAY,MAAM,GAAG,GAAI,YAAY,OAAO,EAAE,MAAM,YAAY,KAAK,IAAI,CAAC,EAAG;AACnH,QAAM,cAAc,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ;AAC/D,MAAI,YAAa,QAAO,EAAE,QAAQ,CAAC,YAAY,IAAI,EAAE;AACrD,QAAM,IAAI,MAAM,0BAA0B,MAAM,IAAI,0CAA0C;AAChG;AAEO,IAAM,YAAY,CAAC,WACvB,MAAM,iBAAiB,IAAI,MAAM,OAAO,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,MAAM,cAAc;AAEnF,SAAS,iBAAiB,WAA2B,gBAA0B,CAAC,GAAyB;AAC9G,QAAM,WAAW,IAAI,IAAI,aAAa;AACtC,QAAM,UAAU,cAAc,OAAO,CAAC,SAAS,CAAC,UAAU,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,IAAI,CAAC;AACrG,MAAI,QAAQ,SAAS,EAAG,OAAM,IAAI,MAAM,+CAA+C,QAAQ,KAAK,IAAI,CAAC,EAAE;AAC3G,QAAM,eAAe,WAAW,QAAQ,EACrC,OAAO,KAAK,UAAU,SAAS,IAAI,iBAAiB,EACpD,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AACd,QAAM,OAAO,UAAU,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,aAAa,KAAK,CAAC,CAAU;AACvF,QAAM,QAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAO,IAAI,OAAO,CAAC,CAAC,MAAM,IAAI,IAAI,CAAU,IAAI,CAAC,CAAE;AACzF,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB,OAAO,YAAY,UAAU,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,SAAS,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC;AAAA,IAClI,kBAAkB,UAAU,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,SAAS,CAAC;AAAA,IACzG,YAAY,UAAU,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI;AAAA,IACtD,yBAAyB,OAAO,YAAY,KAAK,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;AAAA,IACzF,uBAAuB,OAAO,YAAY,KAAK;AAAA,IAC/C,eAAe,OAAO;AAAA,MACpB,UAAU,OACP,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,YAAY,OAAO,UAAU,MAAM,CAAC,CAAU,EAC1E,OAAO,CAAC,CAAC,EAAE,SAAS,MAAM,UAAU,SAAS,CAAC;AAAA,IACnD;AAAA,EACF;AACF;AAEO,SAAS,kBAAkB,QAA8B,YAA4B;AAC1F,SAAO,8CAA8C,UAAU;AAAA;AAAA,mDAEd,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA;AAElF;;;AD1EA,IAAM,eAAe;AAErB,SAAS,WAAW,OAAgD;AAClE,QAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI,SAAS,SAAS,IAAI,MAAM,GAAG;AACpE,SAAO,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AAC1E;AAEA,OAAO,iBAAiB;AAAA,EACtB,WAAW,SAAS;AAClB,UAAM,SAAS,QAAQ,UAAU,QAAQ;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,qCAAqC;AAClE,UAAM,SAAS,iBAAiB,QAAQ,KAAK,WAAW,WAAW,QAAQ,UAAU,OAAO,OAAO,CAAC;AACpG,cAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,kBAAc,KAAK,QAAQ,iBAAiB,GAAG,kBAAkB,QAAQ,YAAY,CAAC;AACtF,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EACA,aAAa;AACX,WAAO,EAAE,eAAe,qBAAqB,YAAY,uBAAuB;AAAA,EAClF;AACF,CAAC;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { d as CacheExtensionOptions, I as InvalidationTarget } from './types-DwtU0KpX.js';
|
|
2
|
+
export { e as CacheShape, C as CacheStore, f as CacheTestHooks, D as DecimalConstructor, G as GeneratedCacheConfig, g as RelationInfo } from './types-DwtU0KpX.js';
|
|
3
|
+
|
|
4
|
+
declare class CacheUnavailableError extends Error {
|
|
5
|
+
constructor(cause: unknown);
|
|
6
|
+
}
|
|
7
|
+
type Query = (args: unknown) => Promise<unknown>;
|
|
8
|
+
interface OperationParams {
|
|
9
|
+
__internalParams?: unknown;
|
|
10
|
+
args: unknown;
|
|
11
|
+
model?: string;
|
|
12
|
+
operation: string;
|
|
13
|
+
query: Query;
|
|
14
|
+
}
|
|
15
|
+
declare function createCacheExtension(options: CacheExtensionOptions): {
|
|
16
|
+
client: {
|
|
17
|
+
$cacheInvalidate(target: InvalidationTarget): Promise<void>;
|
|
18
|
+
$cacheRawWrite<T>(target: InvalidationTarget, run: () => Promise<T>): Promise<T>;
|
|
19
|
+
};
|
|
20
|
+
name: string;
|
|
21
|
+
query: {
|
|
22
|
+
$allModels: {
|
|
23
|
+
$allOperations(params: OperationParams): Promise<unknown>;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { CacheExtensionOptions, CacheUnavailableError, InvalidationTarget, createCacheExtension };
|