@firela/runtime-adapters 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 fire-la
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @firela/runtime-adapters
2
+
3
+ Platform-agnostic runtime adapters for Cloudflare Workers, Node.js, and edge runtimes.
4
+
5
+ ## Overview
6
+
7
+ This package provides a unified abstraction layer for runtime-specific capabilities, allowing your code to run seamlessly across different JavaScript environments:
8
+
9
+ - **Cloudflare Workers** - KV storage, Web Crypto API
10
+ - **Node.js** - File-based storage, Node crypto module
11
+ - **Edge runtimes** - Any environment implementing the adapter interfaces
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @firela/runtime-adapters
17
+ # or
18
+ pnpm add @firela/runtime-adapters
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### Cloudflare Workers
24
+
25
+ ```typescript
26
+ import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
27
+
28
+ export default {
29
+ async fetch(request, env, ctx) {
30
+ const adapter = createCloudflareAdapter(env)
31
+
32
+ // Use KV store
33
+ await adapter.kv.set('session:abc', { userId: 'user1' }, { ttl: 3600000 })
34
+
35
+ // Use crypto
36
+ const signature = await adapter.crypto.hmacSha256('payload', 'secret')
37
+
38
+ // Log messages
39
+ adapter.logger.info('Request processed')
40
+
41
+ return new Response('OK')
42
+ }
43
+ }
44
+ ```
45
+
46
+ ### Node.js
47
+
48
+ ```typescript
49
+ import { createNodeAdapter } from '@firela/runtime-adapters/node'
50
+
51
+ const adapter = createNodeAdapter()
52
+
53
+ // Use in-memory KV store (useful for development/testing)
54
+ await adapter.kv.set('key', 'value')
55
+
56
+ // Use Node.js crypto
57
+ const bytes = adapter.crypto.randomBytes(16)
58
+
59
+ // Console logging
60
+ adapter.logger.info('Application started')
61
+ ```
62
+
63
+ ## API Reference
64
+
65
+ ### Types
66
+
67
+ ```typescript
68
+ interface KVStore {
69
+ get<T = unknown>(key: string): Promise<T | null>
70
+ set<T>(key: string, value: T, options?: { ttl?: number }): Promise<void>
71
+ delete(key: string): Promise<boolean>
72
+ }
73
+
74
+ interface CryptoAdapter {
75
+ hmacSha256(data: string, secret: string): Promise<string>
76
+ randomBytes(length: number): Uint8Array
77
+ }
78
+
79
+ interface Logger {
80
+ debug(message: string, ...args: unknown[]): void
81
+ info(message: string, ...args: unknown[]): void
82
+ warn(message: string, ...args: unknown[]): void
83
+ error(message: string, ...args: unknown[]): void
84
+ }
85
+
86
+ interface RuntimeAdapter {
87
+ kv: KVStore
88
+ crypto: CryptoAdapter
89
+ logger: Logger
90
+ platform: string
91
+ }
92
+ ```
93
+
94
+ ### Cloudflare Adapter
95
+
96
+ ```typescript
97
+ import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
98
+
99
+ const adapter = createCloudflareAdapter(env, 'KV') // 'KV' is the default namespace
100
+ ```
101
+
102
+ **Features:**
103
+ - `CloudflareKVStore` - Wraps KVNamespace for key-value storage
104
+ - `CloudflareCryptoAdapter` - Uses Web Crypto API
105
+ - `ConsoleLogger` - Console-based logging
106
+
107
+ ### Node.js Adapter
108
+
109
+ ```typescript
110
+ import { createNodeAdapter } from '@firela/runtime-adapters/node'
111
+
112
+ const adapter = createNodeAdapter()
113
+ ```
114
+
115
+ **Features:**
116
+ - `MemoryKVStore` - In-memory key-value storage (useful for development)
117
+ - `NodeCryptoAdapter` - Uses Node.js crypto module
118
+ - `ConsoleLogger` - Console-based logging
119
+
120
+ ## Usage Examples
121
+
122
+ ### Rate Limiting with KV Storage
123
+
124
+ ```typescript
125
+ import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
126
+
127
+ const adapter = createCloudflareAdapter(env)
128
+
129
+ async function checkRateLimit(key: string, limit: number, windowMs: number): Promise<boolean> {
130
+ const count = await adapter.kv.get<number>(key) || 0
131
+
132
+ if (count >= limit) {
133
+ return false
134
+ }
135
+
136
+ await adapter.kv.set(key, count + 1, { ttl: windowMs })
137
+ return true
138
+ }
139
+ ```
140
+
141
+ ### HMAC Signature Verification
142
+
143
+ ```typescript
144
+ import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
145
+
146
+ const adapter = createCloudflareAdapter(env)
147
+
148
+ async function verifySignature(payload: string, signature: string, secret: string): Promise<boolean> {
149
+ const expected = await adapter.crypto.hmacSha256(payload, secret)
150
+ return expected === signature
151
+ }
152
+ ```
153
+
154
+ ## License
155
+
156
+ MIT
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Cloudflare Workers Runtime Adapter
3
+ *
4
+ * Provides RuntimeAdapter implementation for Cloudflare Workers environment:
5
+ * - KVNamespace for KVStore
6
+ * - Web Crypto API for CryptoAdapter
7
+ * - Console for Logger
8
+ */
9
+ import type { KVStore, CryptoAdapter, Logger, RuntimeAdapter } from './types.js';
10
+ /**
11
+ * CloudflareKVStore - KVNamespace wrapper implementing KVStore interface
12
+ *
13
+ * Uses Cloudflare KV for persistent storage with TTL support.
14
+ */
15
+ export declare class CloudflareKVStore implements KVStore {
16
+ private kv;
17
+ constructor(kv: KVNamespace);
18
+ get<T = unknown>(key: string): Promise<T | null>;
19
+ set<T>(key: string, value: T, options?: {
20
+ ttl?: number;
21
+ }): Promise<void>;
22
+ delete(key: string): Promise<boolean>;
23
+ }
24
+ /**
25
+ * CloudflareCryptoAdapter - Web Crypto API implementation
26
+ *
27
+ * Uses the Web Crypto API available in Cloudflare Workers.
28
+ */
29
+ export declare class CloudflareCryptoAdapter implements CryptoAdapter {
30
+ hmacSha256(data: string, secret: string): Promise<string>;
31
+ randomBytes(length: number): Uint8Array;
32
+ }
33
+ /**
34
+ * ConsoleLogger - Console-based logger for Cloudflare Workers
35
+ */
36
+ export declare class ConsoleLogger implements Logger {
37
+ debug(message: string, ...args: unknown[]): void;
38
+ info(message: string, ...args: unknown[]): void;
39
+ warn(message: string, ...args: unknown[]): void;
40
+ error(message: string, ...args: unknown[]): void;
41
+ }
42
+ /**
43
+ * Cloudflare environment bindings type
44
+ *
45
+ * Extend this interface to include your specific bindings.
46
+ */
47
+ export interface CloudflareEnv {
48
+ /** Cloudflare KV namespace binding */
49
+ KV?: KVNamespace;
50
+ }
51
+ /**
52
+ * Create a RuntimeAdapter for Cloudflare Workers
53
+ *
54
+ * @param env - Cloudflare environment bindings (includes KV namespace)
55
+ * @param kvNamespace - Optional KV namespace name (defaults to 'KV')
56
+ * @returns RuntimeAdapter instance configured for Cloudflare Workers
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
61
+ *
62
+ * export default {
63
+ * async fetch(request, env, ctx) {
64
+ * const adapter = createCloudflareAdapter(env)
65
+ *
66
+ * // Use KV store
67
+ * await adapter.kv.set('session:abc', { userId: 'user1' }, { ttl: 3600000 })
68
+ *
69
+ * // Use crypto
70
+ * const signature = await adapter.crypto.hmacSha256('payload', 'secret')
71
+ *
72
+ * return new Response('OK')
73
+ * }
74
+ * }
75
+ * ```
76
+ */
77
+ export declare function createCloudflareAdapter(env: CloudflareEnv, kvNamespace?: string): RuntimeAdapter;
78
+ export type { KVStore, CryptoAdapter, Logger, RuntimeAdapter } from './types.js';
79
+ //# sourceMappingURL=cloudflare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../src/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhF;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IACnC,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,WAAW;IAE7B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKhD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAO5C;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,YAAW,aAAa;IACrD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB/D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;CAKxC;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,MAAM;IAC1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGjD;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,EAAE,CAAC,EAAE,WAAW,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,aAAa,EAClB,WAAW,GAAE,MAAa,GACzB,cAAc,CAchB;AAGD,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Cloudflare Workers Runtime Adapter
3
+ *
4
+ * Provides RuntimeAdapter implementation for Cloudflare Workers environment:
5
+ * - KVNamespace for KVStore
6
+ * - Web Crypto API for CryptoAdapter
7
+ * - Console for Logger
8
+ */
9
+ /**
10
+ * CloudflareKVStore - KVNamespace wrapper implementing KVStore interface
11
+ *
12
+ * Uses Cloudflare KV for persistent storage with TTL support.
13
+ */
14
+ export class CloudflareKVStore {
15
+ kv;
16
+ constructor(kv) {
17
+ this.kv = kv;
18
+ }
19
+ async get(key) {
20
+ const value = await this.kv.get(key, 'json');
21
+ return value;
22
+ }
23
+ async set(key, value, options) {
24
+ if (options?.ttl !== undefined) {
25
+ // Convert ms to seconds for Cloudflare KV expirationTtl
26
+ const expirationTtl = Math.floor(options.ttl / 1000);
27
+ await this.kv.put(key, JSON.stringify(value), { expirationTtl });
28
+ }
29
+ else {
30
+ await this.kv.put(key, JSON.stringify(value));
31
+ }
32
+ }
33
+ async delete(key) {
34
+ // Cloudflare KV delete doesn't return whether key existed
35
+ // We check first to provide consistent interface
36
+ const exists = await this.kv.get(key) !== null;
37
+ await this.kv.delete(key);
38
+ return exists;
39
+ }
40
+ }
41
+ /**
42
+ * CloudflareCryptoAdapter - Web Crypto API implementation
43
+ *
44
+ * Uses the Web Crypto API available in Cloudflare Workers.
45
+ */
46
+ export class CloudflareCryptoAdapter {
47
+ async hmacSha256(data, secret) {
48
+ const encoder = new TextEncoder();
49
+ const keyData = encoder.encode(secret);
50
+ // Import the secret key
51
+ const key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
52
+ // Sign the data
53
+ const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(data));
54
+ // Convert to base64
55
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
56
+ }
57
+ randomBytes(length) {
58
+ const bytes = new Uint8Array(length);
59
+ crypto.getRandomValues(bytes);
60
+ return bytes;
61
+ }
62
+ }
63
+ /**
64
+ * ConsoleLogger - Console-based logger for Cloudflare Workers
65
+ */
66
+ export class ConsoleLogger {
67
+ debug(message, ...args) {
68
+ console.debug(message, ...args);
69
+ }
70
+ info(message, ...args) {
71
+ console.info(message, ...args);
72
+ }
73
+ warn(message, ...args) {
74
+ console.warn(message, ...args);
75
+ }
76
+ error(message, ...args) {
77
+ console.error(message, ...args);
78
+ }
79
+ }
80
+ /**
81
+ * Create a RuntimeAdapter for Cloudflare Workers
82
+ *
83
+ * @param env - Cloudflare environment bindings (includes KV namespace)
84
+ * @param kvNamespace - Optional KV namespace name (defaults to 'KV')
85
+ * @returns RuntimeAdapter instance configured for Cloudflare Workers
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
90
+ *
91
+ * export default {
92
+ * async fetch(request, env, ctx) {
93
+ * const adapter = createCloudflareAdapter(env)
94
+ *
95
+ * // Use KV store
96
+ * await adapter.kv.set('session:abc', { userId: 'user1' }, { ttl: 3600000 })
97
+ *
98
+ * // Use crypto
99
+ * const signature = await adapter.crypto.hmacSha256('payload', 'secret')
100
+ *
101
+ * return new Response('OK')
102
+ * }
103
+ * }
104
+ * ```
105
+ */
106
+ export function createCloudflareAdapter(env, kvNamespace = 'KV') {
107
+ // Get KV namespace from env
108
+ const kv = env[kvNamespace];
109
+ if (!kv) {
110
+ throw new Error(`KV namespace '${kvNamespace}' not found in environment bindings`);
111
+ }
112
+ return {
113
+ kv: new CloudflareKVStore(kv),
114
+ logger: new ConsoleLogger(),
115
+ platform: 'cloudflare',
116
+ crypto: new CloudflareCryptoAdapter(),
117
+ };
118
+ }
119
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../src/cloudflare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @firela/runtime-adapters - Platform-agnostic runtime abstraction
3
+ *
4
+ * This package provides interfaces and implementations for abstracting
5
+ * platform-specific capabilities across different runtime environments.
6
+ *
7
+ * ## Available Adapters
8
+ *
9
+ * - **Cloudflare Workers**: `import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'`
10
+ * - **Node.js**: `import { createNodeAdapter } from '@firela/runtime-adapters/node'`
11
+ *
12
+ * ## Usage
13
+ *
14
+ * ```typescript
15
+ * // For Cloudflare Workers
16
+ * import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
17
+ *
18
+ * export default {
19
+ * async fetch(request, env) {
20
+ * const adapter = createCloudflareAdapter(env)
21
+ * await adapter.kv.set('key', 'value')
22
+ * return new Response('OK')
23
+ * }
24
+ * }
25
+ *
26
+ * // For Node.js
27
+ * import { createNodeAdapter } from '@firela/runtime-adapters/node'
28
+ *
29
+ * const adapter = createNodeAdapter()
30
+ * await adapter.kv.set('key', 'value')
31
+ * ```
32
+ */
33
+ export type { KVStore, CryptoAdapter, Logger, RuntimeAdapter } from './types.js';
34
+ export { createCloudflareAdapter, CloudflareKVStore, CloudflareCryptoAdapter } from './cloudflare.js';
35
+ export { createNodeAdapter, MemoryKVStore, NodeCryptoAdapter, ConsoleLogger } from './node.js';
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAGhF,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AACrG,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @firela/runtime-adapters - Platform-agnostic runtime abstraction
3
+ *
4
+ * This package provides interfaces and implementations for abstracting
5
+ * platform-specific capabilities across different runtime environments.
6
+ *
7
+ * ## Available Adapters
8
+ *
9
+ * - **Cloudflare Workers**: `import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'`
10
+ * - **Node.js**: `import { createNodeAdapter } from '@firela/runtime-adapters/node'`
11
+ *
12
+ * ## Usage
13
+ *
14
+ * ```typescript
15
+ * // For Cloudflare Workers
16
+ * import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
17
+ *
18
+ * export default {
19
+ * async fetch(request, env) {
20
+ * const adapter = createCloudflareAdapter(env)
21
+ * await adapter.kv.set('key', 'value')
22
+ * return new Response('OK')
23
+ * }
24
+ * }
25
+ *
26
+ * // For Node.js
27
+ * import { createNodeAdapter } from '@firela/runtime-adapters/node'
28
+ *
29
+ * const adapter = createNodeAdapter()
30
+ * await adapter.kv.set('key', 'value')
31
+ * ```
32
+ */
33
+ // Re-export adapters for convenience (sub-path exports recommended)
34
+ export { createCloudflareAdapter, CloudflareKVStore, CloudflareCryptoAdapter } from './cloudflare.js';
35
+ export { createNodeAdapter, MemoryKVStore, NodeCryptoAdapter, ConsoleLogger } from './node.js';
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,oEAAoE;AACpE,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AACrG,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Node.js Runtime Adapter
3
+ *
4
+ * Provides RuntimeAdapter implementation for Node.js environment:
5
+ * - In-memory Map for KVStore (MemoryKVStore)
6
+ * - Node.js crypto module for CryptoAdapter
7
+ * - Console for Logger
8
+ */
9
+ import type { KVStore, CryptoAdapter, Logger, RuntimeAdapter } from './types.js';
10
+ /**
11
+ * MemoryKVStore - In-memory KVStore implementation
12
+ *
13
+ * Stores values in a Map with optional TTL support.
14
+ * Note: Data is not persisted and is lost on process restart.
15
+ */
16
+ export declare class MemoryKVStore implements KVStore {
17
+ private store;
18
+ get<T = unknown>(key: string): Promise<T | null>;
19
+ set<T>(key: string, value: T, options?: {
20
+ ttl?: number;
21
+ }): Promise<void>;
22
+ delete(key: string): Promise<boolean>;
23
+ /**
24
+ * Clear all entries (useful for testing)
25
+ */
26
+ clear(): void;
27
+ /**
28
+ * Get number of entries (useful for testing)
29
+ */
30
+ get size(): number;
31
+ }
32
+ /**
33
+ * NodeCryptoAdapter - Node.js crypto module implementation
34
+ *
35
+ * Uses the built-in node:crypto module for cryptographic operations.
36
+ */
37
+ export declare class NodeCryptoAdapter implements CryptoAdapter {
38
+ hmacSha256(data: string, secret: string): Promise<string>;
39
+ randomBytes(length: number): Uint8Array;
40
+ }
41
+ /**
42
+ * ConsoleLogger - Console-based logger for Node.js
43
+ */
44
+ export declare class ConsoleLogger implements Logger {
45
+ debug(message: string, ...args: unknown[]): void;
46
+ info(message: string, ...args: unknown[]): void;
47
+ warn(message: string, ...args: unknown[]): void;
48
+ error(message: string, ...args: unknown[]): void;
49
+ }
50
+ /**
51
+ * Create a RuntimeAdapter for Node.js
52
+ *
53
+ * @param kv - Optional KVStore instance (defaults to MemoryKVStore)
54
+ * @param logger - Optional Logger instance (defaults to ConsoleLogger)
55
+ * @returns RuntimeAdapter instance configured for Node.js
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { createNodeAdapter, MemoryKVStore } from '@firela/runtime-adapters/node'
60
+ *
61
+ * // Create adapter with default in-memory KV store
62
+ * const adapter = createNodeAdapter()
63
+ *
64
+ * // Or with custom KV store
65
+ * const customKV = new MemoryKVStore()
66
+ * const adapter = createNodeAdapter({ kv: customKV })
67
+ *
68
+ * // Use KV store
69
+ * await adapter.kv.set('session:abc', { userId: 'user1' }, { ttl: 3600000 })
70
+ *
71
+ * // Use crypto
72
+ * const signature = await adapter.crypto.hmacSha256('payload', 'secret')
73
+ * ```
74
+ */
75
+ export declare function createNodeAdapter(options?: {
76
+ kv?: KVStore;
77
+ logger?: Logger;
78
+ }): RuntimeAdapter;
79
+ export type { KVStore, CryptoAdapter, Logger, RuntimeAdapter } from './types.js';
80
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhF;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,KAAK,CAA4D;IAEnE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAgBhD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM/D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;CAGxC;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,MAAM;IAC1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAIhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE;IAC1C,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,cAAc,CAOjB;AAGD,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
package/dist/node.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Node.js Runtime Adapter
3
+ *
4
+ * Provides RuntimeAdapter implementation for Node.js environment:
5
+ * - In-memory Map for KVStore (MemoryKVStore)
6
+ * - Node.js crypto module for CryptoAdapter
7
+ * - Console for Logger
8
+ */
9
+ import crypto from 'node:crypto';
10
+ /**
11
+ * MemoryKVStore - In-memory KVStore implementation
12
+ *
13
+ * Stores values in a Map with optional TTL support.
14
+ * Note: Data is not persisted and is lost on process restart.
15
+ */
16
+ export class MemoryKVStore {
17
+ store = new Map();
18
+ async get(key) {
19
+ const entry = this.store.get(key);
20
+ if (!entry) {
21
+ return null;
22
+ }
23
+ // Check TTL expiration
24
+ if (entry.expiresAt !== undefined && Date.now() > entry.expiresAt) {
25
+ this.store.delete(key);
26
+ return null;
27
+ }
28
+ return entry.value;
29
+ }
30
+ async set(key, value, options) {
31
+ const entry = { value };
32
+ if (options?.ttl !== undefined) {
33
+ entry.expiresAt = Date.now() + options.ttl;
34
+ }
35
+ this.store.set(key, entry);
36
+ }
37
+ async delete(key) {
38
+ return this.store.delete(key);
39
+ }
40
+ /**
41
+ * Clear all entries (useful for testing)
42
+ */
43
+ clear() {
44
+ this.store.clear();
45
+ }
46
+ /**
47
+ * Get number of entries (useful for testing)
48
+ */
49
+ get size() {
50
+ return this.store.size;
51
+ }
52
+ }
53
+ /**
54
+ * NodeCryptoAdapter - Node.js crypto module implementation
55
+ *
56
+ * Uses the built-in node:crypto module for cryptographic operations.
57
+ */
58
+ export class NodeCryptoAdapter {
59
+ async hmacSha256(data, secret) {
60
+ const hmac = crypto.createHmac('sha256', secret);
61
+ hmac.update(data);
62
+ return hmac.digest('base64');
63
+ }
64
+ randomBytes(length) {
65
+ return crypto.randomBytes(length);
66
+ }
67
+ }
68
+ /**
69
+ * ConsoleLogger - Console-based logger for Node.js
70
+ */
71
+ export class ConsoleLogger {
72
+ debug(message, ...args) {
73
+ console.debug(message, ...args);
74
+ }
75
+ info(message, ...args) {
76
+ console.info(message, ...args);
77
+ }
78
+ warn(message, ...args) {
79
+ console.warn(message, ...args);
80
+ }
81
+ error(message, ...args) {
82
+ console.error(message, ...args);
83
+ }
84
+ }
85
+ /**
86
+ * Create a RuntimeAdapter for Node.js
87
+ *
88
+ * @param kv - Optional KVStore instance (defaults to MemoryKVStore)
89
+ * @param logger - Optional Logger instance (defaults to ConsoleLogger)
90
+ * @returns RuntimeAdapter instance configured for Node.js
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * import { createNodeAdapter, MemoryKVStore } from '@firela/runtime-adapters/node'
95
+ *
96
+ * // Create adapter with default in-memory KV store
97
+ * const adapter = createNodeAdapter()
98
+ *
99
+ * // Or with custom KV store
100
+ * const customKV = new MemoryKVStore()
101
+ * const adapter = createNodeAdapter({ kv: customKV })
102
+ *
103
+ * // Use KV store
104
+ * await adapter.kv.set('session:abc', { userId: 'user1' }, { ttl: 3600000 })
105
+ *
106
+ * // Use crypto
107
+ * const signature = await adapter.crypto.hmacSha256('payload', 'secret')
108
+ * ```
109
+ */
110
+ export function createNodeAdapter(options) {
111
+ return {
112
+ kv: options?.kv ?? new MemoryKVStore(),
113
+ logger: options?.logger ?? new ConsoleLogger(),
114
+ platform: 'node',
115
+ crypto: new NodeCryptoAdapter(),
116
+ };
117
+ }
118
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * RuntimeAdapter Types - Platform-agnostic runtime abstraction
3
+ *
4
+ * This module defines interfaces for abstracting platform-specific capabilities
5
+ * across different runtime environments (Cloudflare Workers, Node.js, Vercel, etc.)
6
+ *
7
+ * ## Design Decisions (Expert Review 2026-03-12)
8
+ *
9
+ * 1. **RuntimeAdapter vs RuntimeContext** - These are independent interfaces:
10
+ * - RuntimeAdapter: Platform capabilities (kv, crypto) - for Workers
11
+ * - RuntimeContext: Application context (config, storage, events) - for CLI/OpenClaw
12
+ *
13
+ * 2. **No SQLDatabase interface** - Existing StorageAdapter satisfies business needs
14
+ *
15
+ * 3. **KVStore usage** - For session, rate limit counter, cache
16
+ */
17
+ /**
18
+ * Logger interface - Platform-agnostic logging
19
+ *
20
+ * Implementations:
21
+ * - Cloudflare: console (native)
22
+ * - Node.js: console or pino/winston
23
+ */
24
+ export interface Logger {
25
+ debug(message: string, ...args: unknown[]): void;
26
+ info(message: string, ...args: unknown[]): void;
27
+ warn(message: string, ...args: unknown[]): void;
28
+ error(message: string, ...args: unknown[]): void;
29
+ }
30
+ /**
31
+ * KVStore - Key-value storage for session, rate limiting, and caching
32
+ *
33
+ * Implementations:
34
+ * - Cloudflare: KVNamespace binding
35
+ * - Node.js: MemoryKVStore / SQLite
36
+ * - Vercel/Netlify: Upstash Redis
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Store session with TTL
41
+ * await kv.set('session:abc123', { userId: 'user1' }, { ttl: 3600000 }) // 1 hour
42
+ *
43
+ * // Retrieve session
44
+ * const session = await kv.get<{ userId: string }>('session:abc123')
45
+ *
46
+ * // Delete session
47
+ * await kv.delete('session:abc123')
48
+ * ```
49
+ */
50
+ export interface KVStore {
51
+ /**
52
+ * Get a value by key
53
+ * @param key - The key to retrieve
54
+ * @returns The value or null if not found
55
+ */
56
+ get<T = unknown>(key: string): Promise<T | null>;
57
+ /**
58
+ * Set a value with optional TTL
59
+ * @param key - The key to set
60
+ * @param value - The value to store
61
+ * @param options - Optional settings including TTL in milliseconds
62
+ */
63
+ set<T>(key: string, value: T, options?: {
64
+ ttl?: number;
65
+ }): Promise<void>;
66
+ /**
67
+ * Delete a key
68
+ * @param key - The key to delete
69
+ * @returns true if the key existed and was deleted
70
+ */
71
+ delete(key: string): Promise<boolean>;
72
+ }
73
+ /**
74
+ * CryptoAdapter - Platform-agnostic cryptographic capabilities
75
+ *
76
+ * Implementations:
77
+ * - Cloudflare: Web Crypto API
78
+ * - Node.js: node:crypto module
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * // HMAC for webhook signature verification
83
+ * const signature = await crypto.hmacSha256(payload, secret)
84
+ *
85
+ * // Generate random bytes for session IDs
86
+ * const sessionId = crypto.randomBytes(16)
87
+ * ```
88
+ */
89
+ export interface CryptoAdapter {
90
+ /**
91
+ * Compute HMAC-SHA256
92
+ * @param data - The data to sign
93
+ * @param secret - The secret key
94
+ * @returns Base64-encoded signature
95
+ */
96
+ hmacSha256(data: string, secret: string): Promise<string>;
97
+ /**
98
+ * Generate cryptographically secure random bytes
99
+ * @param length - Number of bytes to generate
100
+ * @returns Uint8Array of random bytes
101
+ */
102
+ randomBytes(length: number): Uint8Array;
103
+ }
104
+ /**
105
+ * RuntimeAdapter - Platform abstraction for Worker environments
106
+ *
107
+ * This interface abstracts platform-specific capabilities for Cloudflare Workers,
108
+ * Vercel Edge Functions, Netlify Edge Functions, and similar edge runtimes.
109
+ *
110
+ * Note: CLI/OpenClaw continue using RuntimeContext (includes config, platform.openUrl).
111
+ * The two interfaces are independent and serve different purposes:
112
+ * - RuntimeAdapter: Platform capabilities (kv, crypto)
113
+ * - RuntimeContext: Application context (config, storage, events)
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * // In Cloudflare Worker
118
+ * import { createCloudflareAdapter } from '@firela/runtime-adapters/cloudflare'
119
+ *
120
+ * export default {
121
+ * async fetch(request, env) {
122
+ * const adapter = createCloudflareAdapter(env)
123
+ * await adapter.kv.set('key', 'value')
124
+ * return new Response('OK')
125
+ * }
126
+ * }
127
+ * ```
128
+ */
129
+ export interface RuntimeAdapter {
130
+ /** Key-value store for session, rate limiting, and cache */
131
+ readonly kv: KVStore;
132
+ /** Logger instance */
133
+ readonly logger: Logger;
134
+ /** Platform identifier */
135
+ readonly platform: 'cloudflare' | 'node' | 'vercel' | 'netlify';
136
+ /** Cryptographic utilities */
137
+ readonly crypto: CryptoAdapter;
138
+ }
139
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;CACjD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAEhD;;;;;OAKG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAExE;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACtC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAEzD;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;CACxC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IAEpB,sBAAsB;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IAEvB,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IAE/D,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAC/B"}
package/dist/types.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * RuntimeAdapter Types - Platform-agnostic runtime abstraction
3
+ *
4
+ * This module defines interfaces for abstracting platform-specific capabilities
5
+ * across different runtime environments (Cloudflare Workers, Node.js, Vercel, etc.)
6
+ *
7
+ * ## Design Decisions (Expert Review 2026-03-12)
8
+ *
9
+ * 1. **RuntimeAdapter vs RuntimeContext** - These are independent interfaces:
10
+ * - RuntimeAdapter: Platform capabilities (kv, crypto) - for Workers
11
+ * - RuntimeContext: Application context (config, storage, events) - for CLI/OpenClaw
12
+ *
13
+ * 2. **No SQLDatabase interface** - Existing StorageAdapter satisfies business needs
14
+ *
15
+ * 3. **KVStore usage** - For session, rate limit counter, cache
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@firela/runtime-adapters",
3
+ "version": "0.1.0",
4
+ "description": "Platform-agnostic runtime adapters for Cloudflare Workers, Node.js, and edge runtimes",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./cloudflare": {
15
+ "types": "./dist/cloudflare.d.ts",
16
+ "import": "./dist/cloudflare.js",
17
+ "default": "./dist/cloudflare.js"
18
+ },
19
+ "./node": {
20
+ "types": "./dist/node.d.ts",
21
+ "import": "./dist/node.js",
22
+ "default": "./dist/node.js"
23
+ },
24
+ "./types": {
25
+ "types": "./dist/types.d.ts",
26
+ "import": "./dist/types.js",
27
+ "default": "./dist/types.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "keywords": [
37
+ "runtime",
38
+ "adapters",
39
+ "cloudflare-workers",
40
+ "nodejs",
41
+ "edge-computing",
42
+ "platform-agnostic"
43
+ ],
44
+ "author": "fire-la",
45
+ "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/fire-la/billclaw.git",
49
+ "directory": "packages/runtime-adapters"
50
+ },
51
+ "devDependencies": {
52
+ "@cloudflare/workers-types": "^4.20260312.0",
53
+ "@types/node": "^25.2.0",
54
+ "oxfmt": "^0.1.0",
55
+ "oxlint": "^0.15.0",
56
+ "typescript": "^5.8.0",
57
+ "vitest": "^2.1.0"
58
+ },
59
+ "engines": {
60
+ "node": ">=20.0.0"
61
+ },
62
+ "scripts": {
63
+ "build": "tsc",
64
+ "dev": "tsc --watch",
65
+ "lint": "oxlint",
66
+ "format": "oxfmt src/",
67
+ "format:write": "oxfmt -w src/",
68
+ "clean": "rm -rf dist"
69
+ }
70
+ }