@datum-cloud/strapi-revalidate 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -222,6 +222,18 @@ Every successful Strapi fetch writes to **two** caches: the primary TTL cache (c
222
222
 
223
223
  Issues and PRs welcome at [github.com/datum-cloud/strapi-revalidate](https://github.com/datum-cloud/strapi-revalidate/issues). This library was extracted from production code at [datum.net](https://datum.net); contributions that keep the public surface small and the dependencies few are especially appreciated.
224
224
 
225
+ ### Releasing
226
+
227
+ This repo uses [Changesets](https://github.com/changesets/changesets) + GitHub Actions for automated releases. When your PR introduces a user-visible change, add a changeset:
228
+
229
+ ```bash
230
+ npx changeset
231
+ ```
232
+
233
+ Pick the bump type (`patch` / `minor` / `major`) and write a short summary. Commit the generated `.changeset/*.md` alongside your changes.
234
+
235
+ After your PR merges to `main`, the **Release** workflow opens (or updates) a `chore: version packages` PR that consumes the pending changesets, bumps `package.json`, and updates `CHANGELOG.md`. Merging that PR triggers an automated `npm publish` via [npm OIDC trusted publishing](https://docs.npmjs.com/trusted-publishers) — no long-lived npm token in repo secrets, and each release ships with a verifiable provenance attestation tied back to the source commit.
236
+
225
237
  ## License
226
238
 
227
239
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/cache/drivers/file.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/cache/drivers/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,WAAW,GAAG,OAAO,CAAC;AAC5B,MAAM,WAAW,GAAG,UAAU,CAAC;AAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC;AAQzB,uCAAuC;AACvC,MAAM,OAAO,eAAe;IACT,GAAG,CAAS;IAE7B,YAAY,OAA0B;QACpC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAElD,mDAAmD;YACnD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CAAC,uBAAuB,GAAG,4BAA4B,CAAC,CAAC;gBACrE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,cAAc,GAAkB,IAAI,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAC5D,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAW,CAAC;YACrD,CAAC;YAAC,MAAM,CAAC;gBACP,wCAAwC;YAC1C,CAAC;YAED,IAAI,cAAc,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;gBAC3D,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,sCAAsC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;YACjE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,UAA2B,EAAE;QAC9D,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;YACvD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,yFAAyF;YACzF,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAChF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;SACtC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAW;QAC3B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACvF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAe;QACxB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,KAAK;iBACf,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;iBAC5C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;YACnD,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,GAAW;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,WAAW,EAAE,CAAC,CAAC;IACrD,CAAC;IAEO,WAAW,CAAC,GAAW;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,WAAW,EAAE,CAAC,CAAC;IACrD,CAAC;IAEO,QAAQ,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,GAAW;QAChC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,QAAgB;QACzC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Filesystem cache driver.\n *\n * Adapted from datum.net's production `Cache` class. Preserves the original\n * behaviour:\n * - one `.json` payload file per key\n * - sibling `.expires` file storing the absolute expiry timestamp (ms)\n * - empty-file guard: a zero-length cache file is auto-cleared\n * - ENOENT is silent; other read errors clear the corrupt entry\n *\n * Tag membership is persisted alongside the payload in a sidecar `.tags` file\n * so `deleteByTag` survives process restarts.\n */\n\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CacheDriver, CacheSetOptions } from '../types.js';\n\nconst PAYLOAD_EXT = '.json';\nconst EXPIRES_EXT = '.expires';\nconst TAGS_EXT = '.tags';\n\n/** Configuration for the file driver. */\nexport interface FileDriverOptions {\n /** Directory where cache files live. Created on first write. */\n dir: string;\n}\n\n/** Filesystem-backed `CacheDriver`. */\nexport class FileCacheDriver implements CacheDriver {\n private readonly dir: string;\n\n constructor(options: FileDriverOptions) {\n this.dir = options.dir;\n }\n\n async get<T>(key: string): Promise<T | null> {\n const filePath = this.payloadPath(key);\n const expiresPath = this.expiresPath(key);\n\n try {\n const data = await fs.readFile(filePath, 'utf-8');\n\n // Empty-file guard preserved from datum.net Cache.\n if (!data.trim()) {\n console.warn(`Cache file for key \"${key}\" is empty, clearing cache`);\n await this.delete(key);\n return null;\n }\n\n let expirationTime: number | null = null;\n try {\n const expiresData = await fs.readFile(expiresPath, 'utf-8');\n expirationTime = JSON.parse(expiresData) as number;\n } catch {\n // No expires file — treat as no expiry.\n }\n\n if (expirationTime !== null && Date.now() > expirationTime) {\n await this.delete(key);\n return null;\n }\n\n return JSON.parse(data) as T;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return null;\n }\n console.warn(`Failed to read cache file for key \"${key}\":`, err);\n await this.delete(key);\n return null;\n }\n }\n\n async set<T>(key: string, data: T, options: CacheSetOptions = {}): Promise<void> {\n await this.ensureDir();\n\n const filePath = this.payloadPath(key);\n await fs.writeFile(filePath, JSON.stringify(data), 'utf-8');\n\n if (typeof options.ttl === 'number' && options.ttl > 0) {\n const expirationTime = Date.now() + options.ttl * 1000;\n await fs.writeFile(this.expiresPath(key), JSON.stringify(expirationTime), 'utf-8');\n } else {\n // If a previous entry had an expiry, remove it so the new entry is treated as permanent.\n await this.silentUnlink(this.expiresPath(key));\n }\n\n if (options.tags && options.tags.length > 0) {\n await fs.writeFile(this.tagsPath(key), JSON.stringify(options.tags), 'utf-8');\n } else {\n await this.silentUnlink(this.tagsPath(key));\n }\n }\n\n async delete(key: string): Promise<void> {\n await Promise.all([\n this.silentUnlink(this.payloadPath(key)),\n this.silentUnlink(this.expiresPath(key)),\n this.silentUnlink(this.tagsPath(key)),\n ]);\n }\n\n async deleteByTag(tag: string): Promise<void> {\n const keys = await this.keys();\n await Promise.all(\n keys.map(async (key) => {\n const tags = await this.readTags(key);\n if (tags.includes(tag)) {\n await this.delete(key);\n }\n })\n );\n }\n\n async clear(): Promise<void> {\n try {\n const files = await fs.readdir(this.dir);\n await Promise.all(files.map((file) => this.silentUnlink(path.join(this.dir, file))));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n }\n }\n\n async keys(prefix?: string): Promise<string[]> {\n try {\n const files = await fs.readdir(this.dir);\n const keys = files\n .filter((file) => file.endsWith(PAYLOAD_EXT))\n .map((file) => path.basename(file, PAYLOAD_EXT));\n return prefix ? keys.filter((k) => k.startsWith(prefix)) : keys;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw err;\n }\n }\n\n private payloadPath(key: string): string {\n return path.join(this.dir, `${key}${PAYLOAD_EXT}`);\n }\n\n private expiresPath(key: string): string {\n return path.join(this.dir, `${key}${EXPIRES_EXT}`);\n }\n\n private tagsPath(key: string): string {\n return path.join(this.dir, `${key}${TAGS_EXT}`);\n }\n\n private async ensureDir(): Promise<void> {\n await fs.mkdir(this.dir, { recursive: true });\n }\n\n private async readTags(key: string): Promise<string[]> {\n try {\n const raw = await fs.readFile(this.tagsPath(key), 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n return Array.isArray(parsed) ? parsed.filter((t): t is string => typeof t === 'string') : [];\n } catch {\n return [];\n }\n }\n\n private async silentUnlink(filePath: string): Promise<void> {\n try {\n await fs.unlink(filePath);\n } catch {\n // ENOENT and similar — ignore.\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cache/drivers/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cache/drivers/memory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * In-memory cache driver.\n *\n * Intended for development, testing, and short-lived serverless functions\n * where process restarts naturally evict the cache. Not suitable for\n * multi-instance deployments — use the redis driver for that.\n */\n\nimport type { CacheDriver, CacheSetOptions } from '../types.js';\n\ninterface MemoryEntry {\n /** Stored payload (typed as `unknown` so `get<T>` can cast). */\n data: unknown;\n /** Absolute expiry timestamp in ms, or `null` for no expiry. */\n expiresAt: number | null;\n /** Tags associated with the entry. */\n tags: Set<string>;\n}\n\n/** Map-based in-memory `CacheDriver`. */\nexport class MemoryCacheDriver implements CacheDriver {\n private readonly store = new Map<string, MemoryEntry>();\n private readonly tagIndex = new Map<string, Set<string>>();\n\n async get<T>(key: string): Promise<T | null> {\n const entry = this.store.get(key);\n if (!entry) return null;\n\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n await this.delete(key);\n return null;\n }\n\n return entry.data as T;\n }\n\n async set<T>(key: string, data: T, options: CacheSetOptions = {}): Promise<void> {\n // Detach old tags first so reassignments don't leak.\n const previous = this.store.get(key);\n if (previous) {\n for (const tag of previous.tags) {\n this.tagIndex.get(tag)?.delete(key);\n }\n }\n\n const expiresAt =\n typeof options.ttl === 'number' && options.ttl > 0 ? Date.now() + options.ttl * 1000 : null;\n const tags = new Set(options.tags ?? []);\n\n this.store.set(key, { data, expiresAt, tags });\n\n for (const tag of tags) {\n let bucket = this.tagIndex.get(tag);\n if (!bucket) {\n bucket = new Set();\n this.tagIndex.set(tag, bucket);\n }\n bucket.add(key);\n }\n }\n\n async delete(key: string): Promise<void> {\n const entry = this.store.get(key);\n if (!entry) return;\n\n for (const tag of entry.tags) {\n const bucket = this.tagIndex.get(tag);\n if (bucket) {\n bucket.delete(key);\n if (bucket.size === 0) {\n this.tagIndex.delete(tag);\n }\n }\n }\n this.store.delete(key);\n }\n\n async deleteByTag(tag: string): Promise<void> {\n const bucket = this.tagIndex.get(tag);\n if (!bucket) return;\n // Materialize before iterating — delete() mutates the bucket.\n const keys = Array.from(bucket);\n for (const key of keys) {\n await this.delete(key);\n }\n }\n\n async clear(): Promise<void> {\n this.store.clear();\n this.tagIndex.clear();\n }\n\n async keys(prefix?: string): Promise<string[]> {\n const keys = Array.from(this.store.keys());\n return prefix ? keys.filter((k) => k.startsWith(prefix)) : keys;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/cache/drivers/redis.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,uBAAuB,GAC3B,wGAAwG,CAAC;AAE3G,wDAAwD;AACxD,MAAM,OAAO,gBAAgB;IAC3B,wEAAwE;IACvD,OAAO,CAAqB;IAE7C,YAAY,OAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,IAAY;QACvB,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,KAAQ,EAAE,QAA0B;QAC7D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY;QAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAgB;QACzB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;CACF"}
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/cache/drivers/redis.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,uBAAuB,GAC3B,wGAAwG,CAAC;AAE3G,wDAAwD;AACxD,MAAM,OAAO,gBAAgB;IAC3B,wEAAwE;IACvD,OAAO,CAAqB;IAE7C,YAAY,OAA2B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,IAAY;QACvB,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,KAAQ,EAAE,QAA0B;QAC7D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY;QAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAgB;QACzB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;CACF","sourcesContent":["/**\n * Redis cache driver — STUB.\n *\n * The interface is exported so config typing and exports stay stable.\n * Actual ioredis-backed implementation is planned for v1.x; consumers\n * that try to instantiate this driver will get a clear runtime error.\n */\n\nimport type { CacheDriver, CacheSetOptions } from '../types.js';\n\n/** Configuration for the (not-yet-implemented) Redis driver. */\nexport interface RedisDriverOptions {\n redisUrl: string;\n keyPrefix?: string;\n}\n\nconst NOT_IMPLEMENTED_MESSAGE =\n 'Redis driver: not implemented in v0.1.0. Install ioredis and use file/memory driver, or wait for v1.x.';\n\n/** Stubbed Redis `CacheDriver`. Every method throws. */\nexport class RedisCacheDriver implements CacheDriver {\n // Stored to satisfy strict property init while keeping the stub honest.\n private readonly options: RedisDriverOptions;\n\n constructor(options: RedisDriverOptions) {\n this.options = options;\n }\n\n async get<T>(_key: string): Promise<T | null> {\n void this.options;\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n\n async set<T>(_key: string, _data: T, _options?: CacheSetOptions): Promise<void> {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n\n async delete(_key: string): Promise<void> {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n\n async deleteByTag(_tag: string): Promise<void> {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n\n async clear(): Promise<void> {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n\n async keys(_prefix?: string): Promise<string[]> {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACxE,OAAO,IAAI,YAAY,CAAC;QACtB,OAAO;QACP,QAAQ;QACR,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG;QAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,MAAwB;IAC3C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IAChC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,KAAK,QAAQ;YACX,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACjC,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,OAAO,IAAI,gBAAgB,CAAC;gBAC1B,QAAQ;gBACR,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;aAClC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI5C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACxE,OAAO,IAAI,YAAY,CAAC;QACtB,OAAO;QACP,QAAQ;QACR,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG;QAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,MAAwB;IAC3C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;IAChC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,OAAO,IAAI,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,KAAK,QAAQ;YACX,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACjC,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,OAAO,IAAI,gBAAgB,CAAC;gBAC1B,QAAQ;gBACR,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS;aAClC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * Public cache surface.\n *\n * `createCache(config)` is the factory most users want — it builds primary\n * and fallback drivers from a `RevalidateConfig` and wraps them in a\n * `CacheManager`. Driver classes and the `CacheDriver` interface are\n * re-exported for users who want to hand-wire a custom topology.\n */\n\nimport type { RevalidateConfig } from '../types/config.js';\nimport { FileCacheDriver } from './drivers/file.js';\nimport { MemoryCacheDriver } from './drivers/memory.js';\nimport { RedisCacheDriver } from './drivers/redis.js';\nimport { CacheManager } from './manager.js';\nimport type { CacheDriver } from './types.js';\n\nexport type { CacheDriver, CacheSetOptions } from './types.js';\nexport { CacheManager } from './manager.js';\nexport type { CacheManagerOptions } from './manager.js';\nexport { FileCacheDriver } from './drivers/file.js';\nexport type { FileDriverOptions } from './drivers/file.js';\nexport { MemoryCacheDriver } from './drivers/memory.js';\nexport { RedisCacheDriver } from './drivers/redis.js';\nexport type { RedisDriverOptions } from './drivers/redis.js';\n\n/**\n * Build a `CacheManager` from a validated `RevalidateConfig`.\n *\n * The primary driver is whichever was configured (`file` by default); the\n * fallback driver is always a file-backed cache pointed at\n * `config.cache.fallbackDir` so persistence survives process restarts even\n * when the primary is in-memory.\n */\nexport function createCache(config: RevalidateConfig): CacheManager {\n const primary = buildDriver(config);\n const fallback = new FileCacheDriver({ dir: config.cache.fallbackDir });\n return new CacheManager({\n primary,\n fallback,\n defaultTtl: config.cache.ttl,\n debug: config.debug,\n });\n}\n\nfunction buildDriver(config: RevalidateConfig): CacheDriver {\n const { driver } = config.cache;\n switch (driver) {\n case 'file':\n return new FileCacheDriver({ dir: config.cache.dir });\n case 'memory':\n return new MemoryCacheDriver();\n case 'redis': {\n const redisUrl = config.cache.redisUrl;\n if (!redisUrl) {\n throw new Error('Redis driver requires `cache.redisUrl` to be set.');\n }\n return new RedisCacheDriver({\n redisUrl,\n keyPrefix: config.cache.keyPrefix,\n });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/cache/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH;;;GAGG;AACH,MAAM,OAAO,YAAY;IACN,OAAO,CAAc;IACrB,QAAQ,CAAc;IACtB,UAAU,CAAS;IACnB,KAAK,CAAU;IAEhC,YAAY,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kFAAkF;IAClF,KAAK,CAAC,WAAW,CAAI,GAAW;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,UAA2B,EAAE;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC;QAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/D,2EAA2E;QAC3E,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/cache/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH;;;GAGG;AACH,MAAM,OAAO,YAAY;IACN,OAAO,CAAc;IACrB,QAAQ,CAAc;IACtB,UAAU,CAAS;IACnB,KAAK,CAAU;IAEhC,YAAY,OAA4B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,GAAG,CAAI,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kFAAkF;IAClF,KAAK,CAAC,WAAW,CAAI,GAAW;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,UAA2B,EAAE;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC;QAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/D,2EAA2E;QAC3E,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,mFAAmF;IACnF,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * CacheManager — the composition layer the public API talks to.\n *\n * Responsibilities:\n * - Track tag membership across writes so `invalidate(tag)` is O(tagged keys).\n * - Mirror every successful `set()` to a persistent fallback driver with no\n * TTL, so Strapi outages don't take the site down.\n * - Provide `getWithFallback()` for read paths: short-TTL hit > fetch >\n * long-lived fallback hit.\n *\n * Drivers themselves stay storage-only; tag accounting lives here.\n */\n\nimport type { CacheDriver, CacheSetOptions } from './types.js';\n\n/** Options for instantiating a `CacheManager`. */\nexport interface CacheManagerOptions {\n /** Primary driver — honours TTL, serves hot reads. */\n primary: CacheDriver;\n /** Persistent fallback driver — never expires, written on every successful set. */\n fallback: CacheDriver;\n /** Default TTL (seconds) applied when `set` is called without one. */\n defaultTtl?: number;\n /** When true, hits/misses are logged via `console.debug`. */\n debug?: boolean;\n}\n\n/**\n * Cache facade. All content fetchers and the webhook handler talk to this,\n * not to a driver directly.\n */\nexport class CacheManager {\n private readonly primary: CacheDriver;\n private readonly fallback: CacheDriver;\n private readonly defaultTtl: number;\n private readonly debug: boolean;\n\n constructor(options: CacheManagerOptions) {\n this.primary = options.primary;\n this.fallback = options.fallback;\n this.defaultTtl = options.defaultTtl ?? 3600;\n this.debug = options.debug ?? false;\n }\n\n /** Read from the primary cache. Returns `null` on miss or expiry. */\n async get<T>(key: string): Promise<T | null> {\n const value = await this.primary.get<T>(key);\n if (this.debug) {\n console.debug(`[strapi-revalidate] cache ${value === null ? 'MISS' : 'HIT'} → ${key}`);\n }\n return value;\n }\n\n /** Read from the persistent fallback cache. Returns `null` if never populated. */\n async getFallback<T>(key: string): Promise<T | null> {\n return this.fallback.get<T>(key);\n }\n\n /**\n * Write to both the primary cache (with TTL + tags) and the fallback cache\n * (no TTL, no tags). Tag accounting happens at the driver level.\n */\n async set<T>(key: string, data: T, options: CacheSetOptions = {}): Promise<void> {\n const ttl = options.ttl ?? this.defaultTtl;\n await this.primary.set(key, data, { ttl, tags: options.tags });\n // Fallback: no TTL, no tag indexing — it exists purely to survive outages.\n await this.fallback.set(key, data);\n }\n\n /** Remove a single key from the primary cache. Fallback is preserved by design. */\n async delete(key: string): Promise<void> {\n await this.primary.delete(key);\n }\n\n /**\n * Invalidate every primary-cache key associated with `tag`. The fallback\n * cache is intentionally untouched — if the upcoming refetch fails, stale\n * data should still serve.\n */\n async invalidate(tag: string): Promise<void> {\n await this.primary.deleteByTag(tag);\n if (this.debug) {\n console.debug(`[strapi-revalidate] invalidated tag → ${tag}`);\n }\n }\n\n /** Invalidate all primary-cache entries. Fallback is preserved. */\n async invalidateAll(): Promise<void> {\n await this.primary.clear();\n if (this.debug) {\n console.debug('[strapi-revalidate] invalidated all');\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cache/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cache/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Cache driver contract.\n *\n * Implementations are responsible for storage details (filesystem, in-memory\n * Map, Redis, etc.). The `CacheManager` layered above provides tag tracking\n * and fallback semantics so drivers stay simple.\n */\n\n/** Options accepted by `CacheDriver.set`. */\nexport interface CacheSetOptions {\n /** Time-to-live in **seconds**. Omit for no expiry. */\n ttl?: number;\n /** Tag names associated with this key. Drivers may persist these to support `deleteByTag`. */\n tags?: string[];\n}\n\n/**\n * Storage-agnostic cache contract. All public cache APIs accept anything\n * that satisfies this interface.\n */\nexport interface CacheDriver {\n /** Returns the cached value for `key`, or `null` if missing or expired. */\n get<T>(key: string): Promise<T | null>;\n\n /** Stores `data` under `key` with optional ttl (seconds) and tag list. */\n set<T>(key: string, data: T, options?: CacheSetOptions): Promise<void>;\n\n /** Removes a single key. No-op if absent. */\n delete(key: string): Promise<void>;\n\n /** Removes every key associated with `tag`. */\n deleteByTag(tag: string): Promise<void>;\n\n /** Removes every key managed by this driver. */\n clear(): Promise<void>;\n\n /** Lists all keys, optionally filtered by a string prefix. */\n keys(prefix?: string): Promise<string[]>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../src/client/graphql.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../src/client/graphql.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GraphQL transport for Strapi v5.\n *\n * Adapted from datum.net's `graphqlQuery()` with two additions: configurable\n * retry with exponential backoff, and a structured `StrapiClient` surface so\n * the same instance is reused across fetchers (no module-level state).\n */\n\n/** Generic Strapi GraphQL response envelope. */\nexport interface GraphQLResponse<T> {\n data: T;\n errors?: Array<{ message: string }>;\n}\n\n/** Configuration for a `GraphQLStrapiClient`. */\nexport interface GraphQLClientOptions {\n /** Strapi base URL (no trailing `/graphql`). */\n url: string;\n /** Strapi API token. Sent as `Authorization: Bearer <token>`. */\n token: string;\n /** Per-request timeout in **milliseconds**. */\n timeout: number;\n /** Number of retries on transport failure (timeout, network, 5xx). 0 disables retry. */\n retry: number;\n /** When true, logs request lifecycle via `console.debug`. */\n debug?: boolean;\n}\n\n/**\n * Strapi GraphQL client.\n *\n * `query<T>()` returns the unwrapped `data` payload or `null` on failure;\n * callers are expected to treat `null` as \"Strapi unreachable / invalid\"\n * and fall back to stale cache.\n */\nexport class GraphQLStrapiClient {\n private readonly options: GraphQLClientOptions;\n\n constructor(options: GraphQLClientOptions) {\n this.options = options;\n }\n\n /**\n * Execute a GraphQL operation. Returns the `data` payload on success,\n * `null` if the server returns an error envelope, a non-2xx status,\n * times out, or all retries are exhausted.\n */\n async query<T>(query: string, variables: Record<string, unknown> = {}): Promise<T | null> {\n const { retry } = this.options;\n let lastError: unknown = null;\n\n for (let attempt = 0; attempt <= retry; attempt++) {\n try {\n const result = await this.executeOnce<T>(query, variables);\n if (result !== null) return result;\n // result === null means a structured Strapi error (4xx / GraphQL errors).\n // Don't retry those — they won't get better.\n return null;\n } catch (err) {\n lastError = err;\n if (this.options.debug) {\n console.debug(\n `[strapi-revalidate] graphql attempt ${attempt + 1}/${retry + 1} failed:`,\n err\n );\n }\n if (attempt < retry) {\n await sleep(backoffMs(attempt));\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n console.error(`Strapi request timed out after ${this.options.timeout}ms`);\n } else if (lastError) {\n console.error('Error fetching from Strapi:', lastError);\n }\n return null;\n }\n\n private async executeOnce<T>(\n query: string,\n variables: Record<string, unknown>\n ): Promise<T | null> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.options.timeout);\n\n try {\n const response = await fetch(`${this.options.url.replace(/\\/$/, '')}/graphql`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.options.token}`,\n },\n body: JSON.stringify({ query, variables }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n console.error(`Strapi GraphQL error: ${response.status} ${response.statusText}`, text);\n // 5xx is retryable — surface as a thrown error so the retry loop fires.\n if (response.status >= 500) {\n throw new Error(`Strapi ${response.status} ${response.statusText}`);\n }\n return null;\n }\n\n const result = (await response.json()) as GraphQLResponse<T>;\n\n if (result.errors && result.errors.length > 0) {\n console.error('Strapi GraphQL errors:', result.errors);\n return null;\n }\n\n return result.data;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Exponential backoff with a sane cap. Attempt is 0-indexed. */\nfunction backoffMs(attempt: number): number {\n const base = 200 * 2 ** attempt;\n return Math.min(base, 2000);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAW/D;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,wDAAwD;QACxD,gBAAgB,CAAC;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QACH,4EAA4E;QAC5E,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,IAAI,mBAAmB,CAAC;QAC7B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAW/D;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,wDAAwD;QACxD,gBAAgB,CAAC;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QACH,4EAA4E;QAC5E,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,IAAI,mBAAmB,CAAC;QAC7B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Public client surface.\n *\n * `createStrapiClient(config)` picks the right transport (graphql today,\n * rest later) and returns a unified `StrapiClient`. All built-in content\n * fetchers receive a client through their `fetch*` helpers rather than\n * instantiating one themselves — so the same connection, timeout, and\n * retry policy applies across the package.\n */\n\nimport type { RevalidateConfig } from '../types/config.js';\nimport { GraphQLStrapiClient } from './graphql.js';\nimport { createRestClient } from './rest.js';\n\nexport { GraphQLStrapiClient } from './graphql.js';\nexport type { GraphQLClientOptions, GraphQLResponse } from './graphql.js';\nexport { createRestClient, RestStrapiClient } from './rest.js';\nexport type { RestClientOptions } from './rest.js';\n\n/**\n * Anything the package's content fetchers know how to talk to.\n *\n * Today this is exclusively the GraphQL client; the REST stub is planned\n * to satisfy the same shape via a `query`-style adapter in a future release.\n */\nexport type StrapiClient = GraphQLStrapiClient;\n\n/**\n * Build a `StrapiClient` from a validated `RevalidateConfig`. Throws\n * `Error` if the configured transport isn't implemented yet (REST).\n */\nexport function createStrapiClient(config: RevalidateConfig): StrapiClient {\n if (config.transport === 'rest') {\n // Surfaced via the stub for a consistent error message.\n createRestClient({\n url: config.url,\n token: config.token,\n timeout: config.timeout,\n retry: config.retry,\n });\n // Unreachable — createRestClient throws — but keeps the return type honest.\n throw new Error('REST transport not yet implemented');\n }\n\n return new GraphQLStrapiClient({\n url: config.url,\n token: config.token,\n timeout: config.timeout,\n retry: config.retry,\n debug: config.debug,\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../src/client/rest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,uBAAuB,GAC3B,+FAA+F,CAAC;AAElG,4FAA4F;AAC5F,MAAM,OAAO,gBAAgB;IAC3B,iEAAiE;IAChD,OAAO,CAAoB;IAE5C,YAAY,OAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,KAAa,EAAE,OAAiC;QAC3D,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,QAA2B;IAC1D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"rest.js","sourceRoot":"","sources":["../../src/client/rest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,uBAAuB,GAC3B,+FAA+F,CAAC;AAElG,4FAA4F;AAC5F,MAAM,OAAO,gBAAgB;IAC3B,iEAAiE;IAChD,OAAO,CAAoB;IAE5C,YAAY,OAA0B;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,KAAa,EAAE,OAAiC;QAC3D,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,QAA2B;IAC1D,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["/**\n * REST transport for Strapi — STUB.\n *\n * The interface is exported for forward compatibility; runtime usage throws\n * a clear error. v0.1.0 only ships the GraphQL transport because every\n * built-in content fetcher uses GraphQL.\n */\n\n/** Configuration for the (not-yet-implemented) REST client. */\nexport interface RestClientOptions {\n url: string;\n token: string;\n timeout: number;\n retry: number;\n}\n\nconst NOT_IMPLEMENTED_MESSAGE =\n 'REST transport not yet implemented. Use transport: \"graphql\" or pin to a future v1.x release.';\n\n/** Stubbed REST client. Constructor is callable so config typing works; all reads throw. */\nexport class RestStrapiClient {\n // Stored to keep strict property init quiet and document intent.\n private readonly options: RestClientOptions;\n\n constructor(options: RestClientOptions) {\n this.options = options;\n }\n\n async get<T>(_path: string, _params?: Record<string, unknown>): Promise<T | null> {\n void this.options;\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n }\n}\n\n/** Factory that mirrors `createStrapiClient` shape. Throws on first use. */\nexport function createRestClient(_options: RestClientOptions): RestStrapiClient {\n throw new Error(NOT_IMPLEMENTED_MESSAGE);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/content/articles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/content/articles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Article fetchers.\n *\n * Refactored from datum.net's `articles.ts`: same GraphQL queries and same\n * primary-then-fallback read pattern, but the client and cache are injected\n * rather than module-level singletons. Datum-specific transforms (block\n * stripping, top-3 cover preservation, reading-time calculation) are\n * intentionally not ported — those belong in application code.\n */\n\nimport type { CacheManager } from '../cache/manager.js';\nimport type { StrapiClient } from '../client/index.js';\nimport type { StrapiArticle, StrapiArticlesResponse } from '../types/strapi.js';\n\nconst LIST_CACHE_KEY = 'strapi-articles';\nconst DETAIL_CACHE_PREFIX = 'strapi-article-';\nconst FALLBACK_LIST_KEY = 'articles';\nconst FALLBACK_DETAIL_PREFIX = 'article-';\n\n/** GraphQL query: every published article, newest first. */\nexport const ARTICLES_QUERY = `\n query GetArticles {\n articles(pagination: { limit: 100 }, sort: [\"originalPublishedAt:desc\"]) {\n documentId\n title\n slug\n description\n originalPublishedAt\n blocks {\n __typename\n ... on ComponentSharedRichText {\n id\n body\n }\n }\n cover {\n url\n alternativeText\n width\n height\n formats\n }\n author {\n documentId\n slug\n name\n isTeam\n avatar {\n url\n alternativeText\n }\n }\n category {\n name\n slug\n }\n }\n }\n`;\n\n/** GraphQL query: a single article by slug, including SEO and quote blocks. */\nexport const ARTICLE_BY_SLUG_QUERY = `\n query GetArticleBySlug($slug: String!) {\n articles(filters: { slug: { eq: $slug } }) {\n documentId\n title\n slug\n description\n originalPublishedAt\n blocks {\n __typename\n ... on ComponentSharedQuote {\n body\n title\n }\n ... on ComponentSharedRichText {\n id\n body\n }\n }\n cover {\n url\n alternativeText\n width\n height\n formats\n }\n author {\n documentId\n slug\n name\n isTeam\n avatar {\n url\n alternativeText\n }\n }\n category {\n name\n slug\n }\n seo {\n metaTitle\n metaDescription\n ogTitle\n ogDescription\n shareImage {\n url\n }\n }\n }\n }\n`;\n\n/** Dependencies threaded into every content fetcher. */\nexport interface ContentDeps {\n client: StrapiClient;\n cache: CacheManager;\n}\n\n/**\n * Fetch every article from Strapi. Reads from cache first; on Strapi failure,\n * serves stale data from the persistent fallback cache instead of throwing.\n *\n * Cache key: `strapi-articles`. Tags: `[\"articles\"]`.\n */\nexport async function fetchArticles({ client, cache }: ContentDeps): Promise<StrapiArticle[]> {\n const cached = await cache.get<StrapiArticle[]>(LIST_CACHE_KEY);\n if (cached) return cached;\n\n const response = await client.query<StrapiArticlesResponse>(ARTICLES_QUERY);\n\n if (!response?.articles) {\n const fallback = await cache.getFallback<StrapiArticle[]>(FALLBACK_LIST_KEY);\n if (fallback) {\n console.warn(`Strapi unreachable — serving ${fallback.length} articles from fallback`);\n return fallback;\n }\n return [];\n }\n\n await cache.set(LIST_CACHE_KEY, response.articles, { tags: ['articles'] });\n // Mirror to fallback under the legacy datum.net key so manual recovery is straightforward.\n await cache.set(FALLBACK_LIST_KEY, response.articles, { tags: ['articles'] });\n return response.articles;\n}\n\n/**\n * Fetch a single article by slug. Cached per slug; falls back to stale\n * data when Strapi is unreachable.\n *\n * Cache key: `strapi-article-<slug>`. Tags: `[\"articles\", \"article:<slug>\"]`.\n */\nexport async function fetchArticle(\n slug: string,\n { client, cache }: ContentDeps\n): Promise<StrapiArticle | null> {\n const cacheKey = `${DETAIL_CACHE_PREFIX}${slug}`;\n const cached = await cache.get<StrapiArticle>(cacheKey);\n if (cached) return cached;\n\n const response = await client.query<StrapiArticlesResponse>(ARTICLE_BY_SLUG_QUERY, { slug });\n\n if (!response?.articles || response.articles.length === 0) {\n const fallback = await cache.getFallback<StrapiArticle>(`${FALLBACK_DETAIL_PREFIX}${slug}`);\n if (fallback) {\n console.warn(`Strapi unreachable — serving article \"${slug}\" from fallback`);\n return fallback;\n }\n return null;\n }\n\n const article = response.articles[0];\n const tags = ['articles', `article:${slug}`];\n await cache.set(cacheKey, article, { tags });\n await cache.set(`${FALLBACK_DETAIL_PREFIX}${slug}`, article, { tags });\n return article;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"authors.js","sourceRoot":"","sources":["../../src/content/authors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authors.js","sourceRoot":"","sources":["../../src/content/authors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Author fetchers.\n *\n * Refactored from datum.net's `authors.ts`. Datum-specific concerns (team\n * sorting, cardCategories normalization, color helpers) are intentionally\n * out of scope — this module returns Strapi authors as-is.\n */\n\nimport type { StrapiAuthorFull, StrapiAuthorsResponse } from '../types/strapi.js';\nimport type { ContentDeps } from './articles.js';\n\nconst LIST_CACHE_KEY = 'strapi-authors';\nconst DETAIL_CACHE_PREFIX = 'strapi-author-';\nconst FALLBACK_LIST_KEY = 'authors';\nconst FALLBACK_DETAIL_PREFIX = 'author-';\n\n/** GraphQL query: every author. */\nexport const AUTHORS_QUERY = `\n query GetAuthors {\n authors(pagination: { limit: 100 }) {\n documentId\n slug\n name\n title\n bio\n isTeam\n team\n location\n timezone\n avatar {\n url\n alternativeText\n }\n social {\n twitter\n linkedin\n github\n discord\n email\n }\n }\n }\n`;\n\n/** GraphQL query: a single author by slug. */\nexport const AUTHOR_BY_SLUG_QUERY = `\n query GetAuthorBySlug($slug: String!) {\n authors(filters: { slug: { eq: $slug } }) {\n documentId\n slug\n name\n title\n bio\n isTeam\n team\n location\n timezone\n avatar {\n url\n alternativeText\n }\n social {\n twitter\n linkedin\n github\n discord\n email\n }\n }\n }\n`;\n\n/**\n * Fetch every author from Strapi. Caches the list; falls back to stale data\n * on Strapi failure.\n *\n * Cache key: `strapi-authors`. Tags: `[\"authors\"]`.\n */\nexport async function fetchAuthors({ client, cache }: ContentDeps): Promise<StrapiAuthorFull[]> {\n const cached = await cache.get<StrapiAuthorFull[]>(LIST_CACHE_KEY);\n if (cached) return cached;\n\n const response = await client.query<StrapiAuthorsResponse>(AUTHORS_QUERY);\n\n if (!response?.authors) {\n const fallback = await cache.getFallback<StrapiAuthorFull[]>(FALLBACK_LIST_KEY);\n if (fallback) {\n console.warn(`Strapi unreachable — serving ${fallback.length} authors from fallback`);\n return fallback;\n }\n return [];\n }\n\n await cache.set(LIST_CACHE_KEY, response.authors, { tags: ['authors'] });\n await cache.set(FALLBACK_LIST_KEY, response.authors, { tags: ['authors'] });\n return response.authors;\n}\n\n/**\n * Fetch a single author by slug. Cached per slug; falls back to stale data\n * on Strapi failure.\n *\n * Cache key: `strapi-author-<slug>`. Tags: `[\"authors\", \"author:<slug>\"]`.\n */\nexport async function fetchAuthor(\n slug: string,\n { client, cache }: ContentDeps\n): Promise<StrapiAuthorFull | null> {\n const cacheKey = `${DETAIL_CACHE_PREFIX}${slug}`;\n const cached = await cache.get<StrapiAuthorFull>(cacheKey);\n if (cached) return cached;\n\n const response = await client.query<StrapiAuthorsResponse>(AUTHOR_BY_SLUG_QUERY, { slug });\n\n if (!response?.authors || response.authors.length === 0) {\n const fallback = await cache.getFallback<StrapiAuthorFull>(`${FALLBACK_DETAIL_PREFIX}${slug}`);\n if (fallback) {\n console.warn(`Strapi unreachable — serving author \"${slug}\" from fallback`);\n return fallback;\n }\n return null;\n }\n\n const author = response.authors[0];\n const tags = ['authors', `author:${slug}`];\n await cache.set(cacheKey, author, { tags });\n await cache.set(`${FALLBACK_DETAIL_PREFIX}${slug}`, author, { tags });\n return author;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["/**\n * Public content surface.\n *\n * Re-exports every built-in fetcher and their GraphQL queries. Queries are\n * exported as `const` strings so consumers can extend them with additional\n * fields by composing their own query and passing it to the client directly.\n */\n\nexport type { ContentDeps } from './articles.js';\nexport {\n fetchArticles,\n fetchArticle,\n ARTICLES_QUERY,\n ARTICLE_BY_SLUG_QUERY,\n} from './articles.js';\nexport { fetchAuthors, fetchAuthor, AUTHORS_QUERY, AUTHOR_BY_SLUG_QUERY } from './authors.js';\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,6DAA6D;AAC7D,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAiB3D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA4B;IACjE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,6DAA6D;AAC7D,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAiB3D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA4B;IACjE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["/**\n * Package root — re-exports the most commonly used API surface so most\n * consumers can `import { createStrapiRevalidate } from 'strapi-revalidate'`\n * and never touch the subpath imports.\n */\n\nimport { createCache } from './cache/index.js';\nimport type { CacheManager } from './cache/manager.js';\nimport { createStrapiClient } from './client/index.js';\nimport type { StrapiClient } from './client/index.js';\nimport { revalidateConfigSchema } from './types/config.js';\nimport type { RevalidateConfig, RevalidateConfigInput } from './types/config.js';\nimport { createWebhookHandler } from './webhook/handler.js';\nimport type { WebhookHandler } from './webhook/handler.js';\n\n// Subpath re-exports (mirrors the package.json exports map).\nexport * from './cache/index.js';\nexport * from './client/index.js';\nexport * from './content/index.js';\nexport * from './webhook/index.js';\nexport * from './types/strapi.js';\nexport { revalidateConfigSchema } from './types/config.js';\nexport type {\n RevalidateConfig,\n RevalidateConfigInput,\n CacheDriverName,\n TransportName,\n} from './types/config.js';\n\n/** Bundle of objects returned by `createStrapiRevalidate`. */\nexport interface StrapiRevalidate {\n config: RevalidateConfig;\n client: StrapiClient;\n cache: CacheManager;\n /** Pre-built webhook handler bound to this `client`/`cache` pair. */\n webhook: WebhookHandler;\n}\n\n/**\n * One-call factory that validates config, builds the client, cache manager,\n * and webhook handler, and returns them as a single object.\n *\n * @example\n * const { cache, client, webhook } = createStrapiRevalidate({\n * url: process.env.STRAPI_URL!,\n * token: process.env.STRAPI_TOKEN!,\n * webhook: { secret: process.env.STRAPI_WEBHOOK_SECRET },\n * });\n */\nexport function createStrapiRevalidate(input: RevalidateConfigInput): StrapiRevalidate {\n const config = revalidateConfigSchema.parse(input);\n const cache = createCache(config);\n const client = createStrapiClient(config);\n const webhook = createWebhookHandler({ config, cache });\n return { config, client, cache, webhook };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,0CAA0C;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAGzE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAG/D,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IACnD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IACzD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,OAAO,CAAC,EAAE,CAAC,CAAC;AAEf,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,iEAAiE;IACjE,YAAY,EAAE,CAAC;SACZ,MAAM,CACL,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,UAAU,CACnC;SACA,QAAQ,EAAE;CACd,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,mBAAmB;IAC5B,KAAK,EAAE,iBAAiB;IACxB,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAClC,CAAC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,0CAA0C;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAGzE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAG/D,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IACnD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IACzD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,OAAO,CAAC,EAAE,CAAC,CAAC;AAEf,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,iEAAiE;IACjE,YAAY,EAAE,CAAC;SACZ,MAAM,CACL,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,UAAU,CACnC;SACA,QAAQ,EAAE;CACd,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,mBAAmB;IAC5B,KAAK,EAAE,iBAAiB;IACxB,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAClC,CAAC,CAAC","sourcesContent":["/**\n * Runtime configuration schema for strapi-revalidate.\n *\n * Validated with zod so misconfigurations surface at startup rather than\n * at the first cache miss or webhook delivery.\n */\n\nimport { z } from 'zod';\nimport type { WebhookEvent } from '../webhook/types.js';\n\n/** Supported cache driver identifiers. */\nexport const cacheDriverNameSchema = z.enum(['file', 'memory', 'redis']);\nexport type CacheDriverName = z.infer<typeof cacheDriverNameSchema>;\n\n/** Supported transport identifiers for the Strapi client. */\nexport const transportNameSchema = z.enum(['graphql', 'rest']);\nexport type TransportName = z.infer<typeof transportNameSchema>;\n\nconst cacheConfigSchema = z\n .object({\n driver: cacheDriverNameSchema.default('file'),\n ttl: z.number().int().positive().default(3600),\n dir: z.string().default('.cache/strapi-revalidate'),\n fallbackDir: z.string().default('.cache/strapi-fallback'),\n redisUrl: z.string().url().optional(),\n keyPrefix: z.string().optional(),\n })\n .default({});\n\nconst webhookConfigSchema = z\n .object({\n secret: z.string().optional(),\n tagMap: z.record(z.array(z.string())).optional(),\n // `z.function().args(...).returns(...)` is a zod v3-only chain — v4 reshaped\n // the function schema API and removed it. Use `z.custom` instead so the schema\n // loads under either major version. Runtime validation still ensures the value\n // is a function; the TS-level signature carries the typed shape.\n onRevalidate: z\n .custom<(event: WebhookEvent) => void | Promise<void>>(\n (val) => typeof val === 'function'\n )\n .optional(),\n })\n .optional();\n\n/**\n * Full runtime configuration schema.\n *\n * Use `revalidateConfigSchema.parse(input)` to validate user input and\n * apply defaults in one step.\n */\nexport const revalidateConfigSchema = z.object({\n url: z.string().url(),\n token: z.string().min(1),\n webhook: webhookConfigSchema,\n cache: cacheConfigSchema,\n transport: transportNameSchema.default('graphql'),\n timeout: z.number().int().positive().default(3000),\n retry: z.number().int().min(0).default(2),\n debug: z.boolean().default(false),\n});\n\n/** User-supplied configuration (pre-validation). */\nexport type RevalidateConfigInput = z.input<typeof revalidateConfigSchema>;\n\n/** Validated, defaults-applied configuration. */\nexport type RevalidateConfig = z.output<typeof revalidateConfigSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"strapi.js","sourceRoot":"","sources":["../../src/types/strapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"strapi.js","sourceRoot":"","sources":["../../src/types/strapi.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG","sourcesContent":["/**\n * Type definitions for Strapi v5 content types.\n *\n * These mirror the shape returned by the default Strapi v5 GraphQL API.\n * They are intentionally narrow: only fields that strapi-revalidate's\n * built-in helpers query are included. Consumers fetching custom content\n * types should declare their own interfaces and pass them through\n * `createStrapiClient().query<T>()`.\n */\n\n/** A single Strapi media format (thumbnail, small, medium, large). */\nexport interface StrapiImageFormat {\n url: string;\n width?: number;\n height?: number;\n}\n\n/** A Strapi media asset with optional responsive formats. */\nexport interface StrapiImage {\n url: string;\n alternativeText?: string;\n caption?: string;\n width?: number;\n height?: number;\n formats?: {\n thumbnail?: StrapiImageFormat;\n small?: StrapiImageFormat;\n medium?: StrapiImageFormat;\n large?: StrapiImageFormat;\n };\n}\n\n/** Minimal author reference embedded in other content types. */\nexport interface StrapiAuthor {\n documentId?: string;\n slug?: string;\n name: string;\n isTeam?: boolean;\n avatar?: StrapiImage;\n}\n\n/** Social handles for a Strapi author. */\nexport interface StrapiSocial {\n twitter?: string;\n linkedin?: string;\n github?: string;\n discord?: string;\n email?: string;\n}\n\n/** Full author record (Strapi `author` content type). */\nexport interface StrapiAuthorFull {\n documentId: string;\n slug?: string;\n name: string;\n title?: string;\n bio?: string;\n isTeam?: boolean;\n team?: string;\n avatar?: StrapiImage;\n social?: StrapiSocial;\n location?: string;\n timezone?: string;\n}\n\n/** GraphQL response shape for the `authors` query. */\nexport interface StrapiAuthorsResponse {\n authors: StrapiAuthorFull[];\n}\n\n/** Category reference on an article. */\nexport interface StrapiCategory {\n name: string;\n slug: string;\n}\n\n/** SEO component fields. */\nexport interface StrapiSeo {\n metaTitle?: string;\n metaDescription?: string;\n ogTitle?: string;\n ogDescription?: string;\n shareImage?: { url?: string };\n}\n\n/** A block of an article body (Strapi Dynamic Zone entry). */\nexport interface StrapiBlock {\n __typename?: string;\n id?: string;\n body?: string;\n title?: string;\n}\n\n/** Article record (Strapi `article` content type). */\nexport interface StrapiArticle {\n documentId: string;\n title: string;\n slug: string;\n description?: string;\n originalPublishedAt?: string;\n blocks?: StrapiBlock[];\n cover?: StrapiImage;\n author?: StrapiAuthor;\n category?: StrapiCategory;\n seo?: StrapiSeo;\n}\n\n/** GraphQL response shape for the `articles` query. */\nexport interface StrapiArticlesResponse {\n articles: StrapiArticle[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/webhook/handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-agnostic webhook handler.\n *\n * `createWebhookHandler(config)` returns an `async (req, res) => void`\n * function whose `req` and `res` accept the lowest-common-denominator\n * shapes used by Astro, Next.js (Route Handlers), SvelteKit, Express,\n * and raw Node http. Each framework's docs page in the README shows the\n * single line of glue code needed.\n *\n * Behaviour:\n * 1. 405 if method isn't POST.\n * 2. 401 if a secret is configured and the request's secret doesn't match\n * (constant-time compare; supports `Authorization: Bearer <secret>`,\n * `X-Strapi-Signature`, or a raw `strapi-webhook-secret` header).\n * 3. 400 if the body isn't a parseable Strapi v5 webhook payload.\n * 4. Resolves tags via `mapModelToTags`, calls `cache.invalidate(tag)` for\n * each, and invokes `onRevalidate` if configured.\n * 5. 200 with `{ ok: true, tags }`.\n */\n\nimport { timingSafeEqual } from 'node:crypto';\nimport { createCache } from '../cache/index.js';\nimport type { CacheManager } from '../cache/manager.js';\nimport { revalidateConfigSchema } from '../types/config.js';\nimport type { RevalidateConfig, RevalidateConfigInput } from '../types/config.js';\nimport { mapModelToTags } from './tags.js';\nimport type {\n WebhookEvent,\n WebhookPayload,\n WebhookRequest,\n WebhookResponse,\n} from './types.js';\n\n/** Async function shape returned by `createWebhookHandler`. */\nexport type WebhookHandler = (req: WebhookRequest, res: WebhookResponse) => Promise<void>;\n\n/**\n * Build a webhook handler bound to a validated config and the cache\n * manager derived from it.\n *\n * Accepts either a `RevalidateConfigInput` (raw user object — gets validated)\n * or a pair of pre-built dependencies, so power users can share a single\n * `CacheManager` across handlers and content fetchers.\n */\nexport function createWebhookHandler(input: RevalidateConfigInput): WebhookHandler;\nexport function createWebhookHandler(deps: {\n config: RevalidateConfig;\n cache: CacheManager;\n}): WebhookHandler;\nexport function createWebhookHandler(\n input: RevalidateConfigInput | { config: RevalidateConfig; cache: CacheManager }\n): WebhookHandler {\n const { config, cache } = resolveDeps(input);\n\n return async function handle(req, res) {\n if (req.method && req.method.toUpperCase() !== 'POST') {\n res.status(405);\n res.json({ ok: false, error: 'Method not allowed' });\n return;\n }\n\n const configuredSecret = config.webhook?.secret;\n if (configuredSecret) {\n const provided = readSecret(req);\n if (!provided || !constantTimeEqual(provided, configuredSecret)) {\n res.status(401);\n res.json({ ok: false, error: 'Invalid secret' });\n return;\n }\n }\n\n let payload: WebhookPayload;\n try {\n payload = await readPayload(req);\n } catch (err) {\n res.status(400);\n res.json({\n ok: false,\n error: err instanceof Error ? err.message : 'Bad payload',\n });\n return;\n }\n\n const tags = mapModelToTags(payload, config.webhook?.tagMap);\n for (const tag of tags) {\n await cache.invalidate(tag);\n }\n\n const event: WebhookEvent = {\n event: payload.event,\n model: payload.model,\n uid: payload.uid,\n entryId: payload.entry.documentId,\n slug: typeof payload.entry.slug === 'string' ? payload.entry.slug : undefined,\n tags,\n };\n\n if (config.webhook?.onRevalidate) {\n try {\n await config.webhook.onRevalidate(event);\n } catch (err) {\n // The cache is already invalidated; surface the hook failure to the caller\n // but treat the revalidation itself as successful.\n console.error('[strapi-revalidate] onRevalidate hook threw:', err);\n }\n }\n\n res.status(200);\n res.json({ ok: true, tags });\n };\n}\n\nfunction resolveDeps(\n input: RevalidateConfigInput | { config: RevalidateConfig; cache: CacheManager }\n): { config: RevalidateConfig; cache: CacheManager } {\n if (isPreBuilt(input)) return input;\n const config = revalidateConfigSchema.parse(input);\n const cache = createCache(config);\n return { config, cache };\n}\n\nfunction isPreBuilt(\n value: unknown\n): value is { config: RevalidateConfig; cache: CacheManager } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'config' in value &&\n 'cache' in value &&\n typeof (value as { cache: unknown }).cache === 'object'\n );\n}\n\nfunction readSecret(req: WebhookRequest): string | null {\n // Headers can arrive as Fetch-style Headers (`.get()`) or as a plain map.\n const direct = headerValue(req, 'authorization');\n if (direct) {\n const match = /^Bearer\\s+(.+)$/i.exec(direct);\n if (match) return match[1].trim();\n }\n\n return (\n headerValue(req, 'x-strapi-signature') ??\n headerValue(req, 'strapi-webhook-secret') ??\n null\n );\n}\n\nfunction headerValue(req: WebhookRequest, name: string): string | null {\n const headers = req.headers;\n if (typeof headers.get === 'function') {\n return headers.get(name);\n }\n const lower = name.toLowerCase();\n const raw = (headers as Record<string, unknown>)[lower] ?? (headers as Record<string, unknown>)[name];\n if (typeof raw === 'string') return raw;\n if (Array.isArray(raw) && typeof raw[0] === 'string') return raw[0];\n return null;\n}\n\nasync function readPayload(req: WebhookRequest): Promise<WebhookPayload> {\n let raw: unknown;\n if (typeof req.json === 'function') {\n raw = await req.json();\n } else if (typeof req.text === 'function') {\n const text = await req.text();\n raw = text.length > 0 ? JSON.parse(text) : {};\n } else {\n throw new Error('Request object exposes neither json() nor text()');\n }\n\n if (!isWebhookPayload(raw)) {\n throw new Error('Payload is not a valid Strapi v5 webhook event');\n }\n return raw;\n}\n\nfunction isWebhookPayload(value: unknown): value is WebhookPayload {\n if (typeof value !== 'object' || value === null) return false;\n const v = value as Record<string, unknown>;\n if (typeof v.event !== 'string' || typeof v.model !== 'string' || typeof v.uid !== 'string') {\n return false;\n }\n if (typeof v.entry !== 'object' || v.entry === null) return false;\n const entry = v.entry as Record<string, unknown>;\n return typeof entry.documentId === 'string' || typeof entry.id === 'number';\n}\n\nfunction constantTimeEqual(a: string, b: string): boolean {\n // timingSafeEqual requires equal-length buffers; pad both to the longer length so the\n // length check itself is constant-time-safe (different lengths still return false).\n const bufA = Buffer.from(a, 'utf-8');\n const bufB = Buffer.from(b, 'utf-8');\n if (bufA.length !== bufB.length) return false;\n return timingSafeEqual(bufA, bufB);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhook/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC","sourcesContent":["/**\n * Public webhook surface — re-exports for the `strapi-revalidate/webhook`\n * subpath.\n */\n\nexport { createWebhookHandler } from './handler.js';\nexport type { WebhookHandler } from './handler.js';\nexport { mapModelToTags } from './tags.js';\nexport type {\n WebhookEvent,\n WebhookEventName,\n WebhookPayload,\n WebhookRequest,\n WebhookResponse,\n} from './types.js';\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/webhook/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,+BAA+B;AAC/B,MAAM,eAAe,GAA6B;IAChD,sBAAsB,EAAE,CAAC,UAAU,CAAC;IACpC,oBAAoB,EAAE,CAAC,SAAS,CAAC;CAClC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAuB,EACvB,SAAoC;IAEpC,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IACjG,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,OAAuB;IAC3C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/webhook/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,+BAA+B;AAC/B,MAAM,eAAe,GAA6B;IAChD,sBAAsB,EAAE,CAAC,UAAU,CAAC;IACpC,oBAAoB,EAAE,CAAC,SAAS,CAAC;CAClC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAuB,EACvB,SAAoC;IAEpC,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;IACjG,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,OAAuB;IAC3C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC;AACrC,CAAC","sourcesContent":["/**\n * Strapi UID → cache tag mapping.\n *\n * Default rules:\n * - `api::article.article` → `[\"articles\"]` (+ `article:<slug>` if entry has slug)\n * - `api::author.author` → `[\"authors\"]` (+ `author:<slug>` if entry has slug)\n * - any other `api::<name>.<name>` → `[<name>]` (+ `<name>:<slug>` if present)\n *\n * Override per-UID via `config.webhook.tagMap` — passing `[\"foo\", \"bar\"]`\n * replaces the default tag list for that UID (the slug-derived tag is still\n * appended automatically when present).\n */\n\nimport type { WebhookPayload } from './types.js';\n\n/** Built-in UID → tag list. */\nconst DEFAULT_TAG_MAP: Record<string, string[]> = {\n 'api::article.article': ['articles'],\n 'api::author.author': ['authors'],\n};\n\n/**\n * Resolve cache tags for a webhook payload.\n *\n * @param payload - Raw Strapi v5 webhook payload.\n * @param overrides - Optional UID → tag list overrides from config.\n * @returns Deduplicated list of tags to invalidate.\n */\nexport function mapModelToTags(\n payload: WebhookPayload,\n overrides?: Record<string, string[]>\n): string[] {\n const base = overrides?.[payload.uid] ?? DEFAULT_TAG_MAP[payload.uid] ?? [extractModel(payload)];\n const slug = typeof payload.entry?.slug === 'string' ? payload.entry.slug : undefined;\n const tags = slug ? [...base, `${payload.model}:${slug}`] : base;\n return Array.from(new Set(tags));\n}\n\n/**\n * Extract the model name from a UID. `api::article.article` → `article`.\n * Falls back to `payload.model` if the UID is in an unexpected shape.\n */\nfunction extractModel(payload: WebhookPayload): string {\n const match = /^api::([^.]+)\\./.exec(payload.uid);\n return match?.[1] ?? payload.model;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webhook/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webhook/types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * Strapi v5 webhook payload types and the normalized event surfaced to\n * downstream handlers.\n */\n\n/** All webhook event names Strapi v5 emits. */\nexport type WebhookEventName =\n | 'entry.create'\n | 'entry.update'\n | 'entry.delete'\n | 'entry.publish'\n | 'entry.unpublish'\n | 'media.create'\n | 'media.update'\n | 'media.delete';\n\n/** Raw payload Strapi v5 POSTs to the webhook URL. */\nexport interface WebhookPayload {\n event: WebhookEventName;\n createdAt: string;\n /** Singular model name, e.g. `\"article\"`. */\n model: string;\n /** Strapi UID, e.g. `\"api::article.article\"`. */\n uid: string;\n entry: {\n id: number;\n documentId: string;\n slug?: string;\n [key: string]: unknown;\n };\n}\n\n/** Normalized event passed to `onRevalidate` after tag resolution. */\nexport interface WebhookEvent {\n event: WebhookEventName;\n model: string;\n uid: string;\n entryId: string;\n slug?: string;\n /** Cache tags resolved from `uid` (and `slug`, if present). */\n tags: string[];\n}\n\n/**\n * Minimal request interface the webhook handler accepts.\n *\n * Designed so an Astro `APIContext.request`, a Next.js `Request`, a\n * SvelteKit `RequestEvent.request`, an Express `req`, and a Node\n * `IncomingMessage` can all satisfy it (after light adapter code in the\n * user's route handler).\n */\nexport interface WebhookRequest {\n method?: string;\n headers: {\n get?: (name: string) => string | null;\n [key: string]: unknown;\n };\n text?: () => Promise<string>;\n json?: () => Promise<unknown>;\n}\n\n/**\n * Minimal response interface the webhook handler writes to.\n *\n * The handler always calls `status(code)` first and then `json(body)`. Both\n * calls are independent — `status()`'s return value is ignored — so adapters\n * in framework routes can be a few lines of capture-and-forward.\n */\nexport interface WebhookResponse {\n status: (code: number) => unknown;\n json: (body: unknown) => void | Promise<void>;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datum-cloud/strapi-revalidate",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Framework-agnostic runtime cache invalidation for Strapi v5 in SSR frontends. Receives Strapi publish webhooks, clears affected cache tags, next request serves fresh data.",
5
5
  "keywords": [
6
6
  "strapi",
@@ -60,6 +60,9 @@
60
60
  "typecheck": "tsc --noEmit",
61
61
  "test": "vitest run",
62
62
  "test:watch": "vitest",
63
+ "changeset": "changeset",
64
+ "version-packages": "changeset version",
65
+ "release": "changeset publish",
63
66
  "prepublishOnly": "npm run build"
64
67
  },
65
68
  "engines": {
@@ -83,6 +86,7 @@
83
86
  "ioredis": "^5.0.0"
84
87
  },
85
88
  "devDependencies": {
89
+ "@changesets/cli": "^2.31.0",
86
90
  "@types/node": "^20.0.0",
87
91
  "typescript": "^5.4.0",
88
92
  "vitest": "^1.6.0"