@mpgd/adapter-ait 0.6.0 → 0.8.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/host.d.ts CHANGED
@@ -1,22 +1,68 @@
1
- import { getTossShareLink, isMinVersionSupported, loadFullScreenAd, openGameCenterLeaderboard, share, showFullScreenAd, Storage, submitGameCenterLeaderBoardScore } from '@apps-in-toss/web-framework';
2
- import type { ShareResult } from '@mpgd/platform';
1
+ import { getTossShareLink, grantPromotionRewardForGame as grantPromotionReward, isMinVersionSupported, loadFullScreenAd, openGameCenterLeaderboard, requestNotificationAgreement, share, showFullScreenAd, Storage, submitGameCenterLeaderBoardScore } from '@apps-in-toss/web-framework';
2
+ import type { NotificationTopic, ShareResult } from '@mpgd/platform';
3
3
  import type { GamePlatformBridge } from './index.js';
4
4
  export type AitIdentityProvider = () => Promise<unknown>;
5
5
  export interface AitHostDependencies {
6
6
  readonly identityProvider: AitIdentityProvider;
7
- readonly storage: Pick<typeof Storage, 'getItem' | 'setItem'>;
7
+ readonly storage: Pick<typeof Storage, 'getItem' | 'removeItem' | 'setItem'>;
8
8
  readonly getTossShareLink: typeof getTossShareLink;
9
9
  readonly share: typeof share;
10
+ readonly grantPromotionReward: typeof grantPromotionReward;
11
+ readonly requestNotificationAgreement: typeof requestNotificationAgreement;
10
12
  readonly isMinVersionSupported: typeof isMinVersionSupported;
11
13
  readonly loadFullScreenAd: typeof loadFullScreenAd;
12
14
  readonly showFullScreenAd: typeof showFullScreenAd;
13
15
  readonly openGameCenterLeaderboard: typeof openGameCenterLeaderboard;
14
16
  readonly submitGameCenterLeaderBoardScore: typeof submitGameCenterLeaderBoardScore;
15
17
  }
18
+ export interface AitPromotionRewardConfig {
19
+ readonly promotionCode: string;
20
+ readonly amount: number;
21
+ }
22
+ export interface AitPendingPromotionGrantInput {
23
+ readonly campaignId: string;
24
+ readonly idempotencyKey: string;
25
+ /** Missing for legacy or malformed pending markers; resolvers must fail closed. */
26
+ readonly pendingSince?: string;
27
+ }
28
+ export type AitPendingPromotionGrantResolution = {
29
+ readonly status: 'granted';
30
+ readonly receiptKey: string;
31
+ } | {
32
+ readonly status: 'retry' | 'pending';
33
+ };
34
+ /**
35
+ * Server-backed reconciliation hook for an ambiguous native promotion call.
36
+ * Returning `retry` must only happen after the game authority decides that a
37
+ * second provider call is safe for this single-use claim id.
38
+ */
39
+ export type AitPendingPromotionGrantResolver = (input: AitPendingPromotionGrantInput) => Promise<AitPendingPromotionGrantResolution>;
40
+ export interface AitPromotionGrantAuthorizationInput {
41
+ readonly campaignId: string;
42
+ /** Single-use claim id issued by the game backend. */
43
+ readonly idempotencyKey: string;
44
+ }
45
+ export type AitPromotionGrantAuthorization = {
46
+ readonly status: 'authorized';
47
+ } | {
48
+ readonly status: 'pending' | 'rejected';
49
+ };
50
+ /**
51
+ * Server-backed gate for the first provider call. A configured campaign is not
52
+ * available until this hook confirms that the idempotency key is a genuine,
53
+ * single-use game claim.
54
+ */
55
+ export type AitPromotionGrantAuthorizer = (input: AitPromotionGrantAuthorizationInput) => Promise<AitPromotionGrantAuthorization>;
16
56
  export interface InstallAitHostBridgeOptions {
17
57
  readonly appName?: string;
18
58
  readonly adGroupIds?: Readonly<Record<string, string>>;
19
59
  readonly adPlacementTypes?: Readonly<Record<string, 'rewarded' | 'interstitial'>>;
60
+ /** Logical campaign ids mapped to console-issued Apps in Toss promotion configuration. */
61
+ readonly promotionRewards?: Readonly<Record<string, AitPromotionRewardConfig>>;
62
+ readonly authorizePromotionGrant?: AitPromotionGrantAuthorizer;
63
+ readonly resolvePendingPromotionGrant?: AitPendingPromotionGrantResolver;
64
+ /** Logical notification topics mapped to approved Apps in Toss template codes. */
65
+ readonly notificationTemplateCodes?: Partial<Readonly<Record<NotificationTopic, string>>>;
20
66
  /** Maximum total wait for the native show request before display is observed. */
21
67
  readonly adTimeoutMs?: number;
22
68
  /** Maximum wait to acquire the process-wide native full-screen load slot. */
package/dist/host.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getTossShareLink, getUserKeyForGame, isMinVersionSupported, loadFullScreenAd, openGameCenterLeaderboard, share, showFullScreenAd, Storage, submitGameCenterLeaderBoardScore, } from '@apps-in-toss/web-framework';
1
+ import { getTossShareLink, getUserKeyForGame, grantPromotionRewardForGame as grantPromotionReward, isMinVersionSupported, loadFullScreenAd, openGameCenterLeaderboard, requestNotificationAgreement, share, showFullScreenAd, Storage, submitGameCenterLeaderBoardScore, } from '@apps-in-toss/web-framework';
2
2
  import { assertBridgeRequest, bridgeStorageLoadProtocol, } from '@mpgd/bridge';
3
3
  import { dispatchAitLifecycleEvent } from './lifecycle.js';
4
4
  const defaultAdTimeoutMs = 60000;
@@ -7,6 +7,14 @@ const defaultAdDisplayStartTimeoutMs = 60000;
7
7
  const defaultAdMaximumDisplayMs = 30 * 60000;
8
8
  const invalidBridgeRequestId = 'ait-invalid-request';
9
9
  const rewardedAdEvidenceSchema = 'apps-in-toss.rewarded-ad.callback.v1';
10
+ const minimumPromotionTossAppVersion = '5.232.0';
11
+ const promotionGrantStoragePrefix = 'mpgd:ait:promotion-grant:v1:';
12
+ const defaultNotificationAgreementTimeoutMs = 120000;
13
+ const notificationTopics = new Set([
14
+ 'daily-ready',
15
+ 'streak-at-risk',
16
+ 'friend-challenge',
17
+ ]);
10
18
  const launchEntries = new Set([
11
19
  'home',
12
20
  'daily',
@@ -21,6 +29,8 @@ const defaultDependencies = {
21
29
  storage: Storage,
22
30
  getTossShareLink,
23
31
  share,
32
+ grantPromotionReward,
33
+ requestNotificationAgreement,
24
34
  isMinVersionSupported,
25
35
  loadFullScreenAd,
26
36
  showFullScreenAd,
@@ -37,6 +47,12 @@ export function createAitHostBridge(options = {}) {
37
47
  const appName = normalizeAppName(options.appName ?? 'mpgd-kit');
38
48
  const adGroupIds = normalizeAdGroupIds(options.adGroupIds);
39
49
  const adPlacementTypes = normalizeAdPlacementTypes(options.adPlacementTypes);
50
+ const promotionRewards = normalizePromotionRewards(options.promotionRewards);
51
+ const authorizePromotionGrant = options.authorizePromotionGrant;
52
+ const resolvePendingPromotionGrant = options.resolvePendingPromotionGrant;
53
+ const notificationTemplateCodes = normalizeNotificationTemplateCodes(options.notificationTemplateCodes);
54
+ const promotionGrantsInFlight = new Map();
55
+ const notificationSubscriptions = new Set();
40
56
  const loadedAdGroupIds = new Set();
41
57
  const loadingAdGroups = new Map();
42
58
  const activeAdGroupIds = new Set();
@@ -111,9 +127,67 @@ export function createAitHostBridge(options = {}) {
111
127
  case 'share.readInboundShare':
112
128
  return ok(request, readInboundShare());
113
129
  case 'notifications.getStatus':
114
- return ok(request, 'unsupported');
115
- case 'notifications.requestSubscription':
116
- return ok(request, 'unavailable');
130
+ return ok(request, getNotificationStatus(readNotificationTopic(request.payload), notificationTemplateCodes, notificationSubscriptions, dependencies));
131
+ case 'notifications.requestSubscription': {
132
+ const topic = readNotificationTopic(request.payload);
133
+ const templateCode = notificationTemplateCodes.get(topic);
134
+ if (templateCode === undefined
135
+ || !isCapabilitySupported(() => dependencies.requestNotificationAgreement.isSupported())) {
136
+ return ok(request, 'unavailable');
137
+ }
138
+ const result = await requestAitNotificationAgreement(dependencies.requestNotificationAgreement, templateCode);
139
+ if (result === 'subscribed') {
140
+ notificationSubscriptions.add(topic);
141
+ }
142
+ return ok(request, result);
143
+ }
144
+ case 'promotions.getAvailability': {
145
+ const campaignId = readCampaignId(request.payload);
146
+ const availability = getPromotionAvailability(campaignId, promotionRewards, authorizePromotionGrant, dependencies);
147
+ return ok(request, availability);
148
+ }
149
+ case 'promotions.grantReward': {
150
+ const campaignId = readCampaignId(request.payload);
151
+ const reward = promotionRewards.get(campaignId);
152
+ const idempotencyKey = readRequiredIdempotencyKey(request.payload);
153
+ if (reward === undefined
154
+ || !isPromotionSupported(dependencies)) {
155
+ return ok(request, { status: 'unavailable' });
156
+ }
157
+ const persisted = await resolvePersistedPromotionGrant({
158
+ campaignId,
159
+ idempotencyKey,
160
+ storage: dependencies.storage,
161
+ ...(resolvePendingPromotionGrant === undefined
162
+ ? {}
163
+ : { resolver: resolvePendingPromotionGrant }),
164
+ });
165
+ if (persisted.result !== undefined) {
166
+ return ok(request, persisted.result);
167
+ }
168
+ const existing = promotionGrantsInFlight.get(idempotencyKey);
169
+ if (existing !== undefined) {
170
+ return ok(request, await existing);
171
+ }
172
+ const pending = authorizeAndGrantAitPromotionReward({
173
+ campaignId,
174
+ idempotencyKey,
175
+ reward,
176
+ dependencies,
177
+ ...(authorizePromotionGrant === undefined
178
+ ? {}
179
+ : { authorizer: authorizePromotionGrant }),
180
+ });
181
+ promotionGrantsInFlight.set(idempotencyKey, pending);
182
+ try {
183
+ return ok(request, await pending);
184
+ }
185
+ finally {
186
+ if (promotionGrantsInFlight.get(idempotencyKey) === pending) {
187
+ promotionGrantsInFlight.delete(idempotencyKey);
188
+ }
189
+ }
190
+ }
117
191
  // IAP must be installed with game-owned server verification. Never return demo grants.
118
192
  case 'commerce.getProducts':
119
193
  return ok(request, []);
@@ -228,6 +302,227 @@ export function createAitHostBridge(options = {}) {
228
302
  }
229
303
  }
230
304
  }
305
+ function getNotificationStatus(topic, templateCodes, subscriptions, dependencies) {
306
+ if (!templateCodes.has(topic)) {
307
+ return 'configuration-required';
308
+ }
309
+ if (!isCapabilitySupported(() => dependencies.requestNotificationAgreement.isSupported())) {
310
+ return 'unsupported';
311
+ }
312
+ return subscriptions.has(topic) ? 'subscribed' : 'not-subscribed';
313
+ }
314
+ function requestAitNotificationAgreement(requestAgreement, templateCode) {
315
+ return new Promise((resolve) => {
316
+ let settled = false;
317
+ let cleanup = () => { };
318
+ const finish = (result) => {
319
+ if (settled) {
320
+ return;
321
+ }
322
+ settled = true;
323
+ globalThis.clearTimeout(timer);
324
+ cleanup();
325
+ resolve(result);
326
+ };
327
+ const timer = globalThis.setTimeout(() => finish('unavailable'), defaultNotificationAgreementTimeoutMs);
328
+ try {
329
+ const unregister = requestAgreement({
330
+ options: { templateCode },
331
+ onEvent: ({ type }) => {
332
+ finish(type === 'agreementRejected' ? 'rejected' : 'subscribed');
333
+ },
334
+ onError: () => finish('unavailable'),
335
+ });
336
+ cleanup = unregister;
337
+ if (settled) {
338
+ cleanup();
339
+ }
340
+ }
341
+ catch {
342
+ finish('unavailable');
343
+ }
344
+ });
345
+ }
346
+ function getPromotionAvailability(campaignId, rewards, authorizer, dependencies) {
347
+ if (!rewards.has(campaignId) || authorizer === undefined) {
348
+ return 'configuration-required';
349
+ }
350
+ return isPromotionSupported(dependencies) ? 'available' : 'unsupported';
351
+ }
352
+ async function authorizeAndGrantAitPromotionReward(input) {
353
+ if (input.authorizer === undefined) {
354
+ return { status: 'unavailable' };
355
+ }
356
+ let authorization;
357
+ try {
358
+ authorization = await input.authorizer({
359
+ campaignId: input.campaignId,
360
+ idempotencyKey: input.idempotencyKey,
361
+ });
362
+ }
363
+ catch (error) {
364
+ console.warn('AIT promotion grant authorization failed; keeping the claim pending.', input.campaignId, error);
365
+ return { status: 'pending' };
366
+ }
367
+ if (authorization.status !== 'authorized') {
368
+ return {
369
+ status: authorization.status === 'pending' ? 'pending' : 'unavailable',
370
+ };
371
+ }
372
+ return grantAitPromotionReward(input.dependencies, input.reward, input.idempotencyKey);
373
+ }
374
+ function isPromotionSupported(dependencies) {
375
+ return isCapabilitySupported(() => dependencies.isMinVersionSupported({
376
+ android: minimumPromotionTossAppVersion,
377
+ ios: minimumPromotionTossAppVersion,
378
+ }));
379
+ }
380
+ async function grantAitPromotionReward(dependencies, reward, idempotencyKey) {
381
+ const storageKey = promotionGrantStorageKey(idempotencyKey);
382
+ await dependencies.storage.setItem(storageKey, JSON.stringify({
383
+ status: 'pending',
384
+ pendingSince: new Date().toISOString(),
385
+ }));
386
+ try {
387
+ const response = await dependencies.grantPromotionReward({
388
+ params: {
389
+ promotionCode: reward.promotionCode,
390
+ amount: reward.amount,
391
+ },
392
+ });
393
+ if (isExplicitPromotionFailure(response)) {
394
+ return clearFailedPromotionGrant(dependencies.storage, storageKey);
395
+ }
396
+ if (!isRecord(response)
397
+ || typeof response.key !== 'string'
398
+ || response.key.trim().length === 0) {
399
+ // An undocumented shape is ambiguous after native dispatch. Preserve the
400
+ // marker so a backend resolver can determine whether a grant happened.
401
+ return { status: 'pending' };
402
+ }
403
+ const result = { status: 'granted', receiptKey: response.key };
404
+ try {
405
+ await dependencies.storage.setItem(storageKey, JSON.stringify(result));
406
+ }
407
+ catch (error) {
408
+ console.warn('AIT native promotion receipt could not be cached; keeping it terminal.', reward.promotionCode, error);
409
+ }
410
+ return result;
411
+ }
412
+ catch {
413
+ // Keep the pending marker. A provider error after dispatch is ambiguous and
414
+ // retrying the same promotion blindly can double-grant Toss points.
415
+ return { status: 'pending' };
416
+ }
417
+ }
418
+ function isExplicitPromotionFailure(value) {
419
+ if (value === 'ERROR') {
420
+ return true;
421
+ }
422
+ return isRecord(value)
423
+ && typeof value.errorCode === 'string'
424
+ && value.errorCode.trim().length > 0
425
+ && typeof value.message === 'string';
426
+ }
427
+ async function clearFailedPromotionGrant(storage, storageKey) {
428
+ try {
429
+ await storage.removeItem(storageKey);
430
+ return { status: 'failed' };
431
+ }
432
+ catch (error) {
433
+ console.warn('AIT failed promotion marker could not be cleared; keeping the claim pending.', storageKey, error);
434
+ return { status: 'pending' };
435
+ }
436
+ }
437
+ async function resolvePersistedPromotionGrant(input) {
438
+ const storageKey = promotionGrantStorageKey(input.idempotencyKey);
439
+ const serialized = await input.storage.getItem(storageKey);
440
+ if (serialized === null) {
441
+ return {};
442
+ }
443
+ let state;
444
+ try {
445
+ state = JSON.parse(serialized);
446
+ }
447
+ catch (error) {
448
+ console.warn('AIT persisted promotion state is unreadable; keeping the claim pending.', input.campaignId, error);
449
+ return { result: { status: 'pending' } };
450
+ }
451
+ if (!isRecord(state)) {
452
+ console.warn('AIT persisted promotion state is malformed; keeping the claim pending.', input.campaignId);
453
+ return { result: { status: 'pending' } };
454
+ }
455
+ try {
456
+ if (state.status === 'granted'
457
+ && typeof state.receiptKey === 'string'
458
+ && state.receiptKey.trim().length > 0) {
459
+ return { result: { status: 'granted', receiptKey: state.receiptKey } };
460
+ }
461
+ if (state.status === 'pending') {
462
+ const pendingSince = normalizePendingSince(state.pendingSince);
463
+ if (pendingSince === undefined) {
464
+ return { result: { status: 'pending' } };
465
+ }
466
+ if (input.resolver === undefined) {
467
+ return { result: { status: 'pending' } };
468
+ }
469
+ let resolution;
470
+ try {
471
+ resolution = await input.resolver({
472
+ campaignId: input.campaignId,
473
+ idempotencyKey: input.idempotencyKey,
474
+ pendingSince,
475
+ });
476
+ }
477
+ catch (error) {
478
+ console.warn('AIT pending promotion grant resolver failed; keeping the claim pending.', input.campaignId, error);
479
+ return { result: { status: 'pending' } };
480
+ }
481
+ if (resolution.status === 'pending') {
482
+ return { result: { status: 'pending' } };
483
+ }
484
+ if (resolution.status === 'granted') {
485
+ if (typeof resolution.receiptKey !== 'string'
486
+ || resolution.receiptKey.trim().length === 0) {
487
+ return { result: { status: 'pending' } };
488
+ }
489
+ const result = { status: 'granted', receiptKey: resolution.receiptKey };
490
+ try {
491
+ await input.storage.setItem(storageKey, JSON.stringify(result));
492
+ }
493
+ catch (error) {
494
+ console.warn('AIT reconciled promotion receipt could not be cached; keeping it terminal.', input.campaignId, error);
495
+ }
496
+ return { result };
497
+ }
498
+ return removeInvalidPersistedPromotionGrant(input.storage, storageKey);
499
+ }
500
+ console.warn('AIT persisted promotion state has an unknown status; keeping the claim pending.', input.campaignId);
501
+ return { result: { status: 'pending' } };
502
+ }
503
+ catch (error) {
504
+ console.warn('AIT persisted promotion state could not be reconciled; keeping the claim pending.', input.campaignId, error);
505
+ return { result: { status: 'pending' } };
506
+ }
507
+ }
508
+ async function removeInvalidPersistedPromotionGrant(storage, storageKey) {
509
+ try {
510
+ await storage.removeItem(storageKey);
511
+ return {};
512
+ }
513
+ catch {
514
+ return { result: { status: 'pending' } };
515
+ }
516
+ }
517
+ function promotionGrantStorageKey(idempotencyKey) {
518
+ return `${promotionGrantStoragePrefix}${encodeURIComponent(idempotencyKey)}`;
519
+ }
520
+ function normalizePendingSince(value) {
521
+ if (typeof value !== 'string' || value.length === 0) {
522
+ return undefined;
523
+ }
524
+ return Number.isFinite(Date.parse(value)) ? value : undefined;
525
+ }
231
526
  export async function shareIntent(payload, dependencies) {
232
527
  const intent = readPayloadRecord(payload);
233
528
  if (typeof intent.text !== 'string' || typeof intent.deepLink !== 'string') {
@@ -655,6 +950,32 @@ function normalizeAdPlacementTypes(input) {
655
950
  .map(([placementId, type]) => [placementId.trim(), type])
656
951
  .filter(([placementId]) => placementId.length > 0));
657
952
  }
953
+ function normalizePromotionRewards(input) {
954
+ const rewards = new Map();
955
+ for (const [rawCampaignId, rawReward] of Object.entries(input ?? {})) {
956
+ const campaignId = rawCampaignId.trim();
957
+ const promotionCode = rawReward.promotionCode.trim();
958
+ if (campaignId.length === 0 || promotionCode.length === 0) {
959
+ continue;
960
+ }
961
+ if (!Number.isSafeInteger(rawReward.amount) || rawReward.amount <= 0) {
962
+ console.warn(`AIT promotion amount must be a positive safe integer; disabling campaign: ${campaignId}`);
963
+ continue;
964
+ }
965
+ rewards.set(campaignId, { promotionCode, amount: rawReward.amount });
966
+ }
967
+ return rewards;
968
+ }
969
+ function normalizeNotificationTemplateCodes(input) {
970
+ const templateCodes = new Map();
971
+ for (const topic of notificationTopics) {
972
+ const templateCode = input?.[topic]?.trim();
973
+ if (templateCode !== undefined && templateCode.length > 0) {
974
+ templateCodes.set(topic, templateCode);
975
+ }
976
+ }
977
+ return templateCodes;
978
+ }
658
979
  function normalizeAppName(value) {
659
980
  const normalized = value.trim();
660
981
  if (!/^[A-Za-z0-9-]+$/u.test(normalized)) {
@@ -701,6 +1022,27 @@ function readIdempotencyKey(payload, fallback) {
701
1022
  const value = readPayloadRecord(payload).idempotencyKey;
702
1023
  return typeof value === 'string' && value.length > 0 ? value : fallback;
703
1024
  }
1025
+ function readRequiredIdempotencyKey(payload) {
1026
+ const value = readPayloadRecord(payload).idempotencyKey;
1027
+ if (typeof value !== 'string' || value.length === 0 || value.length > 256) {
1028
+ throw new TypeError('AIT promotion idempotencyKey must contain 1 to 256 characters.');
1029
+ }
1030
+ return value;
1031
+ }
1032
+ function readCampaignId(payload) {
1033
+ const value = readPayloadRecord(payload).campaignId;
1034
+ if (typeof value !== 'string' || value.length === 0 || value.length > 128) {
1035
+ throw new TypeError('AIT promotion campaignId must contain 1 to 128 characters.');
1036
+ }
1037
+ return value;
1038
+ }
1039
+ function readNotificationTopic(payload) {
1040
+ const value = readPayloadRecord(payload).topic;
1041
+ if (typeof value !== 'string' || !notificationTopics.has(value)) {
1042
+ throw new TypeError('AIT notification topic is invalid.');
1043
+ }
1044
+ return value;
1045
+ }
704
1046
  function readFiniteScore(payload) {
705
1047
  const score = readPayloadRecord(payload).score;
706
1048
  if (typeof score !== 'number' || !Number.isFinite(score)) {
package/dist/index.js CHANGED
@@ -44,6 +44,10 @@ export function createAitPlatformGateway(input) {
44
44
  getStatus: (topic) => request('notifications.getStatus', { topic }),
45
45
  requestSubscription: (topic) => request('notifications.requestSubscription', { topic }),
46
46
  },
47
+ promotions: {
48
+ getAvailability: (payload) => request('promotions.getAvailability', payload),
49
+ grantReward: (payload) => request('promotions.grantReward', payload),
50
+ },
47
51
  commerce: {
48
52
  getProducts: () => request('commerce.getProducts', {}),
49
53
  purchase: (payload) => request('commerce.purchase', payload),
@@ -132,6 +136,10 @@ export function createAitSandboxBridge(options = {}) {
132
136
  return ok(input, 'configuration-required');
133
137
  case 'notifications.requestSubscription':
134
138
  return ok(input, 'unavailable');
139
+ case 'promotions.getAvailability':
140
+ return ok(input, 'configuration-required');
141
+ case 'promotions.grantReward':
142
+ return ok(input, { status: 'unavailable' });
135
143
  case 'commerce.getProducts':
136
144
  return ok(input, [
137
145
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/adapter-ait",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Apps in Toss WebView platform adapter for mpgd games.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -47,11 +47,11 @@
47
47
  "dist"
48
48
  ],
49
49
  "dependencies": {
50
- "@mpgd/bridge": "0.6.1",
51
- "@mpgd/platform": "0.7.0"
50
+ "@mpgd/platform": "0.8.0",
51
+ "@mpgd/bridge": "0.7.0"
52
52
  },
53
53
  "peerDependencies": {
54
- "@apps-in-toss/web-framework": ">=2.10.4 <3"
54
+ "@apps-in-toss/web-framework": ">=3.0.0-beta <4"
55
55
  },
56
56
  "peerDependenciesMeta": {
57
57
  "@apps-in-toss/web-framework": {
@@ -59,7 +59,7 @@
59
59
  }
60
60
  },
61
61
  "devDependencies": {
62
- "@apps-in-toss/web-framework": "^2.10.6",
62
+ "@apps-in-toss/web-framework": "3.0.0-beta.da14818",
63
63
  "ttsc": "0.18.4",
64
64
  "typescript": "7.0.2",
65
65
  "vitest": "^4.0.0"