@itd-api/captcha 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +231 -0
- package/dist/index.cjs +687 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +380 -0
- package/dist/index.d.ts +380 -0
- package/dist/index.js +675 -0
- package/dist/index.js.map +1 -0
- package/package.json +85 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
//#region src/driver.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Минимальные структурные типы драйвера браузера.
|
|
4
|
+
*
|
|
5
|
+
* Ни один драйвер не импортируется даже как тип: пакет собирается и проверяется без них,
|
|
6
|
+
* а подойдёт любой совместимый по API — `patchright`, `playwright`, `playwright-core`,
|
|
7
|
+
* Camoufox. Форма взята у Playwright, потому что её повторяют остальные. Описаны только
|
|
8
|
+
* те методы, которыми пользуется солвер.
|
|
9
|
+
*/
|
|
10
|
+
/** Перехваченный запрос. Нужен, чтобы отдать свою страницу вместо настоящей. */
|
|
11
|
+
interface Route {
|
|
12
|
+
fulfill(options: {
|
|
13
|
+
status?: number;
|
|
14
|
+
contentType?: string;
|
|
15
|
+
body?: string;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/** Прямоугольник элемента в координатах страницы. */
|
|
19
|
+
interface BoundingBox {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
}
|
|
25
|
+
interface ElementHandle {
|
|
26
|
+
boundingBox(): Promise<BoundingBox | null>;
|
|
27
|
+
}
|
|
28
|
+
/** Мышь уровня страницы: события идут через CDP, а не через DOM. */
|
|
29
|
+
interface Mouse {
|
|
30
|
+
move(x: number, y: number, options?: {
|
|
31
|
+
steps?: number;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
click(x: number, y: number, options?: {
|
|
34
|
+
delay?: number;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
interface Page {
|
|
38
|
+
route(url: string, handler: (route: Route) => void | Promise<void>): Promise<void>;
|
|
39
|
+
goto(url: string, options?: {
|
|
40
|
+
waitUntil?: 'domcontentloaded' | 'load';
|
|
41
|
+
}): Promise<unknown>;
|
|
42
|
+
evaluate<R>(fn: () => R): Promise<R>;
|
|
43
|
+
waitForSelector(selector: string, options?: {
|
|
44
|
+
timeout?: number;
|
|
45
|
+
state?: 'attached' | 'visible';
|
|
46
|
+
}): Promise<unknown>;
|
|
47
|
+
$(selector: string): Promise<ElementHandle | null>;
|
|
48
|
+
readonly mouse: Mouse;
|
|
49
|
+
close(): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
interface BrowserContext {
|
|
52
|
+
newPage(): Promise<Page>;
|
|
53
|
+
close(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Настройки контекста. Совпадают по форме с `browser.newContext` в Playwright.
|
|
57
|
+
*
|
|
58
|
+
* Кроме перечисленных полей принимается что угодно ещё: драйверы вроде Camoufox понимают
|
|
59
|
+
* свои настройки, и перечислять их здесь пакет не берётся.
|
|
60
|
+
*/
|
|
61
|
+
interface NewContextOptions {
|
|
62
|
+
locale?: string;
|
|
63
|
+
viewport?: {
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
} | null;
|
|
67
|
+
userAgent?: string;
|
|
68
|
+
[option: string]: unknown;
|
|
69
|
+
}
|
|
70
|
+
interface Browser {
|
|
71
|
+
newContext(options?: NewContextOptions): Promise<BrowserContext>;
|
|
72
|
+
/** Версия браузера, например `149.0.7827.55`. Есть не у всякого драйвера. */
|
|
73
|
+
version?(): string;
|
|
74
|
+
close(): Promise<void>;
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/types.d.ts
|
|
78
|
+
/**
|
|
79
|
+
* Открытый строковый enum.
|
|
80
|
+
*
|
|
81
|
+
* Даёт автодополнение известных значений, но не ломается, если появится новое.
|
|
82
|
+
*/
|
|
83
|
+
type Loose<T extends string> = T | (string & {});
|
|
84
|
+
/** Провайдер капчи — теми же именами, какими его называет сервер итд.com. */
|
|
85
|
+
declare const CaptchaType: Readonly<{
|
|
86
|
+
/** Собственная капча ИТД: карточка «Я не робот» в iframe с `captcha.итд.com`. */
|
|
87
|
+
readonly Itd: "itd";
|
|
88
|
+
/** Cloudflare Turnstile. */
|
|
89
|
+
readonly Cloudflare: "cloudflare";
|
|
90
|
+
}>;
|
|
91
|
+
type CaptchaType = Loose<(typeof CaptchaType)[keyof typeof CaptchaType]>;
|
|
92
|
+
/** Оформление виджета. */
|
|
93
|
+
type Theme = 'auto' | 'light' | 'dark';
|
|
94
|
+
/** Результат виджета, снятый со страницы через `page.evaluate`. */
|
|
95
|
+
interface WidgetState {
|
|
96
|
+
token: string | null;
|
|
97
|
+
error: string | null;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/errors.d.ts
|
|
101
|
+
/** Почему не удалось получить токен. */
|
|
102
|
+
declare const CaptchaFailure: Readonly<{
|
|
103
|
+
/** Драйвер браузера не установлен. */
|
|
104
|
+
readonly DriverMissing: "driver-missing";
|
|
105
|
+
/** Браузер не запустился: нет исполняемого файла, нет дисплея, отказ песочницы. */
|
|
106
|
+
readonly LaunchFailed: "launch-failed";
|
|
107
|
+
/** Браузер или страница закрылись, пока решался виджет. */
|
|
108
|
+
readonly BrowserClosed: "browser-closed";
|
|
109
|
+
/** Виджет не отдал токен за отведённое время. */
|
|
110
|
+
readonly Timeout: "timeout";
|
|
111
|
+
/** Сам виджет сообщил об ошибке — код лежит в `widgetCode`. */
|
|
112
|
+
readonly WidgetError: "widget-error";
|
|
113
|
+
}>;
|
|
114
|
+
type CaptchaFailure = (typeof CaptchaFailure)[keyof typeof CaptchaFailure];
|
|
115
|
+
/**
|
|
116
|
+
* Ошибка получения токена капчи.
|
|
117
|
+
*
|
|
118
|
+
* Причина в {@link CaptchaError.reason} определяет, что с ошибкой делать: отсутствие драйвера
|
|
119
|
+
* чинится установкой, таймаут — повтором, а ошибка виджета повтором не лечится. Поле
|
|
120
|
+
* {@link CaptchaError.type} говорит, чей именно виджет решался, — оно есть не у всех ошибок
|
|
121
|
+
* (запуск браузера происходит до выбора виджета).
|
|
122
|
+
*/
|
|
123
|
+
declare class CaptchaError extends Error {
|
|
124
|
+
readonly reason: CaptchaFailure;
|
|
125
|
+
/** Какой провайдер решался в момент ошибки. */
|
|
126
|
+
readonly type: CaptchaType | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Код ошибки виджета, если он его сообщил.
|
|
129
|
+
*
|
|
130
|
+
* Для Cloudflare самые частые: `110200` — домен не разрешён для этого ключа, `300***`
|
|
131
|
+
* и `600***` — внутренние сбои виджета, лечатся повтором.
|
|
132
|
+
*/
|
|
133
|
+
readonly widgetCode: string | undefined;
|
|
134
|
+
constructor(reason: CaptchaFailure, message: string, options?: {
|
|
135
|
+
type?: CaptchaType;
|
|
136
|
+
widgetCode?: string;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/handler.d.ts
|
|
141
|
+
/**
|
|
142
|
+
* Контракт одного провайдера капчи: всё, чем один виджет отличается от другого.
|
|
143
|
+
*
|
|
144
|
+
* Перехват навигации, ожидание, клик и повторы одинаковы для всех виджетов и в реализацию
|
|
145
|
+
* не входят. Свой провайдер достаточно описать этим интерфейсом и передать в `solveCaptcha`.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const myCaptcha: CaptchaHandler = {
|
|
150
|
+
* type: 'my-captcha',
|
|
151
|
+
* label: 'моей капчи',
|
|
152
|
+
* buildPage: ({ theme }) => `<!doctype html>…`,
|
|
153
|
+
* widgetReadySelector: '#widget',
|
|
154
|
+
* checkboxOffsetX: 30,
|
|
155
|
+
* readState: (page) => page.evaluate(() => ({ token: null, error: null })),
|
|
156
|
+
* isPermanentWidgetError: () => false,
|
|
157
|
+
* };
|
|
158
|
+
*
|
|
159
|
+
* const token = await solveCaptcha(myCaptcha);
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
interface CaptchaHandler {
|
|
163
|
+
/** Имя провайдера. */
|
|
164
|
+
readonly type: CaptchaType;
|
|
165
|
+
/** Как назвать виджет в сообщении об ошибке. */
|
|
166
|
+
readonly label: string;
|
|
167
|
+
/** Собирает страницу с одним виджетом. Ключ и адрес виджета обработчик хранит сам. */
|
|
168
|
+
buildPage(input: {
|
|
169
|
+
theme: Theme;
|
|
170
|
+
}): string;
|
|
171
|
+
/** Селектор, по которому видно, что виджет отрисовался. */
|
|
172
|
+
readonly widgetReadySelector: string;
|
|
173
|
+
/** Насколько правее левого края контейнера находится чекбокс, px. */
|
|
174
|
+
readonly checkboxOffsetX: number;
|
|
175
|
+
/** Читает результат виджета со страницы. */
|
|
176
|
+
readState(page: Page): Promise<WidgetState>;
|
|
177
|
+
/** Постоянна ли ошибка виджета с таким кодом: повтор её не исправит. */
|
|
178
|
+
isPermanentWidgetError(code: string): boolean;
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/launch.d.ts
|
|
182
|
+
/** Настройки запуска браузера. */
|
|
183
|
+
interface BrowserOptions {
|
|
184
|
+
/**
|
|
185
|
+
* Запускать ли браузер без окна. По умолчанию `false`.
|
|
186
|
+
*
|
|
187
|
+
* В безоконном режиме виджет проходится заметно хуже: признаки такого режима видны
|
|
188
|
+
* странице. На сервере поднимите виртуальный дисплей (`xvfb-run -a node bot.js`).
|
|
189
|
+
*/
|
|
190
|
+
headless?: boolean | undefined;
|
|
191
|
+
/**
|
|
192
|
+
* Какой драйвер брать вместо перебора `patchright` → `playwright` → `playwright-core`.
|
|
193
|
+
*
|
|
194
|
+
* Нужен, когда установлено несколько и важно, какой именно поднимется. Названный
|
|
195
|
+
* драйвер берётся один: не найден — ошибка, а не молчаливая подмена соседним.
|
|
196
|
+
*/
|
|
197
|
+
driver?: string | undefined;
|
|
198
|
+
/** Путь к исполняемому файлу браузера, если он лежит не там, где его ищет драйвер. */
|
|
199
|
+
executablePath?: string | undefined;
|
|
200
|
+
/** Канал браузера, например `chrome` или `msedge`, — вместо сборки из комплекта драйвера. */
|
|
201
|
+
channel?: string | undefined;
|
|
202
|
+
/** Дополнительные аргументы командной строки — добавляются к стандартным. */
|
|
203
|
+
args?: readonly string[] | undefined;
|
|
204
|
+
/**
|
|
205
|
+
* Отключить sandbox Chromium. По умолчанию `false`.
|
|
206
|
+
*
|
|
207
|
+
* Используйте только внутри изолированного контейнера, где sandbox невозможно настроить:
|
|
208
|
+
* страница исполняет удалённый код виджета, и без изоляции браузера его компрометация
|
|
209
|
+
* получает больше доступа к процессу и системе.
|
|
210
|
+
*/
|
|
211
|
+
disableSandbox?: boolean | undefined;
|
|
212
|
+
/** Прокси для браузера. */
|
|
213
|
+
proxy?: {
|
|
214
|
+
server: string;
|
|
215
|
+
username?: string;
|
|
216
|
+
password?: string;
|
|
217
|
+
} | undefined;
|
|
218
|
+
/**
|
|
219
|
+
* Свой запуск браузера. Заменяет все остальные параметры запуска.
|
|
220
|
+
*
|
|
221
|
+
* Нужен, чтобы подставить другой драйвер или подключиться к уже работающему браузеру.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```ts
|
|
225
|
+
* launch: async () => {
|
|
226
|
+
* const { chromium } = await import('patchright');
|
|
227
|
+
* return chromium.launch({ headless: false });
|
|
228
|
+
* };
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
launch?: (() => Promise<Browser>) | undefined;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Поднимает браузер по настройкам.
|
|
235
|
+
*
|
|
236
|
+
* Тем же путём, что и солверы: те же флаги, тот же порядок драйверов. Пригодится, чтобы
|
|
237
|
+
* поднять браузер один раз на несколько токенов и передать его в `browser`, — и чтобы
|
|
238
|
+
* проверять связки драйвера и сборки ровно в том виде, в каком их поднимает пакет.
|
|
239
|
+
*/
|
|
240
|
+
declare function launchBrowser(options: BrowserOptions): Promise<Browser>;
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region src/options.d.ts
|
|
243
|
+
/** Базовый URL сайта итд.com. Домен записан в punycode: `итд.com`. */
|
|
244
|
+
declare const DEFAULT_ORIGIN = "https://xn--d1ah4a.com";
|
|
245
|
+
/**
|
|
246
|
+
* Настройки получения токена, общие для любого виджета.
|
|
247
|
+
*
|
|
248
|
+
* Ключ, назначение токена и адрес виджета задаются при создании провайдера:
|
|
249
|
+
* `solveCaptcha(itdCaptcha({ action: 'register' }))`.
|
|
250
|
+
*/
|
|
251
|
+
interface SolveOptions extends BrowserOptions {
|
|
252
|
+
/** Сайт, чей виджет решается. По умолчанию {@link DEFAULT_ORIGIN}. */
|
|
253
|
+
origin?: string | undefined;
|
|
254
|
+
/** Оформление виджета. По умолчанию `auto`. */
|
|
255
|
+
theme?: Theme | undefined;
|
|
256
|
+
/** Сколько ждать токен, мс. По умолчанию 60000. */
|
|
257
|
+
timeout?: number | undefined;
|
|
258
|
+
/** Сколько попыток делать при неудаче. По умолчанию 2. */
|
|
259
|
+
attempts?: number | undefined;
|
|
260
|
+
/**
|
|
261
|
+
* Готовый браузер. Тогда пакет его не запускает и не закрывает.
|
|
262
|
+
*
|
|
263
|
+
* Пригодится, если браузер уже поднят для чего-то ещё.
|
|
264
|
+
*/
|
|
265
|
+
browser?: Browser | undefined;
|
|
266
|
+
/**
|
|
267
|
+
* Настройки контекста. Заменяют стандартные целиком, а не дополняют их.
|
|
268
|
+
*
|
|
269
|
+
* По умолчанию `{ locale: 'ru-RU', viewport: { width: 1280, height: 800 } }`. Драйверам,
|
|
270
|
+
* которые собирают отпечаток браузера сами, навязанный `locale` мешает — им передайте `{}`.
|
|
271
|
+
*/
|
|
272
|
+
contextOptions?: NewContextOptions | undefined;
|
|
273
|
+
/** Куда писать ход решения. Например `console.debug`. */
|
|
274
|
+
logger?: ((message: string) => void) | undefined;
|
|
275
|
+
}
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/providers/itd.d.ts
|
|
278
|
+
/** Базовый адрес виджета собственной капчи ИТД. Домен в punycode: `captcha.итд.com`. */
|
|
279
|
+
declare const DEFAULT_CAPTCHA_ORIGIN = "https://captcha.xn--d1ah4a.com";
|
|
280
|
+
/**
|
|
281
|
+
* Публичный ключ виджета собственной капчи ИТД.
|
|
282
|
+
*
|
|
283
|
+
* Как и ключ Turnstile, он публичный и привязан к домену итд.com: виджет отдаёт его браузеру
|
|
284
|
+
* каждому посетителю.
|
|
285
|
+
*/
|
|
286
|
+
declare const ITD_CAPTCHA_SITE_KEY = "sk_44d64cf7bf8bc8377f5b";
|
|
287
|
+
/** Настройки виджета собственной капчи ИТД. */
|
|
288
|
+
interface ItdCaptchaOptions {
|
|
289
|
+
/** Публичный ключ виджета. По умолчанию {@link ITD_CAPTCHA_SITE_KEY} — ключ итд.com. */
|
|
290
|
+
sitekey?: string | undefined;
|
|
291
|
+
/**
|
|
292
|
+
* Назначение токена: `login`, `register`, `password_reset`. По умолчанию `login`.
|
|
293
|
+
*
|
|
294
|
+
* Сервер сверяет назначение с операцией, поэтому для регистрации или сброса пароля нужен
|
|
295
|
+
* токен с соответствующим `action`.
|
|
296
|
+
*/
|
|
297
|
+
action?: string | undefined;
|
|
298
|
+
/** Базовый адрес виджета. По умолчанию {@link DEFAULT_CAPTCHA_ORIGIN}. */
|
|
299
|
+
captchaOrigin?: string | undefined;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Создаёт обработчик собственной капчи ИТД.
|
|
303
|
+
*
|
|
304
|
+
* @throws {TypeError} при некорректных настройках
|
|
305
|
+
*/
|
|
306
|
+
declare function itdCaptcha(options?: ItdCaptchaOptions): CaptchaHandler;
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/providers/registry.d.ts
|
|
309
|
+
/** Что решать: имя известного провайдера либо свой обработчик. */
|
|
310
|
+
type CaptchaTarget = CaptchaType | CaptchaHandler;
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region src/providers/turnstile.d.ts
|
|
313
|
+
/**
|
|
314
|
+
* Публичный ключ виджета Cloudflare Turnstile на итд.com.
|
|
315
|
+
*
|
|
316
|
+
* Ключ публичный — виджет отдаёт его браузеру каждому посетителю — и привязан к домену
|
|
317
|
+
* итд.com, поэтому больше ни для чего не годится. Держим его прямо в пакете: это его данные,
|
|
318
|
+
* а не пользовательская настройка. Тот же ключ экспортирует `itd-api`.
|
|
319
|
+
*/
|
|
320
|
+
declare const TURNSTILE_SITE_KEY = "0x4AAAAAACHhxczw6fJGwPBg";
|
|
321
|
+
/** Настройки виджета Cloudflare Turnstile. */
|
|
322
|
+
interface TurnstileOptions {
|
|
323
|
+
/** Публичный ключ виджета. По умолчанию {@link TURNSTILE_SITE_KEY} — ключ итд.com. */
|
|
324
|
+
sitekey?: string | undefined;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Создаёт обработчик Cloudflare Turnstile.
|
|
328
|
+
*
|
|
329
|
+
* @throws {TypeError} при некорректных настройках
|
|
330
|
+
*/
|
|
331
|
+
declare function turnstile(options?: TurnstileOptions): CaptchaHandler;
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/solve.d.ts
|
|
334
|
+
/**
|
|
335
|
+
* Получает один токен капчи указанного типа.
|
|
336
|
+
*
|
|
337
|
+
* Поднимает браузер, решает виджет и закрывает браузер за собой.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```ts
|
|
341
|
+
* await solveCaptcha(CaptchaType.Itd);
|
|
342
|
+
* await solveCaptcha(itdCaptcha({ action: 'register' }), { headless: true });
|
|
343
|
+
* await solveCaptcha(myOwnHandler);
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @throws {CaptchaError} если токен получить не удалось
|
|
347
|
+
* @throws {TypeError} при некорректных настройках или незнакомом типе
|
|
348
|
+
*/
|
|
349
|
+
declare function solveCaptcha(target: CaptchaTarget, options?: SolveOptions): Promise<string>;
|
|
350
|
+
/** Источник токена капчи для `auth.captcha` клиента `itd-api`. */
|
|
351
|
+
interface CaptchaSolver {
|
|
352
|
+
/** Решает капчу названного типа и отдаёт токен. */
|
|
353
|
+
getToken(type: CaptchaType): Promise<string>;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Собирает источник токена для клиента `itd-api`.
|
|
357
|
+
*
|
|
358
|
+
* Токен одноразовый и живёт несколько минут, поэтому клиент спрашивает его заново перед
|
|
359
|
+
* каждым входом. Браузер поднимается на время одного вызова и сразу закрывается.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* import { ItdClient } from 'itd-api';
|
|
364
|
+
* import { FileTokenStorage } from 'itd-api/node';
|
|
365
|
+
* import { createCaptchaSolver } from '@itd-api/captcha';
|
|
366
|
+
*
|
|
367
|
+
* const itd = new ItdClient({
|
|
368
|
+
* storage: new FileTokenStorage('./.itd-session.json'),
|
|
369
|
+
* auth: {
|
|
370
|
+
* email: process.env.ITD_EMAIL!,
|
|
371
|
+
* password: process.env.ITD_PASSWORD!,
|
|
372
|
+
* captcha: createCaptchaSolver(),
|
|
373
|
+
* },
|
|
374
|
+
* });
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
declare function createCaptchaSolver(options?: SolveOptions): CaptchaSolver;
|
|
378
|
+
//#endregion
|
|
379
|
+
export { type Browser, type BrowserContext, type BrowserOptions, CaptchaError, CaptchaFailure, type CaptchaHandler, type CaptchaSolver, type CaptchaTarget, CaptchaType, DEFAULT_CAPTCHA_ORIGIN, DEFAULT_ORIGIN, ITD_CAPTCHA_SITE_KEY, type ItdCaptchaOptions, type Loose, type NewContextOptions, type Page, type SolveOptions, TURNSTILE_SITE_KEY, type Theme, type TurnstileOptions, type WidgetState, createCaptchaSolver, itdCaptcha, launchBrowser, solveCaptcha, turnstile };
|
|
380
|
+
//# sourceMappingURL=index.d.ts.map
|