otter-types 0.1.2

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 ADDED
@@ -0,0 +1,36 @@
1
+ # otter-types
2
+
3
+ TypeScript definitions for [Otter](https://github.com/octofhir/otter) runtime.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install otter-types
9
+ ```
10
+
11
+ This package depends on `@types/node` for Web API and Node.js type definitions.
12
+
13
+ ## Usage
14
+
15
+ Types are automatically available when you install this package. For best results, use this `tsconfig.json`:
16
+
17
+ ```json
18
+ {
19
+ "compilerOptions": {
20
+ "target": "ES2022",
21
+ "module": "ESNext",
22
+ "moduleResolution": "bundler",
23
+ "lib": ["ES2022"],
24
+ "types": ["otter-types"],
25
+ "skipLibCheck": true
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## What's included
31
+
32
+ - **globals.d.ts** - CommonJS support (`require`, `module`, `exports`, `__dirname`, `__filename`)
33
+ - **sql.d.ts** - SQL and KV store APIs
34
+ - **serve.d.ts** - HTTP server APIs (`Otter.serve()`)
35
+
36
+ Web APIs (fetch, URL, TextEncoder, etc.) and Node.js APIs (fs, path, etc.) come from `@types/node`.
package/globals.d.ts ADDED
@@ -0,0 +1,104 @@
1
+ // Otter Runtime - Global Type Definitions
2
+ // Only includes Otter-specific globals, Web APIs come from @types/node
3
+
4
+ declare global {
5
+ // ============================================================================
6
+ // CommonJS Support
7
+ // ============================================================================
8
+
9
+ /**
10
+ * Require a CommonJS module.
11
+ * @param id Module specifier (path or package name)
12
+ * @returns The module's exports
13
+ */
14
+ function require(id: string): any;
15
+
16
+ /**
17
+ * The require function interface with additional properties.
18
+ */
19
+ interface NodeRequire {
20
+ (id: string): any;
21
+
22
+ /**
23
+ * Resolve a module path to its absolute path.
24
+ */
25
+ resolve(id: string): string;
26
+
27
+ /**
28
+ * Module cache - loaded modules are cached here.
29
+ */
30
+ cache: Record<string, NodeModule>;
31
+
32
+ /**
33
+ * The main module (entry point).
34
+ */
35
+ main: NodeModule | undefined;
36
+ }
37
+
38
+ /**
39
+ * The module object available in CommonJS modules.
40
+ */
41
+ interface NodeModule {
42
+ /**
43
+ * The module's exports object.
44
+ */
45
+ exports: any;
46
+
47
+ /**
48
+ * The require function for this module.
49
+ */
50
+ require: NodeRequire;
51
+
52
+ /**
53
+ * The module's unique identifier.
54
+ */
55
+ id: string;
56
+
57
+ /**
58
+ * The absolute path to the module file.
59
+ */
60
+ filename: string;
61
+
62
+ /**
63
+ * Whether the module has finished loading.
64
+ */
65
+ loaded: boolean;
66
+
67
+ /**
68
+ * The module that first required this one.
69
+ */
70
+ parent: NodeModule | null;
71
+
72
+ /**
73
+ * Modules that have been required by this module.
74
+ */
75
+ children: NodeModule[];
76
+
77
+ /**
78
+ * The search paths for modules.
79
+ */
80
+ paths: string[];
81
+ }
82
+
83
+ /**
84
+ * The module object - available in CommonJS modules.
85
+ */
86
+ var module: NodeModule;
87
+
88
+ /**
89
+ * Alias to module.exports - available in CommonJS modules.
90
+ */
91
+ var exports: any;
92
+
93
+ /**
94
+ * The directory name of the current module - available in CommonJS modules.
95
+ */
96
+ var __dirname: string;
97
+
98
+ /**
99
+ * The file name of the current module - available in CommonJS modules.
100
+ */
101
+ var __filename: string;
102
+ }
103
+
104
+ export {};
package/index.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ // Otter Runtime Type Definitions
2
+ // Entry point for @types/otter
3
+
4
+ /// <reference types="node" />
5
+
6
+ /// <reference path="./globals.d.ts" />
7
+ /// <reference path="./sql.d.ts" />
8
+ /// <reference path="./serve.d.ts" />
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "otter-types",
3
+ "version": "0.1.2",
4
+ "description": "TypeScript definitions for Otter runtime",
5
+ "types": "./index.d.ts",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/octofhir/otter",
10
+ "directory": "packages/otter-types"
11
+ },
12
+ "keywords": ["otter", "javascript", "typescript", "types", "runtime"],
13
+ "dependencies": {
14
+ "@types/node": "*"
15
+ }
16
+ }
package/serve.d.ts ADDED
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Otter.serve() - High-performance HTTP/HTTPS server
3
+ *
4
+ * Supports HTTP/1.1 and HTTP/2 with ALPN negotiation for TLS connections.
5
+ */
6
+
7
+ declare namespace Otter {
8
+ /**
9
+ * TLS configuration for HTTPS support.
10
+ */
11
+ interface TlsOptions {
12
+ /**
13
+ * PEM-encoded certificate chain.
14
+ */
15
+ cert: string | Uint8Array;
16
+
17
+ /**
18
+ * PEM-encoded private key.
19
+ */
20
+ key: string | Uint8Array;
21
+ }
22
+
23
+ /**
24
+ * Options for Otter.serve()
25
+ */
26
+ interface ServeOptions {
27
+ /**
28
+ * Port to listen on.
29
+ * Use 0 to get a random available port.
30
+ * @default 3000
31
+ */
32
+ port?: number;
33
+
34
+ /**
35
+ * Hostname to bind to.
36
+ * @default "0.0.0.0"
37
+ */
38
+ hostname?: string;
39
+
40
+ /**
41
+ * Request handler function.
42
+ * Called for each incoming HTTP request.
43
+ *
44
+ * @param request - The incoming request
45
+ * @returns A Response object or a Promise that resolves to one
46
+ */
47
+ fetch(request: Request): Response | Promise<Response>;
48
+
49
+ /**
50
+ * Error handler function.
51
+ * Called when the fetch handler throws an error.
52
+ *
53
+ * @param error - The error that was thrown
54
+ * @returns A Response object to send, or void to use default 500 response
55
+ */
56
+ error?(error: Error): Response | void;
57
+
58
+ /**
59
+ * TLS configuration for HTTPS.
60
+ * If provided, the server will use HTTPS with HTTP/2 support via ALPN.
61
+ */
62
+ tls?: TlsOptions;
63
+ }
64
+
65
+ /**
66
+ * A running HTTP server instance.
67
+ */
68
+ interface Server {
69
+ /**
70
+ * The actual port the server is listening on.
71
+ * Useful when port 0 was specified to get a random port.
72
+ */
73
+ readonly port: number;
74
+
75
+ /**
76
+ * The hostname the server is bound to.
77
+ */
78
+ readonly hostname: string;
79
+
80
+ /**
81
+ * The full URL of the server.
82
+ */
83
+ readonly url: string;
84
+
85
+ /**
86
+ * Stop the server gracefully.
87
+ * Existing connections will be allowed to complete.
88
+ */
89
+ stop(): void;
90
+
91
+ /**
92
+ * Reload the server with new options.
93
+ * Only fetch and error handlers can be changed.
94
+ *
95
+ * @param options - New options to apply
96
+ */
97
+ reload(options: Partial<Pick<ServeOptions, "fetch" | "error">>): void;
98
+ }
99
+
100
+ /**
101
+ * Start an HTTP/HTTPS server.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * // Basic HTTP server
106
+ * const server = await Otter.serve({
107
+ * port: 3000,
108
+ * fetch(req) {
109
+ * return new Response("Hello World!");
110
+ * }
111
+ * });
112
+ *
113
+ * // HTTPS server with HTTP/2
114
+ * const httpsServer = await Otter.serve({
115
+ * port: 443,
116
+ * tls: {
117
+ * cert: await Otter.file("cert.pem").text(),
118
+ * key: await Otter.file("key.pem").text()
119
+ * },
120
+ * fetch(req) {
121
+ * return new Response("Secure!");
122
+ * }
123
+ * });
124
+ *
125
+ * // Random port
126
+ * const server = await Otter.serve({
127
+ * port: 0,
128
+ * fetch(req) {
129
+ * return new Response("Running on port " + server.port);
130
+ * }
131
+ * });
132
+ * console.log(`Server running at ${server.url}`);
133
+ * ```
134
+ *
135
+ * @param options - Server configuration
136
+ * @returns A promise that resolves to a Server instance
137
+ */
138
+ function serve(options: ServeOptions): Promise<Server>;
139
+
140
+ /**
141
+ * Server class constructor (for instanceof checks).
142
+ */
143
+ const Server: {
144
+ prototype: Server;
145
+ };
146
+ }
package/sql.d.ts ADDED
@@ -0,0 +1,396 @@
1
+ /**
2
+ * Otter SQL API
3
+ *
4
+ * Provides unified SQLite and PostgreSQL support with tagged template queries,
5
+ * transactions, and COPY operations (PostgreSQL only).
6
+ */
7
+
8
+ // ============================================================================
9
+ // SQL Module
10
+ // ============================================================================
11
+
12
+ declare module "otter" {
13
+ /**
14
+ * Default SQL tagged template function.
15
+ * Uses DATABASE_URL environment variable or falls back to SQLite :memory:.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { sql } from "otter";
20
+ *
21
+ * const users = await sql`SELECT * FROM users`;
22
+ * const user = await sql`SELECT * FROM users WHERE id = ${userId}`;
23
+ * ```
24
+ */
25
+ export const sql: SqlTaggedTemplate & SqlHelpers;
26
+
27
+ /**
28
+ * SQL class for creating database connections.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { SQL } from "otter";
33
+ *
34
+ * const db = new SQL(":memory:");
35
+ * const pg = new SQL("postgres://localhost/mydb");
36
+ * ```
37
+ */
38
+ export class SQL {
39
+ constructor(url: string);
40
+ constructor(options: SQLOptions);
41
+
42
+ /** Execute a tagged template query and return results */
43
+ query<T = any>(
44
+ strings: TemplateStringsArray,
45
+ ...values: any[]
46
+ ): Promise<T[]>;
47
+
48
+ /** Execute a tagged template statement and return affected rows */
49
+ execute(strings: TemplateStringsArray, ...values: any[]): Promise<number>;
50
+
51
+ /**
52
+ * Begin a transaction.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * await db.begin(async (tx) => {
57
+ * await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
58
+ * await tx`UPDATE accounts SET balance = balance - 100`;
59
+ * // auto-commit on success, auto-rollback on error
60
+ * });
61
+ * ```
62
+ */
63
+ begin<T>(fn: (tx: Transaction) => Promise<T>): Promise<T>;
64
+
65
+ /**
66
+ * Reserve a connection for exclusive use.
67
+ */
68
+ reserve(): Promise<ReservedSQL>;
69
+
70
+ /**
71
+ * COPY FROM - bulk import data (PostgreSQL only).
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * await pg.copyFrom("users", {
76
+ * columns: ["name", "email"],
77
+ * format: "csv",
78
+ * source: new Blob(["Alice,alice@example.com\n"]),
79
+ * });
80
+ * ```
81
+ */
82
+ copyFrom(table: string, options: CopyFromOptions): Promise<number>;
83
+
84
+ /**
85
+ * COPY TO - bulk export data (PostgreSQL only).
86
+ * Returns an async iterable of chunks.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * for await (const chunk of await pg.copyTo("users", { format: "csv" })) {
91
+ * process.stdout.write(chunk);
92
+ * }
93
+ * ```
94
+ */
95
+ copyTo(
96
+ table: string,
97
+ options?: CopyToOptions,
98
+ ): Promise<AsyncIterable<Uint8Array>>;
99
+
100
+ /**
101
+ * COPY TO with a query (PostgreSQL only).
102
+ */
103
+ copyToQuery(
104
+ query: string,
105
+ options?: CopyToOptions,
106
+ ): Promise<AsyncIterable<Uint8Array>>;
107
+
108
+ /**
109
+ * Close all connections.
110
+ */
111
+ close(options?: { timeout?: number }): Promise<void>;
112
+
113
+ /** Get the adapter type ("sqlite" or "postgres") */
114
+ readonly adapter: "sqlite" | "postgres";
115
+
116
+ /** PostgreSQL error class */
117
+ static PostgresError: typeof PostgresError;
118
+
119
+ /** SQLite error class */
120
+ static SQLiteError: typeof SQLiteError;
121
+ }
122
+
123
+ /**
124
+ * KV store function.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * import { kv } from "otter";
129
+ *
130
+ * const store = kv("./data.kv");
131
+ * const cache = kv(":memory:");
132
+ * ```
133
+ */
134
+ export function kv(path: string): KVStore;
135
+
136
+ // ============================================================================
137
+ // SQL Types
138
+ // ============================================================================
139
+
140
+ /**
141
+ * Tagged template function for SQL queries.
142
+ */
143
+ interface SqlTaggedTemplate {
144
+ <T = any>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
145
+ }
146
+
147
+ /**
148
+ * SQL helper functions.
149
+ */
150
+ interface SqlHelpers {
151
+ /**
152
+ * Escape an identifier (table/column name).
153
+ */
154
+ (value: string): SqlIdentifier;
155
+
156
+ /**
157
+ * Insert object values.
158
+ */
159
+ (value: object, ...columns: string[]): SqlObjectInsert;
160
+
161
+ /**
162
+ * Insert array of values (for IN clause) or bulk insert.
163
+ */
164
+ (value: any[]): SqlArrayValues;
165
+
166
+ /**
167
+ * Create a PostgreSQL array literal.
168
+ */
169
+ array(values: any[]): SqlArray;
170
+
171
+ /**
172
+ * Raw SQL (use with caution!).
173
+ */
174
+ raw(sql: string): SqlRaw;
175
+ }
176
+
177
+ interface SqlIdentifier {
178
+ __sql_type: "identifier";
179
+ value: string;
180
+ }
181
+
182
+ interface SqlObjectInsert {
183
+ __sql_type: "object_insert";
184
+ values: object | object[];
185
+ columns: string[] | null;
186
+ }
187
+
188
+ interface SqlArrayValues {
189
+ __sql_type: "array_in" | "object_insert";
190
+ values: any[];
191
+ columns?: string[] | null;
192
+ }
193
+
194
+ interface SqlArray {
195
+ __sql_type: "array_values";
196
+ values: any[];
197
+ }
198
+
199
+ interface SqlRaw {
200
+ __sql_type: "raw";
201
+ value: string;
202
+ }
203
+
204
+ /**
205
+ * SQL connection options.
206
+ */
207
+ interface SQLOptions {
208
+ /** Database adapter type */
209
+ adapter?: "postgres" | "sqlite";
210
+ /** Hostname for PostgreSQL */
211
+ hostname?: string;
212
+ /** Port for PostgreSQL */
213
+ port?: number;
214
+ /** Database name */
215
+ database?: string;
216
+ /** Username for PostgreSQL */
217
+ username?: string;
218
+ /** Password for PostgreSQL */
219
+ password?: string;
220
+ /** SSL mode for PostgreSQL */
221
+ ssl?: "disable" | "prefer" | "require";
222
+ /** Maximum connections for PostgreSQL pool */
223
+ max?: number;
224
+ /** Idle timeout in seconds */
225
+ idleTimeout?: number;
226
+ /** Connection timeout in seconds */
227
+ connectionTimeout?: number;
228
+ }
229
+
230
+ /**
231
+ * SQL transaction.
232
+ */
233
+ interface Transaction {
234
+ /** Execute a query within the transaction */
235
+ <T = any>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
236
+
237
+ /** Execute a query within the transaction */
238
+ query<T = any>(
239
+ strings: TemplateStringsArray,
240
+ ...values: any[]
241
+ ): Promise<T[]>;
242
+
243
+ /**
244
+ * Create a savepoint.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * await tx.savepoint(async (sp) => {
249
+ * await sp`UPDATE users SET status = 'active'`;
250
+ * if (error) throw new Error("rollback to savepoint");
251
+ * });
252
+ * ```
253
+ */
254
+ savepoint<T>(fn: (sp: Transaction) => Promise<T>): Promise<T>;
255
+ }
256
+
257
+ /**
258
+ * Reserved SQL connection.
259
+ */
260
+ interface ReservedSQL {
261
+ /** Execute a query on the reserved connection */
262
+ query<T = any>(
263
+ strings: TemplateStringsArray,
264
+ ...values: any[]
265
+ ): Promise<T[]>;
266
+
267
+ /** Release the connection back to the pool */
268
+ release(): void;
269
+ }
270
+
271
+ /**
272
+ * COPY FROM options.
273
+ */
274
+ interface CopyFromOptions {
275
+ /** Column names */
276
+ columns?: string[];
277
+ /** Data format */
278
+ format?: "text" | "csv" | "binary";
279
+ /** Whether the data has a header row */
280
+ header?: boolean;
281
+ /** Column delimiter */
282
+ delimiter?: string;
283
+ /** Data source (string, Blob, or object with text() method) */
284
+ source: string | Blob | { text(): Promise<string> };
285
+ /** Called when COPY starts */
286
+ onCopyStart?: (info: { columns: string[] }) => void;
287
+ /** Called for each chunk */
288
+ onCopyChunk?: (bytes: number) => void;
289
+ /** Called when COPY completes */
290
+ onCopyEnd?: (result: { rowsCopied: number }) => void;
291
+ }
292
+
293
+ /**
294
+ * COPY TO options.
295
+ */
296
+ interface CopyToOptions {
297
+ /** Column names */
298
+ columns?: string[];
299
+ /** Data format */
300
+ format?: "text" | "csv" | "binary";
301
+ /** Whether to include a header row */
302
+ header?: boolean;
303
+ /** Column delimiter */
304
+ delimiter?: string;
305
+ }
306
+
307
+ /**
308
+ * PostgreSQL error.
309
+ */
310
+ class PostgresError extends Error {
311
+ name: "PostgresError";
312
+ /** PostgreSQL error code (e.g., "42P01" for undefined table) */
313
+ code: string;
314
+ /** Detailed error message */
315
+ detail?: string;
316
+ /** Hint for fixing the error */
317
+ hint?: string;
318
+ }
319
+
320
+ /**
321
+ * SQLite error.
322
+ */
323
+ class SQLiteError extends Error {
324
+ name: "SQLiteError";
325
+ /** SQLite error code (e.g., "SQLITE_CONSTRAINT") */
326
+ code: string;
327
+ }
328
+
329
+ // ============================================================================
330
+ // KV Store Types
331
+ // ============================================================================
332
+
333
+ /**
334
+ * Key-value store.
335
+ */
336
+ interface KVStore {
337
+ /**
338
+ * Set a value for a key.
339
+ * @param key The key
340
+ * @param value The value (will be JSON serialized)
341
+ */
342
+ set(key: string, value: any): void;
343
+
344
+ /**
345
+ * Get a value by key.
346
+ * @param key The key
347
+ * @returns The value, or undefined if not found
348
+ */
349
+ get(key: string): any;
350
+
351
+ /**
352
+ * Delete a key.
353
+ * @param key The key
354
+ * @returns True if the key existed
355
+ */
356
+ delete(key: string): boolean;
357
+
358
+ /**
359
+ * Check if a key exists.
360
+ * @param key The key
361
+ * @returns True if the key exists
362
+ */
363
+ has(key: string): boolean;
364
+
365
+ /**
366
+ * Get all keys.
367
+ * @returns Array of keys
368
+ */
369
+ keys(): string[];
370
+
371
+ /**
372
+ * Clear all keys.
373
+ */
374
+ clear(): void;
375
+
376
+ /**
377
+ * Get the number of keys.
378
+ */
379
+ readonly size: number;
380
+
381
+ /**
382
+ * Close the store.
383
+ */
384
+ close(): void;
385
+
386
+ /**
387
+ * Get the path to the store.
388
+ */
389
+ readonly path: string;
390
+
391
+ /**
392
+ * Check if the store is closed.
393
+ */
394
+ readonly isClosed: boolean;
395
+ }
396
+ }