@devlab.group/agent-commerce 0.1.0-alpha.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 +17 -0
- package/README.md +324 -0
- package/dist/chunk-CZ6ZDAYD.js +192 -0
- package/dist/chunk-CZ6ZDAYD.js.map +1 -0
- package/dist/cli/index.js +2396 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +412 -0
- package/dist/index.js +2930 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +68 -0
- package/dist/mcp.js +400 -0
- package/dist/mcp.js.map +1 -0
- package/dist/protocol-adapter-C0goMgLK.d.ts +223 -0
- package/dist/runtime-LCk2TzGN.d.ts +277 -0
- package/dist/x402.d.ts +77 -0
- package/dist/x402.js +650 -0
- package/dist/x402.js.map +1 -0
- package/package.json +136 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import { I as IsoTimestamp, D as DecimalAmount, P as PaymentMethodName, B as BackendHandler, A as AdapterDescriptor, a as AdapterHealth, C as CommerceResource, R as ResourceRegistry, b as PaymentProvider, L as Logger, c as Clock, d as IdGenerator } from './runtime-LCk2TzGN.js';
|
|
2
|
+
export { e as BackendMethod, f as DEFAULT_BACKEND_TIMEOUT_MS, J as JsonSchema, N as NOOP_LOGGER, g as PaymentChallenge, h as PaymentContext, i as PaymentRequirement, j as PaymentResult, k as PaymentSettlementContext, l as PaymentSubmission, m as PaymentVerificationContext, n as Pricing, o as ProtocolName, s as systemClock } from './runtime-LCk2TzGN.js';
|
|
3
|
+
import { D as DeliveredOutcome, P as PaymentRequiredOutcome, C as CommerceEvent, a as PaymentAttempt, b as CommerceReceipt, E as ExecutionPipeline, c as ProtocolAdapter } from './protocol-adapter-C0goMgLK.js';
|
|
4
|
+
export { d as COMMERCE_EVENT_TYPES, e as CanonicalRequest, f as CommerceEventType, g as EventSink, h as ExecutionOutcome, H as HttpProtocolAdapter, i as ProtocolAdapterContext, j as isHttpProtocolAdapter } from './protocol-adapter-C0goMgLK.js';
|
|
5
|
+
import { FastifyInstance } from 'fastify';
|
|
6
|
+
import 'node:http';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Typed domain error codes.
|
|
10
|
+
*
|
|
11
|
+
* FROZEN CONTRACT. Protocol adapters map these codes into their own response
|
|
12
|
+
* format. Never throw a bare string or untyped Error across a package boundary.
|
|
13
|
+
*/
|
|
14
|
+
declare const COMMERCE_ERROR_CODES: readonly ["CONFIG_INVALID", "RESOURCE_NOT_FOUND", "INPUT_INVALID", "PAYMENT_REQUIRED", "PAYMENT_INVALID", "PAYMENT_REPLAYED", "PAYMENT_PROVIDER_UNAVAILABLE", "PAYMENT_SETTLEMENT_FAILED", "BACKEND_TIMEOUT", "BACKEND_ERROR", "PROTOCOL_UNSUPPORTED", "GATEWAY_BUSY", "STORAGE_ERROR", "INTERNAL_ERROR"];
|
|
15
|
+
type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Canonical HTTP status for each error code.
|
|
18
|
+
*
|
|
19
|
+
* Paid resources fail closed: every payment failure maps to a 4xx/5xx status
|
|
20
|
+
* and never to a successful delivery.
|
|
21
|
+
*/
|
|
22
|
+
declare const COMMERCE_ERROR_HTTP_STATUS: Readonly<Record<CommerceErrorCode, number>>;
|
|
23
|
+
/** Codes for which a client may reasonably retry the same request. */
|
|
24
|
+
declare const RETRYABLE_ERROR_CODES: ReadonlySet<CommerceErrorCode>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The single error type crossing package boundaries.
|
|
28
|
+
*
|
|
29
|
+
* FROZEN CONTRACT.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
interface CommerceErrorOptions {
|
|
33
|
+
/** Structured, non-secret detail safe to return to a client. */
|
|
34
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
35
|
+
readonly cause?: unknown;
|
|
36
|
+
readonly requestId?: string;
|
|
37
|
+
readonly resourceId?: string;
|
|
38
|
+
/** Override the default HTTP status for this code. */
|
|
39
|
+
readonly httpStatus?: number;
|
|
40
|
+
}
|
|
41
|
+
/** Serialisable wire form of a CommerceError. */
|
|
42
|
+
interface CommerceErrorInfo {
|
|
43
|
+
readonly code: CommerceErrorCode;
|
|
44
|
+
readonly message: string;
|
|
45
|
+
readonly httpStatus: number;
|
|
46
|
+
readonly retryable: boolean;
|
|
47
|
+
readonly requestId?: string;
|
|
48
|
+
readonly resourceId?: string;
|
|
49
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
50
|
+
}
|
|
51
|
+
declare class CommerceError extends Error {
|
|
52
|
+
readonly code: CommerceErrorCode;
|
|
53
|
+
readonly httpStatus: number;
|
|
54
|
+
readonly retryable: boolean;
|
|
55
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
56
|
+
readonly requestId?: string;
|
|
57
|
+
readonly resourceId?: string;
|
|
58
|
+
constructor(code: CommerceErrorCode, message: string, options?: CommerceErrorOptions);
|
|
59
|
+
/** Non-secret, client-safe representation. */
|
|
60
|
+
toInfo(): CommerceErrorInfo;
|
|
61
|
+
}
|
|
62
|
+
declare function isCommerceError(value: unknown): value is CommerceError;
|
|
63
|
+
/**
|
|
64
|
+
* Normalise any thrown value into a CommerceError.
|
|
65
|
+
*
|
|
66
|
+
* Used at package boundaries so an unexpected failure never escapes untyped.
|
|
67
|
+
*
|
|
68
|
+
* SECURITY — do not "improve" this by propagating `value.message`.
|
|
69
|
+
* `CommerceError.message` is client-visible: it is serialised by `toInfo()`
|
|
70
|
+
* and `toErrorEnvelope()` and returned over HTTP and MCP. An arbitrary thrown
|
|
71
|
+
* Error's message routinely carries internal detail — database connection
|
|
72
|
+
* strings, internal hostnames, filesystem paths, backend URLs. Copying it into
|
|
73
|
+
* a client-facing field turns every unexpected exception into an information
|
|
74
|
+
* disclosure.
|
|
75
|
+
*
|
|
76
|
+
* The original value is preserved on `cause`, which is never serialised, so
|
|
77
|
+
* logs and diagnostics keep the full detail while clients get only the
|
|
78
|
+
* caller's deliberate, reviewed `fallbackMessage`.
|
|
79
|
+
*
|
|
80
|
+
* A caller that *wants* a specific client-facing message passes one:
|
|
81
|
+
* toCommerceError(err, 'BACKEND_ERROR', 'Backend call failed')
|
|
82
|
+
*/
|
|
83
|
+
declare function toCommerceError(value: unknown, fallbackCode?: CommerceErrorCode, fallbackMessage?: string): CommerceError;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Gateway-defined wire envelopes.
|
|
87
|
+
*
|
|
88
|
+
* FROZEN CONTRACT. These are the *only* representations of "payment required"
|
|
89
|
+
* and "error" that leave the gateway, whichever protocol carries them. The HTTP
|
|
90
|
+
* routes, the MCP adapter and the demo buyer agent all use these helpers so the
|
|
91
|
+
* three can never drift apart.
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Reserved input property carrying a payment proof on protocols that have no
|
|
96
|
+
* header channel (MCP tool calls). Over HTTP the `X-PAYMENT` header is used.
|
|
97
|
+
*/
|
|
98
|
+
declare const PAYMENT_INPUT_FIELD = "_payment";
|
|
99
|
+
/** HTTP header carrying the payment proof. */
|
|
100
|
+
declare const PAYMENT_HEADER = "x-payment";
|
|
101
|
+
/** HTTP response header carrying the settlement reference. */
|
|
102
|
+
declare const PAYMENT_RESPONSE_HEADER = "x-payment-response";
|
|
103
|
+
/**
|
|
104
|
+
* Key under which a protocol adapter attaches a {@link DeliverySummary} to its
|
|
105
|
+
* result metadata — MCP's `CallToolResult._meta`, and anywhere else a protocol
|
|
106
|
+
* offers an out-of-band metadata channel.
|
|
107
|
+
*
|
|
108
|
+
* Frozen deliberately. The bug this whole mechanism exists to fix was two
|
|
109
|
+
* surfaces disagreeing about what a payer gets back; a key name enforced only
|
|
110
|
+
* by one side's tests would reintroduce exactly that drift. Producer and
|
|
111
|
+
* consumer both import this constant.
|
|
112
|
+
*
|
|
113
|
+
* Follows MCP's `<namespace>/<name>` convention for `_meta` keys.
|
|
114
|
+
*/
|
|
115
|
+
declare const DELIVERY_SUMMARY_META_KEY = "agent-commerce/delivery";
|
|
116
|
+
interface PaymentRequiredEnvelope {
|
|
117
|
+
readonly status: 'payment-required';
|
|
118
|
+
readonly code: 'PAYMENT_REQUIRED';
|
|
119
|
+
readonly requestId: string;
|
|
120
|
+
readonly resourceId: string;
|
|
121
|
+
readonly message: string;
|
|
122
|
+
readonly payment: {
|
|
123
|
+
readonly provider: PaymentMethodName;
|
|
124
|
+
readonly version: string;
|
|
125
|
+
readonly amount: DecimalAmount;
|
|
126
|
+
readonly currency: string;
|
|
127
|
+
readonly destination: string;
|
|
128
|
+
readonly network?: string;
|
|
129
|
+
readonly asset?: string;
|
|
130
|
+
readonly expiresAt?: IsoTimestamp;
|
|
131
|
+
/** Provider-native requirement objects, passed through verbatim. */
|
|
132
|
+
readonly accepts: readonly Readonly<Record<string, unknown>>[];
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
interface ErrorEnvelope {
|
|
136
|
+
readonly status: 'error';
|
|
137
|
+
readonly code: CommerceErrorCode;
|
|
138
|
+
readonly message: string;
|
|
139
|
+
readonly retryable: boolean;
|
|
140
|
+
readonly requestId?: string;
|
|
141
|
+
readonly resourceId?: string;
|
|
142
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* What a buyer learns about their own completed purchase.
|
|
146
|
+
*
|
|
147
|
+
* A payer is entitled to the record of their own transaction — the request it
|
|
148
|
+
* belonged to, whether it settled, and the settlement reference they can check
|
|
149
|
+
* on-chain. They are NOT entitled to the merchant's ledger, which is why
|
|
150
|
+
* `/api/receipts` is an operator route behind `server.adminToken`.
|
|
151
|
+
*
|
|
152
|
+
* Before this existed the two surfaces disagreed: HTTP callers received a
|
|
153
|
+
* settlement summary in `X-PAYMENT-RESPONSE` while MCP callers received
|
|
154
|
+
* nothing, so an MCP buyer's only route to their own receipt was the merchant's
|
|
155
|
+
* ledger. Both surfaces now emit this same shape.
|
|
156
|
+
*/
|
|
157
|
+
interface DeliverySummary {
|
|
158
|
+
readonly requestId: string;
|
|
159
|
+
readonly resourceId: string;
|
|
160
|
+
readonly receiptId: string;
|
|
161
|
+
readonly deliveredAt: IsoTimestamp;
|
|
162
|
+
readonly payment?: {
|
|
163
|
+
readonly status: 'verified' | 'settled' | 'rejected';
|
|
164
|
+
readonly amount: DecimalAmount;
|
|
165
|
+
readonly currency: string;
|
|
166
|
+
/** Settlement reference, e.g. an on-chain transaction hash. */
|
|
167
|
+
readonly externalReference?: string;
|
|
168
|
+
readonly network?: string;
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** Build the payer-facing summary of a delivered outcome. */
|
|
172
|
+
declare function toDeliverySummary(outcome: DeliveredOutcome): DeliverySummary;
|
|
173
|
+
declare function toPaymentRequiredEnvelope(outcome: PaymentRequiredOutcome): PaymentRequiredEnvelope;
|
|
174
|
+
declare function toErrorEnvelope(error: CommerceError): ErrorEnvelope;
|
|
175
|
+
declare function isPaymentRequiredEnvelope(value: unknown): value is PaymentRequiredEnvelope;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Merchant backend execution boundary.
|
|
179
|
+
*
|
|
180
|
+
* The only place in the system allowed to make an outbound HTTP call to a
|
|
181
|
+
* merchant backend. Every call is bounded by a timeout; redirects are not
|
|
182
|
+
* followed (see docs/security.md).
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
interface BackendRequest {
|
|
186
|
+
readonly requestId: string;
|
|
187
|
+
readonly resourceId: string;
|
|
188
|
+
/** Validated resource input. */
|
|
189
|
+
readonly input: unknown;
|
|
190
|
+
}
|
|
191
|
+
interface BackendResponse {
|
|
192
|
+
readonly status: number;
|
|
193
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
194
|
+
readonly body: unknown;
|
|
195
|
+
readonly durationMs: number;
|
|
196
|
+
}
|
|
197
|
+
interface BackendExecutor {
|
|
198
|
+
/**
|
|
199
|
+
* Call the merchant backend.
|
|
200
|
+
*
|
|
201
|
+
* Must throw `CommerceError('BACKEND_TIMEOUT')` on timeout and
|
|
202
|
+
* `CommerceError('BACKEND_ERROR')` for non-2xx responses and transport
|
|
203
|
+
* failures. Must never throw an untyped error.
|
|
204
|
+
*/
|
|
205
|
+
call(handler: BackendHandler, request: BackendRequest): Promise<BackendResponse>;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Persistence boundary for receipts, events and payment attempts.
|
|
210
|
+
*
|
|
211
|
+
* Implemented by src/storage/receipts. Core depends only on this
|
|
212
|
+
* interface, never on SQLite.
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
interface PaymentAttemptReservation {
|
|
216
|
+
readonly requestId: string;
|
|
217
|
+
readonly resourceId: string;
|
|
218
|
+
readonly provider: string;
|
|
219
|
+
/** Must be unique across the store — see PaymentResult.replayKey. */
|
|
220
|
+
readonly replayKey: string;
|
|
221
|
+
readonly amount: string;
|
|
222
|
+
readonly currency: string;
|
|
223
|
+
readonly payer?: string;
|
|
224
|
+
readonly payee?: string;
|
|
225
|
+
}
|
|
226
|
+
interface PaymentAttemptUpdate {
|
|
227
|
+
readonly replayKey: string;
|
|
228
|
+
readonly status: PaymentAttempt['status'];
|
|
229
|
+
readonly externalReference?: string;
|
|
230
|
+
readonly rejectionReason?: string;
|
|
231
|
+
}
|
|
232
|
+
interface ListOptions {
|
|
233
|
+
readonly limit?: number;
|
|
234
|
+
readonly requestId?: string;
|
|
235
|
+
}
|
|
236
|
+
interface ReceiptStore {
|
|
237
|
+
init(): Promise<void>;
|
|
238
|
+
/** Append a canonical event. Must not throw into the caller's flow. */
|
|
239
|
+
appendEvent(event: CommerceEvent): Promise<void>;
|
|
240
|
+
/**
|
|
241
|
+
* Atomically claim a payment authorisation before settlement.
|
|
242
|
+
*
|
|
243
|
+
* Throws `CommerceError('PAYMENT_REPLAYED')` if `replayKey` was already
|
|
244
|
+
* reserved. This is the gateway's replay defence and is required for every
|
|
245
|
+
* paid request.
|
|
246
|
+
*/
|
|
247
|
+
reservePaymentAttempt(reservation: PaymentAttemptReservation): Promise<PaymentAttempt>;
|
|
248
|
+
updatePaymentAttempt(update: PaymentAttemptUpdate): Promise<void>;
|
|
249
|
+
saveReceipt(receipt: CommerceReceipt): Promise<void>;
|
|
250
|
+
getReceipt(id: string): Promise<CommerceReceipt | undefined>;
|
|
251
|
+
listReceipts(options?: ListOptions): Promise<readonly CommerceReceipt[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Total receipts held, ignoring any list limit.
|
|
254
|
+
*
|
|
255
|
+
* `listReceipts` clamps to a bounded page (a store-level invariant, so an
|
|
256
|
+
* unbounded `limit` cannot dump the ledger). Counting by measuring the length
|
|
257
|
+
* of a list therefore silently saturates at the clamp — `doctor` reported
|
|
258
|
+
* "receipts=500" forever once 500 was passed. A diagnostic that quietly stops
|
|
259
|
+
* counting is worse than one that admits it cannot.
|
|
260
|
+
*/
|
|
261
|
+
countReceipts(): Promise<number>;
|
|
262
|
+
/**
|
|
263
|
+
* Receipts whose delivery did not succeed — `backendStatus` outside 2xx.
|
|
264
|
+
*
|
|
265
|
+
* A paid-but-undelivered purchase is the one row a merchant must notice:
|
|
266
|
+
* settlement is final and v0.1 has no refunds, so *seeing* it is the only
|
|
267
|
+
* remedy available. Counted rather than listed for the same reason as
|
|
268
|
+
* {@link countReceipts} — `listReceipts` is clamped, so counting by list
|
|
269
|
+
* length silently saturates.
|
|
270
|
+
*
|
|
271
|
+
* In practice this is exactly "paid but undelivered", not "any failed
|
|
272
|
+
* delivery": the pipeline only ever persists a receipt when a payment was
|
|
273
|
+
* attempted (`paymentResult !== undefined`), so a free resource whose
|
|
274
|
+
* backend call fails throws without writing a receipt at all — there is no
|
|
275
|
+
* row for `countUndeliveredReceipts` to see. Free-resource failures are
|
|
276
|
+
* therefore *not* counted here, however natural it is to read the name as
|
|
277
|
+
* saying they are. Writing a receipt for a failed free delivery too would be
|
|
278
|
+
* a more complete ledger, but it changes what this count means — that is
|
|
279
|
+
* a product decision for after the alpha, not something to do here.
|
|
280
|
+
*/
|
|
281
|
+
countUndeliveredReceipts(): Promise<number>;
|
|
282
|
+
listEvents(options?: ListOptions): Promise<readonly CommerceEvent[]>;
|
|
283
|
+
listPaymentAttempts(options?: ListOptions): Promise<readonly PaymentAttempt[]>;
|
|
284
|
+
readonly descriptor: AdapterDescriptor;
|
|
285
|
+
health(): Promise<AdapterHealth>;
|
|
286
|
+
close(): Promise<void>;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* `config.yaml` schema, validation and normalisation into the
|
|
291
|
+
* canonical `GatewayConfig` (docs/contracts.md).
|
|
292
|
+
*
|
|
293
|
+
* Two-phase validation:
|
|
294
|
+
* 1. Zod validates *shape* (types, required fields, unknown-key rejection).
|
|
295
|
+
* Numeric/boolean leaves accept either their native type or a string
|
|
296
|
+
* (env substitution always produces a string), and are left as-is here —
|
|
297
|
+
* Zod's typed transforms have surprising inference interactions with
|
|
298
|
+
* `.strict()` objects, so numeric/boolean coercion is done explicitly,
|
|
299
|
+
* in plain TypeScript, in the normalisation pass below.
|
|
300
|
+
* 2. A manual business-rule pass validates cross-references that need a
|
|
301
|
+
* specific, actionable message (duplicate ids, disabled protocols/payment
|
|
302
|
+
* methods, dynamic pricing, destination-address plausibility) and
|
|
303
|
+
* performs the numeric/boolean coercion.
|
|
304
|
+
*
|
|
305
|
+
* Env substitution (`${VAR}` / `${VAR:-default}`) runs over the raw parsed
|
|
306
|
+
* value *before* either phase, so numeric/boolean fields can be templated too.
|
|
307
|
+
* One exception, deliberate: `checkVersion` runs **before** substitution, so
|
|
308
|
+
* `version:` cannot itself be templated. It is the compatibility gate that
|
|
309
|
+
* decides whether this parser understands the document at all; resolving
|
|
310
|
+
* environment variables to find out which schema version to expect would be
|
|
311
|
+
* backwards. The order is intended; `version:` is the one exception to the
|
|
312
|
+
* substitution rule, which this sentence exists to record.
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
interface GatewayConfig {
|
|
316
|
+
readonly version: 1;
|
|
317
|
+
readonly merchant: {
|
|
318
|
+
readonly id: string;
|
|
319
|
+
readonly name: string;
|
|
320
|
+
readonly publicBaseUrl: string;
|
|
321
|
+
};
|
|
322
|
+
readonly server: {
|
|
323
|
+
readonly port: number;
|
|
324
|
+
readonly host: string;
|
|
325
|
+
readonly adminToken?: string;
|
|
326
|
+
readonly allowedOrigins: readonly string[];
|
|
327
|
+
};
|
|
328
|
+
readonly storage: {
|
|
329
|
+
readonly receipts: {
|
|
330
|
+
readonly driver: 'sqlite';
|
|
331
|
+
readonly path: string;
|
|
332
|
+
};
|
|
333
|
+
};
|
|
334
|
+
readonly protocols: {
|
|
335
|
+
readonly http: {
|
|
336
|
+
readonly enabled: boolean;
|
|
337
|
+
};
|
|
338
|
+
readonly mcp: {
|
|
339
|
+
readonly enabled: boolean;
|
|
340
|
+
readonly mountPath: string;
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
/** Canonical resources, already normalised. */
|
|
344
|
+
readonly resources: readonly CommerceResource[];
|
|
345
|
+
readonly payments: {
|
|
346
|
+
readonly x402?: {
|
|
347
|
+
readonly enabled: boolean;
|
|
348
|
+
readonly network: string;
|
|
349
|
+
readonly rpcUrl: string;
|
|
350
|
+
readonly asset: string;
|
|
351
|
+
readonly assetName: string;
|
|
352
|
+
readonly assetVersion: string;
|
|
353
|
+
readonly assetDecimals: number;
|
|
354
|
+
readonly payTo: string;
|
|
355
|
+
readonly maxTimeoutSeconds: number;
|
|
356
|
+
readonly facilitator: {
|
|
357
|
+
readonly mode: 'local';
|
|
358
|
+
readonly signerPrivateKey: string;
|
|
359
|
+
} | {
|
|
360
|
+
readonly mode: 'remote';
|
|
361
|
+
readonly url: string;
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
declare function parseConfig(raw: unknown, env: NodeJS.ProcessEnv): GatewayConfig;
|
|
367
|
+
|
|
368
|
+
interface LoadConfigOptions {
|
|
369
|
+
readonly path?: string;
|
|
370
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
371
|
+
readonly cwd?: string;
|
|
372
|
+
}
|
|
373
|
+
declare function loadConfig(options?: LoadConfigOptions): Promise<GatewayConfig>;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* `createGateway()` — the Fastify server. Fully usable (and tested) with
|
|
377
|
+
* fakes, without `main.ts` (docs/contracts.md "Composition root").
|
|
378
|
+
*/
|
|
379
|
+
|
|
380
|
+
interface GatewayOptions {
|
|
381
|
+
readonly config: GatewayConfig;
|
|
382
|
+
readonly store: ReceiptStore;
|
|
383
|
+
readonly paymentProviders: readonly PaymentProvider[];
|
|
384
|
+
readonly protocolAdapters: readonly ProtocolAdapter[];
|
|
385
|
+
readonly logger?: Logger;
|
|
386
|
+
readonly clock?: Clock;
|
|
387
|
+
readonly ids?: IdGenerator;
|
|
388
|
+
/** Override for tests. */
|
|
389
|
+
readonly backend?: BackendExecutor;
|
|
390
|
+
}
|
|
391
|
+
interface GatewayInstance {
|
|
392
|
+
readonly pipeline: ExecutionPipeline;
|
|
393
|
+
readonly resources: ResourceRegistry;
|
|
394
|
+
listen(): Promise<{
|
|
395
|
+
url: string;
|
|
396
|
+
}>;
|
|
397
|
+
close(): Promise<void>;
|
|
398
|
+
/** Fastify instance, for `.inject()` in tests. */
|
|
399
|
+
readonly server: FastifyInstance;
|
|
400
|
+
}
|
|
401
|
+
declare function createGateway(options: GatewayOptions): Promise<GatewayInstance>;
|
|
402
|
+
|
|
403
|
+
interface SqliteReceiptStoreOptions {
|
|
404
|
+
/** File path, or ':memory:' for tests. Parent directory is created if missing. */
|
|
405
|
+
readonly path: string;
|
|
406
|
+
readonly logger?: Logger;
|
|
407
|
+
readonly clock?: Clock;
|
|
408
|
+
readonly ids?: IdGenerator;
|
|
409
|
+
}
|
|
410
|
+
declare function createSqliteReceiptStore(options: SqliteReceiptStoreOptions): ReceiptStore;
|
|
411
|
+
|
|
412
|
+
export { AdapterDescriptor, AdapterHealth, type BackendExecutor, BackendHandler, type BackendRequest, type BackendResponse, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, Clock, CommerceError, type CommerceErrorCode, type CommerceErrorInfo, type CommerceErrorOptions, CommerceEvent, CommerceReceipt, CommerceResource, DELIVERY_SUMMARY_META_KEY, DecimalAmount, DeliveredOutcome, type DeliverySummary, type ErrorEnvelope, ExecutionPipeline, type GatewayConfig, type GatewayInstance, type GatewayOptions, IdGenerator, IsoTimestamp, type ListOptions, Logger, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_RESPONSE_HEADER, PaymentAttempt, type PaymentAttemptReservation, type PaymentAttemptUpdate, PaymentMethodName, PaymentProvider, type PaymentRequiredEnvelope, PaymentRequiredOutcome, ProtocolAdapter, RETRYABLE_ERROR_CODES, type ReceiptStore, ResourceRegistry, createGateway, createSqliteReceiptStore, isCommerceError, isPaymentRequiredEnvelope, loadConfig, parseConfig, createSqliteReceiptStore as receipts, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope };
|