@cocreate/sqlite 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +141 -51
  3. package/package.json +15 -10
  4. package/src/index.js +106 -113
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [1.2.0](https://github.com/CoCreate-app/CoCreate-sqlite/compare/v1.1.0...v1.2.0) (2026-07-19)
2
+
3
+
4
+ ### Features
5
+
6
+ * Update README to reflect CoCreate-sqlite functionality and documentation ([bfd599f](https://github.com/CoCreate-app/CoCreate-sqlite/commit/bfd599f98289370b4db52a993e0c51ab1b9559b0))
7
+
8
+ # [1.1.0](https://github.com/CoCreate-app/CoCreate-sqlite/compare/v1.0.0...v1.1.0) (2026-07-18)
9
+
10
+
11
+ ### Features
12
+
13
+ * Refactor to use @libsql/client and update database handling ([3569e47](https://github.com/CoCreate-app/CoCreate-sqlite/commit/3569e47a98dc076ff8beb45e59880abefbbf3da7))
14
+
1
15
  # 1.0.0 (2026-07-18)
2
16
 
3
17
 
package/README.md CHANGED
@@ -1,88 +1,178 @@
1
- # CoCreate-mongodb
1
+ # sqlite
2
2
 
3
- A simple mongodb component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API. Take it for a spin in our [playground!](https://cocreate.app/docs/mongodb)
3
+ A highly efficient, enterprise-grade SQLite relational database CRUD wrapper and state-routing backend client for the collaborative CoCreate ecosystem. This wrapper maps SQLite's lightweight, zero-configuration embedded SQL capabilities into CoCreate's unified JSON interface.
4
4
 
5
- ![GitHub latest release](https://img.shields.io/github/v/release/CoCreate-app/CoCreate-mongodb?style=flat-square)
6
- ![GitHub](https://img.shields.io/github/license/CoCreate-app/CoCreate-mongodb?style=flat-square)
7
- ![GitHub](https://img.shields.io/static/v1?style=flat-square&label=&message=Hiring&color=blueviolet)
5
+ ## Documentation
8
6
 
9
- ![CoCreate-mongodb](https://cdn.cocreate.app/docs/CoCreate-mongodb.gif)
7
+ For a complete guide and working integration examples, refer to the [CoCreate SQLite Documentation](https://www.google.com/search?q=https://cocreatejs.com/docs/sqlite).
10
8
 
11
- ## [Docs & Demo](https://cocreate.app/docs/mongodb)
9
+ ---
12
10
 
13
- For a complete guide and working demo refer to the [doumentation](https://cocreate.app/docs/mongodb)
11
+ ## Table of Contents
14
12
 
15
- ## CDN
13
+ * [The Power of the CoCreate Unified Ecosystem](https://www.google.com/search?q=%23the-power-of-the-cocreate-unified-ecosystem)
14
+ * [Why SQLite?](https://www.google.com/search?q=%23why-sqlite)
15
+ * [Installation](https://www.google.com/search?q=%23installation)
16
+ * [Unified JSON Payload Examples](https://www.google.com/search?q=%23unified-json-payload-examples)
17
+ * [Announcements](https://www.google.com/search?q=%23announcements)
18
+ * [Roadmap](https://www.google.com/search?q=%23roadmap)
19
+ * [How to Contribute](https://www.google.com/search?q=%23how-to-contribute)
20
+ * [About](https://www.google.com/search?q=%23about)
16
21
 
17
- ```html
18
- <script src="https://cdn.cocreate.app/mongodb/latest/CoCreate-mongodb.min.js"></script>
19
- ```
22
+ ---
20
23
 
21
- ```html
22
- <script src="https://cdn.cocreate.app/mongodb/latest/CoCreate-mongodb.min.css"></script>
23
- ```
24
+ ## The Power of the CoCreate Unified Ecosystem
24
25
 
25
- ## NPM
26
+ This is not just another database driver. By wrapping SQLite into the CoCreate state-routing pipeline, you unlock the full power of a multi-cloud, multi-model data orchestration mesh:
26
27
 
27
- ```shell
28
- $ npm i @cocreate/mongodb
29
- ```
28
+ * **Unified JSON Interface (MongoDB-like Syntax):** You don't need to write raw SQL dialect strings or manually create storage table schemas. CoCreate translates standard NoSQL JSON CRUD operations (such as `object.create` or `object.read`) transparently into optimized SQLite single-file relational statements under the hood.
29
+ * **Parallel Multi-Database Writing:** Write to many target databases simultaneously with a single API call. You can stream transactional data to MongoDB (for instant operational state), vectorize it into Qdrant (for real-time semantic search), and persist it in SQLite (for lightweight local prototyping or embedded execution) in perfect parallel harmony:
30
+
31
+ $$\text{Write Command} \xrightarrow{\text{Parallel Mesh}} \begin{cases} \text{MongoDB} & \text{(ACID Transaction Store)} \\ \text{Qdrant} & \text{(Semantic Vector Search)} \\ \text{SQLite} & \text{(Embedded Relational Engine)} \end{cases}$$
32
+
33
+ * **Dynamic State-Routing:** Isolate multi-tenant environments effortlessly. The routing mesh automatically injects tenant metadata and organization boundaries, dynamically selecting separate `.db` file descriptors or table workspaces within your shared infrastructure.
34
+
35
+ ---
36
+
37
+ ## Why SQLite?
38
+
39
+ SQLite is an in-process library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine. It is the most widely deployed database engine in the world, running natively inside mobile apps, IoT gateways, desktop software, and minimal cloud environments.
30
40
 
31
- ## yarn
41
+ By routing application configurations, localized cache files, or local testing datasets straight to SQLite via this wrapper, you leverage full ACID-compliant structured SQL storage directly out of an embedded, hyper-portable file system instance while maintaining a zero-friction JSON pipeline.
42
+
43
+ ---
44
+
45
+ ## Installation
46
+
47
+ ### NPM Installation
48
+
49
+ ```bash
50
+ npm i @cocreate/sqlite
32
51
 
33
- ```shell
34
- $ yarn install @cocreate/mongodb
35
52
  ```
36
53
 
37
- # Table of Contents
54
+ ### Yarn Installation
38
55
 
39
- - [Table of Contents](#table-of-contents)
40
- - [Announcements](#announcements)
41
- - [Roadmap](#roadmap)
42
- - [How to Contribute](#how-to-contribute)
43
- - [About](#about)
44
- - [License](#license)
56
+ ```bash
57
+ yarn add @cocreate/sqlite
45
58
 
46
- <a name="announcements"></a>
59
+ ```
47
60
 
48
- # Announcements
61
+ ---
62
+
63
+ ## Unified JSON Payload Examples
64
+
65
+ Here are the complete, real-world JSON objects representing raw payloads routed through the CoCreate system. By declaring an array in the `storage` key, CoCreate fires the write operations to all specified backends simultaneously in parallel.
66
+
67
+ ### 1. Writing a Full Transaction Object (`object.create`)
68
+
69
+ When this operational payload is sent, CoCreate registers it, processes the nested JSON fields, and automatically warehouses it across all listed parallel storage platforms.
70
+
71
+ ```json
72
+ {
73
+ "method": "object.create",
74
+ "storage": ["sqlite", "mongodb", "qdrant"], // Array of storages to store in parallel!
75
+ "database": "sales_analytics",
76
+ "array": "order_events",
77
+ "object": {
78
+ "_id": "order_77c8f2a9_3b01",
79
+ "customer": {
80
+ "id": "cust_88301",
81
+ "email": "customer@example.com",
82
+ "region": "North America",
83
+ "acquisition_channel": "Google Search"
84
+ },
85
+ "transaction": {
86
+ "payment_method": "Credit Card",
87
+ "currency": "USD",
88
+ "subtotal": 249.99,
89
+ "discount": 15.00,
90
+ "tax": 18.80,
91
+ "total": 253.79
92
+ },
93
+ "items": [
94
+ {
95
+ "product_id": "prod_head_009",
96
+ "name": "Wireless Noise-Cancelling Headphones",
97
+ "category": "Electronics",
98
+ "quantity": 1,
99
+ "unit_price": 199.99
100
+ },
101
+ {
102
+ "product_id": "prod_stand_012",
103
+ "name": "Aluminum Headphone Stand",
104
+ "category": "Accessories",
105
+ "quantity": 2,
106
+ "unit_price": 25.00
107
+ }
108
+ ],
109
+ "shipping": {
110
+ "carrier": "FedEx",
111
+ "service": "2-Day Air",
112
+ "estimated_delivery": "2026-07-20T12:00:00.000Z"
113
+ }
114
+ },
115
+ "organization_id": "org_enterprise_99x",
116
+ "user_id": "usr_sales_runner_402",
117
+ "timeStamp": "2026-07-18T18:40:43.000Z"
118
+ }
49
119
 
50
- All updates to this library are documented in our [CHANGELOG](https://github.com/CoCreate-app/CoCreate-mongodb/blob/master/CHANGELOG.md) and [releases](https://github.com/CoCreate-app/CoCreate-mongodb/releases). You may also subscribe to email for releases and breaking changes.
120
+ ```
51
121
 
52
- <a name="roadmap"></a>
122
+ ### 2. Reading and Filtering Warehoused Data (`object.read`)
123
+
124
+ Querying targets a single database engine via a string filter syntax. The query below retrieves high-value orders handled by a specific shipping carrier from SQLite, sorting them by total sale volume.
125
+
126
+ ```json
127
+ {
128
+ "method": "object.read",
129
+ "storage": "sqlite",
130
+ "database": "sales_analytics",
131
+ "array": "order_events",
132
+ "$filter": {
133
+ "query": {
134
+ "transaction.total": { "$gte": 100.00 },
135
+ "shipping.carrier": "FedEx"
136
+ },
137
+ "sort": [
138
+ { "key": "transaction.total", "direction": "desc" }
139
+ ],
140
+ "limit": 50,
141
+ "index": 0
142
+ },
143
+ "organization_id": "org_enterprise_99x"
144
+ }
53
145
 
54
- # Roadmap
146
+ ```
55
147
 
56
- If you are interested in the future direction of this project, please take a look at our open [issues](https://github.com/CoCreate-app/CoCreate-mongodb/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-mongodb/pulls). We would love to hear your feedback.
148
+ ---
57
149
 
58
- <a name="about"></a>
150
+ ## Announcements
59
151
 
60
- # About
152
+ All updates to this library are documented in our `CHANGELOG` and releases. You may also subscribe to email for releases and breaking changes.
61
153
 
62
- CoCreate-mongodb is guided and supported by the CoCreate Developer Experience Team.
154
+ ---
63
155
 
64
- Please Email the Developer Experience Team [here](mailto:develop@cocreate.app) in case of any queries.
156
+ ## Roadmap
65
157
 
66
- CoCreate-mongodb is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
158
+ If you are interested in the future direction of this project, please take a look at our open issues and pull requests. We would love to hear your feedback.
67
159
 
68
- <a name="contribute"></a>
160
+ ---
69
161
 
70
- # How to Contribute
162
+ ## How to Contribute
71
163
 
72
- We encourage contribution to our libraries (you might even score some nifty swag), please see our [CONTRIBUTING](https://github.com/CoCreate-app/CoCreate-mongodb/blob/master/CONTRIBUTING.md) guide for details.
164
+ We encourage contribution to our libraries (you might even score some nifty swag), please see our `CONTRIBUTING` guide for details.
73
165
 
74
- We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create [issues](https://github.com/CoCreate-app/CoCreate-mongodb/issues) and [pull requests](https://github.com/CoCreate-app/CoCreate-mongodb/pulls) or merely upvote or comment on existing issues or pull requests.
166
+ We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create issues and pull requests or merely upvote or comment on existing issues or pull requests.
75
167
 
76
168
  We appreciate your continued support, thank you!
77
169
 
78
- <a name="license"></a>
79
-
80
- # License
170
+ ---
81
171
 
82
- This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.
172
+ ## About
83
173
 
84
- - **Open Source Use**: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the [LICENSE file](https://github.com/CoCreate-app/CoCreate-mongodb/blob/master/LICENSE).
174
+ `CoCreate-sqlite` is guided and supported by the **CoCreate Developer Experience Team**.
85
175
 
86
- - **Commercial Use**: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our [website](https://cocreate.app). This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.
176
+ > Please Email the Developer Experience Team here in case of any queries.
87
177
 
88
- If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.
178
+ `CoCreate-sqlite` is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "@cocreate/sqlite",
3
- "version": "1.0.0",
4
- "description": "A simple sqlite component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
3
+ "version": "1.2.0",
4
+ "description": "Lightweight SQLite CRUD wrapper and multi-tenant state routing client for the CoCreate ecosystem.",
5
5
  "keywords": [
6
6
  "sqlite",
7
- "low-code",
8
- "realtime",
9
- "realtime-framework",
10
- "collaboration",
11
- "shared-editing",
12
- "html5-framework",
13
- "javascript-framework"
7
+ "sqlite3",
8
+ "sql",
9
+ "json",
10
+ "crud-api",
11
+ "abstract-crud",
12
+ "database-abstraction",
13
+ "multi-tenant",
14
+ "multi-tenant-routing",
15
+ "realtime-sync",
16
+ "state-synchronization",
17
+ "state-routing",
18
+ "embedded-replicas"
14
19
  ],
15
20
  "publishConfig": {
16
21
  "access": "public"
@@ -38,6 +43,6 @@
38
43
  "main": "./src/index.js",
39
44
  "dependencies": {
40
45
  "@cocreate/utils": "^1.44.0",
41
- "sqlite": "^7.5.0"
46
+ "@libsql/client": "^0.6.0"
42
47
  }
43
48
  }
package/src/index.js CHANGED
@@ -1,46 +1,35 @@
1
- const sqlite3 = require("sqlite3");
2
- const {
1
+ /********************************************************************************
2
+ * Copyright (C) 2026 CoCreate and Contributors.
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU Affero General Public License as published
6
+ * by the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU Affero General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Affero General Public License
15
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ ********************************************************************************/
17
+
18
+ import { createClient } from "@libsql/client";
19
+ import {
3
20
  dotNotationToObject,
4
21
  queryData,
5
22
  searchData,
6
23
  sortData,
7
24
  isValidDate
8
- } = require("@cocreate/utils");
25
+ } from "@cocreate/utils";
9
26
 
10
27
  const organizations = {};
11
28
 
12
29
  /**
13
- * Promisified database helpers to clean up sqlite3's callback-based API.
14
- */
15
- function runQuery(db, sql, params = []) {
16
- return new Promise((resolve, reject) => {
17
- db.run(sql, params, function (err) {
18
- if (err) reject(err);
19
- else resolve({ lastID: this.lastID, changes: this.changes });
20
- });
21
- });
22
- }
23
-
24
- function allQuery(db, sql, params = []) {
25
- return new Promise((resolve, reject) => {
26
- db.all(sql, params, (err, rows) => {
27
- if (err) reject(err);
28
- else resolve(rows);
29
- });
30
- });
31
- }
32
-
33
- function getQuery(db, sql, params = []) {
34
- return new Promise((resolve, reject) => {
35
- db.get(sql, params, (err, row) => {
36
- if (err) reject(err);
37
- else resolve(row);
38
- });
39
- });
40
- }
41
-
42
- /**
43
- * Dynamically resolves or caches a long-lived SQLite Connection handle.
30
+ * Dynamically resolves or caches a long-lived libSQL Database Client.
31
+ * Supports standard local SQLite files ("file:local.db"), in-memory paths (":memory:"),
32
+ * and remote Turso connections ("libsql://...") with cloud tokens.
44
33
  */
45
34
  async function dbClient(data) {
46
35
  if (data.storageUrl) {
@@ -49,25 +38,28 @@ async function dbClient(data) {
49
38
  }
50
39
  try {
51
40
  if (!organizations[data.organization_id][data.storageUrl]) {
52
- // Establish sqlite3 handle. Path can be file based or in-memory ':memory:'
53
- const dbPath = data.storageUrl.replace("sqlite://", "");
54
-
55
- const connectionPromise = new Promise((resolve, reject) => {
56
- const client = new sqlite3.Database(dbPath, (err) => {
57
- if (err) reject(err);
58
- else resolve(client);
59
- });
60
- });
41
+ const connectionPromise = (async () => {
42
+ let config = { url: data.storageUrl };
43
+
44
+ // If an authentication token is passed inside dynamic payloads for cloud/Turso targets
45
+ if (data.authToken || data.auth_token) {
46
+ config.authToken = data.authToken || data.auth_token;
47
+ }
48
+
49
+ const client = createClient(config);
50
+
51
+ // Verify active driver connectivity safely
52
+ await client.execute("SELECT 1;");
53
+ return client;
54
+ })();
61
55
 
62
56
  organizations[data.organization_id][data.storageUrl] = connectionPromise;
63
57
  }
64
-
65
- // Await the cached connection promise resolution
66
- organizations[data.organization_id][data.storageUrl] = await organizations[data.organization_id][data.storageUrl];
67
- return organizations[data.organization_id][data.storageUrl];
58
+
59
+ return await organizations[data.organization_id][data.storageUrl];
68
60
  } catch (error) {
69
61
  console.error(
70
- `${data.organization_id}: storageUrl ${data.storageUrl} failed to connect to SQLite`
62
+ `${data.organization_id}: Connection failed using @libsql/client`
71
63
  );
72
64
  errorHandler(data, error);
73
65
  return { status: false };
@@ -80,36 +72,32 @@ async function dbClient(data) {
80
72
 
81
73
  /**
82
74
  * Global Event Listener: orgDeleted
83
- * Gracefully terminates active SQLite connections and releases lock pools.
75
+ * Gracefully terminates active libSQL database connections and clears the local pool cache.
84
76
  */
85
77
  process.on("orgDeleted", (organization_id) => {
86
78
  const orgPools = organizations[organization_id];
87
79
  if (orgPools) {
88
- console.log(`[SQLite Utilities] Cleanup Scheduled: Initiating 5-second grace period for Org: ${organization_id}`);
80
+ console.log(`[libSQL Utilities] Cleanup Scheduled: Initiating 5-second grace period for Org: ${organization_id}`);
89
81
  setTimeout(async () => {
90
82
  const currentPools = organizations[organization_id];
91
83
  if (!currentPools) return;
92
84
 
93
- console.log(`[SQLite Utilities] Cleanup Executing: Closing connection handles for Org: ${organization_id}`);
85
+ console.log(`[libSQL Utilities] Cleanup Executing: Closing connection clients for Org: ${organization_id}`);
94
86
  const dbList = Object.values(currentPools);
95
87
 
96
- for (const db of dbList) {
88
+ for (const dbPromise of dbList) {
97
89
  try {
90
+ const db = await dbPromise;
98
91
  if (db && typeof db.close === "function") {
99
- await new Promise((resolve, reject) => {
100
- db.close((err) => {
101
- if (err) reject(err);
102
- else resolve();
103
- });
104
- });
92
+ db.close();
105
93
  }
106
94
  } catch (err) {
107
- console.error(`[SQLite Utilities] Error closing connection for Org ${organization_id}:`, err);
95
+ console.error(`[libSQL Utilities] Error closing connection for Org ${organization_id}:`, err);
108
96
  }
109
97
  }
110
98
 
111
99
  delete organizations[organization_id];
112
- console.log(`[SQLite Utilities] Memory Cleared: Registry freed for Org: ${organization_id}`);
100
+ console.log(`[libSQL Utilities] Memory Cleared: Registry freed for Org: ${organization_id}`);
113
101
  }, 5000);
114
102
  }
115
103
  });
@@ -117,7 +105,7 @@ process.on("orgDeleted", (organization_id) => {
117
105
  /**
118
106
  * Universal router routing request methods safely.
119
107
  */
120
- function send(data) {
108
+ export function send(data) {
121
109
  let [type, method] = data.method.split(".");
122
110
  if (type === "database") return database(method, data);
123
111
  if (type === "array") return array(method, data);
@@ -128,6 +116,7 @@ function send(data) {
128
116
  * "database" operations mapped to SQLite Files (emulated catalogs).
129
117
  */
130
118
  function database(method, data) {
119
+ const storageName = data.storageName || data.provider || "sqlite";
131
120
  return new Promise(
132
121
  async (resolve, reject) => {
133
122
  let type = "database";
@@ -135,10 +124,9 @@ function database(method, data) {
135
124
 
136
125
  try {
137
126
  const db = await dbClient(data);
138
- if (!db || db.status === false) return data;
127
+ if (!db || db.status === false) return resolve(data);
139
128
 
140
129
  if (method === "read") {
141
- // Emulating catalog query targeting active database context
142
130
  const sql = "PRAGMA database_list;";
143
131
  process.emit("usage", {
144
132
  type: "egress",
@@ -146,36 +134,37 @@ function database(method, data) {
146
134
  organization_id: data.organization_id
147
135
  });
148
136
 
149
- const res = await allQuery(db, sql);
137
+ const res = await db.execute(sql);
150
138
  process.emit("usage", {
151
139
  type: "ingress",
152
- data: res,
140
+ data: res.rows,
153
141
  organization_id: data.organization_id
154
142
  });
155
143
 
156
- for (let row of res) {
144
+ for (let row of res.rows) {
145
+ // libSQL ResultSet rows support standard property lookup
157
146
  const dbObj = { name: row.file ? row.file.split("/").pop() : "memory" };
158
147
  if (data.$filter && data.$filter.query) {
159
148
  let isFilter = queryData(dbObj, data.$filter.query);
160
149
  if (isFilter) {
161
150
  databaseArray.push({
162
151
  database: dbObj,
163
- storage: data.storageName
152
+ storage: storageName
164
153
  });
165
154
  }
166
155
  } else {
167
156
  databaseArray.push({
168
157
  database: dbObj,
169
- storage: data.storageName
158
+ storage: storageName
170
159
  });
171
160
  }
172
161
  }
173
162
  resolve(createData(data, databaseArray, type));
174
163
  }
175
164
  if (method === "delete") {
176
- // SQLite databases are typically filesystem files. We empty schema inside in-memory/file context safely
177
- const tables = await allQuery(db, "SELECT name FROM sqlite_master WHERE type='table';");
178
- for (let t of tables) {
165
+ // Drop all non-system tables inside the database context safely
166
+ const tables = await db.execute("SELECT name FROM sqlite_master WHERE type='table';");
167
+ for (let t of tables.rows) {
179
168
  if (!t.name.startsWith("sqlite_")) {
180
169
  const sql = `DROP TABLE IF EXISTS "${t.name}";`;
181
170
  process.emit("usage", {
@@ -183,7 +172,7 @@ function database(method, data) {
183
172
  data: { sql },
184
173
  organization_id: data.organization_id
185
174
  });
186
- await runQuery(db, sql);
175
+ await db.execute(sql);
187
176
  }
188
177
  }
189
178
  resolve({ status: true });
@@ -204,6 +193,7 @@ function database(method, data) {
204
193
  * "array" operations mapped to SQL Tables.
205
194
  */
206
195
  function array(method, data) {
196
+ const storageName = data.storageName || data.provider || "sqlite";
207
197
  return new Promise(
208
198
  async (resolve, reject) => {
209
199
  let type = "array";
@@ -211,7 +201,7 @@ function array(method, data) {
211
201
 
212
202
  try {
213
203
  const db = await dbClient(data);
214
- if (!db || db.status === false) return data;
204
+ if (!db || db.status === false) return resolve(data);
215
205
 
216
206
  if (data.request) data.array = data.request;
217
207
 
@@ -228,14 +218,14 @@ function array(method, data) {
228
218
  organization_id: data.organization_id
229
219
  });
230
220
 
231
- const res = await allQuery(db, sql);
221
+ const res = await db.execute(sql);
232
222
  process.emit("usage", {
233
223
  type: "ingress",
234
- data: res,
224
+ data: res.rows,
235
225
  organization_id: data.organization_id
236
226
  });
237
227
 
238
- for (let row of res) {
228
+ for (let row of res.rows) {
239
229
  const tableObj = { name: row.name };
240
230
  if (data.$filter && data.$filter.query) {
241
231
  let isFilter = queryData(tableObj, data.$filter.query);
@@ -243,14 +233,14 @@ function array(method, data) {
243
233
  arrayArray.push({
244
234
  name: row.name,
245
235
  database,
246
- storage: data.storageName
236
+ storage: storageName
247
237
  });
248
238
  }
249
239
  } else {
250
240
  arrayArray.push({
251
241
  name: row.name,
252
242
  database,
253
- storage: data.storageName
243
+ storage: storageName
254
244
  });
255
245
  }
256
246
  }
@@ -283,11 +273,11 @@ function array(method, data) {
283
273
  organization_id: data.organization_id
284
274
  });
285
275
 
286
- await runQuery(db, sql);
276
+ await db.execute(sql);
287
277
  arrayArray.push({
288
278
  name: array,
289
279
  database,
290
- storage: data.storageName
280
+ storage: storageName
291
281
  });
292
282
 
293
283
  arraysLength -= 1;
@@ -306,12 +296,12 @@ function array(method, data) {
306
296
  organization_id: data.organization_id
307
297
  });
308
298
 
309
- await runQuery(db, sql);
299
+ await db.execute(sql);
310
300
  arrayArray.push({
311
301
  name: newName,
312
302
  oldName: oldName,
313
303
  database,
314
- storage: data.storageName
304
+ storage: storageName
315
305
  });
316
306
 
317
307
  arraysLength -= 1;
@@ -330,11 +320,11 @@ function array(method, data) {
330
320
  organization_id: data.organization_id
331
321
  });
332
322
 
333
- await runQuery(db, sql);
323
+ await db.execute(sql);
334
324
  arrayArray.push({
335
325
  name: array,
336
326
  database,
337
- storage: data.storageName
327
+ storage: storageName
338
328
  });
339
329
 
340
330
  arraysLength -= 1;
@@ -364,11 +354,12 @@ function array(method, data) {
364
354
  * "object" operations mapped to SQL Rows.
365
355
  */
366
356
  function object(method, data) {
357
+ const storageName = data.storageName || data.provider || "sqlite";
367
358
  return new Promise(
368
359
  async (resolve, reject) => {
369
360
  try {
370
361
  const db = await dbClient(data);
371
- if (!db || db.status === false) return data;
362
+ if (!db || db.status === false) return resolve(data);
372
363
 
373
364
  let type = "object";
374
365
  let documents = [];
@@ -386,7 +377,7 @@ function object(method, data) {
386
377
 
387
378
  for (let array of arrays) {
388
379
  const reference = {
389
- $storage: data.storageName,
380
+ $storage: storageName,
390
381
  $database: database,
391
382
  $array: array
392
383
  };
@@ -411,7 +402,7 @@ function object(method, data) {
411
402
  if (!Array.isArray($database)) $database = [data[type][i].$database];
412
403
  if (!Array.isArray($array)) $array = [data[type][i].$array];
413
404
 
414
- if (!$storage.includes(data.storageName)) $storage.push(data.storageName);
405
+ if (!$storage.includes(storageName)) $storage.push(storageName);
415
406
  if (!$database.includes(database)) $database.push(database);
416
407
  if (!$array.includes(array)) $array.push(array);
417
408
 
@@ -449,11 +440,14 @@ function object(method, data) {
449
440
  organization_id: data.organization_id
450
441
  });
451
442
 
452
- await runQuery(db, sql, queryParams);
443
+ await db.execute({ sql, args: queryParams });
453
444
 
454
- const createdDoc = await getQuery(db, `SELECT * FROM "${array}" WHERE _id = ? AND organization_id = ?`, [id, orgId]);
455
- if (createdDoc) {
456
- const formattedDoc = parseSqlRow(createdDoc);
445
+ const createdDoc = await db.execute({
446
+ sql: `SELECT * FROM "${array}" WHERE _id = ? AND organization_id = ?`,
447
+ args: [id, orgId]
448
+ });
449
+ if (createdDoc.rows.length > 0) {
450
+ const formattedDoc = parseSqlRow(createdDoc.rows[0]);
457
451
  data[type][i] = { ...formattedDoc, $storage, $database, $array };
458
452
  }
459
453
  }
@@ -488,15 +482,15 @@ function object(method, data) {
488
482
  organization_id: data.organization_id
489
483
  });
490
484
 
491
- const rows = await allQuery(db, sql, params);
485
+ const result = await db.execute({ sql, args: params });
492
486
  process.emit("usage", {
493
487
  type: "ingress",
494
- data: rows,
488
+ data: result.rows,
495
489
  organization_id: data.organization_id
496
490
  });
497
491
 
498
492
  if (isFilter) {
499
- for (let row of rows) {
493
+ for (let row of result.rows) {
500
494
  const parsedRow = parseSqlRow(row);
501
495
  if (data.$filter && data.$filter.search) {
502
496
  let isMatch = searchData(parsedRow, data.$filter.search);
@@ -507,8 +501,8 @@ function object(method, data) {
507
501
  ...reference
508
502
  });
509
503
  }
510
- } else if (rows.length > 0) {
511
- let dbRecord = parseSqlRow(rows[0]);
504
+ } else if (result.rows.length > 0) {
505
+ let dbRecord = parseSqlRow(result.rows[0]);
512
506
 
513
507
  if ($storage.length && data[type][i].modified && data[type][i].modified.on) {
514
508
  let clientTime = new Date(data[type][i].modified.on);
@@ -550,9 +544,9 @@ function object(method, data) {
550
544
  data: { selectSql, params },
551
545
  organization_id: data.organization_id
552
546
  });
553
- const selectRows = await allQuery(db, selectSql, params);
547
+ const selectResult = await db.execute({ sql: selectSql, args: params });
554
548
 
555
- for (let row of selectRows) {
549
+ for (let row of selectResult.rows) {
556
550
  const updatedDoc = await executeUpdateTransaction(db, array, row._id, updatePayload, data);
557
551
  if (updatedDoc) {
558
552
  documents.push({ ...updatedDoc, ...reference });
@@ -576,7 +570,7 @@ function object(method, data) {
576
570
  data: { sql, queryParams },
577
571
  organization_id: data.organization_id
578
572
  });
579
- const runResult = await runQuery(db, sql, queryParams);
573
+ const runResult = await db.execute({ sql, args: queryParams });
580
574
  process.emit("usage", {
581
575
  type: "ingress",
582
576
  data: runResult,
@@ -584,7 +578,6 @@ function object(method, data) {
584
578
  });
585
579
 
586
580
  if (isFilter) {
587
- // Return deleted references
588
581
  documents.push({ _id: data[type][i]._id, ...reference });
589
582
  } else {
590
583
  data[type][i] = { _id: data[type][i]._id, $storage, $database, $array };
@@ -610,22 +603,23 @@ function object(method, data) {
610
603
  }
611
604
 
612
605
  /**
613
- * Safe transaction helper to update unstructured payloads with MongoDB behavior inside SQLite.
606
+ * Safe transaction helper to update unstructured payloads with MongoDB behavior inside libSQL.
614
607
  */
615
608
  async function executeUpdateTransaction(db, arrayName, docId, rawUpdateInput, requestData) {
616
609
  try {
617
- // SQLite is single-write bound, using IMMEDIATE locks database cleanly
618
- await runQuery(db, "BEGIN IMMEDIATE TRANSACTION;");
619
-
620
610
  const selectSql = `SELECT * FROM "${arrayName}" WHERE _id = ? AND organization_id = ?;`;
621
- const currentRecordRaw = await getQuery(db, selectSql, [docId, requestData.organization_id]);
622
- let currentRecord = currentRecordRaw ? parseSqlRow(currentRecordRaw) : null;
611
+
612
+ // Run isolation transaction
613
+ const tx = await db.transaction("deferred");
614
+
615
+ const currentRecordRaw = await tx.execute({ sql: selectSql, args: [docId, requestData.organization_id] });
616
+ let currentRecord = currentRecordRaw.rows.length > 0 ? parseSqlRow(currentRecordRaw.rows[0]) : null;
623
617
 
624
618
  if (!currentRecord) {
625
619
  if (requestData.upsert || rawUpdateInput.upsert || rawUpdateInput.$upsert) {
626
620
  currentRecord = { _id: docId, organization_id: requestData.organization_id };
627
621
  } else {
628
- await runQuery(db, "ROLLBACK;");
622
+ await tx.rollback();
629
623
  return null;
630
624
  }
631
625
  }
@@ -657,13 +651,12 @@ async function executeUpdateTransaction(db, arrayName, docId, rawUpdateInput, re
657
651
  organization_id: requestData.organization_id
658
652
  });
659
653
 
660
- await runQuery(db, updateSql, updateParams);
661
- await runQuery(db, "COMMIT;");
654
+ await tx.execute({ sql: updateSql, args: updateParams });
655
+ await tx.commit();
662
656
 
663
- const finalRecordRaw = await getQuery(db, selectSql, [docId, requestData.organization_id]);
664
- return parseSqlRow(finalRecordRaw);
657
+ const finalRecordRaw = await db.execute({ sql: selectSql, args: [docId, requestData.organization_id] });
658
+ return parseSqlRow(finalRecordRaw.rows[0]);
665
659
  } catch (error) {
666
- await runQuery(db, "ROLLBACK;");
667
660
  throw error;
668
661
  }
669
662
  }
@@ -922,4 +915,4 @@ function errorHandler(data, error, database, array) {
922
915
  }
923
916
  }
924
917
 
925
- module.exports = { send };
918
+ export default { send };