itd-api 0.3.0 → 0.5.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 (42) hide show
  1. package/README.md +3 -2
  2. package/dist/index.cjs +3329 -1795
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1640 -1092
  5. package/dist/index.d.ts +1640 -1092
  6. package/dist/index.js +3249 -1730
  7. package/dist/index.js.map +1 -1
  8. package/dist/{multi-storage-CyMe404l.js → multi-storage-B0r0AInH.js} +151 -281
  9. package/dist/multi-storage-B0r0AInH.js.map +1 -0
  10. package/dist/{multi-storage-BhcA2Izn.d.ts → multi-storage-CLqmzq07.d.ts} +14 -54
  11. package/dist/{multi-storage-D1keK2Op.cjs → multi-storage-mBuCOVZY.cjs} +188 -294
  12. package/dist/multi-storage-mBuCOVZY.cjs.map +1 -0
  13. package/dist/{multi-storage-NDqzRQcD.d.cts → multi-storage-s_PcWPGH.d.cts} +14 -54
  14. package/dist/node.cjs +62 -53
  15. package/dist/node.cjs.map +1 -1
  16. package/dist/node.d.cts +19 -5
  17. package/dist/node.d.ts +19 -5
  18. package/dist/node.js +62 -54
  19. package/dist/node.js.map +1 -1
  20. package/dist/{storage-D9tfHx7Z.js → storage-DWrK3Z4M.js} +201 -18
  21. package/dist/storage-DWrK3Z4M.js.map +1 -0
  22. package/dist/storage-Doe3lpFQ.d.cts +152 -0
  23. package/dist/storage-Doe3lpFQ.d.ts +152 -0
  24. package/dist/{storage-ycBqLBRB.cjs → storage-dF8Tio5y.cjs} +254 -17
  25. package/dist/storage-dF8Tio5y.cjs.map +1 -0
  26. package/dist/web.cjs +143 -40
  27. package/dist/web.cjs.map +1 -1
  28. package/dist/web.d.cts +40 -3
  29. package/dist/web.d.ts +40 -3
  30. package/dist/web.js +141 -41
  31. package/dist/web.js.map +1 -1
  32. package/package.json +3 -3
  33. package/dist/multi-storage-CyMe404l.js.map +0 -1
  34. package/dist/multi-storage-D1keK2Op.cjs.map +0 -1
  35. package/dist/runtime-CFEsf-jD.cjs +0 -185
  36. package/dist/runtime-CFEsf-jD.cjs.map +0 -1
  37. package/dist/runtime-DHxDn8gf.js +0 -126
  38. package/dist/runtime-DHxDn8gf.js.map +0 -1
  39. package/dist/storage-BjNRlkbE.d.cts +0 -82
  40. package/dist/storage-BjNRlkbE.d.ts +0 -82
  41. package/dist/storage-D9tfHx7Z.js.map +0 -1
  42. package/dist/storage-ycBqLBRB.cjs.map +0 -1
package/dist/web.cjs CHANGED
@@ -1,16 +1,15 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_storage = require("./storage-ycBqLBRB.cjs");
3
- const require_runtime = require("./runtime-CFEsf-jD.cjs");
2
+ const require_storage = require("./storage-dF8Tio5y.cjs");
4
3
  //#region src/web.ts
5
4
  /**
6
- * `itd-api/web` — хранилище сессии для браузера.
5
+ * `itd-api/web` — хранилища для браузера.
7
6
  *
8
7
  * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,
9
8
  * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.
10
9
  *
11
- * Отдельная точка входа нужна не сборщику, а вам: {@link LocalStorageTokenStorage}
12
- * при недоступном `localStorage` молча работает как хранилище в памяти, и такое
13
- * поведение стоит выбирать осознанно, а не получать вместе с общим импортом.
10
+ * Отдельная точка входа нужна не сборщику, а вам: браузерные хранилища при
11
+ * недоступном Web Storage молча работают в памяти, и такое поведение стоит выбирать
12
+ * осознанно, а не получать вместе с общим импортом.
14
13
  *
15
14
  * @example
16
15
  * ```ts
@@ -22,6 +21,107 @@ const require_runtime = require("./runtime-CFEsf-jD.cjs");
22
21
  *
23
22
  * @packageDocumentation
24
23
  */
24
+ function getWebStorage(property) {
25
+ try {
26
+ return globalThis[property] ?? void 0;
27
+ } catch {
28
+ return;
29
+ }
30
+ }
31
+ /** Общая реализация Web Storage; публичные классы ниже фиксируют его вид. */
32
+ var WebStorageKeyValueStore = class {
33
+ #fallback = new require_storage.MemoryKeyValueStore();
34
+ #storage;
35
+ #property;
36
+ constructor(property) {
37
+ this.#property = property;
38
+ this.#storage = getWebStorage(property);
39
+ }
40
+ get(key) {
41
+ if (!this.#storage) return this.#fallback.get(key);
42
+ let raw;
43
+ try {
44
+ raw = this.#storage.getItem(key);
45
+ } catch {
46
+ this.#degrade();
47
+ return this.#fallback.get(key);
48
+ }
49
+ if (raw === null) return void 0;
50
+ try {
51
+ return JSON.parse(raw);
52
+ } catch (error) {
53
+ throw new require_storage.ItdConfigError(`Повреждён JSON в ${this.#property} по ключу «${key}»`, { cause: error });
54
+ }
55
+ }
56
+ set(key, value) {
57
+ if (this.#storage) try {
58
+ this.#storage.setItem(key, JSON.stringify(value));
59
+ return;
60
+ } catch {
61
+ this.#degrade();
62
+ }
63
+ this.#fallback.set(key, value);
64
+ }
65
+ delete(key) {
66
+ if (this.#storage) try {
67
+ this.#storage.removeItem(key);
68
+ return;
69
+ } catch {
70
+ this.#degrade();
71
+ }
72
+ this.#fallback.delete(key);
73
+ }
74
+ keys(prefix = "") {
75
+ if (!this.#storage) return this.#fallback.keys(prefix);
76
+ try {
77
+ const keys = [];
78
+ for (let index = 0; index < this.#storage.length; index += 1) {
79
+ const key = this.#storage.key(index);
80
+ if (key?.startsWith(prefix)) keys.push(key);
81
+ }
82
+ return keys;
83
+ } catch {
84
+ this.#degrade();
85
+ return this.#fallback.keys(prefix);
86
+ }
87
+ }
88
+ #degrade() {
89
+ this.#storage = void 0;
90
+ this.#fallback = new require_storage.MemoryKeyValueStore();
91
+ }
92
+ };
93
+ /** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */
94
+ var LocalStorageKeyValueStore = class {
95
+ #inner = new WebStorageKeyValueStore("localStorage");
96
+ get(key) {
97
+ return this.#inner.get(key);
98
+ }
99
+ set(key, value) {
100
+ this.#inner.set(key, value);
101
+ }
102
+ delete(key) {
103
+ this.#inner.delete(key);
104
+ }
105
+ keys(prefix = "") {
106
+ return this.#inner.keys(prefix);
107
+ }
108
+ };
109
+ /** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */
110
+ var SessionStorageKeyValueStore = class {
111
+ #inner = new WebStorageKeyValueStore("sessionStorage");
112
+ get(key) {
113
+ return this.#inner.get(key);
114
+ }
115
+ set(key, value) {
116
+ this.#inner.set(key, value);
117
+ }
118
+ delete(key) {
119
+ this.#inner.delete(key);
120
+ }
121
+ keys(prefix = "") {
122
+ return this.#inner.keys(prefix);
123
+ }
124
+ };
25
125
  /**
26
126
  * Хранилище поверх `localStorage` браузера.
27
127
  *
@@ -33,55 +133,58 @@ const require_runtime = require("./runtime-CFEsf-jD.cjs");
33
133
  * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,
34
134
  * если для вашего приложения это неприемлемый риск.
35
135
  *
36
- * После ошибки записи или удаления хранилище переключается на память до конца
136
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,
137
+ * записи или удаления хранилище переключается на память до конца
37
138
  * своего жизненного цикла.
38
139
  */
39
140
  var LocalStorageTokenStorage = class {
40
- #key;
41
- #fallback = new require_storage.MemoryTokenStorage();
42
- /** Доступен ли `localStorage` для дальнейших операций. */
43
- #available;
141
+ #inner;
44
142
  /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */
45
143
  constructor(key = "itd-api:session") {
46
- this.#key = key;
47
- this.#available = require_runtime.hasLocalStorage();
144
+ this.#inner = require_storage.createTokenStorage(new LocalStorageKeyValueStore(), { key });
48
145
  }
49
146
  get() {
50
- if (!this.#available) return this.#fallback.get();
51
- try {
52
- const raw = globalThis.localStorage.getItem(this.#key);
53
- if (!raw) return null;
54
- const parsed = JSON.parse(raw);
55
- return typeof parsed === "object" && parsed !== null ? parsed : null;
56
- } catch {
57
- return null;
58
- }
147
+ return this.#inner.get();
59
148
  }
60
149
  set(session) {
61
- if (this.#available) try {
62
- globalThis.localStorage.setItem(this.#key, JSON.stringify(session));
63
- return;
64
- } catch {
65
- this.#degrade();
66
- }
67
- this.#fallback.set(session);
150
+ this.#inner.set(session);
68
151
  }
69
152
  clear() {
70
- if (this.#available) try {
71
- globalThis.localStorage.removeItem(this.#key);
72
- return;
73
- } catch {
74
- this.#degrade();
75
- }
76
- this.#fallback.clear();
153
+ this.#inner.clear();
77
154
  }
78
- /** Переводит хранилище в память без переноса прежнего значения. */
79
- #degrade() {
80
- this.#available = false;
81
- this.#fallback.clear();
155
+ };
156
+ /**
157
+ * Хранилище сессии поверх браузерного `sessionStorage`.
158
+ *
159
+ * Данные переживают перезагрузку страницы, но существуют только в пределах текущей
160
+ * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает
161
+ * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца
162
+ * своего жизненного цикла.
163
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.
164
+ *
165
+ * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию
166
+ * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.
167
+ */
168
+ var SessionStorageTokenStorage = class {
169
+ #inner;
170
+ /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */
171
+ constructor(key = "itd-api:session") {
172
+ this.#inner = require_storage.createTokenStorage(new SessionStorageKeyValueStore(), { key });
173
+ }
174
+ get() {
175
+ return this.#inner.get();
176
+ }
177
+ set(session) {
178
+ this.#inner.set(session);
179
+ }
180
+ clear() {
181
+ this.#inner.clear();
82
182
  }
83
183
  };
84
184
  //#endregion
185
+ exports.LocalStorageKeyValueStore = LocalStorageKeyValueStore;
85
186
  exports.LocalStorageTokenStorage = LocalStorageTokenStorage;
187
+ exports.SessionStorageKeyValueStore = SessionStorageKeyValueStore;
188
+ exports.SessionStorageTokenStorage = SessionStorageTokenStorage;
86
189
 
87
190
  //# sourceMappingURL=web.cjs.map
package/dist/web.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.cjs","names":["#key","#fallback","MemoryTokenStorage","#available","hasLocalStorage","#degrade"],"sources":["../src/web.ts"],"sourcesContent":["/**\n * `itd-api/web` — хранилище сессии для браузера.\n *\n * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,\n * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.\n *\n * Отдельная точка входа нужна не сборщику, а вам: {@link LocalStorageTokenStorage}\n * при недоступном `localStorage` молча работает как хранилище в памяти, и такое\n * поведение стоит выбирать осознанно, а не получать вместе с общим импортом.\n *\n * @example\n * ```ts\n * import { ItdClient } from 'itd-api';\n * import { LocalStorageTokenStorage } from 'itd-api/web';\n *\n * const itd = new ItdClient({ storage: new LocalStorageTokenStorage() });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { hasLocalStorage } from './core/runtime.js';\nimport { type ItdSession, MemoryTokenStorage, type TokenStorage } from './core/storage.js';\n\n/**\n * Хранилище поверх `localStorage` браузера.\n *\n * Если `localStorage` недоступен (приватный режим, серверный рендеринг), молча работает\n * как хранилище в памяти — библиотека не должна падать из-за настроек браузера. Сессия\n * в этом случае теряется при перезагрузке страницы; когда это неприемлемо, проверьте\n * доступность сами или возьмите своё хранилище через `createTokenStorage`.\n *\n * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,\n * если для вашего приложения это неприемлемый риск.\n *\n * После ошибки записи или удаления хранилище переключается на память до конца\n * своего жизненного цикла.\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n readonly #key: string;\n readonly #fallback = new MemoryTokenStorage();\n /** Доступен ли `localStorage` для дальнейших операций. */\n #available: boolean;\n\n /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#key = key;\n this.#available = hasLocalStorage();\n }\n\n get(): ItdSession | null {\n if (!this.#available) return this.#fallback.get();\n\n try {\n const raw = globalThis.localStorage.getItem(this.#key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === 'object' && parsed !== null ? (parsed as ItdSession) : null;\n } catch {\n // Повреждённое значение ведём себя так, будто сессии нет.\n return null;\n }\n }\n\n set(session: ItdSession): void {\n if (this.#available) {\n try {\n globalThis.localStorage.setItem(this.#key, JSON.stringify(session));\n return;\n } catch {\n this.#degrade();\n }\n }\n\n this.#fallback.set(session);\n }\n\n clear(): void {\n if (this.#available) {\n try {\n globalThis.localStorage.removeItem(this.#key);\n return;\n } catch {\n this.#degrade();\n }\n }\n\n this.#fallback.clear();\n }\n\n /** Переводит хранилище в память без переноса прежнего значения. */\n #degrade(): void {\n this.#available = false;\n this.#fallback.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,IAAa,2BAAb,MAA8D;CAC5D;CACA,YAAqB,IAAIE,gBAAAA,mBAAmB;;CAE5C;;CAGA,YAAY,MAAM,mBAAmB;EACnC,KAAKF,OAAO;EACZ,KAAKG,aAAaC,gBAAAA,gBAAgB;CACpC;CAEA,MAAyB;EACvB,IAAI,CAAC,KAAKD,YAAY,OAAO,KAAKF,UAAU,IAAI;EAEhD,IAAI;GACF,MAAM,MAAM,WAAW,aAAa,QAAQ,KAAKD,IAAI;GACrD,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,SAAkB,KAAK,MAAM,GAAG;GACtC,OAAO,OAAO,WAAW,YAAY,WAAW,OAAQ,SAAwB;EAClF,QAAQ;GAEN,OAAO;EACT;CACF;CAEA,IAAI,SAA2B;EAC7B,IAAI,KAAKG,YACP,IAAI;GACF,WAAW,aAAa,QAAQ,KAAKH,MAAM,KAAK,UAAU,OAAO,CAAC;GAClE;EACF,QAAQ;GACN,KAAKK,SAAS;EAChB;EAGF,KAAKJ,UAAU,IAAI,OAAO;CAC5B;CAEA,QAAc;EACZ,IAAI,KAAKE,YACP,IAAI;GACF,WAAW,aAAa,WAAW,KAAKH,IAAI;GAC5C;EACF,QAAQ;GACN,KAAKK,SAAS;EAChB;EAGF,KAAKJ,UAAU,MAAM;CACvB;;CAGA,WAAiB;EACf,KAAKE,aAAa;EAClB,KAAKF,UAAU,MAAM;CACvB;AACF"}
1
+ {"version":3,"file":"web.cjs","names":["MemoryKeyValueStore","#property","#storage","#fallback","#degrade","ItdConfigError","#inner","createTokenStorage"],"sources":["../src/web.ts"],"sourcesContent":["/**\n * `itd-api/web` — хранилища для браузера.\n *\n * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,\n * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.\n *\n * Отдельная точка входа нужна не сборщику, а вам: браузерные хранилища при\n * недоступном Web Storage молча работают в памяти, и такое поведение стоит выбирать\n * осознанно, а не получать вместе с общим импортом.\n *\n * @example\n * ```ts\n * import { ItdClient } from 'itd-api';\n * import { LocalStorageTokenStorage } from 'itd-api/web';\n *\n * const itd = new ItdClient({ storage: new LocalStorageTokenStorage() });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { ItdConfigError } from './core/errors.js';\nimport { MemoryKeyValueStore } from './core/key-value-store.js';\nimport { createTokenStorage, type ItdSession, type TokenStorage } from './core/storage.js';\n\ntype WebStorageProperty = 'localStorage' | 'sessionStorage';\n\nfunction getWebStorage(property: WebStorageProperty): Storage | undefined {\n try {\n return globalThis[property] ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Общая реализация Web Storage; публичные классы ниже фиксируют его вид. */\nclass WebStorageKeyValueStore<T> {\n #fallback = new MemoryKeyValueStore<T>();\n #storage: Storage | undefined;\n readonly #property: WebStorageProperty;\n\n constructor(property: WebStorageProperty) {\n this.#property = property;\n this.#storage = getWebStorage(property);\n }\n\n get(key: string): T | undefined {\n if (!this.#storage) return this.#fallback.get(key);\n let raw: string | null;\n try {\n raw = this.#storage.getItem(key);\n } catch {\n this.#degrade();\n return this.#fallback.get(key);\n }\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch (error) {\n throw new ItdConfigError(`Повреждён JSON в ${this.#property} по ключу «${key}»`, {\n cause: error,\n });\n }\n }\n\n set(key: string, value: T): void {\n if (this.#storage) {\n try {\n this.#storage.setItem(key, JSON.stringify(value));\n return;\n } catch {\n this.#degrade();\n }\n }\n this.#fallback.set(key, value);\n }\n\n delete(key: string): void {\n if (this.#storage) {\n try {\n this.#storage.removeItem(key);\n return;\n } catch {\n this.#degrade();\n }\n }\n this.#fallback.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n if (!this.#storage) return this.#fallback.keys(prefix);\n try {\n const keys: string[] = [];\n for (let index = 0; index < this.#storage.length; index += 1) {\n const key = this.#storage.key(index);\n if (key?.startsWith(prefix)) keys.push(key);\n }\n return keys;\n } catch {\n this.#degrade();\n return this.#fallback.keys(prefix);\n }\n }\n\n #degrade(): void {\n this.#storage = undefined;\n this.#fallback = new MemoryKeyValueStore<T>();\n }\n}\n\n/** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */\nexport class LocalStorageKeyValueStore<T> {\n readonly #inner = new WebStorageKeyValueStore<T>('localStorage');\n\n get(key: string): T | undefined {\n return this.#inner.get(key);\n }\n\n set(key: string, value: T): void {\n this.#inner.set(key, value);\n }\n\n delete(key: string): void {\n this.#inner.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n return this.#inner.keys(prefix);\n }\n}\n\n/** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */\nexport class SessionStorageKeyValueStore<T> {\n readonly #inner = new WebStorageKeyValueStore<T>('sessionStorage');\n\n get(key: string): T | undefined {\n return this.#inner.get(key);\n }\n\n set(key: string, value: T): void {\n this.#inner.set(key, value);\n }\n\n delete(key: string): void {\n this.#inner.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n return this.#inner.keys(prefix);\n }\n}\n\n/**\n * Хранилище поверх `localStorage` браузера.\n *\n * Если `localStorage` недоступен (приватный режим, серверный рендеринг), молча работает\n * как хранилище в памяти — библиотека не должна падать из-за настроек браузера. Сессия\n * в этом случае теряется при перезагрузке страницы; когда это неприемлемо, проверьте\n * доступность сами или возьмите своё хранилище через `createTokenStorage`.\n *\n * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,\n * если для вашего приложения это неприемлемый риск.\n *\n * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,\n * записи или удаления хранилище переключается на память до конца\n * своего жизненного цикла.\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n readonly #inner: TokenStorage;\n\n /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#inner = createTokenStorage(new LocalStorageKeyValueStore<ItdSession>(), { key });\n }\n\n get(): ItdSession | null {\n return this.#inner.get() as ItdSession | null;\n }\n\n set(session: ItdSession): void {\n void this.#inner.set(session);\n }\n\n clear(): void {\n void this.#inner.clear();\n }\n}\n\n/**\n * Хранилище сессии поверх браузерного `sessionStorage`.\n *\n * Данные переживают перезагрузку страницы, но существуют только в пределах текущей\n * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает\n * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца\n * своего жизненного цикла.\n * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.\n *\n * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию\n * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.\n */\nexport class SessionStorageTokenStorage implements TokenStorage {\n readonly #inner: TokenStorage;\n\n /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#inner = createTokenStorage(new SessionStorageKeyValueStore<ItdSession>(), { key });\n }\n\n get(): ItdSession | null {\n return this.#inner.get() as ItdSession | null;\n }\n\n set(session: ItdSession): void {\n void this.#inner.set(session);\n }\n\n clear(): void {\n void this.#inner.clear();\n }\n}\n"],"mappings":"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"}
package/dist/web.d.cts CHANGED
@@ -1,5 +1,21 @@
1
- import { r as TokenStorage, t as ItdSession } from "./storage-BjNRlkbE.cjs";
1
+ import { r as TokenStorage, t as ItdSession } from "./storage-Doe3lpFQ.cjs";
2
2
  //#region src/web.d.ts
3
+ /** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */
4
+ declare class LocalStorageKeyValueStore<T> {
5
+ #private;
6
+ get(key: string): T | undefined;
7
+ set(key: string, value: T): void;
8
+ delete(key: string): void;
9
+ keys(prefix?: string): Iterable<string> | AsyncIterable<string>;
10
+ }
11
+ /** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */
12
+ declare class SessionStorageKeyValueStore<T> {
13
+ #private;
14
+ get(key: string): T | undefined;
15
+ set(key: string, value: T): void;
16
+ delete(key: string): void;
17
+ keys(prefix?: string): Iterable<string> | AsyncIterable<string>;
18
+ }
3
19
  /**
4
20
  * Хранилище поверх `localStorage` браузера.
5
21
  *
@@ -11,7 +27,8 @@ import { r as TokenStorage, t as ItdSession } from "./storage-BjNRlkbE.cjs";
11
27
  * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,
12
28
  * если для вашего приложения это неприемлемый риск.
13
29
  *
14
- * После ошибки записи или удаления хранилище переключается на память до конца
30
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,
31
+ * записи или удаления хранилище переключается на память до конца
15
32
  * своего жизненного цикла.
16
33
  */
17
34
  declare class LocalStorageTokenStorage implements TokenStorage {
@@ -22,6 +39,26 @@ declare class LocalStorageTokenStorage implements TokenStorage {
22
39
  set(session: ItdSession): void;
23
40
  clear(): void;
24
41
  }
42
+ /**
43
+ * Хранилище сессии поверх браузерного `sessionStorage`.
44
+ *
45
+ * Данные переживают перезагрузку страницы, но существуют только в пределах текущей
46
+ * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает
47
+ * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца
48
+ * своего жизненного цикла.
49
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.
50
+ *
51
+ * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию
52
+ * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.
53
+ */
54
+ declare class SessionStorageTokenStorage implements TokenStorage {
55
+ #private;
56
+ /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */
57
+ constructor(key?: string);
58
+ get(): ItdSession | null;
59
+ set(session: ItdSession): void;
60
+ clear(): void;
61
+ }
25
62
  //#endregion
26
- export { LocalStorageTokenStorage };
63
+ export { LocalStorageKeyValueStore, LocalStorageTokenStorage, SessionStorageKeyValueStore, SessionStorageTokenStorage };
27
64
  //# sourceMappingURL=web.d.cts.map
package/dist/web.d.ts CHANGED
@@ -1,5 +1,21 @@
1
- import { r as TokenStorage, t as ItdSession } from "./storage-BjNRlkbE.js";
1
+ import { r as TokenStorage, t as ItdSession } from "./storage-Doe3lpFQ.js";
2
2
  //#region src/web.d.ts
3
+ /** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */
4
+ declare class LocalStorageKeyValueStore<T> {
5
+ #private;
6
+ get(key: string): T | undefined;
7
+ set(key: string, value: T): void;
8
+ delete(key: string): void;
9
+ keys(prefix?: string): Iterable<string> | AsyncIterable<string>;
10
+ }
11
+ /** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */
12
+ declare class SessionStorageKeyValueStore<T> {
13
+ #private;
14
+ get(key: string): T | undefined;
15
+ set(key: string, value: T): void;
16
+ delete(key: string): void;
17
+ keys(prefix?: string): Iterable<string> | AsyncIterable<string>;
18
+ }
3
19
  /**
4
20
  * Хранилище поверх `localStorage` браузера.
5
21
  *
@@ -11,7 +27,8 @@ import { r as TokenStorage, t as ItdSession } from "./storage-BjNRlkbE.js";
11
27
  * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,
12
28
  * если для вашего приложения это неприемлемый риск.
13
29
  *
14
- * После ошибки записи или удаления хранилище переключается на память до конца
30
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,
31
+ * записи или удаления хранилище переключается на память до конца
15
32
  * своего жизненного цикла.
16
33
  */
17
34
  declare class LocalStorageTokenStorage implements TokenStorage {
@@ -22,6 +39,26 @@ declare class LocalStorageTokenStorage implements TokenStorage {
22
39
  set(session: ItdSession): void;
23
40
  clear(): void;
24
41
  }
42
+ /**
43
+ * Хранилище сессии поверх браузерного `sessionStorage`.
44
+ *
45
+ * Данные переживают перезагрузку страницы, но существуют только в пределах текущей
46
+ * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает
47
+ * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца
48
+ * своего жизненного цикла.
49
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.
50
+ *
51
+ * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию
52
+ * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.
53
+ */
54
+ declare class SessionStorageTokenStorage implements TokenStorage {
55
+ #private;
56
+ /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */
57
+ constructor(key?: string);
58
+ get(): ItdSession | null;
59
+ set(session: ItdSession): void;
60
+ clear(): void;
61
+ }
25
62
  //#endregion
26
- export { LocalStorageTokenStorage };
63
+ export { LocalStorageKeyValueStore, LocalStorageTokenStorage, SessionStorageKeyValueStore, SessionStorageTokenStorage };
27
64
  //# sourceMappingURL=web.d.ts.map
package/dist/web.js CHANGED
@@ -1,15 +1,14 @@
1
- import { t as MemoryTokenStorage } from "./storage-D9tfHx7Z.js";
2
- import { i as hasLocalStorage } from "./runtime-DHxDn8gf.js";
1
+ import { h as ItdConfigError, i as MemoryKeyValueStore, r as createTokenStorage } from "./storage-DWrK3Z4M.js";
3
2
  //#region src/web.ts
4
3
  /**
5
- * `itd-api/web` — хранилище сессии для браузера.
4
+ * `itd-api/web` — хранилища для браузера.
6
5
  *
7
6
  * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,
8
7
  * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.
9
8
  *
10
- * Отдельная точка входа нужна не сборщику, а вам: {@link LocalStorageTokenStorage}
11
- * при недоступном `localStorage` молча работает как хранилище в памяти, и такое
12
- * поведение стоит выбирать осознанно, а не получать вместе с общим импортом.
9
+ * Отдельная точка входа нужна не сборщику, а вам: браузерные хранилища при
10
+ * недоступном Web Storage молча работают в памяти, и такое поведение стоит выбирать
11
+ * осознанно, а не получать вместе с общим импортом.
13
12
  *
14
13
  * @example
15
14
  * ```ts
@@ -21,6 +20,107 @@ import { i as hasLocalStorage } from "./runtime-DHxDn8gf.js";
21
20
  *
22
21
  * @packageDocumentation
23
22
  */
23
+ function getWebStorage(property) {
24
+ try {
25
+ return globalThis[property] ?? void 0;
26
+ } catch {
27
+ return;
28
+ }
29
+ }
30
+ /** Общая реализация Web Storage; публичные классы ниже фиксируют его вид. */
31
+ var WebStorageKeyValueStore = class {
32
+ #fallback = new MemoryKeyValueStore();
33
+ #storage;
34
+ #property;
35
+ constructor(property) {
36
+ this.#property = property;
37
+ this.#storage = getWebStorage(property);
38
+ }
39
+ get(key) {
40
+ if (!this.#storage) return this.#fallback.get(key);
41
+ let raw;
42
+ try {
43
+ raw = this.#storage.getItem(key);
44
+ } catch {
45
+ this.#degrade();
46
+ return this.#fallback.get(key);
47
+ }
48
+ if (raw === null) return void 0;
49
+ try {
50
+ return JSON.parse(raw);
51
+ } catch (error) {
52
+ throw new ItdConfigError(`Повреждён JSON в ${this.#property} по ключу «${key}»`, { cause: error });
53
+ }
54
+ }
55
+ set(key, value) {
56
+ if (this.#storage) try {
57
+ this.#storage.setItem(key, JSON.stringify(value));
58
+ return;
59
+ } catch {
60
+ this.#degrade();
61
+ }
62
+ this.#fallback.set(key, value);
63
+ }
64
+ delete(key) {
65
+ if (this.#storage) try {
66
+ this.#storage.removeItem(key);
67
+ return;
68
+ } catch {
69
+ this.#degrade();
70
+ }
71
+ this.#fallback.delete(key);
72
+ }
73
+ keys(prefix = "") {
74
+ if (!this.#storage) return this.#fallback.keys(prefix);
75
+ try {
76
+ const keys = [];
77
+ for (let index = 0; index < this.#storage.length; index += 1) {
78
+ const key = this.#storage.key(index);
79
+ if (key?.startsWith(prefix)) keys.push(key);
80
+ }
81
+ return keys;
82
+ } catch {
83
+ this.#degrade();
84
+ return this.#fallback.keys(prefix);
85
+ }
86
+ }
87
+ #degrade() {
88
+ this.#storage = void 0;
89
+ this.#fallback = new MemoryKeyValueStore();
90
+ }
91
+ };
92
+ /** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */
93
+ var LocalStorageKeyValueStore = class {
94
+ #inner = new WebStorageKeyValueStore("localStorage");
95
+ get(key) {
96
+ return this.#inner.get(key);
97
+ }
98
+ set(key, value) {
99
+ this.#inner.set(key, value);
100
+ }
101
+ delete(key) {
102
+ this.#inner.delete(key);
103
+ }
104
+ keys(prefix = "") {
105
+ return this.#inner.keys(prefix);
106
+ }
107
+ };
108
+ /** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */
109
+ var SessionStorageKeyValueStore = class {
110
+ #inner = new WebStorageKeyValueStore("sessionStorage");
111
+ get(key) {
112
+ return this.#inner.get(key);
113
+ }
114
+ set(key, value) {
115
+ this.#inner.set(key, value);
116
+ }
117
+ delete(key) {
118
+ this.#inner.delete(key);
119
+ }
120
+ keys(prefix = "") {
121
+ return this.#inner.keys(prefix);
122
+ }
123
+ };
24
124
  /**
25
125
  * Хранилище поверх `localStorage` браузера.
26
126
  *
@@ -32,55 +132,55 @@ import { i as hasLocalStorage } from "./runtime-DHxDn8gf.js";
32
132
  * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,
33
133
  * если для вашего приложения это неприемлемый риск.
34
134
  *
35
- * После ошибки записи или удаления хранилище переключается на память до конца
135
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,
136
+ * записи или удаления хранилище переключается на память до конца
36
137
  * своего жизненного цикла.
37
138
  */
38
139
  var LocalStorageTokenStorage = class {
39
- #key;
40
- #fallback = new MemoryTokenStorage();
41
- /** Доступен ли `localStorage` для дальнейших операций. */
42
- #available;
140
+ #inner;
43
141
  /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */
44
142
  constructor(key = "itd-api:session") {
45
- this.#key = key;
46
- this.#available = hasLocalStorage();
143
+ this.#inner = createTokenStorage(new LocalStorageKeyValueStore(), { key });
47
144
  }
48
145
  get() {
49
- if (!this.#available) return this.#fallback.get();
50
- try {
51
- const raw = globalThis.localStorage.getItem(this.#key);
52
- if (!raw) return null;
53
- const parsed = JSON.parse(raw);
54
- return typeof parsed === "object" && parsed !== null ? parsed : null;
55
- } catch {
56
- return null;
57
- }
146
+ return this.#inner.get();
58
147
  }
59
148
  set(session) {
60
- if (this.#available) try {
61
- globalThis.localStorage.setItem(this.#key, JSON.stringify(session));
62
- return;
63
- } catch {
64
- this.#degrade();
65
- }
66
- this.#fallback.set(session);
149
+ this.#inner.set(session);
67
150
  }
68
151
  clear() {
69
- if (this.#available) try {
70
- globalThis.localStorage.removeItem(this.#key);
71
- return;
72
- } catch {
73
- this.#degrade();
74
- }
75
- this.#fallback.clear();
152
+ this.#inner.clear();
76
153
  }
77
- /** Переводит хранилище в память без переноса прежнего значения. */
78
- #degrade() {
79
- this.#available = false;
80
- this.#fallback.clear();
154
+ };
155
+ /**
156
+ * Хранилище сессии поверх браузерного `sessionStorage`.
157
+ *
158
+ * Данные переживают перезагрузку страницы, но существуют только в пределах текущей
159
+ * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает
160
+ * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца
161
+ * своего жизненного цикла.
162
+ * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.
163
+ *
164
+ * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию
165
+ * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.
166
+ */
167
+ var SessionStorageTokenStorage = class {
168
+ #inner;
169
+ /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */
170
+ constructor(key = "itd-api:session") {
171
+ this.#inner = createTokenStorage(new SessionStorageKeyValueStore(), { key });
172
+ }
173
+ get() {
174
+ return this.#inner.get();
175
+ }
176
+ set(session) {
177
+ this.#inner.set(session);
178
+ }
179
+ clear() {
180
+ this.#inner.clear();
81
181
  }
82
182
  };
83
183
  //#endregion
84
- export { LocalStorageTokenStorage };
184
+ export { LocalStorageKeyValueStore, LocalStorageTokenStorage, SessionStorageKeyValueStore, SessionStorageTokenStorage };
85
185
 
86
186
  //# sourceMappingURL=web.js.map
package/dist/web.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","names":["#key","#fallback","#available","#degrade"],"sources":["../src/web.ts"],"sourcesContent":["/**\n * `itd-api/web` — хранилище сессии для браузера.\n *\n * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,\n * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.\n *\n * Отдельная точка входа нужна не сборщику, а вам: {@link LocalStorageTokenStorage}\n * при недоступном `localStorage` молча работает как хранилище в памяти, и такое\n * поведение стоит выбирать осознанно, а не получать вместе с общим импортом.\n *\n * @example\n * ```ts\n * import { ItdClient } from 'itd-api';\n * import { LocalStorageTokenStorage } from 'itd-api/web';\n *\n * const itd = new ItdClient({ storage: new LocalStorageTokenStorage() });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { hasLocalStorage } from './core/runtime.js';\nimport { type ItdSession, MemoryTokenStorage, type TokenStorage } from './core/storage.js';\n\n/**\n * Хранилище поверх `localStorage` браузера.\n *\n * Если `localStorage` недоступен (приватный режим, серверный рендеринг), молча работает\n * как хранилище в памяти — библиотека не должна падать из-за настроек браузера. Сессия\n * в этом случае теряется при перезагрузке страницы; когда это неприемлемо, проверьте\n * доступность сами или возьмите своё хранилище через `createTokenStorage`.\n *\n * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,\n * если для вашего приложения это неприемлемый риск.\n *\n * После ошибки записи или удаления хранилище переключается на память до конца\n * своего жизненного цикла.\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n readonly #key: string;\n readonly #fallback = new MemoryTokenStorage();\n /** Доступен ли `localStorage` для дальнейших операций. */\n #available: boolean;\n\n /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#key = key;\n this.#available = hasLocalStorage();\n }\n\n get(): ItdSession | null {\n if (!this.#available) return this.#fallback.get();\n\n try {\n const raw = globalThis.localStorage.getItem(this.#key);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n return typeof parsed === 'object' && parsed !== null ? (parsed as ItdSession) : null;\n } catch {\n // Повреждённое значение ведём себя так, будто сессии нет.\n return null;\n }\n }\n\n set(session: ItdSession): void {\n if (this.#available) {\n try {\n globalThis.localStorage.setItem(this.#key, JSON.stringify(session));\n return;\n } catch {\n this.#degrade();\n }\n }\n\n this.#fallback.set(session);\n }\n\n clear(): void {\n if (this.#available) {\n try {\n globalThis.localStorage.removeItem(this.#key);\n return;\n } catch {\n this.#degrade();\n }\n }\n\n this.#fallback.clear();\n }\n\n /** Переводит хранилище в память без переноса прежнего значения. */\n #degrade(): void {\n this.#available = false;\n this.#fallback.clear();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,IAAa,2BAAb,MAA8D;CAC5D;CACA,YAAqB,IAAI,mBAAmB;;CAE5C;;CAGA,YAAY,MAAM,mBAAmB;EACnC,KAAKA,OAAO;EACZ,KAAKE,aAAa,gBAAgB;CACpC;CAEA,MAAyB;EACvB,IAAI,CAAC,KAAKA,YAAY,OAAO,KAAKD,UAAU,IAAI;EAEhD,IAAI;GACF,MAAM,MAAM,WAAW,aAAa,QAAQ,KAAKD,IAAI;GACrD,IAAI,CAAC,KAAK,OAAO;GACjB,MAAM,SAAkB,KAAK,MAAM,GAAG;GACtC,OAAO,OAAO,WAAW,YAAY,WAAW,OAAQ,SAAwB;EAClF,QAAQ;GAEN,OAAO;EACT;CACF;CAEA,IAAI,SAA2B;EAC7B,IAAI,KAAKE,YACP,IAAI;GACF,WAAW,aAAa,QAAQ,KAAKF,MAAM,KAAK,UAAU,OAAO,CAAC;GAClE;EACF,QAAQ;GACN,KAAKG,SAAS;EAChB;EAGF,KAAKF,UAAU,IAAI,OAAO;CAC5B;CAEA,QAAc;EACZ,IAAI,KAAKC,YACP,IAAI;GACF,WAAW,aAAa,WAAW,KAAKF,IAAI;GAC5C;EACF,QAAQ;GACN,KAAKG,SAAS;EAChB;EAGF,KAAKF,UAAU,MAAM;CACvB;;CAGA,WAAiB;EACf,KAAKC,aAAa;EAClB,KAAKD,UAAU,MAAM;CACvB;AACF"}
1
+ {"version":3,"file":"web.js","names":["#property","#storage","#fallback","#degrade","#inner"],"sources":["../src/web.ts"],"sourcesContent":["/**\n * `itd-api/web` — хранилища для браузера.\n *\n * Здесь лежит только то, что рассчитано на браузерное окружение. Клиент, аккаунты,\n * билдеры, типы и всё остальное берутся из `itd-api` — одинаково на всех платформах.\n *\n * Отдельная точка входа нужна не сборщику, а вам: браузерные хранилища при\n * недоступном Web Storage молча работают в памяти, и такое поведение стоит выбирать\n * осознанно, а не получать вместе с общим импортом.\n *\n * @example\n * ```ts\n * import { ItdClient } from 'itd-api';\n * import { LocalStorageTokenStorage } from 'itd-api/web';\n *\n * const itd = new ItdClient({ storage: new LocalStorageTokenStorage() });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { ItdConfigError } from './core/errors.js';\nimport { MemoryKeyValueStore } from './core/key-value-store.js';\nimport { createTokenStorage, type ItdSession, type TokenStorage } from './core/storage.js';\n\ntype WebStorageProperty = 'localStorage' | 'sessionStorage';\n\nfunction getWebStorage(property: WebStorageProperty): Storage | undefined {\n try {\n return globalThis[property] ?? undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Общая реализация Web Storage; публичные классы ниже фиксируют его вид. */\nclass WebStorageKeyValueStore<T> {\n #fallback = new MemoryKeyValueStore<T>();\n #storage: Storage | undefined;\n readonly #property: WebStorageProperty;\n\n constructor(property: WebStorageProperty) {\n this.#property = property;\n this.#storage = getWebStorage(property);\n }\n\n get(key: string): T | undefined {\n if (!this.#storage) return this.#fallback.get(key);\n let raw: string | null;\n try {\n raw = this.#storage.getItem(key);\n } catch {\n this.#degrade();\n return this.#fallback.get(key);\n }\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as T;\n } catch (error) {\n throw new ItdConfigError(`Повреждён JSON в ${this.#property} по ключу «${key}»`, {\n cause: error,\n });\n }\n }\n\n set(key: string, value: T): void {\n if (this.#storage) {\n try {\n this.#storage.setItem(key, JSON.stringify(value));\n return;\n } catch {\n this.#degrade();\n }\n }\n this.#fallback.set(key, value);\n }\n\n delete(key: string): void {\n if (this.#storage) {\n try {\n this.#storage.removeItem(key);\n return;\n } catch {\n this.#degrade();\n }\n }\n this.#fallback.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n if (!this.#storage) return this.#fallback.keys(prefix);\n try {\n const keys: string[] = [];\n for (let index = 0; index < this.#storage.length; index += 1) {\n const key = this.#storage.key(index);\n if (key?.startsWith(prefix)) keys.push(key);\n }\n return keys;\n } catch {\n this.#degrade();\n return this.#fallback.keys(prefix);\n }\n }\n\n #degrade(): void {\n this.#storage = undefined;\n this.#fallback = new MemoryKeyValueStore<T>();\n }\n}\n\n/** JSON key-value backend поверх браузерного `localStorage` с откатом в память. */\nexport class LocalStorageKeyValueStore<T> {\n readonly #inner = new WebStorageKeyValueStore<T>('localStorage');\n\n get(key: string): T | undefined {\n return this.#inner.get(key);\n }\n\n set(key: string, value: T): void {\n this.#inner.set(key, value);\n }\n\n delete(key: string): void {\n this.#inner.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n return this.#inner.keys(prefix);\n }\n}\n\n/** JSON key-value backend поверх браузерного `sessionStorage` с откатом в память. */\nexport class SessionStorageKeyValueStore<T> {\n readonly #inner = new WebStorageKeyValueStore<T>('sessionStorage');\n\n get(key: string): T | undefined {\n return this.#inner.get(key);\n }\n\n set(key: string, value: T): void {\n this.#inner.set(key, value);\n }\n\n delete(key: string): void {\n this.#inner.delete(key);\n }\n\n keys(prefix = ''): Iterable<string> | AsyncIterable<string> {\n return this.#inner.keys(prefix);\n }\n}\n\n/**\n * Хранилище поверх `localStorage` браузера.\n *\n * Если `localStorage` недоступен (приватный режим, серверный рендеринг), молча работает\n * как хранилище в памяти — библиотека не должна падать из-за настроек браузера. Сессия\n * в этом случае теряется при перезагрузке страницы; когда это неприемлемо, проверьте\n * доступность сами или возьмите своё хранилище через `createTokenStorage`.\n *\n * Помните, что `localStorage` доступен любому скрипту на странице: не используйте его,\n * если для вашего приложения это неприемлемый риск.\n *\n * Повреждённый JSON считается ошибкой, а не отсутствующей сессией. После ошибки доступа,\n * записи или удаления хранилище переключается на память до конца\n * своего жизненного цикла.\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n readonly #inner: TokenStorage;\n\n /** @param key ключ в `localStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#inner = createTokenStorage(new LocalStorageKeyValueStore<ItdSession>(), { key });\n }\n\n get(): ItdSession | null {\n return this.#inner.get() as ItdSession | null;\n }\n\n set(session: ItdSession): void {\n void this.#inner.set(session);\n }\n\n clear(): void {\n void this.#inner.clear();\n }\n}\n\n/**\n * Хранилище сессии поверх браузерного `sessionStorage`.\n *\n * Данные переживают перезагрузку страницы, но существуют только в пределах текущей\n * browser page session. Если `sessionStorage` недоступен, экземпляр молча работает\n * в памяти; после ошибки доступа, записи или удаления он также остаётся в памяти до конца\n * своего жизненного цикла.\n * Повреждённый JSON считается ошибкой, а не отсутствующей сессией.\n *\n * Как и `localStorage`, это хранилище доступно скриптам страницы и не защищает сессию\n * от XSS. Выбирайте его ради более короткого срока жизни, а не ради изоляции секрета.\n */\nexport class SessionStorageTokenStorage implements TokenStorage {\n readonly #inner: TokenStorage;\n\n /** @param key ключ в `sessionStorage`. По умолчанию `itd-api:session`. */\n constructor(key = 'itd-api:session') {\n this.#inner = createTokenStorage(new SessionStorageKeyValueStore<ItdSession>(), { key });\n }\n\n get(): ItdSession | null {\n return this.#inner.get() as ItdSession | null;\n }\n\n set(session: ItdSession): void {\n void this.#inner.set(session);\n }\n\n clear(): void {\n void this.#inner.clear();\n }\n}\n"],"mappings":"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"}