@mastra/duckdb 1.0.1 → 1.1.0-alpha.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 (48) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/LICENSE.md +15 -0
  3. package/dist/chunk-37GBWD4M.js +195 -0
  4. package/dist/chunk-37GBWD4M.js.map +1 -0
  5. package/dist/chunk-S2AWBPTS.cjs +198 -0
  6. package/dist/chunk-S2AWBPTS.cjs.map +1 -0
  7. package/dist/docs/SKILL.md +2 -2
  8. package/dist/docs/assets/SOURCE_MAP.json +8 -2
  9. package/dist/docs/references/reference-vectors-duckdb.md +46 -46
  10. package/dist/index.cjs +241 -4
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +5 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +238 -6
  15. package/dist/index.js.map +1 -1
  16. package/dist/observability-PW6J27KS.js +1675 -0
  17. package/dist/observability-PW6J27KS.js.map +1 -0
  18. package/dist/observability-W2QRBK56.cjs +1677 -0
  19. package/dist/observability-W2QRBK56.cjs.map +1 -0
  20. package/dist/storage/db/index.d.ts +46 -0
  21. package/dist/storage/db/index.d.ts.map +1 -0
  22. package/dist/storage/domains/observability/ddl.d.ts +25 -0
  23. package/dist/storage/domains/observability/ddl.d.ts.map +1 -0
  24. package/dist/storage/domains/observability/discovery.d.ts +13 -0
  25. package/dist/storage/domains/observability/discovery.d.ts.map +1 -0
  26. package/dist/storage/domains/observability/feedback.d.ts +9 -0
  27. package/dist/storage/domains/observability/feedback.d.ts.map +1 -0
  28. package/dist/storage/domains/observability/filters.d.ts +27 -0
  29. package/dist/storage/domains/observability/filters.d.ts.map +1 -0
  30. package/dist/storage/domains/observability/helpers.d.ts +14 -0
  31. package/dist/storage/domains/observability/helpers.d.ts.map +1 -0
  32. package/dist/storage/domains/observability/index.d.ts +54 -0
  33. package/dist/storage/domains/observability/index.d.ts.map +1 -0
  34. package/dist/storage/domains/observability/logs.d.ts +7 -0
  35. package/dist/storage/domains/observability/logs.d.ts.map +1 -0
  36. package/dist/storage/domains/observability/metrics.d.ts +21 -0
  37. package/dist/storage/domains/observability/metrics.d.ts.map +1 -0
  38. package/dist/storage/domains/observability/scores.d.ts +9 -0
  39. package/dist/storage/domains/observability/scores.d.ts.map +1 -0
  40. package/dist/storage/domains/observability/tracing.d.ts +17 -0
  41. package/dist/storage/domains/observability/tracing.d.ts.map +1 -0
  42. package/dist/storage/index.d.ts +101 -0
  43. package/dist/storage/index.d.ts.map +1 -0
  44. package/dist/vector/filter-builder.d.ts +1 -0
  45. package/dist/vector/filter-builder.d.ts.map +1 -1
  46. package/dist/vector/index.d.ts +9 -0
  47. package/dist/vector/index.d.ts.map +1 -1
  48. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,103 @@
1
1
  # @mastra/duckdb
2
2
 
3
+ ## 1.1.0-alpha.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Adds observability storage using DuckDB for traces, metrics, logs, scores, and feedback. Exports `DuckDBStore`, `ObservabilityStorageDuckDB`, and `DuckDBConnection`. ([#14249](https://github.com/mastra-ai/mastra/pull/14249))
8
+
9
+ Older `@mastra/core` versions show an upgrade error when you use the DuckDB observability store.
10
+
11
+ ```typescript
12
+ import { Mastra } from '@mastra/core/mastra';
13
+ import { DefaultExporter, Observability } from '@mastra/observability';
14
+ import { MastraCompositeStore } from '@mastra/core/storage';
15
+ import { LibSQLStore } from '@mastra/libsql';
16
+ import { DuckDBStore } from '@mastra/duckdb';
17
+
18
+ const duckDBStore = new DuckDBStore();
19
+ const libSqlStore = new LibSQLStore();
20
+
21
+ const storage = new MastraCompositeStore({
22
+ id: 'composite',
23
+ domains: {
24
+ ...libSqlStore.stores,
25
+ observability: duckDBStore.observability,
26
+ },
27
+ });
28
+
29
+ export const mastra = new Mastra({
30
+ agents: {
31
+ /* your agents here */
32
+ },
33
+ observability: new Observability({
34
+ configs: {
35
+ default: {
36
+ serviceName: 'obs-test',
37
+ exporters: [new DefaultExporter()],
38
+ },
39
+ },
40
+ }),
41
+ storage,
42
+ });
43
+ ```
44
+
45
+ ### Patch Changes
46
+
47
+ - Fixed `'Cannot create values of type ANY'` error when querying metrics endpoints with DuckDB. Parameter binding now uses explicit typed methods instead of relying on DuckDB's type inference, which fails for certain SQL contexts like `json_extract_string`. ([#14666](https://github.com/mastra-ai/mastra/pull/14666))
48
+
49
+ - Updated dependencies [[`dc514a8`](https://github.com/mastra-ai/mastra/commit/dc514a83dba5f719172dddfd2c7b858e4943d067), [`404fea1`](https://github.com/mastra-ai/mastra/commit/404fea13042181f0b0c73a101392ac87c79ceae2), [`ebf5047`](https://github.com/mastra-ai/mastra/commit/ebf5047e825c38a1a356f10b214c1d4260dfcd8d), [`675f15b`](https://github.com/mastra-ai/mastra/commit/675f15b7eaeea649158d228ea635be40480c584d), [`b174c63`](https://github.com/mastra-ai/mastra/commit/b174c63a093108d4e53b9bc89a078d9f66202b3f), [`eef7cb2`](https://github.com/mastra-ai/mastra/commit/eef7cb2abe7ef15951e2fdf792a5095c6c643333), [`e8a5b0b`](https://github.com/mastra-ai/mastra/commit/e8a5b0b9bc94d12dee4150095512ca27a288d778)]:
50
+ - @mastra/core@1.18.0-alpha.0
51
+
52
+ ## 1.1.0-alpha.0
53
+
54
+ ### Minor Changes
55
+
56
+ - Adds observability storage using DuckDB for traces, metrics, logs, scores, and feedback. Exports `DuckDBStore`, `ObservabilityStorageDuckDB`, and `DuckDBConnection`. ([#14249](https://github.com/mastra-ai/mastra/pull/14249))
57
+
58
+ Older `@mastra/core` versions show an upgrade error when you use the DuckDB observability store.
59
+
60
+ ```typescript
61
+ import { Mastra } from '@mastra/core/mastra';
62
+ import { DefaultExporter, Observability } from '@mastra/observability';
63
+ import { MastraCompositeStore } from '@mastra/core/storage';
64
+ import { LibSQLStore } from '@mastra/libsql';
65
+ import { DuckDBStore } from '@mastra/duckdb';
66
+
67
+ const duckDBStore = new DuckDBStore();
68
+ const libSqlStore = new LibSQLStore();
69
+
70
+ const storage = new MastraCompositeStore({
71
+ id: 'composite',
72
+ domains: {
73
+ ...libSqlStore.stores,
74
+ observability: duckDBStore.observability,
75
+ },
76
+ });
77
+
78
+ export const mastra = new Mastra({
79
+ agents: {
80
+ /* your agents here */
81
+ },
82
+ observability: new Observability({
83
+ configs: {
84
+ default: {
85
+ serviceName: 'obs-test',
86
+ exporters: [new DefaultExporter()],
87
+ },
88
+ },
89
+ }),
90
+ storage,
91
+ });
92
+ ```
93
+
94
+ ### Patch Changes
95
+
96
+ - Fixed 'Cannot create values of type ANY' error when querying metrics endpoints with DuckDB. Parameter binding now uses explicit typed methods instead of relying on DuckDB's type inference, which fails for certain SQL contexts like json_extract_string. ([#14666](https://github.com/mastra-ai/mastra/pull/14666))
97
+
98
+ - Updated dependencies [[`7302e5c`](https://github.com/mastra-ai/mastra/commit/7302e5ce0f52d769d3d63fb0faa8a7d4089cda6d)]:
99
+ - @mastra/core@1.16.1-alpha.1
100
+
3
101
  ## 1.0.1
4
102
 
5
103
  ### Patch Changes
package/LICENSE.md CHANGED
@@ -1,3 +1,18 @@
1
+ Portions of this software are licensed as follows:
2
+
3
+ - All content that resides under any directory named "ee/" within this
4
+ repository, including but not limited to:
5
+ - `packages/core/src/auth/ee/`
6
+ - `packages/server/src/server/auth/ee/`
7
+ is licensed under the license defined in `ee/LICENSE`.
8
+
9
+ - All third-party components incorporated into the Mastra Software are
10
+ licensed under the original license provided by the owner of the
11
+ applicable component.
12
+
13
+ - Content outside of the above-mentioned directories or restrictions is
14
+ available under the "Apache License 2.0" as defined below.
15
+
1
16
  # Apache License 2.0
2
17
 
3
18
  Copyright (c) 2025 Kepler Software, Inc.
@@ -0,0 +1,195 @@
1
+ import { DuckDBTimestampValue, DuckDBTimestampTZValue, DuckDBInstance } from '@duckdb/node-api';
2
+ import { MastraBase } from '@mastra/core/base';
3
+
4
+ // src/storage/db/index.ts
5
+ function bindParam(stmt, index, value) {
6
+ if (value === null || value === void 0) {
7
+ stmt.bindNull(index);
8
+ } else if (typeof value === "string") {
9
+ stmt.bindVarchar(index, value);
10
+ } else if (typeof value === "number") {
11
+ if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
12
+ stmt.bindInteger(index, value);
13
+ } else {
14
+ stmt.bindDouble(index, value);
15
+ }
16
+ } else if (typeof value === "boolean") {
17
+ stmt.bindBoolean(index, value);
18
+ } else if (typeof value === "bigint") {
19
+ stmt.bindBigInt(index, value);
20
+ } else if (value instanceof Date) {
21
+ stmt.bindTimestamp(index, new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));
22
+ } else if (value instanceof DuckDBTimestampValue) {
23
+ stmt.bindTimestamp(index, value);
24
+ } else if (value instanceof DuckDBTimestampTZValue) {
25
+ stmt.bindTimestampTZ(index, value);
26
+ } else {
27
+ stmt.bindVarchar(index, JSON.stringify(value));
28
+ }
29
+ }
30
+ function toJsValue(val) {
31
+ if (val === null || val === void 0) return val;
32
+ if (val instanceof DuckDBTimestampValue) {
33
+ return new Date(Number(val.micros / 1000n));
34
+ }
35
+ if (typeof val === "bigint") {
36
+ return Number(val);
37
+ }
38
+ return val;
39
+ }
40
+ var DuckDBConnection = class extends MastraBase {
41
+ instance = null;
42
+ initialized = false;
43
+ initPromise = null;
44
+ path;
45
+ constructor(config = {}) {
46
+ super({ component: "STORAGE", name: "DUCKDB" });
47
+ this.path = config.path ?? "mastra.duckdb";
48
+ }
49
+ async initialize() {
50
+ if (this.initialized && this.instance) return;
51
+ if (this.initPromise) {
52
+ await this.initPromise;
53
+ if (this.instance) return;
54
+ this.initPromise = null;
55
+ this.initialized = false;
56
+ }
57
+ this.initPromise = (async () => {
58
+ try {
59
+ this.instance = await DuckDBInstance.create(this.path);
60
+ this.initialized = true;
61
+ } catch (error) {
62
+ this.instance = null;
63
+ this.initialized = false;
64
+ this.initPromise = null;
65
+ throw error;
66
+ }
67
+ })();
68
+ return this.initPromise;
69
+ }
70
+ /** Create a new connection to the DuckDB instance, initializing if needed. */
71
+ async getConnection() {
72
+ await this.initialize();
73
+ if (!this.instance) {
74
+ throw new Error("DuckDB instance not initialized");
75
+ }
76
+ return this.instance.connect();
77
+ }
78
+ closeConnection(connection) {
79
+ const conn = connection;
80
+ try {
81
+ if (typeof conn?.closeSync === "function") {
82
+ conn.closeSync();
83
+ return;
84
+ }
85
+ if (typeof conn?.disconnectSync === "function") {
86
+ conn.disconnectSync();
87
+ return;
88
+ }
89
+ if (typeof conn?.close === "function") {
90
+ conn.close();
91
+ return;
92
+ }
93
+ if (typeof conn?.disconnect === "function") {
94
+ conn.disconnect();
95
+ }
96
+ } catch {
97
+ }
98
+ }
99
+ /**
100
+ * Execute a SQL query and return results as objects.
101
+ */
102
+ async query(sql, params = []) {
103
+ const connection = await this.getConnection();
104
+ try {
105
+ if (params.length === 0) {
106
+ const result2 = await connection.run(sql);
107
+ const rows2 = await result2.getRows();
108
+ const columns2 = result2.columnNames();
109
+ return rows2.map((row) => {
110
+ const obj = {};
111
+ columns2.forEach((col, i) => {
112
+ obj[col] = toJsValue(row[i]);
113
+ });
114
+ return obj;
115
+ });
116
+ }
117
+ let paramIndex = 0;
118
+ const preparedSql = sql.replace(/\?/g, () => `$${++paramIndex}`);
119
+ const stmt = await connection.prepare(preparedSql);
120
+ for (let i = 0; i < params.length; i++) {
121
+ bindParam(stmt, i + 1, params[i]);
122
+ }
123
+ const result = await stmt.run();
124
+ const rows = await result.getRows();
125
+ const columns = result.columnNames();
126
+ return rows.map((row) => {
127
+ const obj = {};
128
+ columns.forEach((col, i) => {
129
+ obj[col] = toJsValue(row[i]);
130
+ });
131
+ return obj;
132
+ });
133
+ } finally {
134
+ this.closeConnection(connection);
135
+ }
136
+ }
137
+ /**
138
+ * Execute a SQL statement without returning results.
139
+ */
140
+ async execute(sql, params = []) {
141
+ const connection = await this.getConnection();
142
+ try {
143
+ if (params.length === 0) {
144
+ await connection.run(sql);
145
+ return;
146
+ }
147
+ let paramIndex = 0;
148
+ const preparedSql = sql.replace(/\?/g, () => `$${++paramIndex}`);
149
+ const stmt = await connection.prepare(preparedSql);
150
+ for (let i = 0; i < params.length; i++) {
151
+ bindParam(stmt, i + 1, params[i]);
152
+ }
153
+ await stmt.run();
154
+ } finally {
155
+ this.closeConnection(connection);
156
+ }
157
+ }
158
+ /**
159
+ * Escape a value for safe inline SQL use.
160
+ * DuckDB prepared statements can't handle NULL for parameters typed as ANY,
161
+ * so for complex INSERT/UPDATE operations we inline values safely.
162
+ */
163
+ static sqlValue(value) {
164
+ if (value === null || value === void 0) return "NULL";
165
+ if (typeof value === "number") {
166
+ if (!Number.isFinite(value)) return "NULL";
167
+ return String(value);
168
+ }
169
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
170
+ if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;
171
+ if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
172
+ return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
173
+ }
174
+ /** Release the DuckDB instance, allowing garbage collection. */
175
+ async close() {
176
+ if (this.instance) {
177
+ try {
178
+ const instance = this.instance;
179
+ if (typeof instance.closeSync === "function") {
180
+ instance.closeSync();
181
+ } else if (typeof instance.close === "function") {
182
+ instance.close();
183
+ }
184
+ } catch {
185
+ }
186
+ this.instance = null;
187
+ this.initialized = false;
188
+ this.initPromise = null;
189
+ }
190
+ }
191
+ };
192
+
193
+ export { DuckDBConnection, bindParam };
194
+ //# sourceMappingURL=chunk-37GBWD4M.js.map
195
+ //# sourceMappingURL=chunk-37GBWD4M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/db/index.ts"],"names":["result","rows","columns"],"mappings":";;;;AASO,SAAS,SAAA,CAAU,IAAA,EAA+B,KAAA,EAAe,KAAA,EAAsB;AAC5F,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AACzC,IAAA,IAAA,CAAK,SAAS,KAAK,CAAA;AAAA,EACrB,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AACpC,IAAA,IAAA,CAAK,WAAA,CAAY,OAAO,KAAK,CAAA;AAAA,EAC/B,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AACpC,IAAA,IAAI,OAAO,SAAA,CAAU,KAAK,KAAK,KAAA,IAAS,WAAA,IAAe,SAAS,UAAA,EAAY;AAC1E,MAAA,IAAA,CAAK,WAAA,CAAY,OAAO,KAAK,CAAA;AAAA,IAC/B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,IAC9B;AAAA,EACF,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,SAAA,EAAW;AACrC,IAAA,IAAA,CAAK,WAAA,CAAY,OAAO,KAAK,CAAA;AAAA,EAC/B,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AACpC,IAAA,IAAA,CAAK,UAAA,CAAW,OAAO,KAAK,CAAA;AAAA,EAC9B,CAAA,MAAA,IAAW,iBAAiB,IAAA,EAAM;AAChC,IAAA,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,IAAI,oBAAA,CAAqB,MAAA,CAAO,MAAM,OAAA,EAAS,CAAA,GAAI,KAAK,CAAC,CAAA;AAAA,EACrF,CAAA,MAAA,IAAW,iBAAiB,oBAAA,EAAsB;AAChD,IAAA,IAAA,CAAK,aAAA,CAAc,OAAO,KAAK,CAAA;AAAA,EACjC,CAAA,MAAA,IAAW,iBAAiB,sBAAA,EAAwB;AAClD,IAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,KAAK,CAAA;AAAA,EACnC,CAAA,MAAO;AAEL,IAAA,IAAA,CAAK,WAAA,CAAY,KAAA,EAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EAC/C;AACF;AAGA,SAAS,UAAU,GAAA,EAAuB;AACxC,EAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,GAAA,KAAQ,MAAA,EAAW,OAAO,GAAA;AAE9C,EAAA,IAAI,eAAe,oBAAA,EAAsB;AACvC,IAAA,OAAO,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,MAAA,GAAS,KAAK,CAAC,CAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,OAAO,GAAG,CAAA;AAAA,EACnB;AACA,EAAA,OAAO,GAAA;AACT;AAaO,IAAM,gBAAA,GAAN,cAA+B,UAAA,CAAW;AAAA,EACvC,QAAA,GAAkC,IAAA;AAAA,EAClC,WAAA,GAAc,KAAA;AAAA,EACd,WAAA,GAAoC,IAAA;AAAA,EACpC,IAAA;AAAA,EAER,WAAA,CAAY,MAAA,GAA8B,EAAC,EAAG;AAC5C,IAAA,KAAA,CAAM,EAAE,SAAA,EAAW,SAAA,EAAW,IAAA,EAAM,UAAU,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,OAAO,IAAA,IAAQ,eAAA;AAAA,EAC7B;AAAA,EAEA,MAAc,UAAA,GAA4B;AACxC,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,QAAA,EAAU;AAEvC,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,MAAM,IAAA,CAAK,WAAA;AACX,MAAA,IAAI,KAAK,QAAA,EAAU;AACnB,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AAAA,IACrB;AAEA,IAAA,IAAA,CAAK,eAAe,YAAY;AAC9B,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,QAAA,GAAW,MAAM,cAAA,CAAe,MAAA,CAAO,KAAK,IAAI,CAAA;AACrD,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,MACrB,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,QAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AACnB,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA,GAAG;AAEH,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,aAAA,GAAgB;AACpB,IAAA,MAAM,KAAK,UAAA,EAAW;AACtB,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AACA,IAAA,OAAO,IAAA,CAAK,SAAS,OAAA,EAAQ;AAAA,EAC/B;AAAA,EAEQ,gBAAgB,UAAA,EAA2B;AACjD,IAAA,MAAM,IAAA,GAAO,UAAA;AAMb,IAAA,IAAI;AACF,MAAA,IAAI,OAAO,IAAA,EAAM,SAAA,KAAc,UAAA,EAAY;AACzC,QAAA,IAAA,CAAK,SAAA,EAAU;AACf,QAAA;AAAA,MACF;AACA,MAAA,IAAI,OAAO,IAAA,EAAM,cAAA,KAAmB,UAAA,EAAY;AAC9C,QAAA,IAAA,CAAK,cAAA,EAAe;AACpB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,OAAO,IAAA,EAAM,KAAA,KAAU,UAAA,EAAY;AACrC,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA;AAAA,MACF;AACA,MAAA,IAAI,OAAO,IAAA,EAAM,UAAA,KAAe,UAAA,EAAY;AAC1C,QAAA,IAAA,CAAK,UAAA,EAAW;AAAA,MAClB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,CAAmC,GAAA,EAAa,MAAA,GAAoB,EAAC,EAAiB;AAC1F,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,aAAA,EAAc;AAC5C,IAAA,IAAI;AACF,MAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,QAAA,MAAMA,OAAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AACvC,QAAA,MAAMC,KAAAA,GAAO,MAAMD,OAAAA,CAAO,OAAA,EAAQ;AAClC,QAAA,MAAME,QAAAA,GAAUF,QAAO,WAAA,EAAY;AACnC,QAAA,OAAOC,KAAAA,CAAK,IAAI,CAAA,GAAA,KAAO;AACrB,UAAA,MAAM,MAA+B,EAAC;AACtC,UAAAC,QAAAA,CAAQ,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AAC1B,YAAA,GAAA,CAAI,GAAG,CAAA,GAAI,SAAA,CAAU,GAAA,CAAI,CAAC,CAAC,CAAA;AAAA,UAC7B,CAAC,CAAA;AACD,UAAA,OAAO,GAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,IAAI,UAAA,GAAa,CAAA;AACjB,MAAA,MAAM,WAAA,GAAc,IAAI,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CAAA,EAAI,EAAE,UAAU,CAAA,CAAE,CAAA;AAC/D,MAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,OAAA,CAAQ,WAAW,CAAA;AACjD,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,SAAA,CAAU,IAAA,EAAM,CAAA,GAAI,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAClC;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,EAAI;AAC9B,MAAA,MAAM,IAAA,GAAO,MAAM,MAAA,CAAO,OAAA,EAAQ;AAClC,MAAA,MAAM,OAAA,GAAU,OAAO,WAAA,EAAY;AACnC,MAAA,OAAO,IAAA,CAAK,IAAI,CAAA,GAAA,KAAO;AACrB,QAAA,MAAM,MAA+B,EAAC;AACtC,QAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AAC1B,UAAA,GAAA,CAAI,GAAG,CAAA,GAAI,SAAA,CAAU,GAAA,CAAI,CAAC,CAAC,CAAA;AAAA,QAC7B,CAAC,CAAA;AACD,QAAA,OAAO,GAAA;AAAA,MACT,CAAC,CAAA;AAAA,IACH,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,gBAAgB,UAAU,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,GAAA,EAAa,MAAA,GAAoB,EAAC,EAAkB;AAChE,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,aAAA,EAAc;AAC5C,IAAA,IAAI;AACF,MAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,QAAA,MAAM,UAAA,CAAW,IAAI,GAAG,CAAA;AACxB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,UAAA,GAAa,CAAA;AACjB,MAAA,MAAM,WAAA,GAAc,IAAI,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CAAA,EAAI,EAAE,UAAU,CAAA,CAAE,CAAA;AAC/D,MAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,OAAA,CAAQ,WAAW,CAAA;AACjD,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,SAAA,CAAU,IAAA,EAAM,CAAA,GAAI,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAClC;AACA,MAAA,MAAM,KAAK,GAAA,EAAI;AAAA,IACjB,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,gBAAgB,UAAU,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,SAAS,KAAA,EAAwB;AACtC,IAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW,OAAO,MAAA;AAClD,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,GAAG,OAAO,MAAA;AACpC,MAAA,OAAO,OAAO,KAAK,CAAA;AAAA,IACrB;AACA,IAAA,IAAI,OAAO,KAAA,KAAU,SAAA,EAAW,OAAO,QAAQ,MAAA,GAAS,OAAA;AACxD,IAAA,IAAI,iBAAiB,IAAA,EAAM,OAAO,CAAA,CAAA,EAAI,KAAA,CAAM,aAAa,CAAA,YAAA,CAAA;AACzD,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU,OAAO,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAEnE,IAAA,OAAO,CAAA,CAAA,EAAI,KAAK,SAAA,CAAU,KAAK,EAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,EACtD;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,IAAI;AACF,QAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,QAAA,IAAI,OAAO,QAAA,CAAS,SAAA,KAAc,UAAA,EAAY;AAC5C,UAAA,QAAA,CAAS,SAAA,EAAU;AAAA,QACrB,CAAA,MAAA,IAAW,OAAO,QAAA,CAAS,KAAA,KAAU,UAAA,EAAY;AAC/C,UAAA,QAAA,CAAS,KAAA,EAAM;AAAA,QACjB;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,MAAA,IAAA,CAAK,WAAA,GAAc,KAAA;AACnB,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,IACrB;AAAA,EACF;AACF","file":"chunk-37GBWD4M.js","sourcesContent":["import { DuckDBInstance, DuckDBTimestampValue, DuckDBTimestampTZValue } from '@duckdb/node-api';\nimport type { DuckDBPreparedStatement } from '@duckdb/node-api';\nimport { MastraBase } from '@mastra/core/base';\n\n/**\n * Bind a single parameter to a prepared statement using explicit typed methods.\n * This avoids the \"Cannot create values of type ANY\" error that occurs when\n * DuckDB cannot infer parameter types from SQL context (e.g. json_extract_string).\n */\nexport function bindParam(stmt: DuckDBPreparedStatement, index: number, value: unknown): void {\n if (value === null || value === undefined) {\n stmt.bindNull(index);\n } else if (typeof value === 'string') {\n stmt.bindVarchar(index, value);\n } else if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {\n stmt.bindInteger(index, value);\n } else {\n stmt.bindDouble(index, value);\n }\n } else if (typeof value === 'boolean') {\n stmt.bindBoolean(index, value);\n } else if (typeof value === 'bigint') {\n stmt.bindBigInt(index, value);\n } else if (value instanceof Date) {\n stmt.bindTimestamp(index, new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));\n } else if (value instanceof DuckDBTimestampValue) {\n stmt.bindTimestamp(index, value);\n } else if (value instanceof DuckDBTimestampTZValue) {\n stmt.bindTimestampTZ(index, value);\n } else {\n // Fallback: serialize to JSON string\n stmt.bindVarchar(index, JSON.stringify(value));\n }\n}\n\n/** Convert DuckDB-specific return types to plain JS types */\nfunction toJsValue(val: unknown): unknown {\n if (val === null || val === undefined) return val;\n // DuckDBTimestampValue → Date (micros since epoch)\n if (val instanceof DuckDBTimestampValue) {\n return new Date(Number(val.micros / 1000n));\n }\n // BigInt → Number (safe for values we care about)\n if (typeof val === 'bigint') {\n return Number(val);\n }\n return val;\n}\n\n/** Configuration for the DuckDB database connection. */\nexport interface DuckDBStorageConfig {\n /** Path to the DuckDB file. Defaults to 'mastra.duckdb'. Use ':memory:' for ephemeral. */\n path?: string;\n}\n\n/**\n * Shared DuckDB connection management for Mastra storage.\n * Defaults to a local file (`mastra.duckdb`) when no path is provided.\n * Pass `path: ':memory:'` for an ephemeral in-memory database.\n */\nexport class DuckDBConnection extends MastraBase {\n private instance: DuckDBInstance | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private path: string;\n\n constructor(config: DuckDBStorageConfig = {}) {\n super({ component: 'STORAGE', name: 'DUCKDB' });\n this.path = config.path ?? 'mastra.duckdb';\n }\n\n private async initialize(): Promise<void> {\n if (this.initialized && this.instance) return;\n\n if (this.initPromise) {\n await this.initPromise;\n if (this.instance) return;\n this.initPromise = null;\n this.initialized = false;\n }\n\n this.initPromise = (async () => {\n try {\n this.instance = await DuckDBInstance.create(this.path);\n this.initialized = true;\n } catch (error) {\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /** Create a new connection to the DuckDB instance, initializing if needed. */\n async getConnection() {\n await this.initialize();\n if (!this.instance) {\n throw new Error('DuckDB instance not initialized');\n }\n return this.instance.connect();\n }\n\n private closeConnection(connection: unknown): void {\n const conn = connection as {\n closeSync?: () => void;\n disconnectSync?: () => void;\n close?: () => void;\n disconnect?: () => void;\n };\n try {\n if (typeof conn?.closeSync === 'function') {\n conn.closeSync();\n return;\n }\n if (typeof conn?.disconnectSync === 'function') {\n conn.disconnectSync();\n return;\n }\n if (typeof conn?.close === 'function') {\n conn.close();\n return;\n }\n if (typeof conn?.disconnect === 'function') {\n conn.disconnect();\n }\n } catch {\n // Ignore close failures to avoid masking query/execute errors.\n }\n }\n\n /**\n * Execute a SQL query and return results as objects.\n */\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T[]> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n const result = await connection.run(sql);\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n }\n\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n const result = await stmt.run();\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute a SQL statement without returning results.\n */\n async execute(sql: string, params: unknown[] = []): Promise<void> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n await connection.run(sql);\n return;\n }\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n await stmt.run();\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Escape a value for safe inline SQL use.\n * DuckDB prepared statements can't handle NULL for parameters typed as ANY,\n * so for complex INSERT/UPDATE operations we inline values safely.\n */\n static sqlValue(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) return 'NULL';\n return String(value);\n }\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';\n if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;\n if (typeof value === 'string') return `'${value.replace(/'/g, \"''\")}'`;\n // Objects/arrays → JSON string\n return `'${JSON.stringify(value).replace(/'/g, \"''\")}'`;\n }\n\n /** Release the DuckDB instance, allowing garbage collection. */\n async close(): Promise<void> {\n if (this.instance) {\n try {\n const instance = this.instance as unknown as { closeSync?: () => void; close?: () => void };\n if (typeof instance.closeSync === 'function') {\n instance.closeSync();\n } else if (typeof instance.close === 'function') {\n instance.close();\n }\n } catch {\n // Ignore close failures to allow cleanup of references.\n }\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n }\n }\n}\n"]}
@@ -0,0 +1,198 @@
1
+ 'use strict';
2
+
3
+ var nodeApi = require('@duckdb/node-api');
4
+ var base = require('@mastra/core/base');
5
+
6
+ // src/storage/db/index.ts
7
+ function bindParam(stmt, index, value) {
8
+ if (value === null || value === void 0) {
9
+ stmt.bindNull(index);
10
+ } else if (typeof value === "string") {
11
+ stmt.bindVarchar(index, value);
12
+ } else if (typeof value === "number") {
13
+ if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
14
+ stmt.bindInteger(index, value);
15
+ } else {
16
+ stmt.bindDouble(index, value);
17
+ }
18
+ } else if (typeof value === "boolean") {
19
+ stmt.bindBoolean(index, value);
20
+ } else if (typeof value === "bigint") {
21
+ stmt.bindBigInt(index, value);
22
+ } else if (value instanceof Date) {
23
+ stmt.bindTimestamp(index, new nodeApi.DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));
24
+ } else if (value instanceof nodeApi.DuckDBTimestampValue) {
25
+ stmt.bindTimestamp(index, value);
26
+ } else if (value instanceof nodeApi.DuckDBTimestampTZValue) {
27
+ stmt.bindTimestampTZ(index, value);
28
+ } else {
29
+ stmt.bindVarchar(index, JSON.stringify(value));
30
+ }
31
+ }
32
+ function toJsValue(val) {
33
+ if (val === null || val === void 0) return val;
34
+ if (val instanceof nodeApi.DuckDBTimestampValue) {
35
+ return new Date(Number(val.micros / 1000n));
36
+ }
37
+ if (typeof val === "bigint") {
38
+ return Number(val);
39
+ }
40
+ return val;
41
+ }
42
+ var DuckDBConnection = class extends base.MastraBase {
43
+ instance = null;
44
+ initialized = false;
45
+ initPromise = null;
46
+ path;
47
+ constructor(config = {}) {
48
+ super({ component: "STORAGE", name: "DUCKDB" });
49
+ this.path = config.path ?? "mastra.duckdb";
50
+ }
51
+ async initialize() {
52
+ if (this.initialized && this.instance) return;
53
+ if (this.initPromise) {
54
+ await this.initPromise;
55
+ if (this.instance) return;
56
+ this.initPromise = null;
57
+ this.initialized = false;
58
+ }
59
+ this.initPromise = (async () => {
60
+ try {
61
+ this.instance = await nodeApi.DuckDBInstance.create(this.path);
62
+ this.initialized = true;
63
+ } catch (error) {
64
+ this.instance = null;
65
+ this.initialized = false;
66
+ this.initPromise = null;
67
+ throw error;
68
+ }
69
+ })();
70
+ return this.initPromise;
71
+ }
72
+ /** Create a new connection to the DuckDB instance, initializing if needed. */
73
+ async getConnection() {
74
+ await this.initialize();
75
+ if (!this.instance) {
76
+ throw new Error("DuckDB instance not initialized");
77
+ }
78
+ return this.instance.connect();
79
+ }
80
+ closeConnection(connection) {
81
+ const conn = connection;
82
+ try {
83
+ if (typeof conn?.closeSync === "function") {
84
+ conn.closeSync();
85
+ return;
86
+ }
87
+ if (typeof conn?.disconnectSync === "function") {
88
+ conn.disconnectSync();
89
+ return;
90
+ }
91
+ if (typeof conn?.close === "function") {
92
+ conn.close();
93
+ return;
94
+ }
95
+ if (typeof conn?.disconnect === "function") {
96
+ conn.disconnect();
97
+ }
98
+ } catch {
99
+ }
100
+ }
101
+ /**
102
+ * Execute a SQL query and return results as objects.
103
+ */
104
+ async query(sql, params = []) {
105
+ const connection = await this.getConnection();
106
+ try {
107
+ if (params.length === 0) {
108
+ const result2 = await connection.run(sql);
109
+ const rows2 = await result2.getRows();
110
+ const columns2 = result2.columnNames();
111
+ return rows2.map((row) => {
112
+ const obj = {};
113
+ columns2.forEach((col, i) => {
114
+ obj[col] = toJsValue(row[i]);
115
+ });
116
+ return obj;
117
+ });
118
+ }
119
+ let paramIndex = 0;
120
+ const preparedSql = sql.replace(/\?/g, () => `$${++paramIndex}`);
121
+ const stmt = await connection.prepare(preparedSql);
122
+ for (let i = 0; i < params.length; i++) {
123
+ bindParam(stmt, i + 1, params[i]);
124
+ }
125
+ const result = await stmt.run();
126
+ const rows = await result.getRows();
127
+ const columns = result.columnNames();
128
+ return rows.map((row) => {
129
+ const obj = {};
130
+ columns.forEach((col, i) => {
131
+ obj[col] = toJsValue(row[i]);
132
+ });
133
+ return obj;
134
+ });
135
+ } finally {
136
+ this.closeConnection(connection);
137
+ }
138
+ }
139
+ /**
140
+ * Execute a SQL statement without returning results.
141
+ */
142
+ async execute(sql, params = []) {
143
+ const connection = await this.getConnection();
144
+ try {
145
+ if (params.length === 0) {
146
+ await connection.run(sql);
147
+ return;
148
+ }
149
+ let paramIndex = 0;
150
+ const preparedSql = sql.replace(/\?/g, () => `$${++paramIndex}`);
151
+ const stmt = await connection.prepare(preparedSql);
152
+ for (let i = 0; i < params.length; i++) {
153
+ bindParam(stmt, i + 1, params[i]);
154
+ }
155
+ await stmt.run();
156
+ } finally {
157
+ this.closeConnection(connection);
158
+ }
159
+ }
160
+ /**
161
+ * Escape a value for safe inline SQL use.
162
+ * DuckDB prepared statements can't handle NULL for parameters typed as ANY,
163
+ * so for complex INSERT/UPDATE operations we inline values safely.
164
+ */
165
+ static sqlValue(value) {
166
+ if (value === null || value === void 0) return "NULL";
167
+ if (typeof value === "number") {
168
+ if (!Number.isFinite(value)) return "NULL";
169
+ return String(value);
170
+ }
171
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
172
+ if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;
173
+ if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
174
+ return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
175
+ }
176
+ /** Release the DuckDB instance, allowing garbage collection. */
177
+ async close() {
178
+ if (this.instance) {
179
+ try {
180
+ const instance = this.instance;
181
+ if (typeof instance.closeSync === "function") {
182
+ instance.closeSync();
183
+ } else if (typeof instance.close === "function") {
184
+ instance.close();
185
+ }
186
+ } catch {
187
+ }
188
+ this.instance = null;
189
+ this.initialized = false;
190
+ this.initPromise = null;
191
+ }
192
+ }
193
+ };
194
+
195
+ exports.DuckDBConnection = DuckDBConnection;
196
+ exports.bindParam = bindParam;
197
+ //# sourceMappingURL=chunk-S2AWBPTS.cjs.map
198
+ //# sourceMappingURL=chunk-S2AWBPTS.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/db/index.ts"],"names":["DuckDBTimestampValue","DuckDBTimestampTZValue","MastraBase","DuckDBInstance","result","rows","columns"],"mappings":"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","file":"chunk-S2AWBPTS.cjs","sourcesContent":["import { DuckDBInstance, DuckDBTimestampValue, DuckDBTimestampTZValue } from '@duckdb/node-api';\nimport type { DuckDBPreparedStatement } from '@duckdb/node-api';\nimport { MastraBase } from '@mastra/core/base';\n\n/**\n * Bind a single parameter to a prepared statement using explicit typed methods.\n * This avoids the \"Cannot create values of type ANY\" error that occurs when\n * DuckDB cannot infer parameter types from SQL context (e.g. json_extract_string).\n */\nexport function bindParam(stmt: DuckDBPreparedStatement, index: number, value: unknown): void {\n if (value === null || value === undefined) {\n stmt.bindNull(index);\n } else if (typeof value === 'string') {\n stmt.bindVarchar(index, value);\n } else if (typeof value === 'number') {\n if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {\n stmt.bindInteger(index, value);\n } else {\n stmt.bindDouble(index, value);\n }\n } else if (typeof value === 'boolean') {\n stmt.bindBoolean(index, value);\n } else if (typeof value === 'bigint') {\n stmt.bindBigInt(index, value);\n } else if (value instanceof Date) {\n stmt.bindTimestamp(index, new DuckDBTimestampValue(BigInt(value.getTime()) * 1000n));\n } else if (value instanceof DuckDBTimestampValue) {\n stmt.bindTimestamp(index, value);\n } else if (value instanceof DuckDBTimestampTZValue) {\n stmt.bindTimestampTZ(index, value);\n } else {\n // Fallback: serialize to JSON string\n stmt.bindVarchar(index, JSON.stringify(value));\n }\n}\n\n/** Convert DuckDB-specific return types to plain JS types */\nfunction toJsValue(val: unknown): unknown {\n if (val === null || val === undefined) return val;\n // DuckDBTimestampValue → Date (micros since epoch)\n if (val instanceof DuckDBTimestampValue) {\n return new Date(Number(val.micros / 1000n));\n }\n // BigInt → Number (safe for values we care about)\n if (typeof val === 'bigint') {\n return Number(val);\n }\n return val;\n}\n\n/** Configuration for the DuckDB database connection. */\nexport interface DuckDBStorageConfig {\n /** Path to the DuckDB file. Defaults to 'mastra.duckdb'. Use ':memory:' for ephemeral. */\n path?: string;\n}\n\n/**\n * Shared DuckDB connection management for Mastra storage.\n * Defaults to a local file (`mastra.duckdb`) when no path is provided.\n * Pass `path: ':memory:'` for an ephemeral in-memory database.\n */\nexport class DuckDBConnection extends MastraBase {\n private instance: DuckDBInstance | null = null;\n private initialized = false;\n private initPromise: Promise<void> | null = null;\n private path: string;\n\n constructor(config: DuckDBStorageConfig = {}) {\n super({ component: 'STORAGE', name: 'DUCKDB' });\n this.path = config.path ?? 'mastra.duckdb';\n }\n\n private async initialize(): Promise<void> {\n if (this.initialized && this.instance) return;\n\n if (this.initPromise) {\n await this.initPromise;\n if (this.instance) return;\n this.initPromise = null;\n this.initialized = false;\n }\n\n this.initPromise = (async () => {\n try {\n this.instance = await DuckDBInstance.create(this.path);\n this.initialized = true;\n } catch (error) {\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n throw error;\n }\n })();\n\n return this.initPromise;\n }\n\n /** Create a new connection to the DuckDB instance, initializing if needed. */\n async getConnection() {\n await this.initialize();\n if (!this.instance) {\n throw new Error('DuckDB instance not initialized');\n }\n return this.instance.connect();\n }\n\n private closeConnection(connection: unknown): void {\n const conn = connection as {\n closeSync?: () => void;\n disconnectSync?: () => void;\n close?: () => void;\n disconnect?: () => void;\n };\n try {\n if (typeof conn?.closeSync === 'function') {\n conn.closeSync();\n return;\n }\n if (typeof conn?.disconnectSync === 'function') {\n conn.disconnectSync();\n return;\n }\n if (typeof conn?.close === 'function') {\n conn.close();\n return;\n }\n if (typeof conn?.disconnect === 'function') {\n conn.disconnect();\n }\n } catch {\n // Ignore close failures to avoid masking query/execute errors.\n }\n }\n\n /**\n * Execute a SQL query and return results as objects.\n */\n async query<T = Record<string, unknown>>(sql: string, params: unknown[] = []): Promise<T[]> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n const result = await connection.run(sql);\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n }\n\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n const result = await stmt.run();\n const rows = await result.getRows();\n const columns = result.columnNames();\n return rows.map(row => {\n const obj: Record<string, unknown> = {};\n columns.forEach((col, i) => {\n obj[col] = toJsValue(row[i]);\n });\n return obj as T;\n });\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Execute a SQL statement without returning results.\n */\n async execute(sql: string, params: unknown[] = []): Promise<void> {\n const connection = await this.getConnection();\n try {\n if (params.length === 0) {\n await connection.run(sql);\n return;\n }\n let paramIndex = 0;\n const preparedSql = sql.replace(/\\?/g, () => `$${++paramIndex}`);\n const stmt = await connection.prepare(preparedSql);\n for (let i = 0; i < params.length; i++) {\n bindParam(stmt, i + 1, params[i]);\n }\n await stmt.run();\n } finally {\n this.closeConnection(connection);\n }\n }\n\n /**\n * Escape a value for safe inline SQL use.\n * DuckDB prepared statements can't handle NULL for parameters typed as ANY,\n * so for complex INSERT/UPDATE operations we inline values safely.\n */\n static sqlValue(value: unknown): string {\n if (value === null || value === undefined) return 'NULL';\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) return 'NULL';\n return String(value);\n }\n if (typeof value === 'boolean') return value ? 'TRUE' : 'FALSE';\n if (value instanceof Date) return `'${value.toISOString()}'::TIMESTAMP`;\n if (typeof value === 'string') return `'${value.replace(/'/g, \"''\")}'`;\n // Objects/arrays → JSON string\n return `'${JSON.stringify(value).replace(/'/g, \"''\")}'`;\n }\n\n /** Release the DuckDB instance, allowing garbage collection. */\n async close(): Promise<void> {\n if (this.instance) {\n try {\n const instance = this.instance as unknown as { closeSync?: () => void; close?: () => void };\n if (typeof instance.closeSync === 'function') {\n instance.closeSync();\n } else if (typeof instance.close === 'function') {\n instance.close();\n }\n } catch {\n // Ignore close failures to allow cleanup of references.\n }\n this.instance = null;\n this.initialized = false;\n this.initPromise = null;\n }\n }\n}\n"]}
@@ -3,7 +3,7 @@ name: mastra-duckdb
3
3
  description: Documentation for @mastra/duckdb. Use when working with @mastra/duckdb APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/duckdb"
6
- version: "1.0.1"
6
+ version: "1.1.0-alpha.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -16,7 +16,7 @@ Read the individual reference documents for detailed explanations and code examp
16
16
 
17
17
  ### Reference
18
18
 
19
- - [Reference: DuckDBVector Store](references/reference-vectors-duckdb.md) - Documentation for the DuckDBVector class in Mastra, which provides embedded high-performance vector search using DuckDB with HNSW indexing.
19
+ - [Reference: DuckDB vector store](references/reference-vectors-duckdb.md) - Documentation for the DuckDBVector class in Mastra, which provides embedded high-performance vector search using DuckDB with HNSW indexing.
20
20
 
21
21
 
22
22
  Read [assets/SOURCE_MAP.json](assets/SOURCE_MAP.json) for source code references.
@@ -1,6 +1,12 @@
1
1
  {
2
- "version": "1.0.1",
2
+ "version": "1.1.0-alpha.1",
3
3
  "package": "@mastra/duckdb",
4
- "exports": {},
4
+ "exports": {
5
+ "DuckDBConnection": {
6
+ "types": "dist/index.d.ts",
7
+ "implementation": "dist/chunk-37GBWD4M.js",
8
+ "line": 40
9
+ }
10
+ },
5
11
  "modules": {}
6
12
  }