@nemigo/server 1.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/dist/jwt.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import type { IStorage } from "@nemigo/storage/types";
2
+ export interface JWToken<PayloadData> {
3
+ /**
4
+ * Полезная нагрузка токена
5
+ */
6
+ pld: PayloadData;
7
+ /**
8
+ * Когда станет инвалидным (в секундах)
9
+ */
10
+ exp: number;
11
+ /**
12
+ * Когда было создано (в секундах)
13
+ */
14
+ iat: number;
15
+ }
16
+ export interface ConstructJWT {
17
+ signature: string;
18
+ /**
19
+ * Когда станет инвалидным (в секундах)
20
+ */
21
+ expired?: number;
22
+ }
23
+ export declare class JWT<PayloadData, Storage extends IStorage = IStorage> {
24
+ storage: Storage;
25
+ ctx: ConstructJWT;
26
+ constructor(storage: Storage, ctx: ConstructJWT);
27
+ /**
28
+ *
29
+ * @param pld - Данные внутри токена
30
+ * @param expired - Когда станет инвалидным (в секундах)
31
+ */
32
+ generate(pld: PayloadData, expired?: number): string;
33
+ decode(token?: string | null): Promise<JWToken<PayloadData> | null>;
34
+ invalidate(token?: string | null): Promise<void>;
35
+ }
package/dist/jwt.js ADDED
@@ -0,0 +1,47 @@
1
+ import { MS_IN_DAY } from "@nemigo/helpers/datetime/delta";
2
+ import jwt from "jsonwebtoken";
3
+ //...
4
+ export class JWT {
5
+ storage;
6
+ ctx;
7
+ constructor(storage, ctx) {
8
+ this.storage = storage;
9
+ this.ctx = ctx;
10
+ }
11
+ /**
12
+ *
13
+ * @param pld - Данные внутри токена
14
+ * @param expired - Когда станет инвалидным (в секундах)
15
+ */
16
+ generate(pld, expired) {
17
+ return jwt.sign({ pld }, this.ctx.signature, { expiresIn: expired ?? this.ctx.expired ?? (10 * MS_IN_DAY) / 1000 });
18
+ }
19
+ async decode(token) {
20
+ try {
21
+ if (!token)
22
+ return null;
23
+ const invalidated = await this.storage.has(token);
24
+ if (invalidated)
25
+ return null;
26
+ return jwt.verify(token, this.ctx.signature);
27
+ }
28
+ catch (_) {
29
+ return null;
30
+ }
31
+ }
32
+ async invalidate(token) {
33
+ if (!token)
34
+ return;
35
+ const invalidated = await this.storage.has(token);
36
+ if (invalidated)
37
+ return;
38
+ const decoded = await this.decode(token);
39
+ if (decoded && decoded.exp) {
40
+ const now = Math.floor(Date.now() / 1000);
41
+ const remaining = decoded.exp - now;
42
+ if (remaining > 0) {
43
+ return this.storage.set(token, "INVALIDATED", { ttl_seconds: remaining });
44
+ }
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,25 @@
1
+ import type { IStorage, IStorageValue, IStorageSetOptions, IStoragePanic } from "@nemigo/storage/types";
2
+ import type { RedisClientType } from "@redis/client";
3
+ export interface ConstructRedisStorage {
4
+ client: RedisClientType;
5
+ panic?: IStoragePanic<boolean>;
6
+ prefix?: string;
7
+ ttl_seconds?: number;
8
+ }
9
+ export declare class RedisStorage implements IStorage<boolean> {
10
+ /**
11
+ * TTL хранилища для быстрого использования
12
+ */
13
+ ttl_seconds?: number;
14
+ prefix: string;
15
+ panic?: IStoragePanic<boolean>;
16
+ client: RedisClientType;
17
+ constructor(ctx: ConstructRedisStorage);
18
+ __toKey(name: string, prefix?: string): string;
19
+ has(name: string, prefix?: string): Promise<boolean>;
20
+ get<T extends IStorageValue>(name: string, prefix?: string): Promise<T | undefined>;
21
+ set(name: string, value: IStorageValue, options?: IStorageSetOptions & {
22
+ prefix?: string;
23
+ }): Promise<void>;
24
+ delete(name: string, prefix?: string): Promise<boolean>;
25
+ }
package/dist/redis.js ADDED
@@ -0,0 +1,58 @@
1
+ export class RedisStorage {
2
+ /**
3
+ * TTL хранилища для быстрого использования
4
+ */
5
+ ttl_seconds;
6
+ prefix;
7
+ panic;
8
+ client;
9
+ constructor(ctx) {
10
+ this.prefix = ctx.prefix ?? "";
11
+ this.ttl_seconds = ctx.ttl_seconds;
12
+ this.panic = ctx.panic;
13
+ this.client = ctx.client;
14
+ }
15
+ __toKey(name, prefix = this.prefix) {
16
+ return prefix + name;
17
+ }
18
+ async has(name, prefix) {
19
+ try {
20
+ const result = await this.client.exists(this.__toKey(name, prefix));
21
+ return result === 1;
22
+ }
23
+ catch (err) {
24
+ return this.panic?.onhas?.(err) ?? false;
25
+ }
26
+ }
27
+ async get(name, prefix) {
28
+ try {
29
+ const cached = await this.client.get(this.__toKey(name, prefix));
30
+ if (cached)
31
+ return JSON.parse(cached);
32
+ }
33
+ catch (err) {
34
+ return this.panic?.onget?.(err);
35
+ }
36
+ }
37
+ async set(name, value, options = {}) {
38
+ try {
39
+ const key = this.__toKey(name, options.prefix);
40
+ const result = await this.client.set(key, JSON.stringify(value), { EX: options.ttl_seconds });
41
+ if (result !== "OK")
42
+ return await this.panic?.onset?.(new Error(`Redis SET returned: ${result}`));
43
+ }
44
+ catch (error) {
45
+ return this.panic?.onset?.(error);
46
+ }
47
+ }
48
+ async delete(name, prefix) {
49
+ try {
50
+ const result = await this.client.del(this.__toKey(name, prefix));
51
+ // DEL возвращает количество удаленных ключей
52
+ return result > 0;
53
+ }
54
+ catch (err) {
55
+ return this.panic?.ondelete?.(err) ?? false;
56
+ }
57
+ }
58
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@nemigo/server",
3
+ "version": "1.5.0",
4
+ "private": false,
5
+ "author": {
6
+ "name": "Vlad Logvin",
7
+ "email": "vlad.logvin84@gmail.com"
8
+ },
9
+ "type": "module",
10
+ "engines": {
11
+ "node": ">=22",
12
+ "pnpm": ">=10.9.0"
13
+ },
14
+ "scripts": {
15
+ "build": "svelte-package && rimraf .svelte-kit",
16
+ "check": "tsc --noemit",
17
+ "lint": "eslint ./",
18
+ "format": "prettier --write ./"
19
+ },
20
+ "exports": {
21
+ "./jwt": {
22
+ "types": "./dist/jwt.d.ts",
23
+ "default": "./dist/jwt.js"
24
+ },
25
+ "./redis": {
26
+ "types": "./dist/redis.d.ts",
27
+ "default": "./dist/redis.js"
28
+ }
29
+ },
30
+ "peerDependencies": {
31
+ "@nemigo/helpers": ">=1.6.0",
32
+ "@nemigo/storage": ">=1.7.0"
33
+ },
34
+ "dependencies": {
35
+ "@redis/client": "5.9.0",
36
+ "@types/jsonwebtoken": "9.0.10",
37
+ "jsonwebtoken": "9.0.2"
38
+ },
39
+ "devDependencies": {
40
+ "@nemigo/configs": "workspace:*",
41
+ "@nemigo/helpers": "workspace:*",
42
+ "@nemigo/storage": "workspace:*"
43
+ }
44
+ }