@mpgd/platform 0.19.0 → 0.20.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,222 @@
1
+ import type { CommerceCapabilities, LogicalProductId, PlatformEvidenceEnvelope, StarterLogicalProductId } from './index.js';
2
+ /**
3
+ * Commerce v2 client contract types (RFC "Client contract"). This module is
4
+ * typia-free on purpose: `./index` references `CommerceProvider` for
5
+ * `PlatformGateway.commerceV2`, and headless consumers type-check
6
+ * `@mpgd/platform` with `skipLibCheck: false` and no DOM lib, where typia's
7
+ * root declarations do not compile. `./commerce` re-exports everything here
8
+ * and builds the validators and JSON Schemas from these same types.
9
+ *
10
+ * The validation tags below are the structural phantom form typia reads
11
+ * (`'typia.tag'`), mirrored field for field from `@typia/interface` so the
12
+ * generated validators and schemas are identical to the typia aliases;
13
+ * `commerce-contract.test.ts` proves that parity and the schema alignment
14
+ * validator compares the committed files byte for byte.
15
+ */
16
+ type CommerceTag<Props extends object> = {
17
+ 'typia.tag'?: Props;
18
+ };
19
+ /** `tags.MinLength<Value>` */
20
+ export type CommerceMinLength<Value extends number> = CommerceTag<{
21
+ target: 'string';
22
+ kind: 'minLength';
23
+ value: Value;
24
+ validate: `${Value} <= $input.length`;
25
+ exclusive: true;
26
+ schema: {
27
+ minLength: Value;
28
+ };
29
+ }>;
30
+ /** `tags.Format<'date-time'>` */
31
+ export type CommerceDateTimeFormat = CommerceTag<{
32
+ target: 'string';
33
+ kind: 'format';
34
+ value: 'date-time';
35
+ validate: '$importInternal("isFormatDateTime")($input)';
36
+ exclusive: ['format', 'pattern'];
37
+ schema: {
38
+ format: 'date-time';
39
+ };
40
+ }>;
41
+ /** `tags.Type<'uint32'>` */
42
+ export type CommerceUint32 = CommerceTag<{
43
+ target: 'number';
44
+ kind: 'type';
45
+ value: 'uint32';
46
+ validate: '$importInternal("isTypeUint32")($input)';
47
+ exclusive: true;
48
+ schema: {
49
+ type: 'integer';
50
+ minimum: 0;
51
+ };
52
+ }>;
53
+ /** `tags.Type<'int64'>` */
54
+ export type CommerceInt64 = CommerceTag<{
55
+ target: 'bigint' | 'number';
56
+ kind: 'type';
57
+ value: 'int64';
58
+ validate: {
59
+ number: '$importInternal("isTypeInt64")($input)';
60
+ bigint: 'true';
61
+ };
62
+ exclusive: true;
63
+ schema: {
64
+ type: 'integer';
65
+ };
66
+ }>;
67
+ /** `tags.Minimum<Value>` for a number literal */
68
+ export type CommerceMinimum<Value extends number> = CommerceTag<{
69
+ target: 'number';
70
+ kind: 'minimum';
71
+ value: Value;
72
+ validate: `${Value} <= $input`;
73
+ exclusive: ['minimum', 'exclusiveMinimum'];
74
+ schema: {
75
+ minimum: Value;
76
+ };
77
+ }>;
78
+ export type NonEmptyString = string & CommerceMinLength<1>;
79
+ export type IsoTimestamp = string & CommerceDateTimeFormat;
80
+ export type PositiveQuantity = number & CommerceUint32 & CommerceMinimum<1>;
81
+ export type NonNegativeInteger = number & CommerceUint32;
82
+ /**
83
+ * Open store identifier. Reference providers use 'google-play', 'app-store',
84
+ * 'microsoft-store', 'apps-in-toss', 'devvit', and 'verse8'; a consuming
85
+ * project adds its own, for example a credit wallet id.
86
+ */
87
+ export type StoreId = NonEmptyString;
88
+ export type PurchaseKind = 'consumable' | 'durable' | 'subscription';
89
+ /**
90
+ * `LogicalProductId` narrowed to its open string branch and tagged non-empty,
91
+ * so validators and the generated schemas carry `minLength: 1`. Starter ids and
92
+ * plain `LogicalProductId` values remain assignable.
93
+ */
94
+ export type CommerceLogicalProductId = Exclude<LogicalProductId, StarterLogicalProductId> & CommerceMinLength<1>;
95
+ export interface StorePrice {
96
+ readonly formatted: string;
97
+ /** ISO 4217 code or a project-declared code such as a wallet currency. */
98
+ readonly currencyCode: NonEmptyString;
99
+ readonly amountMicros?: number & CommerceInt64;
100
+ }
101
+ export interface StoreOffer {
102
+ readonly offerId: NonEmptyString;
103
+ readonly price: StorePrice;
104
+ readonly title?: string;
105
+ readonly description?: string;
106
+ }
107
+ export interface StoreProduct {
108
+ readonly logicalId: CommerceLogicalProductId;
109
+ readonly store: StoreId;
110
+ readonly storeSku: NonEmptyString;
111
+ readonly kind: PurchaseKind;
112
+ readonly title: string;
113
+ readonly description: string;
114
+ readonly price: StorePrice;
115
+ readonly offers?: readonly StoreOffer[];
116
+ }
117
+ export type StorePurchaseState = 'pending' | 'purchased' | 'revoked';
118
+ export interface StorePurchaseAccountBinding {
119
+ readonly kind: 'obfuscated-account-id' | 'app-account-token' | 'host-identity';
120
+ readonly value?: string;
121
+ }
122
+ export interface StorePurchase {
123
+ readonly store: StoreId;
124
+ /** Store transaction id; a provider derives one when the store has none. */
125
+ readonly transactionId: NonEmptyString;
126
+ readonly originalTransactionId?: NonEmptyString;
127
+ readonly storeSku: NonEmptyString;
128
+ readonly logicalId?: CommerceLogicalProductId;
129
+ readonly quantity: PositiveQuantity;
130
+ readonly state: StorePurchaseState;
131
+ readonly purchasedAt?: IsoTimestamp;
132
+ /** Play purchase token, App Store signed transaction (JWS), or host order id. */
133
+ readonly token: NonEmptyString;
134
+ readonly evidence: PlatformEvidenceEnvelope;
135
+ readonly accountBinding?: StorePurchaseAccountBinding;
136
+ /** Present only for `authority.evidence: 'adapter-settled'`; a reconciler pointer, not a grant. */
137
+ readonly settlement?: {
138
+ readonly ledgerEntryId: NonEmptyString;
139
+ };
140
+ }
141
+ export type PurchaseSource = 'shop' | 'stage_fail' | 'result' | 'event';
142
+ export interface RequestPurchaseInput {
143
+ readonly logicalId: CommerceLogicalProductId;
144
+ readonly idempotencyKey: NonEmptyString;
145
+ readonly source: PurchaseSource;
146
+ readonly offerId?: NonEmptyString;
147
+ /** Integer >= 1. Rejected with ITEM_UNAVAILABLE when the provider does not declare `purchase.quantity`. */
148
+ readonly quantity?: PositiveQuantity;
149
+ }
150
+ export type RequestPurchaseResult = {
151
+ readonly outcome: 'launched';
152
+ } | {
153
+ readonly outcome: 'purchased';
154
+ readonly purchase: StorePurchase;
155
+ } | {
156
+ readonly outcome: 'cancelled' | 'failed';
157
+ readonly error: CommerceErrorInfo;
158
+ };
159
+ export type CommerceErrorCode = 'USER_CANCELLED' | 'OUTCOME_UNKNOWN' | 'ALREADY_OWNED' | 'IN_PROGRESS' | 'ITEM_UNAVAILABLE' | 'NOT_PREPARED' | 'NETWORK' | 'STORE_UNAVAILABLE' | 'CONFIGURATION_REQUIRED' | 'ACTION_REQUIRED' | 'ACCOUNT_BINDING_REQUIRED' | 'INSUFFICIENT_BALANCE' | 'INVALID_RESPONSE' | 'UNKNOWN';
160
+ export interface CommerceErrorInfo {
161
+ readonly code: CommerceErrorCode;
162
+ readonly retryable: boolean;
163
+ /** The store's original code, for example PLAY_BILLING_SERVICE_UNAVAILABLE. */
164
+ readonly storeCode?: string;
165
+ readonly message?: string;
166
+ }
167
+ export type CommerceEvent = {
168
+ readonly type: 'purchaseUpdated';
169
+ readonly purchase: StorePurchase;
170
+ } | {
171
+ readonly type: 'purchaseError';
172
+ readonly logicalId?: CommerceLogicalProductId;
173
+ readonly error: CommerceErrorInfo;
174
+ } | {
175
+ readonly type: 'subscriptionUpdated';
176
+ readonly subscription: ActiveSubscription;
177
+ };
178
+ export type FetchProductsType = 'in-app' | 'subscription' | 'all';
179
+ export interface FetchProductsInput {
180
+ readonly logicalIds?: readonly CommerceLogicalProductId[];
181
+ readonly type?: FetchProductsType;
182
+ }
183
+ export interface GetAvailablePurchasesInput {
184
+ readonly includePending?: boolean;
185
+ }
186
+ export interface FinishTransactionInput {
187
+ readonly transactionId: NonEmptyString;
188
+ readonly ledgerEntryId: NonEmptyString;
189
+ readonly isConsumable: boolean;
190
+ }
191
+ export interface FinishTransactionResult {
192
+ readonly finished: boolean;
193
+ }
194
+ export interface CommerceProvider {
195
+ readonly store: StoreId;
196
+ getCapabilities(): Promise<CommerceCapabilities>;
197
+ fetchProducts(input: FetchProductsInput): Promise<readonly StoreProduct[]>;
198
+ /** Returns `launched` when the result arrives later as a `purchaseUpdated` event. */
199
+ requestPurchase(input: RequestPurchaseInput): Promise<RequestPurchaseResult>;
200
+ /** Purchases the store still reports as unfinished. */
201
+ getAvailablePurchases(input?: GetAvailablePurchasesInput): Promise<readonly StorePurchase[]>;
202
+ /** Required when `lifecycle.finish` is 'client' or 'host'. */
203
+ finishTransaction?(input: FinishTransactionInput): Promise<FinishTransactionResult>;
204
+ /** Asks the store to resynchronize, for example `AppStore.sync`. */
205
+ restorePurchases?(): Promise<void>;
206
+ /** Designed, not implemented by any reference store provider. */
207
+ getActiveSubscriptions?(): Promise<readonly ActiveSubscription[]>;
208
+ /** Events emitted before the first listener are delivered to that listener. */
209
+ subscribe(listener: (event: CommerceEvent) => void): () => void;
210
+ }
211
+ export type ActiveSubscriptionState = 'active' | 'lapsed' | 'revoked';
212
+ export interface ActiveSubscription {
213
+ readonly store: StoreId;
214
+ readonly logicalId: CommerceLogicalProductId;
215
+ readonly subscriptionId: NonEmptyString;
216
+ readonly periodIndex: NonNegativeInteger;
217
+ readonly state: ActiveSubscriptionState;
218
+ readonly startedAt: IsoTimestamp;
219
+ readonly expiresAt: IsoTimestamp;
220
+ readonly autoRenew: boolean;
221
+ }
222
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -16,6 +16,14 @@ export interface CommerceConformanceProfile {
16
16
  readonly purchase?: CommercePurchaseCapabilities;
17
17
  readonly lifecycle?: CommerceLifecycleCapabilities;
18
18
  readonly authority?: CommerceAuthorityCapabilities;
19
+ /**
20
+ * The scenario is finish-owner independent: when a caller-supplied provider
21
+ * runs the vector, the runner derives `journal`, `finishCalls`,
22
+ * `verifyRequests`, and `available` from the provider's declared
23
+ * capabilities instead of this fixture profile (RFC "Conformance vectors",
24
+ * adaptive vectors). The reference harness ignores the flag.
25
+ */
26
+ readonly adaptive?: boolean;
19
27
  }
20
28
  export interface CommerceConformanceCatalogEntry {
21
29
  readonly logicalId: CommerceLogicalProductId;
@@ -178,8 +178,13 @@ const assertCommerceConformanceVectorShape = (() => {
178
178
  path: _path + ".authority",
179
179
  expected: "(CommerceAuthorityCapabilities | undefined)",
180
180
  value: input.authority
181
+ }, _errorFactory)) && (undefined === input.adaptive || "boolean" === typeof input.adaptive || _assertGuard_1._assertGuard(_exceptionable, {
182
+ method: "typia.createAssertEquals",
183
+ path: _path + ".adaptive",
184
+ expected: "(boolean | undefined)",
185
+ value: input.adaptive
181
186
  }, _errorFactory)) && (1 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
182
- if (["store", "purchase", "lifecycle", "authority"].some(prop => key === prop))
187
+ if (["store", "purchase", "lifecycle", "authority", "adaptive"].some(prop => key === prop))
183
188
  return true;
184
189
  const value = input[key];
185
190
  if (undefined === value)
@@ -237,12 +242,12 @@ const assertCommerceConformanceVectorShape = (() => {
237
242
  const _ao11 = (input, _path, _exceptionable = true) => ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
238
243
  method: "typia.createAssertEquals",
239
244
  path: _path + ".logicalId",
240
- expected: "string & MinLength<1>",
245
+ expected: "string & CommerceMinLength<1>",
241
246
  value: input.logicalId
242
247
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
243
248
  method: "typia.createAssertEquals",
244
249
  path: _path + ".logicalId",
245
- expected: "(string & MinLength<1>)",
250
+ expected: "(string & CommerceMinLength<1>)",
246
251
  value: input.logicalId
247
252
  }, _errorFactory)) && ("string" === typeof input.idempotencyKey && (1 <= input.idempotencyKey.length || _assertGuard_1._assertGuard(_exceptionable, {
248
253
  method: "typia.createAssertEquals",
@@ -404,12 +409,12 @@ const assertCommerceConformanceVectorShape = (() => {
404
409
  }, _errorFactory)) && input.logicalIds.every((elem, _index20) => "string" === typeof elem && (1 <= elem.length || _assertGuard_1._assertGuard(_exceptionable, {
405
410
  method: "typia.createAssertEquals",
406
411
  path: _path + ".logicalIds[" + _index20 + "]",
407
- expected: "string & MinLength<1>",
412
+ expected: "string & CommerceMinLength<1>",
408
413
  value: elem
409
414
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
410
415
  method: "typia.createAssertEquals",
411
416
  path: _path + ".logicalIds[" + _index20 + "]",
412
- expected: "(string & MinLength<1>)",
417
+ expected: "(string & CommerceMinLength<1>)",
413
418
  value: elem
414
419
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
415
420
  method: "typia.createAssertEquals",
@@ -442,12 +447,12 @@ const assertCommerceConformanceVectorShape = (() => {
442
447
  }, _errorFactory)) && input.logicalIds.every((elem, _index21) => "string" === typeof elem && (1 <= elem.length || _assertGuard_1._assertGuard(_exceptionable, {
443
448
  method: "typia.createAssertEquals",
444
449
  path: _path + ".logicalIds[" + _index21 + "]",
445
- expected: "string & MinLength<1>",
450
+ expected: "string & CommerceMinLength<1>",
446
451
  value: elem
447
452
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
448
453
  method: "typia.createAssertEquals",
449
454
  path: _path + ".logicalIds[" + _index21 + "]",
450
- expected: "(string & MinLength<1>)",
455
+ expected: "(string & CommerceMinLength<1>)",
451
456
  value: elem
452
457
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
453
458
  method: "typia.createAssertEquals",
@@ -647,12 +652,12 @@ const assertCommerceConformanceVectorShape = (() => {
647
652
  }, _errorFactory)) && (undefined === input.logicalId || "string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
648
653
  method: "typia.createAssertEquals",
649
654
  path: _path + ".logicalId",
650
- expected: "string & MinLength<1>",
655
+ expected: "string & CommerceMinLength<1>",
651
656
  value: input.logicalId
652
657
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
653
658
  method: "typia.createAssertEquals",
654
659
  path: _path + ".logicalId",
655
- expected: "((string & MinLength<1>) | undefined)",
660
+ expected: "((string & CommerceMinLength<1>) | undefined)",
656
661
  value: input.logicalId
657
662
  }, _errorFactory)) && (("object" === typeof input.error && null !== input.error || _assertGuard_1._assertGuard(_exceptionable, {
658
663
  method: "typia.createAssertEquals",
@@ -1023,12 +1028,12 @@ const assertCommerceConformanceVectorShape = (() => {
1023
1028
  }, _errorFactory)) && ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
1024
1029
  method: "typia.createAssertEquals",
1025
1030
  path: _path + ".logicalId",
1026
- expected: "string & MinLength<1>",
1031
+ expected: "string & CommerceMinLength<1>",
1027
1032
  value: input.logicalId
1028
1033
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
1029
1034
  method: "typia.createAssertEquals",
1030
1035
  path: _path + ".logicalId",
1031
- expected: "(string & MinLength<1>)",
1036
+ expected: "(string & CommerceMinLength<1>)",
1032
1037
  value: input.logicalId
1033
1038
  }, _errorFactory)) && (5 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
1034
1039
  if (["actor", "action", "transactionId", "entryId", "logicalId"].some(prop => key === prop))
@@ -1210,22 +1215,22 @@ const assertCommerceConformanceVectorShape = (() => {
1210
1215
  }, _errorFactory)) && ("string" === typeof input.store && (1 <= input.store.length || _assertGuard_1._assertGuard(_exceptionable, {
1211
1216
  method: "typia.createAssertEquals",
1212
1217
  path: _path + ".store",
1213
- expected: "string & MinLength<1>",
1218
+ expected: "string & CommerceMinLength<1>",
1214
1219
  value: input.store
1215
1220
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
1216
1221
  method: "typia.createAssertEquals",
1217
1222
  path: _path + ".store",
1218
- expected: "(string & MinLength<1>)",
1223
+ expected: "(string & CommerceMinLength<1>)",
1219
1224
  value: input.store
1220
1225
  }, _errorFactory)) && ("string" === typeof input.titleId && (1 <= input.titleId.length || _assertGuard_1._assertGuard(_exceptionable, {
1221
1226
  method: "typia.createAssertEquals",
1222
1227
  path: _path + ".titleId",
1223
- expected: "string & MinLength<1>",
1228
+ expected: "string & CommerceMinLength<1>",
1224
1229
  value: input.titleId
1225
1230
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
1226
1231
  method: "typia.createAssertEquals",
1227
1232
  path: _path + ".titleId",
1228
- expected: "(string & MinLength<1>)",
1233
+ expected: "(string & CommerceMinLength<1>)",
1229
1234
  value: input.titleId
1230
1235
  }, _errorFactory)) && (3 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
1231
1236
  if (["channel", "store", "titleId"].some(prop => key === prop))
@@ -1816,12 +1821,12 @@ const assertCommerceConformanceVectorShape = (() => {
1816
1821
  }, _errorFactory)) && ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
1817
1822
  method: "typia.createAssertEquals",
1818
1823
  path: _path + ".logicalId",
1819
- expected: "string & MinLength<1>",
1824
+ expected: "string & CommerceMinLength<1>",
1820
1825
  value: input.logicalId
1821
1826
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
1822
1827
  method: "typia.createAssertEquals",
1823
1828
  path: _path + ".logicalId",
1824
- expected: "(string & MinLength<1>)",
1829
+ expected: "(string & CommerceMinLength<1>)",
1825
1830
  value: input.logicalId
1826
1831
  }, _errorFactory)) && (undefined === input.reverses || "string" === typeof input.reverses && (1 <= input.reverses.length || _assertGuard_1._assertGuard(_exceptionable, {
1827
1832
  method: "typia.createAssertEquals",
@@ -1955,12 +1960,12 @@ const assertCommerceConformanceVectorShape = (() => {
1955
1960
  }, _errorFactory)) && (undefined === input.logicalId || "string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
1956
1961
  method: "typia.createAssertEquals",
1957
1962
  path: _path + ".logicalId",
1958
- expected: "string & MinLength<1>",
1963
+ expected: "string & CommerceMinLength<1>",
1959
1964
  value: input.logicalId
1960
1965
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
1961
1966
  method: "typia.createAssertEquals",
1962
1967
  path: _path + ".logicalId",
1963
- expected: "((string & MinLength<1>) | undefined)",
1968
+ expected: "((string & CommerceMinLength<1>) | undefined)",
1964
1969
  value: input.logicalId
1965
1970
  }, _errorFactory)) && (1 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
1966
1971
  if (["id", "logicalId"].some(prop => key === prop))
@@ -2051,12 +2056,12 @@ const assertCommerceConformanceVectorShape = (() => {
2051
2056
  const _ao5 = (input, _path, _exceptionable = true) => ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
2052
2057
  method: "typia.createAssertEquals",
2053
2058
  path: _path + ".logicalId",
2054
- expected: "string & MinLength<1>",
2059
+ expected: "string & CommerceMinLength<1>",
2055
2060
  value: input.logicalId
2056
2061
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2057
2062
  method: "typia.createAssertEquals",
2058
2063
  path: _path + ".logicalId",
2059
- expected: "(string & MinLength<1>)",
2064
+ expected: "(string & CommerceMinLength<1>)",
2060
2065
  value: input.logicalId
2061
2066
  }, _errorFactory)) && ("consumable" === input.kind || "durable" === input.kind || "subscription" === input.kind || _assertGuard_1._assertGuard(_exceptionable, {
2062
2067
  method: "typia.createAssertEquals",
@@ -2104,12 +2109,12 @@ const assertCommerceConformanceVectorShape = (() => {
2104
2109
  }, _errorFactory)) && ("string" === typeof input.titleId && (1 <= input.titleId.length || _assertGuard_1._assertGuard(_exceptionable, {
2105
2110
  method: "typia.createAssertEquals",
2106
2111
  path: _path + ".titleId",
2107
- expected: "string & MinLength<1>",
2112
+ expected: "string & CommerceMinLength<1>",
2108
2113
  value: input.titleId
2109
2114
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2110
2115
  method: "typia.createAssertEquals",
2111
2116
  path: _path + ".titleId",
2112
- expected: "(string & MinLength<1>)",
2117
+ expected: "(string & CommerceMinLength<1>)",
2113
2118
  value: input.titleId
2114
2119
  }, _errorFactory)) && (2 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
2115
2120
  if (["kind", "titleId"].some(prop => key === prop))
@@ -2220,12 +2225,12 @@ const assertCommerceConformanceVectorShape = (() => {
2220
2225
  }, _errorFactory)) && ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
2221
2226
  method: "typia.createAssertEquals",
2222
2227
  path: _path + ".logicalId",
2223
- expected: "string & MinLength<1>",
2228
+ expected: "string & CommerceMinLength<1>",
2224
2229
  value: input.logicalId
2225
2230
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2226
2231
  method: "typia.createAssertEquals",
2227
2232
  path: _path + ".logicalId",
2228
- expected: "(string & MinLength<1>)",
2233
+ expected: "(string & CommerceMinLength<1>)",
2229
2234
  value: input.logicalId
2230
2235
  }, _errorFactory)) && ("number" === typeof input.periodIndex && (_isTypeUint32_1._isTypeUint32(input.periodIndex) || _assertGuard_1._assertGuard(_exceptionable, {
2231
2236
  method: "typia.createAssertEquals",
@@ -2268,12 +2273,12 @@ const assertCommerceConformanceVectorShape = (() => {
2268
2273
  const _ao56 = (input, _path, _exceptionable = true) => ("string" === typeof input.logicalId && (1 <= input.logicalId.length || _assertGuard_1._assertGuard(_exceptionable, {
2269
2274
  method: "typia.createAssertEquals",
2270
2275
  path: _path + ".logicalId",
2271
- expected: "string & MinLength<1>",
2276
+ expected: "string & CommerceMinLength<1>",
2272
2277
  value: input.logicalId
2273
2278
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2274
2279
  method: "typia.createAssertEquals",
2275
2280
  path: _path + ".logicalId",
2276
- expected: "(string & MinLength<1>)",
2281
+ expected: "(string & CommerceMinLength<1>)",
2277
2282
  value: input.logicalId
2278
2283
  }, _errorFactory)) && (undefined === input.periodIndex || "number" === typeof input.periodIndex && (_isTypeUint32_1._isTypeUint32(input.periodIndex) || _assertGuard_1._assertGuard(_exceptionable, {
2279
2284
  method: "typia.createAssertEquals",
@@ -2331,12 +2336,12 @@ const assertCommerceConformanceVectorShape = (() => {
2331
2336
  }, _errorFactory)) && ("string" === typeof input.period && (1 <= input.period.length || _assertGuard_1._assertGuard(_exceptionable, {
2332
2337
  method: "typia.createAssertEquals",
2333
2338
  path: _path + ".period",
2334
- expected: "string & MinLength<1>",
2339
+ expected: "string & CommerceMinLength<1>",
2335
2340
  value: input.period
2336
2341
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2337
2342
  method: "typia.createAssertEquals",
2338
2343
  path: _path + ".period",
2339
- expected: "(string & MinLength<1>)",
2344
+ expected: "(string & CommerceMinLength<1>)",
2340
2345
  value: input.period
2341
2346
  }, _errorFactory)) && (3 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
2342
2347
  if (["scope", "price", "period"].some(prop => key === prop))
@@ -2354,12 +2359,12 @@ const assertCommerceConformanceVectorShape = (() => {
2354
2359
  const _ao7 = (input, _path, _exceptionable = true) => ("string" === typeof input.currency && (1 <= input.currency.length || _assertGuard_1._assertGuard(_exceptionable, {
2355
2360
  method: "typia.createAssertEquals",
2356
2361
  path: _path + ".currency",
2357
- expected: "string & MinLength<1>",
2362
+ expected: "string & CommerceMinLength<1>",
2358
2363
  value: input.currency
2359
2364
  }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
2360
2365
  method: "typia.createAssertEquals",
2361
2366
  path: _path + ".currency",
2362
- expected: "(string & MinLength<1>)",
2367
+ expected: "(string & CommerceMinLength<1>)",
2363
2368
  value: input.currency
2364
2369
  }, _errorFactory)) && ("number" === typeof input.amount && (0 < input.amount || _assertGuard_1._assertGuard(_exceptionable, {
2365
2370
  method: "typia.createAssertEquals",
@@ -2536,8 +2541,8 @@ const assertCommerceConformanceVectorShape = (() => {
2536
2541
  return true;
2537
2542
  return false;
2538
2543
  }));
2539
- const _io1 = (input, _exceptionable = true) => "string" === typeof input.store && 1 <= input.store.length && (undefined === input.purchase || "object" === typeof input.purchase && null !== input.purchase && _io2(input.purchase, true && _exceptionable)) && (undefined === input.lifecycle || "object" === typeof input.lifecycle && null !== input.lifecycle && _io3(input.lifecycle, true && _exceptionable)) && (undefined === input.authority || "object" === typeof input.authority && null !== input.authority && _io4(input.authority, true && _exceptionable)) && (1 === Object.keys(input).length || Object.keys(input).every(key => {
2540
- if (["store", "purchase", "lifecycle", "authority"].some(prop => key === prop))
2544
+ const _io1 = (input, _exceptionable = true) => "string" === typeof input.store && 1 <= input.store.length && (undefined === input.purchase || "object" === typeof input.purchase && null !== input.purchase && _io2(input.purchase, true && _exceptionable)) && (undefined === input.lifecycle || "object" === typeof input.lifecycle && null !== input.lifecycle && _io3(input.lifecycle, true && _exceptionable)) && (undefined === input.authority || "object" === typeof input.authority && null !== input.authority && _io4(input.authority, true && _exceptionable)) && (undefined === input.adaptive || "boolean" === typeof input.adaptive) && (1 === Object.keys(input).length || Object.keys(input).every(key => {
2545
+ if (["store", "purchase", "lifecycle", "authority", "adaptive"].some(prop => key === prop))
2541
2546
  return true;
2542
2547
  const value = input[key];
2543
2548
  if (undefined === value)
@@ -1,5 +1,6 @@
1
1
  import { type tags } from 'typia';
2
- import { PlatformOperationError, type CommerceAdapter, type CommerceCapabilities, type LogicalProductId, type PlatformEvidenceEnvelope, type StarterLogicalProductId } from './index.js';
2
+ import { PlatformOperationError, type CommerceAdapter, type CommerceCapabilities } from './index.js';
3
+ import type { ActiveSubscription, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, FetchProductsInput, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, IsoTimestamp, NonEmptyString, NonNegativeInteger, PurchaseKind, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreProduct, StorePurchase } from './commerce-contract.js';
3
4
  export { createUnsupportedCommerceCapabilities, deriveLegacyCommerceCapabilities, type LegacyCommerceCapabilities, } from './commerce-capabilities.js';
4
5
  export type { CommerceAccountBindingPolicy, CommerceAuthorityCapabilities, CommerceCapabilities, CommerceCatalogCapabilities, CommerceEvidenceAuthority, CommerceFinishOwner, CommerceLifecycleCapabilities, CommercePurchaseCapabilities, } from './index.js';
5
6
  /**
@@ -10,157 +11,14 @@ export type { CommerceAccountBindingPolicy, CommerceAuthorityCapabilities, Comme
10
11
  */
11
12
  export declare const commerceProtocolVersion: '2.0.0-draft.1';
12
13
  export declare const commerceProtocol: 'mpgd.commerce.v2';
13
- type NonEmptyString = string & tags.MinLength<1>;
14
- type IsoTimestamp = string & tags.Format<'date-time'>;
15
- type PositiveQuantity = number & tags.Type<'uint32'> & tags.Minimum<1>;
16
- type NonNegativeInteger = number & tags.Type<'uint32'>;
17
- /**
18
- * Open store identifier. Reference providers use 'google-play', 'app-store',
19
- * 'microsoft-store', 'apps-in-toss', 'devvit', and 'verse8'; a consuming
20
- * project adds its own, for example a credit wallet id.
21
- */
22
- export type StoreId = NonEmptyString;
23
- export type PurchaseKind = 'consumable' | 'durable' | 'subscription';
24
- /**
25
- * `LogicalProductId` narrowed to its open string branch and tagged non-empty,
26
- * so validators and the generated schemas carry `minLength: 1`. Starter ids and
27
- * plain `LogicalProductId` values remain assignable.
28
- */
29
- export type CommerceLogicalProductId = Exclude<LogicalProductId, StarterLogicalProductId> & tags.MinLength<1>;
30
- export interface StorePrice {
31
- readonly formatted: string;
32
- /** ISO 4217 code or a project-declared code such as a wallet currency. */
33
- readonly currencyCode: NonEmptyString;
34
- readonly amountMicros?: number & tags.Type<'int64'>;
35
- }
36
- export interface StoreOffer {
37
- readonly offerId: NonEmptyString;
38
- readonly price: StorePrice;
39
- readonly title?: string;
40
- readonly description?: string;
41
- }
42
- export interface StoreProduct {
43
- readonly logicalId: CommerceLogicalProductId;
44
- readonly store: StoreId;
45
- readonly storeSku: NonEmptyString;
46
- readonly kind: PurchaseKind;
47
- readonly title: string;
48
- readonly description: string;
49
- readonly price: StorePrice;
50
- readonly offers?: readonly StoreOffer[];
51
- }
52
- export type StorePurchaseState = 'pending' | 'purchased' | 'revoked';
53
- export interface StorePurchaseAccountBinding {
54
- readonly kind: 'obfuscated-account-id' | 'app-account-token' | 'host-identity';
55
- readonly value?: string;
56
- }
57
- export interface StorePurchase {
58
- readonly store: StoreId;
59
- /** Store transaction id; a provider derives one when the store has none. */
60
- readonly transactionId: NonEmptyString;
61
- readonly originalTransactionId?: NonEmptyString;
62
- readonly storeSku: NonEmptyString;
63
- readonly logicalId?: CommerceLogicalProductId;
64
- readonly quantity: PositiveQuantity;
65
- readonly state: StorePurchaseState;
66
- readonly purchasedAt?: IsoTimestamp;
67
- /** Play purchase token, App Store signed transaction (JWS), or host order id. */
68
- readonly token: NonEmptyString;
69
- readonly evidence: PlatformEvidenceEnvelope;
70
- readonly accountBinding?: StorePurchaseAccountBinding;
71
- /** Present only for `authority.evidence: 'adapter-settled'`; a reconciler pointer, not a grant. */
72
- readonly settlement?: {
73
- readonly ledgerEntryId: NonEmptyString;
74
- };
75
- }
76
- export type PurchaseSource = 'shop' | 'stage_fail' | 'result' | 'event';
77
- export interface RequestPurchaseInput {
78
- readonly logicalId: CommerceLogicalProductId;
79
- readonly idempotencyKey: NonEmptyString;
80
- readonly source: PurchaseSource;
81
- readonly offerId?: NonEmptyString;
82
- /** Integer >= 1. Rejected with ITEM_UNAVAILABLE when the provider does not declare `purchase.quantity`. */
83
- readonly quantity?: PositiveQuantity;
84
- }
85
- export type RequestPurchaseResult = {
86
- readonly outcome: 'launched';
87
- } | {
88
- readonly outcome: 'purchased';
89
- readonly purchase: StorePurchase;
90
- } | {
91
- readonly outcome: 'cancelled' | 'failed';
92
- readonly error: CommerceErrorInfo;
93
- };
94
- export type CommerceErrorCode = 'USER_CANCELLED' | 'OUTCOME_UNKNOWN' | 'ALREADY_OWNED' | 'IN_PROGRESS' | 'ITEM_UNAVAILABLE' | 'NOT_PREPARED' | 'NETWORK' | 'STORE_UNAVAILABLE' | 'CONFIGURATION_REQUIRED' | 'ACTION_REQUIRED' | 'ACCOUNT_BINDING_REQUIRED' | 'INSUFFICIENT_BALANCE' | 'INVALID_RESPONSE' | 'UNKNOWN';
14
+ export type { ActiveSubscription, ActiveSubscriptionState, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, FetchProductsInput, FetchProductsType, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, PurchaseKind, PurchaseSource, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreOffer, StorePrice, StoreProduct, StorePurchase, StorePurchaseAccountBinding, StorePurchaseState, } from './commerce-contract.js';
95
15
  export declare const commerceErrorCodes: readonly ["USER_CANCELLED", "OUTCOME_UNKNOWN", "ALREADY_OWNED", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NOT_PREPARED", "NETWORK", "STORE_UNAVAILABLE", "CONFIGURATION_REQUIRED", "ACTION_REQUIRED", "ACCOUNT_BINDING_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "UNKNOWN"];
96
- export interface CommerceErrorInfo {
97
- readonly code: CommerceErrorCode;
98
- readonly retryable: boolean;
99
- /** The store's original code, for example PLAY_BILLING_SERVICE_UNAVAILABLE. */
100
- readonly storeCode?: string;
101
- readonly message?: string;
102
- }
103
- export type CommerceEvent = {
104
- readonly type: 'purchaseUpdated';
105
- readonly purchase: StorePurchase;
106
- } | {
107
- readonly type: 'purchaseError';
108
- readonly logicalId?: CommerceLogicalProductId;
109
- readonly error: CommerceErrorInfo;
110
- } | {
111
- readonly type: 'subscriptionUpdated';
112
- readonly subscription: ActiveSubscription;
113
- };
114
16
  /** Bridge event envelope; `sequence` is per session and starts at 0. */
115
17
  export interface CommerceEventEnvelope {
116
18
  readonly protocol: typeof commerceProtocol;
117
19
  readonly sequence: NonNegativeInteger;
118
20
  readonly event: CommerceEvent;
119
21
  }
120
- export type FetchProductsType = 'in-app' | 'subscription' | 'all';
121
- export interface FetchProductsInput {
122
- readonly logicalIds?: readonly CommerceLogicalProductId[];
123
- readonly type?: FetchProductsType;
124
- }
125
- export interface GetAvailablePurchasesInput {
126
- readonly includePending?: boolean;
127
- }
128
- export interface FinishTransactionInput {
129
- readonly transactionId: NonEmptyString;
130
- readonly ledgerEntryId: NonEmptyString;
131
- readonly isConsumable: boolean;
132
- }
133
- export interface FinishTransactionResult {
134
- readonly finished: boolean;
135
- }
136
- export interface CommerceProvider {
137
- readonly store: StoreId;
138
- getCapabilities(): Promise<CommerceCapabilities>;
139
- fetchProducts(input: FetchProductsInput): Promise<readonly StoreProduct[]>;
140
- /** Returns `launched` when the result arrives later as a `purchaseUpdated` event. */
141
- requestPurchase(input: RequestPurchaseInput): Promise<RequestPurchaseResult>;
142
- /** Purchases the store still reports as unfinished. */
143
- getAvailablePurchases(input?: GetAvailablePurchasesInput): Promise<readonly StorePurchase[]>;
144
- /** Required when `lifecycle.finish` is 'client' or 'host'. */
145
- finishTransaction?(input: FinishTransactionInput): Promise<FinishTransactionResult>;
146
- /** Asks the store to resynchronize, for example `AppStore.sync`. */
147
- restorePurchases?(): Promise<void>;
148
- /** Designed, not implemented by any reference store provider. */
149
- getActiveSubscriptions?(): Promise<readonly ActiveSubscription[]>;
150
- /** Events emitted before the first listener are delivered to that listener. */
151
- subscribe(listener: (event: CommerceEvent) => void): () => void;
152
- }
153
- export type ActiveSubscriptionState = 'active' | 'lapsed' | 'revoked';
154
- export interface ActiveSubscription {
155
- readonly store: StoreId;
156
- readonly logicalId: CommerceLogicalProductId;
157
- readonly subscriptionId: NonEmptyString;
158
- readonly periodIndex: NonNegativeInteger;
159
- readonly state: ActiveSubscriptionState;
160
- readonly startedAt: IsoTimestamp;
161
- readonly expiresAt: IsoTimestamp;
162
- readonly autoRenew: boolean;
163
- }
164
22
  export type CommerceBillingAuthority = 'store' | 'host';
165
23
  export type CreditMembershipScope = 'title' | 'platform';
166
24
  export interface CreditPrice {