@mpgd/target-config 0.10.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/effective.js CHANGED
@@ -126,6 +126,9 @@ function effectiveProductReason(runtime, targetEnabled, product, platformProduct
126
126
  if (runtime === 'verse8-web' && product.grant.type === 'resource') {
127
127
  return 'capability-unsupported';
128
128
  }
129
+ if (runtime === 'microsoft-store-pwa' && product.type !== 'consumable') {
130
+ return 'capability-unsupported';
131
+ }
129
132
  return effectiveItemReason(targetEnabled, platformProductId);
130
133
  }
131
134
  function createEffectiveAdPlacementConfig(target, config, placement) {
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
24
24
  expected: "string",
25
25
  value: input["version"]
26
26
  }, _errorFactory);
27
+ const _ae0 = "(\"apps-in-toss\" | \"capacitor-android\" | \"capacitor-ios\" | \"devvit-web\" | \"microsoft-store-pwa\" | \"verse8-web\" | \"web\" | \"web-preview\")";
27
28
  const _ap1 = (input, _path, _exceptionable = true) => "boolean" === typeof input["iap"] || _assertGuard_1._assertGuard(_exceptionable, {
28
29
  method: "typia.createAssert",
29
30
  path: _path + ".iap",
@@ -54,7 +55,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
54
55
  expected: "string",
55
56
  value: input["id"]
56
57
  }, _errorFactory);
57
- const _ae0 = "({ 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>; })";
58
+ const _ae1 = "({ 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>; })";
58
59
  const _ap6 = (input, _path, _exceptionable = true) => "boolean" === typeof input["enabled"] || _assertGuard_1._assertGuard(_exceptionable, {
59
60
  method: "typia.createAssert",
60
61
  path: _path + ".enabled",
@@ -85,8 +86,8 @@ export const assertEffectiveTargetConfigMatrix = (() => {
85
86
  expected: "number",
86
87
  value: input["amount"]
87
88
  }, _errorFactory);
88
- const _ae1 = "(undefined | { readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
89
- const _ae2 = "({ readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
89
+ const _ae2 = "(undefined | { readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
90
+ const _ae3 = "({ readonly type: \"continue\"; readonly amount: number; } | { readonly type: \"currency\"; readonly amount: number; readonly currency: \"coin\" | \"gem\"; })";
90
91
  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, {
91
92
  method: "typia.createAssert",
92
93
  path: _path + ".targets",
@@ -122,12 +123,12 @@ export const assertEffectiveTargetConfigMatrix = (() => {
122
123
  }, _errorFactory)) && (("object" === typeof input.grant && null !== input.grant || _assertGuard_1._assertGuard(_exceptionable, {
123
124
  method: "typia.createAssert",
124
125
  path: _path + ".grant",
125
- expected: _ae0,
126
+ expected: _ae1,
126
127
  value: input.grant
127
128
  }, _errorFactory)) && _au0(input.grant, _path + ".grant", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
128
129
  method: "typia.createAssert",
129
130
  path: _path + ".grant",
130
- expected: _ae0,
131
+ expected: _ae1,
131
132
  value: input.grant
132
133
  }, _errorFactory)) && _ap6(input, _path, true && _exceptionable) && _ap7(input, _path, true && _exceptionable) && (undefined === input.platformProductId || "string" === typeof input.platformProductId || _assertGuard_1._assertGuard(_exceptionable, {
133
134
  method: "typia.createAssert",
@@ -207,12 +208,12 @@ export const assertEffectiveTargetConfigMatrix = (() => {
207
208
  }, _errorFactory)) && (undefined === input.reward || ("object" === typeof input.reward && null !== input.reward || _assertGuard_1._assertGuard(_exceptionable, {
208
209
  method: "typia.createAssert",
209
210
  path: _path + ".reward",
210
- expected: _ae1,
211
+ expected: _ae2,
211
212
  value: input.reward
212
213
  }, _errorFactory)) && _au1(input.reward, _path + ".reward", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
213
214
  method: "typia.createAssert",
214
215
  path: _path + ".reward",
215
- expected: _ae1,
216
+ expected: _ae2,
216
217
  value: input.reward
217
218
  }, _errorFactory)) && (("object" === typeof input.frequencyCap && null !== input.frequencyCap || _assertGuard_1._assertGuard(_exceptionable, {
218
219
  method: "typia.createAssert",
@@ -274,10 +275,10 @@ export const assertEffectiveTargetConfigMatrix = (() => {
274
275
  path: _path + ".target",
275
276
  expected: "string",
276
277
  value: input.target
277
- }, _errorFactory)) && ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web-preview" === input.runtime || _assertGuard_1._assertGuard(_exceptionable, {
278
+ }, _errorFactory)) && ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web" === input.runtime || "web-preview" === input.runtime || _assertGuard_1._assertGuard(_exceptionable, {
278
279
  method: "typia.createAssert",
279
280
  path: _path + ".runtime",
280
- expected: "(\"apps-in-toss\" | \"capacitor-android\" | \"capacitor-ios\" | \"devvit-web\" | \"microsoft-store-pwa\" | \"verse8-web\" | \"web-preview\")",
281
+ expected: _ae0,
281
282
  value: input.runtime
282
283
  }, _errorFactory)) && (("object" === typeof input.release && null !== input.release || _assertGuard_1._assertGuard(_exceptionable, {
283
284
  method: "typia.createAssert",
@@ -402,10 +403,10 @@ export const assertEffectiveTargetConfigMatrix = (() => {
402
403
  expected: "(\"en\" | \"ko\")",
403
404
  value: input.fallbackLocale
404
405
  }, _errorFactory));
405
- const _ao3 = (input, _path, _exceptionable = true) => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web-preview" === input.profile || _assertGuard_1._assertGuard(_exceptionable, {
406
+ const _ao3 = (input, _path, _exceptionable = true) => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web" === input.profile || "web-preview" === input.profile || _assertGuard_1._assertGuard(_exceptionable, {
406
407
  method: "typia.createAssert",
407
408
  path: _path + ".profile",
408
- expected: "(\"app-store\" | \"apps-in-toss\" | \"devvit\" | \"google-play\" | \"microsoft-store\" | \"verse8\" | \"web-preview\")",
409
+ expected: "(\"app-store\" | \"apps-in-toss\" | \"devvit\" | \"google-play\" | \"microsoft-store\" | \"verse8\" | \"web\" | \"web-preview\")",
409
410
  value: input.profile
410
411
  }, _errorFactory);
411
412
  const _ao4 = (input, _path, _exceptionable = true) => _ap1(input, _path, true && _exceptionable) && _ap2(input, _path, true && _exceptionable) && _ap3(input, _path, true && _exceptionable) && ("boolean" === typeof input.leaderboard || _assertGuard_1._assertGuard(_exceptionable, {
@@ -535,7 +536,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
535
536
  return _assertGuard_1._assertGuard(_exceptionable, {
536
537
  method: "typia.createAssert",
537
538
  path: _path,
538
- expected: _ae0,
539
+ expected: _ae1,
539
540
  value: input
540
541
  }, _errorFactory);
541
542
  })();
@@ -548,7 +549,7 @@ export const assertEffectiveTargetConfigMatrix = (() => {
548
549
  return _assertGuard_1._assertGuard(_exceptionable, {
549
550
  method: "typia.createAssert",
550
551
  path: _path,
551
- expected: _ae2,
552
+ expected: _ae3,
552
553
  value: input
553
554
  }, _errorFactory);
554
555
  })();
@@ -569,10 +570,10 @@ export const assertEffectiveTargetConfigMatrix = (() => {
569
570
  const _io17 = input => _ip8(input) && _ip10(input) && _ip9(input);
570
571
  const _io18 = input => "number" === typeof input.cooldownSeconds && (undefined === input.maxPerSession || "number" === typeof input.maxPerSession) && (undefined === input.minStageInterval || "number" === typeof input.minStageInterval);
571
572
  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);
572
- const _io2 = input => _ip0(input) && "string" === typeof input.target && ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web-preview" === 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));
573
+ const _io2 = input => _ip0(input) && "string" === typeof input.target && ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web" === input.runtime || "web-preview" === 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));
573
574
  const _io20 = input => ("local" === input.support || "native" === input.support || "none" === input.support) && _ip6(input);
574
575
  const _io21 = input => _ip6(input) && ("en" === input.fallbackLocale || "ko" === input.fallbackLocale);
575
- const _io3 = input => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web-preview" === input.profile;
576
+ const _io3 = input => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web" === input.profile || "web-preview" === input.profile;
576
577
  const _io4 = input => _ip1(input) && _ip2(input) && _ip3(input) && "boolean" === typeof input.leaderboard && _ip4(input);
577
578
  const _io5 = input => ("local" === input.storage || "native" === input.storage || "none" === input.storage) && _ip4(input);
578
579
  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);
@@ -622,6 +623,7 @@ export const assertTargetConfigMatrix = (() => {
622
623
  const _ip1 = input => "boolean" === typeof input["rewardedAds"];
623
624
  const _ip2 = input => "boolean" === typeof input["interstitialAds"];
624
625
  const _ip3 = input => "boolean" === typeof input["localization"];
626
+ const _ae0 = "(\"apps-in-toss\" | \"capacitor-android\" | \"capacitor-ios\" | \"devvit-web\" | \"microsoft-store-pwa\" | \"verse8-web\" | \"web\" | \"web-preview\")";
625
627
  const _ap0 = (input, _path, _exceptionable = true) => "boolean" === typeof input["iap"] || _assertGuard_1._assertGuard(_exceptionable, {
626
628
  method: "typia.createAssert",
627
629
  path: _path + ".iap",
@@ -709,10 +711,10 @@ export const assertTargetConfigMatrix = (() => {
709
711
  expected: "(\"fullscreen\" | \"inline-expanded\")",
710
712
  value: input.presentationMode
711
713
  }, _errorFactory));
712
- const _ao2 = (input, _path, _exceptionable = true) => ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web-preview" === input.runtime || _assertGuard_1._assertGuard(_exceptionable, {
714
+ const _ao2 = (input, _path, _exceptionable = true) => ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web" === input.runtime || "web-preview" === input.runtime || _assertGuard_1._assertGuard(_exceptionable, {
713
715
  method: "typia.createAssert",
714
716
  path: _path + ".runtime",
715
- expected: "(\"apps-in-toss\" | \"capacitor-android\" | \"capacitor-ios\" | \"devvit-web\" | \"microsoft-store-pwa\" | \"verse8-web\" | \"web-preview\")",
717
+ expected: _ae0,
716
718
  value: input.runtime
717
719
  }, _errorFactory)) && (("object" === typeof input.features && null !== input.features || _assertGuard_1._assertGuard(_exceptionable, {
718
720
  method: "typia.createAssert",
@@ -820,10 +822,10 @@ export const assertTargetConfigMatrix = (() => {
820
822
  expected: "boolean",
821
823
  value: input.native
822
824
  }, _errorFactory);
823
- const _ao8 = (input, _path, _exceptionable = true) => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web-preview" === input.profile || _assertGuard_1._assertGuard(_exceptionable, {
825
+ const _ao8 = (input, _path, _exceptionable = true) => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web" === input.profile || "web-preview" === input.profile || _assertGuard_1._assertGuard(_exceptionable, {
824
826
  method: "typia.createAssert",
825
827
  path: _path + ".profile",
826
- expected: "(\"app-store\" | \"apps-in-toss\" | \"devvit\" | \"google-play\" | \"microsoft-store\" | \"verse8\" | \"web-preview\")",
828
+ expected: "(\"app-store\" | \"apps-in-toss\" | \"devvit\" | \"google-play\" | \"microsoft-store\" | \"verse8\" | \"web\" | \"web-preview\")",
827
829
  value: input.profile
828
830
  }, _errorFactory);
829
831
  const _ao9 = (input, _path, _exceptionable = true) => ("boolean" === typeof input.externalPaymentAllowed || _assertGuard_1._assertGuard(_exceptionable, {
@@ -860,13 +862,13 @@ export const assertTargetConfigMatrix = (() => {
860
862
  return "object" === typeof value && null !== value && _io2(value);
861
863
  });
862
864
  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);
863
- const _io2 = input => ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web-preview" === 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));
865
+ const _io2 = input => ("apps-in-toss" === input.runtime || "capacitor-android" === input.runtime || "capacitor-ios" === input.runtime || "devvit-web" === input.runtime || "microsoft-store-pwa" === input.runtime || "verse8-web" === input.runtime || "web" === input.runtime || "web-preview" === 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));
864
866
  const _io3 = input => _ip0(input) && _ip1(input) && _ip2(input) && "boolean" === typeof input.leaderboard && _ip3(input);
865
867
  const _io4 = input => ("local" === input.storage || "native" === input.storage || "none" === input.storage) && _ip3(input);
866
868
  const _io5 = input => "en" === input.fallbackLocale || "ko" === input.fallbackLocale;
867
869
  const _io6 = input => _ip0(input) && _ip1(input) && _ip2(input);
868
870
  const _io7 = input => "boolean" === typeof input.native;
869
- const _io8 = input => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web-preview" === input.profile;
871
+ const _io8 = input => "app-store" === input.profile || "apps-in-toss" === input.profile || "devvit" === input.profile || "google-play" === input.profile || "microsoft-store" === input.profile || "verse8" === input.profile || "web" === input.profile || "web-preview" === input.profile;
870
872
  const _io9 = input => "boolean" === typeof input.externalPaymentAllowed && "boolean" === typeof input.remoteExecutableCodeAllowed && "boolean" === typeof input.installOtherAppCTAAllowed && "boolean" === typeof input.requiresStoreReview && "boolean" === typeof input.requiresAitReview;
871
873
  const __is = input => "object" === typeof input && null !== input && _io0(input);
872
874
  let _errorFactory;
package/dist/runtime.d.ts CHANGED
@@ -4,8 +4,8 @@ import type { EffectiveTargetConfig } from './effective.js';
4
4
  export type PlatformFeature = 'iap' | 'rewardedAds' | 'interstitialAds' | 'leaderboard' | 'localization';
5
5
  export type AdPlacementType = 'rewarded' | 'interstitial';
6
6
  type PlatformConfigTarget = PlatformGateway['target'];
7
- export type TargetRuntimeKind = 'web-preview' | 'microsoft-store-pwa' | 'capacitor-android' | 'capacitor-ios' | 'apps-in-toss' | 'devvit-web' | 'verse8-web';
8
- export type ReleaseProfile = 'web-preview' | 'microsoft-store' | 'google-play' | 'app-store' | 'apps-in-toss' | 'devvit' | 'verse8';
7
+ export type TargetRuntimeKind = 'web' | 'web-preview' | 'microsoft-store-pwa' | 'capacitor-android' | 'capacitor-ios' | 'apps-in-toss' | 'devvit-web' | 'verse8-web';
8
+ export type ReleaseProfile = 'web' | 'web-preview' | 'microsoft-store' | 'google-play' | 'app-store' | 'apps-in-toss' | 'devvit' | 'verse8';
9
9
  export type StorageSupport = 'local' | 'native' | 'none';
10
10
  export type TargetIntegration = 'identityUpgrade' | 'presentation' | 'sharing' | 'inboundShare' | 'notifications';
11
11
  export type IntegrationAvailabilityState = 'available' | 'disabled' | 'approval-required' | 'configuration-required' | 'unsupported';
package/dist/runtime.js CHANGED
@@ -111,6 +111,7 @@ export function applyTargetConfigToCapabilities(capabilities, config) {
111
111
  rewardedAds: capabilities.rewardedAds && config.features.rewardedAds,
112
112
  interstitialAds: capabilities.interstitialAds && config.features.interstitialAds,
113
113
  nativeLeaderboard: capabilities.nativeLeaderboard && config.features.leaderboard,
114
+ remoteLeaderboard: capabilities.remoteLeaderboard && config.features.leaderboard,
114
115
  localizedContent: capabilities.localizedContent && config.features.localization,
115
116
  };
116
117
  }
@@ -206,6 +207,13 @@ export function withTargetAvailability(gateway, config, options = {}) {
206
207
  };
207
208
  const notifications = notificationsAvailable ? gatewayNotifications : undefined;
208
209
  const isIapAvailable = async () => (availabilityConfig.features.iap && (await getGatewayCapabilities()).nativeIap);
210
+ const isLeaderboardAvailable = async () => {
211
+ if (!availabilityConfig.features.leaderboard) {
212
+ return false;
213
+ }
214
+ const capabilities = await getGatewayCapabilities();
215
+ return capabilities.nativeLeaderboard || capabilities.remoteLeaderboard;
216
+ };
209
217
  const isAdPlacementAllowed = (placementId, expectedType) => {
210
218
  const actualType = options.resolveAdPlacementType?.(placementId);
211
219
  if (actualType !== undefined && actualType !== expectedType) {
@@ -303,16 +311,21 @@ export function withTargetAvailability(gateway, config, options = {}) {
303
311
  return gateway.ads.showInterstitial(input);
304
312
  },
305
313
  },
306
- leaderboard: availabilityConfig.features.leaderboard
307
- ? gateway.leaderboard
308
- : {
309
- async submitScore() {
314
+ leaderboard: {
315
+ async submitScore(input) {
316
+ if (!await isLeaderboardAvailable()) {
310
317
  return {
311
318
  submitted: false,
312
319
  };
313
- },
314
- async open() { },
320
+ }
321
+ return gateway.leaderboard.submitScore(input);
315
322
  },
323
+ async open(input) {
324
+ if (await isLeaderboardAvailable()) {
325
+ await gateway.leaderboard.open(input);
326
+ }
327
+ },
328
+ },
316
329
  };
317
330
  }
318
331
  function resolveAvailabilityConfig(config, effectiveConfig) {
@@ -335,7 +348,7 @@ function isFeatureCapabilitySupported(feature, capabilities) {
335
348
  case 'interstitialAds':
336
349
  return capabilities.interstitialAds;
337
350
  case 'leaderboard':
338
- return capabilities.nativeLeaderboard;
351
+ return capabilities.nativeLeaderboard || capabilities.remoteLeaderboard;
339
352
  case 'localization':
340
353
  return capabilities.localizedContent;
341
354
  }
@@ -15,6 +15,10 @@ export type TargetViewportMeasurementSource = 'container' | 'visual-viewport' |
15
15
  export type TargetViewportControlPlacement = 'bottom' | 'side';
16
16
  /** Recommended placement for secondary game panels. */
17
17
  export type TargetViewportPanelPlacement = 'below' | 'side' | 'drawer';
18
+ /** Adaptive shell arrangement for a game surface and its surrounding UI. */
19
+ export type TargetViewportCompositionMode = 'side-rails' | 'bottom-controls' | 'compact-portrait';
20
+ /** Optional expanded-screen arrangement requested by a game. */
21
+ export type TargetViewportExpandedLayout = 'none' | 'side-rails';
18
22
  /** Width thresholds used to classify target viewports. */
19
23
  export interface TargetViewportBreakpoints {
20
24
  readonly compactMaxWidth: number;
@@ -109,6 +113,36 @@ export interface TargetViewportSnapshot extends TargetViewportPlan {
109
113
  readonly safeArea: TargetViewportSafeArea;
110
114
  }
111
115
  /**
116
+ * Input for resolving a concrete adaptive game shell from an existing viewport
117
+ * snapshot. The aspect ratio is expressed as width divided by height.
118
+ */
119
+ export interface TargetViewportCompositionInput {
120
+ readonly viewport: Pick<TargetViewportSnapshot, 'layout' | 'safeArea'>;
121
+ readonly gameAspectRatio: number;
122
+ readonly expandedLayout?: TargetViewportExpandedLayout;
123
+ readonly minRailWidth?: number;
124
+ }
125
+ interface TargetViewportCompositionBounds {
126
+ readonly contentBounds: TargetViewportBounds;
127
+ readonly gameBounds: TargetViewportBounds;
128
+ }
129
+ /** Concrete safe-area-relative geometry for an adaptive game shell. */
130
+ export type TargetViewportComposition = TargetViewportCompositionBounds & ({
131
+ readonly mode: 'side-rails';
132
+ readonly leftRailBounds: TargetViewportBounds;
133
+ readonly rightRailBounds: TargetViewportBounds;
134
+ readonly primaryControls: 'side';
135
+ readonly secondaryPanels: 'side';
136
+ } | {
137
+ readonly mode: 'bottom-controls';
138
+ readonly primaryControls: 'bottom';
139
+ readonly secondaryPanels: 'below';
140
+ } | {
141
+ readonly mode: 'compact-portrait';
142
+ readonly primaryControls: 'bottom';
143
+ readonly secondaryPanels: 'drawer';
144
+ });
145
+ /**
112
146
  * The minimal browser style surface needed to read CSS safe-area custom
113
147
  * properties. Keeping this structural avoids a runtime DOM dependency in the
114
148
  * target-config package.
@@ -151,6 +185,8 @@ export declare const defaultTargetViewportSafeAreaCssVariables: {
151
185
  readonly bottom: '--mpgd-safe-area-bottom';
152
186
  readonly left: '--mpgd-safe-area-left';
153
187
  };
188
+ /** Default minimum width for each expanded-layout side rail. */
189
+ export declare const defaultTargetViewportCompositionMinRailWidth = 160;
154
190
  /** Map a configured target runtime to its viewport host shell. */
155
191
  export declare function targetViewportShellForRuntime(runtime: TargetRuntimeKind): TargetViewportShell;
156
192
  /** Resolve a viewport shell from the runtime field of a target config. */
@@ -171,6 +207,15 @@ export declare function resolveTargetViewportPlan(input: TargetViewportInput, br
171
207
  */
172
208
  export declare function resolveTargetViewportSnapshot(input: TargetViewportSnapshotInput, breakpoints?: TargetViewportBreakpoints): TargetViewportSnapshot;
173
209
  /**
210
+ * Resolve an adaptive game shell inside the snapshot's safe content bounds.
211
+ *
212
+ * A landscape viewport uses side rails only when the requested game aspect and
213
+ * both minimum rails fit at full content height. Portrait viewports remain
214
+ * full-bleed so phone shells do not inherit desktop letterboxing. Intermediate
215
+ * layouts keep the full game bounds and move persistent controls to the bottom.
216
+ */
217
+ export declare function resolveTargetViewportComposition(input: TargetViewportCompositionInput): TargetViewportComposition;
218
+ /**
174
219
  * Resolve safe-area insets and content bounds for a given layout.
175
220
  *
176
221
  * Insets are clamped sequentially (top before bottom, left before right) so
@@ -185,3 +230,4 @@ export declare function resolveTargetViewportSafeArea(layout: Pick<TargetViewpor
185
230
  * the same full-viewport layout as before.
186
231
  */
187
232
  export declare function readTargetViewportSafeAreaInsets(style: TargetViewportComputedStyle, variables?: TargetViewportSafeAreaCssVariables): TargetViewportSafeAreaInsets;
233
+ export {};
package/dist/viewport.js CHANGED
@@ -26,6 +26,8 @@ export const defaultTargetViewportSafeAreaCssVariables = {
26
26
  bottom: '--mpgd-safe-area-bottom',
27
27
  left: '--mpgd-safe-area-left',
28
28
  };
29
+ /** Default minimum width for each expanded-layout side rail. */
30
+ export const defaultTargetViewportCompositionMinRailWidth = 160;
29
31
  const targetViewportOrientationPolicyModeDescriptors = {
30
32
  responsive: {
31
33
  preferredOrientation: undefined,
@@ -63,6 +65,7 @@ export function targetViewportShellForRuntime(runtime) {
63
65
  case 'devvit-web':
64
66
  case 'verse8-web':
65
67
  return 'embedded-webview';
68
+ case 'web':
66
69
  case 'web-preview':
67
70
  case 'microsoft-store-pwa':
68
71
  return 'browser';
@@ -146,6 +149,80 @@ export function resolveTargetViewportSnapshot(input, breakpoints = defaultTarget
146
149
  safeArea: resolveTargetViewportSafeArea(plan.layout, input.safeAreaInsets),
147
150
  };
148
151
  }
152
+ /**
153
+ * Resolve an adaptive game shell inside the snapshot's safe content bounds.
154
+ *
155
+ * A landscape viewport uses side rails only when the requested game aspect and
156
+ * both minimum rails fit at full content height. Portrait viewports remain
157
+ * full-bleed so phone shells do not inherit desktop letterboxing. Intermediate
158
+ * layouts keep the full game bounds and move persistent controls to the bottom.
159
+ */
160
+ export function resolveTargetViewportComposition(input) {
161
+ const gameAspectRatio = normalizeViewportAspectRatio(input.gameAspectRatio);
162
+ const minRailWidth = normalizeViewportMinimum(input.minRailWidth ?? defaultTargetViewportCompositionMinRailWidth, 'minRailWidth');
163
+ const contentBounds = { ...input.viewport.safeArea.contentBounds };
164
+ const portrait = input.viewport.layout.orientation === 'portrait';
165
+ if (portrait) {
166
+ if (input.viewport.layout.sizeClass === 'compact') {
167
+ return {
168
+ mode: 'compact-portrait',
169
+ contentBounds,
170
+ gameBounds: contentBounds,
171
+ primaryControls: 'bottom',
172
+ secondaryPanels: 'drawer',
173
+ };
174
+ }
175
+ return {
176
+ mode: 'bottom-controls',
177
+ contentBounds,
178
+ gameBounds: contentBounds,
179
+ primaryControls: 'bottom',
180
+ secondaryPanels: 'below',
181
+ };
182
+ }
183
+ const requestedSideRails = input.expandedLayout === 'side-rails';
184
+ const minimumGameWidth = contentBounds.width > 0 && contentBounds.height > 0 ? 1 : 0;
185
+ const desiredGameWidth = Math.max(minimumGameWidth, Math.round(contentBounds.height * gameAspectRatio));
186
+ const fittedGameWidth = Math.min(contentBounds.width, desiredGameWidth);
187
+ const availableRailWidth = (contentBounds.width - fittedGameWidth) / 2;
188
+ if (requestedSideRails &&
189
+ input.viewport.layout.sizeClass === 'expanded' &&
190
+ desiredGameWidth <= contentBounds.width &&
191
+ availableRailWidth >= minRailWidth) {
192
+ const gameBounds = {
193
+ x: contentBounds.x + availableRailWidth,
194
+ y: contentBounds.y,
195
+ width: fittedGameWidth,
196
+ height: contentBounds.height,
197
+ };
198
+ return {
199
+ mode: 'side-rails',
200
+ contentBounds,
201
+ gameBounds,
202
+ leftRailBounds: {
203
+ x: contentBounds.x,
204
+ y: contentBounds.y,
205
+ width: availableRailWidth,
206
+ height: contentBounds.height,
207
+ },
208
+ rightRailBounds: {
209
+ x: gameBounds.x + gameBounds.width,
210
+ y: contentBounds.y,
211
+ width: availableRailWidth,
212
+ height: contentBounds.height,
213
+ },
214
+ primaryControls: 'side',
215
+ secondaryPanels: 'side',
216
+ };
217
+ }
218
+ return {
219
+ mode: 'bottom-controls',
220
+ contentBounds,
221
+ gameBounds: contentBounds,
222
+ primaryControls: 'bottom',
223
+ secondaryPanels: 'below',
224
+ };
225
+ }
149
226
  /**
150
227
  * Resolve safe-area insets and content bounds for a given layout.
151
228
  *
@@ -245,6 +322,20 @@ function normalizeViewportInset(value, name) {
245
322
  }
246
323
  return Math.round(value);
247
324
  }
325
+ /** Validate a non-negative CSS-pixel minimum without discarding fractions. */
326
+ function normalizeViewportMinimum(value, name) {
327
+ if (!Number.isFinite(value) || value < 0) {
328
+ throw new Error(`Viewport ${name} must be a non-negative finite number.`);
329
+ }
330
+ return value;
331
+ }
332
+ /** Validate a finite positive width-to-height aspect ratio. */
333
+ function normalizeViewportAspectRatio(value) {
334
+ if (!Number.isFinite(value) || value <= 0) {
335
+ throw new Error('Viewport gameAspectRatio must be a positive finite number.');
336
+ }
337
+ return value;
338
+ }
248
339
  /** Parse a non-negative CSS pixel custom-property value. */
249
340
  function readTargetViewportCssPixels(style, property) {
250
341
  const value = style.getPropertyValue(property).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/target-config",
3
- "version": "0.10.1",
3
+ "version": "0.12.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.5.2",
41
- "@mpgd/platform": "0.8.0",
42
- "@mpgd/i18n": "0.5.4"
40
+ "@mpgd/catalog": "0.6.0",
41
+ "@mpgd/i18n": "0.5.5",
42
+ "@mpgd/platform": "0.9.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "ttsc": "0.18.4",
package/targets.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026-07-19.1",
2
+ "version": "2026-08-12",
3
3
  "targets": {
4
4
  "web-preview": {
5
5
  "runtime": "web-preview",
@@ -47,10 +47,10 @@
47
47
  "microsoft-store": {
48
48
  "runtime": "microsoft-store-pwa",
49
49
  "features": {
50
- "iap": false,
50
+ "iap": true,
51
51
  "rewardedAds": false,
52
52
  "interstitialAds": false,
53
- "leaderboard": false,
53
+ "leaderboard": true,
54
54
  "localization": true
55
55
  },
56
56
  "capabilities": {
@@ -61,7 +61,7 @@
61
61
  "fallbackLocale": "en"
62
62
  },
63
63
  "monetization": {
64
- "iap": false,
64
+ "iap": true,
65
65
  "rewardedAds": false,
66
66
  "interstitialAds": false
67
67
  },