workers-qb 0.1.7 → 0.1.8
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 +78 -123
- package/dist/Builder.d.ts +9 -9
- package/dist/databases/d1.d.ts +13 -0
- package/dist/databases/pg.d.ts +16 -0
- package/dist/interfaces.d.ts +16 -4
- package/dist/workers-qb.d.ts +2 -1
- package/dist/workers-qb.js +1 -1
- package/dist/workers-qb.mjs +1 -1
- package/package.json +8 -6
- package/dist/Databases.d.ts +0 -12
package/README.md
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# workers-qb
|
|
2
2
|
|
|
3
|
-
Zero dependencies Query Builder for [Cloudflare
|
|
4
|
-
[Workers](https://developers.cloudflare.com/workers/)
|
|
3
|
+
Zero dependencies Query Builder for [Cloudflare Workers](https://developers.cloudflare.com/workers/)
|
|
5
4
|
|
|
6
|
-
This module provides a simple standardized interface while keeping the
|
|
7
|
-
|
|
5
|
+
This module provides a simple standardized interface while keeping the benefits and speed of using raw queries over a
|
|
6
|
+
traditional ORM.
|
|
8
7
|
|
|
9
|
-
`workers-qb` is not intended to provide ORM-like functionality, rather to make it easier to interact with the database
|
|
10
|
-
code for direct SQL access using convenient wrapper methods.
|
|
8
|
+
`workers-qb` is not intended to provide ORM-like functionality, rather to make it easier to interact with the database
|
|
9
|
+
from code for direct SQL access using convenient wrapper methods.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
Currently, 2 databases are supported:
|
|
12
|
+
|
|
13
|
+
- [Cloudflare D1](https://developers.cloudflare.com/d1/)
|
|
14
|
+
- [PostgreSQL (using node-postgres)](https://developers.cloudflare.com/workers/databases/connect-to-postgres/)
|
|
15
|
+
|
|
16
|
+
Read the documentation [workers-qb.massadas.com](https://workers-qb.massadas.com/)!
|
|
13
17
|
|
|
14
18
|
## Features
|
|
15
19
|
|
|
@@ -21,30 +25,86 @@ Read the documentation [Here](https://workers-qb.massadas.com/)!
|
|
|
21
25
|
- [x] Create/drop tables
|
|
22
26
|
- [x] Keep where conditions simple in code
|
|
23
27
|
- [x] Bulk insert
|
|
28
|
+
- [x] Workers D1 Support
|
|
29
|
+
- [x] Workers PostgreSQL Support
|
|
24
30
|
- [ ] Named parameters (waiting for full support in D1)
|
|
25
31
|
|
|
26
32
|
## Installation
|
|
27
33
|
|
|
28
34
|
```
|
|
29
|
-
npm install workers-qb
|
|
35
|
+
npm install workers-qb --save
|
|
30
36
|
```
|
|
31
37
|
|
|
32
|
-
##
|
|
38
|
+
## Example Cloudflare D1 Usage
|
|
33
39
|
|
|
34
40
|
```ts
|
|
35
41
|
import { D1QB } from 'workers-qb'
|
|
36
|
-
const qb = new D1QB(env.DB)
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
export interface Env {
|
|
44
|
+
DB: any
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
|
49
|
+
const qb = new D1QB(env.DB)
|
|
50
|
+
|
|
51
|
+
const fetched = await qb.fetchOne({
|
|
52
|
+
tableName: 'employees',
|
|
53
|
+
fields: 'count(*) as count',
|
|
54
|
+
where: {
|
|
55
|
+
conditions: 'active = ?1',
|
|
56
|
+
params: [true],
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return Response.json({
|
|
61
|
+
activeEmployees: fetched.results?.count || 0,
|
|
62
|
+
})
|
|
44
63
|
},
|
|
45
|
-
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Example Cloudflare Workers with PostgreSQL Usage
|
|
68
|
+
|
|
69
|
+
Remember to close the connection using `ctx.waitUntil(qb.close());` or `await qb.close();` at the end of your request.
|
|
70
|
+
You may also reuse this connection to execute multiple queries, or share it between multiple requests if you are using
|
|
71
|
+
a connection pool in front of your PostgreSQL.
|
|
46
72
|
|
|
47
|
-
|
|
73
|
+
You must also enable `node_compat = true` in your `wrangler.toml`
|
|
74
|
+
|
|
75
|
+
You need to install `node-postgres`:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm install pg --save
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
import { PGQB } from 'workers-qb'
|
|
83
|
+
|
|
84
|
+
export interface Env {
|
|
85
|
+
DB_URL: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default {
|
|
89
|
+
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
|
90
|
+
const qb = new PGQB(env.DB_URL)
|
|
91
|
+
await qb.connect()
|
|
92
|
+
|
|
93
|
+
const fetched = await qb.fetchOne({
|
|
94
|
+
tableName: 'employees',
|
|
95
|
+
fields: 'count(*) as count',
|
|
96
|
+
where: {
|
|
97
|
+
conditions: 'active = ?1',
|
|
98
|
+
params: [true],
|
|
99
|
+
},
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
ctx.waitUntil(qb.close())
|
|
103
|
+
return Response.json({
|
|
104
|
+
activeEmployees: fetched.results?.count || 0,
|
|
105
|
+
})
|
|
106
|
+
},
|
|
107
|
+
}
|
|
48
108
|
```
|
|
49
109
|
|
|
50
110
|
#### Fetching a single record
|
|
@@ -189,108 +249,3 @@ const dropped = await qb.dropTable({
|
|
|
189
249
|
tableName: 'testTable',
|
|
190
250
|
})
|
|
191
251
|
```
|
|
192
|
-
|
|
193
|
-
## Development
|
|
194
|
-
|
|
195
|
-
### Set up tools and environment
|
|
196
|
-
|
|
197
|
-
You need to have [Node.js](https://nodejs.org/en/download/) installed. Node includes npm as its default package manager.
|
|
198
|
-
|
|
199
|
-
Open the whole package folder with a good code editor, preferably [Visual Studio Code](https://code.visualstudio.com/download). Consider installing VS Code extensions [ES Lint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode).
|
|
200
|
-
|
|
201
|
-
In the VS Code top menu: **Terminal** -> **New Terminal**
|
|
202
|
-
|
|
203
|
-
### Install dependencies
|
|
204
|
-
|
|
205
|
-
Install dependencies with npm:
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
npm i
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Write your code
|
|
212
|
-
|
|
213
|
-
Write your code in **src** folder, and unit test in **test** folder.
|
|
214
|
-
|
|
215
|
-
The VS Code shortcuts for formatting of a code file are: <kbd>Shift</kbd> + <kbd>Alt</kbd> + <kbd>F</kbd> (Windows); <kbd>Shift</kbd> + <kbd>Option (Alt)</kbd> + <kbd>F</kbd> (MacOS); <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd> (Linux).
|
|
216
|
-
|
|
217
|
-
### Test
|
|
218
|
-
|
|
219
|
-
Test your code with Jest framework:
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
npm run test
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
**Note:** This project uses [husky](https://typicode.github.io/husky/), [pinst](https://github.com/typicode/pinst) and [commitlint](https://commitlint.js.org/) to automatically execute test and [lint commit message](https://www.conventionalcommits.org/) before every commit.
|
|
226
|
-
|
|
227
|
-
### Build
|
|
228
|
-
|
|
229
|
-
Build production (distribution) files in your **dist** folder:
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
npm run build
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
It generates CommonJS (in **dist/cjs** folder), ES Modules (in **dist/esm** folder), bundled and minified UMD (in **dist/umd** folder), as well as TypeScript declaration files (in **dist/types** folder).
|
|
236
|
-
|
|
237
|
-
### Try it before publishing
|
|
238
|
-
|
|
239
|
-
Run:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
npm link
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
[npm link](https://docs.npmjs.com/cli/v6/commands/npm-link) will create a symlink in the global folder, which may be **{prefix}/lib/node_modules/workers-qb** or **C:\Users\<username>\AppData\Roaming\npm\node_modules\workers-qb**.
|
|
246
|
-
|
|
247
|
-
Create an empty folder elsewhere, you don't even need to `npm init` (to generate **package.json**). Open the folder with VS Code, open a terminal and just run:
|
|
248
|
-
|
|
249
|
-
```bash
|
|
250
|
-
npm link workers-qb
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
This will create a symbolic link from globally-installed workers-qb to **node_modules/** of the current folder.
|
|
254
|
-
|
|
255
|
-
You can then create a, for example, **testsql.ts** file with the content:
|
|
256
|
-
|
|
257
|
-
```ts
|
|
258
|
-
import { D1QB } from 'workers-qb'
|
|
259
|
-
const qb = new D1QB(env.DB)
|
|
260
|
-
|
|
261
|
-
console.log('Creating table...')
|
|
262
|
-
const created = await qb.createTable({
|
|
263
|
-
tableName: 'testTable',
|
|
264
|
-
schema: `
|
|
265
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
266
|
-
name TEXT NOT NULL
|
|
267
|
-
`,
|
|
268
|
-
ifNotExists: true,
|
|
269
|
-
})
|
|
270
|
-
console.log(created)
|
|
271
|
-
|
|
272
|
-
console.log('Inserting rows...')
|
|
273
|
-
const inserted = await qb.insert({
|
|
274
|
-
tableName: 'testTable',
|
|
275
|
-
data: {
|
|
276
|
-
name: 'my name',
|
|
277
|
-
},
|
|
278
|
-
returning: '*',
|
|
279
|
-
})
|
|
280
|
-
console.log(inserted)
|
|
281
|
-
|
|
282
|
-
console.log('Selecting rows...')
|
|
283
|
-
const selected = await qb.fetchAll({
|
|
284
|
-
tableName: 'testTable',
|
|
285
|
-
fields: '*',
|
|
286
|
-
})
|
|
287
|
-
console.log(selected)
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
If you don't see any linting errors in VS Code, if you put your mouse cursor over `D1QB` and see its type, then it's all good.
|
|
291
|
-
|
|
292
|
-
Whenever you want to uninstall the globally-installed workers-qb and remove the symlink in the global folder, run:
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
npm uninstall workers-qb -g
|
|
296
|
-
```
|
package/dist/Builder.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Delete, Insert, Join,
|
|
1
|
+
import { Delete, Insert, Join, SelectAll, SelectOne, Update } from './interfaces';
|
|
2
2
|
import { ConflictTypes, FetchTypes, OrderTypes } from './enums';
|
|
3
3
|
import { Raw } from './tools';
|
|
4
|
-
export declare class QueryBuilder {
|
|
4
|
+
export declare class QueryBuilder<GenericResult, GenericResultOne> {
|
|
5
5
|
execute(params: {
|
|
6
6
|
query: string;
|
|
7
7
|
arguments?: (string | number | boolean | null | Raw)[];
|
|
@@ -11,16 +11,16 @@ export declare class QueryBuilder {
|
|
|
11
11
|
tableName: string;
|
|
12
12
|
schema: string;
|
|
13
13
|
ifNotExists?: boolean;
|
|
14
|
-
}): Promise<
|
|
14
|
+
}): Promise<GenericResult>;
|
|
15
15
|
dropTable(params: {
|
|
16
16
|
tableName: string;
|
|
17
17
|
ifExists?: boolean;
|
|
18
|
-
}): Promise<
|
|
19
|
-
fetchOne(params: SelectOne): Promise<
|
|
20
|
-
fetchAll(params: SelectAll): Promise<
|
|
21
|
-
insert(params: Insert): Promise<
|
|
22
|
-
update(params: Update): Promise<
|
|
23
|
-
delete(params: Delete): Promise<
|
|
18
|
+
}): Promise<GenericResult>;
|
|
19
|
+
fetchOne(params: SelectOne): Promise<GenericResultOne>;
|
|
20
|
+
fetchAll(params: SelectAll): Promise<GenericResult>;
|
|
21
|
+
insert(params: Insert): Promise<GenericResult>;
|
|
22
|
+
update(params: Update): Promise<GenericResult>;
|
|
23
|
+
delete(params: Delete): Promise<GenericResult>;
|
|
24
24
|
_parse_arguments(row: Record<string, string | boolean | number | null | Raw>): Array<any>;
|
|
25
25
|
_onConflict(resolution?: string | ConflictTypes): string;
|
|
26
26
|
_insert(params: Insert): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { QueryBuilder } from '../Builder';
|
|
2
|
+
import { FetchTypes } from '../enums';
|
|
3
|
+
import { Raw } from '../tools';
|
|
4
|
+
import { D1Result, D1ResultOne } from '../interfaces';
|
|
5
|
+
export declare class D1QB extends QueryBuilder<D1Result, D1ResultOne> {
|
|
6
|
+
private db;
|
|
7
|
+
constructor(db: any);
|
|
8
|
+
execute(params: {
|
|
9
|
+
query: string;
|
|
10
|
+
arguments?: (string | number | boolean | null | Raw)[];
|
|
11
|
+
fetchType?: FetchTypes;
|
|
12
|
+
}): Promise<any>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryBuilder } from '../Builder';
|
|
2
|
+
import { FetchTypes } from '../enums';
|
|
3
|
+
import { Raw } from '../tools';
|
|
4
|
+
import { PGResult, PGResultOne } from '../interfaces';
|
|
5
|
+
export declare class PGQB extends QueryBuilder<PGResult, PGResultOne> {
|
|
6
|
+
private dbUrl;
|
|
7
|
+
private client;
|
|
8
|
+
constructor(dbUrl: string);
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
execute(params: {
|
|
12
|
+
query: String;
|
|
13
|
+
arguments?: (string | number | boolean | null | Raw)[];
|
|
14
|
+
fetchType?: FetchTypes;
|
|
15
|
+
}): Promise<any>;
|
|
16
|
+
}
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -40,19 +40,31 @@ export interface Delete {
|
|
|
40
40
|
where: Where;
|
|
41
41
|
returning?: string | Array<string>;
|
|
42
42
|
}
|
|
43
|
-
export interface
|
|
43
|
+
export interface D1Result {
|
|
44
44
|
changes?: number;
|
|
45
45
|
duration: number;
|
|
46
|
-
lastRowId?: number;
|
|
46
|
+
lastRowId?: string | number;
|
|
47
47
|
results?: Array<Record<string, string | boolean | number | null>>;
|
|
48
48
|
served_by: string;
|
|
49
49
|
success: boolean;
|
|
50
50
|
}
|
|
51
|
-
export interface
|
|
51
|
+
export interface D1ResultOne {
|
|
52
52
|
changes?: number;
|
|
53
53
|
duration: number;
|
|
54
|
-
lastRowId?: number;
|
|
54
|
+
lastRowId?: string | number;
|
|
55
55
|
results?: Record<string, string | boolean | number | null>;
|
|
56
56
|
served_by: string;
|
|
57
57
|
success: boolean;
|
|
58
58
|
}
|
|
59
|
+
export interface PGResult {
|
|
60
|
+
command: string;
|
|
61
|
+
lastRowId?: string | number;
|
|
62
|
+
rowCount: number;
|
|
63
|
+
results?: Array<Record<string, string | boolean | number | null>>;
|
|
64
|
+
}
|
|
65
|
+
export interface PGResultOne {
|
|
66
|
+
command: string;
|
|
67
|
+
lastRowId?: string | number;
|
|
68
|
+
rowCount: number;
|
|
69
|
+
results?: Record<string, string | boolean | number | null>;
|
|
70
|
+
}
|
package/dist/workers-qb.d.ts
CHANGED
package/dist/workers-qb.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t,r,s;exports.OrderTypes=void 0,(e=exports.OrderTypes||(exports.OrderTypes={})).ASC="ASC",e.DESC="DESC",exports.FetchTypes=void 0,(t=exports.FetchTypes||(exports.FetchTypes={})).ONE="ONE",t.ALL="ALL",exports.ConflictTypes=void 0,(r=exports.ConflictTypes||(exports.ConflictTypes={})).ROLLBACK="ROLLBACK",r.ABORT="ABORT",r.FAIL="FAIL",r.IGNORE="IGNORE",r.REPLACE="REPLACE",exports.JoinTypes=void 0,(s=exports.JoinTypes||(exports.JoinTypes={})).INNER="INNER",s.LEFT="LEFT",s.CROSS="CROSS";class n{isRaw=!0;content;constructor(e){this.content=e}}class i{async execute(e){throw new Error("Execute method not implemented")}async createTable(e){return this.execute({query:`CREATE TABLE ${e.ifNotExists?"IF NOT EXISTS":""} ${e.tableName}\n (\n ${e.schema}\n )`})}async dropTable(e){return this.execute({query:`DROP TABLE ${e.ifExists?"IF EXISTS":""} ${e.tableName}`})}async fetchOne(e){const t=await this.execute({query:this._select({...e,limit:1}),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL});return{...t,results:t.results[0]}}async fetchAll(e){return this.execute({query:this._select(e),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL})}async insert(e){let t=[];if(Array.isArray(e.data))for(const r of e.data)t=t.concat(this._parse_arguments(r));else t=t.concat(this._parse_arguments(e.data));return this.execute({query:this._insert(e),arguments:t,fetchType:exports.FetchTypes.ALL})}async update(e){let t=this._parse_arguments(e.data);return e.where&&e.where.params&&(t=e.where.params.concat(t)),this.execute({query:this._update(e),arguments:t,fetchType:exports.FetchTypes.ALL})}async delete(e){return this.execute({query:this._delete(e),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL})}_parse_arguments(e){return Object.values(e).map((e=>e instanceof n?e.content:e))}_onConflict(e){return e?`OR ${e} `:""}_insert(e){const t=[];Array.isArray(e.data)||(e.data=[e.data]);const r=Object.keys(e.data[0]).join(", ");let s=1;for(const r of e.data){const e=[];Object.
|
|
1
|
+
"use strict";var e,t,r,s;exports.OrderTypes=void 0,(e=exports.OrderTypes||(exports.OrderTypes={})).ASC="ASC",e.DESC="DESC",exports.FetchTypes=void 0,(t=exports.FetchTypes||(exports.FetchTypes={})).ONE="ONE",t.ALL="ALL",exports.ConflictTypes=void 0,(r=exports.ConflictTypes||(exports.ConflictTypes={})).ROLLBACK="ROLLBACK",r.ABORT="ABORT",r.FAIL="FAIL",r.IGNORE="IGNORE",r.REPLACE="REPLACE",exports.JoinTypes=void 0,(s=exports.JoinTypes||(exports.JoinTypes={})).INNER="INNER",s.LEFT="LEFT",s.CROSS="CROSS";class n{isRaw=!0;content;constructor(e){this.content=e}}class i{async execute(e){throw new Error("Execute method not implemented")}async createTable(e){return this.execute({query:`CREATE TABLE ${e.ifNotExists?"IF NOT EXISTS":""} ${e.tableName}\n (\n ${e.schema}\n )`})}async dropTable(e){return this.execute({query:`DROP TABLE ${e.ifExists?"IF EXISTS":""} ${e.tableName}`})}async fetchOne(e){const t=await this.execute({query:this._select({...e,limit:1}),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL});return{...t,results:t.results.length>0?t.results[0]:null}}async fetchAll(e){return this.execute({query:this._select(e),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL})}async insert(e){let t=[];if(Array.isArray(e.data))for(const r of e.data)t=t.concat(this._parse_arguments(r));else t=t.concat(this._parse_arguments(e.data));return this.execute({query:this._insert(e),arguments:t,fetchType:exports.FetchTypes.ALL})}async update(e){let t=this._parse_arguments(e.data);return e.where&&e.where.params&&(t=e.where.params.concat(t)),this.execute({query:this._update(e),arguments:t,fetchType:exports.FetchTypes.ALL})}async delete(e){return this.execute({query:this._delete(e),arguments:e.where?e.where.params:void 0,fetchType:exports.FetchTypes.ALL})}_parse_arguments(e){return Object.values(e).map((e=>e instanceof n?e.content:e))}_onConflict(e){return e?`OR ${e} `:""}_insert(e){const t=[];Array.isArray(e.data)||(e.data=[e.data]);const r=Object.keys(e.data[0]).join(", ");let s=1;for(const r of e.data){const e=[];Object.values(r).forEach((t=>{t instanceof n?e.push(t.content):e.push(`?${s}`),s+=1})),t.push(`(${e.join(", ")})`)}return`INSERT ${this._onConflict(e.onConflict)}INTO ${e.tableName} (${r}) VALUES ${t.join(", ")}`+this._returning(e.returning)}_update(e){const t=e.where&&e.where.params?Object.keys(e.where.params).length:0,r=[];return Object.entries(e.data).forEach((([e,s],i)=>{s instanceof n?r.push(`${e} = ${s.content}`):r.push(`${e} = ?${t+i+1}`)})),`UPDATE ${this._onConflict(e.onConflict)}${e.tableName} SET ${r.join(", ")}`+this._where(e.where?.conditions)+this._returning(e.returning)}_delete(e){return`DELETE FROM ${e.tableName}`+this._where(e.where?.conditions)+this._returning(e.returning)}_select(e){return`SELECT ${this._fields(e.fields)} FROM ${e.tableName}`+this._join(e.join)+this._where(e.where?.conditions)+this._groupBy(e.groupBy)+this._having(e.having)+this._orderBy(e.orderBy)+this._limit(e.limit)+this._offset(e.offset)}_fields(e){return"string"==typeof e?e:e.join(", ")}_where(e){return e?"string"==typeof e?` WHERE ${e}`:` WHERE ${e.join(" AND ")}`:""}_join(e){if(!e)return"";Array.isArray(e)||(e=[e]);const t=[];return e.forEach((e=>{const r=e.type?`${e.type} `:"";t.push(`${r}JOIN ${e.table} ON ${e.on}`)}))," "+t.join(" ")}_groupBy(e){return e?"string"==typeof e?` GROUP BY ${e}`:` GROUP BY ${e.join(", ")}`:""}_having(e){return e?` HAVING ${e}`:""}_orderBy(e){if(!e)return"";if("string"==typeof e)return` ORDER BY ${e}`;if(Array.isArray(e))return` ORDER BY ${e.join(", ")}`;const t=[];return Object.entries(e).forEach((([e,r])=>{t.push(`${e} ${r}`)})),` ORDER BY ${t.join(", ")}`}_limit(e){return e?` LIMIT ${e}`:""}_offset(e){return e?` OFFSET ${e}`:""}_returning(e){return e?"string"==typeof e?` RETURNING ${e}`:` RETURNING ${e.join(", ")}`:""}}let o;try{o=require("pg")}catch(e){o=null}exports.D1QB=class extends i{db;constructor(e){super(),this.db=e}async execute(e){let t=this.db.prepare(e.query);if(e.arguments){const r=e.arguments.map((e=>e instanceof n?e.content:e));t=t.bind(...r)}return e.fetchType===exports.FetchTypes.ONE?t.first():e.fetchType===exports.FetchTypes.ALL?t.all():t.run()}},exports.PGQB=class extends i{dbUrl;client;constructor(e){if(null===o)throw new Error('You must have "pg" installed, in order to use PGQB!');super(),this.dbUrl=e,this.client=new o.Client(this.dbUrl)}async connect(){await this.client.connect()}async close(){await this.client.end()}async execute(e){const t=e.query.replaceAll("?","$");let r;if(e.arguments){const s=e.arguments.map((e=>e instanceof n?e.content:e));r=await this.client.query({values:s,text:t})}else r=await this.client.query({text:t});return e.fetchType===exports.FetchTypes.ONE||e.fetchType===exports.FetchTypes.ALL?{command:r.command,lastRowId:r.oid,rowCount:r.rowCount,results:r.rows}:null}},exports.QueryBuilder=i,exports.Raw=n;
|
package/dist/workers-qb.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t,r,n;!function(e){e.ASC="ASC",e.DESC="DESC"}(e||(e={})),function(e){e.ONE="ONE",e.ALL="ALL"}(t||(t={})),function(e){e.ROLLBACK="ROLLBACK",e.ABORT="ABORT",e.FAIL="FAIL",e.IGNORE="IGNORE",e.REPLACE="REPLACE"}(r||(r={})),function(e){e.INNER="INNER",e.LEFT="LEFT",e.CROSS="CROSS"}(n||(n={}));class s{isRaw=!0;content;constructor(e){this.content=e}}class i{async execute(e){throw new Error("Execute method not implemented")}async createTable(e){return this.execute({query:`CREATE TABLE ${e.ifNotExists?"IF NOT EXISTS":""} ${e.tableName}\n (\n ${e.schema}\n )`})}async dropTable(e){return this.execute({query:`DROP TABLE ${e.ifExists?"IF EXISTS":""} ${e.tableName}`})}async fetchOne(e){const r=await this.execute({query:this._select({...e,limit:1}),arguments:e.where?e.where.params:void 0,fetchType:t.ALL});return{...r,results:r.results[0]}}async fetchAll(e){return this.execute({query:this._select(e),arguments:e.where?e.where.params:void 0,fetchType:t.ALL})}async insert(e){let r=[];if(Array.isArray(e.data))for(const t of e.data)r=r.concat(this._parse_arguments(t));else r=r.concat(this._parse_arguments(e.data));return this.execute({query:this._insert(e),arguments:r,fetchType:t.ALL})}async update(e){let r=this._parse_arguments(e.data);return e.where&&e.where.params&&(r=e.where.params.concat(r)),this.execute({query:this._update(e),arguments:r,fetchType:t.ALL})}async delete(e){return this.execute({query:this._delete(e),arguments:e.where?e.where.params:void 0,fetchType:t.ALL})}_parse_arguments(e){return Object.values(e).map((e=>e instanceof s?e.content:e))}_onConflict(e){return e?`OR ${e} `:""}_insert(e){const t=[];Array.isArray(e.data)||(e.data=[e.data]);const r=Object.keys(e.data[0]).join(", ");let n=1;for(const r of e.data){const e=[];Object.
|
|
1
|
+
var e,t,r,n;!function(e){e.ASC="ASC",e.DESC="DESC"}(e||(e={})),function(e){e.ONE="ONE",e.ALL="ALL"}(t||(t={})),function(e){e.ROLLBACK="ROLLBACK",e.ABORT="ABORT",e.FAIL="FAIL",e.IGNORE="IGNORE",e.REPLACE="REPLACE"}(r||(r={})),function(e){e.INNER="INNER",e.LEFT="LEFT",e.CROSS="CROSS"}(n||(n={}));class s{isRaw=!0;content;constructor(e){this.content=e}}class i{async execute(e){throw new Error("Execute method not implemented")}async createTable(e){return this.execute({query:`CREATE TABLE ${e.ifNotExists?"IF NOT EXISTS":""} ${e.tableName}\n (\n ${e.schema}\n )`})}async dropTable(e){return this.execute({query:`DROP TABLE ${e.ifExists?"IF EXISTS":""} ${e.tableName}`})}async fetchOne(e){const r=await this.execute({query:this._select({...e,limit:1}),arguments:e.where?e.where.params:void 0,fetchType:t.ALL});return{...r,results:r.results.length>0?r.results[0]:null}}async fetchAll(e){return this.execute({query:this._select(e),arguments:e.where?e.where.params:void 0,fetchType:t.ALL})}async insert(e){let r=[];if(Array.isArray(e.data))for(const t of e.data)r=r.concat(this._parse_arguments(t));else r=r.concat(this._parse_arguments(e.data));return this.execute({query:this._insert(e),arguments:r,fetchType:t.ALL})}async update(e){let r=this._parse_arguments(e.data);return e.where&&e.where.params&&(r=e.where.params.concat(r)),this.execute({query:this._update(e),arguments:r,fetchType:t.ALL})}async delete(e){return this.execute({query:this._delete(e),arguments:e.where?e.where.params:void 0,fetchType:t.ALL})}_parse_arguments(e){return Object.values(e).map((e=>e instanceof s?e.content:e))}_onConflict(e){return e?`OR ${e} `:""}_insert(e){const t=[];Array.isArray(e.data)||(e.data=[e.data]);const r=Object.keys(e.data[0]).join(", ");let n=1;for(const r of e.data){const e=[];Object.values(r).forEach((t=>{t instanceof s?e.push(t.content):e.push(`?${n}`),n+=1})),t.push(`(${e.join(", ")})`)}return`INSERT ${this._onConflict(e.onConflict)}INTO ${e.tableName} (${r}) VALUES ${t.join(", ")}`+this._returning(e.returning)}_update(e){const t=e.where&&e.where.params?Object.keys(e.where.params).length:0,r=[];return Object.entries(e.data).forEach((([e,n],i)=>{n instanceof s?r.push(`${e} = ${n.content}`):r.push(`${e} = ?${t+i+1}`)})),`UPDATE ${this._onConflict(e.onConflict)}${e.tableName} SET ${r.join(", ")}`+this._where(e.where?.conditions)+this._returning(e.returning)}_delete(e){return`DELETE FROM ${e.tableName}`+this._where(e.where?.conditions)+this._returning(e.returning)}_select(e){return`SELECT ${this._fields(e.fields)} FROM ${e.tableName}`+this._join(e.join)+this._where(e.where?.conditions)+this._groupBy(e.groupBy)+this._having(e.having)+this._orderBy(e.orderBy)+this._limit(e.limit)+this._offset(e.offset)}_fields(e){return"string"==typeof e?e:e.join(", ")}_where(e){return e?"string"==typeof e?` WHERE ${e}`:` WHERE ${e.join(" AND ")}`:""}_join(e){if(!e)return"";Array.isArray(e)||(e=[e]);const t=[];return e.forEach((e=>{const r=e.type?`${e.type} `:"";t.push(`${r}JOIN ${e.table} ON ${e.on}`)}))," "+t.join(" ")}_groupBy(e){return e?"string"==typeof e?` GROUP BY ${e}`:` GROUP BY ${e.join(", ")}`:""}_having(e){return e?` HAVING ${e}`:""}_orderBy(e){if(!e)return"";if("string"==typeof e)return` ORDER BY ${e}`;if(Array.isArray(e))return` ORDER BY ${e.join(", ")}`;const t=[];return Object.entries(e).forEach((([e,r])=>{t.push(`${e} ${r}`)})),` ORDER BY ${t.join(", ")}`}_limit(e){return e?` LIMIT ${e}`:""}_offset(e){return e?` OFFSET ${e}`:""}_returning(e){return e?"string"==typeof e?` RETURNING ${e}`:` RETURNING ${e.join(", ")}`:""}}class a extends i{db;constructor(e){super(),this.db=e}async execute(e){let r=this.db.prepare(e.query);if(e.arguments){const t=e.arguments.map((e=>e instanceof s?e.content:e));r=r.bind(...t)}return e.fetchType===t.ONE?r.first():e.fetchType===t.ALL?r.all():r.run()}}let c;try{c=require("pg")}catch(e){c=null}class o extends i{dbUrl;client;constructor(e){if(null===c)throw new Error('You must have "pg" installed, in order to use PGQB!');super(),this.dbUrl=e,this.client=new c.Client(this.dbUrl)}async connect(){await this.client.connect()}async close(){await this.client.end()}async execute(e){const r=e.query.replaceAll("?","$");let n;if(e.arguments){const t=e.arguments.map((e=>e instanceof s?e.content:e));n=await this.client.query({values:t,text:r})}else n=await this.client.query({text:r});return e.fetchType===t.ONE||e.fetchType===t.ALL?{command:n.command,lastRowId:n.oid,rowCount:n.rowCount,results:n.rows}:null}}export{r as ConflictTypes,a as D1QB,t as FetchTypes,n as JoinTypes,e as OrderTypes,o as PGQB,i as QueryBuilder,s as Raw};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workers-qb",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Zero dependencies Query Builder for Cloudflare
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"description": "Zero dependencies Query Builder for Cloudflare Workers",
|
|
5
5
|
"main": "./dist/workers-qb.js",
|
|
6
6
|
"types": "./dist/workers-qb.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"prepublishOnly": "pinst --disable",
|
|
22
22
|
"postpublish": "pinst --enable",
|
|
23
23
|
"build": "rollup -c",
|
|
24
|
-
"clean": "node tools/cleanup",
|
|
25
24
|
"package": "npm run build && npm pack",
|
|
26
25
|
"test": "jest --no-cache --runInBand",
|
|
27
26
|
"test:cov": "jest --coverage --no-cache --runInBand",
|
|
@@ -69,6 +68,8 @@
|
|
|
69
68
|
"devDependencies": {
|
|
70
69
|
"@commitlint/cli": "^13.1.0",
|
|
71
70
|
"@commitlint/config-conventional": "^13.1.0",
|
|
71
|
+
"@rollup/plugin-terser": "^0.2.1",
|
|
72
|
+
"@rollup/plugin-typescript": "^10.0.1",
|
|
72
73
|
"@types/jest": "^27.0.1",
|
|
73
74
|
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
|
74
75
|
"@typescript-eslint/parser": "^4.31.1",
|
|
@@ -79,11 +80,12 @@
|
|
|
79
80
|
"jest": "^28.1.2",
|
|
80
81
|
"pinst": "^2.1.6",
|
|
81
82
|
"prettier": "^2.4.0",
|
|
82
|
-
"ts-jest": "^28.0.5",
|
|
83
|
-
"@rollup/plugin-terser": "^0.2.1",
|
|
84
|
-
"@rollup/plugin-typescript": "^10.0.1",
|
|
85
83
|
"rollup": "^3.8.1",
|
|
86
84
|
"rollup-plugin-bundle-size": "^1.0.3",
|
|
85
|
+
"ts-jest": "^28.0.5",
|
|
87
86
|
"typescript": "^4.8.4"
|
|
87
|
+
},
|
|
88
|
+
"optionalDependencies": {
|
|
89
|
+
"pg": "^8.11.0"
|
|
88
90
|
}
|
|
89
91
|
}
|
package/dist/Databases.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { QueryBuilder } from './Builder';
|
|
2
|
-
import { FetchTypes } from './enums';
|
|
3
|
-
import { Raw } from './tools';
|
|
4
|
-
export declare class D1QB extends QueryBuilder {
|
|
5
|
-
private db;
|
|
6
|
-
constructor(db: any);
|
|
7
|
-
execute(params: {
|
|
8
|
-
query: string;
|
|
9
|
-
arguments?: (string | number | boolean | null | Raw)[];
|
|
10
|
-
fetchType?: FetchTypes;
|
|
11
|
-
}): Promise<any>;
|
|
12
|
-
}
|