@mantajs/adapter-cache-upstash 0.2.0-beta.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.
@@ -0,0 +1,16 @@
1
+ import { type ICachePort } from '@mantajs/core';
2
+ export interface UpstashCacheOptions {
3
+ url?: string;
4
+ token?: string;
5
+ }
6
+ export declare class UpstashCacheAdapter implements ICachePort {
7
+ private _redis;
8
+ constructor(options?: UpstashCacheOptions);
9
+ get(key: string): Promise<unknown>;
10
+ set(key: string, data: unknown, ttl?: number): Promise<void>;
11
+ invalidate(key: string): Promise<void>;
12
+ clear(): Promise<void>;
13
+ ping(): Promise<boolean>;
14
+ _reset(): void;
15
+ }
16
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAc,MAAM,eAAe,CAAA;AAG3D,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,mBAAoB,YAAW,UAAU;IACpD,OAAO,CAAC,MAAM,CAAO;gBAET,OAAO,GAAE,mBAAwB;IAcvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5D,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAW9B,MAAM;CAGP"}
@@ -0,0 +1,48 @@
1
+ // SPEC-064/077 — UpstashCacheAdapter implements ICachePort
2
+ import { MantaError } from '@mantajs/core';
3
+ import { Redis } from '@upstash/redis';
4
+ export class UpstashCacheAdapter {
5
+ _redis;
6
+ constructor(options = {}) {
7
+ const url = options.url ?? process.env.UPSTASH_REDIS_REST_URL;
8
+ const token = options.token ?? process.env.UPSTASH_REDIS_REST_TOKEN;
9
+ if (!url || !token) {
10
+ throw new MantaError('INVALID_DATA', 'UpstashCacheAdapter requires UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN (env or constructor options)');
11
+ }
12
+ this._redis = new Redis({ url, token });
13
+ }
14
+ async get(key) {
15
+ const value = await this._redis.get(key);
16
+ return value ?? null;
17
+ }
18
+ async set(key, data, ttl) {
19
+ const value = typeof data === 'string' ? data : JSON.stringify(data);
20
+ if (ttl && ttl > 0) {
21
+ await this._redis.set(key, value, { ex: ttl });
22
+ }
23
+ else {
24
+ await this._redis.set(key, value);
25
+ }
26
+ }
27
+ async invalidate(key) {
28
+ await this._redis.del(key);
29
+ }
30
+ async clear() {
31
+ await this._redis.flushdb();
32
+ }
33
+ async ping() {
34
+ // Upstash Redis exposes PING as a REST command. Any successful response
35
+ // (typically "PONG") means the backend is reachable.
36
+ try {
37
+ const result = await this._redis.ping();
38
+ return result !== null && result !== undefined;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ _reset() {
45
+ this._redis.flushdb();
46
+ }
47
+ }
48
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAE3D,OAAO,EAAmB,UAAU,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAOtC,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAO;IAErB,YAAY,UAA+B,EAAE;QAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;QAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAA;QAEnE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,+GAA+G,CAChH,CAAA;QACH,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACxC,OAAO,KAAK,IAAI,IAAI,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,IAAa,EAAE,GAAY;QAChD,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QACpE,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAChD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI;QACR,wEAAwE;QACxE,qDAAqD;QACrD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAO,IAAI,CAAC,MAAsD,CAAC,IAAI,EAAE,CAAA;YACxF,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,CAAA;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;IACvB,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export type { UpstashCacheOptions } from './adapter';
2
+ export { UpstashCacheAdapter } from './adapter';
3
+ export type { UpstashProgressChannelOptions } from './progress-channel';
4
+ export { UpstashProgressChannel } from './progress-channel';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAA;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // SPEC-064/077 — @mantajs/adapter-cache-upstash barrel export
2
+ export { UpstashCacheAdapter } from './adapter';
3
+ export { UpstashProgressChannel } from './progress-channel';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAG9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAE/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,26 @@
1
+ import type { ILoggerPort, IProgressChannelPort, ProgressSnapshot } from '@mantajs/core';
2
+ import { Redis } from '@upstash/redis';
3
+ export interface UpstashProgressChannelOptions {
4
+ url?: string;
5
+ token?: string;
6
+ }
7
+ /**
8
+ * Progress channel backed by Upstash Redis.
9
+ *
10
+ * Accepts either a pre-built `Redis` client (preferred — reuses the cache
11
+ * adapter's client) or the same credentials the cache adapter uses.
12
+ *
13
+ * @example
14
+ * const channel = new UpstashProgressChannel(redisClient, { logger })
15
+ */
16
+ export declare class UpstashProgressChannel implements IProgressChannelPort {
17
+ private _redis;
18
+ private _logger?;
19
+ constructor(clientOrOptions?: Redis | UpstashProgressChannelOptions, deps?: {
20
+ logger?: ILoggerPort;
21
+ });
22
+ set(runId: string, snapshot: ProgressSnapshot): Promise<void>;
23
+ get(runId: string): Promise<ProgressSnapshot | null>;
24
+ clear(runId: string): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=progress-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-channel.d.ts","sourceRoot":"","sources":["../src/progress-channel.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAExF,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAItC,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAMD;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,YAAW,oBAAoB;IACjE,OAAO,CAAC,MAAM,CAAO;IACrB,OAAO,CAAC,OAAO,CAAC,CAAa;gBAEjB,eAAe,GAAE,KAAK,GAAG,6BAAkC,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO;IAsBtG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7D,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAcpD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}
@@ -0,0 +1,67 @@
1
+ // UpstashProgressChannel — ephemeral workflow progress via Upstash Redis.
2
+ // Implements IProgressChannelPort — see WORKFLOW_PROGRESS.md §5.2 and §9.2.
3
+ //
4
+ // Key format: `workflow:{runId}:progress` (spec §4 architecture diagram).
5
+ // TTL: 3600 seconds (spec §5.2 "TTL 1h").
6
+ // `set()` MUST NOT throw — channel errors are logged, not propagated (§10.2 invariant #2).
7
+ import { MantaError } from '@mantajs/core';
8
+ import { Redis } from '@upstash/redis';
9
+ const TTL_SECONDS = 3600;
10
+ function progressKey(runId) {
11
+ return `workflow:${runId}:progress`;
12
+ }
13
+ /**
14
+ * Progress channel backed by Upstash Redis.
15
+ *
16
+ * Accepts either a pre-built `Redis` client (preferred — reuses the cache
17
+ * adapter's client) or the same credentials the cache adapter uses.
18
+ *
19
+ * @example
20
+ * const channel = new UpstashProgressChannel(redisClient, { logger })
21
+ */
22
+ export class UpstashProgressChannel {
23
+ _redis;
24
+ _logger;
25
+ constructor(clientOrOptions = {}, deps = {}) {
26
+ this._logger = deps.logger;
27
+ if (clientOrOptions instanceof Redis) {
28
+ this._redis = clientOrOptions;
29
+ return;
30
+ }
31
+ const options = clientOrOptions;
32
+ const url = options.url ?? process.env.UPSTASH_REDIS_REST_URL;
33
+ const token = options.token ?? process.env.UPSTASH_REDIS_REST_TOKEN;
34
+ if (!url || !token) {
35
+ throw new MantaError('INVALID_DATA', 'UpstashProgressChannel requires UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN (env or constructor options)');
36
+ }
37
+ this._redis = new Redis({ url, token });
38
+ }
39
+ async set(runId, snapshot) {
40
+ try {
41
+ await this._redis.set(progressKey(runId), JSON.stringify(snapshot), { ex: TTL_SECONDS });
42
+ }
43
+ catch (err) {
44
+ // Invariant #2: never throw. Log and swallow.
45
+ this._logger?.warn('progress write failed', { err, runId, stepName: snapshot.stepName });
46
+ }
47
+ }
48
+ async get(runId) {
49
+ const raw = await this._redis.get(progressKey(runId));
50
+ if (raw === null || raw === undefined)
51
+ return null;
52
+ if (typeof raw === 'string') {
53
+ try {
54
+ return JSON.parse(raw);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ // Upstash auto-parses JSON for some payloads — accept already-parsed objects.
61
+ return raw;
62
+ }
63
+ async clear(runId) {
64
+ await this._redis.del(progressKey(runId));
65
+ }
66
+ }
67
+ //# sourceMappingURL=progress-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-channel.js","sourceRoot":"","sources":["../src/progress-channel.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,4EAA4E;AAC5E,EAAE;AACF,0EAA0E;AAC1E,0CAA0C;AAC1C,2FAA2F;AAG3F,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAEtC,MAAM,WAAW,GAAG,IAAI,CAAA;AAOxB,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,YAAY,KAAK,WAAW,CAAA;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,sBAAsB;IACzB,MAAM,CAAO;IACb,OAAO,CAAc;IAE7B,YAAY,kBAAyD,EAAE,EAAE,OAAiC,EAAE;QAC1G,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAA;QAE1B,IAAI,eAAe,YAAY,KAAK,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,GAAG,eAAe,CAAA;YAC7B,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAG,eAAe,CAAA;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAA;QAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAA;QAEnE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,cAAc,EACd,kHAAkH,CACnH,CAAA;QACH,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;IACzC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa,EAAE,QAA0B;QACjD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAA;QAC1F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,8CAA8C;YAC9C,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC1F,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;QACrD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAA;QAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAA;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QACD,8EAA8E;QAC9E,OAAO,GAAuB,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAa;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3C,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@mantajs/adapter-cache-upstash",
3
+ "version": "0.2.0-beta.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "dependencies": {
15
+ "@upstash/redis": "^1.34.0"
16
+ },
17
+ "peerDependencies": {
18
+ "@mantajs/core": "0.2.0-beta.0"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ]
23
+ }