@mpgd/target-config 0.15.1 → 0.16.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.
@@ -36,6 +36,7 @@ export interface EffectiveAdPlacementConfig {
36
36
  }
37
37
  export interface EffectiveMonetizationConfig {
38
38
  readonly iap: boolean;
39
+ readonly subscriptions?: boolean;
39
40
  readonly products: readonly EffectiveProductConfig[];
40
41
  }
41
42
  export interface EffectiveAdsConfig {
package/dist/effective.js CHANGED
@@ -3,6 +3,7 @@ import { adPlacementFeatureFor, assertTargetIntegrationRuntimeBounds, } from './
3
3
  export const defaultLeaderboardId = 'default';
4
4
  const disabledAuthoritativeMonetization = {
5
5
  iap: false,
6
+ subscriptions: false,
6
7
  bannerAds: false,
7
8
  rewardedAds: false,
8
9
  interstitialAds: false,
@@ -42,6 +43,9 @@ export function createEffectiveTargetConfig(input) {
42
43
  },
43
44
  monetization: {
44
45
  iap: config.monetization.iap,
46
+ subscriptions: config.features.iap
47
+ && config.features.subscriptions === true
48
+ && config.monetization.iap,
45
49
  products,
46
50
  },
47
51
  ads: {
@@ -111,7 +115,7 @@ export function getEffectiveAdPlacementConfig(config, placementId) {
111
115
  }
112
116
  function createEffectiveProductConfig(target, config, product) {
113
117
  const platformProductId = resolveProductPlatformId(product, target);
114
- const reason = effectiveProductReason(config.runtime, config.features.iap, product, platformProductId);
118
+ const reason = effectiveProductReason(config.runtime, config.features.iap && (product.type !== 'subscription' || config.features.subscriptions === true), product, platformProductId);
115
119
  return {
116
120
  id: product.id,
117
121
  type: product.type,
package/dist/index.js CHANGED
@@ -12,15 +12,16 @@ export const assertEffectiveTargetConfigMatrix = (() => {
12
12
  const _iv0 = new Set(["apps-in-toss", "capacitor-android", "capacitor-ios", "devvit-web", "microsoft-store-pwa", "tiktok-minigame", "verse8-web", "web", "web-preview", "wechat-minigame"]);
13
13
  const _iv1 = new Set(["app-store", "apps-in-toss", "devvit", "google-play", "microsoft-store", "tiktok-minigame", "verse8", "web", "web-preview", "wechat-minigame"]);
14
14
  const _ip1 = input => "boolean" === typeof input["iap"];
15
- const _ip2 = input => "boolean" === typeof input["rewardedAds"];
16
- const _ip3 = input => "boolean" === typeof input["interstitialAds"];
17
- const _ip4 = input => "boolean" === typeof input["localization"];
18
- const _ip5 = input => "string" === typeof input["id"];
19
- const _ip6 = input => "boolean" === typeof input["enabled"];
20
- const _ip7 = input => "available" === input["reason"] || "capability-unsupported" === input["reason"] || "missing-platform-id" === input["reason"] || "target-disabled" === input["reason"];
21
- const _ip8 = input => "currency" === input["type"];
22
- const _ip9 = input => "coin" === input["currency"] || "gem" === input["currency"];
23
- const _ip10 = input => "number" === typeof input["amount"];
15
+ const _ip2 = input => undefined === input["subscriptions"] || "boolean" === typeof input["subscriptions"];
16
+ const _ip3 = input => "boolean" === typeof input["rewardedAds"];
17
+ const _ip4 = input => "boolean" === typeof input["interstitialAds"];
18
+ const _ip5 = input => "boolean" === typeof input["localization"];
19
+ const _ip6 = input => "string" === typeof input["id"];
20
+ const _ip7 = input => "boolean" === typeof input["enabled"];
21
+ const _ip8 = input => "action-required" === input["reason"] || "available" === input["reason"] || "capability-unsupported" === input["reason"] || "configuration-required" === input["reason"] || "missing-platform-id" === input["reason"] || "target-disabled" === input["reason"] || "temporarily-unavailable" === input["reason"];
22
+ const _ip9 = input => "currency" === input["type"];
23
+ const _ip10 = input => "coin" === input["currency"] || "gem" === input["currency"];
24
+ const _ip11 = input => "number" === typeof input["amount"];
24
25
  const _ap0 = (input, _path, _exceptionable = true) => "string" === typeof input["version"] || _assertGuard_1._assertGuard(_exceptionable, {
25
26
  method: "typia.createAssert",
26
27
  path: _path + ".version",
@@ -37,63 +38,72 @@ export const assertEffectiveTargetConfigMatrix = (() => {
37
38
  expected: "boolean",
38
39
  value: input["iap"]
39
40
  }, _errorFactory);
40
- const _ap2 = (input, _path, _exceptionable = true) => "boolean" === typeof input["rewardedAds"] || _assertGuard_1._assertGuard(_exceptionable, {
41
+ const _ap2 = (input, _path, _exceptionable = true) => undefined === input["subscriptions"] || "boolean" === typeof input["subscriptions"] || _assertGuard_1._assertGuard(_exceptionable, {
42
+ method: "typia.createAssert",
43
+ path: _path + ".subscriptions",
44
+ expected: "(boolean | undefined)",
45
+ value: input["subscriptions"]
46
+ }, _errorFactory);
47
+ const _ap3 = (input, _path, _exceptionable = true) => "boolean" === typeof input["rewardedAds"] || _assertGuard_1._assertGuard(_exceptionable, {
41
48
  method: "typia.createAssert",
42
49
  path: _path + ".rewardedAds",
43
50
  expected: "boolean",
44
51
  value: input["rewardedAds"]
45
52
  }, _errorFactory);
46
- const _ap3 = (input, _path, _exceptionable = true) => "boolean" === typeof input["interstitialAds"] || _assertGuard_1._assertGuard(_exceptionable, {
53
+ const _ap4 = (input, _path, _exceptionable = true) => "boolean" === typeof input["interstitialAds"] || _assertGuard_1._assertGuard(_exceptionable, {
47
54
  method: "typia.createAssert",
48
55
  path: _path + ".interstitialAds",
49
56
  expected: "boolean",
50
57
  value: input["interstitialAds"]
51
58
  }, _errorFactory);
52
- const _ap4 = (input, _path, _exceptionable = true) => "boolean" === typeof input["localization"] || _assertGuard_1._assertGuard(_exceptionable, {
59
+ const _ap5 = (input, _path, _exceptionable = true) => "boolean" === typeof input["localization"] || _assertGuard_1._assertGuard(_exceptionable, {
53
60
  method: "typia.createAssert",
54
61
  path: _path + ".localization",
55
62
  expected: "boolean",
56
63
  value: input["localization"]
57
64
  }, _errorFactory);
58
- const _ap5 = (input, _path, _exceptionable = true) => "string" === typeof input["id"] || _assertGuard_1._assertGuard(_exceptionable, {
65
+ const _ae2 = "(\"action-required\" | \"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"temporarily-unavailable\" | \"unsupported\")";
66
+ const _ap6 = (input, _path, _exceptionable = true) => "string" === typeof input["id"] || _assertGuard_1._assertGuard(_exceptionable, {
59
67
  method: "typia.createAssert",
60
68
  path: _path + ".id",
61
69
  expected: "string",
62
70
  value: input["id"]
63
71
  }, _errorFactory);
64
- const _ae2 = "({ readonly type: \"currency\"; readonly currency: \"coin\" | \"gem\"; readonly amount: number; } | { readonly type: \"entitlement\"; readonly entitlement: string; } | { readonly type: \"resource\"; readonly resource: string & MinLength<1>; readonly amount: number & ExclusiveMinimum<0> & Maximum<1.7976931348623157e+308>; })";
65
- const _ap6 = (input, _path, _exceptionable = true) => "boolean" === typeof input["enabled"] || _assertGuard_1._assertGuard(_exceptionable, {
72
+ const _ae3 = "({ readonly type: \"currency\"; readonly currency: \"coin\" | \"gem\"; readonly amount: number; } | { readonly type: \"entitlement\"; readonly entitlement: string; } | { readonly type: \"resource\"; readonly resource: string & MinLength<1>; readonly amount: number & ExclusiveMinimum<0> & Maximum<1.7976931348623157e+308>; })";
73
+ const _ap7 = (input, _path, _exceptionable = true) => "boolean" === typeof input["enabled"] || _assertGuard_1._assertGuard(_exceptionable, {
66
74
  method: "typia.createAssert",
67
75
  path: _path + ".enabled",
68
76
  expected: "boolean",
69
77
  value: input["enabled"]
70
78
  }, _errorFactory);
71
- const _ap7 = (input, _path, _exceptionable = true) => "available" === input["reason"] || "capability-unsupported" === input["reason"] || "missing-platform-id" === input["reason"] || "target-disabled" === input["reason"] || _assertGuard_1._assertGuard(_exceptionable, {
79
+ const _ap8 = (input, _path, _exceptionable = true) => "action-required" === input["reason"] || "available" === input["reason"] || "capability-unsupported" === input["reason"] || "configuration-required" === input["reason"] || "missing-platform-id" === input["reason"] || "target-disabled" === input["reason"] || "temporarily-unavailable" === input["reason"] || _assertGuard_1._assertGuard(_exceptionable, {
72
80
  method: "typia.createAssert",
73
81
  path: _path + ".reason",
74
- expected: "(\"available\" | \"capability-unsupported\" | \"missing-platform-id\" | \"target-disabled\")",
82
+ expected: _ae4,
75
83
  value: input["reason"]
76
84
  }, _errorFactory);
77
- const _ap8 = (input, _path, _exceptionable = true) => "currency" === input["type"] || _assertGuard_1._assertGuard(_exceptionable, {
85
+ const _ae4 = "(\"action-required\" | \"available\" | \"capability-unsupported\" | \"configuration-required\" | \"missing-platform-id\" | \"target-disabled\" | \"temporarily-unavailable\")";
86
+ const _ap9 = (input, _path, _exceptionable = true) => "currency" === input["type"] || _assertGuard_1._assertGuard(_exceptionable, {
78
87
  method: "typia.createAssert",
79
88
  path: _path + ".type",
80
89
  expected: "\"currency\"",
81
90
  value: input["type"]
82
91
  }, _errorFactory);
83
- const _ap9 = (input, _path, _exceptionable = true) => "coin" === input["currency"] || "gem" === input["currency"] || _assertGuard_1._assertGuard(_exceptionable, {
92
+ const _ap10 = (input, _path, _exceptionable = true) => "coin" === input["currency"] || "gem" === input["currency"] || _assertGuard_1._assertGuard(_exceptionable, {
84
93
  method: "typia.createAssert",
85
94
  path: _path + ".currency",
86
95
  expected: "(\"coin\" | \"gem\")",
87
96
  value: input["currency"]
88
97
  }, _errorFactory);
89
- const _ap10 = (input, _path, _exceptionable = true) => "number" === typeof input["amount"] || _assertGuard_1._assertGuard(_exceptionable, {
98
+ const _ap11 = (input, _path, _exceptionable = true) => "number" === typeof input["amount"] || _assertGuard_1._assertGuard(_exceptionable, {
90
99
  method: "typia.createAssert",
91
100
  path: _path + ".amount",
92
101
  expected: "number",
93
102
  value: input["amount"]
94
103
  }, _errorFactory);
95
- const _ae3 = "(undefined | { readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
96
- const _ae4 = "({ readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
104
+ const _ae5 = "(undefined | { readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
105
+ const _ae6 = "(\"action-required\" | \"available\" | \"capability-unsupported\" | \"configuration-required\" | \"target-disabled\" | \"temporarily-unavailable\")";
106
+ const _ae7 = "({ readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
97
107
  const _ao0 = (input, _path, _exceptionable = true) => _ap0(input, _path, true && _exceptionable) && (("object" === typeof input.targets && null !== input.targets && false === Array.isArray(input.targets) || _assertGuard_1._assertGuard(_exceptionable, {
98
108
  method: "typia.createAssert",
99
109
  path: _path + ".targets",
@@ -121,7 +131,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
121
131
  value: value
122
132
  }, _errorFactory);
123
133
  });
124
- const _ao10 = (input, _path, _exceptionable = true) => _ap5(input, _path, true && _exceptionable) && ("consumable" === input.type || "non_consumable" === input.type || "subscription" === input.type || _assertGuard_1._assertGuard(_exceptionable, {
134
+ const _ao10 = (input, _path, _exceptionable = true) => _ap6(input, _path, true && _exceptionable) && ("consumable" === input.type || "non_consumable" === input.type || "subscription" === input.type || _assertGuard_1._assertGuard(_exceptionable, {
125
135
  method: "typia.createAssert",
126
136
  path: _path + ".type",
127
137
  expected: "(\"consumable\" | \"non_consumable\" | \"subscription\")",
@@ -129,20 +139,20 @@ export const assertEffectiveTargetConfigMatrix = (() => {
129
139
  }, _errorFactory)) && (("object" === typeof input.grant && null !== input.grant || _assertGuard_1._assertGuard(_exceptionable, {
130
140
  method: "typia.createAssert",
131
141
  path: _path + ".grant",
132
- expected: _ae2,
142
+ expected: _ae3,
133
143
  value: input.grant
134
144
  }, _errorFactory)) && _au0(input.grant, _path + ".grant", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
135
145
  method: "typia.createAssert",
136
146
  path: _path + ".grant",
137
- expected: _ae2,
147
+ expected: _ae3,
138
148
  value: input.grant
139
- }, _errorFactory)) && _ap6(input, _path, true && _exceptionable) && _ap7(input, _path, true && _exceptionable) && (undefined === input.platformProductId || "string" === typeof input.platformProductId || _assertGuard_1._assertGuard(_exceptionable, {
149
+ }, _errorFactory)) && _ap7(input, _path, true && _exceptionable) && _ap8(input, _path, true && _exceptionable) && (undefined === input.platformProductId || "string" === typeof input.platformProductId || _assertGuard_1._assertGuard(_exceptionable, {
140
150
  method: "typia.createAssert",
141
151
  path: _path + ".platformProductId",
142
152
  expected: "(string | undefined)",
143
153
  value: input.platformProductId
144
154
  }, _errorFactory));
145
- const _ao11 = (input, _path, _exceptionable = true) => _ap8(input, _path, true && _exceptionable) && _ap9(input, _path, true && _exceptionable) && _ap10(input, _path, true && _exceptionable);
155
+ const _ao11 = (input, _path, _exceptionable = true) => _ap9(input, _path, true && _exceptionable) && _ap10(input, _path, true && _exceptionable) && _ap11(input, _path, true && _exceptionable);
146
156
  const _ao12 = (input, _path, _exceptionable = true) => ("entitlement" === input.type || _assertGuard_1._assertGuard(_exceptionable, {
147
157
  method: "typia.createAssert",
148
158
  path: _path + ".type",
@@ -190,7 +200,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
190
200
  path: _path + ".bannerAds",
191
201
  expected: "boolean",
192
202
  value: input.bannerAds
193
- }, _errorFactory)) && _ap2(input, _path, true && _exceptionable) && _ap3(input, _path, true && _exceptionable) && ((Array.isArray(input.placements) || _assertGuard_1._assertGuard(_exceptionable, {
203
+ }, _errorFactory)) && _ap3(input, _path, true && _exceptionable) && _ap4(input, _path, true && _exceptionable) && ((Array.isArray(input.placements) || _assertGuard_1._assertGuard(_exceptionable, {
194
204
  method: "typia.createAssert",
195
205
  path: _path + ".placements",
196
206
  expected: "ReadonlyArray<EffectiveAdPlacementConfig>",
@@ -211,7 +221,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
211
221
  expected: "ReadonlyArray<EffectiveAdPlacementConfig>",
212
222
  value: input.placements
213
223
  }, _errorFactory));
214
- const _ao15 = (input, _path, _exceptionable = true) => _ap5(input, _path, true && _exceptionable) && ("banner" === input.type || "interstitial" === input.type || "rewarded" === input.type || _assertGuard_1._assertGuard(_exceptionable, {
224
+ const _ao15 = (input, _path, _exceptionable = true) => _ap6(input, _path, true && _exceptionable) && ("banner" === input.type || "interstitial" === input.type || "rewarded" === input.type || _assertGuard_1._assertGuard(_exceptionable, {
215
225
  method: "typia.createAssert",
216
226
  path: _path + ".type",
217
227
  expected: "(\"banner\" | \"interstitial\" | \"rewarded\")",
@@ -219,12 +229,12 @@ export const assertEffectiveTargetConfigMatrix = (() => {
219
229
  }, _errorFactory)) && (undefined === input.reward || ("object" === typeof input.reward && null !== input.reward || _assertGuard_1._assertGuard(_exceptionable, {
220
230
  method: "typia.createAssert",
221
231
  path: _path + ".reward",
222
- expected: _ae3,
232
+ expected: _ae5,
223
233
  value: input.reward
224
234
  }, _errorFactory)) && _au1(input.reward, _path + ".reward", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
225
235
  method: "typia.createAssert",
226
236
  path: _path + ".reward",
227
- expected: _ae3,
237
+ expected: _ae5,
228
238
  value: input.reward
229
239
  }, _errorFactory)) && (("object" === typeof input.frequencyCap && null !== input.frequencyCap || _assertGuard_1._assertGuard(_exceptionable, {
230
240
  method: "typia.createAssert",
@@ -236,7 +246,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
236
246
  path: _path + ".frequencyCap",
237
247
  expected: "FrequencyCap",
238
248
  value: input.frequencyCap
239
- }, _errorFactory)) && _ap6(input, _path, true && _exceptionable) && _ap7(input, _path, true && _exceptionable) && (undefined === input.platformPlacementId || "string" === typeof input.platformPlacementId || _assertGuard_1._assertGuard(_exceptionable, {
249
+ }, _errorFactory)) && _ap7(input, _path, true && _exceptionable) && _ap8(input, _path, true && _exceptionable) && (undefined === input.platformPlacementId || "string" === typeof input.platformPlacementId || _assertGuard_1._assertGuard(_exceptionable, {
240
250
  method: "typia.createAssert",
241
251
  path: _path + ".platformPlacementId",
242
252
  expected: "(string | undefined)",
@@ -247,8 +257,8 @@ export const assertEffectiveTargetConfigMatrix = (() => {
247
257
  path: _path + ".type",
248
258
  expected: "\"continue\"",
249
259
  value: input.type
250
- }, _errorFactory)) && _ap10(input, _path, true && _exceptionable);
251
- const _ao17 = (input, _path, _exceptionable = true) => _ap8(input, _path, true && _exceptionable) && _ap10(input, _path, true && _exceptionable) && _ap9(input, _path, true && _exceptionable);
260
+ }, _errorFactory)) && _ap11(input, _path, true && _exceptionable);
261
+ const _ao17 = (input, _path, _exceptionable = true) => _ap9(input, _path, true && _exceptionable) && _ap11(input, _path, true && _exceptionable) && _ap10(input, _path, true && _exceptionable);
252
262
  const _ao18 = (input, _path, _exceptionable = true) => ("number" === typeof input.cooldownSeconds || _assertGuard_1._assertGuard(_exceptionable, {
253
263
  method: "typia.createAssert",
254
264
  path: _path + ".cooldownSeconds",
@@ -270,10 +280,10 @@ export const assertEffectiveTargetConfigMatrix = (() => {
270
280
  path: _path + ".native",
271
281
  expected: "boolean",
272
282
  value: input.native
273
- }, _errorFactory)) && _ap6(input, _path, true && _exceptionable) && ("available" === input.reason || "capability-unsupported" === input.reason || "target-disabled" === input.reason || _assertGuard_1._assertGuard(_exceptionable, {
283
+ }, _errorFactory)) && _ap7(input, _path, true && _exceptionable) && ("action-required" === input.reason || "available" === input.reason || "capability-unsupported" === input.reason || "configuration-required" === input.reason || "target-disabled" === input.reason || "temporarily-unavailable" === input.reason || _assertGuard_1._assertGuard(_exceptionable, {
274
284
  method: "typia.createAssert",
275
285
  path: _path + ".reason",
276
- expected: "(\"available\" | \"capability-unsupported\" | \"target-disabled\")",
286
+ expected: _ae6,
277
287
  value: input.reason
278
288
  }, _errorFactory)) && (undefined === input.defaultLeaderboardId || "string" === typeof input.defaultLeaderboardId || _assertGuard_1._assertGuard(_exceptionable, {
279
289
  method: "typia.createAssert",
@@ -407,8 +417,8 @@ export const assertEffectiveTargetConfigMatrix = (() => {
407
417
  path: _path + ".support",
408
418
  expected: "(\"local\" | \"native\" | \"none\")",
409
419
  value: input.support
410
- }, _errorFactory)) && _ap6(input, _path, true && _exceptionable);
411
- const _ao21 = (input, _path, _exceptionable = true) => _ap6(input, _path, true && _exceptionable) && ("en" === input.fallbackLocale || "ko" === input.fallbackLocale || _assertGuard_1._assertGuard(_exceptionable, {
420
+ }, _errorFactory)) && _ap7(input, _path, true && _exceptionable);
421
+ const _ao21 = (input, _path, _exceptionable = true) => _ap7(input, _path, true && _exceptionable) && ("en" === input.fallbackLocale || "ko" === input.fallbackLocale || _assertGuard_1._assertGuard(_exceptionable, {
412
422
  method: "typia.createAssert",
413
423
  path: _path + ".fallbackLocale",
414
424
  expected: "(\"en\" | \"ko\")",
@@ -420,47 +430,57 @@ export const assertEffectiveTargetConfigMatrix = (() => {
420
430
  expected: _ae1,
421
431
  value: input.profile
422
432
  }, _errorFactory);
423
- const _ao4 = (input, _path, _exceptionable = true) => _ap1(input, _path, true && _exceptionable) && (undefined === input.bannerAds || "boolean" === typeof input.bannerAds || _assertGuard_1._assertGuard(_exceptionable, {
433
+ const _ao4 = (input, _path, _exceptionable = true) => _ap1(input, _path, true && _exceptionable) && _ap2(input, _path, true && _exceptionable) && (undefined === input.bannerAds || "boolean" === typeof input.bannerAds || _assertGuard_1._assertGuard(_exceptionable, {
424
434
  method: "typia.createAssert",
425
435
  path: _path + ".bannerAds",
426
436
  expected: "(boolean | undefined)",
427
437
  value: input.bannerAds
428
- }, _errorFactory)) && _ap2(input, _path, true && _exceptionable) && _ap3(input, _path, true && _exceptionable) && ("boolean" === typeof input.leaderboard || _assertGuard_1._assertGuard(_exceptionable, {
438
+ }, _errorFactory)) && _ap3(input, _path, true && _exceptionable) && _ap4(input, _path, true && _exceptionable) && ("boolean" === typeof input.leaderboard || _assertGuard_1._assertGuard(_exceptionable, {
429
439
  method: "typia.createAssert",
430
440
  path: _path + ".leaderboard",
431
441
  expected: "boolean",
432
442
  value: input.leaderboard
433
- }, _errorFactory)) && _ap4(input, _path, true && _exceptionable);
443
+ }, _errorFactory)) && (undefined === input.nativeLeaderboard || "boolean" === typeof input.nativeLeaderboard || _assertGuard_1._assertGuard(_exceptionable, {
444
+ method: "typia.createAssert",
445
+ path: _path + ".nativeLeaderboard",
446
+ expected: "(boolean | undefined)",
447
+ value: input.nativeLeaderboard
448
+ }, _errorFactory)) && (undefined === input.remoteLeaderboard || "boolean" === typeof input.remoteLeaderboard || _assertGuard_1._assertGuard(_exceptionable, {
449
+ method: "typia.createAssert",
450
+ path: _path + ".remoteLeaderboard",
451
+ expected: "(boolean | undefined)",
452
+ value: input.remoteLeaderboard
453
+ }, _errorFactory)) && _ap5(input, _path, true && _exceptionable);
434
454
  const _ao5 = (input, _path, _exceptionable = true) => ("local" === input.storage || "native" === input.storage || "none" === input.storage || _assertGuard_1._assertGuard(_exceptionable, {
435
455
  method: "typia.createAssert",
436
456
  path: _path + ".storage",
437
457
  expected: "(\"local\" | \"native\" | \"none\")",
438
458
  value: input.storage
439
- }, _errorFactory)) && _ap4(input, _path, true && _exceptionable);
440
- const _ao6 = (input, _path, _exceptionable = true) => ("approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "unsupported" === input.identityUpgrade || _assertGuard_1._assertGuard(_exceptionable, {
459
+ }, _errorFactory)) && _ap5(input, _path, true && _exceptionable);
460
+ const _ao6 = (input, _path, _exceptionable = true) => ("action-required" === input.identityUpgrade || "approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "temporarily-unavailable" === input.identityUpgrade || "unsupported" === input.identityUpgrade || _assertGuard_1._assertGuard(_exceptionable, {
441
461
  method: "typia.createAssert",
442
462
  path: _path + ".identityUpgrade",
443
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
463
+ expected: _ae2,
444
464
  value: input.identityUpgrade
445
- }, _errorFactory)) && ("approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "unsupported" === input.presentation || _assertGuard_1._assertGuard(_exceptionable, {
465
+ }, _errorFactory)) && ("action-required" === input.presentation || "approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "temporarily-unavailable" === input.presentation || "unsupported" === input.presentation || _assertGuard_1._assertGuard(_exceptionable, {
446
466
  method: "typia.createAssert",
447
467
  path: _path + ".presentation",
448
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
468
+ expected: _ae2,
449
469
  value: input.presentation
450
- }, _errorFactory)) && ("approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "unsupported" === input.sharing || _assertGuard_1._assertGuard(_exceptionable, {
470
+ }, _errorFactory)) && ("action-required" === input.sharing || "approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "temporarily-unavailable" === input.sharing || "unsupported" === input.sharing || _assertGuard_1._assertGuard(_exceptionable, {
451
471
  method: "typia.createAssert",
452
472
  path: _path + ".sharing",
453
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
473
+ expected: _ae2,
454
474
  value: input.sharing
455
- }, _errorFactory)) && ("approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "unsupported" === input.inboundShare || _assertGuard_1._assertGuard(_exceptionable, {
475
+ }, _errorFactory)) && ("action-required" === input.inboundShare || "approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "temporarily-unavailable" === input.inboundShare || "unsupported" === input.inboundShare || _assertGuard_1._assertGuard(_exceptionable, {
456
476
  method: "typia.createAssert",
457
477
  path: _path + ".inboundShare",
458
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
478
+ expected: _ae2,
459
479
  value: input.inboundShare
460
- }, _errorFactory)) && ("approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "unsupported" === input.notifications || _assertGuard_1._assertGuard(_exceptionable, {
480
+ }, _errorFactory)) && ("action-required" === input.notifications || "approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "temporarily-unavailable" === input.notifications || "unsupported" === input.notifications || _assertGuard_1._assertGuard(_exceptionable, {
461
481
  method: "typia.createAssert",
462
482
  path: _path + ".notifications",
463
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
483
+ expected: _ae2,
464
484
  value: input.notifications
465
485
  }, _errorFactory)) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode || _assertGuard_1._assertGuard(_exceptionable, {
466
486
  method: "typia.createAssert",
@@ -520,7 +540,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
520
540
  expected: "(string | undefined)",
521
541
  value: input.platformAdapter
522
542
  }, _errorFactory));
523
- const _ao9 = (input, _path, _exceptionable = true) => _ap1(input, _path, true && _exceptionable) && ((Array.isArray(input.products) || _assertGuard_1._assertGuard(_exceptionable, {
543
+ const _ao9 = (input, _path, _exceptionable = true) => _ap1(input, _path, true && _exceptionable) && _ap2(input, _path, true && _exceptionable) && ((Array.isArray(input.products) || _assertGuard_1._assertGuard(_exceptionable, {
524
544
  method: "typia.createAssert",
525
545
  path: _path + ".products",
526
546
  expected: "ReadonlyArray<EffectiveProductConfig>",
@@ -552,7 +572,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
552
572
  return _assertGuard_1._assertGuard(_exceptionable, {
553
573
  method: "typia.createAssert",
554
574
  path: _path,
555
- expected: _ae2,
575
+ expected: _ae3,
556
576
  value: input
557
577
  }, _errorFactory);
558
578
  })();
@@ -565,7 +585,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
565
585
  return _assertGuard_1._assertGuard(_exceptionable, {
566
586
  method: "typia.createAssert",
567
587
  path: _path,
568
- expected: _ae4,
588
+ expected: _ae7,
569
589
  value: input
570
590
  }, _errorFactory);
571
591
  })();
@@ -576,26 +596,26 @@ export const assertEffectiveTargetConfigMatrix = (() => {
576
596
  return true;
577
597
  return "object" === typeof value && null !== value && _io2(value);
578
598
  });
579
- const _io10 = input => _ip5(input) && ("consumable" === input.type || "non_consumable" === input.type || "subscription" === input.type) && ("object" === typeof input.grant && null !== input.grant && _iu0(input.grant)) && _ip6(input) && _ip7(input) && (undefined === input.platformProductId || "string" === typeof input.platformProductId);
580
- const _io11 = input => _ip8(input) && _ip9(input) && _ip10(input);
599
+ const _io10 = input => _ip6(input) && ("consumable" === input.type || "non_consumable" === input.type || "subscription" === input.type) && ("object" === typeof input.grant && null !== input.grant && _iu0(input.grant)) && _ip7(input) && _ip8(input) && (undefined === input.platformProductId || "string" === typeof input.platformProductId);
600
+ const _io11 = input => _ip9(input) && _ip10(input) && _ip11(input);
581
601
  const _io12 = input => "entitlement" === input.type && "string" === typeof input.entitlement;
582
602
  const _io13 = input => "resource" === input.type && ("string" === typeof input.resource && 1 <= input.resource.length) && ("number" === typeof input.amount && (0 < input.amount && input.amount <= 1.7976931348623157e+308));
583
- const _io14 = input => "boolean" === typeof input.bannerAds && _ip2(input) && _ip3(input) && (Array.isArray(input.placements) && input.placements.every(elem => "object" === typeof elem && null !== elem && _io15(elem)));
584
- const _io15 = input => _ip5(input) && ("banner" === input.type || "interstitial" === input.type || "rewarded" === input.type) && (undefined === input.reward || "object" === typeof input.reward && null !== input.reward && _iu1(input.reward)) && ("object" === typeof input.frequencyCap && null !== input.frequencyCap && _io18(input.frequencyCap)) && _ip6(input) && _ip7(input) && (undefined === input.platformPlacementId || "string" === typeof input.platformPlacementId);
585
- const _io16 = input => "continue" === input.type && _ip10(input);
586
- const _io17 = input => _ip8(input) && _ip10(input) && _ip9(input);
603
+ const _io14 = input => "boolean" === typeof input.bannerAds && _ip3(input) && _ip4(input) && (Array.isArray(input.placements) && input.placements.every(elem => "object" === typeof elem && null !== elem && _io15(elem)));
604
+ const _io15 = input => _ip6(input) && ("banner" === input.type || "interstitial" === input.type || "rewarded" === input.type) && (undefined === input.reward || "object" === typeof input.reward && null !== input.reward && _iu1(input.reward)) && ("object" === typeof input.frequencyCap && null !== input.frequencyCap && _io18(input.frequencyCap)) && _ip7(input) && _ip8(input) && (undefined === input.platformPlacementId || "string" === typeof input.platformPlacementId);
605
+ const _io16 = input => "continue" === input.type && _ip11(input);
606
+ const _io17 = input => _ip9(input) && _ip11(input) && _ip10(input);
587
607
  const _io18 = input => "number" === typeof input.cooldownSeconds && (undefined === input.maxPerSession || "number" === typeof input.maxPerSession) && (undefined === input.minStageInterval || "number" === typeof input.minStageInterval);
588
- const _io19 = input => "boolean" === typeof input.native && _ip6(input) && ("available" === input.reason || "capability-unsupported" === input.reason || "target-disabled" === input.reason) && (undefined === input.defaultLeaderboardId || "string" === typeof input.defaultLeaderboardId);
608
+ const _io19 = input => "boolean" === typeof input.native && _ip7(input) && ("action-required" === input.reason || "available" === input.reason || "capability-unsupported" === input.reason || "configuration-required" === input.reason || "target-disabled" === input.reason || "temporarily-unavailable" === input.reason) && (undefined === input.defaultLeaderboardId || "string" === typeof input.defaultLeaderboardId);
589
609
  const _io2 = input => _ip0(input) && "string" === typeof input.target && true === _iv0.has(input.runtime) && ("object" === typeof input.release && null !== input.release && _io3(input.release)) && ("object" === typeof input.features && null !== input.features && _io4(input.features)) && ("object" === typeof input.capabilities && null !== input.capabilities && _io5(input.capabilities)) && ("object" === typeof input.integrations && null !== input.integrations && _io6(input.integrations)) && ("object" === typeof input.policy && null !== input.policy && _io7(input.policy)) && ("object" === typeof input.sources && null !== input.sources && _io8(input.sources)) && ("object" === typeof input.monetization && null !== input.monetization && _io9(input.monetization)) && ("object" === typeof input.ads && null !== input.ads && _io14(input.ads)) && ("object" === typeof input.leaderboard && null !== input.leaderboard && _io19(input.leaderboard)) && ("object" === typeof input.storage && null !== input.storage && _io20(input.storage)) && ("object" === typeof input.localization && null !== input.localization && _io21(input.localization));
590
- const _io20 = input => ("local" === input.support || "native" === input.support || "none" === input.support) && _ip6(input);
591
- const _io21 = input => _ip6(input) && ("en" === input.fallbackLocale || "ko" === input.fallbackLocale);
610
+ const _io20 = input => ("local" === input.support || "native" === input.support || "none" === input.support) && _ip7(input);
611
+ const _io21 = input => _ip7(input) && ("en" === input.fallbackLocale || "ko" === input.fallbackLocale);
592
612
  const _io3 = input => true === _iv1.has(input.profile);
593
- const _io4 = input => _ip1(input) && (undefined === input.bannerAds || "boolean" === typeof input.bannerAds) && _ip2(input) && _ip3(input) && "boolean" === typeof input.leaderboard && _ip4(input);
594
- const _io5 = input => ("local" === input.storage || "native" === input.storage || "none" === input.storage) && _ip4(input);
595
- const _io6 = input => ("approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "unsupported" === input.identityUpgrade) && ("approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "unsupported" === input.presentation) && ("approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "unsupported" === input.sharing) && ("approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "unsupported" === input.inboundShare) && ("approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "unsupported" === input.notifications) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode);
613
+ const _io4 = input => _ip1(input) && _ip2(input) && (undefined === input.bannerAds || "boolean" === typeof input.bannerAds) && _ip3(input) && _ip4(input) && "boolean" === typeof input.leaderboard && (undefined === input.nativeLeaderboard || "boolean" === typeof input.nativeLeaderboard) && (undefined === input.remoteLeaderboard || "boolean" === typeof input.remoteLeaderboard) && _ip5(input);
614
+ const _io5 = input => ("local" === input.storage || "native" === input.storage || "none" === input.storage) && _ip5(input);
615
+ const _io6 = input => ("action-required" === input.identityUpgrade || "approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "temporarily-unavailable" === input.identityUpgrade || "unsupported" === input.identityUpgrade) && ("action-required" === input.presentation || "approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "temporarily-unavailable" === input.presentation || "unsupported" === input.presentation) && ("action-required" === input.sharing || "approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "temporarily-unavailable" === input.sharing || "unsupported" === input.sharing) && ("action-required" === input.inboundShare || "approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "temporarily-unavailable" === input.inboundShare || "unsupported" === input.inboundShare) && ("action-required" === input.notifications || "approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "temporarily-unavailable" === input.notifications || "unsupported" === input.notifications) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode);
596
616
  const _io7 = input => "boolean" === typeof input.externalPaymentAllowed && "boolean" === typeof input.remoteExecutableCodeAllowed && "boolean" === typeof input.installOtherAppCTAAllowed && "boolean" === typeof input.requiresStoreReview && "boolean" === typeof input.requiresAitReview;
597
617
  const _io8 = input => "string" === typeof input.targetConfig && "string" === typeof input.productCatalog && "string" === typeof input.adPlacements && (undefined === input.platformTargetKind || "string" === typeof input.platformTargetKind) && (undefined === input.platformAdapter || "string" === typeof input.platformAdapter);
598
- const _io9 = input => _ip1(input) && (Array.isArray(input.products) && input.products.every(elem => "object" === typeof elem && null !== elem && _io10(elem)));
618
+ const _io9 = input => _ip1(input) && _ip2(input) && (Array.isArray(input.products) && input.products.every(elem => "object" === typeof elem && null !== elem && _io10(elem)));
599
619
  const _iu0 = input => (() => {
600
620
  if ("currency" === input.type)
601
621
  return _io11(input);
@@ -676,6 +696,7 @@ export const assertTargetConfigMatrix = (() => {
676
696
  }, _errorFactory);
677
697
  const _av1 = new Set(["app-store", "apps-in-toss", "devvit", "google-play", "microsoft-store", "tiktok-minigame", "verse8", "web", "web-preview", "wechat-minigame"]);
678
698
  const _ae1 = "(\"app-store\" | \"apps-in-toss\" | \"devvit\" | \"google-play\" | \"microsoft-store\" | \"tiktok-minigame\" | \"verse8\" | \"web\" | \"web-preview\" | \"wechat-minigame\")";
699
+ const _ae2 = "(\"action-required\" | \"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"temporarily-unavailable\" | \"unsupported\")";
679
700
  const _ao0 = (input, _path, _exceptionable = true) => ("string" === typeof input.version || _assertGuard_1._assertGuard(_exceptionable, {
680
701
  method: "typia.createAssert",
681
702
  path: _path + ".version",
@@ -708,30 +729,30 @@ export const assertTargetConfigMatrix = (() => {
708
729
  value: value
709
730
  }, _errorFactory);
710
731
  });
711
- const _ao10 = (input, _path, _exceptionable = true) => ("approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "unsupported" === input.identityUpgrade || _assertGuard_1._assertGuard(_exceptionable, {
732
+ const _ao10 = (input, _path, _exceptionable = true) => ("action-required" === input.identityUpgrade || "approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "temporarily-unavailable" === input.identityUpgrade || "unsupported" === input.identityUpgrade || _assertGuard_1._assertGuard(_exceptionable, {
712
733
  method: "typia.createAssert",
713
734
  path: _path + ".identityUpgrade",
714
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
735
+ expected: _ae2,
715
736
  value: input.identityUpgrade
716
- }, _errorFactory)) && ("approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "unsupported" === input.presentation || _assertGuard_1._assertGuard(_exceptionable, {
737
+ }, _errorFactory)) && ("action-required" === input.presentation || "approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "temporarily-unavailable" === input.presentation || "unsupported" === input.presentation || _assertGuard_1._assertGuard(_exceptionable, {
717
738
  method: "typia.createAssert",
718
739
  path: _path + ".presentation",
719
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
740
+ expected: _ae2,
720
741
  value: input.presentation
721
- }, _errorFactory)) && ("approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "unsupported" === input.sharing || _assertGuard_1._assertGuard(_exceptionable, {
742
+ }, _errorFactory)) && ("action-required" === input.sharing || "approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "temporarily-unavailable" === input.sharing || "unsupported" === input.sharing || _assertGuard_1._assertGuard(_exceptionable, {
722
743
  method: "typia.createAssert",
723
744
  path: _path + ".sharing",
724
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
745
+ expected: _ae2,
725
746
  value: input.sharing
726
- }, _errorFactory)) && ("approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "unsupported" === input.inboundShare || _assertGuard_1._assertGuard(_exceptionable, {
747
+ }, _errorFactory)) && ("action-required" === input.inboundShare || "approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "temporarily-unavailable" === input.inboundShare || "unsupported" === input.inboundShare || _assertGuard_1._assertGuard(_exceptionable, {
727
748
  method: "typia.createAssert",
728
749
  path: _path + ".inboundShare",
729
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
750
+ expected: _ae2,
730
751
  value: input.inboundShare
731
- }, _errorFactory)) && ("approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "unsupported" === input.notifications || _assertGuard_1._assertGuard(_exceptionable, {
752
+ }, _errorFactory)) && ("action-required" === input.notifications || "approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "temporarily-unavailable" === input.notifications || "unsupported" === input.notifications || _assertGuard_1._assertGuard(_exceptionable, {
732
753
  method: "typia.createAssert",
733
754
  path: _path + ".notifications",
734
- expected: "(\"approval-required\" | \"available\" | \"configuration-required\" | \"disabled\" | \"unsupported\")",
755
+ expected: _ae2,
735
756
  value: input.notifications
736
757
  }, _errorFactory)) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode || _assertGuard_1._assertGuard(_exceptionable, {
737
758
  method: "typia.createAssert",
@@ -825,11 +846,26 @@ export const assertTargetConfigMatrix = (() => {
825
846
  expected: "(TargetIntegrationConfig | undefined)",
826
847
  value: input.integrations
827
848
  }, _errorFactory));
828
- const _ao3 = (input, _path, _exceptionable = true) => _ap0(input, _path, true && _exceptionable) && _ap1(input, _path, true && _exceptionable) && _ap2(input, _path, true && _exceptionable) && _ap3(input, _path, true && _exceptionable) && ("boolean" === typeof input.leaderboard || _assertGuard_1._assertGuard(_exceptionable, {
849
+ const _ao3 = (input, _path, _exceptionable = true) => _ap0(input, _path, true && _exceptionable) && (undefined === input.subscriptions || "boolean" === typeof input.subscriptions || _assertGuard_1._assertGuard(_exceptionable, {
850
+ method: "typia.createAssert",
851
+ path: _path + ".subscriptions",
852
+ expected: "(boolean | undefined)",
853
+ value: input.subscriptions
854
+ }, _errorFactory)) && _ap1(input, _path, true && _exceptionable) && _ap2(input, _path, true && _exceptionable) && _ap3(input, _path, true && _exceptionable) && ("boolean" === typeof input.leaderboard || _assertGuard_1._assertGuard(_exceptionable, {
829
855
  method: "typia.createAssert",
830
856
  path: _path + ".leaderboard",
831
857
  expected: "boolean",
832
858
  value: input.leaderboard
859
+ }, _errorFactory)) && (undefined === input.nativeLeaderboard || "boolean" === typeof input.nativeLeaderboard || _assertGuard_1._assertGuard(_exceptionable, {
860
+ method: "typia.createAssert",
861
+ path: _path + ".nativeLeaderboard",
862
+ expected: "(boolean | undefined)",
863
+ value: input.nativeLeaderboard
864
+ }, _errorFactory)) && (undefined === input.remoteLeaderboard || "boolean" === typeof input.remoteLeaderboard || _assertGuard_1._assertGuard(_exceptionable, {
865
+ method: "typia.createAssert",
866
+ path: _path + ".remoteLeaderboard",
867
+ expected: "(boolean | undefined)",
868
+ value: input.remoteLeaderboard
833
869
  }, _errorFactory)) && _ap4(input, _path, true && _exceptionable);
834
870
  const _ao4 = (input, _path, _exceptionable = true) => ("local" === input.storage || "native" === input.storage || "none" === input.storage || _assertGuard_1._assertGuard(_exceptionable, {
835
871
  method: "typia.createAssert",
@@ -889,9 +925,9 @@ export const assertTargetConfigMatrix = (() => {
889
925
  return true;
890
926
  return "object" === typeof value && null !== value && _io2(value);
891
927
  });
892
- const _io10 = input => ("approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "unsupported" === input.identityUpgrade) && ("approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "unsupported" === input.presentation) && ("approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "unsupported" === input.sharing) && ("approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "unsupported" === input.inboundShare) && ("approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "unsupported" === input.notifications) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode);
928
+ const _io10 = input => ("action-required" === input.identityUpgrade || "approval-required" === input.identityUpgrade || "available" === input.identityUpgrade || "configuration-required" === input.identityUpgrade || "disabled" === input.identityUpgrade || "temporarily-unavailable" === input.identityUpgrade || "unsupported" === input.identityUpgrade) && ("action-required" === input.presentation || "approval-required" === input.presentation || "available" === input.presentation || "configuration-required" === input.presentation || "disabled" === input.presentation || "temporarily-unavailable" === input.presentation || "unsupported" === input.presentation) && ("action-required" === input.sharing || "approval-required" === input.sharing || "available" === input.sharing || "configuration-required" === input.sharing || "disabled" === input.sharing || "temporarily-unavailable" === input.sharing || "unsupported" === input.sharing) && ("action-required" === input.inboundShare || "approval-required" === input.inboundShare || "available" === input.inboundShare || "configuration-required" === input.inboundShare || "disabled" === input.inboundShare || "temporarily-unavailable" === input.inboundShare || "unsupported" === input.inboundShare) && ("action-required" === input.notifications || "approval-required" === input.notifications || "available" === input.notifications || "configuration-required" === input.notifications || "disabled" === input.notifications || "temporarily-unavailable" === input.notifications || "unsupported" === input.notifications) && ("fullscreen" === input.presentationMode || "inline-expanded" === input.presentationMode);
893
929
  const _io2 = input => true === _iv0.has(input.runtime) && ("object" === typeof input.features && null !== input.features && _io3(input.features)) && ("object" === typeof input.capabilities && null !== input.capabilities && _io4(input.capabilities)) && ("object" === typeof input.localization && null !== input.localization && _io5(input.localization)) && ("object" === typeof input.monetization && null !== input.monetization && _io6(input.monetization)) && ("object" === typeof input.leaderboard && null !== input.leaderboard && _io7(input.leaderboard)) && ("object" === typeof input.release && null !== input.release && _io8(input.release)) && ("object" === typeof input.policy && null !== input.policy && _io9(input.policy)) && (undefined === input.integrations || "object" === typeof input.integrations && null !== input.integrations && _io10(input.integrations));
894
- const _io3 = input => _ip0(input) && _ip1(input) && _ip2(input) && _ip3(input) && "boolean" === typeof input.leaderboard && _ip4(input);
930
+ const _io3 = input => _ip0(input) && (undefined === input.subscriptions || "boolean" === typeof input.subscriptions) && _ip1(input) && _ip2(input) && _ip3(input) && "boolean" === typeof input.leaderboard && (undefined === input.nativeLeaderboard || "boolean" === typeof input.nativeLeaderboard) && (undefined === input.remoteLeaderboard || "boolean" === typeof input.remoteLeaderboard) && _ip4(input);
895
931
  const _io4 = input => ("local" === input.storage || "native" === input.storage || "none" === input.storage) && _ip4(input);
896
932
  const _io5 = input => "en" === input.fallbackLocale || "ko" === input.fallbackLocale;
897
933
  const _io6 = input => _ip0(input) && _ip1(input) && _ip2(input) && _ip3(input);
package/dist/runtime.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import type { MpgdLocale } from '@mpgd/i18n';
2
2
  import type { PlatformCapabilities, PlatformGateway } from '@mpgd/platform';
3
3
  import type { EffectiveTargetConfig } from './effective.js';
4
- export type PlatformFeature = 'iap' | 'bannerAds' | 'rewardedAds' | 'interstitialAds' | 'leaderboard' | 'localization';
4
+ export type PlatformFeature = 'iap' | 'subscriptions' | 'bannerAds' | 'rewardedAds' | 'interstitialAds' | 'leaderboard' | 'nativeLeaderboard' | 'remoteLeaderboard' | 'localization';
5
5
  export type AdPlacementType = 'rewarded' | 'interstitial' | 'banner';
6
6
  type PlatformConfigTarget = PlatformGateway['target'];
7
7
  export type TargetRuntimeKind = 'web' | 'web-preview' | 'microsoft-store-pwa' | 'capacitor-android' | 'capacitor-ios' | 'apps-in-toss' | 'devvit-web' | 'verse8-web' | 'wechat-minigame' | 'tiktok-minigame';
8
8
  export type ReleaseProfile = 'web' | 'web-preview' | 'microsoft-store' | 'google-play' | 'app-store' | 'apps-in-toss' | 'devvit' | 'verse8' | 'wechat-minigame' | 'tiktok-minigame';
9
9
  export type StorageSupport = 'local' | 'native' | 'none';
10
10
  export type TargetIntegration = 'identityUpgrade' | 'presentation' | 'sharing' | 'inboundShare' | 'notifications';
11
- export type IntegrationAvailabilityState = 'available' | 'disabled' | 'approval-required' | 'configuration-required' | 'unsupported';
11
+ export type IntegrationAvailabilityState = 'available' | 'disabled' | 'approval-required' | 'action-required' | 'configuration-required' | 'temporarily-unavailable' | 'unsupported';
12
12
  export type PresentationMode = 'fullscreen' | 'inline-expanded';
13
13
  export interface TargetIntegrationConfig {
14
14
  readonly identityUpgrade: IntegrationAvailabilityState;
@@ -20,11 +20,16 @@ export interface TargetIntegrationConfig {
20
20
  }
21
21
  export interface TargetFeatureConfig {
22
22
  readonly iap: boolean;
23
+ /** Optional for matrices authored before subscriptions were distinct. */
24
+ readonly subscriptions?: boolean;
23
25
  /** Optional for target matrices authored before inline banner support. */
24
26
  readonly bannerAds?: boolean;
25
27
  readonly rewardedAds: boolean;
26
28
  readonly interstitialAds: boolean;
27
29
  readonly leaderboard: boolean;
30
+ /** Optional narrower policies; absent values inherit leaderboard. */
31
+ readonly nativeLeaderboard?: boolean;
32
+ readonly remoteLeaderboard?: boolean;
28
33
  readonly localization: boolean;
29
34
  }
30
35
  export interface TargetCapabilityConfig {
@@ -69,7 +74,7 @@ export interface TargetConfigMatrix {
69
74
  readonly version: string;
70
75
  readonly targets: Record<string, TargetConfig>;
71
76
  }
72
- export type FeatureAvailabilityReason = 'available' | 'target-disabled' | 'capability-unsupported';
77
+ export type FeatureAvailabilityReason = 'available' | 'target-disabled' | 'capability-unsupported' | 'configuration-required' | 'action-required' | 'temporarily-unavailable';
73
78
  export interface FeatureAvailability {
74
79
  readonly feature: PlatformFeature;
75
80
  readonly enabled: boolean;
@@ -116,11 +121,11 @@ export interface TargetConfiguredGateway extends PlatformGateway {
116
121
  readonly effectiveConfig?: EffectiveTargetConfig;
117
122
  getTargetRuntime(): Promise<TargetRuntimeSnapshot>;
118
123
  }
119
- export declare const platformFeatures: readonly ["iap", "bannerAds", "rewardedAds", "interstitialAds", "leaderboard", "localization"];
124
+ export declare const platformFeatures: readonly ["iap", "subscriptions", "bannerAds", "rewardedAds", "interstitialAds", "leaderboard", "nativeLeaderboard", "remoteLeaderboard", "localization"];
120
125
  export declare function adPlacementFeatureFor(type: AdPlacementType): PlatformFeature;
121
126
  export declare const targetIntegrations: readonly ["identityUpgrade", "presentation", "sharing", "inboundShare", "notifications"];
122
127
  type CompleteValueList<Union, Values extends readonly Union[]> = Exclude<Union, Values[number]> extends never ? Values : never;
123
- declare const integrationAvailabilityStateValues: readonly ["available", "disabled", "approval-required", "configuration-required", "unsupported"];
128
+ declare const integrationAvailabilityStateValues: readonly ["available", "disabled", "approval-required", "action-required", "configuration-required", "temporarily-unavailable", "unsupported"];
124
129
  export declare const integrationAvailabilityStates: CompleteValueList<IntegrationAvailabilityState, typeof integrationAvailabilityStateValues>;
125
130
  declare const presentationModeValues: readonly ["fullscreen", "inline-expanded"];
126
131
  export declare const presentationModes: CompleteValueList<PresentationMode, typeof presentationModeValues>;
@@ -140,7 +145,7 @@ export declare function getTargetConfig(matrix: TargetConfigMatrix, target: Plat
140
145
  export declare function isPlatformFeatureEnabled(config: TargetConfig, feature: PlatformFeature): boolean;
141
146
  export declare function applyTargetConfigToCapabilities(capabilities: PlatformCapabilities, config: TargetConfig): PlatformCapabilities;
142
147
  export declare function getFeatureAvailability(feature: PlatformFeature, config: TargetConfig, capabilities: PlatformCapabilities): FeatureAvailability;
143
- export declare function getIntegrationAvailability(integration: TargetIntegration, config: TargetConfig, gateway?: PlatformGateway): IntegrationAvailability;
148
+ export declare function getIntegrationAvailability(integration: TargetIntegration, config: TargetConfig, gateway?: PlatformGateway, capabilities?: PlatformCapabilities): IntegrationAvailability;
144
149
  export declare function createTargetRuntimeSnapshot(input: {
145
150
  readonly target: PlatformConfigTarget;
146
151
  readonly configTarget?: string;
package/dist/runtime.js CHANGED
@@ -5,10 +5,13 @@ const adPlacementFeatureByType = {
5
5
  };
6
6
  export const platformFeatures = [
7
7
  'iap',
8
+ 'subscriptions',
8
9
  'bannerAds',
9
10
  'rewardedAds',
10
11
  'interstitialAds',
11
12
  'leaderboard',
13
+ 'nativeLeaderboard',
14
+ 'remoteLeaderboard',
12
15
  'localization',
13
16
  ];
14
17
  export function adPlacementFeatureFor(type) {
@@ -55,7 +58,9 @@ const integrationAvailabilityStateValues = [
55
58
  'available',
56
59
  'disabled',
57
60
  'approval-required',
61
+ 'action-required',
58
62
  'configuration-required',
63
+ 'temporarily-unavailable',
59
64
  'unsupported',
60
65
  ];
61
66
  export const integrationAvailabilityStates = integrationAvailabilityStateValues;
@@ -129,7 +134,18 @@ export function getTargetConfig(matrix, target) {
129
134
  return config;
130
135
  }
131
136
  export function isPlatformFeatureEnabled(config, feature) {
132
- return config.features[feature] === true;
137
+ switch (feature) {
138
+ case 'subscriptions':
139
+ return config.features.iap && config.features.subscriptions === true;
140
+ case 'nativeLeaderboard':
141
+ return config.features.leaderboard
142
+ && (config.features.nativeLeaderboard ?? config.leaderboard.native);
143
+ case 'remoteLeaderboard':
144
+ return config.features.leaderboard
145
+ && (config.features.remoteLeaderboard ?? true);
146
+ default:
147
+ return config.features[feature] === true;
148
+ }
133
149
  }
134
150
  export function applyTargetConfigToCapabilities(capabilities, config) {
135
151
  const bannerAds = capabilities.bannerAds === true && config.features.bannerAds === true;
@@ -138,46 +154,61 @@ export function applyTargetConfigToCapabilities(capabilities, config) {
138
154
  return {
139
155
  ...capabilities,
140
156
  nativeIap: capabilities.nativeIap && config.features.iap,
157
+ ...(capabilities.subscriptionIap === undefined
158
+ ? {}
159
+ : { subscriptionIap: capabilities.subscriptionIap && isPlatformFeatureEnabled(config, 'subscriptions') }),
141
160
  nativeAds: capabilities.nativeAds &&
142
161
  (bannerAds || rewardedAds || interstitialAds),
143
162
  bannerAds,
144
163
  rewardedAds,
145
164
  interstitialAds,
146
- nativeLeaderboard: capabilities.nativeLeaderboard && config.features.leaderboard,
147
- remoteLeaderboard: capabilities.remoteLeaderboard && config.features.leaderboard,
165
+ nativeLeaderboard: capabilities.nativeLeaderboard && isPlatformFeatureEnabled(config, 'nativeLeaderboard'),
166
+ remoteLeaderboard: capabilities.remoteLeaderboard && isPlatformFeatureEnabled(config, 'remoteLeaderboard'),
148
167
  localizedContent: capabilities.localizedContent && config.features.localization,
149
168
  };
150
169
  }
151
170
  export function getFeatureAvailability(feature, config, capabilities) {
152
- const targetEnabled = config.features[feature] === true;
153
- const capabilitySupported = isFeatureCapabilitySupported(feature, capabilities);
154
- const enabled = targetEnabled && capabilitySupported;
171
+ const targetEnabled = isPlatformFeatureEnabled(config, feature);
172
+ const capabilitySupported = isFeatureCapabilitySupported(feature, capabilities, config);
173
+ const providerState = getFeatureProviderAvailability(feature, capabilities, config);
174
+ const enabled = targetEnabled && capabilitySupported && (providerState === undefined || providerState === 'available');
155
175
  return {
156
176
  feature,
157
177
  enabled,
158
178
  targetEnabled,
159
179
  capabilitySupported,
160
- reason: enabled ? 'available' : targetEnabled ? 'capability-unsupported' : 'target-disabled',
180
+ reason: !targetEnabled
181
+ ? 'target-disabled'
182
+ : enabled
183
+ ? 'available'
184
+ : providerState === 'configuration-required'
185
+ || providerState === 'action-required'
186
+ || providerState === 'temporarily-unavailable'
187
+ ? providerState
188
+ : 'capability-unsupported',
161
189
  };
162
190
  }
163
- export function getIntegrationAvailability(integration, config, gateway) {
191
+ export function getIntegrationAvailability(integration, config, gateway, capabilities) {
164
192
  const integrations = normalizeTargetIntegrationConfig(config.integrations);
165
- return createIntegrationAvailability(integration, integrations[integration], gateway);
193
+ return createIntegrationAvailability(integration, integrations[integration], gateway, capabilities);
166
194
  }
167
195
  export function createTargetRuntimeSnapshot(input) {
168
196
  const configTarget = input.configTarget ?? targetConfigKeyForPlatform(input.target);
169
197
  const availabilityConfig = resolveAvailabilityConfig(input.config, input.effectiveConfig);
170
198
  const features = {
171
199
  iap: getFeatureAvailability('iap', availabilityConfig, input.capabilities),
200
+ subscriptions: getFeatureAvailability('subscriptions', availabilityConfig, input.capabilities),
172
201
  bannerAds: getFeatureAvailability('bannerAds', availabilityConfig, input.capabilities),
173
202
  rewardedAds: getFeatureAvailability('rewardedAds', availabilityConfig, input.capabilities),
174
203
  interstitialAds: getFeatureAvailability('interstitialAds', availabilityConfig, input.capabilities),
175
204
  leaderboard: getFeatureAvailability('leaderboard', availabilityConfig, input.capabilities),
205
+ nativeLeaderboard: getFeatureAvailability('nativeLeaderboard', availabilityConfig, input.capabilities),
206
+ remoteLeaderboard: getFeatureAvailability('remoteLeaderboard', availabilityConfig, input.capabilities),
176
207
  localization: getFeatureAvailability('localization', availabilityConfig, input.capabilities),
177
208
  };
178
209
  const integrationConfig = normalizeTargetIntegrationConfig(input.effectiveConfig?.integrations ?? input.config.integrations);
179
210
  const integrationEntries = targetIntegrations.map((integration) => {
180
- const availability = createIntegrationAvailability(integration, integrationConfig[integration], input.gateway);
211
+ const availability = createIntegrationAvailability(integration, integrationConfig[integration], input.gateway, input.capabilities);
181
212
  return [integration, availability];
182
213
  });
183
214
  const integrations = Object.fromEntries(integrationEntries);
@@ -208,13 +239,16 @@ export function withTargetAvailability(gateway, config, options = {}) {
208
239
  const configTarget = options.configTarget ?? targetConfigKeyForPlatform(gateway.target);
209
240
  const { identity: gatewayIdentity, presentation: gatewayPresentation, sharing: gatewaySharing, notifications: gatewayNotifications, ...gatewayWithoutIntegrations } = gateway;
210
241
  const integrations = normalizeTargetIntegrationConfig(options.effectiveConfig?.integrations ?? config.integrations);
211
- const isIntegrationAvailable = (integration) => (createIntegrationAvailability(integration, integrations[integration], gateway).state
212
- === 'available');
213
- const identityUpgradeAvailable = isIntegrationAvailable('identityUpgrade');
214
- const presentationAvailable = isIntegrationAvailable('presentation');
215
- const sharingAvailable = isIntegrationAvailable('sharing');
216
- const inboundShareAvailable = isIntegrationAvailable('inboundShare');
217
- const notificationsAvailable = isIntegrationAvailable('notifications');
242
+ const isIntegrationCallable = (integration) => {
243
+ const state = createIntegrationAvailability(integration, integrations[integration], gateway).state;
244
+ return state === 'available' || (state === 'action-required'
245
+ && (integration === 'identityUpgrade' || integration === 'notifications'));
246
+ };
247
+ const identityUpgradeAvailable = isIntegrationCallable('identityUpgrade');
248
+ const presentationAvailable = isIntegrationCallable('presentation');
249
+ const sharingAvailable = isIntegrationCallable('sharing');
250
+ const inboundShareAvailable = isIntegrationCallable('inboundShare');
251
+ const notificationsAvailable = isIntegrationCallable('notifications');
218
252
  const getIdentitySession = gatewayIdentity.getSession?.bind(gatewayIdentity);
219
253
  const requestIdentityUpgrade = gatewayIdentity.requestUpgrade?.bind(gatewayIdentity);
220
254
  const shareOutbound = gatewaySharing?.share?.bind(gatewaySharing);
@@ -236,13 +270,32 @@ export function withTargetAvailability(gateway, config, options = {}) {
236
270
  ...(exposeInboundShare ? { readInboundShare } : {}),
237
271
  };
238
272
  const notifications = notificationsAvailable ? gatewayNotifications : undefined;
239
- const isIapAvailable = async () => (availabilityConfig.features.iap && (await getGatewayCapabilities()).nativeIap);
240
- const isLeaderboardAvailable = async () => {
273
+ const getIapAvailability = async () => {
274
+ const oneTimeEnabled = availabilityConfig.features.iap;
275
+ const subscriptionsEnabled = isPlatformFeatureEnabled(availabilityConfig, 'subscriptions');
276
+ if (!oneTimeEnabled && !subscriptionsEnabled) {
277
+ return { oneTime: false, subscriptions: false };
278
+ }
279
+ const capabilities = await getGatewayCapabilities();
280
+ return {
281
+ oneTime: oneTimeEnabled && capabilities.nativeIap,
282
+ subscriptions: subscriptionsEnabled && capabilities.subscriptionIap === true,
283
+ };
284
+ };
285
+ const getLeaderboardRoute = async () => {
241
286
  if (!availabilityConfig.features.leaderboard) {
242
- return false;
287
+ return null;
243
288
  }
244
289
  const capabilities = await getGatewayCapabilities();
245
- return capabilities.nativeLeaderboard || capabilities.remoteLeaderboard;
290
+ if (capabilities.nativeLeaderboard
291
+ && isPlatformFeatureEnabled(availabilityConfig, 'nativeLeaderboard')) {
292
+ return 'native';
293
+ }
294
+ if (capabilities.remoteLeaderboard
295
+ && isPlatformFeatureEnabled(availabilityConfig, 'remoteLeaderboard')) {
296
+ return 'remote';
297
+ }
298
+ return null;
246
299
  };
247
300
  const isAdPlacementAllowed = (placementId, expectedType) => {
248
301
  const actualType = options.resolveAdPlacementType?.(placementId);
@@ -251,14 +304,19 @@ export function withTargetAvailability(gateway, config, options = {}) {
251
304
  }
252
305
  return availabilityConfig.features[adPlacementFeatureFor(expectedType)] === true;
253
306
  };
254
- const canPreloadAdPlacement = (placementId) => {
255
- const actualType = options.resolveAdPlacementType?.(placementId);
307
+ const canPreloadAdPlacement = (placementId, requestedFormat) => {
308
+ const resolvedType = options.resolveAdPlacementType?.(placementId);
309
+ if (resolvedType !== undefined && requestedFormat !== undefined
310
+ && resolvedType !== requestedFormat) {
311
+ return false;
312
+ }
313
+ const actualType = resolvedType ?? requestedFormat;
256
314
  if (actualType !== undefined) {
257
- return availabilityConfig.features[adPlacementFeatureFor(actualType)] === true;
315
+ return actualType !== 'banner'
316
+ && availabilityConfig.features[adPlacementFeatureFor(actualType)] === true;
258
317
  }
259
318
  return (availabilityConfig.features.rewardedAds ||
260
- availabilityConfig.features.interstitialAds ||
261
- availabilityConfig.features.bannerAds === true);
319
+ availabilityConfig.features.interstitialAds);
262
320
  };
263
321
  return {
264
322
  ...gatewayWithoutIntegrations,
@@ -289,10 +347,29 @@ export function withTargetAvailability(gateway, config, options = {}) {
289
347
  },
290
348
  commerce: {
291
349
  async getProducts() {
292
- return await isIapAvailable() ? gateway.commerce.getProducts() : [];
350
+ const available = await getIapAvailability();
351
+ if (!available.oneTime && !available.subscriptions) {
352
+ return [];
353
+ }
354
+ return (await gateway.commerce.getProducts()).filter((product) => product.type === 'subscription' ? available.subscriptions : available.oneTime);
293
355
  },
294
356
  async purchase(input) {
295
- if (!await isIapAvailable()) {
357
+ const available = await getIapAvailability();
358
+ const configuredProduct = options.effectiveConfig?.monetization.products.find((product) => product.id === input.productId);
359
+ let productType = configuredProduct?.type;
360
+ if (productType === undefined
361
+ && options.effectiveConfig === undefined
362
+ && available.oneTime !== available.subscriptions) {
363
+ productType = (await gateway.commerce.getProducts()).find((product) => product.id === input.productId)?.type;
364
+ }
365
+ // When only one purchase route is available, unknown product types
366
+ // must not fall through to that route. An effective catalog is binding.
367
+ const allowed = productType === 'subscription'
368
+ ? available.subscriptions
369
+ : productType === undefined
370
+ ? available.oneTime && available.subscriptions
371
+ : available.oneTime;
372
+ if (!allowed || (options.effectiveConfig !== undefined && configuredProduct?.enabled !== true)) {
296
373
  return {
297
374
  status: 'cancelled',
298
375
  entitlementIds: [],
@@ -301,7 +378,8 @@ export function withTargetAvailability(gateway, config, options = {}) {
301
378
  return gateway.commerce.purchase(input);
302
379
  },
303
380
  async restore() {
304
- if (!await isIapAvailable() || gateway.commerce.restore === undefined) {
381
+ const available = await getIapAvailability();
382
+ if ((!available.oneTime && !available.subscriptions) || gateway.commerce.restore === undefined) {
305
383
  return {
306
384
  restoredEntitlements: [],
307
385
  };
@@ -309,13 +387,17 @@ export function withTargetAvailability(gateway, config, options = {}) {
309
387
  return gateway.commerce.restore();
310
388
  },
311
389
  async getEntitlements() {
312
- return await isIapAvailable() ? gateway.commerce.getEntitlements() : [];
390
+ const available = await getIapAvailability();
391
+ return available.oneTime || available.subscriptions
392
+ ? gateway.commerce.getEntitlements()
393
+ : [];
313
394
  },
314
395
  },
315
396
  ads: {
316
397
  async preload(input) {
317
- if (canPreloadAdPlacement(input.placementId)) {
318
- await gateway.ads.preload(input);
398
+ if (canPreloadAdPlacement(input.placementId, input.format)) {
399
+ const format = options.resolveAdPlacementType?.(input.placementId) ?? input.format;
400
+ await gateway.ads.preload(format === undefined ? input : { ...input, format });
319
401
  }
320
402
  },
321
403
  async showRewarded(input) {
@@ -351,16 +433,22 @@ export function withTargetAvailability(gateway, config, options = {}) {
351
433
  },
352
434
  leaderboard: {
353
435
  async submitScore(input) {
354
- if (!await isLeaderboardAvailable()) {
436
+ const route = await getLeaderboardRoute();
437
+ if (route === null) {
355
438
  return {
356
439
  submitted: false,
357
440
  };
358
441
  }
359
- return gateway.leaderboard.submitScore(input);
442
+ return gateway.leaderboard.submitScore(gateway.target === 'android' || gateway.target === 'ios'
443
+ ? { ...input, route }
444
+ : input);
360
445
  },
361
446
  async open(input) {
362
- if (await isLeaderboardAvailable()) {
363
- await gateway.leaderboard.open(input);
447
+ const route = await getLeaderboardRoute();
448
+ if (route !== null) {
449
+ await gateway.leaderboard.open(gateway.target === 'android' || gateway.target === 'ios'
450
+ ? { ...input, route }
451
+ : input);
364
452
  }
365
453
  },
366
454
  },
@@ -377,10 +465,12 @@ function resolveAvailabilityConfig(config, effectiveConfig) {
377
465
  export function isTargetConfiguredGateway(gateway) {
378
466
  return typeof gateway.getTargetRuntime === 'function';
379
467
  }
380
- function isFeatureCapabilitySupported(feature, capabilities) {
468
+ function isFeatureCapabilitySupported(feature, capabilities, config) {
381
469
  switch (feature) {
382
470
  case 'iap':
383
471
  return capabilities.nativeIap;
472
+ case 'subscriptions':
473
+ return capabilities.subscriptionIap === true;
384
474
  case 'bannerAds':
385
475
  return capabilities.bannerAds === true;
386
476
  case 'rewardedAds':
@@ -388,11 +478,45 @@ function isFeatureCapabilitySupported(feature, capabilities) {
388
478
  case 'interstitialAds':
389
479
  return capabilities.interstitialAds;
390
480
  case 'leaderboard':
391
- return capabilities.nativeLeaderboard || capabilities.remoteLeaderboard;
481
+ return (capabilities.nativeLeaderboard && isPlatformFeatureEnabled(config, 'nativeLeaderboard')) || (capabilities.remoteLeaderboard && isPlatformFeatureEnabled(config, 'remoteLeaderboard'));
482
+ case 'nativeLeaderboard':
483
+ return capabilities.nativeLeaderboard;
484
+ case 'remoteLeaderboard':
485
+ return capabilities.remoteLeaderboard;
392
486
  case 'localization':
393
487
  return capabilities.localizedContent;
394
488
  }
395
489
  }
490
+ function getFeatureProviderAvailability(feature, capabilities, config) {
491
+ const states = capabilities.providerAvailability;
492
+ if (states === undefined) {
493
+ return undefined;
494
+ }
495
+ switch (feature) {
496
+ case 'iap':
497
+ return states.nativeIap;
498
+ case 'subscriptions':
499
+ return states.subscriptionIap;
500
+ case 'rewardedAds':
501
+ return states.rewardedAds;
502
+ case 'interstitialAds':
503
+ return states.interstitialAds;
504
+ case 'bannerAds':
505
+ return states.bannerAds;
506
+ case 'nativeLeaderboard':
507
+ return states.nativeLeaderboard;
508
+ case 'leaderboard':
509
+ // A game-owned remote leaderboard remains usable without a native provider.
510
+ return capabilities.remoteLeaderboard && isPlatformFeatureEnabled(config, 'remoteLeaderboard')
511
+ ? 'available'
512
+ : isPlatformFeatureEnabled(config, 'nativeLeaderboard')
513
+ ? states.nativeLeaderboard
514
+ : undefined;
515
+ case 'remoteLeaderboard':
516
+ case 'localization':
517
+ return undefined;
518
+ }
519
+ }
396
520
  function isIntegrationAdapterSupported(integration, gateway) {
397
521
  if (gateway === undefined) {
398
522
  return false;
@@ -412,11 +536,23 @@ function isIntegrationAdapterSupported(integration, gateway) {
412
536
  && typeof gateway.notifications?.requestSubscription === 'function');
413
537
  }
414
538
  }
415
- function createIntegrationAvailability(integration, configuredState, gateway) {
539
+ function createIntegrationAvailability(integration, configuredState, gateway, capabilities) {
416
540
  const adapterSupported = isIntegrationAdapterSupported(integration, gateway);
541
+ const providerState = integration === 'identityUpgrade'
542
+ ? capabilities?.providerAvailability?.identityUpgrade
543
+ : integration === 'notifications'
544
+ ? capabilities?.providerAvailability?.pushNotifications
545
+ : undefined;
546
+ const state = configuredState === 'disabled' || configuredState === 'unsupported'
547
+ ? configuredState
548
+ : !adapterSupported || providerState === 'unsupported'
549
+ ? 'unsupported'
550
+ : providerState !== undefined && providerState !== 'available'
551
+ ? providerState
552
+ : configuredState;
417
553
  return {
418
554
  integration,
419
- state: adapterSupported ? configuredState : 'unsupported',
555
+ state,
420
556
  configuredState,
421
557
  adapterSupported,
422
558
  };
@@ -106,6 +106,27 @@ export interface TargetViewportSafeArea {
106
106
  readonly contentBounds: TargetViewportBounds;
107
107
  }
108
108
  /**
109
+ * A named host-owned surface in full-viewport CSS-pixel coordinates. The
110
+ * effective inset extends from `edge` to the surface's far bound, so any gap
111
+ * between a floating surface and that edge is conservatively treated as used.
112
+ */
113
+ export interface TargetViewportOccupiedSurface {
114
+ readonly surfaceId: string;
115
+ readonly edge: 'top' | 'right' | 'bottom' | 'left';
116
+ readonly bounds: TargetViewportBounds;
117
+ }
118
+ /** Independent occlusion measurements. Overlap is combined, never summed. */
119
+ export interface TargetViewportUsableAreaInput {
120
+ readonly safeAreaInsets?: Partial<TargetViewportSafeAreaInsets>;
121
+ readonly systemBarInsets?: Partial<TargetViewportSafeAreaInsets>;
122
+ readonly keyboardInsets?: Partial<TargetViewportSafeAreaInsets>;
123
+ readonly occupiedSurfaces?: readonly TargetViewportOccupiedSurface[];
124
+ }
125
+ /** Remaining geometry shared by a canvas and any DOM overlays. */
126
+ export interface TargetViewportUsableArea extends TargetViewportSafeArea {
127
+ readonly occupiedSurfaceIds: readonly string[];
128
+ }
129
+ /**
109
130
  * A viewport plan enriched with concrete safe-area geometry. It is assignable
110
131
  * to `TargetViewportPlan`, so existing scene code can adopt it incrementally.
111
132
  */
@@ -225,6 +246,14 @@ export declare function resolveTargetViewportComposition(input: TargetViewportCo
225
246
  */
226
247
  export declare function resolveTargetViewportSafeArea(layout: Pick<TargetViewportLayout, 'width' | 'height'>, insets?: Partial<TargetViewportSafeAreaInsets>): TargetViewportSafeArea;
227
248
  /**
249
+ * Resolve all edge occlusions in one CSS-pixel coordinate space. System bars
250
+ * and CSS safe-area measurements can describe the same pixels, as can a banner
251
+ * and the home-indicator inset. Taking the maximum intrusion per edge avoids
252
+ * subtracting those regions twice. A surface's bounds are absolute viewport
253
+ * coordinates, not a banner height to add to another inset.
254
+ */
255
+ export declare function resolveTargetViewportUsableArea(layout: Pick<TargetViewportLayout, 'width' | 'height'>, input?: TargetViewportUsableAreaInput): TargetViewportUsableArea;
256
+ /**
228
257
  * Read the starter's computed CSS variables. Unknown or non-pixel values are
229
258
  * intentionally treated as zero so browser shells without CSS env support keep
230
259
  * the same full-viewport layout as before.
package/dist/viewport.js CHANGED
@@ -255,6 +255,75 @@ export function resolveTargetViewportSafeArea(layout, insets) {
255
255
  },
256
256
  };
257
257
  }
258
+ /**
259
+ * Resolve all edge occlusions in one CSS-pixel coordinate space. System bars
260
+ * and CSS safe-area measurements can describe the same pixels, as can a banner
261
+ * and the home-indicator inset. Taking the maximum intrusion per edge avoids
262
+ * subtracting those regions twice. A surface's bounds are absolute viewport
263
+ * coordinates, not a banner height to add to another inset.
264
+ */
265
+ export function resolveTargetViewportUsableArea(layout, input = {}) {
266
+ const viewport = {
267
+ width: normalizeViewportDimension(layout.width, 'width'),
268
+ height: normalizeViewportDimension(layout.height, 'height'),
269
+ };
270
+ const safeArea = normalizeTargetViewportSafeAreaInsets(input.safeAreaInsets);
271
+ const systemBars = normalizeTargetViewportSafeAreaInsets(input.systemBarInsets);
272
+ const keyboard = normalizeTargetViewportSafeAreaInsets(input.keyboardInsets);
273
+ const insets = {
274
+ top: Math.max(safeArea.top, systemBars.top, keyboard.top),
275
+ right: Math.max(safeArea.right, systemBars.right, keyboard.right),
276
+ bottom: Math.max(safeArea.bottom, systemBars.bottom, keyboard.bottom),
277
+ left: Math.max(safeArea.left, systemBars.left, keyboard.left),
278
+ };
279
+ const occupiedSurfaceIds = new Set();
280
+ for (const surface of input.occupiedSurfaces ?? []) {
281
+ if (surface.surfaceId.trim() === '' || occupiedSurfaceIds.has(surface.surfaceId)) {
282
+ throw new Error('Viewport occupied surface IDs must be non-empty and unique.');
283
+ }
284
+ occupiedSurfaceIds.add(surface.surfaceId);
285
+ const { x: rawX, y: rawY, width: rawWidth, height: rawHeight } = surface.bounds;
286
+ if (![rawX, rawY, rawWidth, rawHeight].every(Number.isFinite)
287
+ || rawX < 0 || rawY < 0 || rawWidth < 0 || rawHeight < 0) {
288
+ throw new Error(`Viewport occupied surface ${surface.surfaceId} is outside the viewport.`);
289
+ }
290
+ // Round endpoints using the same whole-CSS-pixel convention as viewport
291
+ // dimensions. Rounding an origin and size separately can make a valid
292
+ // full-width fractional surface appear to exceed the rounded viewport.
293
+ const x = Math.round(rawX);
294
+ const y = Math.round(rawY);
295
+ const right = Math.round(rawX + rawWidth);
296
+ const bottom = Math.round(rawY + rawHeight);
297
+ const width = right - x;
298
+ const height = bottom - y;
299
+ if (right > viewport.width || bottom > viewport.height) {
300
+ throw new Error(`Viewport occupied surface ${surface.surfaceId} is outside the viewport.`);
301
+ }
302
+ if (width === 0 || height === 0) {
303
+ continue;
304
+ }
305
+ switch (surface.edge) {
306
+ case 'top':
307
+ insets.top = Math.max(insets.top, y + height);
308
+ break;
309
+ case 'right':
310
+ insets.right = Math.max(insets.right, viewport.width - x);
311
+ break;
312
+ case 'bottom':
313
+ insets.bottom = Math.max(insets.bottom, viewport.height - y);
314
+ break;
315
+ case 'left':
316
+ insets.left = Math.max(insets.left, x + width);
317
+ break;
318
+ default:
319
+ throw new Error('Viewport occupied surface edge is invalid.');
320
+ }
321
+ }
322
+ return {
323
+ ...resolveTargetViewportSafeArea(viewport, insets),
324
+ occupiedSurfaceIds: [...occupiedSurfaceIds],
325
+ };
326
+ }
258
327
  /**
259
328
  * Read the starter's computed CSS variables. Unknown or non-pixel values are
260
329
  * intentionally treated as zero so browser shells without CSS env support keep
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/target-config",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "Target-specific platform feature availability and effective config helpers for mpgd.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,9 +37,9 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "typia": "13.0.2",
40
- "@mpgd/catalog": "0.7.3",
41
- "@mpgd/i18n": "0.6.2",
42
- "@mpgd/platform": "0.12.1"
40
+ "@mpgd/catalog": "0.7.5",
41
+ "@mpgd/i18n": "0.6.4",
42
+ "@mpgd/platform": "0.13.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "ttsc": "0.30.4",
@@ -55,6 +55,6 @@
55
55
  "lint": "ttsc --noEmit",
56
56
  "format": "ttsc format",
57
57
  "fix": "ttsc fix",
58
- "test": "cd ../.. && node tools/run-ttsx.mjs packages/target-config/test/target-config-smoke.ts && node tools/run-ttsx.mjs packages/target-config/test/platform-version-allocation-smoke.ts"
58
+ "test": "cd ../.. && node tools/run-ttsx.mjs packages/target-config/test/target-config-smoke.ts && node tools/run-ttsx.mjs packages/target-config/test/platform-version-allocation-smoke.ts && node tools/run-ttsx.mjs packages/target-config/test/provider-availability-smoke.ts"
59
59
  }
60
60
  }