@blacklizard/inertia-cache-redis 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +105 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 blacklizard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @blacklizard/inertia-cache-redis
|
|
2
|
+
|
|
3
|
+
[](https://github.com/blacklizard/inertia-express/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@blacklizard/inertia-cache-redis)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
Redis-backed SSR view cache store for [@blacklizard/inertia-express](../inertia-express). Compatible with [`node-redis` v4+](https://github.com/redis/node-redis) and `ioredis`.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add @blacklizard/inertia-cache-redis redis
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import express from "express";
|
|
20
|
+
import { createClient } from "redis";
|
|
21
|
+
import { inertia, viteManifestVersion } from "@blacklizard/inertia-express";
|
|
22
|
+
import { createRedisCacheStore } from "@blacklizard/inertia-cache-redis";
|
|
23
|
+
|
|
24
|
+
const redis = createClient({ url: process.env.REDIS_URL });
|
|
25
|
+
await redis.connect();
|
|
26
|
+
|
|
27
|
+
const app = express();
|
|
28
|
+
app.use(
|
|
29
|
+
inertia({
|
|
30
|
+
version: viteManifestVersion({ manifestPath: "./dist/client/manifest.json" }),
|
|
31
|
+
ssr: yourSsrFetcher,
|
|
32
|
+
cache: {
|
|
33
|
+
store: createRedisCacheStore({
|
|
34
|
+
client: redis,
|
|
35
|
+
keyPrefix: "myapp:prod",
|
|
36
|
+
onError: (op, err) => console.warn(`redis cache ${op} failed`, err),
|
|
37
|
+
}),
|
|
38
|
+
ttlSeconds: 600,
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## ioredis
|
|
45
|
+
|
|
46
|
+
Pass `setMode: "ioredis"`:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import Redis from "ioredis";
|
|
50
|
+
import { createRedisCacheStore } from "@blacklizard/inertia-cache-redis";
|
|
51
|
+
|
|
52
|
+
const client = new Redis(process.env.REDIS_URL);
|
|
53
|
+
|
|
54
|
+
createRedisCacheStore({ client, setMode: "ioredis" });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Cache invalidation on deploy
|
|
58
|
+
|
|
59
|
+
Cache keys include the asset version. On deploy, a new version automatically retires every existing entry with no manual flush. Old keys expire via TTL.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SsrCacheStore } from "@blacklizard/inertia-express/core";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Structural type representing the subset of the `redis` (node-redis v4+)
|
|
6
|
+
* client API that we use. Defined here so this package does not need a
|
|
7
|
+
* runtime dependency on a specific node-redis version — pass any client
|
|
8
|
+
* with these methods, including `ioredis` (which has a compatible signature
|
|
9
|
+
* for `get`/`set`/`del`).
|
|
10
|
+
*/
|
|
11
|
+
interface RedisClientLike {
|
|
12
|
+
get: (key: string) => Promise<string | null>;
|
|
13
|
+
/**
|
|
14
|
+
* node-redis v4+ accepts an options object: `set(key, value, { EX: n })`
|
|
15
|
+
* for TTL in seconds. We pass that shape; the call is type-erased here so
|
|
16
|
+
* either `redis@4+` or `ioredis` (which uses `set(key, value, "EX", n)`)
|
|
17
|
+
* can be adapted at construction time via `setMode`.
|
|
18
|
+
*/
|
|
19
|
+
set: (key: string, value: string, options?: unknown) => Promise<unknown>;
|
|
20
|
+
del: (keys: string | string[]) => Promise<number>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Construction options for {@link createRedisCacheStore}.
|
|
24
|
+
*/
|
|
25
|
+
interface RedisCacheStoreOptions {
|
|
26
|
+
/** Redis client. node-redis v4+ recommended; ioredis works with `setMode: "ioredis"`. */
|
|
27
|
+
client: RedisClientLike;
|
|
28
|
+
/**
|
|
29
|
+
* Calling convention for `SET` with TTL.
|
|
30
|
+
* - `"node-redis"` (default): `client.set(key, value, { EX: ttl })`
|
|
31
|
+
* - `"ioredis"`: `client.set(key, value, "EX", ttl)`
|
|
32
|
+
*/
|
|
33
|
+
setMode?: 'node-redis' | 'ioredis';
|
|
34
|
+
/**
|
|
35
|
+
* Optional key-prefix wrapper applied on top of whatever prefix the
|
|
36
|
+
* adapter computes. Use this for additional namespacing (per-environment,
|
|
37
|
+
* per-tenant, etc.).
|
|
38
|
+
*/
|
|
39
|
+
keyPrefix?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Called when a Redis op throws. Cache failures are non-fatal — the
|
|
42
|
+
* adapter's middleware swallows them — but logging here is recommended.
|
|
43
|
+
*/
|
|
44
|
+
onError?: (op: 'get' | 'set' | 'delete', err: unknown) => void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build a {@link SsrCacheStore} backed by Redis.
|
|
48
|
+
*
|
|
49
|
+
* Entries are stored as JSON strings. A `JSON.parse` failure on read is
|
|
50
|
+
* treated as a cache miss (the poisoned key is reported via `onError` and
|
|
51
|
+
* best-effort deleted) so a corrupted entry can never break a page render.
|
|
52
|
+
*
|
|
53
|
+
* @param options Store configuration — see {@link RedisCacheStoreOptions}.
|
|
54
|
+
*/
|
|
55
|
+
declare function createRedisCacheStore(options: RedisCacheStoreOptions): SsrCacheStore;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { RedisCacheStoreOptions, RedisClientLike, createRedisCacheStore };
|
|
58
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;AASA;;;;;UAAiB,eAAA;EACf,GAAA,GAAM,GAAA,aAAgB,OAAA;EAQmB;;;;;;EADzC,GAAA,GAAM,GAAA,UAAa,KAAA,UAAe,OAAA,eAAsB,OAAA;EACxD,GAAA,GAAM,IAAA,wBAA4B,OAAA;AAAA;;;;UAMnB,sBAAA;EAN0B;EAQzC,MAAA,EAAQ,eAAe;EAFc;;;;;EAQrC,OAAA;EAMA;;;;;EAAA,SAAA;EAgDc;;;;EA3Cd,OAAA,IAAW,EAAA,4BAA8B,GAAA;AAAA;;;AA2C0C;;;;;;;iBAArE,qBAAA,CAAsB,OAAA,EAAS,sBAAA,GAAyB,aAAa"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* Join an optional namespace prefix onto a cache key with a `:` separator.
|
|
4
|
+
*
|
|
5
|
+
* @param prefix Optional namespace; when undefined the key is returned unchanged.
|
|
6
|
+
* @param key Cache key to prefix.
|
|
7
|
+
*/
|
|
8
|
+
function withPrefix(prefix, key) {
|
|
9
|
+
return prefix ? `${prefix}:${key}` : key;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Delete a key, swallowing any failure after reporting it via `onError`.
|
|
13
|
+
* Used to evict a poisoned (unparseable) cache entry without letting the
|
|
14
|
+
* cleanup error mask the original read.
|
|
15
|
+
*
|
|
16
|
+
* @param client Redis client.
|
|
17
|
+
* @param key Fully-prefixed key to remove.
|
|
18
|
+
* @param onError Optional error reporter.
|
|
19
|
+
*/
|
|
20
|
+
async function bestEffortDelete(client, key, onError) {
|
|
21
|
+
try {
|
|
22
|
+
await client.del(key);
|
|
23
|
+
} catch (delErr) {
|
|
24
|
+
onError?.("delete", delErr);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build a {@link SsrCacheStore} backed by Redis.
|
|
29
|
+
*
|
|
30
|
+
* Entries are stored as JSON strings. A `JSON.parse` failure on read is
|
|
31
|
+
* treated as a cache miss (the poisoned key is reported via `onError` and
|
|
32
|
+
* best-effort deleted) so a corrupted entry can never break a page render.
|
|
33
|
+
*
|
|
34
|
+
* @param options Store configuration — see {@link RedisCacheStoreOptions}.
|
|
35
|
+
*/
|
|
36
|
+
function createRedisCacheStore(options) {
|
|
37
|
+
const setMode = options.setMode ?? "node-redis";
|
|
38
|
+
const prefix = options.keyPrefix;
|
|
39
|
+
return {
|
|
40
|
+
/**
|
|
41
|
+
* Read a cache entry. Returns `null` on miss or on poisoned (unparseable)
|
|
42
|
+
* data; rethrows when the Redis client itself errors after reporting via
|
|
43
|
+
* `onError`.
|
|
44
|
+
*
|
|
45
|
+
* @param key Cache key, before prefixing.
|
|
46
|
+
*/
|
|
47
|
+
async get(key) {
|
|
48
|
+
const fullKey = withPrefix(prefix, key);
|
|
49
|
+
try {
|
|
50
|
+
const raw = await options.client.get(fullKey);
|
|
51
|
+
if (raw === null) return null;
|
|
52
|
+
try {
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
} catch (parseErr) {
|
|
55
|
+
options.onError?.("get", parseErr);
|
|
56
|
+
await bestEffortDelete(options.client, fullKey, options.onError);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
options.onError?.("get", err);
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Write a cache entry with a TTL. Reports via `onError` and rethrows on
|
|
66
|
+
* Redis failure (the calling middleware swallows the throw — writes are
|
|
67
|
+
* fire-and-forget).
|
|
68
|
+
*
|
|
69
|
+
* @param key Cache key, before prefixing.
|
|
70
|
+
* @param value Entry to JSON-serialize and store.
|
|
71
|
+
* @param ttlSeconds Time-to-live in seconds.
|
|
72
|
+
*/
|
|
73
|
+
async set(key, value, ttlSeconds) {
|
|
74
|
+
const fullKey = withPrefix(prefix, key);
|
|
75
|
+
const payload = JSON.stringify(value);
|
|
76
|
+
try {
|
|
77
|
+
if (setMode === "ioredis") {
|
|
78
|
+
const setFn = options.client.set;
|
|
79
|
+
await setFn(fullKey, payload, "EX", ttlSeconds);
|
|
80
|
+
} else await options.client.set(fullKey, payload, { EX: ttlSeconds });
|
|
81
|
+
} catch (err) {
|
|
82
|
+
options.onError?.("set", err);
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
/**
|
|
87
|
+
* Remove a cache entry. Reports via `onError` and rethrows on failure.
|
|
88
|
+
*
|
|
89
|
+
* @param key Cache key, before prefixing.
|
|
90
|
+
*/
|
|
91
|
+
async delete(key) {
|
|
92
|
+
const fullKey = withPrefix(prefix, key);
|
|
93
|
+
try {
|
|
94
|
+
await options.client.del(fullKey);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
options.onError?.("delete", err);
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { createRedisCacheStore };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { SsrCacheEntry, SsrCacheStore } from '@blacklizard/inertia-express/core';\n\n/**\n * Structural type representing the subset of the `redis` (node-redis v4+)\n * client API that we use. Defined here so this package does not need a\n * runtime dependency on a specific node-redis version — pass any client\n * with these methods, including `ioredis` (which has a compatible signature\n * for `get`/`set`/`del`).\n */\nexport interface RedisClientLike {\n get: (key: string) => Promise<string | null>;\n /**\n * node-redis v4+ accepts an options object: `set(key, value, { EX: n })`\n * for TTL in seconds. We pass that shape; the call is type-erased here so\n * either `redis@4+` or `ioredis` (which uses `set(key, value, \"EX\", n)`)\n * can be adapted at construction time via `setMode`.\n */\n set: (key: string, value: string, options?: unknown) => Promise<unknown>;\n del: (keys: string | string[]) => Promise<number>;\n}\n\n/**\n * Construction options for {@link createRedisCacheStore}.\n */\nexport interface RedisCacheStoreOptions {\n /** Redis client. node-redis v4+ recommended; ioredis works with `setMode: \"ioredis\"`. */\n client: RedisClientLike;\n /**\n * Calling convention for `SET` with TTL.\n * - `\"node-redis\"` (default): `client.set(key, value, { EX: ttl })`\n * - `\"ioredis\"`: `client.set(key, value, \"EX\", ttl)`\n */\n setMode?: 'node-redis' | 'ioredis';\n /**\n * Optional key-prefix wrapper applied on top of whatever prefix the\n * adapter computes. Use this for additional namespacing (per-environment,\n * per-tenant, etc.).\n */\n keyPrefix?: string;\n /**\n * Called when a Redis op throws. Cache failures are non-fatal — the\n * adapter's middleware swallows them — but logging here is recommended.\n */\n onError?: (op: 'get' | 'set' | 'delete', err: unknown) => void;\n}\n\n/**\n * Join an optional namespace prefix onto a cache key with a `:` separator.\n *\n * @param prefix Optional namespace; when undefined the key is returned unchanged.\n * @param key Cache key to prefix.\n */\nfunction withPrefix(prefix: string | undefined, key: string): string {\n return prefix ? `${prefix}:${key}` : key;\n}\n\n/**\n * Delete a key, swallowing any failure after reporting it via `onError`.\n * Used to evict a poisoned (unparseable) cache entry without letting the\n * cleanup error mask the original read.\n *\n * @param client Redis client.\n * @param key Fully-prefixed key to remove.\n * @param onError Optional error reporter.\n */\nasync function bestEffortDelete(\n client: RedisClientLike,\n key: string,\n onError: RedisCacheStoreOptions['onError'],\n): Promise<void> {\n try {\n await client.del(key);\n } catch (delErr) {\n onError?.('delete', delErr);\n }\n}\n\n/**\n * Build a {@link SsrCacheStore} backed by Redis.\n *\n * Entries are stored as JSON strings. A `JSON.parse` failure on read is\n * treated as a cache miss (the poisoned key is reported via `onError` and\n * best-effort deleted) so a corrupted entry can never break a page render.\n *\n * @param options Store configuration — see {@link RedisCacheStoreOptions}.\n */\nexport function createRedisCacheStore(options: RedisCacheStoreOptions): SsrCacheStore {\n const setMode = options.setMode ?? 'node-redis';\n const prefix = options.keyPrefix;\n\n return {\n /**\n * Read a cache entry. Returns `null` on miss or on poisoned (unparseable)\n * data; rethrows when the Redis client itself errors after reporting via\n * `onError`.\n *\n * @param key Cache key, before prefixing.\n */\n async get(key: string): Promise<SsrCacheEntry | null> {\n const fullKey = withPrefix(prefix, key);\n\n try {\n const raw = await options.client.get(fullKey);\n\n if (raw === null) {\n return null;\n }\n\n try {\n return JSON.parse(raw) as SsrCacheEntry;\n } catch (parseErr) {\n // Poisoned key — report it, best-effort delete, then treat as a miss.\n options.onError?.('get', parseErr);\n await bestEffortDelete(options.client, fullKey, options.onError);\n\n return null;\n }\n } catch (err) {\n options.onError?.('get', err);\n throw err;\n }\n },\n /**\n * Write a cache entry with a TTL. Reports via `onError` and rethrows on\n * Redis failure (the calling middleware swallows the throw — writes are\n * fire-and-forget).\n *\n * @param key Cache key, before prefixing.\n * @param value Entry to JSON-serialize and store.\n * @param ttlSeconds Time-to-live in seconds.\n */\n async set(key: string, value: SsrCacheEntry, ttlSeconds: number): Promise<void> {\n const fullKey = withPrefix(prefix, key);\n const payload = JSON.stringify(value);\n\n try {\n if (setMode === 'ioredis') {\n // ioredis: client.set(key, value, \"EX\", ttl)\n const setFn = options.client.set as unknown as (\n k: string,\n v: string,\n mode: string,\n ttl: number,\n ) => Promise<unknown>;\n await setFn(fullKey, payload, 'EX', ttlSeconds);\n } else {\n // node-redis v4+: client.set(key, value, { EX: ttl })\n await options.client.set(fullKey, payload, { EX: ttlSeconds });\n }\n } catch (err) {\n options.onError?.('set', err);\n throw err;\n }\n },\n /**\n * Remove a cache entry. Reports via `onError` and rethrows on failure.\n *\n * @param key Cache key, before prefixing.\n */\n async delete(key: string): Promise<void> {\n const fullKey = withPrefix(prefix, key);\n\n try {\n await options.client.del(fullKey);\n } catch (err) {\n options.onError?.('delete', err);\n throw err;\n }\n },\n };\n}\n"],"mappings":";;;;;;;AAoDA,SAAS,WAAW,QAA4B,KAAqB;CACnE,OAAO,SAAS,GAAG,OAAO,GAAG,QAAQ;AACvC;;;;;;;;;;AAWA,eAAe,iBACb,QACA,KACA,SACe;CACf,IAAI;EACF,MAAM,OAAO,IAAI,GAAG;CACtB,SAAS,QAAQ;EACf,UAAU,UAAU,MAAM;CAC5B;AACF;;;;;;;;;;AAWA,SAAgB,sBAAsB,SAAgD;CACpF,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,SAAS,QAAQ;CAEvB,OAAO;;;;;;;;EAQL,MAAM,IAAI,KAA4C;GACpD,MAAM,UAAU,WAAW,QAAQ,GAAG;GAEtC,IAAI;IACF,MAAM,MAAM,MAAM,QAAQ,OAAO,IAAI,OAAO;IAE5C,IAAI,QAAQ,MACV,OAAO;IAGT,IAAI;KACF,OAAO,KAAK,MAAM,GAAG;IACvB,SAAS,UAAU;KAEjB,QAAQ,UAAU,OAAO,QAAQ;KACjC,MAAM,iBAAiB,QAAQ,QAAQ,SAAS,QAAQ,OAAO;KAE/D,OAAO;IACT;GACF,SAAS,KAAK;IACZ,QAAQ,UAAU,OAAO,GAAG;IAC5B,MAAM;GACR;EACF;;;;;;;;;;EAUA,MAAM,IAAI,KAAa,OAAsB,YAAmC;GAC9E,MAAM,UAAU,WAAW,QAAQ,GAAG;GACtC,MAAM,UAAU,KAAK,UAAU,KAAK;GAEpC,IAAI;IACF,IAAI,YAAY,WAAW;KAEzB,MAAM,QAAQ,QAAQ,OAAO;KAM7B,MAAM,MAAM,SAAS,SAAS,MAAM,UAAU;IAChD,OAEE,MAAM,QAAQ,OAAO,IAAI,SAAS,SAAS,EAAE,IAAI,WAAW,CAAC;GAEjE,SAAS,KAAK;IACZ,QAAQ,UAAU,OAAO,GAAG;IAC5B,MAAM;GACR;EACF;;;;;;EAMA,MAAM,OAAO,KAA4B;GACvC,MAAM,UAAU,WAAW,QAAQ,GAAG;GAEtC,IAAI;IACF,MAAM,QAAQ,OAAO,IAAI,OAAO;GAClC,SAAS,KAAK;IACZ,QAAQ,UAAU,UAAU,GAAG;IAC/B,MAAM;GACR;EACF;CACF;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@blacklizard/inertia-cache-redis",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Redis-backed SSR view cache store for @blacklizard/inertia-express. Compatible with node-redis v4+.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "blacklizard",
|
|
8
|
+
"homepage": "https://github.com/blacklizard/inertia-express/tree/main/packages/inertia-cache-redis#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/blacklizard/inertia-express.git",
|
|
12
|
+
"directory": "packages/inertia-cache-redis"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/blacklizard/inertia-express/issues"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=24"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"redis": "^4.6.0 || ^5.0.0",
|
|
38
|
+
"@blacklizard/inertia-express": "0.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.9.1",
|
|
42
|
+
"tsdown": "^0.22.0",
|
|
43
|
+
"typescript": "^6.0.3",
|
|
44
|
+
"vitest": "^4.1.7",
|
|
45
|
+
"@blacklizard/inertia-express": "0.1.0"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"inertia",
|
|
49
|
+
"inertia-js",
|
|
50
|
+
"inertiajs",
|
|
51
|
+
"express",
|
|
52
|
+
"adapter",
|
|
53
|
+
"ssr",
|
|
54
|
+
"spa",
|
|
55
|
+
"redis",
|
|
56
|
+
"cache",
|
|
57
|
+
"worker",
|
|
58
|
+
"load-balancer",
|
|
59
|
+
"self-healing"
|
|
60
|
+
],
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsdown",
|
|
63
|
+
"dev": "tsdown --watch",
|
|
64
|
+
"test": "vitest run",
|
|
65
|
+
"test:watch": "vitest",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"clean": "rm -rf dist"
|
|
68
|
+
}
|
|
69
|
+
}
|