@vanit-co/sql-ts 0.0.2 → 0.3.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 +48 -17
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Writing raw SQL in TypeScript runs into a set of recurring friction points that
|
|
|
10
10
|
|
|
11
11
|
- **Automatic identifier quoting** — table and column names are interpolated as properly quoted identifiers (`` `name` `` for MySQL, `"name"` for PostgreSQL), never as bind parameters. No manual quoting, no dialect-specific escaping scattered across your codebase.
|
|
12
12
|
|
|
13
|
-
- **Table alias and qualified column references** — the `select` tag (and its aliases `join`, `where`) automatically expands schema tables as `"table" "alias"` and columns as `"alias"."column"`, so JOIN-heavy queries stay unambiguous without hand-writing every qualified reference.
|
|
13
|
+
- **Table alias and qualified column references** — the `select` tag (and its aliases `groupBy`, `having`, `join`, `orderBy`, `where`) automatically expands schema tables as `"table" "alias"` and columns as `"alias"."column"`, so JOIN-heavy queries stay unambiguous without hand-writing every qualified reference.
|
|
14
14
|
|
|
15
15
|
- **Column alias expansion** — `selectAs` goes further, rendering each column as `"alias"."column" as "alias_column"`. When querying multiple joined tables, result-set keys no longer collide.
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ npm install @vanit-co/sql-ts
|
|
|
26
26
|
|
|
27
27
|
## Quick example
|
|
28
28
|
|
|
29
|
-
**sql**
|
|
29
|
+
**sql** tag takes care of quoting the identifiers (tables and columns) with the proper quotes `` ` `` for MySQL and `"` for PostgreSQL.
|
|
30
30
|
|
|
31
31
|
```ts
|
|
32
32
|
import { schema, sql, all } from '@vanit-co/sql-ts'
|
|
@@ -46,7 +46,7 @@ console.log(query.values) // [42]
|
|
|
46
46
|
|
|
47
47
|
## Full query example
|
|
48
48
|
|
|
49
|
-
**select**
|
|
49
|
+
**select** tag works like **sql** but automatically adds table aliases and column prefixes. The other tags **groupBy**, **having**, **join**, **orderBy** and **where** are just aliases to **select** with the aim of maintaining semantics. The **selectAs** tag besides the column prefixes will also add the column alias using the format `$prefix_$columnName`.
|
|
50
50
|
|
|
51
51
|
```ts
|
|
52
52
|
import { schema, select, selectAs, join, where, all, insert, update, empty } from '@vanit-co/sql-ts'
|
|
@@ -74,9 +74,9 @@ ins.text // insert into "users" ("id" ,"email") values ($1 ,$2)
|
|
|
74
74
|
ins.values // [1, 'alice@example.com']
|
|
75
75
|
|
|
76
76
|
// UPDATE
|
|
77
|
-
const upd = update(users, { email: 'new@example.com' })
|
|
78
|
-
upd.text // update "users" set "email" = $1
|
|
79
|
-
upd.values // ['new@example.com']
|
|
77
|
+
const upd = update(users, { email: 'new@example.com' }).append(sql` where ${users.id} = ${id}`)
|
|
78
|
+
upd.text // update "users" set "email" = $1 where "id" = $2
|
|
79
|
+
upd.values // ['new@example.com', 42]
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
---
|
|
@@ -197,20 +197,23 @@ selectAs`SELECT ${users.email}`.text // SELECT "users"."email" as "users_email"
|
|
|
197
197
|
sa`SELECT ${u.email}`.text // SELECT "u"."email" as "u_email"
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
### `join` (alias: `j`) and `where` (alias: `w`)
|
|
200
|
+
### `groupBy` (alias: `g`), `having` (alias: `h`), `join` (alias: `j`), `orderBy` (alias: `o`) and `where` (alias: `w`)
|
|
201
201
|
|
|
202
|
-
These are identical to `select`. They exist as semantic aliases so your query construction reads naturally.
|
|
202
|
+
These are all identical to `select`. They exist as semantic aliases so your query construction reads naturally — each tag signals which SQL clause it belongs to.
|
|
203
203
|
|
|
204
204
|
```ts
|
|
205
|
-
import { select, join, j, where, w, schema } from '@vanit-co/sql-ts'
|
|
205
|
+
import { select, join, j, where, w, groupBy, g, having, h, orderBy, o, schema } from '@vanit-co/sql-ts'
|
|
206
206
|
|
|
207
207
|
const posts = schema({ table: 'posts', columns: ['id', 'user_id', 'title'] })
|
|
208
208
|
const users = schema({ table: 'users', columns: ['id', 'email'] })
|
|
209
209
|
|
|
210
210
|
const q = select`SELECT ${posts.title}, ${users.email}`
|
|
211
|
-
const fromClause
|
|
212
|
-
const joinClause
|
|
213
|
-
const whereClause = where`WHERE ${users.id} = ${99}`
|
|
211
|
+
const fromClause = join` FROM ${posts}`
|
|
212
|
+
const joinClause = join` JOIN ${users} ON ${posts.user_id} = ${users.id}`
|
|
213
|
+
const whereClause = where` WHERE ${users.id} = ${99}`
|
|
214
|
+
const groupClause = groupBy` GROUP BY ${posts.title}`
|
|
215
|
+
const havingClause = having` HAVING COUNT(${posts.id}) > ${1}`
|
|
216
|
+
const orderClause = orderBy` ORDER BY ${posts.title}`
|
|
214
217
|
```
|
|
215
218
|
|
|
216
219
|
---
|
|
@@ -265,6 +268,34 @@ selectAs`SELECT ${pick(users.id, users.email)}`.text
|
|
|
265
268
|
// SELECT "users"."id" as "users_id" ,"users"."email" as "users_email"
|
|
266
269
|
```
|
|
267
270
|
|
|
271
|
+
### `as(column)`
|
|
272
|
+
|
|
273
|
+
Returns the aliased column name as a plain string — the same `prefix_name` string that `selectAs` writes into the SQL `AS` clause. Use this to read a column out of query results by its aliased key without repeating the string manually.
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
import { schema, as, selectAs, all } from '@vanit-co/sql-ts'
|
|
277
|
+
|
|
278
|
+
const users = schema({ table: 'users', columns: ['id', 'email'] })
|
|
279
|
+
const u = schema({ table: 'users', columns: ['id', 'email'], alias: 'u' })
|
|
280
|
+
|
|
281
|
+
as(users.id) // 'users_id'
|
|
282
|
+
as(users.email) // 'users_email'
|
|
283
|
+
|
|
284
|
+
as(u.id) // 'u_id'
|
|
285
|
+
as(u.email) // 'u_email'
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
This is particularly useful when mapping over result rows:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
const rows = await client.query(selectAs`SELECT ${all(users)} FROM ${users}`)
|
|
292
|
+
|
|
293
|
+
rows.map(row => ({
|
|
294
|
+
id: row[as(users.id)], // row['users_id']
|
|
295
|
+
email: row[as(users.email)], // row['users_email']
|
|
296
|
+
}))
|
|
297
|
+
```
|
|
298
|
+
|
|
268
299
|
---
|
|
269
300
|
|
|
270
301
|
## Statement builders: `insert` and `update`
|
|
@@ -354,7 +385,7 @@ const posts = schema({ table: 'posts', columns: ['id', 'user_id', 'title'], alia
|
|
|
354
385
|
|
|
355
386
|
const buildQuery = (userId: number) =>
|
|
356
387
|
pipe(
|
|
357
|
-
concat(join`
|
|
388
|
+
concat(join` JOIN ${users} ON ${posts.user_id} = ${users.id}`),
|
|
358
389
|
concat(where` WHERE ${users.id} = ${userId}`)
|
|
359
390
|
)(selectAs`SELECT ${all(users, posts)} FROM ${posts}`)
|
|
360
391
|
|
|
@@ -376,7 +407,7 @@ import { schema, selectAs, join, where, concat, all } from '@vanit-co/sql-ts'
|
|
|
376
407
|
|
|
377
408
|
const q = pipe(
|
|
378
409
|
selectAs`SELECT ${all(users, posts)} FROM ${posts}`,
|
|
379
|
-
concat(join`
|
|
410
|
+
concat(join` JOIN ${users} ON ${posts.user_id} = ${users.id}`),
|
|
380
411
|
concat(where` WHERE ${users.id} = ${42}`)
|
|
381
412
|
)
|
|
382
413
|
```
|
|
@@ -397,9 +428,9 @@ type Filters = { userId?: number; titleLike?: string }
|
|
|
397
428
|
const buildPostsQuery = ({ userId, titleLike }: Filters) => {
|
|
398
429
|
const clauses = [
|
|
399
430
|
select`SELECT ${all(users, posts)} FROM ${posts}`,
|
|
400
|
-
join`
|
|
401
|
-
userId
|
|
402
|
-
titleLike ? where`
|
|
431
|
+
join` JOIN ${users} ON ${posts.user_id} = ${users.id}`,
|
|
432
|
+
userId ? where` WHERE ${users.id} = ${userId}` : empty,
|
|
433
|
+
titleLike ? where` AND ${posts.title} LIKE ${titleLike}` : empty,
|
|
403
434
|
]
|
|
404
435
|
|
|
405
436
|
return reduce(
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ type Params<T extends string> = {
|
|
|
46
46
|
readonly alias?: string;
|
|
47
47
|
};
|
|
48
48
|
declare const schema: <T extends string>({ table, columns, alias }: Params<T>) => SchemaTable<T>;
|
|
49
|
+
declare const as: (col: { [K in symbol]: Column; }) => string;
|
|
49
50
|
|
|
50
51
|
declare const sql: (strings: TemplateStringsArray, ...binds: Array<any>) => Result;
|
|
51
52
|
declare const select: (strings: TemplateStringsArray, ...binds: Array<any>) => Result;
|
|
@@ -68,4 +69,4 @@ declare const pick: (...columns: Array<{
|
|
|
68
69
|
}>) => Value;
|
|
69
70
|
declare const raw: (content: string) => Value;
|
|
70
71
|
|
|
71
|
-
export { all, concat, empty, insert, join as j, join, pick, preparedStatementName, raw, select as s, selectAs as sa, schema, select, selectAs, sql, toMysql, toPostgres, update, where as w, where };
|
|
72
|
+
export { all, as, concat, empty, insert, join as j, join, pick, preparedStatementName, raw, select as s, selectAs as sa, schema, select, selectAs, sql, toMysql, toPostgres, update, where as w, where };
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,10 @@ const schema = ({ table, columns, alias }) => {
|
|
|
79
79
|
...makeColumns(resolvedAlias, columns)
|
|
80
80
|
};
|
|
81
81
|
};
|
|
82
|
+
const as = (col) => {
|
|
83
|
+
const c = col[SYM_COLUMN];
|
|
84
|
+
return c.prefix + '_' + c.name;
|
|
85
|
+
};
|
|
82
86
|
|
|
83
87
|
const identifier = (content) => ({ [SYM_IDENTIFIER]: true, content });
|
|
84
88
|
|
|
@@ -150,6 +154,7 @@ const raw = (content) => ({
|
|
|
150
154
|
});
|
|
151
155
|
|
|
152
156
|
exports.all = all;
|
|
157
|
+
exports.as = as;
|
|
153
158
|
exports.concat = concat;
|
|
154
159
|
exports.empty = empty;
|
|
155
160
|
exports.insert = insert;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanit-co/sql-ts",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "A TypeScript SQL query builder using tagged template literals. Write plain SQL with safe, automatic parameter binding and properly quoted identifiers. No DSL to learn, no magic, no ORM.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|