@apps-in-toss/devtools 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1148 @@
1
+ import * as SDK from "@apps-in-toss/web-framework";
2
+ import { GraniteEvent, PermissionAccess, PermissionName as PermissionName$1, PermissionStatus as PermissionStatus$1, TdsEvent } from "@apps-in-toss/web-framework";
3
+ //#region src/mock/domains-3x.d.ts
4
+ declare const getIsTossLoginIntegratedService: (() => Promise<boolean | undefined>) & {
5
+ MIN_TOSS_APP_VERSION: {
6
+ readonly android: "5.237.0";
7
+ readonly ios: "5.237.0";
8
+ };
9
+ isSupported: () => boolean;
10
+ };
11
+ declare const getUserKeyForGame: (() => Promise<SDK.GetAnonymousKeyResponse | "ERROR" | undefined>) & {
12
+ MIN_TOSS_APP_VERSION: {
13
+ readonly android: "5.232.0";
14
+ readonly ios: "5.232.0";
15
+ };
16
+ isSupported: () => boolean;
17
+ };
18
+ declare const getAnonymousKey: (() => Promise<SDK.GetAnonymousKeyResponse | "ERROR" | undefined>) & {
19
+ MIN_TOSS_APP_VERSION: {
20
+ readonly android: "5.232.0";
21
+ readonly ios: "5.232.0";
22
+ };
23
+ isSupported: () => boolean;
24
+ };
25
+ declare const appsInTossSignTossCert: ((params: SDK.AppsInTossSignTossCertParams) => Promise<void>) & {
26
+ MIN_TOSS_APP_VERSION: {
27
+ readonly android: "5.233.0";
28
+ readonly ios: "5.233.0";
29
+ };
30
+ isSupported: () => boolean;
31
+ };
32
+ declare const getConsentedUserData: ((options: SDK.GetConsentedUserDataOptions) => Promise<SDK.ConsentedUserData | undefined>) & {
33
+ MIN_TOSS_APP_VERSION: {
34
+ readonly android: "5.264.0";
35
+ readonly ios: "5.264.0";
36
+ };
37
+ isSupported: () => boolean;
38
+ };
39
+ declare const getDeclaredAgeRange: ((params: SDK.GetDeclaredAgeRangeParams) => Promise<SDK.DeclaredAgeRange>) & {
40
+ MIN_TOSS_APP_VERSION: {
41
+ readonly ios: "5.266.0";
42
+ };
43
+ MIN_OS_VERSION: {
44
+ readonly ios: "26.0";
45
+ };
46
+ isSupported: () => boolean;
47
+ };
48
+ declare const setDeviceOrientation: ((options: SDK.SetDeviceOrientationOptions) => Promise<void>) & {
49
+ MIN_TOSS_APP_VERSION: {
50
+ readonly android: "5.215.0";
51
+ readonly ios: "5.215.0";
52
+ };
53
+ isSupported: () => boolean;
54
+ };
55
+ declare const getServerTime: (() => Promise<number | undefined>) & {
56
+ MIN_TOSS_APP_VERSION: {
57
+ readonly android: "5.245.0";
58
+ readonly ios: "5.245.0";
59
+ };
60
+ isSupported: () => boolean;
61
+ };
62
+ declare const requestReview: (() => Promise<void>) & {
63
+ MIN_TOSS_APP_VERSION: {
64
+ readonly android: "5.253.0";
65
+ readonly ios: "5.253.0";
66
+ };
67
+ isSupported: () => boolean;
68
+ };
69
+ declare const openPDFViewer: ((params: SDK.OpenPDFViewerParams) => Promise<"CLOSE">) & {
70
+ MIN_TOSS_APP_VERSION: {
71
+ readonly android: "5.261.0";
72
+ readonly ios: "5.261.0";
73
+ };
74
+ isSupported: () => boolean;
75
+ };
76
+ declare const saveBase64Data: ((params: SDK.SaveBase64DataParams) => Promise<void>) & {
77
+ MIN_TOSS_APP_VERSION: {
78
+ readonly android: "5.218.0";
79
+ readonly ios: "5.216.0";
80
+ };
81
+ isSupported: () => boolean;
82
+ };
83
+ declare const grantPromotionReward: ((params: SDK.GrantPromotionRewardParams) => Promise<"ERROR" | SDK.GrantPromotionRewardResponse | {
84
+ errorCode: string;
85
+ message: string;
86
+ } | undefined>) & {
87
+ MIN_TOSS_APP_VERSION: {
88
+ readonly android: "5.232.0";
89
+ readonly ios: "5.232.0";
90
+ };
91
+ isSupported: () => boolean;
92
+ };
93
+ declare const grantPromotionRewardForGame: ((params: SDK.GrantPromotionRewardParams) => Promise<"ERROR" | SDK.GrantPromotionRewardResponse | {
94
+ errorCode: string;
95
+ message: string;
96
+ } | undefined>) & {
97
+ MIN_TOSS_APP_VERSION: {
98
+ readonly android: "5.232.0";
99
+ readonly ios: "5.232.0";
100
+ };
101
+ isSupported: () => boolean;
102
+ };
103
+ declare const submitGameCenterLeaderBoardScore: ((params: {
104
+ score: string;
105
+ }) => Promise<SDK.SubmitGameCenterLeaderBoardScoreResponse | undefined>) & {
106
+ MIN_TOSS_APP_VERSION: {
107
+ readonly android: "5.221.0";
108
+ readonly ios: "5.221.0";
109
+ };
110
+ isSupported: () => boolean;
111
+ };
112
+ declare const getGameCenterGameProfile: (() => Promise<SDK.GameCenterGameProfileResponse | undefined>) & {
113
+ MIN_TOSS_APP_VERSION: {
114
+ readonly android: "5.221.0";
115
+ readonly ios: "5.221.0";
116
+ };
117
+ isSupported: () => boolean;
118
+ };
119
+ declare const openGameCenterLeaderboard: (() => Promise<void>) & {
120
+ MIN_TOSS_APP_VERSION: {
121
+ readonly android: "5.221.0";
122
+ readonly ios: "5.221.0";
123
+ };
124
+ isSupported: () => boolean;
125
+ };
126
+ declare const contactsViral: ((params: SDK.ContactsViralParams) => (() => void)) & {
127
+ MIN_TOSS_APP_VERSION: {
128
+ readonly android: "5.223.0";
129
+ readonly ios: "5.223.0";
130
+ };
131
+ isSupported: () => boolean;
132
+ };
133
+ declare const requestNotificationAgreement: ((params: SDK.RequestNotificationAgreementOptions) => () => void) & {
134
+ MIN_TOSS_APP_VERSION: {
135
+ readonly android: "5.255.0";
136
+ readonly ios: "5.255.0";
137
+ };
138
+ isSupported: () => boolean;
139
+ };
140
+ declare const requestTossPayPaysBilling: ((options: {
141
+ params: SDK.RequestTossPayPaysBillingOptions;
142
+ }) => Promise<SDK.RequestTossPayPaysBillingResult | undefined>) & {
143
+ MIN_TOSS_APP_VERSION: {
144
+ readonly android: "5.256.0";
145
+ readonly ios: "5.256.0";
146
+ };
147
+ isSupported: () => boolean;
148
+ };
149
+ declare const getPlatformOS: typeof SDK.getPlatformOS;
150
+ declare const getOperationalEnvironment: typeof SDK.getOperationalEnvironment;
151
+ declare const getLocale: typeof SDK.getLocale;
152
+ declare const getDeviceId: typeof SDK.getDeviceId;
153
+ declare const getSchemeUri: typeof SDK.getSchemeUri;
154
+ declare const getSafeAreaInsets: typeof SDK.getSafeAreaInsets;
155
+ declare const isMinVersionSupported: typeof SDK.isMinVersionSupported;
156
+ declare const GoogleAdMob: typeof SDK.GoogleAdMob;
157
+ declare const loadFullScreenAd: typeof SDK.loadFullScreenAd;
158
+ declare const showFullScreenAd: typeof SDK.showFullScreenAd;
159
+ declare const IAP: typeof SDK.IAP;
160
+ declare const Analytics: typeof SDK.Analytics;
161
+ declare const Clipboard: typeof SDK.Clipboard;
162
+ declare const Device: typeof SDK.Device;
163
+ declare const Environment: typeof SDK.Environment;
164
+ declare const File: typeof SDK.File;
165
+ declare const Game: typeof SDK.Game;
166
+ declare const Notification: typeof SDK.Notification;
167
+ declare const Promotion: typeof SDK.Promotion;
168
+ declare const Review: typeof SDK.Review;
169
+ declare const SafeArea: typeof SDK.SafeArea;
170
+ declare const Screen: typeof SDK.Screen;
171
+ declare const Share: typeof SDK.Share;
172
+ declare const TossAuth: typeof SDK.TossAuth;
173
+ declare const TossPay: typeof SDK.TossPay;
174
+ declare const User: typeof SDK.User;
175
+ //#endregion
176
+ //#region src/mock/ads/index.d.ts
177
+ declare const TossAds: {
178
+ initialize: ((options: {
179
+ callbacks?: {
180
+ onInitialized?: () => void;
181
+ onInitializationFailed?: (error: Error) => void;
182
+ };
183
+ }) => void) & {
184
+ isSupported: () => boolean;
185
+ };
186
+ attach: ((_adGroupId: string, target: string | HTMLElement, _options?: unknown) => void) & {
187
+ isSupported: () => boolean;
188
+ };
189
+ attachBanner: ((adGroupId: string, target: string | HTMLElement, options?: {
190
+ theme?: "auto" | "light" | "dark";
191
+ tone?: "blackAndWhite" | "grey";
192
+ variant?: "card" | "expanded";
193
+ callbacks?: {
194
+ onAdRendered?: (payload: {
195
+ slotId: string;
196
+ adGroupId: string;
197
+ adMetadata: {
198
+ creativeId: string;
199
+ requestId: string;
200
+ };
201
+ }) => void;
202
+ onAdViewable?: (payload: {
203
+ slotId: string;
204
+ adGroupId: string;
205
+ adMetadata: {
206
+ creativeId: string;
207
+ requestId: string;
208
+ };
209
+ }) => void;
210
+ onAdClicked?: (payload: {
211
+ slotId: string;
212
+ adGroupId: string;
213
+ adMetadata: {
214
+ creativeId: string;
215
+ requestId: string;
216
+ };
217
+ }) => void;
218
+ onAdImpression?: (payload: {
219
+ slotId: string;
220
+ adGroupId: string;
221
+ adMetadata: {
222
+ creativeId: string;
223
+ requestId: string;
224
+ };
225
+ }) => void;
226
+ onAdFailedToRender?: (payload: {
227
+ slotId: string;
228
+ adGroupId: string;
229
+ adMetadata: Record<string, never>;
230
+ error: {
231
+ code: number;
232
+ message: string;
233
+ domain?: string;
234
+ };
235
+ }) => void;
236
+ onNoFill?: (payload: {
237
+ slotId: string;
238
+ adGroupId: string;
239
+ adMetadata: Record<string, never>;
240
+ }) => void;
241
+ };
242
+ } | undefined) => {
243
+ destroy: () => void;
244
+ }) & {
245
+ isSupported: () => boolean;
246
+ };
247
+ destroy: ((slotId: string) => void) & {
248
+ isSupported: () => boolean;
249
+ };
250
+ destroyAll: (() => void) & {
251
+ isSupported: () => boolean;
252
+ };
253
+ };
254
+ //#endregion
255
+ //#region src/mock/analytics/index.d.ts
256
+ /**
257
+ * Analytics mock
258
+ */
259
+ type Primitive$1 = string | number | boolean | null | undefined | symbol;
260
+ declare function eventLog(params: {
261
+ log_name: string;
262
+ log_type: string;
263
+ params: Record<string, Primitive$1>;
264
+ }): Promise<void>;
265
+ //#endregion
266
+ //#region src/mock/types.d.ts
267
+ type Primitive = string | number | boolean | null | undefined | symbol;
268
+ type PlatformOS = "ios" | "android";
269
+ type OperationalEnvironment = "toss" | "sandbox";
270
+ type NetworkStatus = "OFFLINE" | "WIFI" | "2G" | "3G" | "4G" | "5G" | "WWAN" | "UNKNOWN";
271
+ type PermissionStatus = "notDetermined" | "denied" | "allowed";
272
+ type PermissionName = "clipboard" | "contacts" | "photos" | "geolocation" | "camera" | "microphone";
273
+ type HapticFeedbackType = "tickWeak" | "tap" | "tickMedium" | "softMedium" | "basicWeak" | "basicMedium" | "success" | "error" | "wiggle" | "confetti";
274
+ type DeviceApiMode = "mock" | "web" | "prompt";
275
+ interface DeviceModes {
276
+ camera: DeviceApiMode;
277
+ photos: DeviceApiMode;
278
+ location: DeviceApiMode;
279
+ network: "mock" | "web";
280
+ clipboard: "mock" | "web";
281
+ }
282
+ interface MockData {
283
+ images: string[];
284
+ clipboardText: string;
285
+ }
286
+ interface LocationCoords {
287
+ latitude: number;
288
+ longitude: number;
289
+ altitude: number;
290
+ accuracy: number;
291
+ altitudeAccuracy: number;
292
+ heading: number;
293
+ }
294
+ interface MockLocation {
295
+ coords: LocationCoords;
296
+ timestamp: number;
297
+ accessLocation?: "FINE" | "COARSE";
298
+ }
299
+ interface MockContact {
300
+ name: string;
301
+ phoneNumber: string;
302
+ }
303
+ interface MockIapProduct {
304
+ sku: string;
305
+ type: "CONSUMABLE" | "NON_CONSUMABLE" | "SUBSCRIPTION";
306
+ displayName: string;
307
+ displayAmount: string;
308
+ iconUrl: string;
309
+ description: string;
310
+ renewalCycle?: "WEEKLY" | "MONTHLY" | "YEARLY";
311
+ }
312
+ type IapNextResult = "success" | "USER_CANCELED" | "INVALID_PRODUCT_ID" | "PAYMENT_PENDING" | "NETWORK_ERROR" | "ITEM_ALREADY_OWNED" | "INTERNAL_ERROR";
313
+ type NotificationAgreementResult = "newAgreement" | "alreadyAgreed" | "agreementRejected";
314
+ /**
315
+ * `getConsentedUserData`가 반환할 수 있는 동의 데이터 키. SDK 선언(`@apps-in-toss/web-bridge`
316
+ * 경유, web-framework 2.x 라인)의 `ConsentedUserDataKey`와 이름·값 동일(devtools#798).
317
+ */
318
+ type ConsentedUserDataKey = "USER_NAME" | "USER_GENDER" | "USER_NATIONALITY" | "USER_BIRTHDAY" | "USER_PHONE" | "USER_ADDRESS" | "USER_EMAIL" | "USER_CONSUMPTION_HISTORY";
319
+ /** `getConsentedUserData`의 반환 shape. SDK 선언과 동일한 `Partial<Record<..., string>>`. */
320
+ type ConsentedUserData = Partial<Record<ConsentedUserDataKey, string>>;
321
+ interface DeclaredAgeRange {
322
+ status: "SHARING" | "DECLINED_SHARING" | "UNSUPPORTED_OS" | "NOT_AVAILABLE" | "INVALID_REQUEST" | "FAILED";
323
+ lowerBound?: number;
324
+ upperBound?: number;
325
+ ageRangeDeclaration?: string;
326
+ activeParentalControls: string[];
327
+ isEligibleForAgeFeatures?: boolean;
328
+ errorCode?: string;
329
+ }
330
+ interface AnalyticsLogEntry {
331
+ timestamp: number;
332
+ type: string;
333
+ params: Record<string, unknown>;
334
+ }
335
+ interface SafeAreaInsets$1 {
336
+ top: number;
337
+ bottom: number;
338
+ left: number;
339
+ right: number;
340
+ }
341
+ type ViewportPresetId = "none" | "iphone-se-3" | "iphone-15-pro" | "iphone-16e" | "iphone-17" | "iphone-air" | "iphone-17-pro" | "iphone-17-pro-max" | "galaxy-s26" | "galaxy-s26-plus" | "galaxy-s26-ultra" | "galaxy-z-flip7" | "galaxy-z-fold7-folded" | "galaxy-z-fold7-unfolded" | "custom";
342
+ /**
343
+ * Panel의 orientation 선택.
344
+ * - `auto` — Panel이 강제하지 않음. 앱의 SDK `setDeviceOrientation` 호출을 그대로 따름.
345
+ * 호출 값은 별도로 `viewport.appOrientation`에 기록되며, `viewport.orientation`은
346
+ * 계속 `auto`로 유지된다 — 같은 앱이 여러 번 호출해도 매번 정상 반영됨.
347
+ * - `portrait` / `landscape` — Panel이 강제. SDK 호출은 무시됨 (로그만 남김).
348
+ */
349
+ type ViewportOrientation = "auto" | "portrait" | "landscape";
350
+ /**
351
+ * `setDeviceOrientation`이 한 번도 호출되지 않은 초기 상태는 `null`.
352
+ * SDK가 받을 수 있는 값과 일치하므로 portrait/landscape만 허용.
353
+ */
354
+ type AppOrientation = "portrait" | "landscape" | null;
355
+ /**
356
+ * Apps in Toss host nav bar 변형. SDK `webViewProps.type`과 의미 일치.
357
+ * - `partner` (기본): 흰 배경, 뒤로가기 + 앱 아이콘/이름 + ⋯ + ×.
358
+ * - `game`: 투명 배경, 게임 캔버스를 가리지 않도록 ⋯ + ×만 표시.
359
+ */
360
+ type AitNavBarType = "partner" | "game";
361
+ interface ViewportState {
362
+ preset: ViewportPresetId;
363
+ /** User-controlled orientation. `auto`이면 `appOrientation`을 따른다. */
364
+ orientation: ViewportOrientation;
365
+ /**
366
+ * SDK가 마지막으로 요청한 orientation. `setDeviceOrientation` 호출 시 갱신.
367
+ * `orientation === 'auto'`일 때 실제 화면 방향 결정에 쓰인다. 초기값 `null`.
368
+ */
369
+ appOrientation: AppOrientation;
370
+ customWidth: number;
371
+ customHeight: number;
372
+ frame: boolean;
373
+ /** Render the Apps in Toss host nav bar (back / app name / ··· / close) inside the frame. */
374
+ aitNavBar: boolean;
375
+ /** Nav bar 변형. `partner` = 기본(흰 배경 + 아이콘/이름), `game` = 투명 배경 + ⋯/× 만. */
376
+ aitNavBarType: AitNavBarType;
377
+ }
378
+ //#endregion
379
+ //#region src/mock/auth/index.d.ts
380
+ declare function appLogin(): Promise<{
381
+ authorizationCode: string;
382
+ referrer: "DEFAULT" | "SANDBOX";
383
+ }>;
384
+ //#endregion
385
+ //#region src/mock/bridge-factories.d.ts
386
+ /** Generic bridge escape hatches exposed by both SDK lines. */
387
+ declare function createAsyncBridge<Args extends unknown[] = unknown[], Result = unknown>(method: string): (...args: Args) => Promise<Result>;
388
+ declare function createConstantBridge<T>(name: string): () => T;
389
+ declare function createEventBridge<Options = unknown, Event = unknown>(method: string): (args: {
390
+ options?: Options;
391
+ onEvent: (event: Event) => void;
392
+ onError: (error: Error) => void;
393
+ }) => () => void;
394
+ //#endregion
395
+ //#region src/mock/device/_helpers.d.ts
396
+ /**
397
+ * 디바이스 모듈 내부 공유 헬퍼
398
+ */
399
+ declare function getDefaultPlaceholderImages(): string[];
400
+ //#endregion
401
+ //#region src/mock/device/camera.d.ts
402
+ /**
403
+ * Camera & Album Photos & Album Items mock
404
+ * mock/web/prompt 모드 지원
405
+ */
406
+ type AlbumItemType = "PHOTO" | "VIDEO";
407
+ declare const openCamera: ((_options?: {
408
+ base64?: boolean;
409
+ maxWidth?: number;
410
+ }) => Promise<{
411
+ id: string;
412
+ dataUri: string;
413
+ }>) & {
414
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
415
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
416
+ };
417
+ declare const fetchAlbumPhotos: ((options?: {
418
+ maxCount?: number;
419
+ maxWidth?: number;
420
+ base64?: boolean;
421
+ }) => Promise<Array<{
422
+ id: string;
423
+ dataUri: string;
424
+ }>>) & {
425
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
426
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
427
+ };
428
+ interface FetchAlbumItemsOptions {
429
+ types?: AlbumItemType[];
430
+ maxCount?: number;
431
+ maxWidth?: number;
432
+ base64?: boolean;
433
+ }
434
+ interface AlbumItemResponse {
435
+ id: string;
436
+ dataUri: string;
437
+ type: AlbumItemType;
438
+ }
439
+ declare const _fetchAlbumItemsWithPermission: ((options?: FetchAlbumItemsOptions) => Promise<AlbumItemResponse[]>) & {
440
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
441
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
442
+ };
443
+ declare const fetchAlbumItems: typeof _fetchAlbumItemsWithPermission & {
444
+ isSupported: () => boolean;
445
+ };
446
+ //#endregion
447
+ //#region src/mock/device/clipboard.d.ts
448
+ /**
449
+ * Clipboard mock
450
+ * mock/web 모드 지원
451
+ */
452
+ declare const getClipboardText: (() => Promise<string>) & {
453
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
454
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
455
+ };
456
+ declare const setClipboardText: ((text: string) => Promise<void>) & {
457
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
458
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
459
+ };
460
+ //#endregion
461
+ //#region src/mock/device/contacts.d.ts
462
+ declare const _fetchContacts: (options: {
463
+ size: number;
464
+ offset: number;
465
+ query?: {
466
+ contains?: string;
467
+ };
468
+ }) => Promise<{
469
+ result: MockContact[];
470
+ nextOffset: number | null;
471
+ done: boolean;
472
+ }>;
473
+ /**
474
+ * 상류 SDK는 `fetchContacts`의 타입에 `.getPermission`/`.openPermissionDialog`를
475
+ * `PermissionFunctionWithDialog`로 선언하지만, 실기기(2.x×iOS)에는 그 메서드가
476
+ * **런타임에 붙어 있지 않다**(devtools#795 — 호출 시 `fetchContacts.getPermission
477
+ * is not a function` native `TypeError`). standalone `getPermission({name:
478
+ * 'contacts', access: 'access'})`는 실기기에서 정상 resolve하므로(env3 run11,
479
+ * `../permissions.ts`) 부재는 fetchContacts에 **부착된** 메서드에만 해당하는
480
+ * 상류 타입↔런타임 불일치다.
481
+ *
482
+ * mock은 다른 device API처럼 `withPermission()`으로 감싸지 않고, bare async fn을
483
+ * 상류 시그니처로만 캐스트한다 — `.getPermission`/`.openPermissionDialog` 접근은
484
+ * `undefined`가 되고, 호출하면 `undefined()` → native `TypeError`로 떨어져
485
+ * 실기기와 일치한다(`__typecheck.ts`/`__typecheck-2x.ts`는 캐스트 타입에 두
486
+ * 메서드가 여전히 남아 있어 그대로 통과). `_fetchContacts` 내부에서 이미
487
+ * `checkPermission`을 호출하므로 메인 동작(권한 거부 시
488
+ * `FetchContactsPermissionError`)은 변화 없다.
489
+ *
490
+ * 직접 관측된 것은 `getPermission` 부재뿐이다. `openPermissionDialog` 부재는
491
+ * "상류가 fetchContacts에 권한 헬퍼 전체를 붙이지 않는다"는 합리적 추론이지
492
+ * 별도 실측은 아니다. 다른 `withPermission` API(clipboard/camera/location)로는
493
+ * 이 부재를 확장하지 않는다 — 그쪽 부착 메서드가 실기기에서 없다는 관측은
494
+ * 없다(#783 "측정 밖 확장 금지" 원칙).
495
+ */
496
+ declare const fetchContacts: typeof _fetchContacts & {
497
+ getPermission: () => Promise<PermissionStatus$1>;
498
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
499
+ };
500
+ //#endregion
501
+ //#region src/mock/device/haptic.d.ts
502
+ declare function generateHapticFeedback(options: {
503
+ type: HapticFeedbackType;
504
+ }): Promise<void>;
505
+ //#endregion
506
+ //#region src/mock/device/location.d.ts
507
+ declare enum Accuracy {
508
+ Lowest = 1,
509
+ Low = 2,
510
+ Balanced = 3,
511
+ High = 4,
512
+ Highest = 5,
513
+ BestForNavigation = 6
514
+ }
515
+ declare const getCurrentLocation: ((_options?: {
516
+ accuracy: Accuracy;
517
+ }) => Promise<MockLocation>) & {
518
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
519
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
520
+ };
521
+ interface StartUpdateLocationEventParams {
522
+ onEvent: (response: MockLocation) => void;
523
+ onError: (error: unknown) => void;
524
+ options: {
525
+ accuracy: Accuracy;
526
+ timeInterval: number;
527
+ distanceInterval: number;
528
+ };
529
+ }
530
+ declare const startUpdateLocation: ((eventParams: StartUpdateLocationEventParams) => (() => void)) & {
531
+ getPermission: () => Promise<import("@apps-in-toss/web-framework").PermissionStatus>;
532
+ openPermissionDialog: () => Promise<"allowed" | "denied">;
533
+ };
534
+ //#endregion
535
+ //#region src/mock/device/storage.d.ts
536
+ /**
537
+ * Storage mock
538
+ * localStorage에 `__ait_storage:` prefix로 저장하여 앱 자체 localStorage와 분리
539
+ *
540
+ * 실기기(2.x×iOS) capture는 `setItem`/`removeItem`/`clearItems` 세 메서드가
541
+ * `undefined`가 아니라 `null`로 resolve됨을 보였다(devtools#770). 원본 SDK 타입
542
+ * 선언은 여전히 `Promise<void>`이므로 시그니처는 그대로 두고, 런타임 반환값만
543
+ * `null`로 캐스트해 실측과 동치시킨다 — Analytics·setClipboardText와 같은 처리(#775).
544
+ * `getItem`은 이미 `string | null`이라 실측과 일치하므로 손대지 않는다.
545
+ */
546
+ declare const Storage: {
547
+ getItem: (key: string) => Promise<string | null>;
548
+ setItem: (key: string, value: string) => Promise<void>;
549
+ removeItem: (key: string) => Promise<void>;
550
+ clearItems: () => Promise<void>;
551
+ };
552
+ //#endregion
553
+ //#region src/mock/iap/index.d.ts
554
+ declare function checkoutPayment(options: {
555
+ params: {
556
+ payToken: string;
557
+ };
558
+ }): Promise<{
559
+ success: boolean;
560
+ reason?: string;
561
+ }>;
562
+ //#endregion
563
+ //#region src/mock/navigation/index.d.ts
564
+ declare function closeView(): Promise<void>;
565
+ declare function openURL(url: string): Promise<void>;
566
+ declare function share(message: {
567
+ message: string;
568
+ }): Promise<void>;
569
+ declare function getTossShareLink(path: string, _ogImageUrl?: string): Promise<string>;
570
+ declare function setIosSwipeGestureEnabled(options: {
571
+ isEnabled: boolean;
572
+ }): Promise<void>;
573
+ declare const setScreenAwakeMode: (options: {
574
+ enabled: boolean;
575
+ }) => Promise<{
576
+ enabled: boolean;
577
+ }>;
578
+ declare const setSecureScreen: (options: {
579
+ enabled: boolean;
580
+ }) => Promise<{
581
+ enabled: boolean;
582
+ }>;
583
+ declare function getTossAppVersion(): string;
584
+ declare function getGroupId(): string;
585
+ declare function getNetworkStatus(): Promise<NetworkStatus>;
586
+ declare const graniteEvent: {
587
+ addEventListener<K extends keyof GraniteEvent>(event: K, { onEvent, onError }: {
588
+ onEvent: GraniteEvent[K]["onEvent"];
589
+ onError?: GraniteEvent[K]["onError"];
590
+ options?: GraniteEvent[K]["options"];
591
+ }): () => void;
592
+ };
593
+ declare const appsInTossEvent: {
594
+ addEventListener<K extends string>(_event: K, _handlers: {
595
+ onEvent: (...args: unknown[]) => void;
596
+ onError?: (error: Error) => void;
597
+ options?: unknown;
598
+ }): () => void;
599
+ };
600
+ declare const tdsEvent: {
601
+ addEventListener<K extends keyof TdsEvent>(event: K, { onEvent }: {
602
+ onEvent: TdsEvent[K]["onEvent"];
603
+ onError?: TdsEvent[K]["onError"];
604
+ options?: TdsEvent[K]["options"];
605
+ }): () => void;
606
+ };
607
+ /**
608
+ * @deprecated web-framework 3.0 에서 제거됨. 2.x 소비자 back-compat용으로 유지.
609
+ */
610
+ declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
611
+ options: {
612
+ callbackId: string;
613
+ };
614
+ onEvent: (isVisible: boolean) => void;
615
+ onError: (error: unknown) => void;
616
+ }): () => void;
617
+ declare const env: {
618
+ getDeploymentId: () => string;
619
+ };
620
+ declare function getAppsInTossGlobals(): {
621
+ deploymentId: string;
622
+ brandDisplayName: string;
623
+ brandIcon: string;
624
+ brandPrimaryColor: string;
625
+ };
626
+ type SafeAreaInsetsValue = {
627
+ top: number;
628
+ bottom: number;
629
+ left: number;
630
+ right: number;
631
+ };
632
+ type SafeAreaInsetsSubscribeHandler = {
633
+ onEvent: (data: SafeAreaInsetsValue) => void;
634
+ };
635
+ declare const SafeAreaInsets: {
636
+ get: () => SafeAreaInsetsValue;
637
+ subscribe: ({ onEvent }: SafeAreaInsetsSubscribeHandler) => (() => void);
638
+ };
639
+ //#endregion
640
+ //#region src/mock/partner/index.d.ts
641
+ /**
642
+ * Partner / TDS mock
643
+ */
644
+ interface AddAccessoryButtonOptions {
645
+ id: string;
646
+ title: string;
647
+ icon: {
648
+ name: string;
649
+ };
650
+ }
651
+ declare const partner: {
652
+ addAccessoryButton(options: AddAccessoryButtonOptions): Promise<void>;
653
+ removeAccessoryButton(): Promise<void>;
654
+ };
655
+ //#endregion
656
+ //#region src/mock/permissions.d.ts
657
+ /**
658
+ * web-framework 3.0+ 권한 에러 기반 클래스.
659
+ * `instanceof PermissionError`로 체크하는 코드와 호환된다.
660
+ */
661
+ declare class PermissionError extends Error {
662
+ constructor({ methodName, message }: {
663
+ methodName: string;
664
+ message?: string;
665
+ });
666
+ }
667
+ /** openCamera 권한 에러 */
668
+ declare class OpenCameraPermissionError extends PermissionError {
669
+ constructor();
670
+ }
671
+ /** fetchAlbumPhotos 권한 에러 */
672
+ declare class FetchAlbumPhotosPermissionError extends PermissionError {
673
+ constructor();
674
+ }
675
+ /** fetchContacts 권한 에러 */
676
+ declare class FetchContactsPermissionError extends PermissionError {
677
+ constructor();
678
+ }
679
+ /** getCurrentLocation 권한 에러 */
680
+ declare class GetCurrentLocationPermissionError extends PermissionError {
681
+ constructor();
682
+ }
683
+ /** getClipboardText 권한 에러 */
684
+ declare class GetClipboardTextPermissionError extends PermissionError {
685
+ constructor();
686
+ }
687
+ /** setClipboardText 권한 에러 */
688
+ declare class SetClipboardTextPermissionError extends PermissionError {
689
+ constructor();
690
+ }
691
+ /**
692
+ * startUpdateLocation 권한 에러.
693
+ * web-framework 3.0에서 GetCurrentLocationPermissionError의 alias.
694
+ */
695
+ declare const StartUpdateLocationPermissionError: typeof GetCurrentLocationPermissionError;
696
+ declare function getPermission(permission: {
697
+ name: PermissionName$1;
698
+ access: PermissionAccess;
699
+ }): Promise<PermissionStatus$1>;
700
+ declare function openPermissionDialog(permission: {
701
+ name: PermissionName$1;
702
+ access: PermissionAccess;
703
+ }): Promise<"allowed" | "denied">;
704
+ declare function requestPermission(permission: {
705
+ name: PermissionName$1;
706
+ access: PermissionAccess;
707
+ }): Promise<"allowed" | "denied">;
708
+ //#endregion
709
+ //#region src/mock/native-error.d.ts
710
+ /**
711
+ * sdk-example#284 매트릭스에 등재된 2.x 네이티브 실패 코드 인벤토리.
712
+ * 새 코드가 매트릭스에 추가되면 여기에도 추가한다.
713
+ */
714
+ type NativeErrorCode = "APP_LOGIN" | "PLACEMENT_ID_FETCH_FAILED" | "EXECUTION_ERROR" | "NO_PERMISSION" | "INVALID_REQUEST" | "INVALID_DATA" | "FAILED_TO_GET_LOADED_AD" | "APP_BRIDGE_THROTTLED" | "1006" | "4000";
715
+ //#endregion
716
+ //#region src/mock/sdk-call.d.ts
717
+ /**
718
+ * SDK-call trace shape produced by the mock's `observe()` wrapper.
719
+ *
720
+ * These declarations used to live in `src/mcp/ait-source.ts` (that module is now
721
+ * `@ait-co/debugger`'s `packages/debugger/src/mcp/ait-source.ts`) because the MCP
722
+ * `AIT.getSdkCallHistory` tool was their only *consumer*. After the debug
723
+ * surface moved to `@ait-co/debugger` (#818) the producer — `observe()`
724
+ * writing into `aitState.sdkCallLog` — is the only side left in this package,
725
+ * so the types live next to it.
726
+ *
727
+ * They stay part of the public `@apps-in-toss/devtools/mock` surface (re-exported by
728
+ * `state.ts`): a consumer reading `window.__ait.sdkCallLog` needs the shape,
729
+ * and any out-of-process reader (the MCP daemon among them) types against the
730
+ * same declarations.
731
+ */
732
+ /**
733
+ * Mock fidelity grade of the SDK call.
734
+ * - `faithful` — mock faithfully reproduces the real SDK contract (🟢).
735
+ * - `partial` — mock partially matches; edge cases may differ from real (🟡).
736
+ * - `inert` — mock accepts the call but produces no observable effect (🔴).
737
+ */
738
+ type AitSdkCallFidelity = "faithful" | "partial" | "inert";
739
+ /** One entry of the SDK-call trace. */
740
+ interface AitSdkCall {
741
+ /** SDK method name, e.g. `getOperationalEnvironment`, `saveBase64Data`. */
742
+ method: string;
743
+ /** Arguments passed to the call, serialized for transport. */
744
+ args: unknown[];
745
+ /** Milliseconds since epoch when the call was made. */
746
+ timestamp: number;
747
+ /** Outcome — resolved value, rejection error message, or still pending. */
748
+ status: "resolved" | "rejected" | "pending";
749
+ /** Serialized resolved value when `status === 'resolved'`. */
750
+ result?: unknown;
751
+ /** Error message when `status === 'rejected'`. */
752
+ error?: string;
753
+ /** Mock fidelity grade — how closely this mock reproduces the real SDK behaviour. */
754
+ fidelity: AitSdkCallFidelity;
755
+ }
756
+ //#endregion
757
+ //#region src/mock/state.d.ts
758
+ type Listener = () => void;
759
+ interface AitDevtoolsState {
760
+ platform: PlatformOS;
761
+ environment: OperationalEnvironment;
762
+ appVersion: string;
763
+ locale: string;
764
+ schemeUri: string;
765
+ groupId: string;
766
+ deploymentId: string;
767
+ deviceId: string;
768
+ brand: {
769
+ displayName: string;
770
+ icon: string;
771
+ primaryColor: string;
772
+ };
773
+ networkStatus: NetworkStatus;
774
+ navigation: {
775
+ iosSwipeGestureEnabled: boolean | null;
776
+ };
777
+ permissions: Record<PermissionName, PermissionStatus>;
778
+ location: MockLocation;
779
+ safeAreaInsets: SafeAreaInsets$1;
780
+ contacts: MockContact[];
781
+ iap: {
782
+ products: MockIapProduct[];
783
+ nextResult: IapNextResult;
784
+ pendingOrders: Array<{
785
+ orderId: string;
786
+ sku: string;
787
+ paymentCompletedDate: string;
788
+ }>;
789
+ completedOrders: Array<{
790
+ orderId: string;
791
+ sku: string;
792
+ status: "COMPLETED" | "REFUNDED";
793
+ date: string;
794
+ }>;
795
+ };
796
+ payment: {
797
+ nextResult: "success" | "fail";
798
+ failReason: string;
799
+ };
800
+ auth: {
801
+ isLoggedIn: boolean;
802
+ isTossLoginIntegrated: boolean;
803
+ userKeyHash: string;
804
+ anonymousKeyHash: string;
805
+ /**
806
+ * `getConsentedUserData`가 resolve할 최소 plausible 객체(devtools#798). 실제로는
807
+ * 콘솔에 등록된 동의문/데이터 묶음(`consentedUserDataKey`)에 따라 채워지는 키가
808
+ * 달라지지만 그 매핑은 서버 쪽 설정이라 mock이 알 수 없다 — 호출 파라미터와
809
+ * 무관하게 이 상태값을 그대로 반환한다.
810
+ */
811
+ consentedUserData: ConsentedUserData;
812
+ /** `getDeclaredAgeRange`/`User.getDeclaredAgeRange`가 반환할 테스트 값. */
813
+ declaredAgeRange: DeclaredAgeRange;
814
+ };
815
+ notification: {
816
+ nextResult: NotificationAgreementResult;
817
+ };
818
+ ads: {
819
+ isLoaded: boolean;
820
+ nextEvent: "loaded" | "clicked" | "dismissed" | "failedToShow" | "impression" | "userEarnedReward";
821
+ forceNoFill: boolean;
822
+ lastEvent: {
823
+ type: string;
824
+ timestamp: number;
825
+ } | null;
826
+ /** AdMob reward 단위 타입 (기본: 'coins') */
827
+ rewardUnitType: string;
828
+ /** AdMob reward 단위 수량 (기본: 10) */
829
+ rewardAmount: number;
830
+ };
831
+ game: {
832
+ profile: {
833
+ nickname: string;
834
+ profileImageUri: string;
835
+ } | null;
836
+ leaderboardScores: Array<{
837
+ score: string;
838
+ timestamp: number;
839
+ }>;
840
+ };
841
+ analyticsLog: AnalyticsLogEntry[];
842
+ sdkCallLog: AitSdkCall[];
843
+ deviceModes: DeviceModes;
844
+ mockData: MockData;
845
+ panelEditable: boolean;
846
+ viewport: ViewportState;
847
+ failureModes: FailureModes;
848
+ }
849
+ /**
850
+ * per-API 실패 코드 다이얼. 값이 설정된 API만 mock이 reject하고, 나머지는
851
+ * 기존 낙관적 resolve를 유지한다. `sdkLine`은 envelope shape 분기 축 —
852
+ * `'2.x'`(기본)는 native envelope(`{name,code,userInfo,moduleName,__isError}`),
853
+ * `'3.x'`는 맨 Error로 평탄화(sdk-example#284 매트릭스 "패턴 ① envelope 평탄화").
854
+ */
855
+ interface FailureModes {
856
+ /** 네이티브 실패 envelope의 라인 축. 기본 '2.x'. */
857
+ sdkLine: "2.x" | "3.x";
858
+ /** appLogin 실패 코드 (예: 'APP_LOGIN'). 미설정 시 기존처럼 항상 resolve. */
859
+ appLogin?: NativeErrorCode;
860
+ /** GoogleAdMob.loadAppsInTossAdMob 실패 코드 (예: 'PLACEMENT_ID_FETCH_FAILED'). */
861
+ loadAdMob?: NativeErrorCode;
862
+ /** loadFullScreenAd 실패 코드 (예: 'EXECUTION_ERROR'). */
863
+ loadFullScreenAd?: NativeErrorCode;
864
+ /**
865
+ * getIsTossLoginIntegratedService 실패 코드 (devtools#783 실측: env3 run11,
866
+ * 2.x/iOS `A1-awaited-is-boolean` 시나리오 — rejected/`Error`/`EXECUTION_ERROR`).
867
+ */
868
+ getIsTossLoginIntegratedService?: NativeErrorCode;
869
+ /**
870
+ * requestNotificationAgreement 실패 코드 (devtools#783 실측: env3 run11,
871
+ * 2.x/iOS `happy-force-*`/`A1-empty-templateCode` 시나리오 전부 —
872
+ * rejected/`Error`/`4000`).
873
+ */
874
+ requestNotificationAgreement?: NativeErrorCode;
875
+ /**
876
+ * 권한 이름별 실패 코드 (devtools#783 실측: env3 run11, 2.x/iOS
877
+ * `permissions.ait.test.ts` PERMISSION_NAMES 순회 — `geolocation`/`camera`/
878
+ * `microphone`만 rejected/`Error`/`NO_PERMISSION`, `clipboard`/`contacts`/
879
+ * `photos`는 resolved. 31146의 `granite.config.ts`가 `permissions: []`라
880
+ * 선언 안 된 권한만 거부되는 그림과 정합 — 전역 on/off가 아니라 이름 단위 맵.
881
+ * 설정된 이름만 reject, 나머지는 기존대로 resolve.
882
+ */
883
+ getPermission?: Partial<Record<PermissionName, NativeErrorCode>>;
884
+ /**
885
+ * THROTTLED 다이얼 (#834) — 실기기 네이티브 브리지의 per-method rate limit을
886
+ * 재현한다. `methods`에 적힌 메서드를 `intervalMs` 안에 재호출하면
887
+ * `APP_BRIDGE_THROTTLED`로 거부된다(2.x envelope / 3.x 맨 Error는 `sdkLine`을 따름).
888
+ * 미설정이 기본 = zero behavior change.
889
+ *
890
+ * 훅이 실제로 삽입된 메서드는 `throttle.ts`의 `THROTTLE_INSTRUMENTED_METHODS`가
891
+ * 정본이다 — 목록 밖 이름을 넣어도 효과가 없다. 거부된 호출은 창을 갱신하지 않는다.
892
+ */
893
+ throttled?: {
894
+ methods: string[];
895
+ intervalMs: number;
896
+ };
897
+ /**
898
+ * soft-resolve 다이얼 (#789) — reject가 아니라 "다른 shape로 resolve"하는 env3
899
+ * 프로비저닝-의존 실패를 재현한다. 켠 API만 실측 대체 shape로 resolve하고, 미설정
900
+ * API는 선언 타입대로 성공 shape를 유지한다(다이얼 미사용 시 zero behavior change).
901
+ * shape는 API별 고정(env3 run11 2.x/iOS 실측 — valueKeys만 실측, 문자열 내용은 예시):
902
+ * grantPromotionReward/grantPromotionRewardForGame → { errorCode, message }
903
+ * getSubscriptionInfo → {}
904
+ * checkoutPayment/requestTossPayPaysBilling → { false, reason } (valueKeys=['false','reason'])
905
+ * payment shape의 리터럴 `false` 키가 하네스 artifact가 아니라 실기기 WebView 관측값임은
906
+ * 코드로 확정됐다(sdk-example#303: capture는 relay 개입 전 WebView 안에서 계산 — 아래
907
+ * checkoutPayment 항목 주석). #303/#789.
908
+ */
909
+ softResolve?: {
910
+ grantPromotionReward?: boolean;
911
+ grantPromotionRewardForGame?: boolean;
912
+ getSubscriptionInfo?: boolean;
913
+ /**
914
+ * checkoutPayment/requestTossPayPaysBilling → `{ false: …, reason: … }`
915
+ * (valueKeys=['false','reason'], booleanValues=null). env3 run11 실측 shape로,
916
+ * 리터럴 `false` 키는 실기기 WebView가 실제로 관측한 형태다 — capture는 WebView
917
+ * 안에서 `Object.keys(value)`로 계산돼 console 문자열로 나오므로(devtools#696
918
+ * capture.ts) 우리 CDP relay가 개입하기 전이다. 즉 relay 역직렬화 artifact가 아니라
919
+ * 모든 WebView 소비자가 보는 shape다(sdk-example#303 진단 결론). 성공 분기 기본값
920
+ * ({ success: true })은 그대로 두고, 미프로비저닝 실패 재현만 다이얼에 붙인다.
921
+ */
922
+ checkoutPayment?: boolean;
923
+ requestTossPayPaysBilling?: boolean;
924
+ };
925
+ }
926
+ declare class AitStateManager {
927
+ private _state;
928
+ private _listeners;
929
+ private _inTransaction;
930
+ constructor();
931
+ get state(): AitDevtoolsState;
932
+ update(partial: Partial<AitDevtoolsState>): void;
933
+ /** 중첩 객체 업데이트용 */
934
+ patch<K extends keyof AitDevtoolsState>(key: K, partial: Partial<AitDevtoolsState[K]>): void;
935
+ subscribe(listener: Listener): () => void;
936
+ /**
937
+ * 한 묶음의 update/patch 호출을 묶어 listener notify 1회로 만든다.
938
+ * preset 적용처럼 여러 슬라이스를 동시에 바꿀 때 panel re-render 폭주를
939
+ * 방지한다. 중첩 호출은 outermost transaction이 끝날 때 한 번만 notify
940
+ * (inner도 throw해도 outer finally가 flag를 복구한다).
941
+ *
942
+ * Rollback은 없다 — `fn`이 throw해도 그때까지의 state 변경은 유지된다.
943
+ * 구독자가 partial state를 영원히 못 보는 사고를 막기 위해, throw 여부와
944
+ * 무관하게 항상 한 번 notify한 뒤 throw를 propagate한다. DB transaction이
945
+ * 아니라 "여러 mutation을 한 notify로 묶는 batch"라고 생각하면 된다.
946
+ *
947
+ * Listener는 throw해선 안 된다 — finally 안의 `_notify()`가 throw하면 원래
948
+ * `fn`의 throw를 덮어버린다. 우리 구독자는 panel re-render뿐이라 실제
949
+ * 발생 사례는 없지만, 외부에서 listener를 등록할 때 주의.
950
+ */
951
+ transaction(fn: () => void): void;
952
+ /** 분석 로그 추가 */
953
+ logAnalytics(entry: Omit<AnalyticsLogEntry, "timestamp">): void;
954
+ /**
955
+ * SDK 호출 로그 추가 (ring buffer, 상한 SDK_CALL_LOG_MAX).
956
+ * `observe()`가 호출하고, proxy의 KNOWN_UNIMPLEMENTED 경로도 직접 호출한다.
957
+ */
958
+ logSdkCall(entry: AitSdkCall): void;
959
+ /** 이벤트 트리거 (backEvent, homeEvent 등) */
960
+ trigger(event: string): void;
961
+ reset(): void;
962
+ private _notify;
963
+ }
964
+ declare const aitState: AitStateManager;
965
+ //#endregion
966
+ //#region src/mock/presets.d.ts
967
+ /**
968
+ * Preset이 덮어쓸 수 있는 mock state slice. 모든 키는 optional —
969
+ * 한 preset이 모든 분야를 정의할 필요 없다.
970
+ *
971
+ * 일부러 좁게 잡았다: viewport / brand / mockData / analyticsLog 등 QA 시나리오와
972
+ * 직접 관련 없는 영역은 preset 대상에서 제외한다 (preset 적용으로 unrelated state가
973
+ * 흔들리는 사고 방지). 필요해지면 추가.
974
+ *
975
+ * `iap` slice는 일부러 `nextResult`만 노출한다 — products / pendingOrders /
976
+ * completedOrders는 array/object 비교가 까다롭고 QA 시나리오에서 강제할 일이 거의
977
+ * 없다. `captureCurrentState` / `matchesPreset` 의 iap 처리 범위와 동기화.
978
+ */
979
+ interface MockPresetState {
980
+ networkStatus?: AitDevtoolsState["networkStatus"];
981
+ permissions?: Partial<AitDevtoolsState["permissions"]>;
982
+ auth?: Partial<AitDevtoolsState["auth"]>;
983
+ iap?: {
984
+ nextResult?: AitDevtoolsState["iap"]["nextResult"];
985
+ };
986
+ ads?: Partial<AitDevtoolsState["ads"]>;
987
+ payment?: Partial<AitDevtoolsState["payment"]>;
988
+ }
989
+ interface MockPreset {
990
+ id: string;
991
+ label: string;
992
+ description?: string;
993
+ state: MockPresetState;
994
+ }
995
+ declare const builtInPresets: readonly MockPreset[];
996
+ /**
997
+ * Preset state를 현재 `aitState`에 적용한다. 정의된 키만 덮어쓰고, 알지 못하는 키는
998
+ * 조용히 drop한다 (한 번 warn). 여러 슬라이스를 적용해도 listener notify는 한 번이다
999
+ * (`aitState.transaction` 사용 — panel re-render 폭주 방지).
1000
+ */
1001
+ declare function applyPreset(state: MockPresetState): void;
1002
+ /**
1003
+ * Preset의 모든 정의된 슬라이스가 현재 state와 일치하는지 검사. UI에서 dirty
1004
+ * indicator를 그릴 때 쓴다.
1005
+ *
1006
+ * 일치한다 = preset이 정의한 키 전부가 그대로다. preset이 정의하지 않은 키는
1007
+ * 비교 대상이 아니다 — preset은 partial이므로 다른 토글이 바뀌어도 dirty가 아니다.
1008
+ */
1009
+ declare function matchesPreset(snapshot: AitDevtoolsState, preset: MockPresetState): boolean;
1010
+ /**
1011
+ * 현재 state에서 preset에 저장할 만한 슬라이스를 추출. "save current as preset"에서 쓴다.
1012
+ */
1013
+ declare function captureCurrentState(snapshot: AitDevtoolsState): MockPresetState;
1014
+ //#endregion
1015
+ //#region src/mock/preset-store.d.ts
1016
+ declare function listUserPresets(): MockPreset[];
1017
+ /**
1018
+ * Preset을 저장한다. label에서 slug를 derive — 같은 slug가 이미 있으면 `-2`, `-3`
1019
+ * suffix를 붙여 새 entry를 만든다 (기존 entry 덮어쓰기 아님). UI는 label만 받으면 된다.
1020
+ *
1021
+ * Throws:
1022
+ * - label trim한 뒤 빈 문자열일 때
1023
+ * - localStorage 미가용 환경일 때 (SSR 등)
1024
+ * - `setItem` 실패 (`QuotaExceededError` 등) — caller가 처리해야 함
1025
+ */
1026
+ declare function saveUserPreset(label: string, state: MockPresetState, description?: string): MockPreset;
1027
+ declare function deleteUserPreset(id: string): void;
1028
+ //#endregion
1029
+ //#region src/mock/safe-area-bridge.d.ts
1030
+ /** The postMessage envelope the launcher posts to the framed dev app (inset forward). */
1031
+ declare const SAFE_AREA_INSETS_MESSAGE_TYPE: "ait:safe-area-insets";
1032
+ /**
1033
+ * The postMessage command the launcher partner bar's `←` button sends to the
1034
+ * framed dev app (#510). The framed page calls `history.back()` in response.
1035
+ *
1036
+ * Protocol: only `{ type: 'ait:navigate-back' }` is valid. No other fields are
1037
+ * read or acted on — extra fields are silently ignored by the shape guard.
1038
+ * Game variant never sends this message (back button is partner-bar-only).
1039
+ */
1040
+ declare const NAVIGATE_BACK_MESSAGE_TYPE: "ait:navigate-back";
1041
+ /**
1042
+ * The postMessage envelope the framed mini-app self-reports its webViewType
1043
+ * with (#580). The mini-app knows its own type from the build constant
1044
+ * `__WEB_VIEW_TYPE__` (`granite.config.ts`'s `webViewProps.type`, injected by
1045
+ * the devtools unplugin). The launcher is cross-origin so it cannot read that
1046
+ * constant directly — the mini-app posts it to `window.parent` once so the
1047
+ * launcher (env-2 PWA shell) switches to game mode automatically, with no
1048
+ * manual `?navBarType=game` URL edit.
1049
+ *
1050
+ * Direction: this is the SEND side's contract (posted from inside the iframe by
1051
+ * `@ait-co/debug-console`'s `packages/debug-console/src/attach.ts`). The
1052
+ * launcher's receive half lives in
1053
+ * `e2e/fixture/launcher/Launcher.tsx` and mirrors the same value enum inline,
1054
+ * staying decoupled from the mock package internals — the same pattern the
1055
+ * other launcher message types follow.
1056
+ *
1057
+ * Value enum: only `'partner'` and `'game'` are valid. The SDK's deprecated
1058
+ * `'external'` alias of `partner` (web-framework 2.6.1) is mapped to `'partner'`
1059
+ * at the send site so the wire only ever carries the two shapes the launcher
1060
+ * emulates.
1061
+ */
1062
+ declare const WEB_VIEW_TYPE_MESSAGE_TYPE: "ait:web-view-type";
1063
+ /** The two webViewType shapes the launcher can emulate (#580). */
1064
+ type WebViewTypeValue = "partner" | "game";
1065
+ /**
1066
+ * Parse + validate a raw postMessage payload into a `SafeAreaInsets`, or return
1067
+ * null when it is not a well-formed `ait:safe-area-insets` message. Pure — unit
1068
+ * tested without a real MessageEvent.
1069
+ */
1070
+ declare function parseSafeAreaInsetsMessage(data: unknown): SafeAreaInsets$1 | null;
1071
+ /**
1072
+ * Parse + validate a raw postMessage payload into a webViewType value
1073
+ * (`'partner'` | `'game'`), or return `null` when it is not a well-formed
1074
+ * `ait:web-view-type` message (#580). Pure — unit tested without a real
1075
+ * MessageEvent.
1076
+ *
1077
+ * Strict shape guard (the safety boundary for the cross-origin receive path):
1078
+ * the payload must be a non-null object whose `type` is exactly
1079
+ * {@link WEB_VIEW_TYPE_MESSAGE_TYPE} and whose `value` is exactly `'partner'`
1080
+ * or `'game'` (an enum allow-list). Anything else — a foreign type, a missing
1081
+ * or non-string value, the deprecated `'external'` alias, or any other string —
1082
+ * returns `null` so a stray postMessage can never flip the launcher's visual
1083
+ * mode. The send site is responsible for collapsing `'external'` → `'partner'`
1084
+ * before posting; the parser does NOT silently accept it.
1085
+ */
1086
+ declare function parseWebViewTypeMessage(data: unknown): WebViewTypeValue | null;
1087
+ /**
1088
+ * Apply forwarded insets to the mock state. Skips the write (and the resulting
1089
+ * subscribe notify) when nothing changed, so repeated identical messages from a
1090
+ * resize storm don't churn subscribers.
1091
+ */
1092
+ declare function applyForwardedSafeAreaInsets(insets: SafeAreaInsets$1): void;
1093
+ /**
1094
+ * Install the window `message` listener that receives forwarded insets. Safe to
1095
+ * call multiple times (idempotent) and a no-op outside a browser (SSR/jsdom
1096
+ * without a window). Imported for its side effect by the mock barrel so any
1097
+ * consumer that aliases `@apps-in-toss/web-framework` to the mock gets it wired.
1098
+ *
1099
+ * On each valid `ait:safe-area-insets` message:
1100
+ * 1. Writes the corrected insets into the mock `SafeAreaInsets` state
1101
+ * (existing #484 behaviour — for apps that still read SDK insets).
1102
+ * 2. Drives the env-2 dead-band compensation style via
1103
+ * {@link applyEnv2Compensation} — injects a `body { margin-top: calc(-1 *
1104
+ * env(safe-area-inset-top)) }` style when `top === 0` (partner mode) and
1105
+ * removes it when `top > 0` (game / full-bleed mode).
1106
+ */
1107
+ declare function installSafeAreaInsetsBridge(): void;
1108
+ /**
1109
+ * Parse a raw postMessage payload as an `ait:navigate-back` command.
1110
+ *
1111
+ * Returns true when the payload is a well-formed navigate-back command
1112
+ * (`{ type: 'ait:navigate-back' }`), false otherwise. Pure — unit tested
1113
+ * without a real MessageEvent.
1114
+ *
1115
+ * Shape guard: only the `type` field is inspected; any extra fields are
1116
+ * ignored so future extensions do not break older receivers. The function
1117
+ * does NOT read any data field beyond `type` — no sensitive values, no host
1118
+ * disclosure (same principle as the insets bridge).
1119
+ */
1120
+ declare function isNavigateBackMessage(data: unknown): boolean;
1121
+ /**
1122
+ * Install the window `message` listener that handles `ait:navigate-back`
1123
+ * commands (#510). When the launcher partner bar's `←` button is clicked it
1124
+ * posts `{ type: 'ait:navigate-back' }` to the framed dev app; this listener
1125
+ * calls `dispatchHostBackNavigation()` from the navigation module.
1126
+ *
1127
+ * Dispatch semantics: if there are any `graniteEvent.addEventListener('backEvent', …)`
1128
+ * subscribers the CustomEvent `__ait:backEvent` is fired (same path as the env-1
1129
+ * panel back button — the mini-app intercept channel). When there are no
1130
+ * subscribers `history.back()` is called as the fallback. Back semantics are
1131
+ * owned entirely by the navigation module; this bridge only delegates.
1132
+ *
1133
+ * Safe to call multiple times (idempotent) and a no-op outside a browser.
1134
+ * Installed together with the inset bridge by `installBridges()` so any consumer
1135
+ * of the mock barrel gets both wired automatically.
1136
+ *
1137
+ * No-op on apps that predate this bridge — the launcher posts the message but
1138
+ * older mocks simply have no listener (harmless).
1139
+ */
1140
+ declare function installNavigateBackBridge(): void;
1141
+ /**
1142
+ * Install both env-2 postMessage bridges in one call (#484 insets + #510
1143
+ * navigate-back). The mock barrel calls this at import time so consumers get
1144
+ * all bridges wired without any explicit setup.
1145
+ */
1146
+ declare function installBridges(): void;
1147
+ //#endregion
1148
+ export { Accuracy, type AitDevtoolsState, Analytics, type AnalyticsLogEntry, Clipboard, type ConsentedUserData, type ConsentedUserDataKey, type DeclaredAgeRange, Device, type DeviceApiMode, type DeviceModes, Environment, FetchAlbumPhotosPermissionError, FetchContactsPermissionError, File, Game, GetClipboardTextPermissionError, GetCurrentLocationPermissionError, GoogleAdMob, type HapticFeedbackType, IAP, type IapNextResult, type LocationCoords, type MockContact, type MockData, type MockIapProduct, type MockLocation, type MockPreset, type MockPresetState, NAVIGATE_BACK_MESSAGE_TYPE, type NetworkStatus, Notification, OpenCameraPermissionError, type OperationalEnvironment, PermissionError, type PermissionName, type PermissionStatus, type PlatformOS, type Primitive, Promotion, Review, SAFE_AREA_INSETS_MESSAGE_TYPE, SafeArea, SafeAreaInsets, type SafeAreaInsets$1 as SafeAreaInsetsType, Screen, SetClipboardTextPermissionError, Share, StartUpdateLocationPermissionError, Storage, TossAds, TossAuth, TossPay, User, WEB_VIEW_TYPE_MESSAGE_TYPE, type WebViewTypeValue, aitState, appLogin, applyForwardedSafeAreaInsets, applyPreset, appsInTossEvent, appsInTossSignTossCert, builtInPresets, captureCurrentState, checkoutPayment, closeView, contactsViral, createAsyncBridge, createConstantBridge, createEventBridge, deleteUserPreset, env, eventLog, fetchAlbumItems, fetchAlbumPhotos, fetchContacts, generateHapticFeedback, getAnonymousKey, getAppsInTossGlobals, getClipboardText, getConsentedUserData, getCurrentLocation, getDeclaredAgeRange, getDefaultPlaceholderImages, getDeviceId, getGameCenterGameProfile, getGroupId, getIsTossLoginIntegratedService, getLocale, getNetworkStatus, getOperationalEnvironment, getPermission, getPlatformOS, getSafeAreaInsets, getSchemeUri, getServerTime, getTossAppVersion, getTossShareLink, getUserKeyForGame, graniteEvent, grantPromotionReward, grantPromotionRewardForGame, installBridges, installNavigateBackBridge, installSafeAreaInsetsBridge, isMinVersionSupported, isNavigateBackMessage, listUserPresets, loadFullScreenAd, matchesPreset, onVisibilityChangedByTransparentServiceWeb, openCamera, openGameCenterLeaderboard, openPDFViewer, openPermissionDialog, openURL, parseSafeAreaInsetsMessage, parseWebViewTypeMessage, partner, requestNotificationAgreement, requestPermission, requestReview, requestTossPayPaysBilling, saveBase64Data, saveUserPreset, setClipboardText, setDeviceOrientation, setIosSwipeGestureEnabled, setScreenAwakeMode, setSecureScreen, share, showFullScreenAd, startUpdateLocation, submitGameCenterLeaderBoardScore, tdsEvent };