workers-qb 1.9.0 → 1.10.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.
package/README.md CHANGED
@@ -1,44 +1,69 @@
1
- # workers-qb
1
+ <div align="center">
2
+ <h1>workers-qb</h1>
3
+ <p><em>Zero-dependency Query Builder for Cloudflare Workers</em></p>
2
4
 
3
- ### [Read the documentation here!](https://workers-qb.massadas.com/)
5
+ <p>
6
+ <a href="https://workers-qb.massadas.com/" target="_blank">
7
+ <img src="https://img.shields.io/badge/docs-workers--qb-blue.svg" alt="Documentation">
8
+ </a>
9
+ <a href="https://www.npmjs.com/package/workers-qb" target="_blank">
10
+ <img src="https://img.shields.io/npm/v/workers-qb.svg" alt="npm version">
11
+ </a>
12
+ <a href="https://github.com/G4brym/workers-qb/blob/main/LICENSE" target="_blank">
13
+ <img src="https://img.shields.io/badge/license-MIT-brightgreen.svg" alt="Software License">
14
+ </a>
15
+ </p>
16
+ </div>
4
17
 
5
- Zero dependencies Query Builder for [Cloudflare Workers](https://developers.cloudflare.com/workers/)
18
+ ## Overview
6
19
 
7
- This module provides a simple standardized interface while keeping the benefits and speed of using raw queries over a
8
- traditional ORM.
20
+ workers-qb is a lightweight query builder designed specifically for Cloudflare Workers. It provides a simple, standardized interface while maintaining the performance benefits of raw queries over traditional ORMs.
9
21
 
10
- `workers-qb` is not intended to provide ORM-like functionality, rather to make it easier to interact with the database
11
- from code for direct SQL access using convenient wrapper methods.
22
+ 📚 [Read the full documentation](https://workers-qb.massadas.com/)
12
23
 
13
- Currently, 3 databases are supported:
24
+ ### Key Differences from ORMs
14
25
 
15
- - [Cloudflare D1](https://workers-qb.massadas.com/databases/cloudflare-d1/)
16
- - [Cloudflare Durable Objects](https://workers-qb.massadas.com/databases/cloudflare-do/)
17
- - [PostgreSQL (using node-postgres)](https://workers-qb.massadas.com/databases/postgresql/)
18
- - [Bring your own Database](https://workers-qb.massadas.com/databases/bring-your-own-database/)
26
+ - Focused on direct SQL access with convenient wrapper methods
27
+ - Maintains raw query performance
28
+ - Zero dependencies
29
+ - Lightweight and Worker-optimized
30
+
31
+ ## Supported Databases
32
+
33
+ - ☁️ [Cloudflare D1](https://workers-qb.massadas.com/databases/cloudflare-d1/)
34
+ - 💾 [Cloudflare Durable Objects](https://workers-qb.massadas.com/databases/cloudflare-do/)
35
+ - 🐘 [PostgreSQL (via node-postgres)](https://workers-qb.massadas.com/databases/postgresql/)
36
+ - 🔌 [Bring Your Own Database](https://workers-qb.massadas.com/databases/bring-your-own-database/)
19
37
 
20
38
  ## Features
21
39
 
22
- - [x] Zero dependencies
23
- - [x] Fully typed/TypeScript support
24
- - [x] [Migrations](https://workers-qb.massadas.com/migrations/)
25
- - [x] [Type Checks for data read](https://workers-qb.massadas.com/type-check/)
26
- - [x] [Create/drop tables](https://workers-qb.massadas.com/basic-queries/#dropping-and-creating-tables)
27
- - [x] [Insert/Bulk Inserts/Update/Select/Delete/Join queries](https://workers-qb.massadas.com/basic-queries/)
28
- - [x] [Modular selects](https://workers-qb.massadas.com/modular-selects/) (qb.select(...).where(...).where(...).one())
29
- - [x] [On Conflict for Inserts and Updates](https://workers-qb.massadas.com/advanced-queries/onConflict/)
30
- - [x] [Upsert](https://workers-qb.massadas.com/advanced-queries/upsert/)
31
- - [x] Lazy Load Rows
40
+ ### Core Features
41
+ - Zero dependencies
42
+ - Full TypeScript support
43
+ - Database schema migrations
44
+ - Type checking for data reads
45
+ - Lazy row loading
46
+
47
+ ### Query Operations
48
+ - Table operations (create/drop)
49
+ - CRUD operations (insert/update/select/delete)
50
+ - Bulk inserts
51
+ - JOIN queries
52
+ - Modular SELECT queries
53
+ - ON CONFLICT handling
54
+ - UPSERT support
32
55
 
33
56
  ## Installation
34
57
 
35
- ```
58
+ ```bash
36
59
  npm install workers-qb --save
37
60
  ```
38
61
 
39
- ## Example for Cloudflare Workers D1
62
+ ## Usage Examples
63
+
64
+ ### Cloudflare D1
40
65
 
41
- ```ts
66
+ ```typescript
42
67
  import { D1QB } from 'workers-qb'
43
68
 
44
69
  export interface Env {
@@ -55,7 +80,7 @@ export default {
55
80
  level: number
56
81
  }
57
82
 
58
- // Generated query: SELECT * FROM employees WHERE active = ?1
83
+ // Using object syntax
59
84
  const employeeList = await qb
60
85
  .fetchAll<Employee>({
61
86
  tableName: 'employees',
@@ -66,11 +91,11 @@ export default {
66
91
  })
67
92
  .execute()
68
93
 
69
- // Or in a modular approach
70
- const employeeListModular = await qb.select<Employee>('employees').where('active = ?', true).execute()
71
-
72
- // You get IDE type hints on each employee data, like:
73
- // employeeList.results[0].name
94
+ // Using method chaining
95
+ const employeeListModular = await qb
96
+ .select<Employee>('employees')
97
+ .where('active = ?', true)
98
+ .execute()
74
99
 
75
100
  return Response.json({
76
101
  activeEmployees: employeeList.results?.length || 0,
@@ -79,41 +104,39 @@ export default {
79
104
  }
80
105
  ```
81
106
 
82
- ## Example for Cloudflare Durable Objects
107
+ ### Cloudflare Durable Objects
83
108
 
84
- ```ts
109
+ ```typescript
85
110
  import { DOQB } from 'workers-qb'
86
111
 
87
112
  export class DOSRS extends DurableObject {
88
113
  getEmployees() {
89
114
  const qb = new DOQB(this.ctx.storage.sql)
90
-
91
- const fetched = qb
115
+
116
+ return qb
92
117
  .fetchAll({
93
118
  tableName: 'employees',
94
119
  })
95
120
  .execute()
96
-
97
- return fetched.results
121
+ .results
98
122
  }
99
123
  }
100
124
  ```
101
125
 
102
- ## Example for Cloudflare Workers with PostgreSQL
103
-
104
- Remember to close the connection using `ctx.waitUntil(qb.close());` or `await qb.close();` at the end of your request.
105
- You may also reuse this connection to execute multiple queries, or share it between multiple requests if you are using
106
- a connection pool in front of your PostgreSQL.
107
-
108
- You must also enable `node_compat = true` in your `wrangler.toml`
109
-
110
- You need to install `node-postgres`:
126
+ ### PostgreSQL Integration
111
127
 
128
+ First, install the required PostgreSQL client:
112
129
  ```bash
113
130
  npm install pg --save
114
131
  ```
115
132
 
116
- ```ts
133
+ Enable Node compatibility in `wrangler.toml`:
134
+ ```toml
135
+ node_compat = true
136
+ ```
137
+
138
+ Example usage:
139
+ ```typescript
117
140
  import { PGQB } from 'workers-qb'
118
141
  import { Client } from 'pg'
119
142
 
@@ -126,7 +149,6 @@ export default {
126
149
  const qb = new PGQB(new Client(env.DB_URL))
127
150
  await qb.connect()
128
151
 
129
- // Generated query: SELECT count(*) as count FROM employees WHERE active = ?1 LIMIT 1
130
152
  const fetched = await qb
131
153
  .fetchOne({
132
154
  tableName: 'employees',
@@ -138,10 +160,30 @@ export default {
138
160
  })
139
161
  .execute()
140
162
 
163
+ // Important: Close the connection
141
164
  ctx.waitUntil(qb.close())
165
+
142
166
  return Response.json({
143
167
  activeEmployees: fetched.results?.count || 0,
144
168
  })
145
169
  },
146
170
  }
147
171
  ```
172
+
173
+ ## Documentation
174
+
175
+ Visit our [comprehensive documentation](https://workers-qb.massadas.com/) for detailed information about:
176
+
177
+ - [Basic Queries](https://workers-qb.massadas.com/basic-queries/)
178
+ - [Advanced Queries](https://workers-qb.massadas.com/advanced-queries/)
179
+ - [Migrations](https://workers-qb.massadas.com/migrations/)
180
+ - [Type Checking](https://workers-qb.massadas.com/type-check/)
181
+ - [Database-specific guides](https://workers-qb.massadas.com/databases/)
182
+
183
+ ## Contributing
184
+
185
+ Contributions are welcome! Please feel free to submit a Pull Request.
186
+
187
+ ## License
188
+
189
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/dist/index.js CHANGED
@@ -546,6 +546,11 @@ var QueryBuilder = class {
546
546
  }
547
547
  _update(params) {
548
548
  const whereParamsLength = typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? Object.keys(params.where?.params).length : 1 : 0;
549
+ let whereString = this._where(params.where);
550
+ let parameterIndex = 1;
551
+ if (whereString && whereString.match(/(?<!\d)\?(?!\d)/)) {
552
+ whereString = whereString.replace(/\?/g, () => `?${parameterIndex++}`);
553
+ }
549
554
  const set = [];
550
555
  let index = 1;
551
556
  for (const [key, value] of Object.entries(params.data)) {
@@ -557,7 +562,7 @@ var QueryBuilder = class {
557
562
  }
558
563
  }
559
564
  return `UPDATE ${this._onConflict(params.onConflict)}${params.tableName}
560
- SET ${set.join(", ")}` + this._where(params.where) + this._returning(params.returning);
565
+ SET ${set.join(", ")}` + whereString + this._returning(params.returning);
561
566
  }
562
567
  _delete(params) {
563
568
  return `DELETE
package/dist/index.mjs CHANGED
@@ -504,6 +504,11 @@ var QueryBuilder = class {
504
504
  }
505
505
  _update(params) {
506
506
  const whereParamsLength = typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? Object.keys(params.where?.params).length : 1 : 0;
507
+ let whereString = this._where(params.where);
508
+ let parameterIndex = 1;
509
+ if (whereString && whereString.match(/(?<!\d)\?(?!\d)/)) {
510
+ whereString = whereString.replace(/\?/g, () => `?${parameterIndex++}`);
511
+ }
507
512
  const set = [];
508
513
  let index = 1;
509
514
  for (const [key, value] of Object.entries(params.data)) {
@@ -515,7 +520,7 @@ var QueryBuilder = class {
515
520
  }
516
521
  }
517
522
  return `UPDATE ${this._onConflict(params.onConflict)}${params.tableName}
518
- SET ${set.join(", ")}` + this._where(params.where) + this._returning(params.returning);
523
+ SET ${set.join(", ")}` + whereString + this._returning(params.returning);
519
524
  }
520
525
  _delete(params) {
521
526
  return `DELETE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workers-qb",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Zero dependencies Query Builder for Cloudflare Workers",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",