mppx 0.5.7 → 0.5.9
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/CHANGELOG.md +14 -0
- package/dist/Challenge.d.ts +3 -2
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +27 -9
- package/dist/Challenge.js.map +1 -1
- package/dist/Method.d.ts +32 -14
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js.map +1 -1
- package/dist/Store.d.ts +68 -2
- package/dist/Store.d.ts.map +1 -1
- package/dist/Store.js +41 -4
- package/dist/Store.js.map +1 -1
- package/dist/mcp-sdk/server/Transport.d.ts.map +1 -1
- package/dist/mcp-sdk/server/Transport.js +7 -0
- package/dist/mcp-sdk/server/Transport.js.map +1 -1
- package/dist/server/Mppx.d.ts +1 -1
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +133 -70
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Transport.d.ts +8 -2
- package/dist/server/Transport.d.ts.map +1 -1
- package/dist/server/Transport.js +26 -1
- package/dist/server/Transport.js.map +1 -1
- package/dist/tempo/client/SessionManager.d.ts +13 -2
- package/dist/tempo/client/SessionManager.d.ts.map +1 -1
- package/dist/tempo/client/SessionManager.js +429 -4
- package/dist/tempo/client/SessionManager.js.map +1 -1
- package/dist/tempo/internal/fee-payer.d.ts +28 -0
- package/dist/tempo/internal/fee-payer.d.ts.map +1 -1
- package/dist/tempo/internal/fee-payer.js +89 -0
- package/dist/tempo/internal/fee-payer.js.map +1 -1
- package/dist/tempo/server/Charge.d.ts +4 -1
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +90 -66
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Methods.d.ts +3 -0
- package/dist/tempo/server/Methods.d.ts.map +1 -1
- package/dist/tempo/server/Methods.js +3 -0
- package/dist/tempo/server/Methods.js.map +1 -1
- package/dist/tempo/server/Session.d.ts +8 -2
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js.map +1 -1
- package/dist/tempo/server/index.d.ts +1 -0
- package/dist/tempo/server/index.d.ts.map +1 -1
- package/dist/tempo/server/index.js +1 -0
- package/dist/tempo/server/index.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
- package/dist/tempo/server/internal/html.gen.js +1 -1
- package/dist/tempo/server/internal/html.gen.js.map +1 -1
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +16 -6
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/dist/tempo/session/ChannelStore.d.ts +12 -1
- package/dist/tempo/session/ChannelStore.d.ts.map +1 -1
- package/dist/tempo/session/ChannelStore.js +55 -14
- package/dist/tempo/session/ChannelStore.js.map +1 -1
- package/dist/tempo/session/Sse.d.ts +11 -2
- package/dist/tempo/session/Sse.d.ts.map +1 -1
- package/dist/tempo/session/Sse.js +66 -25
- package/dist/tempo/session/Sse.js.map +1 -1
- package/dist/tempo/session/Ws.d.ts +87 -0
- package/dist/tempo/session/Ws.d.ts.map +1 -0
- package/dist/tempo/session/Ws.js +428 -0
- package/dist/tempo/session/Ws.js.map +1 -0
- package/dist/tempo/session/index.d.ts +1 -0
- package/dist/tempo/session/index.d.ts.map +1 -1
- package/dist/tempo/session/index.js +1 -0
- package/dist/tempo/session/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Challenge.test.ts +1 -1
- package/src/Challenge.ts +28 -9
- package/src/Method.ts +61 -20
- package/src/Store.test-d.ts +80 -2
- package/src/Store.test.ts +150 -13
- package/src/Store.ts +140 -3
- package/src/mcp-sdk/server/Transport.test.ts +12 -0
- package/src/mcp-sdk/server/Transport.ts +8 -0
- package/src/server/Mppx.test.ts +105 -0
- package/src/server/Mppx.ts +178 -88
- package/src/server/Transport.test.ts +31 -0
- package/src/server/Transport.ts +31 -2
- package/src/tempo/client/SessionManager.ts +510 -7
- package/src/tempo/internal/fee-payer.test.ts +115 -1
- package/src/tempo/internal/fee-payer.ts +138 -1
- package/src/tempo/server/AtomicStore.test-d.ts +34 -0
- package/src/tempo/server/Charge.test.ts +128 -0
- package/src/tempo/server/Charge.ts +118 -93
- package/src/tempo/server/Methods.ts +3 -0
- package/src/tempo/server/Session.test.ts +1044 -47
- package/src/tempo/server/Session.ts +8 -2
- package/src/tempo/server/Sse.test.ts +29 -0
- package/src/tempo/server/index.ts +1 -0
- package/src/tempo/server/internal/html/main.ts +9 -10
- package/src/tempo/server/internal/html.gen.ts +1 -1
- package/src/tempo/server/internal/transport.ts +19 -6
- package/src/tempo/session/ChannelStore.test.ts +20 -1
- package/src/tempo/session/ChannelStore.ts +77 -14
- package/src/tempo/session/Sse.ts +77 -24
- package/src/tempo/session/Ws.test.ts +410 -0
- package/src/tempo/session/Ws.ts +563 -0
- package/src/tempo/session/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.gen.js","sourceRoot":"","sources":["../../../../src/tempo/server/internal/html.gen.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"html.gen.js","sourceRoot":"","sources":["../../../../src/tempo/server/internal/html.gen.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,IAAI,GAAG,m4tbAAm4tb,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../src/tempo/server/internal/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,SAAS,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAGhD,mDAAmD;AACnD,MAAM,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAA;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,GAAG;IAAE,KAAK,EAAE,YAAY,CAAC,YAAY,CAAA;CAAE,GAAG,GAAG,
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../src/tempo/server/internal/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,SAAS,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAGhD,mDAAmD;AACnD,MAAM,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAA;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,GAAG;IAAE,KAAK,EAAE,YAAY,CAAC,YAAY,CAAA;CAAE,GAAG,GAAG,CAmHpF;AAED,MAAM,CAAC,OAAO,WAAW,GAAG,CAAC;IAC3B,KAAK,OAAO,GAAG;QACb;;;;;;;;;WASG;QACH,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;QAC1B,sDAAsD;QACtD,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KACrC,CAAA;CACF;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE;IACpC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IAC7E,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,QAAQ,CAwBX"}
|
|
@@ -31,18 +31,27 @@ export function sse(options) {
|
|
|
31
31
|
const base = Transport.http();
|
|
32
32
|
return Transport.from({
|
|
33
33
|
name: 'sse',
|
|
34
|
+
captureRequest(request) {
|
|
35
|
+
return (base.captureRequest?.(request) ?? {
|
|
36
|
+
headers: new Headers(request.headers),
|
|
37
|
+
method: request.method,
|
|
38
|
+
url: new URL(request.url),
|
|
39
|
+
});
|
|
40
|
+
},
|
|
34
41
|
getCredential(request) {
|
|
35
42
|
return base.getCredential(request);
|
|
36
43
|
},
|
|
37
44
|
respondChallenge(options) {
|
|
38
45
|
return base.respondChallenge(options);
|
|
39
46
|
},
|
|
40
|
-
respondReceipt({ credential, receipt, response, challengeId, input }) {
|
|
41
|
-
const
|
|
47
|
+
respondReceipt({ credential, envelope, receipt, response, challengeId, input }) {
|
|
48
|
+
const verifiedCredential = envelope?.credential ?? credential;
|
|
49
|
+
const verifiedChallengeId = envelope?.challenge.id ?? challengeId;
|
|
50
|
+
const payload = verifiedCredential.payload;
|
|
42
51
|
if (!payload.channelId)
|
|
43
52
|
throw new Error('No SSE context available');
|
|
44
53
|
const channelId = payload.channelId;
|
|
45
|
-
const tickCost = BigInt(
|
|
54
|
+
const tickCost = BigInt(verifiedCredential.challenge.request.amount);
|
|
46
55
|
// Auto-detect upstream SSE responses and parse them into an
|
|
47
56
|
// AsyncIterable so they flow through the metered pipeline.
|
|
48
57
|
// This lets proxy consumers simply pass `result.withReceipt(upstreamRes)`
|
|
@@ -60,7 +69,7 @@ export function sse(options) {
|
|
|
60
69
|
const stream = Sse_core.serve({
|
|
61
70
|
store,
|
|
62
71
|
channelId,
|
|
63
|
-
challengeId,
|
|
72
|
+
challengeId: verifiedChallengeId,
|
|
64
73
|
tickCost,
|
|
65
74
|
pollIntervalMs: pollingInterval,
|
|
66
75
|
generate,
|
|
@@ -69,11 +78,12 @@ export function sse(options) {
|
|
|
69
78
|
return Sse_core.toResponse(stream);
|
|
70
79
|
}
|
|
71
80
|
const baseResponse = base.respondReceipt({
|
|
72
|
-
credential,
|
|
81
|
+
credential: verifiedCredential,
|
|
82
|
+
envelope,
|
|
73
83
|
input,
|
|
74
84
|
receipt,
|
|
75
85
|
response: response,
|
|
76
|
-
challengeId,
|
|
86
|
+
challengeId: verifiedChallengeId,
|
|
77
87
|
});
|
|
78
88
|
// Non-SSE response (e.g. upstream returned JSON instead of event-stream).
|
|
79
89
|
// Need to deduct tickCost so request isn't free.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/tempo/server/internal/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,SAAS,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,YAAY,MAAM,+BAA+B,CAAA;AAC7D,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAA;AAMhD;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,CAAC,OAA2D;IAC7E,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;IAEzC,oEAAoE;IACpE,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC,KAAK,CAAA;QAC/B,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACpD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,EAAE,CAAA;IAEJ,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAA;IAC7B,OAAO,SAAS,CAAC,IAAI,CAAgE;QACnF,IAAI,EAAE,KAAK;QAEX,aAAa,CAAC,OAAO;YACnB,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACpC,CAAC;QAED,gBAAgB,CAAC,OAAO;YACtB,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAa,CAAA;QACnD,CAAC;QAED,cAAc,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/tempo/server/internal/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,6 +62,9 @@ export interface State {
|
|
|
62
62
|
* guarantee that no concurrent mutation occurs between reading `current`
|
|
63
63
|
* and writing the return value.
|
|
64
64
|
*
|
|
65
|
+
* Callbacks should be synchronous and deterministic. When a `ChannelStore`
|
|
66
|
+
* is backed by `Store.update()`, adapters may retry them internally.
|
|
67
|
+
*
|
|
65
68
|
* Backends implement this via their native mechanisms:
|
|
66
69
|
* - **In-memory / JS single-thread**: Synchronous callback execution
|
|
67
70
|
* - **Durable Objects**: Single-threaded execution model
|
|
@@ -85,6 +88,14 @@ export type ChannelStore = {
|
|
|
85
88
|
* When not implemented, callers fall back to polling.
|
|
86
89
|
*/
|
|
87
90
|
waitForUpdate?(channelId: Hex): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Atomic read-modify-write that returns the callback's `result` directly.
|
|
93
|
+
*
|
|
94
|
+
* Used by {@link deductFromChannel} to atomically compute the deduction
|
|
95
|
+
* outcome. When backed by `Store.update()`, this delegates to the store's
|
|
96
|
+
* native atomic primitive.
|
|
97
|
+
*/
|
|
98
|
+
updateChannelResult?<result>(channelId: Hex, fn: (current: State | null) => Store.Change<State, result>): Promise<result>;
|
|
88
99
|
};
|
|
89
100
|
export type DeductResult = {
|
|
90
101
|
ok: true;
|
|
@@ -101,5 +112,5 @@ export type DeductResult = {
|
|
|
101
112
|
* insufficient. Throws if the channel does not exist.
|
|
102
113
|
*/
|
|
103
114
|
export declare function deductFromChannel(store: ChannelStore, channelId: Hex, amount: bigint): Promise<DeductResult>;
|
|
104
|
-
export declare function fromStore(store: Store.Store): ChannelStore;
|
|
115
|
+
export declare function fromStore(store: Store.Store | Store.AtomicStore): ChannelStore;
|
|
105
116
|
//# sourceMappingURL=ChannelStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelStore.d.ts","sourceRoot":"","sources":["../../../src/tempo/session/ChannelStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAExC,OAAO,KAAK,KAAK,KAAK,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,KAAK;IACpB,kEAAkE;IAClE,gBAAgB,EAAE,OAAO,CAAA;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAA;IACvB,kDAAkD;IAClD,SAAS,EAAE,GAAG,CAAA;IACd,iFAAiF;IACjF,gBAAgB,EAAE,MAAM,CAAA;IACxB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,SAAS,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,cAAc,EAAE,aAAa,GAAG,IAAI,CAAA;IACpC,gEAAgE;IAChE,oBAAoB,EAAE,MAAM,CAAA;IAC5B,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAA;IACd,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAA;IACd,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAA;IACtB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,gDAAgD;IAChD,KAAK,EAAE,OAAO,CAAA;IACd,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAA;CACd;AAED
|
|
1
|
+
{"version":3,"file":"ChannelStore.d.ts","sourceRoot":"","sources":["../../../src/tempo/session/ChannelStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAExC,OAAO,KAAK,KAAK,KAAK,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,KAAK;IACpB,kEAAkE;IAClE,gBAAgB,EAAE,OAAO,CAAA;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAA;IACvB,kDAAkD;IAClD,SAAS,EAAE,GAAG,CAAA;IACd,iFAAiF;IACjF,gBAAgB,EAAE,MAAM,CAAA;IACxB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,SAAS,EAAE,OAAO,CAAA;IAClB,kEAAkE;IAClE,cAAc,EAAE,aAAa,GAAG,IAAI,CAAA;IACpC,gEAAgE;IAChE,oBAAoB,EAAE,MAAM,CAAA;IAC5B,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAA;IACd,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAA;IACd,iDAAiD;IACjD,cAAc,EAAE,MAAM,CAAA;IACtB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,gDAAgD;IAChD,KAAK,EAAE,OAAO,CAAA;IACd,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IAEjD;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IAEjG;;;;;;;;;OASG;IACH,aAAa,CAAC,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7C;;;;;;OAMG;IACH,mBAAmB,CAAC,CAAC,MAAM,EACzB,SAAS,EAAE,GAAG,EACd,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GACzD,OAAO,CAAC,MAAM,CAAC,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAA;AAEvF;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,GAAG,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,CAAC,CAoCvB;AAqBD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,WAAW,GAAG,YAAY,CAyF9E"}
|
|
@@ -6,22 +6,41 @@
|
|
|
6
6
|
* insufficient. Throws if the channel does not exist.
|
|
7
7
|
*/
|
|
8
8
|
export async function deductFromChannel(store, channelId, amount) {
|
|
9
|
-
|
|
9
|
+
if (store.updateChannelResult) {
|
|
10
|
+
const result = await store.updateChannelResult(channelId, (current) => {
|
|
11
|
+
if (!current)
|
|
12
|
+
return { op: 'noop', result: null };
|
|
13
|
+
if (current.finalized)
|
|
14
|
+
return { op: 'noop', result: { ok: false, channel: current } };
|
|
15
|
+
if (current.highestVoucherAmount - current.spent >= amount) {
|
|
16
|
+
const next = { ...current, spent: current.spent + amount, units: current.units + 1 };
|
|
17
|
+
return { op: 'set', value: next, result: { ok: true, channel: next } };
|
|
18
|
+
}
|
|
19
|
+
return { op: 'noop', result: { ok: false, channel: current } };
|
|
20
|
+
});
|
|
21
|
+
if (!result)
|
|
22
|
+
throw new Error('channel not found');
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
let result = null;
|
|
10
26
|
const channel = await store.updateChannel(channelId, (current) => {
|
|
11
|
-
deducted = false;
|
|
12
27
|
if (!current)
|
|
13
28
|
return null;
|
|
14
|
-
if (current.finalized)
|
|
29
|
+
if (current.finalized) {
|
|
30
|
+
result = { ok: false, channel: current };
|
|
15
31
|
return current;
|
|
32
|
+
}
|
|
16
33
|
if (current.highestVoucherAmount - current.spent >= amount) {
|
|
17
|
-
|
|
18
|
-
|
|
34
|
+
const next = { ...current, spent: current.spent + amount, units: current.units + 1 };
|
|
35
|
+
result = { ok: true, channel: next };
|
|
36
|
+
return next;
|
|
19
37
|
}
|
|
38
|
+
result = { ok: false, channel: current };
|
|
20
39
|
return current;
|
|
21
40
|
});
|
|
22
41
|
if (!channel)
|
|
23
42
|
throw new Error('channel not found');
|
|
24
|
-
return { ok:
|
|
43
|
+
return result ?? { ok: false, channel };
|
|
25
44
|
}
|
|
26
45
|
/**
|
|
27
46
|
* Wraps a generic {@link Store} into the internal {@link Store}
|
|
@@ -45,6 +64,7 @@ export function fromStore(store) {
|
|
|
45
64
|
const cached = storeCache.get(store);
|
|
46
65
|
if (cached)
|
|
47
66
|
return cached;
|
|
67
|
+
const atomicUpdate = 'update' in store ? store.update : undefined;
|
|
48
68
|
const waiters = new Map();
|
|
49
69
|
const locks = new Map();
|
|
50
70
|
function notify(channelId) {
|
|
@@ -56,6 +76,26 @@ export function fromStore(store) {
|
|
|
56
76
|
waiters.delete(channelId);
|
|
57
77
|
}
|
|
58
78
|
async function update(channelId, fn) {
|
|
79
|
+
return updateResult(channelId, (current) => {
|
|
80
|
+
const next = fn(current);
|
|
81
|
+
if (next)
|
|
82
|
+
return { op: 'set', value: next, result: next };
|
|
83
|
+
return { op: 'delete', result: null };
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function updateResult(channelId, fn) {
|
|
87
|
+
let change;
|
|
88
|
+
if (atomicUpdate) {
|
|
89
|
+
const result = await atomicUpdate(channelId, (current) => {
|
|
90
|
+
change = fn(current ?? null);
|
|
91
|
+
if (change.op !== 'set')
|
|
92
|
+
return change;
|
|
93
|
+
return { ...change, value: change.value };
|
|
94
|
+
});
|
|
95
|
+
if (change?.op !== 'noop')
|
|
96
|
+
notify(channelId);
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
59
99
|
while (locks.has(channelId))
|
|
60
100
|
await locks.get(channelId);
|
|
61
101
|
let release;
|
|
@@ -64,12 +104,14 @@ export function fromStore(store) {
|
|
|
64
104
|
}));
|
|
65
105
|
try {
|
|
66
106
|
const current = (await store.get(channelId));
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
await store.put(channelId,
|
|
70
|
-
|
|
107
|
+
change = fn(current);
|
|
108
|
+
if (change.op === 'set')
|
|
109
|
+
await store.put(channelId, change.value);
|
|
110
|
+
if (change.op === 'delete')
|
|
71
111
|
await store.delete(channelId);
|
|
72
|
-
|
|
112
|
+
if (change.op !== 'noop')
|
|
113
|
+
notify(channelId);
|
|
114
|
+
return change.result;
|
|
73
115
|
}
|
|
74
116
|
finally {
|
|
75
117
|
locks.delete(channelId);
|
|
@@ -81,9 +123,7 @@ export function fromStore(store) {
|
|
|
81
123
|
return (await store.get(channelId));
|
|
82
124
|
},
|
|
83
125
|
async updateChannel(channelId, fn) {
|
|
84
|
-
|
|
85
|
-
notify(channelId);
|
|
86
|
-
return result;
|
|
126
|
+
return update(channelId, fn);
|
|
87
127
|
},
|
|
88
128
|
waitForUpdate(channelId) {
|
|
89
129
|
return new Promise((resolve) => {
|
|
@@ -96,6 +136,7 @@ export function fromStore(store) {
|
|
|
96
136
|
});
|
|
97
137
|
},
|
|
98
138
|
};
|
|
139
|
+
cs.updateChannelResult = updateResult;
|
|
99
140
|
storeCache.set(store, cs);
|
|
100
141
|
return cs;
|
|
101
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelStore.js","sourceRoot":"","sources":["../../../src/tempo/session/ChannelStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChannelStore.js","sourceRoot":"","sources":["../../../src/tempo/session/ChannelStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,13 @@ export type SseEvent = {
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function parseEvent(raw: string): SseEvent | null;
|
|
49
49
|
export type SessionController = {
|
|
50
|
+
/**
|
|
51
|
+
* Reserve voucher coverage for the next emitted chunk.
|
|
52
|
+
*
|
|
53
|
+
* The reservation blocks until sufficient voucher headroom exists, but the
|
|
54
|
+
* charge is only committed once a chunk is actually emitted. If the stream
|
|
55
|
+
* ends or aborts before that emission, the reservation is dropped.
|
|
56
|
+
*/
|
|
50
57
|
charge(): Promise<void>;
|
|
51
58
|
};
|
|
52
59
|
/**
|
|
@@ -59,11 +66,13 @@ export type SessionController = {
|
|
|
59
66
|
* generator controls when charges happen by calling `stream.charge()`.
|
|
60
67
|
*
|
|
61
68
|
* For each emitted value the stream:
|
|
62
|
-
* 1.
|
|
69
|
+
* 1. Reserves `tickCost` from the channel's available voucher headroom
|
|
70
|
+
* (auto or manual).
|
|
63
71
|
* 2. If balance is sufficient, emits `event: message` with the value.
|
|
64
72
|
* 3. If balance is exhausted, emits `event: payment-need-voucher`
|
|
65
73
|
* and polls store until the client tops up the channel.
|
|
66
|
-
* 4.
|
|
74
|
+
* 4. Commits the reserved charge immediately before the chunk is emitted.
|
|
75
|
+
* 5. On generator completion, emits a final `event: payment-receipt`.
|
|
67
76
|
*
|
|
68
77
|
* Returns a `ReadableStream<Uint8Array>` suitable for use as an HTTP response body.
|
|
69
78
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sse.d.ts","sourceRoot":"","sources":["../../../src/tempo/session/Sse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAG/B,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAA4B,cAAc,EAAE,MAAM,YAAY,CAAA;AAE5F;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEvE;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAA;AAErD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CA2BvD;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"Sse.d.ts","sourceRoot":"","sources":["../../../src/tempo/session/Sse.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAG/B,OAAO,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAA4B,cAAc,EAAE,MAAM,YAAY,CAAA;AAE5F;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEvE;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,CAAA;AAErD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CA2BvD;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;;;OAMG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,CAyExE;AAED,MAAM,CAAC,OAAO,WAAW,KAAK,CAAC;IAC7B,KAAK,OAAO,GAAG;QACb,KAAK,EAAE,YAAY,CAAC,YAAY,CAAA;QAChC,SAAS,EAAE,GAAG,CAAA;QACd,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,CAAA;QAChB,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,iBAAiB,KAAK,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;QACxF,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACnC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;KACjC,CAAA;CACF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,QAAQ,CAQrE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,OAAO,CAcjE;AAED,MAAM,CAAC,OAAO,WAAW,WAAW,CAAC;IACnC,KAAK,OAAO,GAAG;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,SAAS,EAAE,GAAG,CAAA;QACd,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;CACF;AAmGD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAGzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAuB,WAAW,CAChC,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,CAAC,OAAO,GAC5B,cAAc,CAAC,MAAM,CAAC,CAsCxB;AAED,MAAM,CAAC,OAAO,WAAW,WAAW,CAAC;IACnC,KAAK,OAAO,GAAG;QACb,6EAA6E;QAC7E,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAA;KAC/C,CAAA;CACF"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as Credential from '../../Credential.js';
|
|
2
|
-
import * as ChannelStore from './ChannelStore.js';
|
|
3
2
|
import { createSessionReceipt } from './Receipt.js';
|
|
4
3
|
/**
|
|
5
4
|
* Format a session receipt as a Server-Sent Event.
|
|
@@ -66,11 +65,13 @@ export function parseEvent(raw) {
|
|
|
66
65
|
* generator controls when charges happen by calling `stream.charge()`.
|
|
67
66
|
*
|
|
68
67
|
* For each emitted value the stream:
|
|
69
|
-
* 1.
|
|
68
|
+
* 1. Reserves `tickCost` from the channel's available voucher headroom
|
|
69
|
+
* (auto or manual).
|
|
70
70
|
* 2. If balance is sufficient, emits `event: message` with the value.
|
|
71
71
|
* 3. If balance is exhausted, emits `event: payment-need-voucher`
|
|
72
72
|
* and polls store until the client tops up the channel.
|
|
73
|
-
* 4.
|
|
73
|
+
* 4. Commits the reserved charge immediately before the chunk is emitted.
|
|
74
|
+
* 5. On generator completion, emits a final `event: payment-receipt`.
|
|
74
75
|
*
|
|
75
76
|
* Returns a `ReadableStream<Uint8Array>` suitable for use as an HTTP response body.
|
|
76
77
|
*/
|
|
@@ -81,13 +82,19 @@ export function serve(options) {
|
|
|
81
82
|
async start(controller) {
|
|
82
83
|
const aborted = () => signal?.aborted ?? false;
|
|
83
84
|
const emit = (event) => controller.enqueue(encoder.encode(event));
|
|
84
|
-
|
|
85
|
+
let reservedAmount = 0n;
|
|
86
|
+
let reservedUnits = 0;
|
|
87
|
+
const charge = () => reserveChargeOrWait({
|
|
85
88
|
store,
|
|
86
89
|
channelId,
|
|
87
90
|
amount: tickCost,
|
|
91
|
+
reservedAmount,
|
|
88
92
|
emit,
|
|
89
93
|
pollIntervalMs,
|
|
90
94
|
signal,
|
|
95
|
+
}).then(() => {
|
|
96
|
+
reservedAmount += tickCost;
|
|
97
|
+
reservedUnits += 1;
|
|
91
98
|
});
|
|
92
99
|
const iterable = typeof generate === 'function' ? generate({ charge }) : generate;
|
|
93
100
|
try {
|
|
@@ -96,6 +103,14 @@ export function serve(options) {
|
|
|
96
103
|
break;
|
|
97
104
|
if (typeof generate !== 'function')
|
|
98
105
|
await charge();
|
|
106
|
+
await commitReservedCharges({
|
|
107
|
+
store,
|
|
108
|
+
channelId,
|
|
109
|
+
amount: reservedAmount,
|
|
110
|
+
units: reservedUnits,
|
|
111
|
+
});
|
|
112
|
+
reservedAmount = 0n;
|
|
113
|
+
reservedUnits = 0;
|
|
99
114
|
controller.enqueue(encoder.encode(`event: message\ndata: ${value}\n\n`));
|
|
100
115
|
}
|
|
101
116
|
if (!aborted()) {
|
|
@@ -158,32 +173,58 @@ export function fromRequest(request) {
|
|
|
158
173
|
};
|
|
159
174
|
}
|
|
160
175
|
/**
|
|
161
|
-
*
|
|
162
|
-
* insufficient. Uses `store.waitForUpdate()` when available for
|
|
176
|
+
* Reserve `amount` of voucher headroom for a future emission, retrying when
|
|
177
|
+
* balance is insufficient. Uses `store.waitForUpdate()` when available for
|
|
163
178
|
* event-driven wakeups, falling back to polling otherwise. Emits
|
|
164
179
|
* `payment-need-voucher` events via `emit` while waiting.
|
|
165
180
|
*/
|
|
166
|
-
async function
|
|
167
|
-
const { store, channelId, amount, emit, pollIntervalMs, signal } = options;
|
|
168
|
-
let
|
|
169
|
-
if (!
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
181
|
+
async function reserveChargeOrWait(options) {
|
|
182
|
+
const { store, channelId, amount, emit, pollIntervalMs, reservedAmount, signal } = options;
|
|
183
|
+
let channel = await store.getChannel(channelId);
|
|
184
|
+
if (!channel)
|
|
185
|
+
throw new Error('channel not found');
|
|
186
|
+
const hasHeadroom = (state) => state.highestVoucherAmount - state.spent - reservedAmount >= amount;
|
|
187
|
+
if (hasHeadroom(channel))
|
|
188
|
+
return;
|
|
189
|
+
// Emit a single need-voucher event, then wait until the accepted voucher
|
|
190
|
+
// headroom covers both already-reserved units and the next requested unit.
|
|
191
|
+
await Promise.resolve(emit(formatNeedVoucherEvent({
|
|
192
|
+
channelId,
|
|
193
|
+
requiredCumulative: (channel.spent + reservedAmount + amount).toString(),
|
|
194
|
+
acceptedCumulative: channel.highestVoucherAmount.toString(),
|
|
195
|
+
deposit: channel.deposit.toString(),
|
|
196
|
+
})));
|
|
197
|
+
while (!hasHeadroom(channel)) {
|
|
198
|
+
await waitForUpdate(store, channelId, pollIntervalMs, signal);
|
|
199
|
+
channel = await store.getChannel(channelId);
|
|
200
|
+
if (!channel)
|
|
201
|
+
throw new Error('channel not found');
|
|
185
202
|
}
|
|
186
203
|
}
|
|
204
|
+
async function commitReservedCharges(options) {
|
|
205
|
+
const { store, channelId, amount, units } = options;
|
|
206
|
+
if (amount === 0n || units === 0)
|
|
207
|
+
return;
|
|
208
|
+
let committed = false;
|
|
209
|
+
const channel = await store.updateChannel(channelId, (current) => {
|
|
210
|
+
if (!current)
|
|
211
|
+
return null;
|
|
212
|
+
if (current.finalized)
|
|
213
|
+
return current;
|
|
214
|
+
if (current.highestVoucherAmount - current.spent < amount)
|
|
215
|
+
return current;
|
|
216
|
+
committed = true;
|
|
217
|
+
return {
|
|
218
|
+
...current,
|
|
219
|
+
spent: current.spent + amount,
|
|
220
|
+
units: current.units + units,
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
if (!channel)
|
|
224
|
+
throw new Error('channel not found');
|
|
225
|
+
if (!committed)
|
|
226
|
+
throw new Error('reserved voucher coverage is no longer available');
|
|
227
|
+
}
|
|
187
228
|
async function waitForUpdate(store, channelId, pollIntervalMs, signal) {
|
|
188
229
|
if (signal?.aborted)
|
|
189
230
|
throw new Error('Aborted while waiting for voucher');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sse.js","sourceRoot":"","sources":["../../../src/tempo/session/Sse.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"Sse.js","sourceRoot":"","sources":["../../../src/tempo/session/Sse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as ChannelStore from './ChannelStore.js';
|
|
2
|
+
import type { SessionController } from './Sse.js';
|
|
3
|
+
import type { NeedVoucherEvent, SessionReceipt } from './Types.js';
|
|
4
|
+
export type { SessionController } from './Sse.js';
|
|
5
|
+
export type SessionRouteResult = {
|
|
6
|
+
status: 402;
|
|
7
|
+
challenge: Response;
|
|
8
|
+
} | {
|
|
9
|
+
status: 200;
|
|
10
|
+
withReceipt(response?: Response): Response;
|
|
11
|
+
};
|
|
12
|
+
export type SessionRoute = (request: Request) => Promise<SessionRouteResult>;
|
|
13
|
+
export type Socket = {
|
|
14
|
+
close(code?: number, reason?: string): unknown;
|
|
15
|
+
send(data: string): unknown;
|
|
16
|
+
addEventListener?: (type: 'close' | 'error' | 'message', listener: ((event: any) => void) | {
|
|
17
|
+
handleEvent(event: any): void;
|
|
18
|
+
}) => unknown;
|
|
19
|
+
removeEventListener?: (type: 'close' | 'error' | 'message', listener: ((event: any) => void) | {
|
|
20
|
+
handleEvent(event: any): void;
|
|
21
|
+
}) => unknown;
|
|
22
|
+
on?: (type: 'close' | 'error' | 'message', listener: (...args: any[]) => void) => unknown;
|
|
23
|
+
off?: (type: 'close' | 'error' | 'message', listener: (...args: any[]) => void) => unknown;
|
|
24
|
+
};
|
|
25
|
+
export type Message = {
|
|
26
|
+
mpp: 'authorization';
|
|
27
|
+
authorization: string;
|
|
28
|
+
} | {
|
|
29
|
+
mpp: 'message';
|
|
30
|
+
data: string;
|
|
31
|
+
} | {
|
|
32
|
+
mpp: 'payment-close-request';
|
|
33
|
+
} | {
|
|
34
|
+
mpp: 'payment-close-ready';
|
|
35
|
+
data: SessionReceipt;
|
|
36
|
+
} | {
|
|
37
|
+
mpp: 'payment-error';
|
|
38
|
+
status: number;
|
|
39
|
+
message: string;
|
|
40
|
+
} | {
|
|
41
|
+
mpp: 'payment-need-voucher';
|
|
42
|
+
data: NeedVoucherEvent;
|
|
43
|
+
} | {
|
|
44
|
+
mpp: 'payment-receipt';
|
|
45
|
+
data: SessionReceipt;
|
|
46
|
+
};
|
|
47
|
+
export declare function formatAuthorizationMessage(authorization: string): string;
|
|
48
|
+
export declare function formatApplicationMessage(data: string): string;
|
|
49
|
+
export declare function formatCloseRequestMessage(): string;
|
|
50
|
+
export declare function formatCloseReadyMessage(receipt: SessionReceipt): string;
|
|
51
|
+
export declare function formatNeedVoucherMessage(params: NeedVoucherEvent): string;
|
|
52
|
+
export declare function formatReceiptMessage(receipt: SessionReceipt): string;
|
|
53
|
+
export declare function formatErrorMessage(parameters: {
|
|
54
|
+
message: string;
|
|
55
|
+
status: number;
|
|
56
|
+
}): string;
|
|
57
|
+
export declare function parseMessage(raw: string): Message | null;
|
|
58
|
+
/**
|
|
59
|
+
* Bridge a WebSocket connection to a Tempo session payment flow.
|
|
60
|
+
*
|
|
61
|
+
* Credential verification is performed by routing each in-band authorization
|
|
62
|
+
* frame through `route` as a **synthetic `POST` request** that carries only
|
|
63
|
+
* the `Authorization` header. The synthetic request does not include cookies,
|
|
64
|
+
* bodies, query parameters, or other headers from the original WebSocket
|
|
65
|
+
* upgrade request. Do not wrap `route` with middleware that depends on
|
|
66
|
+
* HTTP-specific context beyond the `Authorization` header.
|
|
67
|
+
*/
|
|
68
|
+
export declare function serve(options: serve.Options): Promise<void>;
|
|
69
|
+
export declare namespace serve {
|
|
70
|
+
type Options = {
|
|
71
|
+
/** Expected per-tick amount in raw units. When set, credentials whose
|
|
72
|
+
* challenge `request.amount` does not match are rejected. Use this to
|
|
73
|
+
* pin the price when the route is backed by `Mppx.compose()` with
|
|
74
|
+
* multiple offers — otherwise a client can select the cheapest offer
|
|
75
|
+
* and still receive the same stream. */
|
|
76
|
+
amount?: string | undefined;
|
|
77
|
+
generate: AsyncIterable<string> | ((stream: SessionController) => AsyncIterable<string>);
|
|
78
|
+
pollIntervalMs?: number | undefined;
|
|
79
|
+
/** Payment route handler. Receives synthetic `POST` requests with only
|
|
80
|
+
* the `Authorization` header — no cookies, bodies, or upgrade headers. */
|
|
81
|
+
route: SessionRoute;
|
|
82
|
+
socket: Socket;
|
|
83
|
+
store: ChannelStore.ChannelStore | import('../../Store.js').Store;
|
|
84
|
+
url: string | URL;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=Ws.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ws.d.ts","sourceRoot":"","sources":["../../../src/tempo/session/Ws.ts"],"names":[],"mappings":"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"}
|