@guuey/state 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 +285 -0
- package/dist/context.d.ts +37 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +114 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +144 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.d.ts +30 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +161 -0
- package/dist/http.js.map +1 -0
- package/dist/in-memory.d.ts +28 -0
- package/dist/in-memory.d.ts.map +1 -0
- package/dist/in-memory.js +239 -0
- package/dist/in-memory.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/testing/contract-suite.d.ts +11 -0
- package/dist/testing/contract-suite.d.ts.map +1 -0
- package/dist/testing/contract-suite.js +315 -0
- package/dist/testing/contract-suite.js.map +1 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +19 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +60 -0
- package/dist/validate.js.map +1 -0
- package/package.json +73 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@guuey/state` — open-source KV client for MCP servers
|
|
3
|
+
* hosted on guuey.com.
|
|
4
|
+
*
|
|
5
|
+
* Scope: every operation runs inside one `(userId, mcpId)` namespace.
|
|
6
|
+
* The MCP server holds no data of its own; data ownership stays
|
|
7
|
+
* with the user (export + delete in the guuey console).
|
|
8
|
+
*
|
|
9
|
+
* Two import shapes:
|
|
10
|
+
*
|
|
11
|
+
* **Explicit** (test-friendly, no AsyncLocalStorage):
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { createGuueyState } from '@guuey/state';
|
|
14
|
+
*
|
|
15
|
+
* const kv = createGuueyState({
|
|
16
|
+
* context: { userId: 'u_abc', mcpId: 'mcp_xyz' },
|
|
17
|
+
* });
|
|
18
|
+
* await kv.set('hello', 'world', { ttl: 60 });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* **Implicit via middleware** (production MCP servers):
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { withGuueyContext } from '@guuey/state/context';
|
|
24
|
+
* import { kv } from '@guuey/state';
|
|
25
|
+
*
|
|
26
|
+
* // Inside your tool handler, the surrounding middleware has set
|
|
27
|
+
* // the AsyncLocalStorage context from the request headers.
|
|
28
|
+
* await kv.set('hello', 'world', { ttl: 60 });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* The hard caps + design rationale live in
|
|
32
|
+
* `docs/principles/mcp-hosting-policy.md`.
|
|
33
|
+
*/
|
|
34
|
+
import type { CreateGuueyStateOptions, Kv } from "./types.js";
|
|
35
|
+
export type { CreateGuueyStateOptions, IncrementOptions, KeysPage, Kv, ScopeContext, ScopeInfo, SetOptions, } from "./types.js";
|
|
36
|
+
export { GuueyStateError, InvalidArgumentError, InvalidContextError, InvalidKeyError, InvalidTtlError, MissingContextError, QuotaExceededError, TransportError, TypeMismatchError, ValueTooLargeError, } from "./errors.js";
|
|
37
|
+
export { withGuueyContext, getCurrentContext, mcpIdFromResourceUrl, scopeFromAuthorization, validateContext, } from "./context.js";
|
|
38
|
+
export { HttpKv } from "./http.js";
|
|
39
|
+
/**
|
|
40
|
+
* Create a KV instance bound to the given scope context.
|
|
41
|
+
*
|
|
42
|
+
* Binding selection:
|
|
43
|
+
*
|
|
44
|
+
* 1. `options.bindingUrl` or `GUUEY_KV_URL` env → the hosted HTTP
|
|
45
|
+
* binding (`HttpKv`). Requires a token — `options.authToken`,
|
|
46
|
+
* `GUUEY_KV_TOKEN` env, or `context.token` (from
|
|
47
|
+
* `scopeFromAuthorization`), checked in that order — or this
|
|
48
|
+
* throws `InvalidContextError` rather than silently handing back
|
|
49
|
+
* a non-durable in-memory store to a caller who explicitly asked
|
|
50
|
+
* for the hosted one (data would vanish on pod restart with zero
|
|
51
|
+
* signal).
|
|
52
|
+
* 2. Otherwise → in-memory binding with a one-time warning.
|
|
53
|
+
* Suitable for tests and `guuey dev` runs.
|
|
54
|
+
*/
|
|
55
|
+
export declare function createGuueyState(opts: CreateGuueyStateOptions): Kv;
|
|
56
|
+
/**
|
|
57
|
+
* Convenience: the barrel-exported `kv` reads the current scope
|
|
58
|
+
* context from AsyncLocalStorage on every call. Use this when
|
|
59
|
+
* your MCP server framework has installed `withGuueyContext` as
|
|
60
|
+
* middleware.
|
|
61
|
+
*
|
|
62
|
+
* Throws `MissingContextError` if called outside a context.
|
|
63
|
+
*/
|
|
64
|
+
export declare const kv: Kv;
|
|
65
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAMH,OAAO,KAAK,EACV,uBAAuB,EACvB,EAAE,EAEH,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,EACR,EAAE,EACF,YAAY,EACZ,SAAS,EACT,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,EAAE,CAclE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,EAAE,EAAE,EAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@guuey/state` — open-source KV client for MCP servers
|
|
3
|
+
* hosted on guuey.com.
|
|
4
|
+
*
|
|
5
|
+
* Scope: every operation runs inside one `(userId, mcpId)` namespace.
|
|
6
|
+
* The MCP server holds no data of its own; data ownership stays
|
|
7
|
+
* with the user (export + delete in the guuey console).
|
|
8
|
+
*
|
|
9
|
+
* Two import shapes:
|
|
10
|
+
*
|
|
11
|
+
* **Explicit** (test-friendly, no AsyncLocalStorage):
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { createGuueyState } from '@guuey/state';
|
|
14
|
+
*
|
|
15
|
+
* const kv = createGuueyState({
|
|
16
|
+
* context: { userId: 'u_abc', mcpId: 'mcp_xyz' },
|
|
17
|
+
* });
|
|
18
|
+
* await kv.set('hello', 'world', { ttl: 60 });
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* **Implicit via middleware** (production MCP servers):
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { withGuueyContext } from '@guuey/state/context';
|
|
24
|
+
* import { kv } from '@guuey/state';
|
|
25
|
+
*
|
|
26
|
+
* // Inside your tool handler, the surrounding middleware has set
|
|
27
|
+
* // the AsyncLocalStorage context from the request headers.
|
|
28
|
+
* await kv.set('hello', 'world', { ttl: 60 });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* The hard caps + design rationale live in
|
|
32
|
+
* `docs/principles/mcp-hosting-policy.md`.
|
|
33
|
+
*/
|
|
34
|
+
import { getCurrentContext, validateContext } from "./context.js";
|
|
35
|
+
import { InvalidContextError, MissingContextError } from "./errors.js";
|
|
36
|
+
import { HttpKv } from "./http.js";
|
|
37
|
+
import { InMemoryKv } from "./in-memory.js";
|
|
38
|
+
export { GuueyStateError, InvalidArgumentError, InvalidContextError, InvalidKeyError, InvalidTtlError, MissingContextError, QuotaExceededError, TransportError, TypeMismatchError, ValueTooLargeError, } from "./errors.js";
|
|
39
|
+
export { withGuueyContext, getCurrentContext, mcpIdFromResourceUrl, scopeFromAuthorization, validateContext, } from "./context.js";
|
|
40
|
+
export { HttpKv } from "./http.js";
|
|
41
|
+
/**
|
|
42
|
+
* Create a KV instance bound to the given scope context.
|
|
43
|
+
*
|
|
44
|
+
* Binding selection:
|
|
45
|
+
*
|
|
46
|
+
* 1. `options.bindingUrl` or `GUUEY_KV_URL` env → the hosted HTTP
|
|
47
|
+
* binding (`HttpKv`). Requires a token — `options.authToken`,
|
|
48
|
+
* `GUUEY_KV_TOKEN` env, or `context.token` (from
|
|
49
|
+
* `scopeFromAuthorization`), checked in that order — or this
|
|
50
|
+
* throws `InvalidContextError` rather than silently handing back
|
|
51
|
+
* a non-durable in-memory store to a caller who explicitly asked
|
|
52
|
+
* for the hosted one (data would vanish on pod restart with zero
|
|
53
|
+
* signal).
|
|
54
|
+
* 2. Otherwise → in-memory binding with a one-time warning.
|
|
55
|
+
* Suitable for tests and `guuey dev` runs.
|
|
56
|
+
*/
|
|
57
|
+
export function createGuueyState(opts) {
|
|
58
|
+
validateContext(opts.context);
|
|
59
|
+
const bindingUrl = opts.bindingUrl ?? process.env.GUUEY_KV_URL;
|
|
60
|
+
if (bindingUrl) {
|
|
61
|
+
const token = opts.authToken ?? process.env.GUUEY_KV_TOKEN ?? opts.context.token;
|
|
62
|
+
if (!token) {
|
|
63
|
+
throw new InvalidContextError("token", "hosted binding requires a token: pass context from scopeFromAuthorization(header), or set authToken/GUUEY_KV_TOKEN");
|
|
64
|
+
}
|
|
65
|
+
return new HttpKv(bindingUrl, opts.context, token);
|
|
66
|
+
}
|
|
67
|
+
return new InMemoryKv(opts.context);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convenience: the barrel-exported `kv` reads the current scope
|
|
71
|
+
* context from AsyncLocalStorage on every call. Use this when
|
|
72
|
+
* your MCP server framework has installed `withGuueyContext` as
|
|
73
|
+
* middleware.
|
|
74
|
+
*
|
|
75
|
+
* Throws `MissingContextError` if called outside a context.
|
|
76
|
+
*/
|
|
77
|
+
export const kv = makeAlsKv();
|
|
78
|
+
function makeAlsKv() {
|
|
79
|
+
// Each method wraps `bind()` in an async IIFE so a missing-context
|
|
80
|
+
// throw surfaces as a rejected Promise (matching the async return
|
|
81
|
+
// type) instead of a synchronous throw at the call site. The
|
|
82
|
+
// in-memory binding's underlying store is module-level shared, so
|
|
83
|
+
// a fresh binding per call still sees the same data.
|
|
84
|
+
const withBinding = async (fn) => {
|
|
85
|
+
const ctx = currentContextOrThrow();
|
|
86
|
+
return fn(createGuueyState({ context: ctx }));
|
|
87
|
+
};
|
|
88
|
+
return {
|
|
89
|
+
get: (key) => withBinding((kv) => kv.get(key)),
|
|
90
|
+
set: (key, value, opts) => withBinding((kv) => kv.set(key, value, opts)),
|
|
91
|
+
delete: (key) => withBinding((kv) => kv.delete(key)),
|
|
92
|
+
has: (key) => withBinding((kv) => kv.has(key)),
|
|
93
|
+
keys: (opts) => withBinding((kv) => kv.keys(opts)),
|
|
94
|
+
increment: (key, opts) => withBinding((kv) => kv.increment(key, opts)),
|
|
95
|
+
decrement: (key, opts) => withBinding((kv) => kv.decrement(key, opts)),
|
|
96
|
+
mget: (keys) => withBinding((kv) => kv.mget(keys)),
|
|
97
|
+
scope: () => withBinding((kv) => kv.scope()),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function currentContextOrThrow() {
|
|
101
|
+
const ctx = getCurrentContext();
|
|
102
|
+
if (!ctx)
|
|
103
|
+
throw new MissingContextError();
|
|
104
|
+
return ctx;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAiB5C,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAA6B;IAC5D,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC/D,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QACjF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,mBAAmB,CAC3B,OAAO,EACP,oHAAoH,CACrH,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,EAAE,GAAO,SAAS,EAAE,CAAC;AAElC,SAAS,SAAS;IAChB,mEAAmE;IACnE,kEAAkE;IAClE,6DAA6D;IAC7D,kEAAkE;IAClE,qDAAqD;IACrD,MAAM,WAAW,GAAG,KAAK,EAAK,EAA0B,EAAc,EAAE;QACtE,MAAM,GAAG,GAAG,qBAAqB,EAAE,CAAC;QACpC,OAAO,EAAE,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC;IACF,OAAO;QACL,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACxE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtE,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,KAAK,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB;IAC5B,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,mBAAmB,EAAE,CAAC;IAC1C,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Kv, ScopeContext } from "../types.js";
|
|
2
|
+
export interface KvHarness {
|
|
3
|
+
kv: Kv;
|
|
4
|
+
/** Advance logical time by ms (in-memory: vi timers; stub-DDB: clock var). */
|
|
5
|
+
advance?: (ms: number) => void | Promise<void>;
|
|
6
|
+
/** A second (or third) `Kv` bound to an alternate scope context — for isolation tests. */
|
|
7
|
+
makeScoped: (ctx: ScopeContext) => Promise<Kv>;
|
|
8
|
+
cleanup?: () => void | Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function runKvContractSuite(name: string, makeKv: () => Promise<KvHarness>): void;
|
|
11
|
+
//# sourceMappingURL=contract-suite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-suite.d.ts","sourceRoot":"","sources":["../../src/testing/contract-suite.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,EAAE,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,EAAE,CAAC;IACP,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,0FAA0F;IAC1F,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AA6BD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,GAC/B,IAAI,CAkWN"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binding-agnostic behavioral contract for `Kv`. Every binding
|
|
3
|
+
* (in-memory today, the hosted HTTP/DDB binding later) runs this
|
|
4
|
+
* SAME suite so "works on in-memory" and "works on the real thing"
|
|
5
|
+
* mean the same set of guarantees.
|
|
6
|
+
*
|
|
7
|
+
* Time control: the suite must not assume `vi.useFakeTimers` works
|
|
8
|
+
* against a remote store, so TTL-expiry cases take an optional
|
|
9
|
+
* `advance` hook off the harness. Bindings that can't warp time
|
|
10
|
+
* (live DDB) omit it and the suite SKIPS those cases rather than
|
|
11
|
+
* faking a pass.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, expect, it } from "vitest";
|
|
14
|
+
import { InvalidArgumentError, InvalidKeyError, InvalidTtlError, QuotaExceededError, TypeMismatchError, ValueTooLargeError, } from "../errors.js";
|
|
15
|
+
/** Scope context used by tests that assert exact `scope()` field values. */
|
|
16
|
+
const CTX = { userId: "u_test", mcpId: "mcp_test" };
|
|
17
|
+
async function withHarness(makeKv, fn) {
|
|
18
|
+
const harness = await makeKv();
|
|
19
|
+
try {
|
|
20
|
+
return await fn(harness);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
await harness.cleanup?.();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function runKvContractSuite(name, makeKv) {
|
|
27
|
+
describe(`Kv contract — ${name}`, () => {
|
|
28
|
+
describe("basic operations", () => {
|
|
29
|
+
it("set + get round-trips a JSON-serializable value", async () => {
|
|
30
|
+
await withHarness(makeKv, async (harness) => {
|
|
31
|
+
const kv = harness.kv;
|
|
32
|
+
await kv.set("hello", { value: 1 }, { ttl: 60 });
|
|
33
|
+
expect(await kv.get("hello")).toEqual({
|
|
34
|
+
value: 1,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("get returns undefined for absent keys", async () => {
|
|
39
|
+
await withHarness(makeKv, async (harness) => {
|
|
40
|
+
const kv = harness.kv;
|
|
41
|
+
expect(await kv.get("nope")).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
it("delete is a no-op for absent keys", async () => {
|
|
45
|
+
await withHarness(makeKv, async (harness) => {
|
|
46
|
+
const kv = harness.kv;
|
|
47
|
+
await expect(kv.delete("nope")).resolves.toBeUndefined();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
it("has reports existence correctly", async () => {
|
|
51
|
+
await withHarness(makeKv, async (harness) => {
|
|
52
|
+
const kv = harness.kv;
|
|
53
|
+
expect(await kv.has("a")).toBe(false);
|
|
54
|
+
await kv.set("a", 1, { ttl: 60 });
|
|
55
|
+
expect(await kv.has("a")).toBe(true);
|
|
56
|
+
await kv.delete("a");
|
|
57
|
+
expect(await kv.has("a")).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
it("keys returns the scope's keys, optionally prefix-filtered", async () => {
|
|
61
|
+
await withHarness(makeKv, async (harness) => {
|
|
62
|
+
const kv = harness.kv;
|
|
63
|
+
await kv.set("user:1", "a", { ttl: 60 });
|
|
64
|
+
await kv.set("user:2", "b", { ttl: 60 });
|
|
65
|
+
await kv.set("post:1", "c", { ttl: 60 });
|
|
66
|
+
const all = await kv.keys();
|
|
67
|
+
expect(all.keys).toEqual(expect.arrayContaining(["user:1", "user:2", "post:1"]));
|
|
68
|
+
expect(all.cursor).toBeUndefined();
|
|
69
|
+
expect((await kv.keys({ prefix: "user:" })).keys).toEqual([
|
|
70
|
+
"user:1",
|
|
71
|
+
"user:2",
|
|
72
|
+
]);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
it("keys paginates lexicographically via cursor", async () => {
|
|
76
|
+
await withHarness(makeKv, async (harness) => {
|
|
77
|
+
const kv = harness.kv;
|
|
78
|
+
for (const k of ["e", "c", "a", "d", "b"]) {
|
|
79
|
+
await kv.set(`p:${k}`, 1, { ttl: 60 });
|
|
80
|
+
}
|
|
81
|
+
const page1 = await kv.keys({ prefix: "p:", limit: 2 });
|
|
82
|
+
expect(page1.keys).toEqual(["p:a", "p:b"]);
|
|
83
|
+
expect(page1.cursor).toBe("p:b");
|
|
84
|
+
const page2 = await kv.keys({
|
|
85
|
+
prefix: "p:",
|
|
86
|
+
limit: 2,
|
|
87
|
+
...(page1.cursor !== undefined ? { cursor: page1.cursor } : {}),
|
|
88
|
+
});
|
|
89
|
+
expect(page2.keys).toEqual(["p:c", "p:d"]);
|
|
90
|
+
const page3 = await kv.keys({
|
|
91
|
+
prefix: "p:",
|
|
92
|
+
limit: 2,
|
|
93
|
+
...(page2.cursor !== undefined ? { cursor: page2.cursor } : {}),
|
|
94
|
+
});
|
|
95
|
+
expect(page3.keys).toEqual(["p:e"]);
|
|
96
|
+
expect(page3.cursor).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
it("increment + decrement are atomic on number-typed keys", async () => {
|
|
100
|
+
await withHarness(makeKv, async (harness) => {
|
|
101
|
+
const kv = harness.kv;
|
|
102
|
+
expect(await kv.increment("counter", { ttl: 60 })).toBe(1);
|
|
103
|
+
expect(await kv.increment("counter", { by: 5, ttl: 60 })).toBe(6);
|
|
104
|
+
expect(await kv.decrement("counter", { ttl: 60 })).toBe(5);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
it("scope() returns live usage", async () => {
|
|
108
|
+
await withHarness(makeKv, async (harness) => {
|
|
109
|
+
const kv = await harness.makeScoped(CTX);
|
|
110
|
+
const before = await kv.scope();
|
|
111
|
+
expect(before.usedBytes).toBe(0);
|
|
112
|
+
await kv.set("x", "hello", { ttl: 60 });
|
|
113
|
+
const after = await kv.scope();
|
|
114
|
+
expect(after.usedBytes).toBeGreaterThan(before.usedBytes);
|
|
115
|
+
expect(after.keyCount).toBe(1);
|
|
116
|
+
expect(after.userId).toBe(CTX.userId);
|
|
117
|
+
expect(after.mcpId).toBe(CTX.mcpId);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
it("scopes data per (userId, mcpId) — separate scopes don't see each other", async () => {
|
|
121
|
+
await withHarness(makeKv, async (harness) => {
|
|
122
|
+
const a = await harness.makeScoped({
|
|
123
|
+
userId: "u_a",
|
|
124
|
+
mcpId: "mcp_test",
|
|
125
|
+
});
|
|
126
|
+
const b = await harness.makeScoped({
|
|
127
|
+
userId: "u_b",
|
|
128
|
+
mcpId: "mcp_test",
|
|
129
|
+
});
|
|
130
|
+
await a.set("shared", "from-a", { ttl: 60 });
|
|
131
|
+
expect(await b.get("shared")).toBeUndefined();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it("scope keys cannot collide across (userId, mcpId) splits", async () => {
|
|
135
|
+
// With a printable delimiter, {"a b","c"} and {"a","b c"} could
|
|
136
|
+
// alias. Verify adjacent-looking ids stay isolated regardless
|
|
137
|
+
// of how the binding forms its internal scope key.
|
|
138
|
+
await withHarness(makeKv, async (harness) => {
|
|
139
|
+
const a = await harness.makeScoped({ userId: "a", mcpId: "b_c" });
|
|
140
|
+
const b = await harness.makeScoped({ userId: "a_b", mcpId: "c" });
|
|
141
|
+
await a.set("k", "from-a", { ttl: 60 });
|
|
142
|
+
expect(await b.get("k")).toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("validation", () => {
|
|
147
|
+
it("rejects an invalid key (empty)", async () => {
|
|
148
|
+
await withHarness(makeKv, async (harness) => {
|
|
149
|
+
const kv = harness.kv;
|
|
150
|
+
await expect(kv.set("", 1, { ttl: 60 })).rejects.toBeInstanceOf(InvalidKeyError);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
it("rejects an invalid key (illegal char)", async () => {
|
|
154
|
+
await withHarness(makeKv, async (harness) => {
|
|
155
|
+
const kv = harness.kv;
|
|
156
|
+
await expect(kv.set("key with space", 1, { ttl: 60 })).rejects.toBeInstanceOf(InvalidKeyError);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
it("rejects a missing TTL", async () => {
|
|
160
|
+
await withHarness(makeKv, async (harness) => {
|
|
161
|
+
// Untyped-caller simulation — see KvWithLooseSetOptions.
|
|
162
|
+
const kv = harness.kv;
|
|
163
|
+
await expect(kv.set("a", 1, {})).rejects.toBeInstanceOf(InvalidTtlError);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
it("rejects a TTL over 90 days", async () => {
|
|
167
|
+
await withHarness(makeKv, async (harness) => {
|
|
168
|
+
const kv = harness.kv;
|
|
169
|
+
const ninetyOneDays = 60 * 60 * 24 * 91;
|
|
170
|
+
await expect(kv.set("a", 1, { ttl: ninetyOneDays })).rejects.toBeInstanceOf(InvalidTtlError);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
it("rejects a value over 64 KiB", async () => {
|
|
174
|
+
await withHarness(makeKv, async (harness) => {
|
|
175
|
+
const kv = harness.kv;
|
|
176
|
+
const huge = "x".repeat(65 * 1024);
|
|
177
|
+
await expect(kv.set("a", huge, { ttl: 60 })).rejects.toBeInstanceOf(ValueTooLargeError);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe("TTL expiry", () => {
|
|
182
|
+
it("returns undefined after the TTL elapses", async () => {
|
|
183
|
+
await withHarness(makeKv, async (harness) => {
|
|
184
|
+
if (!harness.advance)
|
|
185
|
+
return;
|
|
186
|
+
const kv = harness.kv;
|
|
187
|
+
await kv.set("ephemeral", "hi", { ttl: 30 });
|
|
188
|
+
expect(await kv.get("ephemeral")).toBe("hi");
|
|
189
|
+
await harness.advance(31_000);
|
|
190
|
+
expect(await kv.get("ephemeral")).toBeUndefined();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe("error envelope", () => {
|
|
195
|
+
it("EVERY failable operation throws a GuueyStateError subclass — no bare TypeError/RangeError", async () => {
|
|
196
|
+
await withHarness(makeKv, async (harness) => {
|
|
197
|
+
const kv = harness.kv;
|
|
198
|
+
// increment on a non-number key
|
|
199
|
+
await kv.set("json-key", { a: 1 }, { ttl: 60 });
|
|
200
|
+
await expect(kv.increment("json-key", { ttl: 60 })).rejects.toBeInstanceOf(TypeMismatchError);
|
|
201
|
+
// keys() limit out of range / non-integer
|
|
202
|
+
await expect(kv.keys({ limit: 0 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
203
|
+
await expect(kv.keys({ limit: 1001 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
204
|
+
await expect(kv.keys({ limit: 2.5 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
205
|
+
// mget over the batch cap
|
|
206
|
+
const tooMany = Array.from({ length: 101 }, (_, i) => `k:${i}`);
|
|
207
|
+
await expect(kv.mget(tooMany)).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
208
|
+
// non-integer counter step
|
|
209
|
+
await expect(kv.increment("counter", { ttl: 60, by: 0.5 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
210
|
+
// non-JSON-serializable values (stringify returns undefined)
|
|
211
|
+
await expect(kv.set("u", undefined, { ttl: 60 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
212
|
+
await expect(kv.set("f", () => "nope", { ttl: 60 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
213
|
+
const circular = {};
|
|
214
|
+
circular.self = circular;
|
|
215
|
+
await expect(kv.set("c", circular, { ttl: 60 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
216
|
+
await expect(kv.set("b", 10n, { ttl: 60 })).rejects.toBeInstanceOf(InvalidArgumentError);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
describe("mget prototype safety", () => {
|
|
221
|
+
it('a key literally named "__proto__" round-trips through mget', async () => {
|
|
222
|
+
await withHarness(makeKv, async (harness) => {
|
|
223
|
+
const kv = harness.kv;
|
|
224
|
+
await kv.set("__proto__", { isAdmin: true }, { ttl: 60 });
|
|
225
|
+
await kv.set("normal", "ok", { ttl: 60 });
|
|
226
|
+
const out = await kv.mget(["__proto__", "normal"]);
|
|
227
|
+
// The entry must exist as an OWN property with the stored value…
|
|
228
|
+
expect(Object.prototype.hasOwnProperty.call(out, "__proto__")).toBe(true);
|
|
229
|
+
expect(out["__proto__"]).toEqual({ isAdmin: true });
|
|
230
|
+
expect(out["normal"]).toBe("ok");
|
|
231
|
+
// …and must NOT have replaced the result object's prototype.
|
|
232
|
+
expect(out.isAdmin).toBeUndefined();
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
describe("byte accounting", () => {
|
|
237
|
+
it("counts UTF-8 bytes of key + value, not UTF-16 code units", async () => {
|
|
238
|
+
await withHarness(makeKv, async (harness) => {
|
|
239
|
+
const kv = harness.kv;
|
|
240
|
+
// "🎉" is 2 UTF-16 units but 4 UTF-8 bytes.
|
|
241
|
+
const emoji = "🎉".repeat(1000);
|
|
242
|
+
await kv.set("emoji", emoji, { ttl: 60 });
|
|
243
|
+
const info = await kv.scope();
|
|
244
|
+
// 5 key bytes + 2 JSON quote bytes + 4000 emoji bytes.
|
|
245
|
+
expect(info.usedBytes).toBe(5 + 2 + 4000);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
it("key bytes count toward the scope quota (long keys can't dodge the cap)", async () => {
|
|
249
|
+
await withHarness(makeKv, async (harness) => {
|
|
250
|
+
const kv = harness.kv;
|
|
251
|
+
// 1023-byte keys with 1-byte values: value bytes alone would say
|
|
252
|
+
// "nearly empty"; key-inclusive accounting fills the 1 MiB cap
|
|
253
|
+
// after ~1024 keys.
|
|
254
|
+
const longKey = (i) => `k${String(i).padStart(4, "0")}`.padEnd(1023, "x");
|
|
255
|
+
let threw;
|
|
256
|
+
for (let i = 0; i < 1100; i++) {
|
|
257
|
+
try {
|
|
258
|
+
await kv.set(longKey(i), 1, { ttl: 60 });
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
threw = err;
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
expect(threw).toBeInstanceOf(QuotaExceededError);
|
|
266
|
+
const info = await kv.scope();
|
|
267
|
+
expect(info.usedBytes).toBeLessThanOrEqual(1024 * 1024);
|
|
268
|
+
expect(info.usedBytes).toBeGreaterThan(1024 * 1000);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
it("rejects a value whose UTF-8 size exceeds the cap even when .length does not", async () => {
|
|
272
|
+
await withHarness(makeKv, async (harness) => {
|
|
273
|
+
const kv = harness.kv;
|
|
274
|
+
// 17k emoji = 34k UTF-16 units (under 64 KiB as .length) but
|
|
275
|
+
// 68 KB UTF-8 (over the cap).
|
|
276
|
+
const sneaky = "🎉".repeat(17 * 1024);
|
|
277
|
+
await expect(kv.set("sneaky", sneaky, { ttl: 60 })).rejects.toBeInstanceOf(ValueTooLargeError);
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
describe("audit regressions (2026-07-20)", () => {
|
|
282
|
+
it("concurrent increments never lose updates (sync read-modify-write)", async () => {
|
|
283
|
+
await withHarness(makeKv, async (harness) => {
|
|
284
|
+
const kv = harness.kv;
|
|
285
|
+
// Pre-fix, get-then-set across await points let all of these read
|
|
286
|
+
// the same base and collapse to 1.
|
|
287
|
+
const results = await Promise.all(Array.from({ length: 25 }, () => kv.increment("counter", { ttl: 60 })));
|
|
288
|
+
expect(await kv.get("counter")).toBe(25);
|
|
289
|
+
// Every intermediate value observed exactly once.
|
|
290
|
+
expect([...results].sort((a, b) => a - b)).toEqual(Array.from({ length: 25 }, (_, i) => i + 1));
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
it("expired keys stop counting toward the scope quota", async () => {
|
|
294
|
+
await withHarness(makeKv, async (harness) => {
|
|
295
|
+
if (!harness.advance)
|
|
296
|
+
return;
|
|
297
|
+
const kv = harness.kv;
|
|
298
|
+
// ~896 KiB of payload under a 1 MiB scope cap, with a 1s TTL.
|
|
299
|
+
const big = "x".repeat(63 * 1024);
|
|
300
|
+
for (let i = 0; i < 14; i++) {
|
|
301
|
+
await kv.set(`dead:${i}`, big, { ttl: 1 });
|
|
302
|
+
}
|
|
303
|
+
await harness.advance(2_000); // everything above is now expired
|
|
304
|
+
// Pre-fix this threw QuotaExceededError: expired corpses still
|
|
305
|
+
// summed into usedBytes.
|
|
306
|
+
await kv.set("fresh", big, { ttl: 60 });
|
|
307
|
+
expect(await kv.get("fresh")).toBe(big);
|
|
308
|
+
const info = await kv.scope();
|
|
309
|
+
expect(info.usedBytes).toBeLessThan(70 * 1024);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=contract-suite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-suite.js","sourceRoot":"","sources":["../../src/testing/contract-suite.ts"],"names":[],"mappings":"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"}
|