itd-api 0.1.0 → 0.3.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.
Files changed (80) hide show
  1. package/README.md +121 -495
  2. package/dist/index.cjs +9212 -412
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +5176 -1
  5. package/dist/index.d.ts +5176 -1
  6. package/dist/index.js +9118 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/multi-storage-BhcA2Izn.d.ts +198 -0
  9. package/dist/multi-storage-CyMe404l.js +805 -0
  10. package/dist/multi-storage-CyMe404l.js.map +1 -0
  11. package/dist/multi-storage-D1keK2Op.cjs +930 -0
  12. package/dist/multi-storage-D1keK2Op.cjs.map +1 -0
  13. package/dist/multi-storage-NDqzRQcD.d.cts +198 -0
  14. package/dist/node.cjs +225 -548
  15. package/dist/node.cjs.map +1 -1
  16. package/dist/node.d.cts +46 -59
  17. package/dist/node.d.ts +46 -59
  18. package/dist/node.js +223 -126
  19. package/dist/node.js.map +1 -1
  20. package/dist/runtime-CFEsf-jD.cjs +185 -0
  21. package/dist/runtime-CFEsf-jD.cjs.map +1 -0
  22. package/dist/runtime-DHxDn8gf.js +126 -0
  23. package/dist/runtime-DHxDn8gf.js.map +1 -0
  24. package/dist/storage-BjNRlkbE.d.cts +82 -0
  25. package/dist/storage-BjNRlkbE.d.ts +82 -0
  26. package/dist/storage-D9tfHx7Z.js +424 -0
  27. package/dist/storage-D9tfHx7Z.js.map +1 -0
  28. package/dist/storage-ycBqLBRB.cjs +615 -0
  29. package/dist/storage-ycBqLBRB.cjs.map +1 -0
  30. package/dist/web.cjs +87 -0
  31. package/dist/web.cjs.map +1 -0
  32. package/dist/web.d.cts +27 -0
  33. package/dist/web.d.ts +27 -0
  34. package/dist/web.js +86 -0
  35. package/dist/web.js.map +1 -0
  36. package/package.json +34 -14
  37. package/dist/chunk-6FB4HTKH.js +0 -7763
  38. package/dist/chunk-6FB4HTKH.js.map +0 -1
  39. package/dist/chunk-73CISRBG.cjs +0 -7873
  40. package/dist/chunk-73CISRBG.cjs.map +0 -1
  41. package/dist/index-BZF4K90s.d.cts +0 -4961
  42. package/dist/index-BZF4K90s.d.ts +0 -4961
  43. package/guides/README.md +0 -24
  44. package/guides/authentication/README.md +0 -176
  45. package/guides/authentication/examples/bot-with-session.mjs +0 -98
  46. package/guides/authentication/examples/turnstile-login.mjs +0 -56
  47. package/guides/integrations/README.md +0 -62
  48. package/guides/integrations/examples/proxy.mjs +0 -26
  49. package/guides/multi-accounts/README.md +0 -143
  50. package/guides/multi-accounts/examples/multi-accounts.mjs +0 -71
  51. package/guides/plugins/README.md +0 -253
  52. package/guides/plugins/examples/cache.mjs +0 -33
  53. package/guides/plugins/examples/crypto.mjs +0 -54
  54. package/guides/quickstart/README.md +0 -124
  55. package/guides/quickstart/examples/quick-start.mjs +0 -44
  56. package/guides/quickstart/examples/typescript.ts +0 -90
  57. package/guides/realtime/README.md +0 -109
  58. package/guides/realtime/examples/notifications.mjs +0 -62
  59. package/guides/reference/README.md +0 -67
  60. package/guides/reference/accounts.md +0 -101
  61. package/guides/reference/auth.md +0 -141
  62. package/guides/reference/builders.md +0 -135
  63. package/guides/reference/client.md +0 -184
  64. package/guides/reference/comments.md +0 -58
  65. package/guides/reference/discovery.md +0 -81
  66. package/guides/reference/enums.md +0 -103
  67. package/guides/reference/errors.md +0 -107
  68. package/guides/reference/files.md +0 -73
  69. package/guides/reference/models.md +0 -448
  70. package/guides/reference/notifications.md +0 -77
  71. package/guides/reference/pagination.md +0 -82
  72. package/guides/reference/platform.md +0 -47
  73. package/guides/reference/posts.md +0 -157
  74. package/guides/reference/realtime.md +0 -78
  75. package/guides/reference/reports.md +0 -28
  76. package/guides/reference/subscription.md +0 -41
  77. package/guides/reference/users.md +0 -146
  78. package/guides/reference/verification.md +0 -24
  79. package/guides/text-markup/README.md +0 -214
  80. package/guides/text-markup/examples/create-post.mjs +0 -64
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-CFEsf-jD.cjs","names":["ItdConfigError"],"sources":["../src/core/runtime.ts"],"sourcesContent":["import { ItdConfigError } from './errors.js';\n\n/**\n * Как библиотека обращается с cookie.\n *\n * - `browser` — cookie ведёт браузер, запросы уходят с `credentials: 'include'`;\n * - `server` — cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную;\n * - `auto` — определяется по среде исполнения (значение по умолчанию).\n */\nexport const RuntimeMode = Object.freeze({\n /** Определяется по среде исполнения. Значение по умолчанию. */\n Auto: 'auto',\n /** Cookie ведёт браузер, запросы уходят с `credentials: 'include'`. */\n Browser: 'browser',\n /** Cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную. */\n Server: 'server',\n} as const);\nexport type RuntimeMode = (typeof RuntimeMode)[keyof typeof RuntimeMode];\n\n/** Распознанная среда исполнения. */\nexport const DetectedRuntime = Object.freeze({\n Browser: 'browser',\n /** Есть `window`, но нет `document`; cookie ведёт нативный сетевой слой. */\n ReactNative: 'react-native',\n Server: 'server',\n} as const);\nexport type DetectedRuntime = (typeof DetectedRuntime)[keyof typeof DetectedRuntime];\n\n/**\n * Определяет среду исполнения.\n *\n * React Native выделен отдельно намеренно: там есть `window`, но нет `document`, а cookie\n * хранит нативный сетевой слой (`NSHTTPCookieStorage` / `OkHttp`). Свой jar в этой среде\n * привёл бы к отправке cookie дважды.\n */\nexport function detectRuntime(): DetectedRuntime {\n const nav = (globalThis as { navigator?: { product?: string } }).navigator;\n if (nav?.product === 'ReactNative') return DetectedRuntime.ReactNative;\n\n if (typeof document !== 'undefined') return DetectedRuntime.Browser;\n\n return DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли вести собственный cookie-jar.\n *\n * Только в серверных средах: в браузере `Set-Cookie` из JS не читается и не нужен,\n * в React Native cookie ведёт нативный слой.\n */\nexport function shouldUseCookieJar(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return false;\n if (mode === RuntimeMode.Server) return true;\n return detectRuntime() === DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли отправлять запросы с `credentials: 'include'`.\n *\n * Только в браузере: именно так refresh-cookie попадает в запрос `POST /api/v1/auth/refresh`.\n * Требует настроенного CORS на стороне итд.com — если его нет, укажите свой прокси в `baseUrl`.\n */\nexport function shouldSendCredentials(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return true;\n if (mode === RuntimeMode.Server) return false;\n return detectRuntime() === DetectedRuntime.Browser;\n}\n\n/**\n * Возвращает реализацию `fetch`.\n *\n * @param custom реализация из конфигурации клиента, если пользователь её передал\n * @throws {ItdConfigError} если `fetch` недоступен — например, на Node ниже 18\n */\nexport function resolveFetch(custom?: typeof fetch): typeof fetch {\n if (custom !== undefined) {\n if (typeof custom !== 'function') {\n throw new ItdConfigError('fetch должен быть функцией');\n }\n return custom;\n }\n\n if (typeof globalThis.fetch === 'function') {\n // Привязка к globalThis обязательна: в некоторых средах несвязанный fetch бросает\n // «Illegal invocation».\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new ItdConfigError(\n 'В этой среде нет глобального fetch. Обновитесь до Node 18+ либо передайте свою ' +\n 'реализацию через опцию fetch.',\n );\n}\n\n/**\n * Проверки бинарных типов, безопасные в любой среде.\n *\n * Обычный `instanceof` здесь недостаточен: конструктора может не быть вовсе, и тогда\n * проверка падает с `ReferenceError`, а не возвращает `false`. `Blob` есть в Node с 18.0,\n * но `File` стал глобальным только в Node 20 — при заявленной поддержке Node 18 голый\n * `instanceof File` ронял бы любую загрузку.\n */\nexport function isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/** @see {@link isBlob} */\nexport function isFile(value: unknown): value is File {\n return typeof File !== 'undefined' && value instanceof File;\n}\n\n/** Доступно ли потоковое чтение тела ответа — от этого зависит, сработает ли SSE. */\nexport function supportsStreamingBody(): boolean {\n return typeof ReadableStream !== 'undefined' && typeof TextDecoder !== 'undefined';\n}\n\n/**\n * Создаёт идентификатор устройства для заголовка `X-Device-Id` — UUID v4.\n *\n * `crypto.randomUUID` есть в Node 19+, браузерах и Deno, но отсутствует в Node 18 вне\n * защищённого контекста, поэтому предусмотрен запасной путь.\n */\nexport function createDeviceId(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n\n if (typeof webCrypto?.randomUUID === 'function') return webCrypto.randomUUID();\n\n // Форма UUID v4 собирается вручную: серверу важна стабильность значения, а не его энтропия.\n const bytes = new Uint8Array(16);\n if (typeof webCrypto?.getRandomValues === 'function') webCrypto.getRandomValues(bytes);\n else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20, 32),\n ].join('-');\n}\n\n/** Есть ли в среде `localStorage`. Проверка безопасна: доступ к нему может бросать. */\nexport function hasLocalStorage(): boolean {\n try {\n return typeof globalThis.localStorage !== 'undefined' && globalThis.localStorage !== null;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,cAAc,OAAO,OAAO;;CAEvC,MAAM;;CAEN,SAAS;;CAET,QAAQ;AACV,CAAU;;AAIV,MAAa,kBAAkB,OAAO,OAAO;CAC3C,SAAS;;CAET,aAAa;CACb,QAAQ;AACV,CAAU;;;;;;;;AAUV,SAAgB,gBAAiC;CAE/C,IADa,WAAoD,WACxD,YAAY,eAAe,OAAO,gBAAgB;CAE3D,IAAI,OAAO,aAAa,aAAa,OAAO,gBAAgB;CAE5D,OAAO,gBAAgB;AACzB;;;;;;;AAQA,SAAgB,mBAAmB,MAA4B;CAC7D,IAAI,SAAS,YAAY,SAAS,OAAO;CACzC,IAAI,SAAS,YAAY,QAAQ,OAAO;CACxC,OAAO,cAAc,MAAM,gBAAgB;AAC7C;;;;;;;AAQA,SAAgB,sBAAsB,MAA4B;CAChE,IAAI,SAAS,YAAY,SAAS,OAAO;CACzC,IAAI,SAAS,YAAY,QAAQ,OAAO;CACxC,OAAO,cAAc,MAAM,gBAAgB;AAC7C;;;;;;;AAQA,SAAgB,aAAa,QAAqC;CAChE,IAAI,WAAW,KAAA,GAAW;EACxB,IAAI,OAAO,WAAW,YACpB,MAAM,IAAIA,gBAAAA,eAAe,4BAA4B;EAEvD,OAAO;CACT;CAEA,IAAI,OAAO,WAAW,UAAU,YAG9B,OAAO,WAAW,MAAM,KAAK,UAAU;CAGzC,MAAM,IAAIA,gBAAAA,eACR,8GAEF;AACF;;;;;;;;;AAUA,SAAgB,OAAO,OAA+B;CACpD,OAAO,OAAO,SAAS,eAAe,iBAAiB;AACzD;;AAGA,SAAgB,OAAO,OAA+B;CACpD,OAAO,OAAO,SAAS,eAAe,iBAAiB;AACzD;;AAGA,SAAgB,wBAAiC;CAC/C,OAAO,OAAO,mBAAmB,eAAe,OAAO,gBAAgB;AACzE;;;;;;;AAQA,SAAgB,iBAAyB;CACvC,MAAM,YAAa,WAAmC;CAEtD,IAAI,OAAO,WAAW,eAAe,YAAY,OAAO,UAAU,WAAW;CAG7E,MAAM,wBAAQ,IAAI,WAAW,EAAE;CAC/B,IAAI,OAAO,WAAW,oBAAoB,YAAY,UAAU,gBAAgB,KAAK;MAChF,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;CAGrF,MAAM,KAAM,MAAM,KAAM,KAAQ;CAEhC,MAAM,KAAM,MAAM,KAAM,KAAQ;CAEhC,MAAM,MAAM,MAAM,KAAK,QAAQ,SAAS,KAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;CAEnF,OAAO;EACL,IAAI,MAAM,GAAG,CAAC;EACd,IAAI,MAAM,GAAG,EAAE;EACf,IAAI,MAAM,IAAI,EAAE;EAChB,IAAI,MAAM,IAAI,EAAE;EAChB,IAAI,MAAM,IAAI,EAAE;CAClB,CAAC,CAAC,KAAK,GAAG;AACZ;;AAGA,SAAgB,kBAA2B;CACzC,IAAI;EACF,OAAO,OAAO,WAAW,iBAAiB,eAAe,WAAW,iBAAiB;CACvF,QAAQ;EACN,OAAO;CACT;AACF"}
@@ -0,0 +1,126 @@
1
+ import { c as ItdConfigError } from "./storage-D9tfHx7Z.js";
2
+ //#region src/core/runtime.ts
3
+ /**
4
+ * Как библиотека обращается с cookie.
5
+ *
6
+ * - `browser` — cookie ведёт браузер, запросы уходят с `credentials: 'include'`;
7
+ * - `server` — cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную;
8
+ * - `auto` — определяется по среде исполнения (значение по умолчанию).
9
+ */
10
+ const RuntimeMode = Object.freeze({
11
+ /** Определяется по среде исполнения. Значение по умолчанию. */
12
+ Auto: "auto",
13
+ /** Cookie ведёт браузер, запросы уходят с `credentials: 'include'`. */
14
+ Browser: "browser",
15
+ /** Cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную. */
16
+ Server: "server"
17
+ });
18
+ /** Распознанная среда исполнения. */
19
+ const DetectedRuntime = Object.freeze({
20
+ Browser: "browser",
21
+ /** Есть `window`, но нет `document`; cookie ведёт нативный сетевой слой. */
22
+ ReactNative: "react-native",
23
+ Server: "server"
24
+ });
25
+ /**
26
+ * Определяет среду исполнения.
27
+ *
28
+ * React Native выделен отдельно намеренно: там есть `window`, но нет `document`, а cookie
29
+ * хранит нативный сетевой слой (`NSHTTPCookieStorage` / `OkHttp`). Свой jar в этой среде
30
+ * привёл бы к отправке cookie дважды.
31
+ */
32
+ function detectRuntime() {
33
+ if (globalThis.navigator?.product === "ReactNative") return DetectedRuntime.ReactNative;
34
+ if (typeof document !== "undefined") return DetectedRuntime.Browser;
35
+ return DetectedRuntime.Server;
36
+ }
37
+ /**
38
+ * Нужно ли вести собственный cookie-jar.
39
+ *
40
+ * Только в серверных средах: в браузере `Set-Cookie` из JS не читается и не нужен,
41
+ * в React Native cookie ведёт нативный слой.
42
+ */
43
+ function shouldUseCookieJar(mode) {
44
+ if (mode === RuntimeMode.Browser) return false;
45
+ if (mode === RuntimeMode.Server) return true;
46
+ return detectRuntime() === DetectedRuntime.Server;
47
+ }
48
+ /**
49
+ * Нужно ли отправлять запросы с `credentials: 'include'`.
50
+ *
51
+ * Только в браузере: именно так refresh-cookie попадает в запрос `POST /api/v1/auth/refresh`.
52
+ * Требует настроенного CORS на стороне итд.com — если его нет, укажите свой прокси в `baseUrl`.
53
+ */
54
+ function shouldSendCredentials(mode) {
55
+ if (mode === RuntimeMode.Browser) return true;
56
+ if (mode === RuntimeMode.Server) return false;
57
+ return detectRuntime() === DetectedRuntime.Browser;
58
+ }
59
+ /**
60
+ * Возвращает реализацию `fetch`.
61
+ *
62
+ * @param custom реализация из конфигурации клиента, если пользователь её передал
63
+ * @throws {ItdConfigError} если `fetch` недоступен — например, на Node ниже 18
64
+ */
65
+ function resolveFetch(custom) {
66
+ if (custom !== void 0) {
67
+ if (typeof custom !== "function") throw new ItdConfigError("fetch должен быть функцией");
68
+ return custom;
69
+ }
70
+ if (typeof globalThis.fetch === "function") return globalThis.fetch.bind(globalThis);
71
+ throw new ItdConfigError("В этой среде нет глобального fetch. Обновитесь до Node 18+ либо передайте свою реализацию через опцию fetch.");
72
+ }
73
+ /**
74
+ * Проверки бинарных типов, безопасные в любой среде.
75
+ *
76
+ * Обычный `instanceof` здесь недостаточен: конструктора может не быть вовсе, и тогда
77
+ * проверка падает с `ReferenceError`, а не возвращает `false`. `Blob` есть в Node с 18.0,
78
+ * но `File` стал глобальным только в Node 20 — при заявленной поддержке Node 18 голый
79
+ * `instanceof File` ронял бы любую загрузку.
80
+ */
81
+ function isBlob(value) {
82
+ return typeof Blob !== "undefined" && value instanceof Blob;
83
+ }
84
+ /** @see {@link isBlob} */
85
+ function isFile(value) {
86
+ return typeof File !== "undefined" && value instanceof File;
87
+ }
88
+ /** Доступно ли потоковое чтение тела ответа — от этого зависит, сработает ли SSE. */
89
+ function supportsStreamingBody() {
90
+ return typeof ReadableStream !== "undefined" && typeof TextDecoder !== "undefined";
91
+ }
92
+ /**
93
+ * Создаёт идентификатор устройства для заголовка `X-Device-Id` — UUID v4.
94
+ *
95
+ * `crypto.randomUUID` есть в Node 19+, браузерах и Deno, но отсутствует в Node 18 вне
96
+ * защищённого контекста, поэтому предусмотрен запасной путь.
97
+ */
98
+ function createDeviceId() {
99
+ const webCrypto = globalThis.crypto;
100
+ if (typeof webCrypto?.randomUUID === "function") return webCrypto.randomUUID();
101
+ const bytes = /* @__PURE__ */ new Uint8Array(16);
102
+ if (typeof webCrypto?.getRandomValues === "function") webCrypto.getRandomValues(bytes);
103
+ else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
104
+ bytes[6] = bytes[6] & 15 | 64;
105
+ bytes[8] = bytes[8] & 63 | 128;
106
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
107
+ return [
108
+ hex.slice(0, 8),
109
+ hex.slice(8, 12),
110
+ hex.slice(12, 16),
111
+ hex.slice(16, 20),
112
+ hex.slice(20, 32)
113
+ ].join("-");
114
+ }
115
+ /** Есть ли в среде `localStorage`. Проверка безопасна: доступ к нему может бросать. */
116
+ function hasLocalStorage() {
117
+ try {
118
+ return typeof globalThis.localStorage !== "undefined" && globalThis.localStorage !== null;
119
+ } catch {
120
+ return false;
121
+ }
122
+ }
123
+ //#endregion
124
+ export { isBlob as a, shouldSendCredentials as c, hasLocalStorage as i, shouldUseCookieJar as l, RuntimeMode as n, isFile as o, createDeviceId as r, resolveFetch as s, DetectedRuntime as t, supportsStreamingBody as u };
125
+
126
+ //# sourceMappingURL=runtime-DHxDn8gf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-DHxDn8gf.js","names":[],"sources":["../src/core/runtime.ts"],"sourcesContent":["import { ItdConfigError } from './errors.js';\n\n/**\n * Как библиотека обращается с cookie.\n *\n * - `browser` — cookie ведёт браузер, запросы уходят с `credentials: 'include'`;\n * - `server` — cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную;\n * - `auto` — определяется по среде исполнения (значение по умолчанию).\n */\nexport const RuntimeMode = Object.freeze({\n /** Определяется по среде исполнения. Значение по умолчанию. */\n Auto: 'auto',\n /** Cookie ведёт браузер, запросы уходят с `credentials: 'include'`. */\n Browser: 'browser',\n /** Cookie ведёт встроенный jar, заголовок `Cookie` подставляется вручную. */\n Server: 'server',\n} as const);\nexport type RuntimeMode = (typeof RuntimeMode)[keyof typeof RuntimeMode];\n\n/** Распознанная среда исполнения. */\nexport const DetectedRuntime = Object.freeze({\n Browser: 'browser',\n /** Есть `window`, но нет `document`; cookie ведёт нативный сетевой слой. */\n ReactNative: 'react-native',\n Server: 'server',\n} as const);\nexport type DetectedRuntime = (typeof DetectedRuntime)[keyof typeof DetectedRuntime];\n\n/**\n * Определяет среду исполнения.\n *\n * React Native выделен отдельно намеренно: там есть `window`, но нет `document`, а cookie\n * хранит нативный сетевой слой (`NSHTTPCookieStorage` / `OkHttp`). Свой jar в этой среде\n * привёл бы к отправке cookie дважды.\n */\nexport function detectRuntime(): DetectedRuntime {\n const nav = (globalThis as { navigator?: { product?: string } }).navigator;\n if (nav?.product === 'ReactNative') return DetectedRuntime.ReactNative;\n\n if (typeof document !== 'undefined') return DetectedRuntime.Browser;\n\n return DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли вести собственный cookie-jar.\n *\n * Только в серверных средах: в браузере `Set-Cookie` из JS не читается и не нужен,\n * в React Native cookie ведёт нативный слой.\n */\nexport function shouldUseCookieJar(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return false;\n if (mode === RuntimeMode.Server) return true;\n return detectRuntime() === DetectedRuntime.Server;\n}\n\n/**\n * Нужно ли отправлять запросы с `credentials: 'include'`.\n *\n * Только в браузере: именно так refresh-cookie попадает в запрос `POST /api/v1/auth/refresh`.\n * Требует настроенного CORS на стороне итд.com — если его нет, укажите свой прокси в `baseUrl`.\n */\nexport function shouldSendCredentials(mode: RuntimeMode): boolean {\n if (mode === RuntimeMode.Browser) return true;\n if (mode === RuntimeMode.Server) return false;\n return detectRuntime() === DetectedRuntime.Browser;\n}\n\n/**\n * Возвращает реализацию `fetch`.\n *\n * @param custom реализация из конфигурации клиента, если пользователь её передал\n * @throws {ItdConfigError} если `fetch` недоступен — например, на Node ниже 18\n */\nexport function resolveFetch(custom?: typeof fetch): typeof fetch {\n if (custom !== undefined) {\n if (typeof custom !== 'function') {\n throw new ItdConfigError('fetch должен быть функцией');\n }\n return custom;\n }\n\n if (typeof globalThis.fetch === 'function') {\n // Привязка к globalThis обязательна: в некоторых средах несвязанный fetch бросает\n // «Illegal invocation».\n return globalThis.fetch.bind(globalThis);\n }\n\n throw new ItdConfigError(\n 'В этой среде нет глобального fetch. Обновитесь до Node 18+ либо передайте свою ' +\n 'реализацию через опцию fetch.',\n );\n}\n\n/**\n * Проверки бинарных типов, безопасные в любой среде.\n *\n * Обычный `instanceof` здесь недостаточен: конструктора может не быть вовсе, и тогда\n * проверка падает с `ReferenceError`, а не возвращает `false`. `Blob` есть в Node с 18.0,\n * но `File` стал глобальным только в Node 20 — при заявленной поддержке Node 18 голый\n * `instanceof File` ронял бы любую загрузку.\n */\nexport function isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/** @see {@link isBlob} */\nexport function isFile(value: unknown): value is File {\n return typeof File !== 'undefined' && value instanceof File;\n}\n\n/** Доступно ли потоковое чтение тела ответа — от этого зависит, сработает ли SSE. */\nexport function supportsStreamingBody(): boolean {\n return typeof ReadableStream !== 'undefined' && typeof TextDecoder !== 'undefined';\n}\n\n/**\n * Создаёт идентификатор устройства для заголовка `X-Device-Id` — UUID v4.\n *\n * `crypto.randomUUID` есть в Node 19+, браузерах и Deno, но отсутствует в Node 18 вне\n * защищённого контекста, поэтому предусмотрен запасной путь.\n */\nexport function createDeviceId(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n\n if (typeof webCrypto?.randomUUID === 'function') return webCrypto.randomUUID();\n\n // Форма UUID v4 собирается вручную: серверу важна стабильность значения, а не его энтропия.\n const bytes = new Uint8Array(16);\n if (typeof webCrypto?.getRandomValues === 'function') webCrypto.getRandomValues(bytes);\n else for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n // biome-ignore lint/style/noNonNullAssertion: длина массива фиксирована выше\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20, 32),\n ].join('-');\n}\n\n/** Есть ли в среде `localStorage`. Проверка безопасна: доступ к нему может бросать. */\nexport function hasLocalStorage(): boolean {\n try {\n return typeof globalThis.localStorage !== 'undefined' && globalThis.localStorage !== null;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,cAAc,OAAO,OAAO;;CAEvC,MAAM;;CAEN,SAAS;;CAET,QAAQ;AACV,CAAU;;AAIV,MAAa,kBAAkB,OAAO,OAAO;CAC3C,SAAS;;CAET,aAAa;CACb,QAAQ;AACV,CAAU;;;;;;;;AAUV,SAAgB,gBAAiC;CAE/C,IADa,WAAoD,WACxD,YAAY,eAAe,OAAO,gBAAgB;CAE3D,IAAI,OAAO,aAAa,aAAa,OAAO,gBAAgB;CAE5D,OAAO,gBAAgB;AACzB;;;;;;;AAQA,SAAgB,mBAAmB,MAA4B;CAC7D,IAAI,SAAS,YAAY,SAAS,OAAO;CACzC,IAAI,SAAS,YAAY,QAAQ,OAAO;CACxC,OAAO,cAAc,MAAM,gBAAgB;AAC7C;;;;;;;AAQA,SAAgB,sBAAsB,MAA4B;CAChE,IAAI,SAAS,YAAY,SAAS,OAAO;CACzC,IAAI,SAAS,YAAY,QAAQ,OAAO;CACxC,OAAO,cAAc,MAAM,gBAAgB;AAC7C;;;;;;;AAQA,SAAgB,aAAa,QAAqC;CAChE,IAAI,WAAW,KAAA,GAAW;EACxB,IAAI,OAAO,WAAW,YACpB,MAAM,IAAI,eAAe,4BAA4B;EAEvD,OAAO;CACT;CAEA,IAAI,OAAO,WAAW,UAAU,YAG9B,OAAO,WAAW,MAAM,KAAK,UAAU;CAGzC,MAAM,IAAI,eACR,8GAEF;AACF;;;;;;;;;AAUA,SAAgB,OAAO,OAA+B;CACpD,OAAO,OAAO,SAAS,eAAe,iBAAiB;AACzD;;AAGA,SAAgB,OAAO,OAA+B;CACpD,OAAO,OAAO,SAAS,eAAe,iBAAiB;AACzD;;AAGA,SAAgB,wBAAiC;CAC/C,OAAO,OAAO,mBAAmB,eAAe,OAAO,gBAAgB;AACzE;;;;;;;AAQA,SAAgB,iBAAyB;CACvC,MAAM,YAAa,WAAmC;CAEtD,IAAI,OAAO,WAAW,eAAe,YAAY,OAAO,UAAU,WAAW;CAG7E,MAAM,wBAAQ,IAAI,WAAW,EAAE;CAC/B,IAAI,OAAO,WAAW,oBAAoB,YAAY,UAAU,gBAAgB,KAAK;MAChF,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;CAGrF,MAAM,KAAM,MAAM,KAAM,KAAQ;CAEhC,MAAM,KAAM,MAAM,KAAM,KAAQ;CAEhC,MAAM,MAAM,MAAM,KAAK,QAAQ,SAAS,KAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;CAEnF,OAAO;EACL,IAAI,MAAM,GAAG,CAAC;EACd,IAAI,MAAM,GAAG,EAAE;EACf,IAAI,MAAM,IAAI,EAAE;EAChB,IAAI,MAAM,IAAI,EAAE;EAChB,IAAI,MAAM,IAAI,EAAE;CAClB,CAAC,CAAC,KAAK,GAAG;AACZ;;AAGA,SAAgB,kBAA2B;CACzC,IAAI;EACF,OAAO,OAAO,WAAW,iBAAiB,eAAe,WAAW,iBAAiB;CACvF,QAAQ;EACN,OAAO;CACT;AACF"}
@@ -0,0 +1,82 @@
1
+ //#region src/core/storage.d.ts
2
+ /**
3
+ * Сохранённая сессия.
4
+ *
5
+ * Кроме токенов сюда попадают cookie: refresh-токен итд.com живёт именно в cookie, и без них
6
+ * восстановить сессию после перезапуска процесса невозможно.
7
+ */
8
+ interface ItdSession {
9
+ /** Токен доступа для заголовка `Authorization: Bearer`. */
10
+ accessToken?: string | undefined;
11
+ /**
12
+ * Refresh-токен, если удалось получить его явным значением.
13
+ *
14
+ * Обычно сервер держит его в httpOnly-cookie и наружу не отдаёт — тогда поле останется
15
+ * пустым, а обновление пойдёт через {@link ItdSession.cookies}.
16
+ */
17
+ refreshToken?: string | undefined;
18
+ /** Сырые cookie в форме `имя=значение`, привязанные к origin API. */
19
+ cookies?: string[] | undefined;
20
+ /**
21
+ * Идентификатор устройства для заголовка `X-Device-Id`.
22
+ *
23
+ * Сервер различает по нему записи в списке сессий, поэтому значение должно пережить
24
+ * перезапуск процесса — иначе каждый старт бота порождает новую сессию. Библиотека
25
+ * заводит его сама при первом запросе и хранит здесь.
26
+ */
27
+ deviceId?: string | undefined;
28
+ /** Когда сессия получена, мс с начала эпохи. Нужно для диагностики. */
29
+ obtainedAt?: number | undefined;
30
+ }
31
+ /**
32
+ * Хранилище сессии.
33
+ *
34
+ * Подключаемый компонент: библиотека не знает, где вы держите токены, и обращается к ним
35
+ * только через этот интерфейс. Все методы могут быть как синхронными, так и асинхронными.
36
+ *
37
+ * @example Своё хранилище поверх AsyncStorage в React Native
38
+ * ```ts
39
+ * const storage = createTokenStorage({
40
+ * get: async () => JSON.parse((await AsyncStorage.getItem('itd')) ?? 'null'),
41
+ * set: (session) => AsyncStorage.setItem('itd', JSON.stringify(session)),
42
+ * clear: () => AsyncStorage.removeItem('itd'),
43
+ * });
44
+ * ```
45
+ */
46
+ interface TokenStorage {
47
+ /** Прочитать сессию. `null`, если её нет. */
48
+ get(): ItdSession | null | Promise<ItdSession | null>;
49
+ /** Сохранить сессию целиком. */
50
+ set(session: ItdSession): void | Promise<void>;
51
+ /** Удалить сессию. Вызывается при выходе и при неудачном обновлении токена. */
52
+ clear(): void | Promise<void>;
53
+ }
54
+ /**
55
+ * Хранилище в памяти процесса — вариант по умолчанию.
56
+ *
57
+ * Сессия теряется при перезапуске. Для долгоживущих ботов возьмите `FileTokenStorage`
58
+ * из `itd-api/node`, для браузера — `LocalStorageTokenStorage` из `itd-api/web`.
59
+ */
60
+ declare class MemoryTokenStorage implements TokenStorage {
61
+ #private;
62
+ constructor(initial?: ItdSession | null);
63
+ get(): ItdSession | null;
64
+ set(session: ItdSession): void;
65
+ clear(): void;
66
+ }
67
+ /**
68
+ * Собирает {@link TokenStorage} из трёх функций — когда заводить класс избыточно.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const storage = createTokenStorage({
73
+ * get: () => db.getSession(userId),
74
+ * set: (session) => db.saveSession(userId, session),
75
+ * clear: () => db.deleteSession(userId),
76
+ * });
77
+ * ```
78
+ */
79
+ declare function createTokenStorage(handlers: TokenStorage): TokenStorage;
80
+ //#endregion
81
+ export { createTokenStorage as i, MemoryTokenStorage as n, TokenStorage as r, ItdSession as t };
82
+ //# sourceMappingURL=storage-BjNRlkbE.d.cts.map
@@ -0,0 +1,82 @@
1
+ //#region src/core/storage.d.ts
2
+ /**
3
+ * Сохранённая сессия.
4
+ *
5
+ * Кроме токенов сюда попадают cookie: refresh-токен итд.com живёт именно в cookie, и без них
6
+ * восстановить сессию после перезапуска процесса невозможно.
7
+ */
8
+ interface ItdSession {
9
+ /** Токен доступа для заголовка `Authorization: Bearer`. */
10
+ accessToken?: string | undefined;
11
+ /**
12
+ * Refresh-токен, если удалось получить его явным значением.
13
+ *
14
+ * Обычно сервер держит его в httpOnly-cookie и наружу не отдаёт — тогда поле останется
15
+ * пустым, а обновление пойдёт через {@link ItdSession.cookies}.
16
+ */
17
+ refreshToken?: string | undefined;
18
+ /** Сырые cookie в форме `имя=значение`, привязанные к origin API. */
19
+ cookies?: string[] | undefined;
20
+ /**
21
+ * Идентификатор устройства для заголовка `X-Device-Id`.
22
+ *
23
+ * Сервер различает по нему записи в списке сессий, поэтому значение должно пережить
24
+ * перезапуск процесса — иначе каждый старт бота порождает новую сессию. Библиотека
25
+ * заводит его сама при первом запросе и хранит здесь.
26
+ */
27
+ deviceId?: string | undefined;
28
+ /** Когда сессия получена, мс с начала эпохи. Нужно для диагностики. */
29
+ obtainedAt?: number | undefined;
30
+ }
31
+ /**
32
+ * Хранилище сессии.
33
+ *
34
+ * Подключаемый компонент: библиотека не знает, где вы держите токены, и обращается к ним
35
+ * только через этот интерфейс. Все методы могут быть как синхронными, так и асинхронными.
36
+ *
37
+ * @example Своё хранилище поверх AsyncStorage в React Native
38
+ * ```ts
39
+ * const storage = createTokenStorage({
40
+ * get: async () => JSON.parse((await AsyncStorage.getItem('itd')) ?? 'null'),
41
+ * set: (session) => AsyncStorage.setItem('itd', JSON.stringify(session)),
42
+ * clear: () => AsyncStorage.removeItem('itd'),
43
+ * });
44
+ * ```
45
+ */
46
+ interface TokenStorage {
47
+ /** Прочитать сессию. `null`, если её нет. */
48
+ get(): ItdSession | null | Promise<ItdSession | null>;
49
+ /** Сохранить сессию целиком. */
50
+ set(session: ItdSession): void | Promise<void>;
51
+ /** Удалить сессию. Вызывается при выходе и при неудачном обновлении токена. */
52
+ clear(): void | Promise<void>;
53
+ }
54
+ /**
55
+ * Хранилище в памяти процесса — вариант по умолчанию.
56
+ *
57
+ * Сессия теряется при перезапуске. Для долгоживущих ботов возьмите `FileTokenStorage`
58
+ * из `itd-api/node`, для браузера — `LocalStorageTokenStorage` из `itd-api/web`.
59
+ */
60
+ declare class MemoryTokenStorage implements TokenStorage {
61
+ #private;
62
+ constructor(initial?: ItdSession | null);
63
+ get(): ItdSession | null;
64
+ set(session: ItdSession): void;
65
+ clear(): void;
66
+ }
67
+ /**
68
+ * Собирает {@link TokenStorage} из трёх функций — когда заводить класс избыточно.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const storage = createTokenStorage({
73
+ * get: () => db.getSession(userId),
74
+ * set: (session) => db.saveSession(userId, session),
75
+ * clear: () => db.deleteSession(userId),
76
+ * });
77
+ * ```
78
+ */
79
+ declare function createTokenStorage(handlers: TokenStorage): TokenStorage;
80
+ //#endregion
81
+ export { createTokenStorage as i, MemoryTokenStorage as n, TokenStorage as r, ItdSession as t };
82
+ //# sourceMappingURL=storage-BjNRlkbE.d.ts.map