@nestjs-pipeline/cache 0.2.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.
Files changed (44) hide show
  1. package/COMMERCIAL_LICENSE.txt +34 -0
  2. package/LICENSE +661 -0
  3. package/README.md +572 -0
  4. package/dist/adapters/cache-manager.adapter.d.ts +21 -0
  5. package/dist/adapters/cache-manager.adapter.d.ts.map +1 -0
  6. package/dist/adapters/cache-manager.adapter.js +56 -0
  7. package/dist/adapters/cache-manager.adapter.js.map +1 -0
  8. package/dist/cache.behavior.d.ts +84 -0
  9. package/dist/cache.behavior.d.ts.map +1 -0
  10. package/dist/cache.behavior.js +239 -0
  11. package/dist/cache.behavior.js.map +1 -0
  12. package/dist/cache.module.d.ts +85 -0
  13. package/dist/cache.module.d.ts.map +1 -0
  14. package/dist/cache.module.js +189 -0
  15. package/dist/cache.module.js.map +1 -0
  16. package/dist/constants/tokens.d.ts +13 -0
  17. package/dist/constants/tokens.d.ts.map +1 -0
  18. package/dist/constants/tokens.js +17 -0
  19. package/dist/constants/tokens.js.map +1 -0
  20. package/dist/errors/missing-partition.error.d.ts +18 -0
  21. package/dist/errors/missing-partition.error.d.ts.map +1 -0
  22. package/dist/errors/missing-partition.error.js +23 -0
  23. package/dist/errors/missing-partition.error.js.map +1 -0
  24. package/dist/helpers/cache-factory.d.ts +39 -0
  25. package/dist/helpers/cache-factory.d.ts.map +1 -0
  26. package/dist/helpers/cache-factory.js +152 -0
  27. package/dist/helpers/cache-factory.js.map +1 -0
  28. package/dist/helpers/cache-key.d.ts +79 -0
  29. package/dist/helpers/cache-key.d.ts.map +1 -0
  30. package/dist/helpers/cache-key.js +92 -0
  31. package/dist/helpers/cache-key.js.map +1 -0
  32. package/dist/helpers/cache.intent.d.ts +26 -0
  33. package/dist/helpers/cache.intent.d.ts.map +1 -0
  34. package/dist/helpers/cache.intent.js +24 -0
  35. package/dist/helpers/cache.intent.js.map +1 -0
  36. package/dist/index.d.ts +10 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +27 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/interfaces/cache-options.interface.d.ts +120 -0
  41. package/dist/interfaces/cache-options.interface.d.ts.map +1 -0
  42. package/dist/interfaces/cache-options.interface.js +4 -0
  43. package/dist/interfaces/cache-options.interface.js.map +1 -0
  44. package/package.json +86 -0
@@ -0,0 +1,120 @@
1
+ import type { InjectionToken, ModuleMetadata, OptionalFactoryDependency } from '@nestjs/common';
2
+ import type { IPipelineContext } from '@nestjs-pipeline/core';
3
+ import type { Cache } from 'cache-manager';
4
+ import type { Keyv } from 'keyv';
5
+ /**
6
+ * Built-in store backends supported through declarative configuration.
7
+ *
8
+ * - `memory` — in-process `Keyv` map (default, no extra dependency).
9
+ * - `redis` — requires the optional `@keyv/redis` package.
10
+ * - `memcache` — requires the optional `@keyv/memcache` package.
11
+ * - `sqlite` — requires the optional `@keyv/sqlite` package.
12
+ * - `postgres` — requires the optional `@keyv/postgres` package.
13
+ */
14
+ export type CacheStoreType = 'memory' | 'redis' | 'memcache' | 'sqlite' | 'postgres';
15
+ /**
16
+ * Declarative description of a single cache store backend. Use this when you
17
+ * want the module to construct the `Keyv` adapter for you.
18
+ */
19
+ export interface CacheStoreConfig {
20
+ /** Which backend to build. */
21
+ type: CacheStoreType;
22
+ /**
23
+ * Connection string / URI for the backend, e.g. `redis://localhost:6379`,
24
+ * `postgresql://user:pass@localhost:5432/db`, `sqlite://./cache.sqlite`, or
25
+ * `localhost:11211` for memcache. Ignored for `memory`.
26
+ */
27
+ url?: string;
28
+ /** Key namespace/prefix applied to every entry in this store. */
29
+ namespace?: string;
30
+ /** Default time-to-live (milliseconds) for entries written to this store. */
31
+ ttl?: number;
32
+ /** Adapter-specific options passed through to the underlying `@keyv/*` package. */
33
+ options?: Record<string, unknown>;
34
+ }
35
+ /** Factory that derives the cache key for a given pipeline request. */
36
+ export type CacheKeyFactory = (context: IPipelineContext) => string;
37
+ /** Predicate deciding whether a given request should participate in caching. */
38
+ export type CacheCondition = (context: IPipelineContext) => boolean;
39
+ /**
40
+ * Per-handler caching options, supplied through `@UsePipeline([CacheBehavior, options])`
41
+ * and/or as module-wide defaults via {@link CacheModuleOptions.defaults}.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * @UsePipeline([CacheBehavior, {
46
+ * key: createPartitionedCacheKeyFactory({
47
+ * principal: (ctx) => ctx.items.get('userId') as string | undefined,
48
+ * scope: (ctx) => ctx.items.get('capabilityVersion') as string | undefined,
49
+ * }),
50
+ * ttl: 60_000,
51
+ * }])
52
+ * export class GetUserHandler {}
53
+ * ```
54
+ */
55
+ export interface CacheBehaviorOptions {
56
+ /**
57
+ * Request kinds eligible for caching. Defaults to `['query']` so that
58
+ * commands and events bypass the cache automatically.
59
+ */
60
+ kinds?: Array<IPipelineContext['requestKind']>;
61
+ /** Time-to-live (milliseconds) for entries written by this handler. */
62
+ ttl?: number;
63
+ /**
64
+ * Cache-key factory. **Required** when this behavior runs — there is no default.
65
+ *
66
+ * A cache hit returns without executing the handler, so the key must partition
67
+ * every dimension that can change the authorized response: tenant, principal,
68
+ * permission scope and request payload. Use `createPartitionedCacheKeyFactory`
69
+ * rather than composing one by hand.
70
+ */
71
+ key?: CacheKeyFactory;
72
+ /** Optional predicate gating whether a given request is cached. */
73
+ condition?: CacheCondition;
74
+ /**
75
+ * When a cache read or write throws, bypass the cache and continue (`true`,
76
+ * default) or propagate the store error (`false`). A failed read bypasses the
77
+ * write for that execution. This option does not catch key, condition, or
78
+ * downstream handler errors.
79
+ */
80
+ failOpen?: boolean;
81
+ }
82
+ /**
83
+ * Options accepted by {@link CacheModule.forRoot}. The store can be provided in
84
+ * three ways: a pre-built `cache`, pre-built `stores`, or declarative `store`
85
+ * configuration. When several are given, `cache` takes precedence over
86
+ * `stores`, which takes precedence over `store`; the others are ignored. An
87
+ * empty `stores` array counts as absent. When none is supplied an in-memory
88
+ * store is used.
89
+ *
90
+ * @example Redis-backed cache
91
+ * ```ts
92
+ * CacheModule.forRoot({
93
+ * store: { type: 'redis', url: process.env.REDIS_URL! },
94
+ * ttl: 30_000,
95
+ * defaults: { failOpen: true },
96
+ * });
97
+ * ```
98
+ */
99
+ export interface CacheModuleOptions {
100
+ /** Escape hatch: a fully constructed `cache-manager` instance. */
101
+ cache?: Cache;
102
+ /** Escape hatch: pre-built `Keyv` stores (tiered, highest priority first). */
103
+ stores?: Keyv[];
104
+ /** Declarative store configuration — a single store or a tiered list. */
105
+ store?: CacheStoreConfig | CacheStoreConfig[];
106
+ /** Default time-to-live (milliseconds) applied across stores and handlers. */
107
+ ttl?: number;
108
+ /** Forwarded to `cache-manager`; optimizes behavior across multiple stores. */
109
+ nonBlocking?: boolean;
110
+ /** Default per-handler behavior options merged into every pipeline. */
111
+ defaults?: CacheBehaviorOptions;
112
+ }
113
+ /** Options for {@link CacheModule.forRootAsync}. */
114
+ export interface CacheModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
115
+ /** Resolves the module options when the application starts. */
116
+ useFactory: (...args: never[]) => CacheModuleOptions | Promise<CacheModuleOptions>;
117
+ /** Providers injected into {@link useFactory}. */
118
+ inject?: Array<InjectionToken | OptionalFactoryDependency>;
119
+ }
120
+ //# sourceMappingURL=cache-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/cache-options.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GACtB,QAAQ,GACR,OAAO,GACP,UAAU,GACV,QAAQ,GACR,UAAU,CAAC;AAEf;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,uEAAuE;AACvE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC;AAEpE,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC;AAEpE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC;IAC/C,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,mEAAmE;IACnE,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,8EAA8E;IAC9E,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAAC;IAC9C,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,oDAAoD;AACpD,MAAM,WAAW,uBACf,SAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;IACvC,+DAA+D;IAC/D,UAAU,EAAE,CACV,GAAG,IAAI,EAAE,KAAK,EAAE,KACb,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtD,kDAAkD;IAClD,MAAM,CAAC,EAAE,KAAK,CAAC,cAAc,GAAG,yBAAyB,CAAC,CAAC;CAC5D"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=cache-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/cache-options.interface.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@nestjs-pipeline/cache",
3
+ "version": "0.2.0",
4
+ "description": "Caching behavior for the NestJS pipeline — cache-manager v7 on top of Keyv with pluggable stores (memory, redis, memcache, sqlite, postgres).",
5
+ "author": "Aristotelis <aristotelis@ik.me>",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "engines": {
8
+ "node": ">=22.0.0"
9
+ },
10
+ "keywords": [
11
+ "nestjs",
12
+ "pipeline",
13
+ "cqrs",
14
+ "cache",
15
+ "caching",
16
+ "cache-manager",
17
+ "keyv",
18
+ "redis",
19
+ "behavior"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/aristoteliss/nestjs-pipeline.git",
24
+ "directory": "packages/pipeline-cache"
25
+ },
26
+ "homepage": "https://github.com/aristoteliss/nestjs-pipeline#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/aristoteliss/nestjs-pipeline/issues"
29
+ },
30
+ "main": "dist/index.js",
31
+ "types": "dist/index.d.ts",
32
+ "files": [
33
+ "dist",
34
+ "LICENSE",
35
+ "COMMERCIAL_LICENSE.txt"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "peerDependencies": {
41
+ "@keyv/memcache": "^2.0.0",
42
+ "@keyv/postgres": "^2.0.0",
43
+ "@keyv/redis": "^4.0.0 || ^5.0.0",
44
+ "@keyv/sqlite": "^4.0.0",
45
+ "@nestjs/common": "^11.0.0",
46
+ "cache-manager": "^7.0.0",
47
+ "keyv": "^5.0.0",
48
+ "reflect-metadata": "^0.1.13 || ^0.2.0",
49
+ "@nestjs-pipeline/core": "^0.2.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@keyv/memcache": {
53
+ "optional": true
54
+ },
55
+ "@keyv/postgres": {
56
+ "optional": true
57
+ },
58
+ "@keyv/redis": {
59
+ "optional": true
60
+ },
61
+ "@keyv/sqlite": {
62
+ "optional": true
63
+ }
64
+ },
65
+ "devDependencies": {
66
+ "@nestjs/common": "^11.2.6",
67
+ "@vitest/coverage-v8": "^4.1.11",
68
+ "cache-manager": "^7.2.9",
69
+ "keyv": "^5.6.0",
70
+ "reflect-metadata": "^0.2.2",
71
+ "vitest": "^4.1.11",
72
+ "@nestjs-pipeline/core": "0.2.0"
73
+ },
74
+ "dependencies": {
75
+ "@cqrs-ddd/safe-stringify": "^0.2.0"
76
+ },
77
+ "scripts": {
78
+ "build": "tsc -p tsconfig.build.json",
79
+ "build:watch": "tsc -p tsconfig.build.json --watch",
80
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
81
+ "rebuild": "pnpm run clean && pnpm run build",
82
+ "lint": "tsc --noEmit",
83
+ "test": "vitest run",
84
+ "test:watch": "vitest"
85
+ }
86
+ }