@nuanu-ai/agentify-contracts 0.3.2
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 +201 -0
- package/NOTICE +2 -0
- package/README.md +32 -0
- package/dist/api.d.ts +1948 -0
- package/dist/api.js +956 -0
- package/dist/card.d.ts +423 -0
- package/dist/card.js +700 -0
- package/dist/envelope.d.ts +174 -0
- package/dist/envelope.js +101 -0
- package/dist/events.d.ts +56 -0
- package/dist/events.js +54 -0
- package/dist/evm-address.d.ts +77 -0
- package/dist/evm-address.js +265 -0
- package/dist/handler.d.ts +90 -0
- package/dist/handler.js +102 -0
- package/dist/index.d.ts +1008 -0
- package/dist/index.js +167 -0
- package/dist/merchant.d.ts +281 -0
- package/dist/merchant.js +433 -0
- package/dist/order-status.d.ts +47 -0
- package/dist/order-status.js +102 -0
- package/dist/order.d.ts +50 -0
- package/dist/order.js +78 -0
- package/dist/param-spec.d.ts +145 -0
- package/dist/param-spec.js +147 -0
- package/dist/primitives.d.ts +103 -0
- package/dist/primitives.js +130 -0
- package/dist/quote.d.ts +79 -0
- package/dist/quote.js +92 -0
- package/dist/receipt.d.ts +79 -0
- package/dist/receipt.js +83 -0
- package/dist/results.d.ts +230 -0
- package/dist/results.js +269 -0
- package/dist/selling.d.ts +24 -0
- package/dist/selling.js +35 -0
- package/package.json +46 -0
package/dist/quote.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The question "how much is this and is it there", and the merchant's answer.
|
|
3
|
+
*
|
|
4
|
+
* One shape, two transports. By default the question rides the same outgoing
|
|
5
|
+
* channel as the orders and is answered by a handler in the merchant's own
|
|
6
|
+
* process; a merchant whose prices come from a separate service answers the
|
|
7
|
+
* same question over https at an address their card names. The fields do not
|
|
8
|
+
* differ between the two, which is what lets a merchant switch transports
|
|
9
|
+
* without touching the code that answers.
|
|
10
|
+
*
|
|
11
|
+
* What the schema deliberately does not describe is silence. A missing answer,
|
|
12
|
+
* a timeout, a broken connection and an answer that did not parse against the
|
|
13
|
+
* shape below are all the same thing to the gateway, and what it does about
|
|
14
|
+
* them depends on the card's mode rather than on the shape of anything on this
|
|
15
|
+
* page.
|
|
16
|
+
*
|
|
17
|
+
* One field an order has and this does not: a price question carries no test
|
|
18
|
+
* marker. For a card with a price check the question rides the same channel as
|
|
19
|
+
* the order it precedes, and it arrives looking like every other question — so
|
|
20
|
+
* a handler that routes test orders to a test environment, which the portal
|
|
21
|
+
* tells merchants they may do, has nothing to route the question by. Whether that wants a field here or is better
|
|
22
|
+
* answered by however the sandbox is eventually separated from live is not
|
|
23
|
+
* decided, and inventing the field ahead of that decision would answer it.
|
|
24
|
+
*/
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
/**
|
|
27
|
+
* Why we are asking.
|
|
28
|
+
*
|
|
29
|
+
* `purchase` means an agent is standing at the till right now; `poll` means we
|
|
30
|
+
* are refreshing what we know between purchases and nobody is buying. The
|
|
31
|
+
* distinction is there so an expensive stock lookup can be spent on the first
|
|
32
|
+
* and skipped on the second.
|
|
33
|
+
*/
|
|
34
|
+
export declare const QuotePurposeSchema: z.ZodEnum<{
|
|
35
|
+
purchase: "purchase";
|
|
36
|
+
poll: "poll";
|
|
37
|
+
}>;
|
|
38
|
+
export declare const QuoteRequestSchema: z.ZodObject<{
|
|
39
|
+
merchant_item_id: z.ZodString;
|
|
40
|
+
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
41
|
+
price_id: z.ZodString;
|
|
42
|
+
purpose: z.ZodEnum<{
|
|
43
|
+
purchase: "purchase";
|
|
44
|
+
poll: "poll";
|
|
45
|
+
}>;
|
|
46
|
+
expires_at: z.ZodISODateTime;
|
|
47
|
+
}, z.core.$strict>;
|
|
48
|
+
/**
|
|
49
|
+
* The answer, in the only two shapes it has.
|
|
50
|
+
*
|
|
51
|
+
* A price and an availability of `false` cannot travel together, and neither
|
|
52
|
+
* can availability of `true` and no price. Both would be two answers at once:
|
|
53
|
+
* whichever the gateway then acted on, the merchant would have grounds to say
|
|
54
|
+
* it acted on the wrong one — and in the first case the sale would quietly
|
|
55
|
+
* fall back to the price in the card, at a price the merchant never quoted.
|
|
56
|
+
*
|
|
57
|
+
* `as_of` is on both branches because it is what separates "I went and looked"
|
|
58
|
+
* from "here is what was in the cache". The gateway carries that moment and
|
|
59
|
+
* does not weigh it: it travels into the order the handler is given and into
|
|
60
|
+
* the record of the sale, so whoever reconciles a charge afterwards can see how
|
|
61
|
+
* old the number behind it was, and nothing anywhere compares it against
|
|
62
|
+
* anything. A price's life runs from the moment the answer reached us rather
|
|
63
|
+
* than from the moment it says it was true, so an answer stamped a year ago is
|
|
64
|
+
* honoured exactly as long as one stamped a second ago.
|
|
65
|
+
*/
|
|
66
|
+
export declare const QuoteResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
67
|
+
available: z.ZodLiteral<true>;
|
|
68
|
+
price: z.ZodObject<{
|
|
69
|
+
amount: z.ZodString;
|
|
70
|
+
currency: z.ZodString;
|
|
71
|
+
}, z.core.$strict>;
|
|
72
|
+
as_of: z.ZodISODateTime;
|
|
73
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
74
|
+
available: z.ZodLiteral<false>;
|
|
75
|
+
as_of: z.ZodISODateTime;
|
|
76
|
+
}, z.core.$strict>], "available">;
|
|
77
|
+
export type QuotePurpose = z.infer<typeof QuotePurposeSchema>;
|
|
78
|
+
export type QuoteRequest = z.infer<typeof QuoteRequestSchema>;
|
|
79
|
+
export type QuoteResponse = z.infer<typeof QuoteResponseSchema>;
|
package/dist/quote.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The question "how much is this and is it there", and the merchant's answer.
|
|
3
|
+
*
|
|
4
|
+
* One shape, two transports. By default the question rides the same outgoing
|
|
5
|
+
* channel as the orders and is answered by a handler in the merchant's own
|
|
6
|
+
* process; a merchant whose prices come from a separate service answers the
|
|
7
|
+
* same question over https at an address their card names. The fields do not
|
|
8
|
+
* differ between the two, which is what lets a merchant switch transports
|
|
9
|
+
* without touching the code that answers.
|
|
10
|
+
*
|
|
11
|
+
* What the schema deliberately does not describe is silence. A missing answer,
|
|
12
|
+
* a timeout, a broken connection and an answer that did not parse against the
|
|
13
|
+
* shape below are all the same thing to the gateway, and what it does about
|
|
14
|
+
* them depends on the card's mode rather than on the shape of anything on this
|
|
15
|
+
* page.
|
|
16
|
+
*
|
|
17
|
+
* One field an order has and this does not: a price question carries no test
|
|
18
|
+
* marker. For a card with a price check the question rides the same channel as
|
|
19
|
+
* the order it precedes, and it arrives looking like every other question — so
|
|
20
|
+
* a handler that routes test orders to a test environment, which the portal
|
|
21
|
+
* tells merchants they may do, has nothing to route the question by. Whether that wants a field here or is better
|
|
22
|
+
* answered by however the sandbox is eventually separated from live is not
|
|
23
|
+
* decided, and inventing the field ahead of that decision would answer it.
|
|
24
|
+
*/
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
import { ParamNameSchema } from "./param-spec.js";
|
|
27
|
+
import { IdentifierSchema, MoneySchema, TimestampSchema } from "./primitives.js";
|
|
28
|
+
/**
|
|
29
|
+
* Why we are asking.
|
|
30
|
+
*
|
|
31
|
+
* `purchase` means an agent is standing at the till right now; `poll` means we
|
|
32
|
+
* are refreshing what we know between purchases and nobody is buying. The
|
|
33
|
+
* distinction is there so an expensive stock lookup can be spent on the first
|
|
34
|
+
* and skipped on the second.
|
|
35
|
+
*/
|
|
36
|
+
export const QuotePurposeSchema = z.enum(["purchase", "poll"]);
|
|
37
|
+
export const QuoteRequestSchema = z.strictObject({
|
|
38
|
+
/** The merchant's own key for the product being asked about. */
|
|
39
|
+
merchant_item_id: IdentifierSchema,
|
|
40
|
+
/**
|
|
41
|
+
* The purchase parameters, where the price depends on them. Absent for a
|
|
42
|
+
* card that takes no input, and for a scheduled poll of such a card.
|
|
43
|
+
*/
|
|
44
|
+
// Same dropped key as everywhere this contract parses free-form names; see
|
|
45
|
+
// `PROTOTYPE_KEY_IS_DROPPED` in `param-spec.ts`.
|
|
46
|
+
params: z.record(ParamNameSchema, z.unknown()).optional(),
|
|
47
|
+
/**
|
|
48
|
+
* The identifier of this question, which comes back attached to the order.
|
|
49
|
+
*
|
|
50
|
+
* It is good for one order: a merchant who set stock aside under it can
|
|
51
|
+
* release it when the order arrives or when the price expires. That "one
|
|
52
|
+
* order" is a rule the gateway keeps — no schema can see a second use of an
|
|
53
|
+
* identifier it is shown once.
|
|
54
|
+
*/
|
|
55
|
+
price_id: IdentifierSchema,
|
|
56
|
+
purpose: QuotePurposeSchema,
|
|
57
|
+
/**
|
|
58
|
+
* Until when the price the merchant names will be honoured, so a merchant
|
|
59
|
+
* holding stock against it knows when to stop. There is no separate message
|
|
60
|
+
* when it passes; this moment is the whole notice.
|
|
61
|
+
*/
|
|
62
|
+
expires_at: TimestampSchema,
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* The answer, in the only two shapes it has.
|
|
66
|
+
*
|
|
67
|
+
* A price and an availability of `false` cannot travel together, and neither
|
|
68
|
+
* can availability of `true` and no price. Both would be two answers at once:
|
|
69
|
+
* whichever the gateway then acted on, the merchant would have grounds to say
|
|
70
|
+
* it acted on the wrong one — and in the first case the sale would quietly
|
|
71
|
+
* fall back to the price in the card, at a price the merchant never quoted.
|
|
72
|
+
*
|
|
73
|
+
* `as_of` is on both branches because it is what separates "I went and looked"
|
|
74
|
+
* from "here is what was in the cache". The gateway carries that moment and
|
|
75
|
+
* does not weigh it: it travels into the order the handler is given and into
|
|
76
|
+
* the record of the sale, so whoever reconciles a charge afterwards can see how
|
|
77
|
+
* old the number behind it was, and nothing anywhere compares it against
|
|
78
|
+
* anything. A price's life runs from the moment the answer reached us rather
|
|
79
|
+
* than from the moment it says it was true, so an answer stamped a year ago is
|
|
80
|
+
* honoured exactly as long as one stamped a second ago.
|
|
81
|
+
*/
|
|
82
|
+
export const QuoteResponseSchema = z.discriminatedUnion("available", [
|
|
83
|
+
z.strictObject({
|
|
84
|
+
available: z.literal(true),
|
|
85
|
+
price: MoneySchema,
|
|
86
|
+
as_of: TimestampSchema,
|
|
87
|
+
}),
|
|
88
|
+
z.strictObject({
|
|
89
|
+
available: z.literal(false),
|
|
90
|
+
as_of: TimestampSchema,
|
|
91
|
+
}),
|
|
92
|
+
]);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The receipt: the record left by a purchase that was paid for.
|
|
3
|
+
*
|
|
4
|
+
* It exists from the moment the money moves, which in two of the three modes
|
|
5
|
+
* is before the product is delivered — so a receipt has to be able to say
|
|
6
|
+
* "paid, delivery still running" without that being mistaken for either "you
|
|
7
|
+
* have it" or "you paid and never got it". A purchase that ends before any
|
|
8
|
+
* payment leaves no receipt at all: nothing moved, and there is nothing for it
|
|
9
|
+
* to be proof of. Which of the order's endings a receipt can carry is worked
|
|
10
|
+
* out at `ReceiptOutcomeSchema` below.
|
|
11
|
+
*
|
|
12
|
+
* The price on a receipt is the price the sale went through at, and it stays
|
|
13
|
+
* what it was even after the merchant's price changes.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
/**
|
|
17
|
+
* What became of the purchase behind this receipt.
|
|
18
|
+
*
|
|
19
|
+
* The words are the order's own — a receipt saying `pending` where the order
|
|
20
|
+
* said `in_progress` would be two names for one state, and whichever an agent
|
|
21
|
+
* happened to read would look like the whole truth.
|
|
22
|
+
*
|
|
23
|
+
* The set is narrower than the order's, and the reason is what a receipt is: a
|
|
24
|
+
* record of a payment that executed. Work through the endings and six of the
|
|
25
|
+
* ten cannot reach one. `rejected`, `declined` and `expired` all close before
|
|
26
|
+
* any money moves. `cancelled` is the merchant leaving, which for a paid order
|
|
27
|
+
* is a debt and arrives here as `refund_due` instead. `delivered_unpaid` is
|
|
28
|
+
* the case where the merchant produced the goods and the charge came back
|
|
29
|
+
* failed — no payment, so no receipt to carry the outcome.
|
|
30
|
+
*
|
|
31
|
+
* `payment_unresolved` is the one worth arguing rather than asserting, because
|
|
32
|
+
* the purchase behind it can have a verified payment behind it and still end
|
|
33
|
+
* there. It is excluded, and the reason is the receipt's own job. That value
|
|
34
|
+
* means nobody can say whether the buyer was charged; a receipt is the
|
|
35
|
+
* evidence that they were. A receipt carrying it would be a proof of payment
|
|
36
|
+
* whose own outcome says it does not know there was a payment — the one
|
|
37
|
+
* artifact in this contract that cannot hold that sentence. So no receipt is
|
|
38
|
+
* written while the question is open. If the answer arrives and the money did
|
|
39
|
+
* move, the receipt is written then and carries whatever the delivery reached;
|
|
40
|
+
* if it did not, there was never anything to record. That is the same promise
|
|
41
|
+
* the portal makes to the buyer in words: we say so when we learn.
|
|
42
|
+
*
|
|
43
|
+
* That leaves four: paid and still running, paid and delivered, paid and owed
|
|
44
|
+
* back, paid and paid back.
|
|
45
|
+
*
|
|
46
|
+
* What this list does not say is when a receipt is written at all, and a reader
|
|
47
|
+
* should not infer it from here. That is the gateway's, and a gateway that
|
|
48
|
+
* writes one only as goods are released will only ever produce `delivered` —
|
|
49
|
+
* so a consumer must not read the presence of these four as a promise that a
|
|
50
|
+
* receipt exists for every payment that executed.
|
|
51
|
+
*/
|
|
52
|
+
export declare const ReceiptOutcomeSchema: z.ZodEnum<{
|
|
53
|
+
delivered: "delivered";
|
|
54
|
+
in_progress: "in_progress";
|
|
55
|
+
refund_due: "refund_due";
|
|
56
|
+
refunded: "refunded";
|
|
57
|
+
}>;
|
|
58
|
+
export declare const ReceiptSchema: z.ZodObject<{
|
|
59
|
+
id: z.ZodString;
|
|
60
|
+
order_id: z.ZodString;
|
|
61
|
+
item_id: z.ZodString;
|
|
62
|
+
price: z.ZodObject<{
|
|
63
|
+
amount: z.ZodString;
|
|
64
|
+
currency: z.ZodString;
|
|
65
|
+
at: z.ZodISODateTime;
|
|
66
|
+
as_of: z.ZodISODateTime;
|
|
67
|
+
}, z.core.$strict>;
|
|
68
|
+
price_id: z.ZodOptional<z.ZodString>;
|
|
69
|
+
paid_at: z.ZodISODateTime;
|
|
70
|
+
outcome: z.ZodEnum<{
|
|
71
|
+
delivered: "delivered";
|
|
72
|
+
in_progress: "in_progress";
|
|
73
|
+
refund_due: "refund_due";
|
|
74
|
+
refunded: "refunded";
|
|
75
|
+
}>;
|
|
76
|
+
test: z.ZodBoolean;
|
|
77
|
+
}, z.core.$strict>;
|
|
78
|
+
export type ReceiptOutcome = z.infer<typeof ReceiptOutcomeSchema>;
|
|
79
|
+
export type Receipt = z.infer<typeof ReceiptSchema>;
|
package/dist/receipt.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The receipt: the record left by a purchase that was paid for.
|
|
3
|
+
*
|
|
4
|
+
* It exists from the moment the money moves, which in two of the three modes
|
|
5
|
+
* is before the product is delivered — so a receipt has to be able to say
|
|
6
|
+
* "paid, delivery still running" without that being mistaken for either "you
|
|
7
|
+
* have it" or "you paid and never got it". A purchase that ends before any
|
|
8
|
+
* payment leaves no receipt at all: nothing moved, and there is nothing for it
|
|
9
|
+
* to be proof of. Which of the order's endings a receipt can carry is worked
|
|
10
|
+
* out at `ReceiptOutcomeSchema` below.
|
|
11
|
+
*
|
|
12
|
+
* The price on a receipt is the price the sale went through at, and it stays
|
|
13
|
+
* what it was even after the merchant's price changes.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import { IdentifierSchema, SalePriceSchema, TimestampSchema } from "./primitives.js";
|
|
17
|
+
/**
|
|
18
|
+
* What became of the purchase behind this receipt.
|
|
19
|
+
*
|
|
20
|
+
* The words are the order's own — a receipt saying `pending` where the order
|
|
21
|
+
* said `in_progress` would be two names for one state, and whichever an agent
|
|
22
|
+
* happened to read would look like the whole truth.
|
|
23
|
+
*
|
|
24
|
+
* The set is narrower than the order's, and the reason is what a receipt is: a
|
|
25
|
+
* record of a payment that executed. Work through the endings and six of the
|
|
26
|
+
* ten cannot reach one. `rejected`, `declined` and `expired` all close before
|
|
27
|
+
* any money moves. `cancelled` is the merchant leaving, which for a paid order
|
|
28
|
+
* is a debt and arrives here as `refund_due` instead. `delivered_unpaid` is
|
|
29
|
+
* the case where the merchant produced the goods and the charge came back
|
|
30
|
+
* failed — no payment, so no receipt to carry the outcome.
|
|
31
|
+
*
|
|
32
|
+
* `payment_unresolved` is the one worth arguing rather than asserting, because
|
|
33
|
+
* the purchase behind it can have a verified payment behind it and still end
|
|
34
|
+
* there. It is excluded, and the reason is the receipt's own job. That value
|
|
35
|
+
* means nobody can say whether the buyer was charged; a receipt is the
|
|
36
|
+
* evidence that they were. A receipt carrying it would be a proof of payment
|
|
37
|
+
* whose own outcome says it does not know there was a payment — the one
|
|
38
|
+
* artifact in this contract that cannot hold that sentence. So no receipt is
|
|
39
|
+
* written while the question is open. If the answer arrives and the money did
|
|
40
|
+
* move, the receipt is written then and carries whatever the delivery reached;
|
|
41
|
+
* if it did not, there was never anything to record. That is the same promise
|
|
42
|
+
* the portal makes to the buyer in words: we say so when we learn.
|
|
43
|
+
*
|
|
44
|
+
* That leaves four: paid and still running, paid and delivered, paid and owed
|
|
45
|
+
* back, paid and paid back.
|
|
46
|
+
*
|
|
47
|
+
* What this list does not say is when a receipt is written at all, and a reader
|
|
48
|
+
* should not infer it from here. That is the gateway's, and a gateway that
|
|
49
|
+
* writes one only as goods are released will only ever produce `delivered` —
|
|
50
|
+
* so a consumer must not read the presence of these four as a promise that a
|
|
51
|
+
* receipt exists for every payment that executed.
|
|
52
|
+
*/
|
|
53
|
+
export const ReceiptOutcomeSchema = z.enum(["in_progress", "delivered", "refund_due", "refunded"]);
|
|
54
|
+
export const ReceiptSchema = z.strictObject({
|
|
55
|
+
/**
|
|
56
|
+
* The receipt's own identifier. In the modes where the payment goes first,
|
|
57
|
+
* this is what an agent repeats a purchase by.
|
|
58
|
+
*/
|
|
59
|
+
id: IdentifierSchema,
|
|
60
|
+
/** The order this purchase produced. */
|
|
61
|
+
order_id: IdentifierSchema,
|
|
62
|
+
/** Our catalog identifier for the card that was bought. */
|
|
63
|
+
item_id: IdentifierSchema,
|
|
64
|
+
/** The price the sale went through at, with the moment behind it. */
|
|
65
|
+
price: SalePriceSchema,
|
|
66
|
+
/** The price question the sale came out of, absent when there was none. */
|
|
67
|
+
price_id: IdentifierSchema.optional(),
|
|
68
|
+
/**
|
|
69
|
+
* When the payment executed — which is neither of the moments in `price`. In
|
|
70
|
+
* the synchronous mode the payment is the last step, after the delivery, and
|
|
71
|
+
* on a card with a price check the agent can spend as long as it likes
|
|
72
|
+
* between the price being struck and paying it, so folding any two of the
|
|
73
|
+
* three together would misdate one of them.
|
|
74
|
+
*/
|
|
75
|
+
paid_at: TimestampSchema,
|
|
76
|
+
outcome: ReceiptOutcomeSchema,
|
|
77
|
+
/**
|
|
78
|
+
* Whether the money behind this receipt was real. A receipt is proof of
|
|
79
|
+
* payment, and an unmarked receipt for a test purchase is proof of a payment
|
|
80
|
+
* that never happened.
|
|
81
|
+
*/
|
|
82
|
+
test: z.boolean(),
|
|
83
|
+
});
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What our calls hand back — the successes as well as the failures.
|
|
3
|
+
*
|
|
4
|
+
* None of it travels as an exception. A merchant's integration code has to
|
|
5
|
+
* read these, branch on them and write some of them down, and an exception is
|
|
6
|
+
* the wrong shape for something you are expected to handle rather than to be
|
|
7
|
+
* surprised by. That is a rule about the whole surface, which is why publishing
|
|
8
|
+
* a card and answering for an order share a file even though they are
|
|
9
|
+
* different calls.
|
|
10
|
+
*
|
|
11
|
+
* The words below are wire names, not prose: a merchant's code branches on
|
|
12
|
+
* them, so rewording one is changing the contract.
|
|
13
|
+
*
|
|
14
|
+
* Every one of those answers arrives in one envelope. `ok` is `true` or it is
|
|
15
|
+
* `false` and nothing else says which; a success carries its own fields beside
|
|
16
|
+
* it, and a failure carries `error`. That `ok` is a value and not a key that
|
|
17
|
+
* may or may not be present is the part worth arguing, because the two look
|
|
18
|
+
* alike from inside TypeScript and do not behave alike anywhere else. A key
|
|
19
|
+
* with an object under it reads as false in Python and in PHP — `{"ok": {}}`
|
|
20
|
+
* is falsy in both — so the one idiom an engineer would write says yes to one
|
|
21
|
+
* answer and no to another, and the JSON Schema export exists for exactly that
|
|
22
|
+
* engineer. As a literal it is also a discriminator: it crosses into the export
|
|
23
|
+
* as a `const` on each branch, which a generator can switch on, where
|
|
24
|
+
* "whichever key happens to be present" is something a reader has to work out.
|
|
25
|
+
*
|
|
26
|
+
* Two words carry what went wrong, and they are not two names for one thing.
|
|
27
|
+
* `error` is why a call did not go through: one object, always, with a code to
|
|
28
|
+
* branch on, a sentence to print, and a flag saying whether repeating the call
|
|
29
|
+
* could change the outcome. `problems` is the list of findings about what was
|
|
30
|
+
* sent — the fields at fault — and it rides inside `error` wherever there are
|
|
31
|
+
* any. A call fails for one reason; a document can be wrong in several places
|
|
32
|
+
* at once, and that is the whole of the difference between the singular and the
|
|
33
|
+
* plural here.
|
|
34
|
+
*/
|
|
35
|
+
import { z } from "zod";
|
|
36
|
+
/**
|
|
37
|
+
* How answering for an order can succeed.
|
|
38
|
+
*
|
|
39
|
+
* "Answering" rather than "delivering or refusing", because two of these reach
|
|
40
|
+
* us from a third surface — a handler's own return — rather than from either
|
|
41
|
+
* call. `accepted` is how an asynchronous handler answers while the delivery
|
|
42
|
+
* is still ahead of it, and `purchase_already_closed` belongs to the
|
|
43
|
+
* synchronous mode, where neither `deliver` nor `refuse` exists at all, as the
|
|
44
|
+
* error code `not_applicable_in_mode` says from the other direction.
|
|
45
|
+
*
|
|
46
|
+
* Each one is a different thing for the merchant to do next, which is why none
|
|
47
|
+
* of them collapses into another. `accepted` is a handler taking the order on: the
|
|
48
|
+
* goods are owed and will follow through the separate `deliver` call, and the
|
|
49
|
+
* merchant's own record of the order should say it is under way. It is a
|
|
50
|
+
* success and belongs among these rather than among the error codes, and that
|
|
51
|
+
* placement is the whole of what it does for a merchant: every handler answer
|
|
52
|
+
* is posted to the answer route by the SDK without being asked to, and an
|
|
53
|
+
* integration that reads anything but a success as trouble would otherwise
|
|
54
|
+
* open a case on every asynchronous order it sells.
|
|
55
|
+
*
|
|
56
|
+
* `delivered` is the sale closing. `already_delivered` is their own retry
|
|
57
|
+
* landing twice — safe, and no second delivery is wanted.
|
|
58
|
+
*
|
|
59
|
+
* That one is worth a warning, because the merchant-facing pages say a
|
|
60
|
+
* repeated call returns "the same success" and this returns a different word
|
|
61
|
+
* for it. Both are true of the effect — nothing is delivered twice and nothing
|
|
62
|
+
* is charged twice — but a merchant who reads that sentence and writes
|
|
63
|
+
* `if (result === "delivered")` turns their own safe retry into a failure
|
|
64
|
+
* branch. The answer these words travel in is built so that nobody has to: a
|
|
65
|
+
* consumer branches on `ok` and records the word, which stays right when this
|
|
66
|
+
* list grows another entry.
|
|
67
|
+
*
|
|
68
|
+
* One kind of consumer it does not stay right for, said here because the list
|
|
69
|
+
* has grown once already and will again. A client that checks the answer
|
|
70
|
+
* against its own copy of this schema — our own SDK does, and so does anything
|
|
71
|
+
* generated from the JSON Schema export — reads an unknown word as a document
|
|
72
|
+
* it cannot parse rather than as a success it cannot name, and reports the
|
|
73
|
+
* call as having gone wrong. So a word added here has to reach those clients
|
|
74
|
+
* before the gateway starts sending it. The version handshake would be the
|
|
75
|
+
* place to catch that. The published SDK keeps this schema strict, and every
|
|
76
|
+
* new word moves `CONTRACT_VERSION` before the gateway sends it. An old worker
|
|
77
|
+
* then stops at its version handshake rather than calling a successful answer
|
|
78
|
+
* unreadable after the merchant has already acted on it (ADR-0006).
|
|
79
|
+
*
|
|
80
|
+
* `debt_closed_by_delivery` says the delivery deadline had already passed and
|
|
81
|
+
* the goods went out anyway, closing a debt instead of completing a sale; the
|
|
82
|
+
* merchant may want to know that happened. `refused` is the refusal taking
|
|
83
|
+
* effect. `purchase_already_closed` is the synchronous handler that came back
|
|
84
|
+
* after its deadline: not an error, because nothing went wrong on their side —
|
|
85
|
+
* the work exists and a repeat purchase will collect it, and the only thing to
|
|
86
|
+
* do is write the case down.
|
|
87
|
+
*/
|
|
88
|
+
export declare const ORDER_CALL_RESULTS: readonly ["accepted", "delivered", "already_delivered", "debt_closed_by_delivery", "refused", "purchase_already_closed"];
|
|
89
|
+
export declare const OrderCallResultSchema: z.ZodEnum<{
|
|
90
|
+
refused: "refused";
|
|
91
|
+
delivered: "delivered";
|
|
92
|
+
accepted: "accepted";
|
|
93
|
+
already_delivered: "already_delivered";
|
|
94
|
+
debt_closed_by_delivery: "debt_closed_by_delivery";
|
|
95
|
+
purchase_already_closed: "purchase_already_closed";
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* The error codes those calls answer with.
|
|
99
|
+
*
|
|
100
|
+
* A list of what we promise to mean the same way, not a gate: the code below
|
|
101
|
+
* stays an open string, because an error nobody anticipated has to reach the
|
|
102
|
+
* merchant in its own words rather than be flattened into the nearest of
|
|
103
|
+
* three. `refund_already_settled` — the debt was paid back, so there is
|
|
104
|
+
* nothing left to deliver against. `order_already_closed` — the order reached
|
|
105
|
+
* an ending that no call reopens. `not_applicable_in_mode` — the call does not
|
|
106
|
+
* exist for this card's mode, as refusing separately does not in the
|
|
107
|
+
* synchronous one, where the handler's own answer is the refusal.
|
|
108
|
+
* `delivery_does_not_match_card` — the goods are not the ones the card for
|
|
109
|
+
* this order declares it delivers, so nothing was written down; the message
|
|
110
|
+
* says whether the order still stands or has already ended, and the fields
|
|
111
|
+
* that did not fit are named one by one in the error's `problems`.
|
|
112
|
+
*
|
|
113
|
+
* The fourth is the only one of them a merchant fixes rather than records, and
|
|
114
|
+
* it is the reason it is promised rather than left to the open set. It is
|
|
115
|
+
* marked retryable where the order is still open, and that retry is not the
|
|
116
|
+
* same retry the other three mean: those say "the call may not have reached
|
|
117
|
+
* us, send it again", while this says the call arrived and was understood and
|
|
118
|
+
* the goods in it were wrong. Sending the same delivery again produces the
|
|
119
|
+
* same refusal until the goods change, and a merchant told only "retryable"
|
|
120
|
+
* would loop on it — which is why the code is named and the message says which
|
|
121
|
+
* field is wrong.
|
|
122
|
+
*
|
|
123
|
+
* On an order that has already ended it is not retryable, and the message says
|
|
124
|
+
* the ending. The goods being wrong and the sale being over are both true
|
|
125
|
+
* there, and only the second decides what he can do next: told the order still
|
|
126
|
+
* stood, a merchant would make the goods a second time for a purchase nobody
|
|
127
|
+
* can complete.
|
|
128
|
+
*
|
|
129
|
+
* Adding to this list is safe in a way that adding a success word is not: the
|
|
130
|
+
* code is an open string on the wire, so an older client parses an unfamiliar
|
|
131
|
+
* one and reads it as the failure it is. What it loses is the meaning, which is
|
|
132
|
+
* what this list and the dictionary below carry.
|
|
133
|
+
*/
|
|
134
|
+
export declare const ORDER_CALL_ERROR_CODES: readonly ["refund_already_settled", "order_already_closed", "not_applicable_in_mode", "delivery_does_not_match_card"];
|
|
135
|
+
/**
|
|
136
|
+
* One thing wrong with what was sent, in a place, in a code and in words.
|
|
137
|
+
*
|
|
138
|
+
* This is one finding and never a whole answer. Wherever a call refuses what it
|
|
139
|
+
* was handed, the findings travel as a list of these under `problems` inside
|
|
140
|
+
* the error: a card that could not be published names every field standing
|
|
141
|
+
* between it and the catalog, a delivery that is not what its card declares
|
|
142
|
+
* names the fields that did not fit, and the local check a merchant runs before
|
|
143
|
+
* publishing — `checkCard` in the SDK — answers in this same shape, so a
|
|
144
|
+
* finding read on their own machine and a finding read off the wire need no
|
|
145
|
+
* two readers.
|
|
146
|
+
*
|
|
147
|
+
* The empty path is the part two readers were left to infer differently, so it
|
|
148
|
+
* is said in the exported description as well as here.
|
|
149
|
+
*/
|
|
150
|
+
export declare const ProblemSchema: z.ZodObject<{
|
|
151
|
+
path: z.ZodArray<z.ZodString>;
|
|
152
|
+
code: z.ZodString;
|
|
153
|
+
message: z.ZodString;
|
|
154
|
+
}, z.core.$strict>;
|
|
155
|
+
/**
|
|
156
|
+
* Why a call did not go through: a code to branch on, a sentence to print, and
|
|
157
|
+
* whether repeating it could change the outcome.
|
|
158
|
+
*
|
|
159
|
+
* One shape for every call on the merchant's surface. Publishing a card and
|
|
160
|
+
* delivering an order fail for entirely different reasons, and a merchant who
|
|
161
|
+
* had to learn two shapes for "this did not happen" would be learning the same
|
|
162
|
+
* lesson twice.
|
|
163
|
+
*
|
|
164
|
+
* The flag is the reason this shape exists at all. "The connection dropped,
|
|
165
|
+
* call again — the call is idempotent" and "nothing you do will change this,
|
|
166
|
+
* write the case down" need different code on the merchant's side, and a
|
|
167
|
+
* merchant left to guess turns one of them into a retry loop and the other into
|
|
168
|
+
* an order nobody comes back to. The refund that has already been paid out is
|
|
169
|
+
* the example of the second kind. It is required rather than defaulted for the
|
|
170
|
+
* same reason: both readings of a missing flag are expensive.
|
|
171
|
+
*
|
|
172
|
+
* `problems` is present where the call is refusing what it was handed rather
|
|
173
|
+
* than reporting a state of the world, and it is the field that turns "no" into
|
|
174
|
+
* an edit. It is optional because most failures have nothing to point at: a
|
|
175
|
+
* refund already settled is about the order and not about a field of the
|
|
176
|
+
* request. Where it is there it is never empty, and a call whose whole answer
|
|
177
|
+
* is "refused, and here is nothing" — a publish — requires it.
|
|
178
|
+
*/
|
|
179
|
+
export declare const CallErrorSchema: z.ZodObject<{
|
|
180
|
+
code: z.ZodString;
|
|
181
|
+
message: z.ZodString;
|
|
182
|
+
retryable: z.ZodBoolean;
|
|
183
|
+
problems: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
184
|
+
path: z.ZodArray<z.ZodString>;
|
|
185
|
+
code: z.ZodString;
|
|
186
|
+
message: z.ZodString;
|
|
187
|
+
}, z.core.$strict>>>;
|
|
188
|
+
}, z.core.$strict>;
|
|
189
|
+
/**
|
|
190
|
+
* The code a refused publish comes back under.
|
|
191
|
+
*
|
|
192
|
+
* Promised rather than left to the open set, because it is the one refusal of
|
|
193
|
+
* this surface a merchant meets on their first afternoon, and every one of them
|
|
194
|
+
* writes the branch that reads it.
|
|
195
|
+
*/
|
|
196
|
+
export declare const CARD_REJECTED = "card_rejected";
|
|
197
|
+
/**
|
|
198
|
+
* The answer to publishing a card: the catalog id, or what stands in its way.
|
|
199
|
+
*
|
|
200
|
+
* `ok` says which, as it does on every other call of this surface, and the
|
|
201
|
+
* catalog identifier sits at the top level of the success beside it rather than
|
|
202
|
+
* nested under a word. There is one fact in a successful publish and this is
|
|
203
|
+
* it.
|
|
204
|
+
*
|
|
205
|
+
* The refusal is `CARD_REJECTED` and it is not retryable: publishing the same
|
|
206
|
+
* card again gets the same answer, and what changes the outcome is fixing what
|
|
207
|
+
* the findings name. That is a different thing from the retry a dropped
|
|
208
|
+
* connection asks for, which is why the flag says no here rather than being
|
|
209
|
+
* left for the merchant to infer from the code.
|
|
210
|
+
*/
|
|
211
|
+
export declare const PublishResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
212
|
+
ok: z.ZodLiteral<true>;
|
|
213
|
+
id: z.ZodString;
|
|
214
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
215
|
+
ok: z.ZodLiteral<false>;
|
|
216
|
+
error: z.ZodObject<{
|
|
217
|
+
code: z.ZodString;
|
|
218
|
+
message: z.ZodString;
|
|
219
|
+
retryable: z.ZodBoolean;
|
|
220
|
+
problems: z.ZodArray<z.ZodObject<{
|
|
221
|
+
path: z.ZodArray<z.ZodString>;
|
|
222
|
+
code: z.ZodString;
|
|
223
|
+
message: z.ZodString;
|
|
224
|
+
}, z.core.$strict>>;
|
|
225
|
+
}, z.core.$strict>;
|
|
226
|
+
}, z.core.$strict>], "ok">;
|
|
227
|
+
export type Problem = z.infer<typeof ProblemSchema>;
|
|
228
|
+
export type PublishResult = z.infer<typeof PublishResultSchema>;
|
|
229
|
+
export type OrderCallResult = z.infer<typeof OrderCallResultSchema>;
|
|
230
|
+
export type CallError = z.infer<typeof CallErrorSchema>;
|