all-you-need 0.2.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.
- package/README.md +51 -1
- package/README.ru.md +51 -1
- package/dist/chunk-BGE46IF6.js +391 -0
- package/dist/chunk-BGE46IF6.js.map +1 -0
- package/dist/{chunk-UEHYJUIE.cjs → chunk-DOV7CXCO.cjs} +165 -2
- package/dist/chunk-DOV7CXCO.cjs.map +1 -0
- package/dist/entities/index.cjs +18 -6
- package/dist/entities/index.d.cts +59 -1
- package/dist/entities/index.d.ts +59 -1
- package/dist/entities/index.js +1 -1
- package/dist/index.cjs +18 -6
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-B2PFOWEO.js +0 -231
- package/dist/chunk-B2PFOWEO.js.map +0 -1
- package/dist/chunk-UEHYJUIE.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -112,8 +112,9 @@ import type { DeepPartial, Nullable, Merge } from "all-you-need/types";
|
|
|
112
112
|
| `Stack<T>` | LIFO stack data structure |
|
|
113
113
|
| `TypedStorage` | Universal typed wrapper for `localStorage`/`sessionStorage` with prefix and TTL |
|
|
114
114
|
| `Logger` | Leveled logger with prefix, timestamp, and configurable log levels |
|
|
115
|
+
| `JwtAuthManager` | JWT auth manager for multiple backends — storage, expiration, headers, subscriptions |
|
|
115
116
|
|
|
116
|
-
Also exports types: `StorageOptions`, `TypedStorageConfig`, `LogLevel`, `LoggerOptions`.
|
|
117
|
+
Also exports types: `StorageOptions`, `TypedStorageConfig`, `LogLevel`, `LoggerOptions`, `JwtAuthTargetConfig`, `JwtAuthEvent`, `JwtPayload`, `JwtStorageAdapter`.
|
|
117
118
|
|
|
118
119
|
### `Result<T, E>`
|
|
119
120
|
|
|
@@ -243,6 +244,55 @@ logger.info("Server started");
|
|
|
243
244
|
logger.debug("This will be hidden"); // level is below "info"
|
|
244
245
|
```
|
|
245
246
|
|
|
247
|
+
### `JwtAuthManager`
|
|
248
|
+
|
|
249
|
+
Manages JWT authentication for multiple targets (e.g. multiple backends). Handles storage, expiration check, auth header injection, and subscriptions to auth changes.
|
|
250
|
+
|
|
251
|
+
| Method | Signature | Description |
|
|
252
|
+
|--------|-----------|-------------|
|
|
253
|
+
| `constructor` | `(config: { storage: JwtStorageAdapter; targets?: JwtAuthTargetConfig[] }) => JwtAuthManager` | Create manager with storage and optional targets |
|
|
254
|
+
| `registerTarget` | `(config: JwtAuthTargetConfig) => void` | Register a new auth target |
|
|
255
|
+
| `setToken` | `(targetId: string, token: string) => void` | Store token for a target |
|
|
256
|
+
| `getToken` | `(targetId: string) => string \| null` | Get token for a target |
|
|
257
|
+
| `removeToken` | `(targetId: string) => void` | Remove token for a target |
|
|
258
|
+
| `isAuthenticated` | `(targetId: string, leewaySeconds?: number) => boolean` | Check if target has valid non-expired token |
|
|
259
|
+
| `isExpired` | `(targetId: string, leewaySeconds?: number) => boolean` | Check if target's token is expired |
|
|
260
|
+
| `getAuthHeaders` | `(targetId: string) => Record<string, string> \| null` | Get headers for HTTP request |
|
|
261
|
+
| `getPayload` | `(targetId: string) => JwtPayload \| null` | Get decoded JWT payload |
|
|
262
|
+
| `subscribe` | `(targetId: string, callback: (event: JwtAuthEvent) => void) => () => void` | Subscribe to auth changes; returns unsubscribe function |
|
|
263
|
+
| `refreshToken` | `(targetId: string, token: string) => void` | Update token (emits `refresh` event) |
|
|
264
|
+
| `markExpired` | `(targetId: string) => void` | Mark token as expired (e.g. on 401 response) |
|
|
265
|
+
|
|
266
|
+
**Utilities:** `decodeJwtPayload(token)`, `isJwtExpired(token, leewaySeconds?)`
|
|
267
|
+
|
|
268
|
+
`JwtAuthEvent`: `{ type: 'login' \| 'logout' \| 'expired' \| 'refresh'; token?: string; payload?: JwtPayload }`
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { JwtAuthManager } from "all-you-need/entities";
|
|
272
|
+
|
|
273
|
+
const manager = new JwtAuthManager({
|
|
274
|
+
storage: localStorage,
|
|
275
|
+
targets: [
|
|
276
|
+
{ id: "api", storageKey: "jwt:api" },
|
|
277
|
+
{
|
|
278
|
+
id: "auth",
|
|
279
|
+
storageKey: "jwt:auth",
|
|
280
|
+
headerName: "X-Auth-Token",
|
|
281
|
+
headerFormat: (t) => t,
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
manager.subscribe("api", (event) => {
|
|
287
|
+
if (event.type === "logout") {
|
|
288
|
+
// redirect to login
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
manager.setToken("api", response.access_token);
|
|
293
|
+
const headers = manager.getAuthHeaders("api"); // { Authorization: "Bearer ..." }
|
|
294
|
+
```
|
|
295
|
+
|
|
246
296
|
## Utils
|
|
247
297
|
|
|
248
298
|
### String
|
package/README.ru.md
CHANGED
|
@@ -112,8 +112,9 @@ import type { DeepPartial, Nullable, Merge } from "all-you-need/types";
|
|
|
112
112
|
| `Stack<T>` | LIFO-стек |
|
|
113
113
|
| `TypedStorage` | Универсальная типизированная обёртка для хранилищ с префиксом и TTL |
|
|
114
114
|
| `Logger` | Логгер с уровнями, префиксом и таймстампом |
|
|
115
|
+
| `JwtAuthManager` | Менеджер JWT-авторизации для нескольких бэкендов — хранение, истечение, заголовки, подписки |
|
|
115
116
|
|
|
116
|
-
Также экспортирует типы: `StorageOptions`, `TypedStorageConfig`, `LogLevel`, `LoggerOptions`.
|
|
117
|
+
Также экспортирует типы: `StorageOptions`, `TypedStorageConfig`, `LogLevel`, `LoggerOptions`, `JwtAuthTargetConfig`, `JwtAuthEvent`, `JwtPayload`, `JwtStorageAdapter`.
|
|
117
118
|
|
|
118
119
|
### `Result<T, E>`
|
|
119
120
|
|
|
@@ -243,6 +244,55 @@ logger.info("Server started");
|
|
|
243
244
|
logger.debug("This will be hidden"); // уровень ниже "info"
|
|
244
245
|
```
|
|
245
246
|
|
|
247
|
+
### `JwtAuthManager`
|
|
248
|
+
|
|
249
|
+
Управляет JWT-авторизацией для нескольких целей (например, разных бэкендов). Хранение токенов, проверка истечения, формирование заголовков запросов, подписка на изменения авторизации.
|
|
250
|
+
|
|
251
|
+
| Метод | Сигнатура | Описание |
|
|
252
|
+
|-------|-----------|----------|
|
|
253
|
+
| `constructor` | `(config: { storage: JwtStorageAdapter; targets?: JwtAuthTargetConfig[] }) => JwtAuthManager` | Создать менеджер с хранилищем и опциональными целями |
|
|
254
|
+
| `registerTarget` | `(config: JwtAuthTargetConfig) => void` | Зарегистрировать новую цель авторизации |
|
|
255
|
+
| `setToken` | `(targetId: string, token: string) => void` | Сохранить токен для цели |
|
|
256
|
+
| `getToken` | `(targetId: string) => string \| null` | Получить токен для цели |
|
|
257
|
+
| `removeToken` | `(targetId: string) => void` | Удалить токен для цели |
|
|
258
|
+
| `isAuthenticated` | `(targetId: string, leewaySeconds?: number) => boolean` | Проверить наличие валидного неистёкшего токена |
|
|
259
|
+
| `isExpired` | `(targetId: string, leewaySeconds?: number) => boolean` | Проверить истечение токена |
|
|
260
|
+
| `getAuthHeaders` | `(targetId: string) => Record<string, string> \| null` | Получить заголовки для HTTP-запроса |
|
|
261
|
+
| `getPayload` | `(targetId: string) => JwtPayload \| null` | Получить декодированный JWT payload |
|
|
262
|
+
| `subscribe` | `(targetId: string, callback: (event: JwtAuthEvent) => void) => () => void` | Подписаться на изменения авторизации; возвращает функцию отписки |
|
|
263
|
+
| `refreshToken` | `(targetId: string, token: string) => void` | Обновить токен (событие `refresh`) |
|
|
264
|
+
| `markExpired` | `(targetId: string) => void` | Пометить токен как истёкший (например, при 401) |
|
|
265
|
+
|
|
266
|
+
**Утилиты:** `decodeJwtPayload(token)`, `isJwtExpired(token, leewaySeconds?)`
|
|
267
|
+
|
|
268
|
+
`JwtAuthEvent`: `{ type: 'login' \| 'logout' \| 'expired' \| 'refresh'; token?: string; payload?: JwtPayload }`
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { JwtAuthManager } from "all-you-need/entities";
|
|
272
|
+
|
|
273
|
+
const manager = new JwtAuthManager({
|
|
274
|
+
storage: localStorage,
|
|
275
|
+
targets: [
|
|
276
|
+
{ id: "api", storageKey: "jwt:api" },
|
|
277
|
+
{
|
|
278
|
+
id: "auth",
|
|
279
|
+
storageKey: "jwt:auth",
|
|
280
|
+
headerName: "X-Auth-Token",
|
|
281
|
+
headerFormat: (t) => t,
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
manager.subscribe("api", (event) => {
|
|
287
|
+
if (event.type === "logout") {
|
|
288
|
+
// редирект на логин
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
manager.setToken("api", response.access_token);
|
|
293
|
+
const headers = manager.getAuthHeaders("api"); // { Authorization: "Bearer ..." }
|
|
294
|
+
```
|
|
295
|
+
|
|
246
296
|
## Утилиты
|
|
247
297
|
|
|
248
298
|
### Строки
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// src/entities/Storage.ts
|
|
2
|
+
var TypedStorage = class {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.adapter = config.adapter;
|
|
5
|
+
this.prefix = config.prefix ?? "";
|
|
6
|
+
}
|
|
7
|
+
prefixKey(key) {
|
|
8
|
+
return this.prefix + key;
|
|
9
|
+
}
|
|
10
|
+
get(key) {
|
|
11
|
+
const raw = this.adapter.getItem(this.prefixKey(key));
|
|
12
|
+
if (raw === null) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const entry = JSON.parse(raw);
|
|
17
|
+
if (entry.expiresAt !== void 0 && Date.now() > entry.expiresAt) {
|
|
18
|
+
this.remove(key);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return entry.value;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
set(key, value, options) {
|
|
27
|
+
const entry = { value };
|
|
28
|
+
if (options?.ttl !== void 0) {
|
|
29
|
+
entry.expiresAt = Date.now() + options.ttl;
|
|
30
|
+
}
|
|
31
|
+
this.adapter.setItem(this.prefixKey(key), JSON.stringify(entry));
|
|
32
|
+
}
|
|
33
|
+
remove(key) {
|
|
34
|
+
this.adapter.removeItem(this.prefixKey(key));
|
|
35
|
+
}
|
|
36
|
+
clear() {
|
|
37
|
+
if (this.prefix === "") {
|
|
38
|
+
this.adapter.clear();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
for (let i = this.adapter.length - 1; i >= 0; i--) {
|
|
42
|
+
const key = this.adapter.key(i);
|
|
43
|
+
if (key !== null && key.startsWith(this.prefix)) {
|
|
44
|
+
this.adapter.removeItem(key);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
has(key) {
|
|
49
|
+
return this.get(key) !== null;
|
|
50
|
+
}
|
|
51
|
+
keys() {
|
|
52
|
+
const result = [];
|
|
53
|
+
for (let i = 0; i < this.adapter.length; i++) {
|
|
54
|
+
const key = this.adapter.key(i);
|
|
55
|
+
if (key !== null && key.startsWith(this.prefix)) {
|
|
56
|
+
result.push(key.slice(this.prefix.length));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// src/entities/Queue.ts
|
|
64
|
+
var Queue = class {
|
|
65
|
+
constructor() {
|
|
66
|
+
this.items = [];
|
|
67
|
+
}
|
|
68
|
+
enqueue(item) {
|
|
69
|
+
this.items.push(item);
|
|
70
|
+
}
|
|
71
|
+
dequeue() {
|
|
72
|
+
return this.items.shift();
|
|
73
|
+
}
|
|
74
|
+
peek() {
|
|
75
|
+
return this.items[0];
|
|
76
|
+
}
|
|
77
|
+
get size() {
|
|
78
|
+
return this.items.length;
|
|
79
|
+
}
|
|
80
|
+
get isEmpty() {
|
|
81
|
+
return this.items.length === 0;
|
|
82
|
+
}
|
|
83
|
+
clear() {
|
|
84
|
+
this.items = [];
|
|
85
|
+
}
|
|
86
|
+
toArray() {
|
|
87
|
+
return [...this.items];
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// src/entities/Stack.ts
|
|
92
|
+
var Stack = class {
|
|
93
|
+
constructor() {
|
|
94
|
+
this.items = [];
|
|
95
|
+
}
|
|
96
|
+
push(item) {
|
|
97
|
+
this.items.push(item);
|
|
98
|
+
}
|
|
99
|
+
pop() {
|
|
100
|
+
return this.items.pop();
|
|
101
|
+
}
|
|
102
|
+
peek() {
|
|
103
|
+
return this.items[this.items.length - 1];
|
|
104
|
+
}
|
|
105
|
+
get size() {
|
|
106
|
+
return this.items.length;
|
|
107
|
+
}
|
|
108
|
+
get isEmpty() {
|
|
109
|
+
return this.items.length === 0;
|
|
110
|
+
}
|
|
111
|
+
clear() {
|
|
112
|
+
this.items = [];
|
|
113
|
+
}
|
|
114
|
+
toArray() {
|
|
115
|
+
return [...this.items];
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// src/entities/Logger.ts
|
|
120
|
+
var LOG_LEVEL_PRIORITY = {
|
|
121
|
+
debug: 0,
|
|
122
|
+
info: 1,
|
|
123
|
+
warn: 2,
|
|
124
|
+
error: 3
|
|
125
|
+
};
|
|
126
|
+
var Logger = class {
|
|
127
|
+
constructor(options = {}) {
|
|
128
|
+
this.level = options.level ?? "debug";
|
|
129
|
+
this.prefix = options.prefix;
|
|
130
|
+
this.timestamp = options.timestamp ?? true;
|
|
131
|
+
}
|
|
132
|
+
debug(...args) {
|
|
133
|
+
this.log("debug", args);
|
|
134
|
+
}
|
|
135
|
+
info(...args) {
|
|
136
|
+
this.log("info", args);
|
|
137
|
+
}
|
|
138
|
+
warn(...args) {
|
|
139
|
+
this.log("warn", args);
|
|
140
|
+
}
|
|
141
|
+
error(...args) {
|
|
142
|
+
this.log("error", args);
|
|
143
|
+
}
|
|
144
|
+
log(level, args) {
|
|
145
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.level]) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const parts = [];
|
|
149
|
+
if (this.timestamp) {
|
|
150
|
+
parts.push(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
151
|
+
}
|
|
152
|
+
parts.push(`[${level.toUpperCase()}]`);
|
|
153
|
+
if (this.prefix) {
|
|
154
|
+
parts.push(`[${this.prefix}]`);
|
|
155
|
+
}
|
|
156
|
+
const method = level === "debug" ? "log" : level;
|
|
157
|
+
console[method](parts.join(" "), ...args);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// src/entities/Result.ts
|
|
162
|
+
var Result = class _Result {
|
|
163
|
+
constructor(_ok, _value) {
|
|
164
|
+
this._ok = _ok;
|
|
165
|
+
this._value = _value;
|
|
166
|
+
}
|
|
167
|
+
static ok(value) {
|
|
168
|
+
return new _Result(true, value);
|
|
169
|
+
}
|
|
170
|
+
static err(error) {
|
|
171
|
+
return new _Result(false, error);
|
|
172
|
+
}
|
|
173
|
+
isOk() {
|
|
174
|
+
return this._ok;
|
|
175
|
+
}
|
|
176
|
+
isErr() {
|
|
177
|
+
return !this._ok;
|
|
178
|
+
}
|
|
179
|
+
get value() {
|
|
180
|
+
if (!this._ok) {
|
|
181
|
+
throw new Error("Cannot get value of an Err result");
|
|
182
|
+
}
|
|
183
|
+
return this._value;
|
|
184
|
+
}
|
|
185
|
+
get error() {
|
|
186
|
+
if (this._ok) {
|
|
187
|
+
throw new Error("Cannot get error of an Ok result");
|
|
188
|
+
}
|
|
189
|
+
return this._value;
|
|
190
|
+
}
|
|
191
|
+
unwrap() {
|
|
192
|
+
if (!this._ok) {
|
|
193
|
+
throw this._value;
|
|
194
|
+
}
|
|
195
|
+
return this._value;
|
|
196
|
+
}
|
|
197
|
+
unwrapOr(defaultValue) {
|
|
198
|
+
if (this._ok) {
|
|
199
|
+
return this._value;
|
|
200
|
+
}
|
|
201
|
+
return defaultValue;
|
|
202
|
+
}
|
|
203
|
+
unwrapErr() {
|
|
204
|
+
if (this._ok) {
|
|
205
|
+
throw new Error("Called unwrapErr on an Ok result");
|
|
206
|
+
}
|
|
207
|
+
return this._value;
|
|
208
|
+
}
|
|
209
|
+
map(fn) {
|
|
210
|
+
if (this._ok) {
|
|
211
|
+
return _Result.ok(fn(this._value));
|
|
212
|
+
}
|
|
213
|
+
return _Result.err(this._value);
|
|
214
|
+
}
|
|
215
|
+
mapErr(fn) {
|
|
216
|
+
if (this._ok) {
|
|
217
|
+
return _Result.ok(this._value);
|
|
218
|
+
}
|
|
219
|
+
return _Result.err(fn(this._value));
|
|
220
|
+
}
|
|
221
|
+
flatMap(fn) {
|
|
222
|
+
if (this._ok) {
|
|
223
|
+
return fn(this._value);
|
|
224
|
+
}
|
|
225
|
+
return _Result.err(this._value);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// src/entities/JwtAuthManager.ts
|
|
230
|
+
var DEFAULT_HEADER_NAME = "Authorization";
|
|
231
|
+
var DEFAULT_HEADER_FORMAT = (token) => `Bearer ${token}`;
|
|
232
|
+
function base64UrlDecode(str) {
|
|
233
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
234
|
+
const pad = base64.length % 4;
|
|
235
|
+
if (pad) {
|
|
236
|
+
base64 += "=".repeat(4 - pad);
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
return atob(base64);
|
|
240
|
+
} catch {
|
|
241
|
+
return "";
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function decodeJwtPayload(token) {
|
|
245
|
+
const parts = token.split(".");
|
|
246
|
+
if (parts.length !== 3) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const payloadStr = base64UrlDecode(parts[1]);
|
|
251
|
+
if (!payloadStr) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
return JSON.parse(payloadStr);
|
|
255
|
+
} catch {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function isJwtExpired(token, leewaySeconds = 0) {
|
|
260
|
+
const payload = decodeJwtPayload(token);
|
|
261
|
+
if (!payload?.exp) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return Date.now() >= (payload.exp + leewaySeconds) * 1e3;
|
|
265
|
+
}
|
|
266
|
+
var JwtAuthManager = class {
|
|
267
|
+
constructor(config) {
|
|
268
|
+
this.targets = /* @__PURE__ */ new Map();
|
|
269
|
+
this.subscribers = /* @__PURE__ */ new Map();
|
|
270
|
+
this.defaultStorage = config.storage;
|
|
271
|
+
for (const target of config.targets ?? []) {
|
|
272
|
+
this.registerTarget(target);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
registerTarget(config) {
|
|
276
|
+
this.targets.set(config.id, config);
|
|
277
|
+
}
|
|
278
|
+
getStorage(targetId) {
|
|
279
|
+
const target = this.targets.get(targetId);
|
|
280
|
+
return target?.storage ?? this.defaultStorage;
|
|
281
|
+
}
|
|
282
|
+
getTarget(targetId) {
|
|
283
|
+
return this.targets.get(targetId);
|
|
284
|
+
}
|
|
285
|
+
notify(targetId, event) {
|
|
286
|
+
const callbacks = this.subscribers.get(targetId);
|
|
287
|
+
if (callbacks) {
|
|
288
|
+
for (const cb of callbacks) {
|
|
289
|
+
cb(event);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
setToken(targetId, token) {
|
|
294
|
+
const target = this.getTarget(targetId);
|
|
295
|
+
if (!target) {
|
|
296
|
+
throw new Error(`JwtAuthManager: target "${targetId}" is not registered`);
|
|
297
|
+
}
|
|
298
|
+
const storage = this.getStorage(targetId);
|
|
299
|
+
storage.setItem(target.storageKey, token);
|
|
300
|
+
const payload = decodeJwtPayload(token) ?? void 0;
|
|
301
|
+
this.notify(targetId, { type: "login", token, payload });
|
|
302
|
+
}
|
|
303
|
+
getToken(targetId) {
|
|
304
|
+
const target = this.getTarget(targetId);
|
|
305
|
+
if (!target) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
const storage = this.getStorage(targetId);
|
|
309
|
+
return storage.getItem(target.storageKey);
|
|
310
|
+
}
|
|
311
|
+
removeToken(targetId) {
|
|
312
|
+
const target = this.getTarget(targetId);
|
|
313
|
+
if (!target) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const storage = this.getStorage(targetId);
|
|
317
|
+
storage.removeItem(target.storageKey);
|
|
318
|
+
this.notify(targetId, { type: "logout" });
|
|
319
|
+
}
|
|
320
|
+
isAuthenticated(targetId, leewaySeconds = 0) {
|
|
321
|
+
const token = this.getToken(targetId);
|
|
322
|
+
if (!token) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
return !isJwtExpired(token, leewaySeconds);
|
|
326
|
+
}
|
|
327
|
+
isExpired(targetId, leewaySeconds = 0) {
|
|
328
|
+
const token = this.getToken(targetId);
|
|
329
|
+
if (!token) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
return isJwtExpired(token, leewaySeconds);
|
|
333
|
+
}
|
|
334
|
+
getAuthHeaders(targetId) {
|
|
335
|
+
const token = this.getToken(targetId);
|
|
336
|
+
if (!token) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
const target = this.getTarget(targetId);
|
|
340
|
+
if (!target) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
const headerName = target.headerName ?? DEFAULT_HEADER_NAME;
|
|
344
|
+
const headerFormat = target.headerFormat ?? DEFAULT_HEADER_FORMAT;
|
|
345
|
+
return {
|
|
346
|
+
[headerName]: headerFormat(token)
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
getPayload(targetId) {
|
|
350
|
+
const token = this.getToken(targetId);
|
|
351
|
+
if (!token) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return decodeJwtPayload(token);
|
|
355
|
+
}
|
|
356
|
+
subscribe(targetId, callback) {
|
|
357
|
+
const target = this.getTarget(targetId);
|
|
358
|
+
if (!target) {
|
|
359
|
+
throw new Error(`JwtAuthManager: target "${targetId}" is not registered`);
|
|
360
|
+
}
|
|
361
|
+
let callbacks = this.subscribers.get(targetId);
|
|
362
|
+
if (!callbacks) {
|
|
363
|
+
callbacks = /* @__PURE__ */ new Set();
|
|
364
|
+
this.subscribers.set(targetId, callbacks);
|
|
365
|
+
}
|
|
366
|
+
callbacks.add(callback);
|
|
367
|
+
return () => {
|
|
368
|
+
callbacks.delete(callback);
|
|
369
|
+
if (callbacks.size === 0) {
|
|
370
|
+
this.subscribers.delete(targetId);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
refreshToken(targetId, token) {
|
|
375
|
+
const target = this.getTarget(targetId);
|
|
376
|
+
if (!target) {
|
|
377
|
+
throw new Error(`JwtAuthManager: target "${targetId}" is not registered`);
|
|
378
|
+
}
|
|
379
|
+
const storage = this.getStorage(targetId);
|
|
380
|
+
storage.setItem(target.storageKey, token);
|
|
381
|
+
const payload = decodeJwtPayload(token) ?? void 0;
|
|
382
|
+
this.notify(targetId, { type: "refresh", token, payload });
|
|
383
|
+
}
|
|
384
|
+
markExpired(targetId) {
|
|
385
|
+
this.notify(targetId, { type: "expired" });
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
export { JwtAuthManager, Logger, Queue, Result, Stack, TypedStorage, decodeJwtPayload, isJwtExpired };
|
|
390
|
+
//# sourceMappingURL=chunk-BGE46IF6.js.map
|
|
391
|
+
//# sourceMappingURL=chunk-BGE46IF6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/entities/Storage.ts","../src/entities/Queue.ts","../src/entities/Stack.ts","../src/entities/Logger.ts","../src/entities/Result.ts","../src/entities/JwtAuthManager.ts"],"names":[],"mappings":"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","file":"chunk-BGE46IF6.js","sourcesContent":["interface StorageEntry<T> {\n value: T;\n expiresAt?: number;\n}\n\nexport interface StorageOptions {\n ttl?: number;\n}\n\nexport interface TypedStorageConfig {\n adapter: globalThis.Storage;\n prefix?: string;\n}\n\nexport class TypedStorage {\n private readonly adapter: globalThis.Storage;\n private readonly prefix: string;\n\n constructor(config: TypedStorageConfig) {\n this.adapter = config.adapter;\n this.prefix = config.prefix ?? \"\";\n }\n\n private prefixKey(key: string): string {\n return this.prefix + key;\n }\n\n get<T>(key: string): T | null {\n const raw = this.adapter.getItem(this.prefixKey(key));\n\n if (raw === null) {\n return null;\n }\n\n try {\n const entry: StorageEntry<T> = JSON.parse(raw);\n\n if (entry.expiresAt !== undefined && Date.now() > entry.expiresAt) {\n this.remove(key);\n\n return null;\n }\n\n return entry.value;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, options?: StorageOptions): void {\n const entry: StorageEntry<T> = { value };\n\n if (options?.ttl !== undefined) {\n entry.expiresAt = Date.now() + options.ttl;\n }\n\n this.adapter.setItem(this.prefixKey(key), JSON.stringify(entry));\n }\n\n remove(key: string): void {\n this.adapter.removeItem(this.prefixKey(key));\n }\n\n clear(): void {\n if (this.prefix === \"\") {\n this.adapter.clear();\n\n return;\n }\n\n for (let i = this.adapter.length - 1; i >= 0; i--) {\n const key = this.adapter.key(i);\n\n if (key !== null && key.startsWith(this.prefix)) {\n this.adapter.removeItem(key);\n }\n }\n }\n\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n keys(): string[] {\n const result: string[] = [];\n\n for (let i = 0; i < this.adapter.length; i++) {\n const key = this.adapter.key(i);\n\n if (key !== null && key.startsWith(this.prefix)) {\n result.push(key.slice(this.prefix.length));\n }\n }\n\n return result;\n }\n}\n","export class Queue<T> {\n private items: T[] = [];\n\n enqueue(item: T): void {\n this.items.push(item);\n }\n\n dequeue(): T | undefined {\n return this.items.shift();\n }\n\n peek(): T | undefined {\n return this.items[0];\n }\n\n get size(): number {\n return this.items.length;\n }\n\n get isEmpty(): boolean {\n return this.items.length === 0;\n }\n\n clear(): void {\n this.items = [];\n }\n\n toArray(): T[] {\n return [...this.items];\n }\n}\n","export class Stack<T> {\n private items: T[] = [];\n\n push(item: T): void {\n this.items.push(item);\n }\n\n pop(): T | undefined {\n return this.items.pop();\n }\n\n peek(): T | undefined {\n return this.items[this.items.length - 1];\n }\n\n get size(): number {\n return this.items.length;\n }\n\n get isEmpty(): boolean {\n return this.items.length === 0;\n }\n\n clear(): void {\n this.items = [];\n }\n\n toArray(): T[] {\n return [...this.items];\n }\n}\n","export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport interface LoggerOptions {\n level?: LogLevel;\n prefix?: string;\n timestamp?: boolean;\n}\n\nexport class Logger {\n private readonly level: LogLevel;\n private readonly prefix: string | undefined;\n private readonly timestamp: boolean;\n\n constructor(options: LoggerOptions = {}) {\n this.level = options.level ?? \"debug\";\n this.prefix = options.prefix;\n this.timestamp = options.timestamp ?? true;\n }\n\n debug(...args: unknown[]): void {\n this.log(\"debug\", args);\n }\n\n info(...args: unknown[]): void {\n this.log(\"info\", args);\n }\n\n warn(...args: unknown[]): void {\n this.log(\"warn\", args);\n }\n\n error(...args: unknown[]): void {\n this.log(\"error\", args);\n }\n\n private log(level: LogLevel, args: unknown[]): void {\n if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[this.level]) {\n return;\n }\n\n const parts: string[] = [];\n\n if (this.timestamp) {\n parts.push(`[${new Date().toISOString()}]`);\n }\n\n parts.push(`[${level.toUpperCase()}]`);\n\n if (this.prefix) {\n parts.push(`[${this.prefix}]`);\n }\n\n const method = level === \"debug\" ? \"log\" : level;\n console[method](parts.join(\" \"), ...args);\n }\n}\n","export class Result<T, E> {\n private constructor(\n private readonly _ok: boolean,\n private readonly _value: T | E,\n ) {}\n\n static ok<T>(value: T): Result<T, never> {\n return new Result<T, never>(true, value);\n }\n\n static err<E>(error: E): Result<never, E> {\n return new Result<never, E>(false, error);\n }\n\n isOk(): this is Result<T, never> {\n return this._ok;\n }\n\n isErr(): this is Result<never, E> {\n return !this._ok;\n }\n\n get value(): T {\n if (!this._ok) {\n throw new Error(\"Cannot get value of an Err result\");\n }\n\n return this._value as T;\n }\n\n get error(): E {\n if (this._ok) {\n throw new Error(\"Cannot get error of an Ok result\");\n }\n\n return this._value as E;\n }\n\n unwrap(): T {\n if (!this._ok) {\n throw this._value;\n }\n\n return this._value as T;\n }\n\n unwrapOr(defaultValue: T): T {\n if (this._ok) {\n return this._value as T;\n }\n\n return defaultValue;\n }\n\n unwrapErr(): E {\n if (this._ok) {\n throw new Error(\"Called unwrapErr on an Ok result\");\n }\n\n return this._value as E;\n }\n\n map<U>(fn: (value: T) => U): Result<U, E> {\n if (this._ok) {\n return Result.ok(fn(this._value as T));\n }\n\n return Result.err(this._value as E);\n }\n\n mapErr<F>(fn: (error: E) => F): Result<T, F> {\n if (this._ok) {\n return Result.ok(this._value as T);\n }\n\n return Result.err(fn(this._value as E));\n }\n\n flatMap<U>(fn: (value: T) => Result<U, E>): Result<U, E> {\n if (this._ok) {\n return fn(this._value as T);\n }\n\n return Result.err(this._value as E);\n }\n}\n","export interface JwtStorageAdapter {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n}\n\nexport type JwtAuthEvent =\n | { type: 'login'; token: string; payload?: JwtPayload }\n | { type: 'logout' }\n | { type: 'expired' }\n | { type: 'refresh'; token: string; payload?: JwtPayload }\n\nexport interface JwtPayload {\n exp?: number\n iat?: number\n sub?: string\n [key: string]: unknown\n}\n\nexport interface JwtAuthTargetConfig {\n id: string\n storageKey: string\n storage?: JwtStorageAdapter\n headerName?: string\n headerFormat?: (token: string) => string\n}\n\nconst DEFAULT_HEADER_NAME = 'Authorization'\nconst DEFAULT_HEADER_FORMAT = (token: string): string => `Bearer ${token}`\n\nfunction base64UrlDecode(str: string): string {\n let base64 = str.replace(/-/g, '+').replace(/_/g, '/')\n const pad = base64.length % 4\n\n if (pad) {\n base64 += '='.repeat(4 - pad)\n }\n\n try {\n return atob(base64)\n } catch {\n return ''\n }\n}\n\nexport function decodeJwtPayload(token: string): JwtPayload | null {\n const parts = token.split('.')\n\n if (parts.length !== 3) {\n return null\n }\n\n try {\n const payloadStr = base64UrlDecode(parts[1]!)\n\n if (!payloadStr) {\n return null\n }\n\n return JSON.parse(payloadStr) as JwtPayload\n } catch {\n return null\n }\n}\n\nexport function isJwtExpired(token: string, leewaySeconds = 0): boolean {\n const payload = decodeJwtPayload(token)\n\n if (!payload?.exp) {\n return false\n }\n\n return Date.now() >= (payload.exp + leewaySeconds) * 1000\n}\n\ntype JwtAuthCallback = (event: JwtAuthEvent) => void\n\nexport class JwtAuthManager {\n private readonly defaultStorage: JwtStorageAdapter\n private readonly targets = new Map<string, JwtAuthTargetConfig>()\n private readonly subscribers = new Map<string, Set<JwtAuthCallback>>()\n\n constructor(config: {\n storage: JwtStorageAdapter\n targets?: JwtAuthTargetConfig[]\n }) {\n this.defaultStorage = config.storage\n\n for (const target of config.targets ?? []) {\n this.registerTarget(target)\n }\n }\n\n registerTarget(config: JwtAuthTargetConfig): void {\n this.targets.set(config.id, config)\n }\n\n private getStorage(targetId: string): JwtStorageAdapter {\n const target = this.targets.get(targetId)\n\n return target?.storage ?? this.defaultStorage\n }\n\n private getTarget(targetId: string): JwtAuthTargetConfig | undefined {\n return this.targets.get(targetId)\n }\n\n private notify(targetId: string, event: JwtAuthEvent): void {\n const callbacks = this.subscribers.get(targetId)\n\n if (callbacks) {\n for (const cb of callbacks) {\n cb(event)\n }\n }\n }\n\n setToken(targetId: string, token: string): void {\n const target = this.getTarget(targetId)\n\n if (!target) {\n throw new Error(`JwtAuthManager: target \"${targetId}\" is not registered`)\n }\n\n const storage = this.getStorage(targetId)\n storage.setItem(target.storageKey, token)\n const payload = decodeJwtPayload(token) ?? undefined\n this.notify(targetId, { type: 'login', token, payload })\n }\n\n getToken(targetId: string): string | null {\n const target = this.getTarget(targetId)\n\n if (!target) {\n return null\n }\n\n const storage = this.getStorage(targetId)\n\n return storage.getItem(target.storageKey)\n }\n\n removeToken(targetId: string): void {\n const target = this.getTarget(targetId)\n\n if (!target) {\n return\n }\n\n const storage = this.getStorage(targetId)\n storage.removeItem(target.storageKey)\n this.notify(targetId, { type: 'logout' })\n }\n\n isAuthenticated(targetId: string, leewaySeconds = 0): boolean {\n const token = this.getToken(targetId)\n\n if (!token) {\n return false\n }\n\n return !isJwtExpired(token, leewaySeconds)\n }\n\n isExpired(targetId: string, leewaySeconds = 0): boolean {\n const token = this.getToken(targetId)\n\n if (!token) {\n return true\n }\n\n return isJwtExpired(token, leewaySeconds)\n }\n\n getAuthHeaders(targetId: string): Record<string, string> | null {\n const token = this.getToken(targetId)\n\n if (!token) {\n return null\n }\n\n const target = this.getTarget(targetId)\n\n if (!target) {\n return null\n }\n\n const headerName = target.headerName ?? DEFAULT_HEADER_NAME\n const headerFormat = target.headerFormat ?? DEFAULT_HEADER_FORMAT\n\n return {\n [headerName]: headerFormat(token),\n }\n }\n\n getPayload(targetId: string): JwtPayload | null {\n const token = this.getToken(targetId)\n\n if (!token) {\n return null\n }\n\n return decodeJwtPayload(token)\n }\n\n subscribe(targetId: string, callback: JwtAuthCallback): () => void {\n const target = this.getTarget(targetId)\n\n if (!target) {\n throw new Error(`JwtAuthManager: target \"${targetId}\" is not registered`)\n }\n\n let callbacks = this.subscribers.get(targetId)\n\n if (!callbacks) {\n callbacks = new Set()\n this.subscribers.set(targetId, callbacks)\n }\n\n callbacks.add(callback)\n\n return () => {\n callbacks!.delete(callback)\n\n if (callbacks!.size === 0) {\n this.subscribers.delete(targetId)\n }\n }\n }\n\n refreshToken(targetId: string, token: string): void {\n const target = this.getTarget(targetId)\n\n if (!target) {\n throw new Error(`JwtAuthManager: target \"${targetId}\" is not registered`)\n }\n\n const storage = this.getStorage(targetId)\n storage.setItem(target.storageKey, token)\n const payload = decodeJwtPayload(token) ?? undefined\n this.notify(targetId, { type: 'refresh', token, payload })\n }\n\n markExpired(targetId: string): void {\n this.notify(targetId, { type: 'expired' })\n }\n}\n"]}
|