nats.do 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/README.md +298 -0
- package/dist/env-Ds3wIkQg.d.cts +28 -0
- package/dist/env-Ds3wIkQg.d.ts +28 -0
- package/dist/index.cjs +235 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +230 -0
- package/dist/index.js.map +1 -0
- package/dist/types.cjs +169 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +444 -0
- package/dist/types.d.ts +444 -0
- package/dist/types.js +155 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.cjs +362 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +214 -0
- package/dist/utils.d.ts +214 -0
- package/dist/utils.js +338 -0
- package/dist/utils.js.map +1 -0
- package/package.json +87 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { DurableObject } from 'cloudflare:workers';
|
|
2
|
+
|
|
3
|
+
// src/durable-objects/nats-coordinator.ts
|
|
4
|
+
|
|
5
|
+
// src/types/rpc.ts
|
|
6
|
+
var RPC_ERROR_CODES = {
|
|
7
|
+
// Standard JSON-RPC errors
|
|
8
|
+
PARSE_ERROR: -32700,
|
|
9
|
+
METHOD_NOT_FOUND: -32601,
|
|
10
|
+
INVALID_PARAMS: -32602,
|
|
11
|
+
CONSUMER_NOT_FOUND: -32002,
|
|
12
|
+
CONSUMER_EXISTS: -32007};
|
|
13
|
+
function createRpcError(code, message, id, data) {
|
|
14
|
+
return {
|
|
15
|
+
jsonrpc: "2.0",
|
|
16
|
+
error: {
|
|
17
|
+
code,
|
|
18
|
+
message,
|
|
19
|
+
...data !== void 0
|
|
20
|
+
},
|
|
21
|
+
id: id ?? null
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createRpcSuccess(result, id) {
|
|
25
|
+
return {
|
|
26
|
+
jsonrpc: "2.0",
|
|
27
|
+
result,
|
|
28
|
+
id
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/durable-objects/nats-coordinator.ts
|
|
33
|
+
var NatsCoordinator = class extends DurableObject {
|
|
34
|
+
sql;
|
|
35
|
+
constructor(ctx, env) {
|
|
36
|
+
super(ctx, env);
|
|
37
|
+
this.sql = ctx.storage.sql;
|
|
38
|
+
this.initSchema();
|
|
39
|
+
}
|
|
40
|
+
initSchema() {
|
|
41
|
+
this.sql.exec(`
|
|
42
|
+
CREATE TABLE IF NOT EXISTS consumers (
|
|
43
|
+
stream_name TEXT NOT NULL,
|
|
44
|
+
name TEXT NOT NULL,
|
|
45
|
+
config TEXT NOT NULL,
|
|
46
|
+
durable INTEGER NOT NULL DEFAULT 0,
|
|
47
|
+
created_at INTEGER NOT NULL,
|
|
48
|
+
last_active_at INTEGER,
|
|
49
|
+
PRIMARY KEY (stream_name, name)
|
|
50
|
+
)
|
|
51
|
+
`);
|
|
52
|
+
}
|
|
53
|
+
async fetch(request) {
|
|
54
|
+
if (request.method !== "POST") {
|
|
55
|
+
return new Response("Method not allowed", { status: 405 });
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const body = await request.json();
|
|
59
|
+
const { method, params, id } = body;
|
|
60
|
+
const result = await this.handleRpc(method, params || {}, id);
|
|
61
|
+
return new Response(JSON.stringify(result), {
|
|
62
|
+
headers: { "Content-Type": "application/json" }
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
const errorResponse = createRpcError(
|
|
66
|
+
RPC_ERROR_CODES.PARSE_ERROR,
|
|
67
|
+
"Invalid JSON",
|
|
68
|
+
null
|
|
69
|
+
);
|
|
70
|
+
return new Response(JSON.stringify(errorResponse), {
|
|
71
|
+
headers: { "Content-Type": "application/json" }
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async handleRpc(method, params, id) {
|
|
76
|
+
switch (method) {
|
|
77
|
+
case "consumers.register":
|
|
78
|
+
return this.registerConsumer(params, id);
|
|
79
|
+
case "consumers.get":
|
|
80
|
+
return this.getConsumer(params, id);
|
|
81
|
+
case "consumers.delete":
|
|
82
|
+
return this.deleteConsumer(params, id);
|
|
83
|
+
case "consumers.list":
|
|
84
|
+
return this.listConsumers(params, id);
|
|
85
|
+
case "consumers.updateLastActive":
|
|
86
|
+
return this.updateConsumerLastActive(params, id);
|
|
87
|
+
default:
|
|
88
|
+
return createRpcError(
|
|
89
|
+
RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
90
|
+
`Method not found: ${method}`,
|
|
91
|
+
id
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
registerConsumer(params, id) {
|
|
96
|
+
const streamName = params.streamName;
|
|
97
|
+
const config = params.config;
|
|
98
|
+
const consumerName = config.name || config.durable_name;
|
|
99
|
+
if (!consumerName) {
|
|
100
|
+
return createRpcError(
|
|
101
|
+
RPC_ERROR_CODES.INVALID_PARAMS,
|
|
102
|
+
"Consumer name is required (name or durable_name)",
|
|
103
|
+
id
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const existing = this.sql.exec("SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?", streamName, consumerName).toArray();
|
|
107
|
+
if (existing.length > 0) {
|
|
108
|
+
return createRpcError(
|
|
109
|
+
RPC_ERROR_CODES.CONSUMER_EXISTS,
|
|
110
|
+
`Consumer ${consumerName} already exists on stream ${streamName}`,
|
|
111
|
+
id
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const now = Date.now();
|
|
115
|
+
const isDurable = !!config.durable_name;
|
|
116
|
+
this.sql.exec(
|
|
117
|
+
`INSERT INTO consumers (stream_name, name, config, durable, created_at, last_active_at)
|
|
118
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
119
|
+
streamName,
|
|
120
|
+
consumerName,
|
|
121
|
+
JSON.stringify(config),
|
|
122
|
+
isDurable ? 1 : 0,
|
|
123
|
+
now,
|
|
124
|
+
null
|
|
125
|
+
);
|
|
126
|
+
const entry = {
|
|
127
|
+
stream_name: streamName,
|
|
128
|
+
name: consumerName,
|
|
129
|
+
config,
|
|
130
|
+
durable: isDurable,
|
|
131
|
+
created_at: now,
|
|
132
|
+
last_active_at: null
|
|
133
|
+
};
|
|
134
|
+
return createRpcSuccess(entry, id);
|
|
135
|
+
}
|
|
136
|
+
getConsumer(params, id) {
|
|
137
|
+
const streamName = params.streamName;
|
|
138
|
+
const consumerName = params.consumerName;
|
|
139
|
+
const rows = this.sql.exec(
|
|
140
|
+
"SELECT stream_name, name, config, durable, created_at, last_active_at FROM consumers WHERE stream_name = ? AND name = ?",
|
|
141
|
+
streamName,
|
|
142
|
+
consumerName
|
|
143
|
+
).toArray();
|
|
144
|
+
if (rows.length === 0) {
|
|
145
|
+
return createRpcError(
|
|
146
|
+
RPC_ERROR_CODES.CONSUMER_NOT_FOUND,
|
|
147
|
+
`Consumer ${consumerName} not found on stream ${streamName}`,
|
|
148
|
+
id
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const row = rows[0];
|
|
152
|
+
const entry = {
|
|
153
|
+
stream_name: row.stream_name,
|
|
154
|
+
name: row.name,
|
|
155
|
+
config: JSON.parse(row.config),
|
|
156
|
+
durable: row.durable === 1,
|
|
157
|
+
created_at: row.created_at,
|
|
158
|
+
last_active_at: row.last_active_at
|
|
159
|
+
};
|
|
160
|
+
return createRpcSuccess(entry, id);
|
|
161
|
+
}
|
|
162
|
+
deleteConsumer(params, id) {
|
|
163
|
+
const streamName = params.streamName;
|
|
164
|
+
const consumerName = params.consumerName;
|
|
165
|
+
const existing = this.sql.exec("SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?", streamName, consumerName).toArray();
|
|
166
|
+
if (existing.length === 0) {
|
|
167
|
+
return createRpcError(
|
|
168
|
+
RPC_ERROR_CODES.CONSUMER_NOT_FOUND,
|
|
169
|
+
`Consumer ${consumerName} not found on stream ${streamName}`,
|
|
170
|
+
id
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
this.sql.exec(
|
|
174
|
+
"DELETE FROM consumers WHERE stream_name = ? AND name = ?",
|
|
175
|
+
streamName,
|
|
176
|
+
consumerName
|
|
177
|
+
);
|
|
178
|
+
return createRpcSuccess({ success: true }, id);
|
|
179
|
+
}
|
|
180
|
+
listConsumers(params, id) {
|
|
181
|
+
const streamName = params.streamName;
|
|
182
|
+
const rows = this.sql.exec(
|
|
183
|
+
"SELECT stream_name, name, config, durable, created_at, last_active_at FROM consumers WHERE stream_name = ? ORDER BY name",
|
|
184
|
+
streamName
|
|
185
|
+
).toArray();
|
|
186
|
+
const consumers = rows.map((row) => {
|
|
187
|
+
const r = row;
|
|
188
|
+
return {
|
|
189
|
+
stream_name: r.stream_name,
|
|
190
|
+
name: r.name,
|
|
191
|
+
config: JSON.parse(r.config),
|
|
192
|
+
durable: r.durable === 1,
|
|
193
|
+
created_at: r.created_at,
|
|
194
|
+
last_active_at: r.last_active_at
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
return createRpcSuccess(consumers, id);
|
|
198
|
+
}
|
|
199
|
+
updateConsumerLastActive(params, id) {
|
|
200
|
+
const streamName = params.streamName;
|
|
201
|
+
const consumerName = params.consumerName;
|
|
202
|
+
const existing = this.sql.exec("SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?", streamName, consumerName).toArray();
|
|
203
|
+
if (existing.length === 0) {
|
|
204
|
+
return createRpcError(
|
|
205
|
+
RPC_ERROR_CODES.CONSUMER_NOT_FOUND,
|
|
206
|
+
`Consumer ${consumerName} not found on stream ${streamName}`,
|
|
207
|
+
id
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
const now = Date.now();
|
|
211
|
+
this.sql.exec(
|
|
212
|
+
"UPDATE consumers SET last_active_at = ? WHERE stream_name = ? AND name = ?",
|
|
213
|
+
now,
|
|
214
|
+
streamName,
|
|
215
|
+
consumerName
|
|
216
|
+
);
|
|
217
|
+
return createRpcSuccess({ last_active_at: now }, id);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// src/index.ts
|
|
222
|
+
var src_default = {
|
|
223
|
+
async fetch(_request, _env) {
|
|
224
|
+
return new Response("NatDO - Not yet implemented", { status: 501 });
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export { NatsCoordinator, src_default as default };
|
|
229
|
+
//# sourceMappingURL=index.js.map
|
|
230
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/rpc.ts","../src/durable-objects/nats-coordinator.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * RPC Types\n *\n * JSON-RPC 2.0 types for NatDO communication.\n */\n\n// Request ID type\nexport type RpcId = string | number\n\n// RPC Request\nexport interface RpcRequest {\n jsonrpc: '2.0'\n method: string\n params?: Record<string, unknown> | unknown[]\n id: RpcId\n}\n\n// RPC Notification (no id)\nexport interface RpcNotification {\n jsonrpc: '2.0'\n method: string\n params?: Record<string, unknown> | unknown[]\n}\n\n// RPC Error\nexport interface RpcError {\n code: number\n message: string\n data?: unknown\n}\n\n// RPC Response\nexport interface RpcResponse {\n jsonrpc: '2.0'\n result?: unknown\n error?: RpcError\n id: RpcId | null\n}\n\n// Batch types\nexport type RpcBatchRequest = Array<RpcRequest | RpcNotification>\nexport type RpcBatchResponse = RpcResponse[]\n\n// Standard JSON-RPC 2.0 error codes\nexport const RPC_ERROR_CODES = {\n // Standard JSON-RPC errors\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n\n // NATS-specific error codes (-32001 to -32099)\n STREAM_NOT_FOUND: -32001,\n CONSUMER_NOT_FOUND: -32002,\n NO_RESPONDERS: -32003,\n TIMEOUT: -32004,\n MESSAGE_NOT_FOUND: -32005,\n STREAM_EXISTS: -32006,\n CONSUMER_EXISTS: -32007,\n INVALID_SUBJECT: -32008,\n PERMISSION_DENIED: -32009,\n MAX_PAYLOAD_EXCEEDED: -32010,\n DUPLICATE_MESSAGE: -32011,\n STREAM_SEALED: -32012,\n CONSUMER_DELETED: -32013,\n} as const\n\n// Type guard for error responses\nexport function isRpcError(response: RpcResponse): response is RpcResponse & { error: RpcError } {\n return 'error' in response && response.error !== undefined\n}\n\n// Type guard for success responses\nexport function isRpcSuccess(response: RpcResponse): response is RpcResponse & { result: unknown } {\n return !isRpcError(response)\n}\n\n// Request ID counter for auto-incrementing IDs\nlet requestIdCounter = 0\n\n// Create RPC request helper\nexport function createRpcRequest(\n method: string,\n opts?: { params?: Record<string, unknown> | unknown[]; id?: RpcId }\n): RpcRequest {\n return {\n jsonrpc: '2.0',\n method,\n ...(opts?.params && { params: opts.params }),\n id: opts?.id ?? ++requestIdCounter,\n }\n}\n\n// Create RPC error response helper\nexport function createRpcError(\n code: number,\n message: string,\n id?: RpcId | null,\n data?: unknown\n): RpcResponse {\n return {\n jsonrpc: '2.0',\n error: {\n code,\n message,\n ...(data !== undefined && { data }),\n },\n id: id ?? null,\n }\n}\n\n// Create RPC success response helper\nexport function createRpcSuccess(result: unknown, id: RpcId): RpcResponse {\n return {\n jsonrpc: '2.0',\n result,\n id,\n }\n}\n\n// Reset request ID counter (for testing)\nexport function resetRequestIdCounter(): void {\n requestIdCounter = 0\n}\n","/**\n * NatsCoordinator Durable Object\n *\n * Central coordinator for NATS/JetStream operations.\n * Manages consumer registry with SQLite storage.\n */\n\nimport { DurableObject } from 'cloudflare:workers'\nimport type { ConsumerConfig } from '../types/jetstream'\nimport { RPC_ERROR_CODES, createRpcError, createRpcSuccess } from '../types/rpc'\nimport type { Env } from '../types/env'\n\n// Consumer registry entry stored in SQLite\ninterface ConsumerEntry {\n stream_name: string\n name: string\n config: ConsumerConfig\n durable: boolean\n created_at: number\n last_active_at: number | null\n}\n\n// RPC request structure\ninterface RpcRequest {\n jsonrpc: '2.0'\n method: string\n params?: Record<string, unknown>\n id: number | string\n}\n\nexport class NatsCoordinator extends DurableObject<Env> {\n private sql: SqlStorage\n\n constructor(ctx: DurableObjectState, env: Env) {\n super(ctx, env)\n this.sql = ctx.storage.sql\n\n // Initialize schema\n this.initSchema()\n }\n\n private initSchema(): void {\n this.sql.exec(`\n CREATE TABLE IF NOT EXISTS consumers (\n stream_name TEXT NOT NULL,\n name TEXT NOT NULL,\n config TEXT NOT NULL,\n durable INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL,\n last_active_at INTEGER,\n PRIMARY KEY (stream_name, name)\n )\n `)\n }\n\n async fetch(request: Request): Promise<Response> {\n if (request.method !== 'POST') {\n return new Response('Method not allowed', { status: 405 })\n }\n\n try {\n const body = await request.json() as RpcRequest\n const { method, params, id } = body\n\n const result = await this.handleRpc(method, params || {}, id)\n return new Response(JSON.stringify(result), {\n headers: { 'Content-Type': 'application/json' },\n })\n } catch (error) {\n const errorResponse = createRpcError(\n RPC_ERROR_CODES.PARSE_ERROR,\n 'Invalid JSON',\n null\n )\n return new Response(JSON.stringify(errorResponse), {\n headers: { 'Content-Type': 'application/json' },\n })\n }\n }\n\n private async handleRpc(\n method: string,\n params: Record<string, unknown>,\n id: number | string\n ) {\n switch (method) {\n case 'consumers.register':\n return this.registerConsumer(params, id)\n case 'consumers.get':\n return this.getConsumer(params, id)\n case 'consumers.delete':\n return this.deleteConsumer(params, id)\n case 'consumers.list':\n return this.listConsumers(params, id)\n case 'consumers.updateLastActive':\n return this.updateConsumerLastActive(params, id)\n default:\n return createRpcError(\n RPC_ERROR_CODES.METHOD_NOT_FOUND,\n `Method not found: ${method}`,\n id\n )\n }\n }\n\n private registerConsumer(params: Record<string, unknown>, id: number | string) {\n const streamName = params.streamName as string\n const config = params.config as ConsumerConfig\n\n // Validate consumer name\n const consumerName = config.name || config.durable_name\n if (!consumerName) {\n return createRpcError(\n RPC_ERROR_CODES.INVALID_PARAMS,\n 'Consumer name is required (name or durable_name)',\n id\n )\n }\n\n // Check if consumer already exists\n const existing = this.sql\n .exec('SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?', streamName, consumerName)\n .toArray()\n\n if (existing.length > 0) {\n return createRpcError(\n RPC_ERROR_CODES.CONSUMER_EXISTS,\n `Consumer ${consumerName} already exists on stream ${streamName}`,\n id\n )\n }\n\n const now = Date.now()\n const isDurable = !!config.durable_name\n\n // Store the consumer\n this.sql.exec(\n `INSERT INTO consumers (stream_name, name, config, durable, created_at, last_active_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n streamName,\n consumerName,\n JSON.stringify(config),\n isDurable ? 1 : 0,\n now,\n null\n )\n\n const entry: ConsumerEntry = {\n stream_name: streamName,\n name: consumerName,\n config,\n durable: isDurable,\n created_at: now,\n last_active_at: null,\n }\n\n return createRpcSuccess(entry, id)\n }\n\n private getConsumer(params: Record<string, unknown>, id: number | string) {\n const streamName = params.streamName as string\n const consumerName = params.consumerName as string\n\n const rows = this.sql\n .exec(\n 'SELECT stream_name, name, config, durable, created_at, last_active_at FROM consumers WHERE stream_name = ? AND name = ?',\n streamName,\n consumerName\n )\n .toArray()\n\n if (rows.length === 0) {\n return createRpcError(\n RPC_ERROR_CODES.CONSUMER_NOT_FOUND,\n `Consumer ${consumerName} not found on stream ${streamName}`,\n id\n )\n }\n\n const row = rows[0] as {\n stream_name: string\n name: string\n config: string\n durable: number\n created_at: number\n last_active_at: number | null\n }\n\n const entry: ConsumerEntry = {\n stream_name: row.stream_name,\n name: row.name,\n config: JSON.parse(row.config) as ConsumerConfig,\n durable: row.durable === 1,\n created_at: row.created_at,\n last_active_at: row.last_active_at,\n }\n\n return createRpcSuccess(entry, id)\n }\n\n private deleteConsumer(params: Record<string, unknown>, id: number | string) {\n const streamName = params.streamName as string\n const consumerName = params.consumerName as string\n\n // Check if consumer exists\n const existing = this.sql\n .exec('SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?', streamName, consumerName)\n .toArray()\n\n if (existing.length === 0) {\n return createRpcError(\n RPC_ERROR_CODES.CONSUMER_NOT_FOUND,\n `Consumer ${consumerName} not found on stream ${streamName}`,\n id\n )\n }\n\n this.sql.exec(\n 'DELETE FROM consumers WHERE stream_name = ? AND name = ?',\n streamName,\n consumerName\n )\n\n return createRpcSuccess({ success: true }, id)\n }\n\n private listConsumers(params: Record<string, unknown>, id: number | string) {\n const streamName = params.streamName as string\n\n const rows = this.sql\n .exec(\n 'SELECT stream_name, name, config, durable, created_at, last_active_at FROM consumers WHERE stream_name = ? ORDER BY name',\n streamName\n )\n .toArray()\n\n const consumers: ConsumerEntry[] = rows.map((row) => {\n const r = row as {\n stream_name: string\n name: string\n config: string\n durable: number\n created_at: number\n last_active_at: number | null\n }\n return {\n stream_name: r.stream_name,\n name: r.name,\n config: JSON.parse(r.config) as ConsumerConfig,\n durable: r.durable === 1,\n created_at: r.created_at,\n last_active_at: r.last_active_at,\n }\n })\n\n return createRpcSuccess(consumers, id)\n }\n\n private updateConsumerLastActive(params: Record<string, unknown>, id: number | string) {\n const streamName = params.streamName as string\n const consumerName = params.consumerName as string\n\n // Check if consumer exists\n const existing = this.sql\n .exec('SELECT 1 FROM consumers WHERE stream_name = ? AND name = ?', streamName, consumerName)\n .toArray()\n\n if (existing.length === 0) {\n return createRpcError(\n RPC_ERROR_CODES.CONSUMER_NOT_FOUND,\n `Consumer ${consumerName} not found on stream ${streamName}`,\n id\n )\n }\n\n const now = Date.now()\n this.sql.exec(\n 'UPDATE consumers SET last_active_at = ? WHERE stream_name = ? AND name = ?',\n now,\n streamName,\n consumerName\n )\n\n return createRpcSuccess({ last_active_at: now }, id)\n }\n}\n","/**\n * NatDO - NATS/JetStream on Cloudflare Durable Objects\n *\n * This is the main entry point for the worker.\n */\n\nexport { NatsCoordinator } from './durable-objects/nats-coordinator'\n\nexport default {\n async fetch(_request: Request, _env: unknown): Promise<Response> {\n return new Response('NatDO - Not yet implemented', { status: 501 })\n },\n}\n"]}
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/types/nats.ts
|
|
4
|
+
var MsgHdrsImpl = class {
|
|
5
|
+
headers = /* @__PURE__ */ new Map();
|
|
6
|
+
code;
|
|
7
|
+
description;
|
|
8
|
+
get(key) {
|
|
9
|
+
const values = this.headers.get(key.toLowerCase());
|
|
10
|
+
return values?.[0];
|
|
11
|
+
}
|
|
12
|
+
set(key, value) {
|
|
13
|
+
this.headers.set(key.toLowerCase(), [value]);
|
|
14
|
+
}
|
|
15
|
+
append(key, value) {
|
|
16
|
+
const lowerKey = key.toLowerCase();
|
|
17
|
+
const existing = this.headers.get(lowerKey) || [];
|
|
18
|
+
existing.push(value);
|
|
19
|
+
this.headers.set(lowerKey, existing);
|
|
20
|
+
}
|
|
21
|
+
has(key) {
|
|
22
|
+
return this.headers.has(key.toLowerCase());
|
|
23
|
+
}
|
|
24
|
+
delete(key) {
|
|
25
|
+
this.headers.delete(key.toLowerCase());
|
|
26
|
+
}
|
|
27
|
+
*keys() {
|
|
28
|
+
yield* this.headers.keys();
|
|
29
|
+
}
|
|
30
|
+
values(key) {
|
|
31
|
+
return this.headers.get(key.toLowerCase()) || [];
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
function createHeaders() {
|
|
35
|
+
return new MsgHdrsImpl();
|
|
36
|
+
}
|
|
37
|
+
function StringCodec() {
|
|
38
|
+
const encoder = new TextEncoder();
|
|
39
|
+
const decoder = new TextDecoder();
|
|
40
|
+
return {
|
|
41
|
+
encode(data) {
|
|
42
|
+
return encoder.encode(data);
|
|
43
|
+
},
|
|
44
|
+
decode(data) {
|
|
45
|
+
return decoder.decode(data);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function JSONCodec() {
|
|
50
|
+
const sc = StringCodec();
|
|
51
|
+
return {
|
|
52
|
+
encode(data) {
|
|
53
|
+
return sc.encode(JSON.stringify(data));
|
|
54
|
+
},
|
|
55
|
+
decode(data) {
|
|
56
|
+
return JSON.parse(sc.decode(data));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
var Empty = new Uint8Array(0);
|
|
61
|
+
|
|
62
|
+
// src/types/jetstream.ts
|
|
63
|
+
function defaultStreamConfig(name) {
|
|
64
|
+
return {
|
|
65
|
+
name,
|
|
66
|
+
subjects: [],
|
|
67
|
+
retention: "limits",
|
|
68
|
+
storage: "file",
|
|
69
|
+
max_msgs: -1,
|
|
70
|
+
max_bytes: -1,
|
|
71
|
+
max_age: 0,
|
|
72
|
+
max_msg_size: -1,
|
|
73
|
+
max_consumers: -1,
|
|
74
|
+
discard: "old",
|
|
75
|
+
duplicate_window: 2 * 60 * 1e9,
|
|
76
|
+
// 2 minutes in nanos
|
|
77
|
+
num_replicas: 1,
|
|
78
|
+
deny_delete: false,
|
|
79
|
+
deny_purge: false
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function defaultConsumerConfig() {
|
|
83
|
+
return {
|
|
84
|
+
ack_policy: "explicit",
|
|
85
|
+
deliver_policy: "all",
|
|
86
|
+
replay_policy: "instant",
|
|
87
|
+
ack_wait: 30 * 1e9,
|
|
88
|
+
// 30 seconds in nanos
|
|
89
|
+
max_deliver: -1,
|
|
90
|
+
max_ack_pending: 1e3,
|
|
91
|
+
max_waiting: 512
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/types/rpc.ts
|
|
96
|
+
var RPC_ERROR_CODES = {
|
|
97
|
+
// Standard JSON-RPC errors
|
|
98
|
+
PARSE_ERROR: -32700,
|
|
99
|
+
INVALID_REQUEST: -32600,
|
|
100
|
+
METHOD_NOT_FOUND: -32601,
|
|
101
|
+
INVALID_PARAMS: -32602,
|
|
102
|
+
INTERNAL_ERROR: -32603,
|
|
103
|
+
// NATS-specific error codes (-32001 to -32099)
|
|
104
|
+
STREAM_NOT_FOUND: -32001,
|
|
105
|
+
CONSUMER_NOT_FOUND: -32002,
|
|
106
|
+
NO_RESPONDERS: -32003,
|
|
107
|
+
TIMEOUT: -32004,
|
|
108
|
+
MESSAGE_NOT_FOUND: -32005,
|
|
109
|
+
STREAM_EXISTS: -32006,
|
|
110
|
+
CONSUMER_EXISTS: -32007,
|
|
111
|
+
INVALID_SUBJECT: -32008,
|
|
112
|
+
PERMISSION_DENIED: -32009,
|
|
113
|
+
MAX_PAYLOAD_EXCEEDED: -32010,
|
|
114
|
+
DUPLICATE_MESSAGE: -32011,
|
|
115
|
+
STREAM_SEALED: -32012,
|
|
116
|
+
CONSUMER_DELETED: -32013
|
|
117
|
+
};
|
|
118
|
+
function isRpcError(response) {
|
|
119
|
+
return "error" in response && response.error !== void 0;
|
|
120
|
+
}
|
|
121
|
+
function isRpcSuccess(response) {
|
|
122
|
+
return !isRpcError(response);
|
|
123
|
+
}
|
|
124
|
+
var requestIdCounter = 0;
|
|
125
|
+
function createRpcRequest(method, opts) {
|
|
126
|
+
return {
|
|
127
|
+
jsonrpc: "2.0",
|
|
128
|
+
method,
|
|
129
|
+
...opts?.params && { params: opts.params },
|
|
130
|
+
id: opts?.id ?? ++requestIdCounter
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function createRpcError(code, message, id, data) {
|
|
134
|
+
return {
|
|
135
|
+
jsonrpc: "2.0",
|
|
136
|
+
error: {
|
|
137
|
+
code,
|
|
138
|
+
message,
|
|
139
|
+
...data !== void 0 && { data }
|
|
140
|
+
},
|
|
141
|
+
id: id ?? null
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function createRpcSuccess(result, id) {
|
|
145
|
+
return {
|
|
146
|
+
jsonrpc: "2.0",
|
|
147
|
+
result,
|
|
148
|
+
id
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function resetRequestIdCounter() {
|
|
152
|
+
requestIdCounter = 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
exports.Empty = Empty;
|
|
156
|
+
exports.JSONCodec = JSONCodec;
|
|
157
|
+
exports.RPC_ERROR_CODES = RPC_ERROR_CODES;
|
|
158
|
+
exports.StringCodec = StringCodec;
|
|
159
|
+
exports.createHeaders = createHeaders;
|
|
160
|
+
exports.createRpcError = createRpcError;
|
|
161
|
+
exports.createRpcRequest = createRpcRequest;
|
|
162
|
+
exports.createRpcSuccess = createRpcSuccess;
|
|
163
|
+
exports.defaultConsumerConfig = defaultConsumerConfig;
|
|
164
|
+
exports.defaultStreamConfig = defaultStreamConfig;
|
|
165
|
+
exports.isRpcError = isRpcError;
|
|
166
|
+
exports.isRpcSuccess = isRpcSuccess;
|
|
167
|
+
exports.resetRequestIdCounter = resetRequestIdCounter;
|
|
168
|
+
//# sourceMappingURL=types.cjs.map
|
|
169
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/nats.ts","../src/types/jetstream.ts","../src/types/rpc.ts"],"names":[],"mappings":"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","file":"types.cjs","sourcesContent":["/**\n * Core NATS Types\n *\n * Implements types compatible with the nats.js library.\n */\n\n// Connection options for NatDO\nexport interface ConnectionOptions {\n servers: string | string[]\n name?: string\n token?: string\n user?: string\n pass?: string\n timeout?: number\n reconnect?: boolean\n maxReconnectAttempts?: number\n reconnectTimeWait?: number\n}\n\n// Message headers interface\nexport interface MsgHdrs {\n get(key: string): string | undefined\n set(key: string, value: string): void\n append(key: string, value: string): void\n has(key: string): boolean\n delete(key: string): void\n keys(): IterableIterator<string>\n values(key: string): string[]\n code?: number\n description?: string\n}\n\n// Create headers implementation\nclass MsgHdrsImpl implements MsgHdrs {\n private readonly headers: Map<string, string[]> = new Map()\n code?: number\n description?: string\n\n get(key: string): string | undefined {\n const values = this.headers.get(key.toLowerCase())\n return values?.[0]\n }\n\n set(key: string, value: string): void {\n this.headers.set(key.toLowerCase(), [value])\n }\n\n append(key: string, value: string): void {\n const lowerKey = key.toLowerCase()\n const existing = this.headers.get(lowerKey) || []\n existing.push(value)\n this.headers.set(lowerKey, existing)\n }\n\n has(key: string): boolean {\n return this.headers.has(key.toLowerCase())\n }\n\n delete(key: string): void {\n this.headers.delete(key.toLowerCase())\n }\n\n *keys(): IterableIterator<string> {\n yield* this.headers.keys()\n }\n\n values(key: string): string[] {\n return this.headers.get(key.toLowerCase()) || []\n }\n}\n\nexport function createHeaders(): MsgHdrs {\n return new MsgHdrsImpl()\n}\n\n// Message interface\nexport interface Msg {\n subject: string\n data: Uint8Array\n sid: number\n reply?: string\n headers?: MsgHdrs\n respond(data?: Uint8Array, opts?: PublishOptions): boolean\n string(): string\n json<T = unknown>(): T\n}\n\n// Publish options\nexport interface PublishOptions {\n reply?: string\n headers?: MsgHdrs\n}\n\n// Subscription options\nexport interface SubscriptionOptions {\n queue?: string\n max?: number\n callback?: (err: Error | null, msg: Msg) => void\n timeout?: number\n}\n\n// Request options\nexport interface RequestOptions {\n timeout?: number\n headers?: MsgHdrs\n noMux?: boolean\n}\n\n// Subscription interface\nexport interface Subscription extends AsyncIterable<Msg> {\n getSubject(): string\n unsubscribe(max?: number): void\n drain(): Promise<void>\n isClosed(): boolean\n getReceived(): number\n getMax(): number | undefined\n}\n\n// Queued iterator for async message consumption\nexport interface QueuedIterator<T> extends AsyncIterator<T> {\n [Symbol.asyncIterator](): AsyncIterator<T>\n stop(): void\n}\n\n// Status types\nexport type StatusType =\n | 'disconnect'\n | 'reconnecting'\n | 'reconnect'\n | 'update'\n | 'ldm'\n | 'error'\n\n// Status event\nexport interface Status {\n type: StatusType\n data?: string | Error | { added?: string[]; deleted?: string[] }\n}\n\n// Server info\nexport interface ServerInfo {\n server_id: string\n server_name: string\n version: string\n proto: number\n host: string\n port: number\n max_payload: number\n jetstream?: boolean\n client_id?: number\n client_ip?: string\n}\n\n// NATS Connection interface\nexport interface NatsConnection {\n publish(subject: string, data?: Uint8Array, opts?: PublishOptions): void\n subscribe(subject: string, opts?: SubscriptionOptions): Subscription\n request(\n subject: string,\n data?: Uint8Array,\n opts?: RequestOptions\n ): Promise<Msg>\n flush(): Promise<void>\n drain(): Promise<void>\n close(): Promise<void>\n closed(): Promise<void | Error>\n status(): AsyncIterable<Status>\n isClosed(): boolean\n isDraining(): boolean\n getServer(): string\n info?: ServerInfo\n}\n\n// Codec interface\nexport interface Codec<T> {\n encode(data: T): Uint8Array\n decode(data: Uint8Array): T\n}\n\n// String codec\nexport function StringCodec(): Codec<string> {\n const encoder = new TextEncoder()\n const decoder = new TextDecoder()\n return {\n encode(data: string): Uint8Array {\n return encoder.encode(data)\n },\n decode(data: Uint8Array): string {\n return decoder.decode(data)\n },\n }\n}\n\n// JSON codec\nexport function JSONCodec<T = unknown>(): Codec<T> {\n const sc = StringCodec()\n return {\n encode(data: T): Uint8Array {\n return sc.encode(JSON.stringify(data))\n },\n decode(data: Uint8Array): T {\n return JSON.parse(sc.decode(data))\n },\n }\n}\n\n// Empty payload constant\nexport const Empty: Uint8Array = new Uint8Array(0)\n","/**\n * JetStream Types\n *\n * Implements types compatible with @nats-io/jetstream library.\n */\n\n// Policy types\nexport type RetentionPolicy = 'limits' | 'interest' | 'workqueue'\nexport type StorageType = 'file' | 'memory'\nexport type DiscardPolicy = 'old' | 'new'\nexport type AckPolicy = 'none' | 'all' | 'explicit'\nexport type DeliverPolicy =\n | 'all'\n | 'last'\n | 'new'\n | 'by_start_sequence'\n | 'by_start_time'\n | 'last_per_subject'\nexport type ReplayPolicy = 'instant' | 'original'\n\n// Stream configuration\nexport interface StreamConfig {\n name: string\n subjects: string[]\n description?: string\n retention?: RetentionPolicy\n storage?: StorageType\n max_msgs?: number\n max_bytes?: number\n max_age?: number // nanoseconds\n max_msg_size?: number\n max_msgs_per_subject?: number\n max_consumers?: number\n discard?: DiscardPolicy\n discard_new_per_subject?: boolean\n duplicate_window?: number // nanoseconds\n num_replicas?: number\n deny_delete?: boolean\n deny_purge?: boolean\n allow_rollup_hdrs?: boolean\n allow_direct?: boolean\n mirror_direct?: boolean\n sealed?: boolean\n placement?: {\n cluster?: string\n tags?: string[]\n }\n mirror?: {\n name: string\n opt_start_seq?: number\n opt_start_time?: string\n filter_subject?: string\n }\n sources?: Array<{\n name: string\n opt_start_seq?: number\n opt_start_time?: string\n filter_subject?: string\n }>\n republish?: {\n src: string\n dest: string\n headers_only?: boolean\n }\n subject_transform?: {\n src: string\n dest: string\n }\n}\n\n// Default stream config helper\nexport function defaultStreamConfig(name: string): StreamConfig {\n return {\n name,\n subjects: [],\n retention: 'limits',\n storage: 'file',\n max_msgs: -1,\n max_bytes: -1,\n max_age: 0,\n max_msg_size: -1,\n max_consumers: -1,\n discard: 'old',\n duplicate_window: 2 * 60 * 1_000_000_000, // 2 minutes in nanos\n num_replicas: 1,\n deny_delete: false,\n deny_purge: false,\n }\n}\n\n// Stream state\nexport interface StreamState {\n messages: number\n bytes: number\n first_seq: number\n first_ts?: string\n last_seq: number\n last_ts?: string\n consumer_count: number\n num_deleted?: number\n num_subjects?: number\n subjects?: Record<string, number>\n}\n\n// Stream info\nexport interface StreamInfo {\n config: StreamConfig\n state: StreamState\n created: string\n cluster?: {\n name?: string\n leader?: string\n replicas?: Array<{\n name: string\n current: boolean\n active: number\n lag: number\n }>\n }\n mirror?: {\n name: string\n lag: number\n active: number\n }\n sources?: Array<{\n name: string\n lag: number\n active: number\n }>\n}\n\n// Consumer configuration\nexport interface ConsumerConfig {\n name?: string\n durable_name?: string\n description?: string\n deliver_policy?: DeliverPolicy\n opt_start_seq?: number\n opt_start_time?: string\n ack_policy: AckPolicy\n ack_wait?: number // nanoseconds\n max_deliver?: number\n filter_subject?: string\n filter_subjects?: string[]\n replay_policy?: ReplayPolicy\n rate_limit_bps?: number\n sample_freq?: string\n max_waiting?: number\n max_ack_pending?: number\n headers_only?: boolean\n max_batch?: number\n max_expires?: number // nanoseconds\n max_bytes?: number\n inactive_threshold?: number // nanoseconds\n backoff?: number[] // nanoseconds\n num_replicas?: number\n mem_storage?: boolean\n metadata?: Record<string, string>\n}\n\n// Default consumer config helper\nexport function defaultConsumerConfig(): ConsumerConfig {\n return {\n ack_policy: 'explicit',\n deliver_policy: 'all',\n replay_policy: 'instant',\n ack_wait: 30 * 1_000_000_000, // 30 seconds in nanos\n max_deliver: -1,\n max_ack_pending: 1000,\n max_waiting: 512,\n }\n}\n\n// Sequence pair for consumer tracking\nexport interface SequencePair {\n consumer_seq: number\n stream_seq: number\n}\n\n// Consumer info\nexport interface ConsumerInfo {\n stream_name: string\n name: string\n config: ConsumerConfig\n created: string\n delivered: SequencePair\n ack_floor: SequencePair\n num_ack_pending: number\n num_redelivered: number\n num_waiting: number\n num_pending: number\n cluster?: {\n name?: string\n leader?: string\n }\n push_bound?: boolean\n}\n\n// Publish acknowledgment\nexport interface PubAck {\n stream: string\n seq: number\n duplicate?: boolean\n domain?: string\n}\n\n// JetStream message info\nexport interface JsMsgInfo {\n stream: string\n consumer: string\n delivered: number\n streamSequence: number\n consumerSequence: number\n timestampNanos: bigint\n pending: number\n redelivered: boolean\n redeliveryCount?: number\n}\n\n// JetStream message\nexport interface JsMsg {\n subject: string\n data: Uint8Array\n headers?: import('./nats').MsgHdrs\n seq: number\n info: JsMsgInfo\n ack(): void\n nak(delay?: number): void\n working(): void\n term(reason?: string): void\n ackAck(): Promise<boolean>\n string?(): string\n json?<T = unknown>(): T\n}\n\n// Pull options for fetch\nexport interface PullOptions {\n max_messages?: number\n max_bytes?: number\n expires?: number // milliseconds\n idle_heartbeat?: number // milliseconds\n batch?: number\n no_wait?: boolean\n}\n\n// Consume options\nexport interface ConsumeOptions {\n max_messages?: number\n max_bytes?: number\n expires?: number\n idle_heartbeat?: number\n callback?: (msg: JsMsg) => void | Promise<void>\n}\n\n// Consumer messages iterator\nexport interface ConsumerMessages extends AsyncIterable<JsMsg> {\n close(): Promise<void>\n stop(): Promise<void>\n}\n\n// Stream interface\nexport interface Stream {\n info(cached?: boolean): Promise<StreamInfo>\n getMessage(query: {\n seq?: number\n last_by_subj?: string\n next_by_subj?: string\n }): Promise<StoredMsg | null>\n deleteMessage(seq: number, erase?: boolean): Promise<boolean>\n}\n\n// Stored message\nexport interface StoredMsg {\n subject: string\n data: Uint8Array\n headers?: import('./nats').MsgHdrs\n seq: number\n time: string\n}\n\n// Consumer interface\nexport interface Consumer {\n info(cached?: boolean): Promise<ConsumerInfo>\n consume(opts?: ConsumeOptions): Promise<ConsumerMessages>\n fetch(opts?: PullOptions): Promise<ConsumerMessages>\n delete(): Promise<boolean>\n}\n\n// Purge response\nexport interface PurgeResponse {\n success: boolean\n purged: number\n}\n\n// Streams API\nexport interface StreamsAPI {\n add(config: StreamConfig): Promise<StreamInfo>\n update(config: StreamConfig): Promise<StreamInfo>\n delete(stream: string): Promise<boolean>\n get(stream: string): Promise<Stream>\n list(): AsyncIterable<StreamInfo>\n info(stream: string): Promise<StreamInfo>\n names(): AsyncIterable<string>\n purge(stream: string, opts?: { filter?: string; seq?: number; keep?: number }): Promise<PurgeResponse>\n}\n\n// Consumers API\nexport interface ConsumersAPI {\n add(stream: string, config: ConsumerConfig): Promise<ConsumerInfo>\n update(stream: string, config: ConsumerConfig): Promise<ConsumerInfo>\n delete(stream: string, consumer: string): Promise<boolean>\n list(stream: string): AsyncIterable<ConsumerInfo>\n info(stream: string, consumer: string): Promise<ConsumerInfo>\n}\n\n// JetStream manager\nexport interface JetStreamManager {\n streams: StreamsAPI\n consumers: ConsumersAPI\n}\n\n// Consumers accessor for JetStreamClient\nexport interface ConsumersAccessor {\n get(stream: string, consumer: string): Promise<Consumer>\n}\n\n// Streams accessor for JetStreamClient\nexport interface StreamsAccessor {\n get(stream: string): Promise<Stream>\n}\n\n// JetStream publish options\nexport interface JetStreamPublishOptions {\n msgID?: string\n expect?: {\n lastMsgID?: string\n lastSequence?: number\n lastSubjectSequence?: number\n streamName?: string\n }\n headers?: import('./nats').MsgHdrs\n timeout?: number\n}\n\n// JetStream client\nexport interface JetStreamClient {\n publish(\n subject: string,\n data?: Uint8Array,\n opts?: JetStreamPublishOptions\n ): Promise<PubAck>\n consumers: ConsumersAccessor\n streams: StreamsAccessor\n}\n","/**\n * RPC Types\n *\n * JSON-RPC 2.0 types for NatDO communication.\n */\n\n// Request ID type\nexport type RpcId = string | number\n\n// RPC Request\nexport interface RpcRequest {\n jsonrpc: '2.0'\n method: string\n params?: Record<string, unknown> | unknown[]\n id: RpcId\n}\n\n// RPC Notification (no id)\nexport interface RpcNotification {\n jsonrpc: '2.0'\n method: string\n params?: Record<string, unknown> | unknown[]\n}\n\n// RPC Error\nexport interface RpcError {\n code: number\n message: string\n data?: unknown\n}\n\n// RPC Response\nexport interface RpcResponse {\n jsonrpc: '2.0'\n result?: unknown\n error?: RpcError\n id: RpcId | null\n}\n\n// Batch types\nexport type RpcBatchRequest = Array<RpcRequest | RpcNotification>\nexport type RpcBatchResponse = RpcResponse[]\n\n// Standard JSON-RPC 2.0 error codes\nexport const RPC_ERROR_CODES = {\n // Standard JSON-RPC errors\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n\n // NATS-specific error codes (-32001 to -32099)\n STREAM_NOT_FOUND: -32001,\n CONSUMER_NOT_FOUND: -32002,\n NO_RESPONDERS: -32003,\n TIMEOUT: -32004,\n MESSAGE_NOT_FOUND: -32005,\n STREAM_EXISTS: -32006,\n CONSUMER_EXISTS: -32007,\n INVALID_SUBJECT: -32008,\n PERMISSION_DENIED: -32009,\n MAX_PAYLOAD_EXCEEDED: -32010,\n DUPLICATE_MESSAGE: -32011,\n STREAM_SEALED: -32012,\n CONSUMER_DELETED: -32013,\n} as const\n\n// Type guard for error responses\nexport function isRpcError(response: RpcResponse): response is RpcResponse & { error: RpcError } {\n return 'error' in response && response.error !== undefined\n}\n\n// Type guard for success responses\nexport function isRpcSuccess(response: RpcResponse): response is RpcResponse & { result: unknown } {\n return !isRpcError(response)\n}\n\n// Request ID counter for auto-incrementing IDs\nlet requestIdCounter = 0\n\n// Create RPC request helper\nexport function createRpcRequest(\n method: string,\n opts?: { params?: Record<string, unknown> | unknown[]; id?: RpcId }\n): RpcRequest {\n return {\n jsonrpc: '2.0',\n method,\n ...(opts?.params && { params: opts.params }),\n id: opts?.id ?? ++requestIdCounter,\n }\n}\n\n// Create RPC error response helper\nexport function createRpcError(\n code: number,\n message: string,\n id?: RpcId | null,\n data?: unknown\n): RpcResponse {\n return {\n jsonrpc: '2.0',\n error: {\n code,\n message,\n ...(data !== undefined && { data }),\n },\n id: id ?? null,\n }\n}\n\n// Create RPC success response helper\nexport function createRpcSuccess(result: unknown, id: RpcId): RpcResponse {\n return {\n jsonrpc: '2.0',\n result,\n id,\n }\n}\n\n// Reset request ID counter (for testing)\nexport function resetRequestIdCounter(): void {\n requestIdCounter = 0\n}\n"]}
|