duckpond 0.3.0 → 0.4.1

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.
Files changed (63) hide show
  1. package/dist/DuckPond.d.ts +76 -79
  2. package/dist/DuckPond.js +29 -1
  3. package/dist/DuckPond.js.map +1 -1
  4. package/dist/LRUCache-Bg_8n4IH.js +2 -0
  5. package/dist/LRUCache-Bg_8n4IH.js.map +1 -0
  6. package/dist/cache/LRUCache.d.ts +107 -69
  7. package/dist/cache/LRUCache.js +1 -2
  8. package/dist/index.d.ts +10 -12
  9. package/dist/index.js +1 -2
  10. package/dist/types.d.ts +117 -114
  11. package/dist/types.js +1 -1
  12. package/dist/types.js.map +1 -1
  13. package/dist/utils/errors.d.ts +18 -18
  14. package/dist/utils/errors.js +2 -1
  15. package/dist/utils/errors.js.map +1 -1
  16. package/dist/utils/logger.d.ts +11 -8
  17. package/dist/utils/logger.js +1 -1
  18. package/dist/utils/logger.js.map +1 -1
  19. package/package.json +33 -46
  20. package/dist/DuckPond.d.mts +0 -83
  21. package/dist/DuckPond.mjs +0 -2
  22. package/dist/DuckPond.mjs.map +0 -1
  23. package/dist/cache/LRUCache.d.mts +0 -75
  24. package/dist/cache/LRUCache.js.map +0 -1
  25. package/dist/cache/LRUCache.mjs +0 -2
  26. package/dist/cache/LRUCache.mjs.map +0 -1
  27. package/dist/chunk-24M54WUC.mjs +0 -2
  28. package/dist/chunk-24M54WUC.mjs.map +0 -1
  29. package/dist/chunk-5XGN7UAV.js +0 -2
  30. package/dist/chunk-5XGN7UAV.js.map +0 -1
  31. package/dist/chunk-BA7KCST7.mjs +0 -30
  32. package/dist/chunk-BA7KCST7.mjs.map +0 -1
  33. package/dist/chunk-GXQJHTJW.mjs +0 -2
  34. package/dist/chunk-GXQJHTJW.mjs.map +0 -1
  35. package/dist/chunk-HFWFDMZL.js +0 -30
  36. package/dist/chunk-HFWFDMZL.js.map +0 -1
  37. package/dist/chunk-J2OQ62DV.js +0 -2
  38. package/dist/chunk-J2OQ62DV.js.map +0 -1
  39. package/dist/chunk-LG2XWWAP.js +0 -2
  40. package/dist/chunk-LG2XWWAP.js.map +0 -1
  41. package/dist/chunk-MZTKR3LR.js +0 -3
  42. package/dist/chunk-MZTKR3LR.js.map +0 -1
  43. package/dist/chunk-PCQEPXO3.mjs +0 -3
  44. package/dist/chunk-PCQEPXO3.mjs.map +0 -1
  45. package/dist/chunk-Q6UFPTQC.js +0 -2
  46. package/dist/chunk-Q6UFPTQC.js.map +0 -1
  47. package/dist/chunk-SZJXSB7U.mjs +0 -2
  48. package/dist/chunk-SZJXSB7U.mjs.map +0 -1
  49. package/dist/chunk-V57JCP3U.mjs +0 -2
  50. package/dist/chunk-V57JCP3U.mjs.map +0 -1
  51. package/dist/index.d.mts +0 -12
  52. package/dist/index.js.map +0 -1
  53. package/dist/index.mjs +0 -2
  54. package/dist/index.mjs.map +0 -1
  55. package/dist/types.d.mts +0 -194
  56. package/dist/types.mjs +0 -2
  57. package/dist/types.mjs.map +0 -1
  58. package/dist/utils/errors.d.mts +0 -41
  59. package/dist/utils/errors.mjs +0 -2
  60. package/dist/utils/errors.mjs.map +0 -1
  61. package/dist/utils/logger.d.mts +0 -25
  62. package/dist/utils/logger.mjs +0 -2
  63. package/dist/utils/logger.mjs.map +0 -1
package/dist/types.d.ts CHANGED
@@ -1,145 +1,147 @@
1
- import { DuckDBConnection } from '@duckdb/node-api';
2
- import { Either } from 'functype/either';
3
- import { List } from 'functype/list';
1
+ import { DuckDBConnection } from "@duckdb/node-api";
2
+ import { List } from "functype/list";
3
+ import { Either } from "functype/either";
4
+
5
+ //#region src/types.d.ts
4
6
 
5
7
  /**
6
8
  * Configuration for DuckPond manager
7
9
  */
8
10
  interface DuckPondConfig {
9
- r2?: {
10
- accountId: string;
11
- accessKeyId: string;
12
- secretAccessKey: string;
13
- bucket: string;
14
- };
15
- s3?: {
16
- region: string;
17
- accessKeyId: string;
18
- secretAccessKey: string;
19
- bucket: string;
20
- endpoint?: string;
21
- };
22
- memoryLimit?: string;
23
- threads?: number;
24
- tempDir?: string;
25
- dataDir?: string;
26
- maxActiveUsers?: number;
27
- evictionTimeout?: number;
28
- cacheType?: "disk" | "memory" | "noop";
29
- cacheDir?: string;
30
- strategy?: "parquet" | "duckdb" | "hybrid";
11
+ r2?: {
12
+ accountId: string;
13
+ accessKeyId: string;
14
+ secretAccessKey: string;
15
+ bucket: string;
16
+ };
17
+ s3?: {
18
+ region: string;
19
+ accessKeyId: string;
20
+ secretAccessKey: string;
21
+ bucket: string;
22
+ endpoint?: string;
23
+ };
24
+ memoryLimit?: string;
25
+ threads?: number;
26
+ tempDir?: string;
27
+ dataDir?: string;
28
+ maxActiveUsers?: number;
29
+ evictionTimeout?: number;
30
+ cacheType?: "disk" | "memory" | "noop";
31
+ cacheDir?: string;
32
+ strategy?: "parquet" | "duckdb" | "hybrid";
31
33
  }
32
34
  /**
33
35
  * Represents an active user database connection
34
36
  */
35
37
  interface UserDatabase {
36
- userId: string;
37
- connection: DuckDBConnection;
38
- lastAccess: Date;
39
- attached: boolean;
40
- memoryUsage?: number;
38
+ userId: string;
39
+ connection: DuckDBConnection;
40
+ lastAccess: Date;
41
+ attached: boolean;
42
+ memoryUsage?: number;
41
43
  }
42
44
  /**
43
45
  * Statistics about a user's database
44
46
  */
45
47
  interface UserStats {
46
- userId: string;
47
- attached: boolean;
48
- lastAccess: Date;
49
- memoryUsage: number;
50
- storageUsage: number;
51
- queryCount: number;
48
+ userId: string;
49
+ attached: boolean;
50
+ lastAccess: Date;
51
+ memoryUsage: number;
52
+ storageUsage: number;
53
+ queryCount: number;
52
54
  }
53
55
  /**
54
56
  * Database schema information
55
57
  */
56
58
  interface Schema {
57
- tables: TableSchema[];
59
+ tables: TableSchema[];
58
60
  }
59
61
  interface TableSchema {
60
- name: string;
61
- columns: ColumnSchema[];
62
- rowCount?: number;
62
+ name: string;
63
+ columns: ColumnSchema[];
64
+ rowCount?: number;
63
65
  }
64
66
  interface ColumnSchema {
65
- name: string;
66
- type: string;
67
- nullable: boolean;
67
+ name: string;
68
+ type: string;
69
+ nullable: boolean;
68
70
  }
69
71
  /**
70
72
  * Options for creating a new user
71
73
  */
72
74
  interface CreateUserOptions {
73
- template?: string;
74
- initialData?: Record<string, unknown[]>;
75
- metadata?: Record<string, unknown>;
75
+ template?: string;
76
+ initialData?: Record<string, unknown[]>;
77
+ metadata?: Record<string, unknown>;
76
78
  }
77
79
  /**
78
80
  * Storage usage statistics
79
81
  */
80
82
  interface StorageStats {
81
- totalSize: number;
82
- fileCount: number;
83
- lastModified: Date;
84
- files?: FileInfo[];
83
+ totalSize: number;
84
+ fileCount: number;
85
+ lastModified: Date;
86
+ files?: FileInfo[];
85
87
  }
86
88
  interface FileInfo {
87
- path: string;
88
- size: number;
89
- modified: Date;
89
+ path: string;
90
+ size: number;
91
+ modified: Date;
90
92
  }
91
93
  /**
92
94
  * Query result with metadata
93
95
  */
94
96
  interface QueryResult<T = unknown> {
95
- rows: T[];
96
- rowCount: number;
97
- executionTime: number;
98
- columns: string[];
97
+ rows: T[];
98
+ rowCount: number;
99
+ executionTime: number;
100
+ columns: string[];
99
101
  }
100
102
  /**
101
103
  * Metrics for monitoring
102
104
  */
103
105
  interface DuckPondMetrics {
104
- activeUsers: number;
105
- totalQueries: number;
106
- avgQueryTime: number;
107
- cacheHitRate: number;
108
- memoryUsage: number;
109
- storageUsage: number;
106
+ activeUsers: number;
107
+ totalQueries: number;
108
+ avgQueryTime: number;
109
+ cacheHitRate: number;
110
+ memoryUsage: number;
111
+ storageUsage: number;
110
112
  }
111
113
  /**
112
114
  * Events emitted by DuckPond
113
115
  */
114
116
  type DuckPondEvent = {
115
- type: "user:attached";
116
- userId: string;
117
- timestamp: Date;
117
+ type: "user:attached";
118
+ userId: string;
119
+ timestamp: Date;
118
120
  } | {
119
- type: "user:detached";
120
- userId: string;
121
- reason: "eviction" | "manual";
122
- timestamp: Date;
121
+ type: "user:detached";
122
+ userId: string;
123
+ reason: "eviction" | "manual";
124
+ timestamp: Date;
123
125
  } | {
124
- type: "query:executed";
125
- userId: string;
126
- duration: number;
127
- timestamp: Date;
126
+ type: "query:executed";
127
+ userId: string;
128
+ duration: number;
129
+ timestamp: Date;
128
130
  } | {
129
- type: "query:failed";
130
- userId: string;
131
- error: string;
132
- timestamp: Date;
131
+ type: "query:failed";
132
+ userId: string;
133
+ error: string;
134
+ timestamp: Date;
133
135
  } | {
134
- type: "cache:hit";
135
- userId: string;
136
+ type: "cache:hit";
137
+ userId: string;
136
138
  } | {
137
- type: "cache:miss";
138
- userId: string;
139
+ type: "cache:miss";
140
+ userId: string;
139
141
  } | {
140
- type: "error";
141
- error: Error;
142
- timestamp: Date;
142
+ type: "error";
143
+ error: Error;
144
+ timestamp: Date;
143
145
  };
144
146
  /**
145
147
  * Type-safe result types using functype Either
@@ -150,45 +152,46 @@ type AsyncDuckPondResult<T> = Promise<Either<DuckPondError, T>>;
150
152
  * Error types
151
153
  */
152
154
  interface DuckPondError {
153
- code: ErrorCode;
154
- message: string;
155
- cause?: Error;
156
- context?: Record<string, unknown>;
155
+ code: ErrorCode;
156
+ message: string;
157
+ cause?: Error;
158
+ context?: Record<string, unknown>;
157
159
  }
158
160
  declare enum ErrorCode {
159
- CONNECTION_FAILED = "CONNECTION_FAILED",
160
- CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT",
161
- R2_CONNECTION_ERROR = "R2_CONNECTION_ERROR",
162
- S3_CONNECTION_ERROR = "S3_CONNECTION_ERROR",
163
- USER_NOT_FOUND = "USER_NOT_FOUND",
164
- USER_ALREADY_EXISTS = "USER_ALREADY_EXISTS",
165
- USER_NOT_ATTACHED = "USER_NOT_ATTACHED",
166
- QUERY_EXECUTION_ERROR = "QUERY_EXECUTION_ERROR",
167
- QUERY_TIMEOUT = "QUERY_TIMEOUT",
168
- INVALID_SQL = "INVALID_SQL",
169
- MEMORY_LIMIT_EXCEEDED = "MEMORY_LIMIT_EXCEEDED",
170
- STORAGE_ERROR = "STORAGE_ERROR",
171
- STORAGE_QUOTA_EXCEEDED = "STORAGE_QUOTA_EXCEEDED",
172
- INVALID_CONFIG = "INVALID_CONFIG",
173
- NOT_INITIALIZED = "NOT_INITIALIZED",
174
- UNKNOWN_ERROR = "UNKNOWN_ERROR"
161
+ CONNECTION_FAILED = "CONNECTION_FAILED",
162
+ CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT",
163
+ R2_CONNECTION_ERROR = "R2_CONNECTION_ERROR",
164
+ S3_CONNECTION_ERROR = "S3_CONNECTION_ERROR",
165
+ USER_NOT_FOUND = "USER_NOT_FOUND",
166
+ USER_ALREADY_EXISTS = "USER_ALREADY_EXISTS",
167
+ USER_NOT_ATTACHED = "USER_NOT_ATTACHED",
168
+ QUERY_EXECUTION_ERROR = "QUERY_EXECUTION_ERROR",
169
+ QUERY_TIMEOUT = "QUERY_TIMEOUT",
170
+ INVALID_SQL = "INVALID_SQL",
171
+ MEMORY_LIMIT_EXCEEDED = "MEMORY_LIMIT_EXCEEDED",
172
+ STORAGE_ERROR = "STORAGE_ERROR",
173
+ STORAGE_QUOTA_EXCEEDED = "STORAGE_QUOTA_EXCEEDED",
174
+ INVALID_CONFIG = "INVALID_CONFIG",
175
+ NOT_INITIALIZED = "NOT_INITIALIZED",
176
+ UNKNOWN_ERROR = "UNKNOWN_ERROR",
175
177
  }
176
178
  /**
177
179
  * Configuration with defaults applied
178
180
  */
179
181
  type ResolvedConfig = Required<Omit<DuckPondConfig, "r2" | "s3" | "dataDir"> & {
180
- r2: DuckPondConfig["r2"];
181
- s3: DuckPondConfig["s3"];
182
- dataDir: DuckPondConfig["dataDir"];
182
+ r2: DuckPondConfig["r2"];
183
+ s3: DuckPondConfig["s3"];
184
+ dataDir: DuckPondConfig["dataDir"];
183
185
  }>;
184
186
  /**
185
187
  * Result of listUsers operation
186
188
  */
187
189
  interface ListUsersResult {
188
- users: List<string>;
189
- count: number;
190
- maxActiveUsers: number;
191
- utilizationPercent: number;
190
+ users: List<string>;
191
+ count: number;
192
+ maxActiveUsers: number;
193
+ utilizationPercent: number;
192
194
  }
193
-
194
- export { type AsyncDuckPondResult, type ColumnSchema, type CreateUserOptions, type DuckPondConfig, type DuckPondError, type DuckPondEvent, type DuckPondMetrics, type DuckPondResult, ErrorCode, type FileInfo, type ListUsersResult, type QueryResult, type ResolvedConfig, type Schema, type StorageStats, type TableSchema, type UserDatabase, type UserStats };
195
+ //#endregion
196
+ export { AsyncDuckPondResult, ColumnSchema, CreateUserOptions, DuckPondConfig, DuckPondError, DuckPondEvent, DuckPondMetrics, DuckPondResult, ErrorCode, FileInfo, ListUsersResult, QueryResult, ResolvedConfig, Schema, StorageStats, TableSchema, UserDatabase, UserStats };
197
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkLG2XWWAPjs = require('./chunk-LG2XWWAP.js');require('./chunk-5XGN7UAV.js');exports.ErrorCode = _chunkLG2XWWAPjs.a;
1
+ let e=function(e){return e.CONNECTION_FAILED=`CONNECTION_FAILED`,e.CONNECTION_TIMEOUT=`CONNECTION_TIMEOUT`,e.R2_CONNECTION_ERROR=`R2_CONNECTION_ERROR`,e.S3_CONNECTION_ERROR=`S3_CONNECTION_ERROR`,e.USER_NOT_FOUND=`USER_NOT_FOUND`,e.USER_ALREADY_EXISTS=`USER_ALREADY_EXISTS`,e.USER_NOT_ATTACHED=`USER_NOT_ATTACHED`,e.QUERY_EXECUTION_ERROR=`QUERY_EXECUTION_ERROR`,e.QUERY_TIMEOUT=`QUERY_TIMEOUT`,e.INVALID_SQL=`INVALID_SQL`,e.MEMORY_LIMIT_EXCEEDED=`MEMORY_LIMIT_EXCEEDED`,e.STORAGE_ERROR=`STORAGE_ERROR`,e.STORAGE_QUOTA_EXCEEDED=`STORAGE_QUOTA_EXCEEDED`,e.INVALID_CONFIG=`INVALID_CONFIG`,e.NOT_INITIALIZED=`NOT_INITIALIZED`,e.UNKNOWN_ERROR=`UNKNOWN_ERROR`,e}({});export{e as ErrorCode};
2
2
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/jordanburke/IdeaProjects/duckpond/dist/types.js"],"names":[],"mappings":"AAAA,+HAAkC,+BAA4B,uCAAuB","file":"/Users/jordanburke/IdeaProjects/duckpond/dist/types.js"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["import type { DuckDBConnection } from \"@duckdb/node-api\"\nimport type { Either } from \"functype/either\"\nimport type { List } from \"functype/list\"\nimport type { Option } from \"functype/option\"\n\n/**\n * Configuration for DuckPond manager\n */\nexport interface DuckPondConfig {\n // R2 Configuration (Cloudflare)\n r2?: {\n accountId: string\n accessKeyId: string\n secretAccessKey: string\n bucket: string\n }\n\n // S3 Configuration (AWS)\n s3?: {\n region: string\n accessKeyId: string\n secretAccessKey: string\n bucket: string\n endpoint?: string // For S3-compatible services\n }\n\n // DuckDB Settings\n memoryLimit?: string // Default: '4GB'\n threads?: number // Default: 4\n tempDir?: string // Default: '/tmp/duckpond'\n\n // Local Storage\n dataDir?: string // Directory for persistent database files (enables local storage when set)\n\n // Cache Settings\n maxActiveUsers?: number // Default: 10\n evictionTimeout?: number // Default: 300000 (5 min in ms)\n cacheType?: \"disk\" | \"memory\" | \"noop\" // Default: 'disk'\n cacheDir?: string // Default: '/tmp/duckpond-cache'\n\n // Storage Strategy\n strategy?: \"parquet\" | \"duckdb\" | \"hybrid\" // Default: 'parquet'\n}\n\n/**\n * Represents an active user database connection\n */\nexport interface UserDatabase {\n userId: string\n connection: DuckDBConnection\n lastAccess: Date\n attached: boolean\n memoryUsage?: number\n}\n\n/**\n * Statistics about a user's database\n */\nexport interface UserStats {\n userId: string\n attached: boolean\n lastAccess: Date\n memoryUsage: number\n storageUsage: number\n queryCount: number\n}\n\n/**\n * Database schema information\n */\nexport interface Schema {\n tables: TableSchema[]\n}\n\nexport interface TableSchema {\n name: string\n columns: ColumnSchema[]\n rowCount?: number\n}\n\nexport interface ColumnSchema {\n name: string\n type: string\n nullable: boolean\n}\n\n/**\n * Options for creating a new user\n */\nexport interface CreateUserOptions {\n template?: string\n initialData?: Record<string, unknown[]>\n metadata?: Record<string, unknown>\n}\n\n/**\n * Storage usage statistics\n */\nexport interface StorageStats {\n totalSize: number\n fileCount: number\n lastModified: Date\n files?: FileInfo[]\n}\n\nexport interface FileInfo {\n path: string\n size: number\n modified: Date\n}\n\n/**\n * Query result with metadata\n */\nexport interface QueryResult<T = unknown> {\n rows: T[]\n rowCount: number\n executionTime: number\n columns: string[]\n}\n\n/**\n * Metrics for monitoring\n */\nexport interface DuckPondMetrics {\n activeUsers: number\n totalQueries: number\n avgQueryTime: number\n cacheHitRate: number\n memoryUsage: number\n storageUsage: number\n}\n\n/**\n * Events emitted by DuckPond\n */\nexport type DuckPondEvent =\n | { type: \"user:attached\"; userId: string; timestamp: Date }\n | { type: \"user:detached\"; userId: string; reason: \"eviction\" | \"manual\"; timestamp: Date }\n | { type: \"query:executed\"; userId: string; duration: number; timestamp: Date }\n | { type: \"query:failed\"; userId: string; error: string; timestamp: Date }\n | { type: \"cache:hit\"; userId: string }\n | { type: \"cache:miss\"; userId: string }\n | { type: \"error\"; error: Error; timestamp: Date }\n\n/**\n * Type-safe result types using functype Either\n */\nexport type DuckPondResult<T> = Either<DuckPondError, T>\nexport type AsyncDuckPondResult<T> = Promise<Either<DuckPondError, T>>\n\n/**\n * Error types\n */\nexport interface DuckPondError {\n code: ErrorCode\n message: string\n cause?: Error\n context?: Record<string, unknown>\n}\n\nexport enum ErrorCode {\n // Connection errors\n CONNECTION_FAILED = \"CONNECTION_FAILED\",\n CONNECTION_TIMEOUT = \"CONNECTION_TIMEOUT\",\n R2_CONNECTION_ERROR = \"R2_CONNECTION_ERROR\",\n S3_CONNECTION_ERROR = \"S3_CONNECTION_ERROR\",\n\n // User errors\n USER_NOT_FOUND = \"USER_NOT_FOUND\",\n USER_ALREADY_EXISTS = \"USER_ALREADY_EXISTS\",\n USER_NOT_ATTACHED = \"USER_NOT_ATTACHED\",\n\n // Query errors\n QUERY_EXECUTION_ERROR = \"QUERY_EXECUTION_ERROR\",\n QUERY_TIMEOUT = \"QUERY_TIMEOUT\",\n INVALID_SQL = \"INVALID_SQL\",\n\n // Resource errors\n MEMORY_LIMIT_EXCEEDED = \"MEMORY_LIMIT_EXCEEDED\",\n STORAGE_ERROR = \"STORAGE_ERROR\",\n STORAGE_QUOTA_EXCEEDED = \"STORAGE_QUOTA_EXCEEDED\",\n\n // Configuration errors\n INVALID_CONFIG = \"INVALID_CONFIG\",\n NOT_INITIALIZED = \"NOT_INITIALIZED\",\n\n // Unknown\n UNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\n/**\n * Configuration with defaults applied\n */\nexport type ResolvedConfig = Required<\n Omit<DuckPondConfig, \"r2\" | \"s3\" | \"dataDir\"> & {\n r2: DuckPondConfig[\"r2\"]\n s3: DuckPondConfig[\"s3\"]\n dataDir: DuckPondConfig[\"dataDir\"]\n }\n>\n\n/**\n * Result of listUsers operation\n */\nexport interface ListUsersResult {\n users: List<string> // List of cached user IDs (functype immutable list)\n count: number // Number of cached users\n maxActiveUsers: number // Maximum cache capacity\n utilizationPercent: number // Cache utilization (0-100)\n}\n"],"mappings":"AAiKA,IAAY,EAAA,SAAA,EAAL,OAEL,GAAA,kBAAA,oBACA,EAAA,mBAAA,qBACA,EAAA,oBAAA,sBACA,EAAA,oBAAA,sBAGA,EAAA,eAAA,iBACA,EAAA,oBAAA,sBACA,EAAA,kBAAA,oBAGA,EAAA,sBAAA,wBACA,EAAA,cAAA,gBACA,EAAA,YAAA,cAGA,EAAA,sBAAA,wBACA,EAAA,cAAA,gBACA,EAAA,uBAAA,yBAGA,EAAA,eAAA,iBACA,EAAA,gBAAA,kBAGA,EAAA,cAAA"}
@@ -1,8 +1,7 @@
1
- import { Either } from 'functype';
2
- import { ErrorCode, DuckPondError } from '../types.js';
3
- import '@duckdb/node-api';
4
- import 'functype/either';
5
- import 'functype/list';
1
+ import { DuckPondError, ErrorCode } from "../types.js";
2
+ import { Either } from "functype";
3
+
4
+ //#region src/utils/errors.d.ts
6
5
 
7
6
  /**
8
7
  * Create a DuckPondError as a Left Either
@@ -20,22 +19,23 @@ declare function toDuckPondError(error: unknown, defaultCode?: ErrorCode): DuckP
20
19
  * Error factory functions for common errors
21
20
  */
22
21
  declare const Errors: {
23
- connectionFailed: (message: string, cause?: Error) => Either<DuckPondError, never>;
24
- r2ConnectionError: (message: string, cause?: Error) => Either<DuckPondError, never>;
25
- s3ConnectionError: (message: string, cause?: Error) => Either<DuckPondError, never>;
26
- userNotFound: (userId: string) => Either<DuckPondError, never>;
27
- userAlreadyExists: (userId: string) => Either<DuckPondError, never>;
28
- userNotAttached: (userId: string) => Either<DuckPondError, never>;
29
- queryExecutionError: (message: string, sql?: string, cause?: Error) => Either<DuckPondError, never>;
30
- queryTimeout: (timeoutMs: number) => Either<DuckPondError, never>;
31
- memoryLimitExceeded: (limit: string) => Either<DuckPondError, never>;
32
- storageError: (message: string, cause?: Error) => Either<DuckPondError, never>;
33
- invalidConfig: (message: string) => Either<DuckPondError, never>;
34
- notInitialized: () => Either<DuckPondError, never>;
22
+ connectionFailed: (message: string, cause?: Error) => Either<DuckPondError, never>;
23
+ r2ConnectionError: (message: string, cause?: Error) => Either<DuckPondError, never>;
24
+ s3ConnectionError: (message: string, cause?: Error) => Either<DuckPondError, never>;
25
+ userNotFound: (userId: string) => Either<DuckPondError, never>;
26
+ userAlreadyExists: (userId: string) => Either<DuckPondError, never>;
27
+ userNotAttached: (userId: string) => Either<DuckPondError, never>;
28
+ queryExecutionError: (message: string, sql?: string, cause?: Error) => Either<DuckPondError, never>;
29
+ queryTimeout: (timeoutMs: number) => Either<DuckPondError, never>;
30
+ memoryLimitExceeded: (limit: string) => Either<DuckPondError, never>;
31
+ storageError: (message: string, cause?: Error) => Either<DuckPondError, never>;
32
+ invalidConfig: (message: string) => Either<DuckPondError, never>;
33
+ notInitialized: () => Either<DuckPondError, never>;
35
34
  };
36
35
  /**
37
36
  * Format an error for logging
38
37
  */
39
38
  declare function formatError(error: DuckPondError): string;
40
-
39
+ //#endregion
41
40
  export { Errors, createError, formatError, success, toDuckPondError };
41
+ //# sourceMappingURL=errors.d.ts.map
@@ -1,2 +1,3 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkMZTKR3LRjs = require('../chunk-MZTKR3LR.js');require('../chunk-LG2XWWAP.js');require('../chunk-5XGN7UAV.js');exports.Errors = _chunkMZTKR3LRjs.d; exports.createError = _chunkMZTKR3LRjs.a; exports.formatError = _chunkMZTKR3LRjs.e; exports.success = _chunkMZTKR3LRjs.b; exports.toDuckPondError = _chunkMZTKR3LRjs.c;
1
+ import{ErrorCode as e}from"../types.js";import{Left as t,Right as n}from"functype";function r(e,n,r,i){return t({code:e,message:n,cause:r,context:i})}function i(e){return n(e)}function a(t,n=e.UNKNOWN_ERROR){return t instanceof Error?{code:n,message:t.message,cause:t}:{code:n,message:String(t)}}const o={connectionFailed:(t,n)=>r(e.CONNECTION_FAILED,t,n),r2ConnectionError:(t,n)=>r(e.R2_CONNECTION_ERROR,t,n),s3ConnectionError:(t,n)=>r(e.S3_CONNECTION_ERROR,t,n),userNotFound:t=>r(e.USER_NOT_FOUND,`User not found: ${t}`,void 0,{userId:t}),userAlreadyExists:t=>r(e.USER_ALREADY_EXISTS,`User already exists: ${t}`,void 0,{userId:t}),userNotAttached:t=>r(e.USER_NOT_ATTACHED,`User not attached: ${t}`,void 0,{userId:t}),queryExecutionError:(t,n,i)=>r(e.QUERY_EXECUTION_ERROR,t,i,{sql:n}),queryTimeout:t=>r(e.QUERY_TIMEOUT,`Query timeout after ${t}ms`,void 0,{timeoutMs:t}),memoryLimitExceeded:t=>r(e.MEMORY_LIMIT_EXCEEDED,`Memory limit exceeded: ${t}`,void 0,{limit:t}),storageError:(t,n)=>r(e.STORAGE_ERROR,t,n),invalidConfig:t=>r(e.INVALID_CONFIG,t),notInitialized:()=>r(e.NOT_INITIALIZED,`DuckPond not initialized. Call init() first.`)};function s(e){let t=[`[${e.code}] ${e.message}`];return e.cause&&t.push(` Caused by: ${e.cause.message}`),e.context&&t.push(` Context: ${JSON.stringify(e.context)}`),t.join(`
2
+ `)}export{o as Errors,r as createError,s as formatError,i as success,a as toDuckPondError};
2
3
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/jordanburke/IdeaProjects/duckpond/dist/utils/errors.js"],"names":[],"mappings":"AAAA,gIAA2C,gCAA6B,gCAA6B,4MAAwF","file":"/Users/jordanburke/IdeaProjects/duckpond/dist/utils/errors.js"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/utils/errors.ts"],"sourcesContent":["import { type Either, Left, Right } from \"functype\"\n\nimport { DuckPondError, ErrorCode } from \"../types\"\n\n/**\n * Create a DuckPondError as a Left Either\n */\nexport function createError(\n code: ErrorCode,\n message: string,\n cause?: Error,\n context?: Record<string, unknown>,\n): Either<DuckPondError, never> {\n return Left({\n code,\n message,\n cause,\n context,\n })\n}\n\n/**\n * Wrap a value in a Right Either\n */\nexport function success<T = void>(value?: T): Either<DuckPondError, T extends void ? void : T> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Right(value) as any\n}\n\n/**\n * Convert an unknown error to a DuckPondError\n */\nexport function toDuckPondError(error: unknown, defaultCode: ErrorCode = ErrorCode.UNKNOWN_ERROR): DuckPondError {\n if (error instanceof Error) {\n return {\n code: defaultCode,\n message: error.message,\n cause: error,\n }\n }\n\n return {\n code: defaultCode,\n message: String(error),\n }\n}\n\n/**\n * Error factory functions for common errors\n */\nexport const Errors = {\n connectionFailed: (message: string, cause?: Error) => createError(ErrorCode.CONNECTION_FAILED, message, cause),\n\n r2ConnectionError: (message: string, cause?: Error) => createError(ErrorCode.R2_CONNECTION_ERROR, message, cause),\n\n s3ConnectionError: (message: string, cause?: Error) => createError(ErrorCode.S3_CONNECTION_ERROR, message, cause),\n\n userNotFound: (userId: string) =>\n createError(ErrorCode.USER_NOT_FOUND, `User not found: ${userId}`, undefined, { userId }),\n\n userAlreadyExists: (userId: string) =>\n createError(ErrorCode.USER_ALREADY_EXISTS, `User already exists: ${userId}`, undefined, {\n userId,\n }),\n\n userNotAttached: (userId: string) =>\n createError(ErrorCode.USER_NOT_ATTACHED, `User not attached: ${userId}`, undefined, {\n userId,\n }),\n\n queryExecutionError: (message: string, sql?: string, cause?: Error) =>\n createError(ErrorCode.QUERY_EXECUTION_ERROR, message, cause, { sql }),\n\n queryTimeout: (timeoutMs: number) =>\n createError(ErrorCode.QUERY_TIMEOUT, `Query timeout after ${timeoutMs}ms`, undefined, {\n timeoutMs,\n }),\n\n memoryLimitExceeded: (limit: string) =>\n createError(ErrorCode.MEMORY_LIMIT_EXCEEDED, `Memory limit exceeded: ${limit}`, undefined, {\n limit,\n }),\n\n storageError: (message: string, cause?: Error) => createError(ErrorCode.STORAGE_ERROR, message, cause),\n\n invalidConfig: (message: string) => createError(ErrorCode.INVALID_CONFIG, message),\n\n notInitialized: () => createError(ErrorCode.NOT_INITIALIZED, \"DuckPond not initialized. Call init() first.\"),\n}\n\n/**\n * Format an error for logging\n */\nexport function formatError(error: DuckPondError): string {\n const parts = [`[${error.code}] ${error.message}`]\n\n if (error.cause) {\n parts.push(` Caused by: ${error.cause.message}`)\n }\n\n if (error.context) {\n parts.push(` Context: ${JSON.stringify(error.context)}`)\n }\n\n return parts.join(\"\\n\")\n}\n"],"mappings":"mFAOA,SAAgB,EACd,EACA,EACA,EACA,EAC8B,CAC9B,OAAO,EAAK,CACV,OACA,UACA,QACA,UACD,CAAC,CAMJ,SAAgB,EAAkB,EAA6D,CAE7F,OAAO,EAAM,EAAM,CAMrB,SAAgB,EAAgB,EAAgB,EAAyB,EAAU,cAA8B,CAS/G,OARI,aAAiB,MACZ,CACL,KAAM,EACN,QAAS,EAAM,QACf,MAAO,EACR,CAGI,CACL,KAAM,EACN,QAAS,OAAO,EAAM,CACvB,CAMH,MAAa,EAAS,CACpB,kBAAmB,EAAiB,IAAkB,EAAY,EAAU,kBAAmB,EAAS,EAAM,CAE9G,mBAAoB,EAAiB,IAAkB,EAAY,EAAU,oBAAqB,EAAS,EAAM,CAEjH,mBAAoB,EAAiB,IAAkB,EAAY,EAAU,oBAAqB,EAAS,EAAM,CAEjH,aAAe,GACb,EAAY,EAAU,eAAgB,mBAAmB,IAAU,IAAA,GAAW,CAAE,SAAQ,CAAC,CAE3F,kBAAoB,GAClB,EAAY,EAAU,oBAAqB,wBAAwB,IAAU,IAAA,GAAW,CACtF,SACD,CAAC,CAEJ,gBAAkB,GAChB,EAAY,EAAU,kBAAmB,sBAAsB,IAAU,IAAA,GAAW,CAClF,SACD,CAAC,CAEJ,qBAAsB,EAAiB,EAAc,IACnD,EAAY,EAAU,sBAAuB,EAAS,EAAO,CAAE,MAAK,CAAC,CAEvE,aAAe,GACb,EAAY,EAAU,cAAe,uBAAuB,EAAU,IAAK,IAAA,GAAW,CACpF,YACD,CAAC,CAEJ,oBAAsB,GACpB,EAAY,EAAU,sBAAuB,0BAA0B,IAAS,IAAA,GAAW,CACzF,QACD,CAAC,CAEJ,cAAe,EAAiB,IAAkB,EAAY,EAAU,cAAe,EAAS,EAAM,CAEtG,cAAgB,GAAoB,EAAY,EAAU,eAAgB,EAAQ,CAElF,mBAAsB,EAAY,EAAU,gBAAiB,+CAA+C,CAC7G,CAKD,SAAgB,EAAY,EAA8B,CACxD,IAAM,EAAQ,CAAC,IAAI,EAAM,KAAK,IAAI,EAAM,UAAU,CAUlD,OARI,EAAM,OACR,EAAM,KAAK,gBAAgB,EAAM,MAAM,UAAU,CAG/C,EAAM,SACR,EAAM,KAAK,cAAc,KAAK,UAAU,EAAM,QAAQ,GAAG,CAGpD,EAAM,KAAK;EAAK"}
@@ -1,4 +1,6 @@
1
- import debug from 'debug';
1
+ import debug from "debug";
2
+
3
+ //#region src/utils/logger.d.ts
2
4
 
3
5
  /**
4
6
  * Create a namespaced logger for DuckPond
@@ -14,12 +16,13 @@ declare function createLogger(namespace: string): debug.Debugger;
14
16
  * Pre-configured loggers for different modules
15
17
  */
16
18
  declare const loggers: {
17
- main: debug.Debugger;
18
- cache: debug.Debugger;
19
- connection: debug.Debugger;
20
- query: debug.Debugger;
21
- storage: debug.Debugger;
22
- metrics: debug.Debugger;
19
+ main: debug.Debugger;
20
+ cache: debug.Debugger;
21
+ connection: debug.Debugger;
22
+ query: debug.Debugger;
23
+ storage: debug.Debugger;
24
+ metrics: debug.Debugger;
23
25
  };
24
-
26
+ //#endregion
25
27
  export { createLogger, loggers };
28
+ //# sourceMappingURL=logger.d.ts.map
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkQ6UFPTQCjs = require('../chunk-Q6UFPTQC.js');require('../chunk-5XGN7UAV.js');exports.createLogger = _chunkQ6UFPTQCjs.a; exports.loggers = _chunkQ6UFPTQCjs.b;
1
+ import e from"debug";function t(t){return e(`duckpond:${t}`)}const n={main:t(`main`),cache:t(`cache`),connection:t(`connection`),query:t(`query`),storage:t(`storage`),metrics:t(`metrics`)};export{t as createLogger,n as loggers};
2
2
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/jordanburke/IdeaProjects/duckpond/dist/utils/logger.js"],"names":[],"mappings":"AAAA,gIAAqC,gCAA6B,gFAAuC","file":"/Users/jordanburke/IdeaProjects/duckpond/dist/utils/logger.js"}
1
+ {"version":3,"file":"logger.js","names":[],"sources":["../../src/utils/logger.ts"],"sourcesContent":["import debug from \"debug\"\n\n/**\n * Create a namespaced logger for DuckPond\n *\n * Usage:\n * const log = createLogger('DuckPond')\n * log('Initializing...')\n *\n * Enable with: DEBUG=duckpond:* node app.js\n */\nexport function createLogger(namespace: string): debug.Debugger {\n return debug(`duckpond:${namespace}`)\n}\n\n/**\n * Pre-configured loggers for different modules\n */\nexport const loggers = {\n main: createLogger(\"main\"),\n cache: createLogger(\"cache\"),\n connection: createLogger(\"connection\"),\n query: createLogger(\"query\"),\n storage: createLogger(\"storage\"),\n metrics: createLogger(\"metrics\"),\n}\n"],"mappings":"qBAWA,SAAgB,EAAa,EAAmC,CAC9D,OAAO,EAAM,YAAY,IAAY,CAMvC,MAAa,EAAU,CACrB,KAAM,EAAa,OAAO,CAC1B,MAAO,EAAa,QAAQ,CAC5B,WAAY,EAAa,aAAa,CACtC,MAAO,EAAa,QAAQ,CAC5B,QAAS,EAAa,UAAU,CAChC,QAAS,EAAa,UAAU,CACjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "duckpond",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Multi-tenant DuckDB manager with R2/S3 storage and functional programming patterns",
5
5
  "keywords": [
6
6
  "duckdb",
@@ -20,61 +20,48 @@
20
20
  "type": "git",
21
21
  "url": "https://github.com/jordanburke/duckpond"
22
22
  },
23
+ "type": "module",
24
+ "scripts": {
25
+ "validate": "ts-builds validate",
26
+ "format": "ts-builds format",
27
+ "format:check": "ts-builds format:check",
28
+ "lint": "ts-builds lint",
29
+ "lint:check": "ts-builds lint:check",
30
+ "typecheck": "ts-builds typecheck",
31
+ "test": "ts-builds test",
32
+ "test:watch": "ts-builds test:watch",
33
+ "test:coverage": "ts-builds test:coverage",
34
+ "build": "ts-builds build",
35
+ "dev": "ts-builds dev",
36
+ "prepublishOnly": "pnpm validate"
37
+ },
38
+ "dependencies": {
39
+ "@duckdb/node-api": "1.4.4-r.1",
40
+ "@duckdb/node-bindings": "1.4.4-r.1",
41
+ "debug": "^4.4.3",
42
+ "functype": "^0.46.2",
43
+ "lru-cache": "^11.2.6"
44
+ },
23
45
  "devDependencies": {
24
- "@eslint/eslintrc": "^3.3.3",
25
- "@eslint/js": "^9.39.2",
26
- "@types/node": "^22.19.3",
27
- "@typescript-eslint/eslint-plugin": "^8.51.0",
28
- "@typescript-eslint/parser": "^8.51.0",
29
- "@vitest/coverage-v8": "4.0.16",
30
- "@vitest/ui": "^4.0.16",
31
- "cross-env": "^10.1.0",
32
- "eslint": "^9.39.2",
33
- "eslint-config-prettier": "^10.1.8",
34
- "eslint-plugin-import": "^2.32.0",
35
- "eslint-plugin-prettier": "^5.5.4",
36
- "eslint-plugin-simple-import-sort": "^12.1.1",
37
- "globals": "^16.5.0",
38
- "prettier": "^3.7.4",
39
- "rimraf": "^6.1.2",
40
- "ts-node": "^10.9.2",
41
- "tsup": "^8.5.1",
42
- "typescript": "^5.9.3",
43
- "vitest": "^4.0.16"
46
+ "@types/node": "~24.10.13",
47
+ "ts-builds": "^2.4.0",
48
+ "tsdown": "^0.18.4",
49
+ "tsx": "^4.21.0",
50
+ "typescript": "^5.9.3"
44
51
  },
45
52
  "main": "./dist/index.js",
46
- "module": "./dist/index.mjs",
53
+ "module": "./dist/index.js",
47
54
  "types": "./dist/index.d.ts",
48
55
  "exports": {
49
56
  ".": {
50
57
  "types": "./dist/index.d.ts",
51
- "require": "./dist/index.js",
52
- "import": "./dist/index.mjs"
58
+ "import": "./dist/index.js"
53
59
  }
54
60
  },
55
61
  "files": [
56
62
  "lib",
57
63
  "dist"
58
64
  ],
59
- "dependencies": {
60
- "@duckdb/node-api": "1.4.3-r.2",
61
- "@duckdb/node-bindings": "1.4.3-r.2",
62
- "debug": "^4.4.3",
63
- "functype": "^0.41.3"
64
- },
65
- "scripts": {
66
- "validate": "pnpm format && pnpm lint && pnpm test && pnpm build",
67
- "format": "prettier --write .",
68
- "format:check": "prettier --check .",
69
- "lint": "eslint ./src --fix",
70
- "lint:check": "eslint ./src",
71
- "test": "vitest run",
72
- "test:watch": "vitest",
73
- "test:coverage": "vitest run --coverage",
74
- "test:ui": "vitest --ui",
75
- "build": "rimraf dist && cross-env NODE_ENV=production tsup",
76
- "build:watch": "tsup --watch",
77
- "dev": "tsup --watch",
78
- "ts-types": "tsc"
79
- }
80
- }
65
+ "prettier": "ts-builds/prettier",
66
+ "packageManager": "pnpm@10.29.3+sha512.498e1fb4cca5aa06c1dcf2611e6fafc50972ffe7189998c409e90de74566444298ffe43e6cd2acdc775ba1aa7cc5e092a8b7054c811ba8c5770f84693d33d2dc"
67
+ }
@@ -1,83 +0,0 @@
1
- import { DuckDBConnection } from '@duckdb/node-api';
2
- import { DuckPondConfig, AsyncDuckPondResult, UserStats, ListUsersResult } from './types.mjs';
3
- import 'functype/either';
4
- import 'functype/list';
5
-
6
- declare class DuckPond {
7
- private instance;
8
- private cache;
9
- private config;
10
- private evictionTimer;
11
- private initialized;
12
- constructor(config: DuckPondConfig);
13
- /**
14
- * Initialize DuckPond
15
- * Must be called before any other operations
16
- */
17
- init(): AsyncDuckPondResult<void>;
18
- /**
19
- * Ensure the data directory exists
20
- */
21
- private ensureDataDir;
22
- /**
23
- * Get the database file path for a user
24
- */
25
- private getUserDbPath;
26
- /**
27
- * Configure R2/S3 access and DuckDB extensions
28
- */
29
- private setupCloudStorage;
30
- /**
31
- * Get a connection for a user
32
- * Loads from cache or creates new database
33
- */
34
- getUserConnection(userId: string): AsyncDuckPondResult<DuckDBConnection>;
35
- /**
36
- * Create a local file-based database connection for a user
37
- */
38
- private createLocalUserConnection;
39
- /**
40
- * Attach a user's database based on storage strategy
41
- */
42
- private attachUserDatabase;
43
- /**
44
- * Execute a SQL query for a user
45
- * Returns Either<Error, results>
46
- */
47
- query<T = unknown>(userId: string, sql: string): AsyncDuckPondResult<T[]>;
48
- /**
49
- * Execute SQL without returning results (DDL, DML)
50
- */
51
- execute(userId: string, sql: string): AsyncDuckPondResult<void>;
52
- /**
53
- * Detach a user's database and free resources
54
- */
55
- detachUser(userId: string): AsyncDuckPondResult<void>;
56
- /**
57
- * Evict the least recently used user
58
- */
59
- private evictLRU;
60
- /**
61
- * Start background timer to evict idle users
62
- */
63
- private startEvictionTimer;
64
- /**
65
- * Check if a user is currently attached
66
- */
67
- isAttached(userId: string): boolean;
68
- /**
69
- * Get statistics about a user's database
70
- */
71
- getUserStats(userId: string): AsyncDuckPondResult<UserStats>;
72
- /**
73
- * Get list of all currently cached users
74
- * Returns a List of user IDs and cache statistics
75
- */
76
- listUsers(): ListUsersResult;
77
- /**
78
- * Close DuckPond and cleanup all resources
79
- */
80
- close(): AsyncDuckPondResult<void>;
81
- }
82
-
83
- export { DuckPond };
package/dist/DuckPond.mjs DELETED
@@ -1,2 +0,0 @@
1
- import{a}from"./chunk-BA7KCST7.mjs";import"./chunk-24M54WUC.mjs";import"./chunk-PCQEPXO3.mjs";import"./chunk-GXQJHTJW.mjs";import"./chunk-SZJXSB7U.mjs";import"./chunk-V57JCP3U.mjs";export{a as DuckPond};
2
- //# sourceMappingURL=DuckPond.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}