@apps-in-toss/web-bridge 2.9.3 → 2.10.1

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/bridge.d.ts CHANGED
@@ -36,6 +36,7 @@ export * from './getIsTossLoginIntegratedService';
36
36
  export * from './getServerTime';
37
37
  export * from './getConsentedUserData';
38
38
  export * from './requestReview';
39
+ export * from './getDeclaredAgeRange';
39
40
  export * from './getLocale';
40
41
  export * from './getSchemeUri';
41
42
  export * from './getPlatformOS';
package/dist/bridge.js CHANGED
@@ -1 +1 @@
1
- import{createAsyncBridge,createConstantBridge,createEventBridge}from"@apps-in-toss/bridge-core";var createEvents=function(){return{emit:function emit(event,args){for(var callbacks=this.events[event]||[],i=0,length=callbacks.length;i<length;i++){callbacks[i](args)}},events:{},on:function on(event,cb){var _this=this;var _this_events,_event;((_this_events=this.events)[_event=event]||(_this_events[_event]=[])).push(cb);return function(){var _this_events_event;_this.events[event]=(_this_events_event=_this.events[event])===null||_this_events_event===void 0?void 0:_this_events_event.filter(function(i){return cb!==i})}}}};if(typeof window!=="undefined"){window.__GRANITE_NATIVE_EMITTER=createEvents()}export var closeView=createAsyncBridge("closeView");export var generateHapticFeedback=createAsyncBridge("generateHapticFeedback");export var share=createAsyncBridge("share");export var setSecureScreen=createAsyncBridge("setSecureScreen");export var setScreenAwakeMode=createAsyncBridge("setScreenAwakeMode");export var getNetworkStatus=createAsyncBridge("getNetworkStatus");export var setIosSwipeGestureEnabled=createAsyncBridge("setIosSwipeGestureEnabled");export var openURL=createAsyncBridge("openURL");export var openPermissionDialog=createAsyncBridge("openPermissionDialog");export var getPermission=createAsyncBridge("getPermission");export var requestPermission=createAsyncBridge("requestPermission");export var setClipboardText=createConstantBridge("setClipboardText");export var getClipboardText=createConstantBridge("getClipboardText");export var fetchContacts=createConstantBridge("fetchContacts");export var fetchAlbumPhotos=createConstantBridge("fetchAlbumPhotos");export var getCurrentLocation=createConstantBridge("getCurrentLocation");export var openCamera=createConstantBridge("openCamera");export var appLogin=createAsyncBridge("appLogin");export var getAnonymousKey=createAsyncBridge("getAnonymousKey");export var eventLog=createAsyncBridge("eventLog");export var getTossShareLink=createAsyncBridge("getTossShareLink");export var setDeviceOrientation=createAsyncBridge("setDeviceOrientation");export var checkoutPayment=createAsyncBridge("checkoutPayment");export var requestTossPayPaysBilling=createAsyncBridge("requestTossPayPaysBilling");export var saveBase64Data=createAsyncBridge("saveBase64Data");export var openPDFViewer=createAsyncBridge("openPDFViewer");export var fetchAlbumItems=createAsyncBridge("fetchAlbumItems");export var appsInTossSignTossCert=createAsyncBridge("appsInTossSignTossCert");export var getGameCenterGameProfile=createAsyncBridge("getGameCenterGameProfile");export var openGameCenterLeaderboard=createAsyncBridge("openGameCenterLeaderboard");export var submitGameCenterLeaderBoardScore=createAsyncBridge("submitGameCenterLeaderBoardScore");export var getUserKeyForGame=createAsyncBridge("getUserKeyForGame");export var grantPromotionReward=createAsyncBridge("grantPromotionReward");export var grantPromotionRewardForGame=createAsyncBridge("grantPromotionRewardForGame");export var getIsTossLoginIntegratedService=createAsyncBridge("getIsTossLoginIntegratedService");export var getServerTime=createAsyncBridge("getServerTime");export var getConsentedUserData=createAsyncBridge("getConsentedUserData");export var requestReview=createAsyncBridge("requestReview");export var getLocale=createConstantBridge("getLocale");export var getSchemeUri=createConstantBridge("getSchemeUri");export var getPlatformOS=createConstantBridge("getPlatformOS");export var getOperationalEnvironment=createConstantBridge("getOperationalEnvironment");export var getTossAppVersion=createConstantBridge("getTossAppVersion");export var getDeviceId=createConstantBridge("getDeviceId");export var getGroupId=createConstantBridge("getGroupId");export var contactsViral=createEventBridge("contactsViral");export var startUpdateLocation=createEventBridge("startUpdateLocation");export var onVisibilityChangedByTransparentServiceWeb=createEventBridge("onVisibilityChangedByTransparentServiceWeb");
1
+ import{createAsyncBridge,createConstantBridge,createEventBridge}from"@apps-in-toss/bridge-core";var createEvents=function(){return{emit:function emit(event,args){for(var callbacks=this.events[event]||[],i=0,length=callbacks.length;i<length;i++){callbacks[i](args)}},events:{},on:function on(event,cb){var _this=this;var _this_events,_event;((_this_events=this.events)[_event=event]||(_this_events[_event]=[])).push(cb);return function(){var _this_events_event;_this.events[event]=(_this_events_event=_this.events[event])===null||_this_events_event===void 0?void 0:_this_events_event.filter(function(i){return cb!==i})}}}};if(typeof window!=="undefined"){window.__GRANITE_NATIVE_EMITTER=createEvents()}export var closeView=createAsyncBridge("closeView");export var generateHapticFeedback=createAsyncBridge("generateHapticFeedback");export var share=createAsyncBridge("share");export var setSecureScreen=createAsyncBridge("setSecureScreen");export var setScreenAwakeMode=createAsyncBridge("setScreenAwakeMode");export var getNetworkStatus=createAsyncBridge("getNetworkStatus");export var setIosSwipeGestureEnabled=createAsyncBridge("setIosSwipeGestureEnabled");export var openURL=createAsyncBridge("openURL");export var openPermissionDialog=createAsyncBridge("openPermissionDialog");export var getPermission=createAsyncBridge("getPermission");export var requestPermission=createAsyncBridge("requestPermission");export var setClipboardText=createConstantBridge("setClipboardText");export var getClipboardText=createConstantBridge("getClipboardText");export var fetchContacts=createConstantBridge("fetchContacts");export var fetchAlbumPhotos=createConstantBridge("fetchAlbumPhotos");export var getCurrentLocation=createConstantBridge("getCurrentLocation");export var openCamera=createConstantBridge("openCamera");export var appLogin=createAsyncBridge("appLogin");export var getAnonymousKey=createAsyncBridge("getAnonymousKey");export var eventLog=createAsyncBridge("eventLog");export var getTossShareLink=createAsyncBridge("getTossShareLink");export var setDeviceOrientation=createAsyncBridge("setDeviceOrientation");export var checkoutPayment=createAsyncBridge("checkoutPayment");export var requestTossPayPaysBilling=createAsyncBridge("requestTossPayPaysBilling");export var saveBase64Data=createAsyncBridge("saveBase64Data");export var openPDFViewer=createAsyncBridge("openPDFViewer");export var fetchAlbumItems=createAsyncBridge("fetchAlbumItems");export var appsInTossSignTossCert=createAsyncBridge("appsInTossSignTossCert");export var getGameCenterGameProfile=createAsyncBridge("getGameCenterGameProfile");export var openGameCenterLeaderboard=createAsyncBridge("openGameCenterLeaderboard");export var submitGameCenterLeaderBoardScore=createAsyncBridge("submitGameCenterLeaderBoardScore");export var getUserKeyForGame=createAsyncBridge("getUserKeyForGame");export var grantPromotionReward=createAsyncBridge("grantPromotionReward");export var grantPromotionRewardForGame=createAsyncBridge("grantPromotionRewardForGame");export var getIsTossLoginIntegratedService=createAsyncBridge("getIsTossLoginIntegratedService");export var getServerTime=createAsyncBridge("getServerTime");export var getConsentedUserData=createAsyncBridge("getConsentedUserData");export var requestReview=createAsyncBridge("requestReview");export var getDeclaredAgeRange=createAsyncBridge("getDeclaredAgeRange");export var getLocale=createConstantBridge("getLocale");export var getSchemeUri=createConstantBridge("getSchemeUri");export var getPlatformOS=createConstantBridge("getPlatformOS");export var getOperationalEnvironment=createConstantBridge("getOperationalEnvironment");export var getTossAppVersion=createConstantBridge("getTossAppVersion");export var getDeviceId=createConstantBridge("getDeviceId");export var getGroupId=createConstantBridge("getGroupId");export var contactsViral=createEventBridge("contactsViral");export var startUpdateLocation=createEventBridge("startUpdateLocation");export var onVisibilityChangedByTransparentServiceWeb=createEventBridge("onVisibilityChangedByTransparentServiceWeb");
@@ -0,0 +1,17 @@
1
+ export interface DeclaredAgeRange {
2
+ status: "SHARING" | "DECLINED_SHARING" | "UNSUPPORTED_OS" | "NOT_AVAILABLE" | "INVALID_REQUEST" | "FAILED";
3
+ lowerBound?: number;
4
+ upperBound?: number;
5
+ ageRangeDeclaration?: string;
6
+ activeParentalControls: string[];
7
+ isEligibleForAgeFeatures?: boolean;
8
+ errorCode?: string;
9
+ }
10
+ export declare function getDeclaredAgeRange(params: {
11
+ ageGates: number[];
12
+ }): Promise<DeclaredAgeRange>;
13
+ export declare namespace getDeclaredAgeRange {
14
+ var isSupported: () => boolean;
15
+ }
16
+
17
+ export {};
package/dist/index.cjs CHANGED
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  getAppsInTossGlobals: () => getAppsInTossGlobals,
38
38
  getClipboardText: () => getClipboardText,
39
39
  getCurrentLocation: () => getCurrentLocation,
40
+ getDeclaredAgeRange: () => getDeclaredAgeRange,
40
41
  getSafeAreaInsets: () => getSafeAreaInsets,
41
42
  getServerTime: () => getServerTime,
42
43
  graniteEvent: () => graniteEvent,
@@ -1035,6 +1036,197 @@ function resetAttachedBannerRegistry() {
1035
1036
  attachedBannerRegistry = /* @__PURE__ */ new WeakMap();
1036
1037
  }
1037
1038
 
1039
+ // src/toss-ad/constants.ts
1040
+ var ERROR_CODES = {
1041
+ NETWORK_ERROR: 1001,
1042
+ INVALID_REQUEST: 1002,
1043
+ NO_AD: 1003,
1044
+ ERROR: 1004,
1045
+ INVALID_SPACE: 1005,
1046
+ SDK_NOT_INITIALIZED: 1007,
1047
+ HTTP_TIMEOUT: 1008,
1048
+ EXECUTION_FAIL: 1009,
1049
+ INTERRUPTED: 1010,
1050
+ FAIL: 1011,
1051
+ BLOCKED: 1012,
1052
+ TIMEOUT: 1013,
1053
+ LIMITED_AD: 1014,
1054
+ CONSENT_REQUIRED: 1015,
1055
+ TEST_MODE: 1016,
1056
+ INTERNAL_ERROR: 1017
1057
+ };
1058
+ var NON_ERROR_STATUSES = /* @__PURE__ */ new Set(["OK", "TEST_MODE", "NO_AD"]);
1059
+ var API_RESULT_ERROR_CODE_MAP = {
1060
+ HTTP_TIMEOUT: ERROR_CODES.HTTP_TIMEOUT,
1061
+ NETWORK_ERROR: ERROR_CODES.NETWORK_ERROR,
1062
+ EXECUTION_FAIL: ERROR_CODES.EXECUTION_FAIL,
1063
+ INTERRUPTED: ERROR_CODES.INTERRUPTED,
1064
+ INTERNAL_ERROR: ERROR_CODES.ERROR,
1065
+ FAIL: ERROR_CODES.FAIL
1066
+ };
1067
+ var AD_STATUS_ERROR_CODE_MAP = {
1068
+ BLOCKED: ERROR_CODES.BLOCKED,
1069
+ ERROR: ERROR_CODES.ERROR,
1070
+ TIMEOUT: ERROR_CODES.TIMEOUT,
1071
+ INVALID_SPACE: ERROR_CODES.INVALID_SPACE,
1072
+ INVALID_REQUEST: ERROR_CODES.INVALID_REQUEST,
1073
+ LIMITED_AD: ERROR_CODES.LIMITED_AD,
1074
+ CONSENT_REQUIRED: ERROR_CODES.CONSENT_REQUIRED
1075
+ };
1076
+
1077
+ // src/toss-ad/tossAdEventLog.ts
1078
+ var tossAdEventLog = createAsyncBridge("tossAdEventLog");
1079
+
1080
+ // src/toss-ad/errorTracking.ts
1081
+ var BANNER_ERROR_LOG_NAME = "display_ads_all::error__banner";
1082
+ function logBannerErrorToAppLog(info) {
1083
+ void tossAdEventLog({
1084
+ log_name: BANNER_ERROR_LOG_NAME,
1085
+ log_type: "debug",
1086
+ params: {
1087
+ error_code: info.errorCode,
1088
+ error_message: info.errorMessage,
1089
+ ad_group_id: info.adGroupId,
1090
+ mediation_id: info.mediationId,
1091
+ event_context_token: info.eventContextToken
1092
+ }
1093
+ }).catch(() => {
1094
+ });
1095
+ }
1096
+ function trackBannerError(info) {
1097
+ if (info.endpointError) {
1098
+ void fetch(info.endpointError, {
1099
+ method: "POST",
1100
+ headers: { "Content-Type": "application/json" },
1101
+ body: JSON.stringify({
1102
+ eventContextToken: info.eventContextToken,
1103
+ mediationId: info.mediationId,
1104
+ errorCode: info.errorCode,
1105
+ errorMessage: info.errorMessage
1106
+ })
1107
+ // POST 실패(CORS·네트워크) → 앱로그 fallback (endpoint와 같은 채널이라 함께 막히는 경우 대비).
1108
+ }).catch(() => logBannerErrorToAppLog(info));
1109
+ return;
1110
+ }
1111
+ logBannerErrorToAppLog(info);
1112
+ }
1113
+ function trackResponseError(response, adGroupId, context) {
1114
+ if (response.resultType !== "SUCCESS") {
1115
+ trackBannerError({
1116
+ adGroupId,
1117
+ errorCode: API_RESULT_ERROR_CODE_MAP[response.resultType] ?? ERROR_CODES.INTERNAL_ERROR,
1118
+ errorMessage: response.error?.reason ?? response.resultType
1119
+ });
1120
+ return;
1121
+ }
1122
+ const success = response.success;
1123
+ if (!success || NON_ERROR_STATUSES.has(String(success.status))) {
1124
+ return;
1125
+ }
1126
+ trackBannerError({
1127
+ adGroupId,
1128
+ errorCode: AD_STATUS_ERROR_CODE_MAP[String(success.status)] ?? ERROR_CODES.INTERNAL_ERROR,
1129
+ mediationId: context.mediationId,
1130
+ eventContextToken: context.eventContextToken,
1131
+ errorMessage: `Ad response status: ${success.status}`,
1132
+ endpointError: context.errorEndpoint
1133
+ });
1134
+ }
1135
+
1136
+ // src/toss-ad/eventTracking.ts
1137
+ async function handleTrackingRequest(request) {
1138
+ if (request.type === "EVENT_TRACKING") {
1139
+ await sendEventTracking(request);
1140
+ }
1141
+ }
1142
+ async function sendEventTracking(request) {
1143
+ if (request.urls.length === 0) {
1144
+ return;
1145
+ }
1146
+ const body = JSON.stringify({ type: request.eventName, data: request.eventPayload });
1147
+ const headers = { "Content-Type": "application/json" };
1148
+ if (request.requestId) {
1149
+ headers["X-Toss-RequestId"] = request.requestId;
1150
+ }
1151
+ const settled = await Promise.allSettled(
1152
+ request.urls.map(
1153
+ (url) => fetch(url, { method: "POST", headers, body }).then((response) => {
1154
+ if (!response.ok) {
1155
+ throw new Error(`HTTP ${response.status}`);
1156
+ }
1157
+ })
1158
+ )
1159
+ );
1160
+ const failedCount = settled.filter((result) => result.status === "rejected").length;
1161
+ if (failedCount === 0) {
1162
+ return;
1163
+ }
1164
+ trackBannerError({
1165
+ adGroupId: request.adGroupId,
1166
+ errorCode: ERROR_CODES.NETWORK_ERROR,
1167
+ errorMessage: `EVENT_TRACKING failed: ${request.eventName} (${failedCount}/${request.urls.length})`,
1168
+ mediationId: request.mediationId || void 0,
1169
+ eventContextToken: request.eventContextToken || void 0,
1170
+ endpointError: request.errorEndpoint
1171
+ });
1172
+ }
1173
+
1174
+ // src/toss-ad/fetchAppsInTossAdSchema.ts
1175
+ var APPS_IN_TOSS_AD_SPEC_VERSION = "1.4.1";
1176
+ var FETCH_APPS_IN_TOSS_AD_DEVICE_MACRO = "{{device}}";
1177
+ var TOSS_APP_BUNDLE_IDS = {
1178
+ ios: "com.vivarepublica.cash",
1179
+ android: "viva.republica.toss"
1180
+ };
1181
+ function resolveTossAppBundleId(os) {
1182
+ return TOSS_APP_BUNDLE_IDS[os];
1183
+ }
1184
+
1185
+ // src/toss-ad/normalize.ts
1186
+ var LIST_BANNER_STYLE_ID = "1";
1187
+ var NATIVE_IMAGE_STYLE_ID = "2";
1188
+ var AVAILABLE_STYLE_IDS = [LIST_BANNER_STYLE_ID, NATIVE_IMAGE_STYLE_ID];
1189
+ var SUPPORTED_STYLE_IDS = new Set(AVAILABLE_STYLE_IDS);
1190
+ function normalizeAdResponse(adResponse) {
1191
+ const ads = Array.isArray(adResponse.ads) ? adResponse.ads.filter((ad) => SUPPORTED_STYLE_IDS.has(String(ad.styleId))) : [];
1192
+ return {
1193
+ requestId: adResponse.requestId ?? "",
1194
+ // SDK가 event 트래킹 위임(onTrackingRequest) 시 응답 top-level에서 읽어 실어 보낸다.
1195
+ // 떼어내면 SDK가 토큰을 못 보고, event 트래킹 실패 시 endpoint.error에서 토큰이 빠진다.
1196
+ eventContextToken: adResponse.eventContextToken,
1197
+ status: adResponse.status ?? "OK",
1198
+ ads,
1199
+ ext: adResponse.ext
1200
+ };
1201
+ }
1202
+ function normalizeApiResponse(raw) {
1203
+ if (isApiResponse(raw)) {
1204
+ if (raw.resultType !== "SUCCESS") {
1205
+ return raw;
1206
+ }
1207
+ if (!raw.success) {
1208
+ return {
1209
+ resultType: "FAIL",
1210
+ error: { reason: "fetchTossAd returned SUCCESS without payload" }
1211
+ };
1212
+ }
1213
+ return { ...raw, success: normalizeAdResponse(raw.success) };
1214
+ }
1215
+ if (isAdResponse(raw)) {
1216
+ return {
1217
+ resultType: "SUCCESS",
1218
+ success: normalizeAdResponse(raw)
1219
+ };
1220
+ }
1221
+ return { resultType: "FAIL", error: { reason: "Invalid response from fetchTossAd" } };
1222
+ }
1223
+ function isApiResponse(payload) {
1224
+ return Boolean(payload && typeof payload === "object" && "resultType" in payload);
1225
+ }
1226
+ function isAdResponse(payload) {
1227
+ return Boolean(payload && typeof payload === "object" && "ads" in payload);
1228
+ }
1229
+
1038
1230
  // src/toss-ad/opener.ts
1039
1231
  var openURL = createAsyncBridge("openURL");
1040
1232
  function openUrlOpener(url) {
@@ -1049,8 +1241,49 @@ function supertossWeb(uri) {
1049
1241
  return `supertoss://web?url=${encodeURIComponent(uri)}&external=true`;
1050
1242
  }
1051
1243
 
1244
+ // src/toss-ad/resultTracking.ts
1245
+ async function fireResultTracking(response, adGroupId, ctx) {
1246
+ const status = response.success?.status;
1247
+ if (response.resultType !== "SUCCESS" || status !== "OK" && status !== "TEST_MODE") {
1248
+ return;
1249
+ }
1250
+ if (ctx.resultEndpoint == null || ctx.mediationId == null) {
1251
+ return;
1252
+ }
1253
+ const body = {
1254
+ mediationId: ctx.mediationId,
1255
+ spaceUnitId: adGroupId,
1256
+ requestId: response.success?.requestId ?? "",
1257
+ eventContextToken: ctx.eventContextToken,
1258
+ winnerSource: "TOSS",
1259
+ content: null,
1260
+ adUnitId: ctx.adUnitId ?? null,
1261
+ placementId: ctx.placementId ?? null,
1262
+ tossFailed: null
1263
+ };
1264
+ try {
1265
+ const res = await fetch(ctx.resultEndpoint, {
1266
+ method: "POST",
1267
+ headers: { "Content-Type": "application/json" },
1268
+ body: JSON.stringify(body)
1269
+ });
1270
+ if (!res.ok) {
1271
+ throw new Error(`HTTP ${res.status}`);
1272
+ }
1273
+ } catch (error) {
1274
+ trackBannerError({
1275
+ adGroupId,
1276
+ errorCode: ERROR_CODES.NETWORK_ERROR,
1277
+ errorMessage: `RESULT_TRACKING failed: ${error instanceof Error ? error.message : String(error)}`,
1278
+ mediationId: ctx.mediationId,
1279
+ eventContextToken: ctx.eventContextToken,
1280
+ endpointError: ctx.errorEndpoint
1281
+ });
1282
+ }
1283
+ }
1284
+
1052
1285
  // src/toss-ad/scriptLoader.ts
1053
- var DEFAULT_SDK_URL = "https://static.toss.im/ads/sdk/toss-ads-space-kit-1.3.0.js";
1286
+ var DEFAULT_SDK_URL = "https://static.toss.im/ads/sdk/toss-ads-space-kit-3.1.0.js";
1054
1287
  var DEFAULT_TIMEOUT_MS = 15e3;
1055
1288
  var pendingLoad = null;
1056
1289
  function getAdsSdk() {
@@ -1106,12 +1339,79 @@ function loadAdsSdk() {
1106
1339
  return promise;
1107
1340
  }
1108
1341
 
1342
+ // package.json
1343
+ var package_default = {
1344
+ name: "@apps-in-toss/web-bridge",
1345
+ type: "module",
1346
+ version: "2.10.1",
1347
+ description: "Web Bridge for Apps In Toss",
1348
+ scripts: {
1349
+ typecheck: "tsc --noEmit",
1350
+ lint: "eslint .",
1351
+ build: "tsup"
1352
+ },
1353
+ main: "./dist/index.cjs",
1354
+ module: "./dist/index.js",
1355
+ types: "./dist/index.d.ts",
1356
+ exports: {
1357
+ ".": {
1358
+ import: {
1359
+ types: "./dist/index.d.ts",
1360
+ default: "./dist/index.js"
1361
+ },
1362
+ require: {
1363
+ types: "./dist/index.d.cts",
1364
+ default: "./dist/index.cjs"
1365
+ }
1366
+ }
1367
+ },
1368
+ files: [
1369
+ "dist"
1370
+ ],
1371
+ dependencies: {
1372
+ "@apps-in-toss/types": "workspace:*"
1373
+ },
1374
+ devDependencies: {
1375
+ "@apps-in-toss/bridge-core": "workspace:*",
1376
+ "@apps-in-toss/native-modules": "workspace:^",
1377
+ "@swc/core": "^1.12.7",
1378
+ picocolors: "^1.1.1",
1379
+ "ts-morph": "^26.0.0",
1380
+ tsup: "^8.5.0",
1381
+ typescript: "5.8.3",
1382
+ vitest: "^3.1.2"
1383
+ }
1384
+ };
1385
+
1386
+ // src/toss-ad/sdkVersion.ts
1387
+ var SDK_VERSION = package_default.version;
1388
+
1389
+ // src/toss-ad/trackingContext.ts
1390
+ function nonEmptyString(value) {
1391
+ return typeof value === "string" && value.length > 0 ? value : void 0;
1392
+ }
1393
+ function extractAdTrackingContext(response) {
1394
+ const mediation = response?.ext?.mediation;
1395
+ return {
1396
+ mediationId: nonEmptyString(mediation?.mediationId),
1397
+ eventContextToken: nonEmptyString(response?.eventContextToken),
1398
+ resultEndpoint: nonEmptyString(mediation?.endpoint?.result),
1399
+ errorEndpoint: nonEmptyString(mediation?.endpoint?.error),
1400
+ adUnitId: nonEmptyString(mediation?.admob?.adUnitId),
1401
+ placementId: typeof mediation?.admob?.placementId === "number" ? mediation.admob.placementId : void 0
1402
+ };
1403
+ }
1404
+
1109
1405
  // src/toss-ad/index.ts
1110
1406
  var fetchTossAd = Object.assign(createEventBridge("fetchTossAd"), {
1111
1407
  isSupported: createConstantBridge("fetchTossAd_isSupported")
1112
1408
  });
1113
- var tossAdEventLog = createAsyncBridge("tossAdEventLog");
1114
- var SUPPORTED_STYLE_IDS = /* @__PURE__ */ new Set(["1", "2"]);
1409
+ var fetchAppsInTossAd = Object.assign(createEventBridge("fetchAppsInTossAd"), {
1410
+ isSupported: createConstantBridge("fetchAppsInTossAd_isSupported")
1411
+ });
1412
+ var getPlatformOS = createConstantBridge("getPlatformOS");
1413
+ var getTossAppVersion = createConstantBridge("getTossAppVersion");
1414
+ var WEB_SDK_ID = "108";
1115
1415
  var INVALID_AD_GROUP_ID_ERROR_MESSAGE = "\uC798\uBABB\uB41C \uC694\uCCAD\uC774\uC5D0\uC694. \uD544\uC694\uD55C \uAC12\uC774 \uBE44\uC5B4 \uC788\uC5B4\uC694.";
1116
1416
  function normalizeAdGroupId(adGroupId) {
1117
1417
  return adGroupId.trim();
@@ -1148,62 +1448,56 @@ function fetchTossAdPromise(options) {
1148
1448
  });
1149
1449
  });
1150
1450
  }
1151
- function normalizeAdResponse(adResponse) {
1152
- const ads = Array.isArray(adResponse.ads) ? adResponse.ads.filter((ad) => SUPPORTED_STYLE_IDS.has(String(ad.styleId))) : [];
1153
- return {
1154
- requestId: adResponse.requestId ?? "",
1155
- status: adResponse.status ?? "OK",
1156
- ads,
1157
- ext: adResponse.ext
1158
- };
1451
+ function getSubBundle() {
1452
+ return globalThis.__granite?.app?.name ?? "";
1159
1453
  }
1160
- function normalizeApiResponse(raw) {
1161
- if (isApiResponse(raw)) {
1162
- if (raw.resultType !== "SUCCESS") {
1163
- return raw;
1164
- }
1165
- if (!raw.success) {
1166
- return {
1167
- resultType: "FAIL",
1168
- error: { reason: "fetchTossAd returned SUCCESS without payload" }
1169
- };
1454
+ function fetchAppsInTossAdPromise(spaceUnitId) {
1455
+ const platformOS = getPlatformOS();
1456
+ const tossAppVersion = getTossAppVersion();
1457
+ const body = {
1458
+ specVersion: APPS_IN_TOSS_AD_SPEC_VERSION,
1459
+ platform: "WEB",
1460
+ spaceUnitId,
1461
+ sdkVersion: SDK_VERSION,
1462
+ availableStyleIds: AVAILABLE_STYLE_IDS,
1463
+ // device는 매크로키만 보내고 native가 실제 device로 치환한다.
1464
+ device: FETCH_APPS_IN_TOSS_AD_DEVICE_MACRO,
1465
+ app: {
1466
+ version: tossAppVersion,
1467
+ bundle: resolveTossAppBundleId(platformOS),
1468
+ subBundle: getSubBundle()
1170
1469
  }
1171
- return { ...raw, success: normalizeAdResponse(raw.success) };
1172
- }
1173
- if (isAdResponse(raw)) {
1174
- return {
1175
- resultType: "SUCCESS",
1176
- success: normalizeAdResponse(raw)
1177
- };
1178
- }
1179
- return { resultType: "FAIL", error: { reason: "Invalid response from fetchTossAd" } };
1180
- }
1181
- function isApiResponse(payload) {
1182
- return Boolean(payload && typeof payload === "object" && "resultType" in payload);
1183
- }
1184
- function isAdResponse(payload) {
1185
- return Boolean(payload && typeof payload === "object" && "ads" in payload);
1470
+ };
1471
+ return new Promise((resolve, reject) => {
1472
+ fetchAppsInTossAd({ options: body, onEvent: resolve, onError: reject });
1473
+ });
1186
1474
  }
1187
1475
  function createCustomAdFetcher() {
1188
1476
  return async (_endpoint, request) => {
1189
1477
  const spaceUnitId = normalizeAdGroupId(request.spaceUnitId);
1190
1478
  if (spaceUnitId.length === 0) {
1479
+ trackBannerError({
1480
+ adGroupId: spaceUnitId,
1481
+ errorCode: ERROR_CODES.INVALID_SPACE,
1482
+ errorMessage: INVALID_AD_GROUP_ID_ERROR_MESSAGE
1483
+ });
1191
1484
  return createInvalidAdGroupIdResponse();
1192
1485
  }
1193
1486
  try {
1194
- const raw = await fetchTossAdPromise({
1487
+ const raw = fetchAppsInTossAd.isSupported() ? await fetchAppsInTossAdPromise(spaceUnitId) : await fetchTossAdPromise({
1195
1488
  adGroupId: spaceUnitId,
1196
- sdkId: "108",
1197
- availableStyleIds: ["1", "2"]
1489
+ sdkId: WEB_SDK_ID,
1490
+ availableStyleIds: AVAILABLE_STYLE_IDS
1198
1491
  });
1199
- return normalizeApiResponse(raw);
1492
+ const response = normalizeApiResponse(raw);
1493
+ const trackingContext = extractAdTrackingContext(response.success);
1494
+ trackResponseError(response, spaceUnitId, trackingContext);
1495
+ void fireResultTracking(response, spaceUnitId, trackingContext);
1496
+ return response;
1200
1497
  } catch (error) {
1201
- return {
1202
- resultType: "FAIL",
1203
- error: {
1204
- reason: error instanceof Error ? error.message : "Unknown fetchTossAd error"
1205
- }
1206
- };
1498
+ const reason = error instanceof Error ? error.message : "Unknown fetchTossAd error";
1499
+ trackBannerError({ adGroupId: spaceUnitId, errorCode: ERROR_CODES.NETWORK_ERROR, errorMessage: reason });
1500
+ return { resultType: "FAIL", error: { reason } };
1207
1501
  }
1208
1502
  };
1209
1503
  }
@@ -1229,7 +1523,12 @@ function initialize(options) {
1229
1523
  return;
1230
1524
  }
1231
1525
  const customAdFetcher = createCustomAdFetcher();
1232
- const config = { environment: "live", customAdFetcher, opener: openUrlOpener };
1526
+ const config = {
1527
+ environment: "live",
1528
+ customAdFetcher,
1529
+ opener: openUrlOpener,
1530
+ onTrackingRequest: handleTrackingRequest
1531
+ };
1233
1532
  sdk.init(config);
1234
1533
  });
1235
1534
  pendingLoad2 = initPromise;
@@ -1406,7 +1705,7 @@ function attachBanner(adGroupId, target, options = {}) {
1406
1705
  autoLoad: true,
1407
1706
  theme: theme === "auto" ? void 0 : theme,
1408
1707
  renderPadding: (styleId) => {
1409
- if (styleId === "1") {
1708
+ if (styleId === LIST_BANNER_STYLE_ID) {
1410
1709
  return DEFAULT_ATTACH_PADDING_BANNER;
1411
1710
  }
1412
1711
  return DEFAULT_ATTACH_PADDING_NATIVE_IMAGE;
@@ -1479,6 +1778,8 @@ function wrapCallbacks(adGroupId, callbacks) {
1479
1778
  });
1480
1779
  callbacks.onAdImpression?.(mapEvent(payload));
1481
1780
  },
1781
+ // 에러 트래킹은 응답을 소유한 createCustomAdFetcher가 담당한다. 콜백은 publisher 전달만.
1782
+ // 응답 수신 후 에러의 mediationId는 SDK(ads-sdk/web)가 error에 실어주므로 그대로 전달한다.
1482
1783
  onAdFailedToRender: (payload) => callbacks.onAdFailedToRender?.({
1483
1784
  ...mapEvent(payload),
1484
1785
  error: payload?.error ?? { code: 0, message: "UNKNOWN" }
@@ -1532,6 +1833,14 @@ function requestNotificationAgreement(params) {
1532
1833
  return unregisterCallbacks;
1533
1834
  }
1534
1835
 
1836
+ // src/getDeclaredAgeRange.ts
1837
+ var getDeclaredAgeRange = Object.assign(
1838
+ createAsyncBridge("getDeclaredAgeRange"),
1839
+ {
1840
+ isSupported: createConstantBridge("getDeclaredAgeRange_isSupported")
1841
+ }
1842
+ );
1843
+
1535
1844
  // src/index.ts
1536
1845
  __reExport(index_exports, require("@apps-in-toss/types"), module.exports);
1537
1846
  // Annotate the CommonJS export names for ESM import in node:
@@ -1551,6 +1860,7 @@ __reExport(index_exports, require("@apps-in-toss/types"), module.exports);
1551
1860
  getAppsInTossGlobals,
1552
1861
  getClipboardText,
1553
1862
  getCurrentLocation,
1863
+ getDeclaredAgeRange,
1554
1864
  getSafeAreaInsets,
1555
1865
  getServerTime,
1556
1866
  graniteEvent,
package/dist/index.d.cts CHANGED
@@ -3,6 +3,7 @@ export * from '@apps-in-toss/bridge-core';
3
3
  import * as _apps_in_toss_types from '@apps-in-toss/types';
4
4
  import { LoadAdMobEvent, LoadAdMobOptions, ShowAdMobEvent, ShowAdMobOptions, IsAdMobLoadedOptions, FetchAlbumPhotos, FetchContacts, GetCurrentLocation, OpenCamera, SetClipboardText, GetClipboardText, StartUpdateLocationEventParams, LoadFullScreenAdEvent, LoadFullScreenAdOptions, ShowFullScreenAdEvent, ShowFullScreenAdOptions } from '@apps-in-toss/types';
5
5
  export * from '@apps-in-toss/types';
6
+ import { DeclaredAgeRange } from '@apps-in-toss/native-modules/async-bridges';
6
7
 
7
8
  /**
8
9
  * @public
@@ -885,6 +886,22 @@ interface RuntimeInfo {
885
886
  safeAreaInsets?: SafeAreaInsets;
886
887
  }
887
888
  type AdOpener = (url: string, target?: string, features?: string) => void;
889
+ /** SDK가 `onTrackingRequest`로 위임하는 트래킹 요청. ads-sdk/web의 동형 계약. */
890
+ interface TrackingRequestBase {
891
+ adGroupId: string;
892
+ requestId?: string;
893
+ creativeId?: string;
894
+ mediationId?: string;
895
+ eventContextToken?: string;
896
+ errorEndpoint?: string;
897
+ }
898
+ interface EventTrackingRequest extends TrackingRequestBase {
899
+ type: 'EVENT_TRACKING';
900
+ eventName: string;
901
+ urls: string[];
902
+ eventPayload: string;
903
+ }
904
+ type TrackingRequest = EventTrackingRequest;
888
905
  interface AdConfig {
889
906
  environment: Environment;
890
907
  apiEndpoint?: string;
@@ -893,6 +910,11 @@ interface AdConfig {
893
910
  runtimeInfo?: RuntimeInfo;
894
911
  opener?: AdOpener;
895
912
  customAdFetcher?: CustomAdFetcher;
913
+ /**
914
+ * 트래킹 전송 위임(SDK 3.1.0+). 지정 시 SDK는 직접 전송하지 않고 이 콜백에 위임한다.
915
+ * fire-and-forget이며 실패 관측은 사용측 책임. 현재 위임 대상은 EVENT_TRACKING이다.
916
+ */
917
+ onTrackingRequest?: (request: TrackingRequest) => void | Promise<void>;
896
918
  }
897
919
  interface AdRequest {
898
920
  spaceUnitId: string;
@@ -907,6 +929,7 @@ interface AdRequest {
907
929
  type AdResponseStatus = 'OK' | 'NO_AD' | 'BLOCKED' | 'ERROR' | 'TIMEOUT' | 'INVALID_SPACE' | 'INVALID_REQUEST' | 'LIMITED_AD' | 'CONSENT_REQUIRED' | 'TEST_MODE';
908
930
  interface AdResponse {
909
931
  requestId?: string;
932
+ eventContextToken?: string;
910
933
  status?: AdResponseStatus;
911
934
  ads: Ad[];
912
935
  ext?: AdResponseExt;
@@ -919,6 +942,19 @@ interface Ad {
919
942
  eventPayload?: string;
920
943
  requestId?: string;
921
944
  }
945
+ interface TossAdsMediation {
946
+ mediationId: string;
947
+ priority: Array<'TOSS' | 'ADMOB'>;
948
+ admob: {
949
+ adUnitId: string;
950
+ placementId: number;
951
+ } | null;
952
+ endpoint?: {
953
+ result?: string;
954
+ exposure?: string;
955
+ error?: string;
956
+ };
957
+ }
922
958
  interface AdResponseExt {
923
959
  skippableOffsetSeconds?: number;
924
960
  reward?: {
@@ -927,6 +963,7 @@ interface AdResponseExt {
927
963
  };
928
964
  isAdBadgeEnabled?: boolean;
929
965
  refetchSeconds?: number | null;
966
+ mediation?: TossAdsMediation;
930
967
  }
931
968
  interface ApiResponse<T> {
932
969
  resultType: 'SUCCESS' | 'HTTP_TIMEOUT' | 'NETWORK_ERROR' | 'EXECUTION_FAIL' | 'INTERRUPTED' | 'INTERNAL_ERROR' | 'FAIL';
@@ -958,10 +995,12 @@ interface BannerSlotErrorPayload {
958
995
  slotId: string;
959
996
  adGroupId: string;
960
997
  adMetadata: Record<string, never>;
998
+ /** `mediationId`는 `/api-web/v3/benefit-ads/display-ad/ads` 응답 수신 후 발생한 에러에만 포함된다. */
961
999
  error: {
962
1000
  code: number;
963
1001
  message: string;
964
1002
  domain?: string;
1003
+ mediationId?: string;
965
1004
  };
966
1005
  }
967
1006
  interface BannerSlotCallbacks {
@@ -1095,4 +1134,10 @@ interface RequestNotificationAgreementOptions {
1095
1134
  */
1096
1135
  declare function requestNotificationAgreement(params: RequestNotificationAgreementOptions): () => void;
1097
1136
 
1098
- export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type IapSubscriptionInfoResponse, type IapSubscriptionInfoResult, type NonConsumableProductListItem, type NotificationAgreementResult, type RequestNotificationAgreementOptions, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, requestNotificationAgreement, requestReview, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
1137
+ declare const getDeclaredAgeRange: ((args_0: {
1138
+ ageGates: number[];
1139
+ }) => Promise<DeclaredAgeRange>) & {
1140
+ isSupported: () => boolean;
1141
+ };
1142
+
1143
+ export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type IapSubscriptionInfoResponse, type IapSubscriptionInfoResult, type NonConsumableProductListItem, type NotificationAgreementResult, type RequestNotificationAgreementOptions, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getDeclaredAgeRange, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, requestNotificationAgreement, requestReview, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from '@apps-in-toss/bridge-core';
3
3
  import * as _apps_in_toss_types from '@apps-in-toss/types';
4
4
  import { LoadAdMobEvent, LoadAdMobOptions, ShowAdMobEvent, ShowAdMobOptions, IsAdMobLoadedOptions, FetchAlbumPhotos, FetchContacts, GetCurrentLocation, OpenCamera, SetClipboardText, GetClipboardText, StartUpdateLocationEventParams, LoadFullScreenAdEvent, LoadFullScreenAdOptions, ShowFullScreenAdEvent, ShowFullScreenAdOptions } from '@apps-in-toss/types';
5
5
  export * from '@apps-in-toss/types';
6
+ import { DeclaredAgeRange } from '@apps-in-toss/native-modules/async-bridges';
6
7
 
7
8
  /**
8
9
  * @public
@@ -885,6 +886,22 @@ interface RuntimeInfo {
885
886
  safeAreaInsets?: SafeAreaInsets;
886
887
  }
887
888
  type AdOpener = (url: string, target?: string, features?: string) => void;
889
+ /** SDK가 `onTrackingRequest`로 위임하는 트래킹 요청. ads-sdk/web의 동형 계약. */
890
+ interface TrackingRequestBase {
891
+ adGroupId: string;
892
+ requestId?: string;
893
+ creativeId?: string;
894
+ mediationId?: string;
895
+ eventContextToken?: string;
896
+ errorEndpoint?: string;
897
+ }
898
+ interface EventTrackingRequest extends TrackingRequestBase {
899
+ type: 'EVENT_TRACKING';
900
+ eventName: string;
901
+ urls: string[];
902
+ eventPayload: string;
903
+ }
904
+ type TrackingRequest = EventTrackingRequest;
888
905
  interface AdConfig {
889
906
  environment: Environment;
890
907
  apiEndpoint?: string;
@@ -893,6 +910,11 @@ interface AdConfig {
893
910
  runtimeInfo?: RuntimeInfo;
894
911
  opener?: AdOpener;
895
912
  customAdFetcher?: CustomAdFetcher;
913
+ /**
914
+ * 트래킹 전송 위임(SDK 3.1.0+). 지정 시 SDK는 직접 전송하지 않고 이 콜백에 위임한다.
915
+ * fire-and-forget이며 실패 관측은 사용측 책임. 현재 위임 대상은 EVENT_TRACKING이다.
916
+ */
917
+ onTrackingRequest?: (request: TrackingRequest) => void | Promise<void>;
896
918
  }
897
919
  interface AdRequest {
898
920
  spaceUnitId: string;
@@ -907,6 +929,7 @@ interface AdRequest {
907
929
  type AdResponseStatus = 'OK' | 'NO_AD' | 'BLOCKED' | 'ERROR' | 'TIMEOUT' | 'INVALID_SPACE' | 'INVALID_REQUEST' | 'LIMITED_AD' | 'CONSENT_REQUIRED' | 'TEST_MODE';
908
930
  interface AdResponse {
909
931
  requestId?: string;
932
+ eventContextToken?: string;
910
933
  status?: AdResponseStatus;
911
934
  ads: Ad[];
912
935
  ext?: AdResponseExt;
@@ -919,6 +942,19 @@ interface Ad {
919
942
  eventPayload?: string;
920
943
  requestId?: string;
921
944
  }
945
+ interface TossAdsMediation {
946
+ mediationId: string;
947
+ priority: Array<'TOSS' | 'ADMOB'>;
948
+ admob: {
949
+ adUnitId: string;
950
+ placementId: number;
951
+ } | null;
952
+ endpoint?: {
953
+ result?: string;
954
+ exposure?: string;
955
+ error?: string;
956
+ };
957
+ }
922
958
  interface AdResponseExt {
923
959
  skippableOffsetSeconds?: number;
924
960
  reward?: {
@@ -927,6 +963,7 @@ interface AdResponseExt {
927
963
  };
928
964
  isAdBadgeEnabled?: boolean;
929
965
  refetchSeconds?: number | null;
966
+ mediation?: TossAdsMediation;
930
967
  }
931
968
  interface ApiResponse<T> {
932
969
  resultType: 'SUCCESS' | 'HTTP_TIMEOUT' | 'NETWORK_ERROR' | 'EXECUTION_FAIL' | 'INTERRUPTED' | 'INTERNAL_ERROR' | 'FAIL';
@@ -958,10 +995,12 @@ interface BannerSlotErrorPayload {
958
995
  slotId: string;
959
996
  adGroupId: string;
960
997
  adMetadata: Record<string, never>;
998
+ /** `mediationId`는 `/api-web/v3/benefit-ads/display-ad/ads` 응답 수신 후 발생한 에러에만 포함된다. */
961
999
  error: {
962
1000
  code: number;
963
1001
  message: string;
964
1002
  domain?: string;
1003
+ mediationId?: string;
965
1004
  };
966
1005
  }
967
1006
  interface BannerSlotCallbacks {
@@ -1095,4 +1134,10 @@ interface RequestNotificationAgreementOptions {
1095
1134
  */
1096
1135
  declare function requestNotificationAgreement(params: RequestNotificationAgreementOptions): () => void;
1097
1136
 
1098
- export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type IapSubscriptionInfoResponse, type IapSubscriptionInfoResult, type NonConsumableProductListItem, type NotificationAgreementResult, type RequestNotificationAgreementOptions, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, requestNotificationAgreement, requestReview, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
1137
+ declare const getDeclaredAgeRange: ((args_0: {
1138
+ ageGates: number[];
1139
+ }) => Promise<DeclaredAgeRange>) & {
1140
+ isSupported: () => boolean;
1141
+ };
1142
+
1143
+ export { type AddAccessoryButtonOptions, type AppsInTossEvent, type AppsInTossGlobals, type CompletedOrRefundedOrdersResult, type ConsumableProductListItem, type CreateSubscriptionPurchaseOrderOptions, GoogleAdMob, type GraniteEvent, IAP, type IapCreateOneTimePurchaseOrderOptions, type IapProductListItem, type IapSubscriptionInfoResponse, type IapSubscriptionInfoResult, type NonConsumableProductListItem, type NotificationAgreementResult, type RequestNotificationAgreementOptions, SafeAreaInsets$1 as SafeAreaInsets, Storage, type SubscriptionProductListItem, type TdsEvent, TossAds, type AttachBannerOptions as TossAdsAttachBannerOptions, type AttachBannerResult as TossAdsAttachBannerResult, type AttachOptions as TossAdsAttachOptions, type BannerSlotCallbacks as TossAdsBannerSlotCallbacks, type BannerSlotErrorPayload as TossAdsBannerSlotErrorPayload, type BannerSlotEventPayload as TossAdsBannerSlotEventPayload, type InitializeOptions as TossAdsInitializeOptions, appsInTossEvent, env, fetchAlbumPhotos, fetchContacts, getAppsInTossGlobals, getClipboardText, getCurrentLocation, getDeclaredAgeRange, getSafeAreaInsets, getServerTime, graniteEvent, isMinVersionSupported, loadFullScreenAd, openCamera, partner, requestNotificationAgreement, requestReview, setClipboardText, showFullScreenAd, startUpdateLocation, tdsEvent };
package/dist/index.js CHANGED
@@ -986,6 +986,197 @@ function resetAttachedBannerRegistry() {
986
986
  attachedBannerRegistry = /* @__PURE__ */ new WeakMap();
987
987
  }
988
988
 
989
+ // src/toss-ad/constants.ts
990
+ var ERROR_CODES = {
991
+ NETWORK_ERROR: 1001,
992
+ INVALID_REQUEST: 1002,
993
+ NO_AD: 1003,
994
+ ERROR: 1004,
995
+ INVALID_SPACE: 1005,
996
+ SDK_NOT_INITIALIZED: 1007,
997
+ HTTP_TIMEOUT: 1008,
998
+ EXECUTION_FAIL: 1009,
999
+ INTERRUPTED: 1010,
1000
+ FAIL: 1011,
1001
+ BLOCKED: 1012,
1002
+ TIMEOUT: 1013,
1003
+ LIMITED_AD: 1014,
1004
+ CONSENT_REQUIRED: 1015,
1005
+ TEST_MODE: 1016,
1006
+ INTERNAL_ERROR: 1017
1007
+ };
1008
+ var NON_ERROR_STATUSES = /* @__PURE__ */ new Set(["OK", "TEST_MODE", "NO_AD"]);
1009
+ var API_RESULT_ERROR_CODE_MAP = {
1010
+ HTTP_TIMEOUT: ERROR_CODES.HTTP_TIMEOUT,
1011
+ NETWORK_ERROR: ERROR_CODES.NETWORK_ERROR,
1012
+ EXECUTION_FAIL: ERROR_CODES.EXECUTION_FAIL,
1013
+ INTERRUPTED: ERROR_CODES.INTERRUPTED,
1014
+ INTERNAL_ERROR: ERROR_CODES.ERROR,
1015
+ FAIL: ERROR_CODES.FAIL
1016
+ };
1017
+ var AD_STATUS_ERROR_CODE_MAP = {
1018
+ BLOCKED: ERROR_CODES.BLOCKED,
1019
+ ERROR: ERROR_CODES.ERROR,
1020
+ TIMEOUT: ERROR_CODES.TIMEOUT,
1021
+ INVALID_SPACE: ERROR_CODES.INVALID_SPACE,
1022
+ INVALID_REQUEST: ERROR_CODES.INVALID_REQUEST,
1023
+ LIMITED_AD: ERROR_CODES.LIMITED_AD,
1024
+ CONSENT_REQUIRED: ERROR_CODES.CONSENT_REQUIRED
1025
+ };
1026
+
1027
+ // src/toss-ad/tossAdEventLog.ts
1028
+ var tossAdEventLog = createAsyncBridge("tossAdEventLog");
1029
+
1030
+ // src/toss-ad/errorTracking.ts
1031
+ var BANNER_ERROR_LOG_NAME = "display_ads_all::error__banner";
1032
+ function logBannerErrorToAppLog(info) {
1033
+ void tossAdEventLog({
1034
+ log_name: BANNER_ERROR_LOG_NAME,
1035
+ log_type: "debug",
1036
+ params: {
1037
+ error_code: info.errorCode,
1038
+ error_message: info.errorMessage,
1039
+ ad_group_id: info.adGroupId,
1040
+ mediation_id: info.mediationId,
1041
+ event_context_token: info.eventContextToken
1042
+ }
1043
+ }).catch(() => {
1044
+ });
1045
+ }
1046
+ function trackBannerError(info) {
1047
+ if (info.endpointError) {
1048
+ void fetch(info.endpointError, {
1049
+ method: "POST",
1050
+ headers: { "Content-Type": "application/json" },
1051
+ body: JSON.stringify({
1052
+ eventContextToken: info.eventContextToken,
1053
+ mediationId: info.mediationId,
1054
+ errorCode: info.errorCode,
1055
+ errorMessage: info.errorMessage
1056
+ })
1057
+ // POST 실패(CORS·네트워크) → 앱로그 fallback (endpoint와 같은 채널이라 함께 막히는 경우 대비).
1058
+ }).catch(() => logBannerErrorToAppLog(info));
1059
+ return;
1060
+ }
1061
+ logBannerErrorToAppLog(info);
1062
+ }
1063
+ function trackResponseError(response, adGroupId, context) {
1064
+ if (response.resultType !== "SUCCESS") {
1065
+ trackBannerError({
1066
+ adGroupId,
1067
+ errorCode: API_RESULT_ERROR_CODE_MAP[response.resultType] ?? ERROR_CODES.INTERNAL_ERROR,
1068
+ errorMessage: response.error?.reason ?? response.resultType
1069
+ });
1070
+ return;
1071
+ }
1072
+ const success = response.success;
1073
+ if (!success || NON_ERROR_STATUSES.has(String(success.status))) {
1074
+ return;
1075
+ }
1076
+ trackBannerError({
1077
+ adGroupId,
1078
+ errorCode: AD_STATUS_ERROR_CODE_MAP[String(success.status)] ?? ERROR_CODES.INTERNAL_ERROR,
1079
+ mediationId: context.mediationId,
1080
+ eventContextToken: context.eventContextToken,
1081
+ errorMessage: `Ad response status: ${success.status}`,
1082
+ endpointError: context.errorEndpoint
1083
+ });
1084
+ }
1085
+
1086
+ // src/toss-ad/eventTracking.ts
1087
+ async function handleTrackingRequest(request) {
1088
+ if (request.type === "EVENT_TRACKING") {
1089
+ await sendEventTracking(request);
1090
+ }
1091
+ }
1092
+ async function sendEventTracking(request) {
1093
+ if (request.urls.length === 0) {
1094
+ return;
1095
+ }
1096
+ const body = JSON.stringify({ type: request.eventName, data: request.eventPayload });
1097
+ const headers = { "Content-Type": "application/json" };
1098
+ if (request.requestId) {
1099
+ headers["X-Toss-RequestId"] = request.requestId;
1100
+ }
1101
+ const settled = await Promise.allSettled(
1102
+ request.urls.map(
1103
+ (url) => fetch(url, { method: "POST", headers, body }).then((response) => {
1104
+ if (!response.ok) {
1105
+ throw new Error(`HTTP ${response.status}`);
1106
+ }
1107
+ })
1108
+ )
1109
+ );
1110
+ const failedCount = settled.filter((result) => result.status === "rejected").length;
1111
+ if (failedCount === 0) {
1112
+ return;
1113
+ }
1114
+ trackBannerError({
1115
+ adGroupId: request.adGroupId,
1116
+ errorCode: ERROR_CODES.NETWORK_ERROR,
1117
+ errorMessage: `EVENT_TRACKING failed: ${request.eventName} (${failedCount}/${request.urls.length})`,
1118
+ mediationId: request.mediationId || void 0,
1119
+ eventContextToken: request.eventContextToken || void 0,
1120
+ endpointError: request.errorEndpoint
1121
+ });
1122
+ }
1123
+
1124
+ // src/toss-ad/fetchAppsInTossAdSchema.ts
1125
+ var APPS_IN_TOSS_AD_SPEC_VERSION = "1.4.1";
1126
+ var FETCH_APPS_IN_TOSS_AD_DEVICE_MACRO = "{{device}}";
1127
+ var TOSS_APP_BUNDLE_IDS = {
1128
+ ios: "com.vivarepublica.cash",
1129
+ android: "viva.republica.toss"
1130
+ };
1131
+ function resolveTossAppBundleId(os) {
1132
+ return TOSS_APP_BUNDLE_IDS[os];
1133
+ }
1134
+
1135
+ // src/toss-ad/normalize.ts
1136
+ var LIST_BANNER_STYLE_ID = "1";
1137
+ var NATIVE_IMAGE_STYLE_ID = "2";
1138
+ var AVAILABLE_STYLE_IDS = [LIST_BANNER_STYLE_ID, NATIVE_IMAGE_STYLE_ID];
1139
+ var SUPPORTED_STYLE_IDS = new Set(AVAILABLE_STYLE_IDS);
1140
+ function normalizeAdResponse(adResponse) {
1141
+ const ads = Array.isArray(adResponse.ads) ? adResponse.ads.filter((ad) => SUPPORTED_STYLE_IDS.has(String(ad.styleId))) : [];
1142
+ return {
1143
+ requestId: adResponse.requestId ?? "",
1144
+ // SDK가 event 트래킹 위임(onTrackingRequest) 시 응답 top-level에서 읽어 실어 보낸다.
1145
+ // 떼어내면 SDK가 토큰을 못 보고, event 트래킹 실패 시 endpoint.error에서 토큰이 빠진다.
1146
+ eventContextToken: adResponse.eventContextToken,
1147
+ status: adResponse.status ?? "OK",
1148
+ ads,
1149
+ ext: adResponse.ext
1150
+ };
1151
+ }
1152
+ function normalizeApiResponse(raw) {
1153
+ if (isApiResponse(raw)) {
1154
+ if (raw.resultType !== "SUCCESS") {
1155
+ return raw;
1156
+ }
1157
+ if (!raw.success) {
1158
+ return {
1159
+ resultType: "FAIL",
1160
+ error: { reason: "fetchTossAd returned SUCCESS without payload" }
1161
+ };
1162
+ }
1163
+ return { ...raw, success: normalizeAdResponse(raw.success) };
1164
+ }
1165
+ if (isAdResponse(raw)) {
1166
+ return {
1167
+ resultType: "SUCCESS",
1168
+ success: normalizeAdResponse(raw)
1169
+ };
1170
+ }
1171
+ return { resultType: "FAIL", error: { reason: "Invalid response from fetchTossAd" } };
1172
+ }
1173
+ function isApiResponse(payload) {
1174
+ return Boolean(payload && typeof payload === "object" && "resultType" in payload);
1175
+ }
1176
+ function isAdResponse(payload) {
1177
+ return Boolean(payload && typeof payload === "object" && "ads" in payload);
1178
+ }
1179
+
989
1180
  // src/toss-ad/opener.ts
990
1181
  var openURL = createAsyncBridge("openURL");
991
1182
  function openUrlOpener(url) {
@@ -1000,8 +1191,49 @@ function supertossWeb(uri) {
1000
1191
  return `supertoss://web?url=${encodeURIComponent(uri)}&external=true`;
1001
1192
  }
1002
1193
 
1194
+ // src/toss-ad/resultTracking.ts
1195
+ async function fireResultTracking(response, adGroupId, ctx) {
1196
+ const status = response.success?.status;
1197
+ if (response.resultType !== "SUCCESS" || status !== "OK" && status !== "TEST_MODE") {
1198
+ return;
1199
+ }
1200
+ if (ctx.resultEndpoint == null || ctx.mediationId == null) {
1201
+ return;
1202
+ }
1203
+ const body = {
1204
+ mediationId: ctx.mediationId,
1205
+ spaceUnitId: adGroupId,
1206
+ requestId: response.success?.requestId ?? "",
1207
+ eventContextToken: ctx.eventContextToken,
1208
+ winnerSource: "TOSS",
1209
+ content: null,
1210
+ adUnitId: ctx.adUnitId ?? null,
1211
+ placementId: ctx.placementId ?? null,
1212
+ tossFailed: null
1213
+ };
1214
+ try {
1215
+ const res = await fetch(ctx.resultEndpoint, {
1216
+ method: "POST",
1217
+ headers: { "Content-Type": "application/json" },
1218
+ body: JSON.stringify(body)
1219
+ });
1220
+ if (!res.ok) {
1221
+ throw new Error(`HTTP ${res.status}`);
1222
+ }
1223
+ } catch (error) {
1224
+ trackBannerError({
1225
+ adGroupId,
1226
+ errorCode: ERROR_CODES.NETWORK_ERROR,
1227
+ errorMessage: `RESULT_TRACKING failed: ${error instanceof Error ? error.message : String(error)}`,
1228
+ mediationId: ctx.mediationId,
1229
+ eventContextToken: ctx.eventContextToken,
1230
+ endpointError: ctx.errorEndpoint
1231
+ });
1232
+ }
1233
+ }
1234
+
1003
1235
  // src/toss-ad/scriptLoader.ts
1004
- var DEFAULT_SDK_URL = "https://static.toss.im/ads/sdk/toss-ads-space-kit-1.3.0.js";
1236
+ var DEFAULT_SDK_URL = "https://static.toss.im/ads/sdk/toss-ads-space-kit-3.1.0.js";
1005
1237
  var DEFAULT_TIMEOUT_MS = 15e3;
1006
1238
  var pendingLoad = null;
1007
1239
  function getAdsSdk() {
@@ -1057,12 +1289,79 @@ function loadAdsSdk() {
1057
1289
  return promise;
1058
1290
  }
1059
1291
 
1292
+ // package.json
1293
+ var package_default = {
1294
+ name: "@apps-in-toss/web-bridge",
1295
+ type: "module",
1296
+ version: "2.10.1",
1297
+ description: "Web Bridge for Apps In Toss",
1298
+ scripts: {
1299
+ typecheck: "tsc --noEmit",
1300
+ lint: "eslint .",
1301
+ build: "tsup"
1302
+ },
1303
+ main: "./dist/index.cjs",
1304
+ module: "./dist/index.js",
1305
+ types: "./dist/index.d.ts",
1306
+ exports: {
1307
+ ".": {
1308
+ import: {
1309
+ types: "./dist/index.d.ts",
1310
+ default: "./dist/index.js"
1311
+ },
1312
+ require: {
1313
+ types: "./dist/index.d.cts",
1314
+ default: "./dist/index.cjs"
1315
+ }
1316
+ }
1317
+ },
1318
+ files: [
1319
+ "dist"
1320
+ ],
1321
+ dependencies: {
1322
+ "@apps-in-toss/types": "workspace:*"
1323
+ },
1324
+ devDependencies: {
1325
+ "@apps-in-toss/bridge-core": "workspace:*",
1326
+ "@apps-in-toss/native-modules": "workspace:^",
1327
+ "@swc/core": "^1.12.7",
1328
+ picocolors: "^1.1.1",
1329
+ "ts-morph": "^26.0.0",
1330
+ tsup: "^8.5.0",
1331
+ typescript: "5.8.3",
1332
+ vitest: "^3.1.2"
1333
+ }
1334
+ };
1335
+
1336
+ // src/toss-ad/sdkVersion.ts
1337
+ var SDK_VERSION = package_default.version;
1338
+
1339
+ // src/toss-ad/trackingContext.ts
1340
+ function nonEmptyString(value) {
1341
+ return typeof value === "string" && value.length > 0 ? value : void 0;
1342
+ }
1343
+ function extractAdTrackingContext(response) {
1344
+ const mediation = response?.ext?.mediation;
1345
+ return {
1346
+ mediationId: nonEmptyString(mediation?.mediationId),
1347
+ eventContextToken: nonEmptyString(response?.eventContextToken),
1348
+ resultEndpoint: nonEmptyString(mediation?.endpoint?.result),
1349
+ errorEndpoint: nonEmptyString(mediation?.endpoint?.error),
1350
+ adUnitId: nonEmptyString(mediation?.admob?.adUnitId),
1351
+ placementId: typeof mediation?.admob?.placementId === "number" ? mediation.admob.placementId : void 0
1352
+ };
1353
+ }
1354
+
1060
1355
  // src/toss-ad/index.ts
1061
1356
  var fetchTossAd = Object.assign(createEventBridge("fetchTossAd"), {
1062
1357
  isSupported: createConstantBridge("fetchTossAd_isSupported")
1063
1358
  });
1064
- var tossAdEventLog = createAsyncBridge("tossAdEventLog");
1065
- var SUPPORTED_STYLE_IDS = /* @__PURE__ */ new Set(["1", "2"]);
1359
+ var fetchAppsInTossAd = Object.assign(createEventBridge("fetchAppsInTossAd"), {
1360
+ isSupported: createConstantBridge("fetchAppsInTossAd_isSupported")
1361
+ });
1362
+ var getPlatformOS = createConstantBridge("getPlatformOS");
1363
+ var getTossAppVersion = createConstantBridge("getTossAppVersion");
1364
+ var WEB_SDK_ID = "108";
1066
1365
  var INVALID_AD_GROUP_ID_ERROR_MESSAGE = "\uC798\uBABB\uB41C \uC694\uCCAD\uC774\uC5D0\uC694. \uD544\uC694\uD55C \uAC12\uC774 \uBE44\uC5B4 \uC788\uC5B4\uC694.";
1067
1366
  function normalizeAdGroupId(adGroupId) {
1068
1367
  return adGroupId.trim();
@@ -1099,62 +1398,56 @@ function fetchTossAdPromise(options) {
1099
1398
  });
1100
1399
  });
1101
1400
  }
1102
- function normalizeAdResponse(adResponse) {
1103
- const ads = Array.isArray(adResponse.ads) ? adResponse.ads.filter((ad) => SUPPORTED_STYLE_IDS.has(String(ad.styleId))) : [];
1104
- return {
1105
- requestId: adResponse.requestId ?? "",
1106
- status: adResponse.status ?? "OK",
1107
- ads,
1108
- ext: adResponse.ext
1109
- };
1401
+ function getSubBundle() {
1402
+ return globalThis.__granite?.app?.name ?? "";
1110
1403
  }
1111
- function normalizeApiResponse(raw) {
1112
- if (isApiResponse(raw)) {
1113
- if (raw.resultType !== "SUCCESS") {
1114
- return raw;
1115
- }
1116
- if (!raw.success) {
1117
- return {
1118
- resultType: "FAIL",
1119
- error: { reason: "fetchTossAd returned SUCCESS without payload" }
1120
- };
1404
+ function fetchAppsInTossAdPromise(spaceUnitId) {
1405
+ const platformOS = getPlatformOS();
1406
+ const tossAppVersion = getTossAppVersion();
1407
+ const body = {
1408
+ specVersion: APPS_IN_TOSS_AD_SPEC_VERSION,
1409
+ platform: "WEB",
1410
+ spaceUnitId,
1411
+ sdkVersion: SDK_VERSION,
1412
+ availableStyleIds: AVAILABLE_STYLE_IDS,
1413
+ // device는 매크로키만 보내고 native가 실제 device로 치환한다.
1414
+ device: FETCH_APPS_IN_TOSS_AD_DEVICE_MACRO,
1415
+ app: {
1416
+ version: tossAppVersion,
1417
+ bundle: resolveTossAppBundleId(platformOS),
1418
+ subBundle: getSubBundle()
1121
1419
  }
1122
- return { ...raw, success: normalizeAdResponse(raw.success) };
1123
- }
1124
- if (isAdResponse(raw)) {
1125
- return {
1126
- resultType: "SUCCESS",
1127
- success: normalizeAdResponse(raw)
1128
- };
1129
- }
1130
- return { resultType: "FAIL", error: { reason: "Invalid response from fetchTossAd" } };
1131
- }
1132
- function isApiResponse(payload) {
1133
- return Boolean(payload && typeof payload === "object" && "resultType" in payload);
1134
- }
1135
- function isAdResponse(payload) {
1136
- return Boolean(payload && typeof payload === "object" && "ads" in payload);
1420
+ };
1421
+ return new Promise((resolve, reject) => {
1422
+ fetchAppsInTossAd({ options: body, onEvent: resolve, onError: reject });
1423
+ });
1137
1424
  }
1138
1425
  function createCustomAdFetcher() {
1139
1426
  return async (_endpoint, request) => {
1140
1427
  const spaceUnitId = normalizeAdGroupId(request.spaceUnitId);
1141
1428
  if (spaceUnitId.length === 0) {
1429
+ trackBannerError({
1430
+ adGroupId: spaceUnitId,
1431
+ errorCode: ERROR_CODES.INVALID_SPACE,
1432
+ errorMessage: INVALID_AD_GROUP_ID_ERROR_MESSAGE
1433
+ });
1142
1434
  return createInvalidAdGroupIdResponse();
1143
1435
  }
1144
1436
  try {
1145
- const raw = await fetchTossAdPromise({
1437
+ const raw = fetchAppsInTossAd.isSupported() ? await fetchAppsInTossAdPromise(spaceUnitId) : await fetchTossAdPromise({
1146
1438
  adGroupId: spaceUnitId,
1147
- sdkId: "108",
1148
- availableStyleIds: ["1", "2"]
1439
+ sdkId: WEB_SDK_ID,
1440
+ availableStyleIds: AVAILABLE_STYLE_IDS
1149
1441
  });
1150
- return normalizeApiResponse(raw);
1442
+ const response = normalizeApiResponse(raw);
1443
+ const trackingContext = extractAdTrackingContext(response.success);
1444
+ trackResponseError(response, spaceUnitId, trackingContext);
1445
+ void fireResultTracking(response, spaceUnitId, trackingContext);
1446
+ return response;
1151
1447
  } catch (error) {
1152
- return {
1153
- resultType: "FAIL",
1154
- error: {
1155
- reason: error instanceof Error ? error.message : "Unknown fetchTossAd error"
1156
- }
1157
- };
1448
+ const reason = error instanceof Error ? error.message : "Unknown fetchTossAd error";
1449
+ trackBannerError({ adGroupId: spaceUnitId, errorCode: ERROR_CODES.NETWORK_ERROR, errorMessage: reason });
1450
+ return { resultType: "FAIL", error: { reason } };
1158
1451
  }
1159
1452
  };
1160
1453
  }
@@ -1180,7 +1473,12 @@ function initialize(options) {
1180
1473
  return;
1181
1474
  }
1182
1475
  const customAdFetcher = createCustomAdFetcher();
1183
- const config = { environment: "live", customAdFetcher, opener: openUrlOpener };
1476
+ const config = {
1477
+ environment: "live",
1478
+ customAdFetcher,
1479
+ opener: openUrlOpener,
1480
+ onTrackingRequest: handleTrackingRequest
1481
+ };
1184
1482
  sdk.init(config);
1185
1483
  });
1186
1484
  pendingLoad2 = initPromise;
@@ -1357,7 +1655,7 @@ function attachBanner(adGroupId, target, options = {}) {
1357
1655
  autoLoad: true,
1358
1656
  theme: theme === "auto" ? void 0 : theme,
1359
1657
  renderPadding: (styleId) => {
1360
- if (styleId === "1") {
1658
+ if (styleId === LIST_BANNER_STYLE_ID) {
1361
1659
  return DEFAULT_ATTACH_PADDING_BANNER;
1362
1660
  }
1363
1661
  return DEFAULT_ATTACH_PADDING_NATIVE_IMAGE;
@@ -1430,6 +1728,8 @@ function wrapCallbacks(adGroupId, callbacks) {
1430
1728
  });
1431
1729
  callbacks.onAdImpression?.(mapEvent(payload));
1432
1730
  },
1731
+ // 에러 트래킹은 응답을 소유한 createCustomAdFetcher가 담당한다. 콜백은 publisher 전달만.
1732
+ // 응답 수신 후 에러의 mediationId는 SDK(ads-sdk/web)가 error에 실어주므로 그대로 전달한다.
1433
1733
  onAdFailedToRender: (payload) => callbacks.onAdFailedToRender?.({
1434
1734
  ...mapEvent(payload),
1435
1735
  error: payload?.error ?? { code: 0, message: "UNKNOWN" }
@@ -1483,6 +1783,14 @@ function requestNotificationAgreement(params) {
1483
1783
  return unregisterCallbacks;
1484
1784
  }
1485
1785
 
1786
+ // src/getDeclaredAgeRange.ts
1787
+ var getDeclaredAgeRange = Object.assign(
1788
+ createAsyncBridge("getDeclaredAgeRange"),
1789
+ {
1790
+ isSupported: createConstantBridge("getDeclaredAgeRange_isSupported")
1791
+ }
1792
+ );
1793
+
1486
1794
  // src/index.ts
1487
1795
  export * from "@apps-in-toss/types";
1488
1796
  export {
@@ -1501,6 +1809,7 @@ export {
1501
1809
  getAppsInTossGlobals,
1502
1810
  getClipboardText,
1503
1811
  getCurrentLocation,
1812
+ getDeclaredAgeRange,
1504
1813
  getSafeAreaInsets,
1505
1814
  getServerTime,
1506
1815
  graniteEvent,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/web-bridge",
3
3
  "type": "module",
4
- "version": "2.9.3",
4
+ "version": "2.10.1",
5
5
  "description": "Web Bridge for Apps In Toss",
6
6
  "scripts": {
7
7
  "typecheck": "tsc --noEmit",
@@ -27,11 +27,11 @@
27
27
  "dist"
28
28
  ],
29
29
  "dependencies": {
30
- "@apps-in-toss/types": "2.9.3"
30
+ "@apps-in-toss/types": "2.10.1"
31
31
  },
32
32
  "devDependencies": {
33
- "@apps-in-toss/bridge-core": "2.9.3",
34
- "@apps-in-toss/native-modules": "^2.9.3",
33
+ "@apps-in-toss/bridge-core": "2.10.1",
34
+ "@apps-in-toss/native-modules": "^2.10.1",
35
35
  "@swc/core": "^1.12.7",
36
36
  "picocolors": "^1.1.1",
37
37
  "ts-morph": "^26.0.0",