@mpgd/platform 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,269 @@
1
+ import { type tags } from 'typia';
2
+ import type { ActiveSubscriptionState, CommerceAuthorityCapabilities, CommerceBillingAuthority, CommerceErrorCode, CommerceLifecycleCapabilities, CommerceLogicalProductId, CommercePurchaseCapabilities, CommercePurchaseState, CreditLotOrigin, CreditLotSpendScope, CreditMembershipTerms, PurchaseKind, PurchaseSource, StorePurchaseState } from './commerce.js';
3
+ /**
4
+ * Conformance vector format for docs/specs/commerce/vectors/*.json. A3 adds
5
+ * the runner; A2 fixes the file shape so every provider and the reference
6
+ * runtime read the same fixtures. Step inputs are fixture shorthand: the
7
+ * runner fills the profile's store, quantity 1, request source `shop`, and
8
+ * fake evidence before calling the typed provider.
9
+ */
10
+ type NonEmptyString = string & tags.MinLength<1>;
11
+ type IsoTimestamp = string & tags.Format<'date-time'>;
12
+ type NonNegativeInteger = number & tags.Type<'uint32'>;
13
+ export interface CommerceConformanceProfile {
14
+ readonly store: NonEmptyString;
15
+ /** Omitted blocks default to all supported. */
16
+ readonly purchase?: CommercePurchaseCapabilities;
17
+ readonly lifecycle?: CommerceLifecycleCapabilities;
18
+ readonly authority?: CommerceAuthorityCapabilities;
19
+ }
20
+ export interface CommerceConformanceCatalogEntry {
21
+ readonly logicalId: CommerceLogicalProductId;
22
+ readonly kind: PurchaseKind;
23
+ readonly storeSku: NonEmptyString;
24
+ /** Membership terms for credit-funded subscription products. */
25
+ readonly membership?: CreditMembershipTerms;
26
+ }
27
+ export interface CommerceConformanceWallet {
28
+ readonly currencies: readonly NonEmptyString[] & tags.MinItems<1>;
29
+ readonly billingAuthority: CommerceBillingAuthority;
30
+ }
31
+ /** Fixture purchase; `store`, `quantity`, and `evidence` come from the profile. */
32
+ export interface CommerceConformancePurchaseFixture {
33
+ readonly transactionId: NonEmptyString;
34
+ readonly storeSku: NonEmptyString;
35
+ readonly token: NonEmptyString;
36
+ readonly state: StorePurchaseState;
37
+ readonly originalTransactionId?: NonEmptyString;
38
+ readonly purchasedAt?: IsoTimestamp;
39
+ readonly settlement?: {
40
+ readonly ledgerEntryId: NonEmptyString;
41
+ };
42
+ }
43
+ /** Explicit normalized class; the runner never guesses it from `storeCode`. */
44
+ export interface CommerceConformanceErrorFixture {
45
+ readonly code: CommerceErrorCode;
46
+ readonly retryable: boolean;
47
+ readonly storeCode?: string;
48
+ }
49
+ /** Partial expectation; omitted fields are not assertions. */
50
+ export interface CommerceConformanceErrorExpectation {
51
+ readonly code: CommerceErrorCode;
52
+ readonly retryable?: boolean;
53
+ readonly storeCode?: string;
54
+ }
55
+ export type CommerceConformanceRequestResultFixture = {
56
+ readonly outcome: 'launched';
57
+ } | {
58
+ readonly outcome: 'purchased';
59
+ readonly purchase: CommerceConformancePurchaseFixture;
60
+ } | {
61
+ readonly outcome: 'cancelled' | 'failed';
62
+ readonly error: CommerceConformanceErrorFixture;
63
+ };
64
+ export type CommerceConformanceFinishResultFixture = {
65
+ readonly finished: boolean;
66
+ } | {
67
+ readonly error: CommerceErrorCode;
68
+ };
69
+ export interface CommerceConformanceVerifyDecision {
70
+ readonly status: 'granted' | 'pending' | 'rejected';
71
+ readonly ledgerEntryId?: NonEmptyString;
72
+ readonly finalization?: 'pending' | 'completed';
73
+ readonly alreadyProcessed?: boolean;
74
+ }
75
+ export interface CommerceConformanceLotFixture {
76
+ readonly ledgerEntryId: NonEmptyString;
77
+ readonly currency: NonEmptyString;
78
+ readonly amount: number & tags.ExclusiveMinimum<0>;
79
+ readonly origin: CreditLotOrigin;
80
+ readonly createdAt: IsoTimestamp;
81
+ readonly expiresAt?: IsoTimestamp;
82
+ }
83
+ export interface CommerceConformanceSpendInput {
84
+ readonly titleId: NonEmptyString;
85
+ readonly currency: NonEmptyString;
86
+ readonly amount: number & tags.ExclusiveMinimum<0>;
87
+ readonly idempotencyKey: NonEmptyString;
88
+ }
89
+ export interface CommerceConformanceDebitExpectation {
90
+ readonly lotId: NonEmptyString;
91
+ readonly amount: number & tags.ExclusiveMinimum<0>;
92
+ }
93
+ export interface CommerceConformanceSpendExpectation {
94
+ readonly status: 'debited' | 'rejected';
95
+ readonly debits?: readonly CommerceConformanceDebitExpectation[];
96
+ readonly alreadyProcessed?: boolean;
97
+ readonly error?: CommerceConformanceErrorExpectation;
98
+ }
99
+ export interface CommerceConformanceRequestPurchaseExpectation {
100
+ readonly outcome: 'launched' | 'purchased' | 'cancelled' | 'failed';
101
+ readonly error?: CommerceConformanceErrorExpectation;
102
+ }
103
+ export interface CommerceConformanceFetchProductsExpectation {
104
+ readonly logicalIds: readonly CommerceLogicalProductId[];
105
+ }
106
+ export type CommerceConformanceStep = {
107
+ readonly actor: 'runtime';
108
+ readonly action: 'start' | 'stop' | 'reconcile';
109
+ } | {
110
+ readonly actor: 'game';
111
+ readonly action: 'requestPurchase';
112
+ readonly input: {
113
+ readonly logicalId: CommerceLogicalProductId;
114
+ readonly idempotencyKey: NonEmptyString;
115
+ readonly source?: PurchaseSource;
116
+ readonly offerId?: NonEmptyString;
117
+ readonly quantity?: number & tags.Type<'uint32'> & tags.Minimum<1>;
118
+ };
119
+ readonly returns?: CommerceConformanceRequestPurchaseExpectation;
120
+ } | {
121
+ readonly actor: 'game';
122
+ readonly action: 'fetchProducts';
123
+ readonly input?: {
124
+ readonly logicalIds?: readonly CommerceLogicalProductId[];
125
+ readonly type?: 'in-app' | 'subscription' | 'all';
126
+ };
127
+ readonly returns?: CommerceConformanceFetchProductsExpectation;
128
+ } | {
129
+ readonly actor: 'store';
130
+ readonly action: 'complete' | 'update';
131
+ readonly purchase: CommerceConformancePurchaseFixture;
132
+ } | {
133
+ readonly actor: 'store';
134
+ readonly action: 'error';
135
+ readonly logicalId?: CommerceLogicalProductId;
136
+ readonly error: CommerceConformanceErrorFixture;
137
+ } | {
138
+ readonly actor: 'store';
139
+ readonly action: 'queueRequest';
140
+ readonly result: CommerceConformanceRequestResultFixture;
141
+ } | {
142
+ readonly actor: 'store';
143
+ readonly action: 'queueFinish';
144
+ readonly result: CommerceConformanceFinishResultFixture;
145
+ } | {
146
+ readonly actor: 'backend';
147
+ readonly action: 'queueVerify';
148
+ readonly decision: CommerceConformanceVerifyDecision;
149
+ } | {
150
+ readonly actor: 'backend';
151
+ readonly action: 'push';
152
+ readonly transactionId: NonEmptyString;
153
+ readonly entryId: NonEmptyString;
154
+ readonly logicalId: CommerceLogicalProductId;
155
+ } | {
156
+ readonly actor: 'backend';
157
+ readonly action: 'revoke';
158
+ readonly ledgerEntryId: NonEmptyString;
159
+ readonly entryId: NonEmptyString;
160
+ readonly reason: NonEmptyString;
161
+ } | {
162
+ readonly actor: 'wallet';
163
+ readonly action: 'creditFromGrant';
164
+ readonly lot: CommerceConformanceLotFixture;
165
+ } | {
166
+ readonly actor: 'wallet';
167
+ readonly action: 'spend';
168
+ readonly input: CommerceConformanceSpendInput;
169
+ readonly returns?: CommerceConformanceSpendExpectation;
170
+ } | {
171
+ readonly actor: 'wallet';
172
+ readonly action: 'renewDue';
173
+ } | {
174
+ readonly actor: 'clock';
175
+ readonly action: 'set';
176
+ readonly at: IsoTimestamp;
177
+ };
178
+ export type CommerceConformanceActor = CommerceConformanceStep['actor'];
179
+ export type CommerceConformanceAction = CommerceConformanceStep['action'];
180
+ export interface CommerceConformanceVerifyRequestExpectation {
181
+ readonly idempotencyKey: NonEmptyString;
182
+ readonly store: NonEmptyString;
183
+ readonly transactionId: NonEmptyString;
184
+ readonly token: NonEmptyString;
185
+ }
186
+ export interface CommerceConformanceLedgerEntryExpectation {
187
+ readonly entryId: NonEmptyString;
188
+ readonly type: 'grant' | 'revoke' | 'period';
189
+ readonly logicalId: CommerceLogicalProductId;
190
+ /** The grant a `revoke` entry reverses. */
191
+ readonly reverses?: NonEmptyString;
192
+ readonly reason?: NonEmptyString;
193
+ }
194
+ export interface CommerceConformanceFinishCallExpectation {
195
+ readonly by: 'client' | 'host';
196
+ readonly transactionId: NonEmptyString;
197
+ readonly ledgerEntryId: NonEmptyString;
198
+ readonly isConsumable: boolean;
199
+ readonly result: 'finished' | CommerceErrorCode;
200
+ }
201
+ export interface CommerceConformanceAvailableExpectation {
202
+ readonly transactionId: NonEmptyString;
203
+ readonly storeSku?: NonEmptyString;
204
+ readonly state?: StorePurchaseState;
205
+ }
206
+ export interface CommerceConformanceEntitlementExpectation {
207
+ readonly id: NonEmptyString;
208
+ readonly logicalId?: CommerceLogicalProductId;
209
+ }
210
+ export interface CommerceConformanceLotExpectation {
211
+ readonly lotId: NonEmptyString;
212
+ readonly currency?: NonEmptyString;
213
+ readonly amount?: number & tags.ExclusiveMinimum<0>;
214
+ readonly remaining: number & tags.Minimum<0>;
215
+ readonly origin?: CreditLotOrigin;
216
+ readonly spendScope?: CreditLotSpendScope;
217
+ }
218
+ export interface CommerceConformanceScheduledDebitExpectation {
219
+ readonly idempotencyKey: NonEmptyString;
220
+ readonly lotId: NonEmptyString;
221
+ readonly amount: number & tags.ExclusiveMinimum<0>;
222
+ }
223
+ export type CommerceConformanceSubscriptionEventType = 'subscriptionStarted' | 'subscriptionRenewed' | 'subscriptionLapsed' | 'subscriptionRevoked';
224
+ export interface CommerceConformanceSubscriptionEventExpectation {
225
+ readonly type: CommerceConformanceSubscriptionEventType;
226
+ readonly logicalId: CommerceLogicalProductId;
227
+ readonly periodIndex: NonNegativeInteger;
228
+ readonly expiresAt: IsoTimestamp;
229
+ readonly reason?: CommerceErrorCode;
230
+ }
231
+ export interface CommerceConformanceActiveSubscriptionExpectation {
232
+ readonly logicalId: CommerceLogicalProductId;
233
+ readonly periodIndex?: NonNegativeInteger;
234
+ readonly state?: ActiveSubscriptionState;
235
+ readonly expiresAt?: IsoTimestamp;
236
+ }
237
+ export interface CommerceConformanceExpectation {
238
+ /** Full state sequence per journal key. */
239
+ readonly journal?: Readonly<Record<string, readonly CommercePurchaseState[]>>;
240
+ readonly verifyRequests?: readonly CommerceConformanceVerifyRequestExpectation[];
241
+ readonly ledger?: readonly CommerceConformanceLedgerEntryExpectation[];
242
+ readonly finishCalls?: readonly CommerceConformanceFinishCallExpectation[];
243
+ readonly available?: readonly CommerceConformanceAvailableExpectation[];
244
+ readonly entitlements?: readonly CommerceConformanceEntitlementExpectation[];
245
+ readonly lots?: readonly CommerceConformanceLotExpectation[];
246
+ /** Spendable balance per title and currency. */
247
+ readonly balances?: Readonly<Record<string, Readonly<Record<string, number>>>>;
248
+ readonly debits?: readonly CommerceConformanceScheduledDebitExpectation[];
249
+ readonly events?: readonly CommerceConformanceSubscriptionEventExpectation[];
250
+ readonly activeSubscriptions?: readonly CommerceConformanceActiveSubscriptionExpectation[];
251
+ readonly purchaseUiOpened?: NonNegativeInteger;
252
+ }
253
+ export interface CommerceConformanceVector {
254
+ /** Equals the file name without `.json`. */
255
+ readonly vector: string & tags.Pattern<'^[a-z0-9]+(?:-[a-z0-9]+)*$'>;
256
+ readonly protocol: NonEmptyString;
257
+ readonly summary: NonEmptyString;
258
+ readonly profile: CommerceConformanceProfile;
259
+ readonly catalog?: readonly CommerceConformanceCatalogEntry[];
260
+ readonly wallet?: CommerceConformanceWallet;
261
+ readonly steps: readonly CommerceConformanceStep[] & tags.MinItems<1>;
262
+ readonly expect: CommerceConformanceExpectation;
263
+ }
264
+ /** Validates one vector file. Catalog logical ids must be unique. */
265
+ export declare function assertCommerceConformanceVector(input: unknown): CommerceConformanceVector;
266
+ export declare function isCommerceConformanceVector(input: unknown): input is CommerceConformanceVector;
267
+ /** The vector name a file at `path` must declare. */
268
+ export declare function commerceConformanceVectorNameOf(path: string): string;
269
+ export {};