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.
- package/README.md +3 -2
- package/dist/index.cjs +3329 -1795
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1640 -1092
- package/dist/index.d.ts +1640 -1092
- package/dist/index.js +3249 -1730
- package/dist/index.js.map +1 -1
- package/dist/{multi-storage-CyMe404l.js → multi-storage-B0r0AInH.js} +151 -281
- package/dist/multi-storage-B0r0AInH.js.map +1 -0
- package/dist/{multi-storage-BhcA2Izn.d.ts → multi-storage-CLqmzq07.d.ts} +14 -54
- package/dist/{multi-storage-D1keK2Op.cjs → multi-storage-mBuCOVZY.cjs} +188 -294
- package/dist/multi-storage-mBuCOVZY.cjs.map +1 -0
- package/dist/{multi-storage-NDqzRQcD.d.cts → multi-storage-s_PcWPGH.d.cts} +14 -54
- package/dist/node.cjs +62 -53
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +19 -5
- package/dist/node.d.ts +19 -5
- package/dist/node.js +62 -54
- package/dist/node.js.map +1 -1
- package/dist/{storage-D9tfHx7Z.js → storage-DWrK3Z4M.js} +201 -18
- package/dist/storage-DWrK3Z4M.js.map +1 -0
- package/dist/storage-Doe3lpFQ.d.cts +152 -0
- package/dist/storage-Doe3lpFQ.d.ts +152 -0
- package/dist/{storage-ycBqLBRB.cjs → storage-dF8Tio5y.cjs} +254 -17
- package/dist/storage-dF8Tio5y.cjs.map +1 -0
- package/dist/web.cjs +143 -40
- package/dist/web.cjs.map +1 -1
- package/dist/web.d.cts +40 -3
- package/dist/web.d.ts +40 -3
- package/dist/web.js +141 -41
- package/dist/web.js.map +1 -1
- package/package.json +3 -3
- package/dist/multi-storage-CyMe404l.js.map +0 -1
- package/dist/multi-storage-D1keK2Op.cjs.map +0 -1
- package/dist/runtime-CFEsf-jD.cjs +0 -185
- package/dist/runtime-CFEsf-jD.cjs.map +0 -1
- package/dist/runtime-DHxDn8gf.js +0 -126
- package/dist/runtime-DHxDn8gf.js.map +0 -1
- package/dist/storage-BjNRlkbE.d.cts +0 -82
- package/dist/storage-BjNRlkbE.d.ts +0 -82
- package/dist/storage-D9tfHx7Z.js.map +0 -1
- 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-
|
|
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
|
-
* Отдельная точка входа нужна не сборщику, а вам:
|
|
12
|
-
*
|
|
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
|
-
#
|
|
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.#
|
|
47
|
-
this.#available = require_runtime.hasLocalStorage();
|
|
144
|
+
this.#inner = require_storage.createTokenStorage(new LocalStorageKeyValueStore(), { key });
|
|
48
145
|
}
|
|
49
146
|
get() {
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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":["#
|
|
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-
|
|
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-
|
|
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 {
|
|
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
|
-
* Отдельная точка входа нужна не сборщику, а вам:
|
|
11
|
-
*
|
|
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
|
-
#
|
|
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.#
|
|
46
|
-
this.#available = hasLocalStorage();
|
|
143
|
+
this.#inner = createTokenStorage(new LocalStorageKeyValueStore(), { key });
|
|
47
144
|
}
|
|
48
145
|
get() {
|
|
49
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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":["#
|
|
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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"}
|