@veryfront/ext-cache-redis 0.1.1186 → 0.1.1188

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
@@ -2,7 +2,9 @@
2
2
 
3
3
  > **Category:** Storage | **Contract:** `TokenCacheStore` | **Optional**
4
4
 
5
- Provides Redis-backed token and cache persistence for Veryfront. Used by the proxy to persist OAuth tokens across processes — the in-memory fallback works for a single-process dev server but loses tokens on restart and doesn't share across workers.
5
+ Provides Redis-backed token-cache persistence for Veryfront. The proxy uses it
6
+ to share OAuth tokens across processes. Explicit Redis selection is fail-closed:
7
+ startup and operations surface missing configuration or service failures.
6
8
 
7
9
  ## Installation
8
10
 
@@ -18,10 +20,12 @@ export default defineConfig({
18
20
 
19
21
  ## Environment Variables
20
22
 
21
- | Variable | Required | Description |
22
- | -------------- | ------------------------------ | ---------------------------------------------------------------------------- |
23
- | `REDIS_URL` | Yes (if explicit config unset) | Redis connection URL e.g. `redis://localhost:6379` or `rediss://...` (TLS) |
24
- | `REDIS_PREFIX` | No | Key prefix for all stored entries (default: none) |
23
+ | Variable | Required | Description |
24
+ | ---------------- | ------------------------------ | -------------------------------------------------------------------------------------------------- |
25
+ | `REDIS_URL` | Yes (if explicit config unset) | Redis connection URL, for example `redis://localhost:6379` or `rediss://...` (TLS) |
26
+ | `REDIS_PREFIX` | No | Token-key prefix (default: `vf:token:`); see prefix constraints below |
27
+ | `REDIS_PASSWORD` | No | Password override when credentials are not embedded in the connection URL |
28
+ | `CACHE_TYPE` | Standalone proxy only | Set to `extension` so the CLI activates this extension before importing the provider-neutral proxy |
25
29
 
26
30
  Explicit config under `ctx.config.proxy.cache.redis` wins over env vars.
27
31
 
@@ -49,9 +53,28 @@ config = {
49
53
 
50
54
  `url` is required; the rest are optional.
51
55
 
56
+ For the standalone CLI proxy, select and configure the extension before
57
+ startup:
58
+
59
+ ```bash
60
+ CACHE_TYPE=extension \
61
+ REDIS_URL=redis://localhost:6379 \
62
+ veryfront serve --mode=proxy
63
+ ```
64
+
65
+ The CLI activates `@veryfront/ext-cache-redis` through the extension loader
66
+ before it imports the proxy runtime. Missing packages, missing Redis
67
+ configuration, or a missing `TokenCacheStore` contract stop startup. The
68
+ loader retains ownership of the store; the proxy borrows it and does not close
69
+ it independently. `REDIS_PREFIX` in this path must contain 1 to 256 visible
70
+ ASCII characters and cannot contain Redis glob metacharacters (`*`, `?`, `[`,
71
+ `]`, or `\`).
72
+
52
73
  ## Provided contract
53
74
 
54
- `TokenCacheStore` `get(key)`, `set(key, value, ttlMs?)`, `delete(key)`. Used by the proxy's OAuth flow to cache access and refresh tokens.
75
+ `TokenCacheStore`: `get(key)`, `set(key, entry)`, `delete(key)`, `clear()`,
76
+ `has(key)`, `stats()`, and `close()`. Entry expiry is carried in
77
+ `entry.expiresAt`. The proxy uses the contract for OAuth service-token caching.
55
78
 
56
79
  ## Capabilities
57
80
 
@@ -4,6 +4,17 @@ declare global {
4
4
  }
5
5
  }
6
6
  export {};
7
+ declare global {
8
+ interface Object {
9
+ /**
10
+ * Determines whether an object has a property with the specified name.
11
+ * @param o An object.
12
+ * @param v A property name.
13
+ */
14
+ hasOwn(o: object, v: PropertyKey): boolean;
15
+ }
16
+ }
17
+ export {};
7
18
  /**
8
19
  * Based on [import-meta-ponyfill](https://github.com/gaubee/import-meta-ponyfill),
9
20
  * but instead of using npm to install additional dependencies,
@@ -123,15 +134,4 @@ declare global {
123
134
  }
124
135
  }
125
136
  export {};
126
- declare global {
127
- interface Object {
128
- /**
129
- * Determines whether an object has a property with the specified name.
130
- * @param o An object.
131
- * @param v A property name.
132
- */
133
- hasOwn(o: object, v: PropertyKey): boolean;
134
- }
135
- }
136
- export {};
137
137
  //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC;AACV;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAgC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAGlE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;;;;;;;;;;;;;WAcG;QACH,GAAG,EAAE,MAAM,CAAC;QACZ;;;;;;;;;;;;WAYG;QACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,GAAG,MAAM,CAAC;QACtE;;;;;;;;WAQG;QACH,IAAI,EAAE,OAAO,CAAC;QAEd;;;;;;;;;;;;WAYG;QACH,QAAQ,EAAE,MAAM,CAAC;QAEjB;;;;;;;;;;;;WAYG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB;CACF;AAED,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,KAAK,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,UAAU,0BAA0B;IAClC,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACxD;AACD,UAAU,0BAA0B;IAClC,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC;CACtC;AACD,UAAU,kBACR,SAAQ,0BAA0B,EAAE,0BAA0B;CAC/D;AAiBD,eAAO,IAAI,6BAA6B,EA2BnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,6BAA6B,EA4DnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,oBAAoB,EAoB1B,kBAAkB,CAAC;AACxB,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,kBAAkB;QAC1B;;;WAGG;QACH,aAAa,CAAC,CAAC,KAAK;YAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;YAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;SAAE,CAAC;KAC3H;CACF;AAcD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAgB;QACxB,SAAS,CAAC,CAAC,EACP,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAC7F,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAEhB,SAAS,CAAC,CAAC,EAAE,CAAC,EACV,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAClE,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAC/B,OAAO,CAAC,EAAE,GAAG,GACd,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KAC1B;CACF;AAoID,OAAO,EAAE,CAAC;AAeV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd;;;;WAIG;QACH,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;KAC5C;CACF;AAED,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,KAAK;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CACF;AAED,OAAO,EAAE,CAAC;AAgBV,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd;;;;WAIG;QACH,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;KAC5C;CACF;AAED,OAAO,EAAE,CAAC;AACV;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAgC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAGlE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;;;;;;;;;;;;;WAcG;QACH,GAAG,EAAE,MAAM,CAAC;QACZ;;;;;;;;;;;;WAYG;QACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,GAAG,MAAM,CAAC;QACtE;;;;;;;;WAQG;QACH,IAAI,EAAE,OAAO,CAAC;QAEd;;;;;;;;;;;;WAYG;QACH,QAAQ,EAAE,MAAM,CAAC;QAEjB;;;;;;;;;;;;WAYG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB;CACF;AAED,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,KAAK,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,UAAU,0BAA0B;IAClC,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACxD;AACD,UAAU,0BAA0B;IAClC,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC;CACtC;AACD,UAAU,kBACR,SAAQ,0BAA0B,EAAE,0BAA0B;CAC/D;AAiBD,eAAO,IAAI,6BAA6B,EA2BnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,6BAA6B,EA4DnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,oBAAoB,EAoB1B,kBAAkB,CAAC;AACxB,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,kBAAkB;QAC1B;;;WAGG;QACH,aAAa,CAAC,CAAC,KAAK;YAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;YAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;SAAE,CAAC;KAC3H;CACF;AAcD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAgB;QACxB,SAAS,CAAC,CAAC,EACP,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAC7F,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;QAEhB,SAAS,CAAC,CAAC,EAAE,CAAC,EACV,mBAAmB,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAClE,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAC/B,OAAO,CAAC,EAAE,GAAG,GACd,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;KAC1B;CACF;AAoID,OAAO,EAAE,CAAC"}
@@ -1,3 +1,17 @@
1
+ // https://github.com/tc39/proposal-accessible-object-hasownproperty/blob/main/polyfill.js
2
+ if (!Object.hasOwn) {
3
+ Object.defineProperty(Object, "hasOwn", {
4
+ value: function (object, property) {
5
+ if (object == null) {
6
+ throw new TypeError("Cannot convert undefined or null to object");
7
+ }
8
+ return Object.prototype.hasOwnProperty.call(Object(object), property);
9
+ },
10
+ configurable: true,
11
+ enumerable: false,
12
+ writable: true,
13
+ });
14
+ }
1
15
  /**
2
16
  * Based on [import-meta-ponyfill](https://github.com/gaubee/import-meta-ponyfill),
3
17
  * but instead of using npm to install additional dependencies,
@@ -245,16 +259,3 @@ async function fromAsync(items, mapfn, thisArg) {
245
259
  if (!Array.fromAsync) {
246
260
  Array.fromAsync = fromAsync;
247
261
  }
248
- if (!Object.hasOwn) {
249
- Object.defineProperty(Object, "hasOwn", {
250
- value: function (object, property) {
251
- if (object == null) {
252
- throw new TypeError("Cannot convert undefined or null to object");
253
- }
254
- return Object.prototype.hasOwnProperty.call(Object(object), property);
255
- },
256
- configurable: true,
257
- enumerable: false,
258
- writable: true,
259
- });
260
- }
@@ -20,8 +20,9 @@
20
20
  * };
21
21
  * }
22
22
  *
23
- * Falls back to the `REDIS_URL` / `REDIS_PREFIX` env vars when the config path
24
- * above is not populated, preserving the proxy's historical behavior.
23
+ * An explicitly activated extension may read `REDIS_URL` / `REDIS_PREFIX`
24
+ * when its config path is not populated. Missing connection configuration is
25
+ * a startup error rather than a silent no-op.
25
26
  *
26
27
  * @module extensions/ext-cache-redis
27
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-cache-redis/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,4BAA4B,CAAC;AAKpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAwCzE,QAAA,MAAM,QAAQ,EAAE,gBAsDf,CAAC;AAEF,eAAe,QAAQ,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-cache-redis/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,4BAA4B,CAAC;AAKpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAwCzE,QAAA,MAAM,QAAQ,EAAE,gBAqDf,CAAC;AAEF,eAAe,QAAQ,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC"}
@@ -20,8 +20,9 @@
20
20
  * };
21
21
  * }
22
22
  *
23
- * Falls back to the `REDIS_URL` / `REDIS_PREFIX` env vars when the config path
24
- * above is not populated, preserving the proxy's historical behavior.
23
+ * An explicitly activated extension may read `REDIS_URL` / `REDIS_PREFIX`
24
+ * when its config path is not populated. Missing connection configuration is
25
+ * a startup error rather than a silent no-op.
25
26
  *
26
27
  * @module extensions/ext-cache-redis
27
28
  */
@@ -74,8 +75,7 @@ const extRedis = () => {
74
75
  const cfg = readRedisConfig(ctx.config);
75
76
  const url = cfg.url ?? readEnv("REDIS_URL");
76
77
  if (!url) {
77
- ctx.logger.debug("[ext-cache-redis] REDIS_URL not configured; skipping TokenCacheStore registration");
78
- return;
78
+ throw new TypeError("ext-cache-redis requires proxy.cache.redis.url or REDIS_URL");
79
79
  }
80
80
  const options = {
81
81
  url,
@@ -1 +1 @@
1
- {"version":3,"file":"redis-cache.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-cache-redis/src/redis-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAgBpG,sDAAsD;AACtD,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAkBD,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAE/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KACtB,eAAe,CAAC;AAErB,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAS;gBAGxB,OAAO,EAAE,2BAA2B,EACpC,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAC1B,aAAa,CAAC,EAAE,kBAAkB,CAAC;KAC/B;IAYR,OAAO,CAAC,GAAG;IAIL,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA8BjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAalC,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IAgBjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAiBd,kBAAkB;YAQlB,eAAe;CAsC9B"}
1
+ {"version":3,"file":"redis-cache.d.ts","sourceRoot":"","sources":["../../../../src/extensions/ext-cache-redis/src/redis-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAgDpG,sDAAsD;AACtD,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAkBD,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAE/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KACtB,eAAe,CAAC;AAErB,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAS;gBAGxB,OAAO,EAAE,2BAA2B,EACpC,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,gBAAgB,CAAC;QAC1B,aAAa,CAAC,EAAE,kBAAkB,CAAC;KAC/B;IAYR,OAAO,CAAC,GAAG;IAIL,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA8BjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAevD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAalC,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IAgBjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAiBd,kBAAkB;YAQlB,eAAe;CAsC9B"}
@@ -11,6 +11,7 @@ import { createClient } from "redis";
11
11
  const DEFAULT_PREFIX = "vf:token:";
12
12
  const DEFAULT_CONNECT_TIMEOUT_MS = 5_000;
13
13
  const DEFAULT_SCAN_COUNT = 100;
14
+ const MAX_PREFIX_CODE_UNITS = 256;
14
15
  const MAX_RECONNECT_RETRIES = 3;
15
16
  const RECONNECT_BACKOFF_BASE_MS = 100;
16
17
  const RECONNECT_BACKOFF_MAX_MS = 3_000;
@@ -21,6 +22,27 @@ const EXPECTED_DISCONNECT_PATTERNS = [
21
22
  "econnreset",
22
23
  "etimedout",
23
24
  ];
25
+ function validatePrefix(prefix) {
26
+ if (typeof prefix !== "string" ||
27
+ prefix.length === 0 ||
28
+ prefix.length > MAX_PREFIX_CODE_UNITS) {
29
+ throw new TypeError("Redis token-cache prefix must contain 1 to 256 visible ASCII characters without glob metacharacters");
30
+ }
31
+ for (let index = 0; index < prefix.length; index += 1) {
32
+ const code = prefix.charCodeAt(index);
33
+ if (code < 0x21 ||
34
+ code > 0x7e ||
35
+ code === 0x2a || // *
36
+ code === 0x3f || // ?
37
+ code === 0x5b || // [
38
+ code === 0x5c || // \
39
+ code === 0x5d // ]
40
+ ) {
41
+ throw new TypeError("Redis token-cache prefix must contain 1 to 256 visible ASCII characters without glob metacharacters");
42
+ }
43
+ }
44
+ return prefix;
45
+ }
24
46
  const NOOP_LOGGER = {
25
47
  debug: () => { },
26
48
  info: () => { },
@@ -49,7 +71,7 @@ export class RedisTokenCacheStore {
49
71
  connected = false;
50
72
  constructor(options, deps = {}) {
51
73
  this.url = options.url;
52
- this.prefix = options.prefix ?? DEFAULT_PREFIX;
74
+ this.prefix = validatePrefix(options.prefix ?? DEFAULT_PREFIX);
53
75
  this.connectTimeout = options.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT_MS;
54
76
  this.tls = options.tls ?? options.url.startsWith("rediss://");
55
77
  this.password = options.password;
@@ -171,7 +193,7 @@ export class RedisTokenCacheStore {
171
193
  error: error instanceof Error ? error.message : String(error),
172
194
  });
173
195
  }
174
- return { hits: this.hits, misses: this.misses, size, type: "redis" };
196
+ return { hits: this.hits, misses: this.misses, size, type: "extension" };
175
197
  }
176
198
  async close() {
177
199
  const client = this.client;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veryfront/ext-cache-redis",
3
- "version": "0.1.1186",
3
+ "version": "0.1.1188",
4
4
  "description": "Veryfront first-party extension package for ext-cache-redis",
5
5
  "keywords": [
6
6
  "veryfront",
@@ -27,13 +27,14 @@
27
27
  },
28
28
  "scripts": {},
29
29
  "engines": {
30
- "node": ">=18.0.0"
30
+ "node": ">=22.3.0"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
35
  "veryfront": {
36
36
  "extension": true,
37
+ "activation": "explicit",
37
38
  "contracts": {
38
39
  "provides": [
39
40
  "TokenCacheStore"
@@ -63,7 +64,7 @@
63
64
  "redis": "5.11.0"
64
65
  },
65
66
  "peerDependencies": {
66
- "veryfront": "^0.1.1186"
67
+ "veryfront": "^0.1.1188"
67
68
  },
68
69
  "type": "module",
69
70
  "types": "./esm/extensions/ext-cache-redis/src/index.d.ts",