@stoolap/node 0.3.3 → 0.3.5

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.
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+
3
+ const { processParams } = require("./ffi");
4
+ const { parseRows, parseRaw } = require("./parse");
5
+
6
+ class Transaction {
7
+ #ptr = null;
8
+ #stoolap = null;
9
+ #dbPtr = null;
10
+ #pendingAsync = 0;
11
+ #tail = Promise.resolve();
12
+ #closingPromise = null;
13
+ #owner = null;
14
+
15
+ constructor(ptr, stoolap, owner, dbPtr) {
16
+ this.#ptr = ptr;
17
+ this.#stoolap = stoolap;
18
+ this.#owner = owner || null;
19
+ this.#dbPtr = dbPtr || null;
20
+ }
21
+
22
+ _invalidate() {
23
+ this.#ptr = null;
24
+ }
25
+
26
+ #checkOpen() {
27
+ if (!this.#ptr) throw new Error("Transaction is closed");
28
+ }
29
+
30
+ #checkSyncReady() {
31
+ this.#checkOpen();
32
+ if (this.#closingPromise || this.#pendingAsync > 0) {
33
+ throw new Error("Transaction has pending async operations");
34
+ }
35
+ }
36
+
37
+ #enqueueAsync(operation) {
38
+ this.#checkOpen();
39
+ if (this.#closingPromise) throw new Error("Transaction is closing");
40
+
41
+ const ptr = this.#ptr;
42
+ const run = async () => {
43
+ this.#pendingAsync += 1;
44
+ try {
45
+ return await operation(ptr);
46
+ } finally {
47
+ this.#pendingAsync -= 1;
48
+ }
49
+ };
50
+
51
+ const promise = this.#tail.then(run, run);
52
+ this.#tail = promise.catch(() => {});
53
+ return promise;
54
+ }
55
+
56
+ // -- Execute --
57
+
58
+ async execute(sql, params) {
59
+ return this.#enqueueAsync((ptr) => {
60
+ if (!params) return this.#stoolap.txExecAsync(ptr, sql);
61
+ if (Array.isArray(params)) {
62
+ if (params.length === 0) return this.#stoolap.txExecAsync(ptr, sql);
63
+ return this.#stoolap.txExecAsync(ptr, sql, params);
64
+ }
65
+ const p = processParams(sql, params);
66
+ return p.values
67
+ ? this.#stoolap.txExecAsync(ptr, p.sql, p.values)
68
+ : this.#stoolap.txExecAsync(ptr, sql);
69
+ });
70
+ }
71
+
72
+ executeSync(sql, params) {
73
+ this.#checkSyncReady();
74
+ if (!params) return this.#stoolap.txExec(this.#ptr, sql);
75
+ if (Array.isArray(params)) {
76
+ if (params.length === 0) return this.#stoolap.txExec(this.#ptr, sql);
77
+ return this.#stoolap.txExec(this.#ptr, sql, params);
78
+ }
79
+ const p = processParams(sql, params);
80
+ return p.values
81
+ ? this.#stoolap.txExec(this.#ptr, p.sql, p.values)
82
+ : this.#stoolap.txExec(this.#ptr, sql);
83
+ }
84
+
85
+ // -- Query --
86
+
87
+ async query(sql, params) {
88
+ const buf = await this.#enqueueAsync((ptr) => {
89
+ if (!params) return this.#stoolap.txQueryBufAsync(ptr, sql);
90
+ if (Array.isArray(params)) {
91
+ if (params.length === 0) return this.#stoolap.txQueryBufAsync(ptr, sql);
92
+ return this.#stoolap.txQueryBufAsync(ptr, sql, params);
93
+ }
94
+ const p = processParams(sql, params);
95
+ return p.values
96
+ ? this.#stoolap.txQueryBufAsync(ptr, p.sql, p.values)
97
+ : this.#stoolap.txQueryBufAsync(ptr, sql);
98
+ });
99
+ return parseRows(buf);
100
+ }
101
+
102
+ querySync(sql, params) {
103
+ this.#checkSyncReady();
104
+ let result;
105
+ if (!params) {
106
+ result = this.#stoolap.txQuery(this.#ptr, sql);
107
+ } else if (Array.isArray(params)) {
108
+ result =
109
+ params.length === 0
110
+ ? this.#stoolap.txQuery(this.#ptr, sql)
111
+ : this.#stoolap.txQuery(this.#ptr, sql, params);
112
+ } else {
113
+ const p = processParams(sql, params);
114
+ result = p.values
115
+ ? this.#stoolap.txQuery(this.#ptr, p.sql, p.values)
116
+ : this.#stoolap.txQuery(this.#ptr, sql);
117
+ }
118
+ return Array.isArray(result) ? result : parseRows(result);
119
+ }
120
+
121
+ // -- QueryOne --
122
+
123
+ async queryOne(sql, params) {
124
+ const rows = await this.query(sql, params);
125
+ return rows.length === 0 ? null : rows[0];
126
+ }
127
+
128
+ queryOneSync(sql, params) {
129
+ this.#checkSyncReady();
130
+ if (!params) return this.#stoolap.txQueryOne(this.#ptr, sql);
131
+ if (Array.isArray(params)) {
132
+ if (params.length === 0) return this.#stoolap.txQueryOne(this.#ptr, sql);
133
+ return this.#stoolap.txQueryOne(this.#ptr, sql, params);
134
+ }
135
+ const p = processParams(sql, params);
136
+ return p.values
137
+ ? this.#stoolap.txQueryOne(this.#ptr, p.sql, p.values)
138
+ : this.#stoolap.txQueryOne(this.#ptr, sql);
139
+ }
140
+
141
+ // -- QueryRaw --
142
+
143
+ async queryRaw(sql, params) {
144
+ const buf = await this.#enqueueAsync((ptr) => {
145
+ if (!params) return this.#stoolap.txQueryBufAsync(ptr, sql);
146
+ if (Array.isArray(params)) {
147
+ if (params.length === 0) return this.#stoolap.txQueryBufAsync(ptr, sql);
148
+ return this.#stoolap.txQueryBufAsync(ptr, sql, params);
149
+ }
150
+ const p = processParams(sql, params);
151
+ return p.values
152
+ ? this.#stoolap.txQueryBufAsync(ptr, p.sql, p.values)
153
+ : this.#stoolap.txQueryBufAsync(ptr, sql);
154
+ });
155
+ return parseRaw(buf);
156
+ }
157
+
158
+ queryRawSync(sql, params) {
159
+ this.#checkSyncReady();
160
+ let buf;
161
+ if (!params) {
162
+ buf = this.#stoolap.txQueryBuf(this.#ptr, sql);
163
+ } else if (Array.isArray(params)) {
164
+ buf =
165
+ params.length === 0
166
+ ? this.#stoolap.txQueryBuf(this.#ptr, sql)
167
+ : this.#stoolap.txQueryBuf(this.#ptr, sql, params);
168
+ } else {
169
+ const p = processParams(sql, params);
170
+ buf = p.values
171
+ ? this.#stoolap.txQueryBuf(this.#ptr, p.sql, p.values)
172
+ : this.#stoolap.txQueryBuf(this.#ptr, sql);
173
+ }
174
+ return parseRaw(buf);
175
+ }
176
+
177
+ // -- Batch --
178
+
179
+ executeBatchSync(sql, paramsArray) {
180
+ this.#checkSyncReady();
181
+ if (paramsArray.length > 0 && Array.isArray(paramsArray[0])) {
182
+ return this.#stoolap.txExecBatch(this.#dbPtr, this.#ptr, sql, paramsArray);
183
+ }
184
+ let totalChanges = 0;
185
+ for (const params of paramsArray) {
186
+ const p = processParams(sql, params);
187
+ const result = p.values
188
+ ? this.#stoolap.txExec(this.#ptr, p.sql, p.values)
189
+ : this.#stoolap.txExec(this.#ptr, sql);
190
+ totalChanges += result.changes;
191
+ }
192
+ return { changes: totalChanges };
193
+ }
194
+
195
+ // -- Commit / Rollback --
196
+
197
+ async commit() {
198
+ this.#checkOpen();
199
+ if (this.#closingPromise) return this.#closingPromise;
200
+
201
+ const ptr = this.#ptr;
202
+ this.#closingPromise = this.#tail
203
+ .then(() => this.#stoolap.txCommitAsync(ptr))
204
+ .finally(() => {
205
+ this.#ptr = null;
206
+ this.#closingPromise = null;
207
+ if (this.#owner) this.#owner._untrackChild(this);
208
+ });
209
+
210
+ this.#tail = this.#closingPromise.catch(() => {});
211
+ return this.#closingPromise;
212
+ }
213
+
214
+ commitSync() {
215
+ this.#checkSyncReady();
216
+ const ptr = this.#ptr;
217
+ this.#ptr = null;
218
+ this.#stoolap.txCommit(ptr);
219
+ if (this.#owner) this.#owner._untrackChild(this);
220
+ }
221
+
222
+ async rollback() {
223
+ this.#checkOpen();
224
+ if (this.#closingPromise) return this.#closingPromise;
225
+
226
+ const ptr = this.#ptr;
227
+ this.#closingPromise = this.#tail
228
+ .then(() => this.#stoolap.txRollbackAsync(ptr))
229
+ .finally(() => {
230
+ this.#ptr = null;
231
+ this.#closingPromise = null;
232
+ if (this.#owner) this.#owner._untrackChild(this);
233
+ });
234
+
235
+ this.#tail = this.#closingPromise.catch(() => {});
236
+ return this.#closingPromise;
237
+ }
238
+
239
+ rollbackSync() {
240
+ this.#checkSyncReady();
241
+ const ptr = this.#ptr;
242
+ this.#ptr = null;
243
+ this.#stoolap.txRollback(ptr);
244
+ if (this.#owner) this.#owner._untrackChild(this);
245
+ }
246
+ }
247
+
248
+ module.exports = { Transaction };
package/package.json CHANGED
@@ -1,42 +1,35 @@
1
1
  {
2
2
  "name": "@stoolap/node",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "High-performance Node.js driver for Stoolap embedded SQL database",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
- "napi": {
8
- "binaryName": "stoolap",
9
- "targets": [
10
- "aarch64-apple-darwin",
11
- "x86_64-apple-darwin",
12
- "x86_64-unknown-linux-gnu",
13
- "aarch64-unknown-linux-gnu",
14
- "x86_64-pc-windows-msvc"
15
- ]
16
- },
17
7
  "files": [
18
8
  "index.js",
19
- "index.d.ts"
9
+ "index.d.ts",
10
+ "lib/",
11
+ "src/stoolap.c",
12
+ "binding.gyp"
20
13
  ],
21
14
  "scripts": {
22
- "build": "napi build --platform --release --no-dts-header && node scripts/patch-dts.mjs",
23
- "build:debug": "napi build --platform --no-dts-header && node scripts/patch-dts.mjs",
15
+ "install": "node-gyp rebuild",
16
+ "build": "node-gyp rebuild",
24
17
  "test": "node --test __test__/index.spec.mjs",
25
- "prepublishOnly": "napi version"
18
+ "bench": "node benchmark.mjs"
26
19
  },
27
20
  "optionalDependencies": {
28
- "@stoolap/node-darwin-arm64": "0.3.3",
29
- "@stoolap/node-darwin-x64": "0.3.3",
30
- "@stoolap/node-linux-x64-gnu": "0.3.3",
31
- "@stoolap/node-linux-arm64-gnu": "0.3.3",
32
- "@stoolap/node-win32-x64-msvc": "0.3.3"
21
+ "@stoolap/lib-darwin-arm64": "0.3.5",
22
+ "@stoolap/lib-darwin-x64": "0.3.5",
23
+ "@stoolap/lib-linux-arm64-gnu": "0.3.5",
24
+ "@stoolap/lib-linux-x64-gnu": "0.3.5",
25
+ "@stoolap/lib-win32-x64-msvc": "0.3.5"
33
26
  },
34
27
  "devDependencies": {
35
- "@napi-rs/cli": "^3.0.0",
36
- "better-sqlite3": "^12.6.2"
28
+ "better-sqlite3": "^12.6.2",
29
+ "node-gyp": "^11.2.0"
37
30
  },
38
31
  "engines": {
39
- "node": ">= 22"
32
+ "node": ">= 18"
40
33
  },
41
34
  "license": "Apache-2.0",
42
35
  "repository": {
@@ -54,7 +47,6 @@
54
47
  "mvcc",
55
48
  "acid",
56
49
  "stoolap",
57
- "napi",
58
50
  "native"
59
51
  ]
60
52
  }