@iskra-bun/kv-kit 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @iskra-bun/kv-kit
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Initial public release.
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @iskra-bun/kv-kit
2
+
3
+ Key-Value store de Iskra con adaptadores intercambiables de Redis y memoria.
4
+
5
+ ## Instalacion
6
+
7
+ ```bash
8
+ bun add @iskra-bun/kv-kit @iskra-bun/core
9
+ ```
10
+
11
+ ## Uso rapido
12
+
13
+ ```typescript
14
+ import { App } from '@iskra-bun/core'
15
+ import { KVManager } from '@iskra-bun/kv-kit'
16
+
17
+ const app = new App({ name: 'mi-app' })
18
+ app.register(new KVManager({ adapter: 'memory' }))
19
+
20
+ await app.start()
21
+ ```
22
+
23
+ Cambia `adapter: 'redis'` para usar Redis en produccion; la API (`get`/`set`/`del`/`has`, TTL) es identica entre adaptadores.
24
+
25
+ ## Documentacion
26
+
27
+ Guia completa: [docs/kv-kit.md](../../docs/kv-kit.md)
28
+
29
+ ## Licencia
30
+
31
+ AGPL-3.0-or-later
@@ -0,0 +1,30 @@
1
+ import { Driver, App } from '@iskra-bun/core';
2
+
3
+ interface KVAdapter {
4
+ id: string;
5
+ connect(): Promise<void> | void;
6
+ disconnect(): Promise<void> | void;
7
+ get(key: string): Promise<any>;
8
+ set(key: string, value: any, ttl?: number): Promise<void>;
9
+ del(key: string): Promise<void>;
10
+ has(key: string): Promise<boolean>;
11
+ }
12
+
13
+ declare class KVManager implements Driver, KVAdapter {
14
+ name: string;
15
+ id: string;
16
+ private app;
17
+ private adapter;
18
+ constructor();
19
+ init(app: App): void;
20
+ connect(): Promise<void>;
21
+ disconnect(): Promise<void>;
22
+ start(): Promise<void>;
23
+ stop(): Promise<void>;
24
+ get(key: string): Promise<any>;
25
+ set(key: string, value: any, ttl?: number): Promise<void>;
26
+ del(key: string): Promise<void>;
27
+ has(key: string): Promise<boolean>;
28
+ }
29
+
30
+ export { type KVAdapter, KVManager };
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ // src/adapters/memory.ts
2
+ var MemoryAdapter = class {
3
+ id = "memory";
4
+ store = /* @__PURE__ */ new Map();
5
+ connect() {
6
+ }
7
+ disconnect() {
8
+ this.store.clear();
9
+ }
10
+ async get(key) {
11
+ return this.store.get(key);
12
+ }
13
+ async set(key, value, ttl) {
14
+ this.store.set(key, value);
15
+ if (ttl) {
16
+ setTimeout(() => this.store.delete(key), ttl * 1e3);
17
+ }
18
+ }
19
+ async del(key) {
20
+ this.store.delete(key);
21
+ }
22
+ async has(key) {
23
+ return this.store.has(key);
24
+ }
25
+ };
26
+
27
+ // src/adapters/redis.ts
28
+ import Redis from "ioredis";
29
+ var RedisAdapter = class {
30
+ id = "redis";
31
+ client = null;
32
+ options;
33
+ constructor(options) {
34
+ this.options = options;
35
+ }
36
+ connect() {
37
+ this.client = new Redis(this.options);
38
+ }
39
+ disconnect() {
40
+ this.client?.disconnect();
41
+ }
42
+ async get(key) {
43
+ const val = await this.client?.get(key);
44
+ try {
45
+ return val ? JSON.parse(val) : null;
46
+ } catch {
47
+ return val;
48
+ }
49
+ }
50
+ async set(key, value, ttl) {
51
+ const val = typeof value === "object" ? JSON.stringify(value) : value;
52
+ if (ttl) {
53
+ await this.client?.set(key, val, "EX", ttl);
54
+ } else {
55
+ await this.client?.set(key, val);
56
+ }
57
+ }
58
+ async del(key) {
59
+ await this.client?.del(key);
60
+ }
61
+ async has(key) {
62
+ const exists = await this.client?.exists(key);
63
+ return exists === 1;
64
+ }
65
+ };
66
+
67
+ // src/manager.ts
68
+ var KVManager = class {
69
+ name = "KVManager";
70
+ id = "manager";
71
+ app = null;
72
+ adapter;
73
+ constructor() {
74
+ this.adapter = new MemoryAdapter();
75
+ }
76
+ init(app) {
77
+ this.app = app;
78
+ const config = app.config.kv;
79
+ if (config?.driver === "redis") {
80
+ app.logger.info("Initializing KV with Redis");
81
+ this.adapter = new RedisAdapter(config.connection);
82
+ } else {
83
+ app.logger.info("Initializing KV with Memory");
84
+ this.adapter = new MemoryAdapter();
85
+ }
86
+ }
87
+ async connect() {
88
+ await this.adapter.connect();
89
+ this.app?.logger.info("KV Store connected");
90
+ }
91
+ async disconnect() {
92
+ await this.adapter.disconnect();
93
+ }
94
+ // Driver Interface
95
+ async start() {
96
+ await this.connect();
97
+ }
98
+ async stop() {
99
+ await this.disconnect();
100
+ }
101
+ // Proxy methods
102
+ get(key) {
103
+ return this.adapter.get(key);
104
+ }
105
+ set(key, value, ttl) {
106
+ return this.adapter.set(key, value, ttl);
107
+ }
108
+ del(key) {
109
+ return this.adapter.del(key);
110
+ }
111
+ has(key) {
112
+ return this.adapter.has(key);
113
+ }
114
+ };
115
+ export {
116
+ KVManager
117
+ };
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/memory.ts","../src/adapters/redis.ts","../src/manager.ts"],"sourcesContent":["import type { KVAdapter } from '../types';\n\nexport class MemoryAdapter implements KVAdapter {\n id = 'memory';\n private store = new Map<string, any>();\n\n connect() {\n // No-op\n }\n disconnect() {\n this.store.clear();\n }\n\n async get(key: string) {\n return this.store.get(key);\n }\n\n async set(key: string, value: any, ttl?: number) {\n this.store.set(key, value);\n if (ttl) {\n setTimeout(() => this.store.delete(key), ttl * 1000);\n }\n }\n\n async del(key: string) {\n this.store.delete(key);\n }\n\n async has(key: string) {\n return this.store.has(key);\n }\n}\n","import type { KVAdapter } from '../types';\nimport Redis from 'ioredis';\n\nexport class RedisAdapter implements KVAdapter {\n id = 'redis';\n private client: Redis | null = null;\n private options: any;\n\n constructor(options: any) {\n this.options = options;\n }\n\n connect() {\n this.client = new Redis(this.options);\n }\n\n disconnect() {\n this.client?.disconnect();\n }\n\n async get(key: string) {\n const val = await this.client?.get(key);\n try {\n return val ? JSON.parse(val) : null;\n } catch {\n return val;\n }\n }\n\n async set(key: string, value: any, ttl?: number) {\n const val = typeof value === 'object' ? JSON.stringify(value) : value;\n if (ttl) {\n await this.client?.set(key, val, 'EX', ttl);\n } else {\n await this.client?.set(key, val);\n }\n }\n\n async del(key: string) {\n await this.client?.del(key);\n }\n\n async has(key: string) {\n const exists = await this.client?.exists(key);\n return exists === 1;\n }\n}\n","import type { App, Driver } from '@iskra-bun/core';\nimport type { KVAdapter } from './types';\nimport { MemoryAdapter } from './adapters/memory';\nimport { RedisAdapter } from './adapters/redis';\n\nexport class KVManager implements Driver, KVAdapter {\n name = 'KVManager';\n id = 'manager';\n private app: App | null = null;\n private adapter: KVAdapter;\n\n constructor() {\n // Default to memory until configured\n this.adapter = new MemoryAdapter();\n }\n\n init(app: App) {\n this.app = app;\n const config = app.config.kv;\n\n if (config?.driver === 'redis') {\n app.logger.info('Initializing KV with Redis');\n this.adapter = new RedisAdapter(config.connection);\n } else {\n app.logger.info('Initializing KV with Memory');\n this.adapter = new MemoryAdapter();\n }\n }\n\n async connect() {\n await this.adapter.connect();\n this.app?.logger.info('KV Store connected');\n }\n\n async disconnect() {\n await this.adapter.disconnect();\n }\n\n // Driver Interface\n async start() {\n await this.connect();\n }\n\n async stop() {\n await this.disconnect();\n }\n\n // Proxy methods\n get(key: string) { return this.adapter.get(key); }\n set(key: string, value: any, ttl?: number) { return this.adapter.set(key, value, ttl); }\n del(key: string) { return this.adapter.del(key); }\n has(key: string) { return this.adapter.has(key); }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@iskra-bun/kv-kit",
3
+ "version": "0.1.0",
4
+ "description": "Key-Value store de Iskra con adaptadores de Redis y memoria.",
5
+ "keywords": [
6
+ "iskra",
7
+ "bun",
8
+ "typescript",
9
+ "redis",
10
+ "kv",
11
+ "key-value",
12
+ "cache"
13
+ ],
14
+ "author": "Joan Lascano",
15
+ "license": "AGPL-3.0-or-later",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/fearful/iskra.git",
19
+ "directory": "packages/kv-kit"
20
+ },
21
+ "homepage": "https://github.com/fearful/iskra/tree/main/packages/kv-kit#readme",
22
+ "bugs": "https://github.com/fearful/iskra/issues",
23
+ "type": "module",
24
+ "main": "./dist/index.js",
25
+ "module": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "source": "./src/index.ts",
30
+ "bun": "./src/index.ts",
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src",
39
+ "README.md",
40
+ "CHANGELOG.md"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "scripts": {
46
+ "test": "bun test",
47
+ "build": "tsup --config ../../tsup.config.ts"
48
+ },
49
+ "dependencies": {
50
+ "@iskra-bun/core": "0.1.0",
51
+ "ioredis": "^5.4.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/bun": "^1.3.5",
55
+ "@types/node": "^22.10.2"
56
+ }
57
+ }
@@ -0,0 +1,32 @@
1
+ import type { KVAdapter } from '../types';
2
+
3
+ export class MemoryAdapter implements KVAdapter {
4
+ id = 'memory';
5
+ private store = new Map<string, any>();
6
+
7
+ connect() {
8
+ // No-op
9
+ }
10
+ disconnect() {
11
+ this.store.clear();
12
+ }
13
+
14
+ async get(key: string) {
15
+ return this.store.get(key);
16
+ }
17
+
18
+ async set(key: string, value: any, ttl?: number) {
19
+ this.store.set(key, value);
20
+ if (ttl) {
21
+ setTimeout(() => this.store.delete(key), ttl * 1000);
22
+ }
23
+ }
24
+
25
+ async del(key: string) {
26
+ this.store.delete(key);
27
+ }
28
+
29
+ async has(key: string) {
30
+ return this.store.has(key);
31
+ }
32
+ }
@@ -0,0 +1,47 @@
1
+ import type { KVAdapter } from '../types';
2
+ import Redis from 'ioredis';
3
+
4
+ export class RedisAdapter implements KVAdapter {
5
+ id = 'redis';
6
+ private client: Redis | null = null;
7
+ private options: any;
8
+
9
+ constructor(options: any) {
10
+ this.options = options;
11
+ }
12
+
13
+ connect() {
14
+ this.client = new Redis(this.options);
15
+ }
16
+
17
+ disconnect() {
18
+ this.client?.disconnect();
19
+ }
20
+
21
+ async get(key: string) {
22
+ const val = await this.client?.get(key);
23
+ try {
24
+ return val ? JSON.parse(val) : null;
25
+ } catch {
26
+ return val;
27
+ }
28
+ }
29
+
30
+ async set(key: string, value: any, ttl?: number) {
31
+ const val = typeof value === 'object' ? JSON.stringify(value) : value;
32
+ if (ttl) {
33
+ await this.client?.set(key, val, 'EX', ttl);
34
+ } else {
35
+ await this.client?.set(key, val);
36
+ }
37
+ }
38
+
39
+ async del(key: string) {
40
+ await this.client?.del(key);
41
+ }
42
+
43
+ async has(key: string) {
44
+ const exists = await this.client?.exists(key);
45
+ return exists === 1;
46
+ }
47
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { KVManager } from './manager';
2
+ export type { KVAdapter } from './types';
package/src/manager.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type { App, Driver } from '@iskra-bun/core';
2
+ import type { KVAdapter } from './types';
3
+ import { MemoryAdapter } from './adapters/memory';
4
+ import { RedisAdapter } from './adapters/redis';
5
+
6
+ export class KVManager implements Driver, KVAdapter {
7
+ name = 'KVManager';
8
+ id = 'manager';
9
+ private app: App | null = null;
10
+ private adapter: KVAdapter;
11
+
12
+ constructor() {
13
+ // Default to memory until configured
14
+ this.adapter = new MemoryAdapter();
15
+ }
16
+
17
+ init(app: App) {
18
+ this.app = app;
19
+ const config = app.config.kv;
20
+
21
+ if (config?.driver === 'redis') {
22
+ app.logger.info('Initializing KV with Redis');
23
+ this.adapter = new RedisAdapter(config.connection);
24
+ } else {
25
+ app.logger.info('Initializing KV with Memory');
26
+ this.adapter = new MemoryAdapter();
27
+ }
28
+ }
29
+
30
+ async connect() {
31
+ await this.adapter.connect();
32
+ this.app?.logger.info('KV Store connected');
33
+ }
34
+
35
+ async disconnect() {
36
+ await this.adapter.disconnect();
37
+ }
38
+
39
+ // Driver Interface
40
+ async start() {
41
+ await this.connect();
42
+ }
43
+
44
+ async stop() {
45
+ await this.disconnect();
46
+ }
47
+
48
+ // Proxy methods
49
+ get(key: string) { return this.adapter.get(key); }
50
+ set(key: string, value: any, ttl?: number) { return this.adapter.set(key, value, ttl); }
51
+ del(key: string) { return this.adapter.del(key); }
52
+ has(key: string) { return this.adapter.has(key); }
53
+ }
package/src/types.ts ADDED
@@ -0,0 +1,10 @@
1
+ export interface KVAdapter {
2
+ id: string; // 'memory', 'redis', 'libsql'
3
+ connect(): Promise<void> | void;
4
+ disconnect(): Promise<void> | void;
5
+
6
+ get(key: string): Promise<any>;
7
+ set(key: string, value: any, ttl?: number): Promise<void>;
8
+ del(key: string): Promise<void>;
9
+ has(key: string): Promise<boolean>;
10
+ }