@remix-run/data-table 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +298 -2
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/adapter.d.ts +180 -0
- package/dist/lib/adapter.d.ts.map +1 -0
- package/dist/lib/adapter.js +1 -0
- package/dist/lib/database.d.ts +361 -0
- package/dist/lib/database.d.ts.map +1 -0
- package/dist/lib/database.js +1368 -0
- package/dist/lib/errors.d.ts +50 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +67 -0
- package/dist/lib/inflection.d.ts +3 -0
- package/dist/lib/inflection.d.ts.map +1 -0
- package/dist/lib/inflection.js +56 -0
- package/dist/lib/operators.d.ts +151 -0
- package/dist/lib/operators.d.ts.map +1 -0
- package/dist/lib/operators.js +218 -0
- package/dist/lib/references.d.ts +42 -0
- package/dist/lib/references.d.ts.map +1 -0
- package/dist/lib/references.js +33 -0
- package/dist/lib/sql.d.ts +28 -0
- package/dist/lib/sql.d.ts.map +1 -0
- package/dist/lib/sql.js +51 -0
- package/dist/lib/table.d.ts +254 -0
- package/dist/lib/table.d.ts.map +1 -0
- package/dist/lib/table.js +496 -0
- package/dist/lib/types.d.ts +4 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +1 -0
- package/package.json +41 -7
- package/src/index.ts +115 -0
- package/src/lib/adapter.ts +209 -0
- package/src/lib/database.ts +2458 -0
- package/src/lib/errors.ts +109 -0
- package/src/lib/inflection.ts +69 -0
- package/src/lib/operators.ts +433 -0
- package/src/lib/references.ts +79 -0
- package/src/lib/sql.ts +67 -0
- package/src/lib/table.ts +981 -0
- package/src/lib/types.ts +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shopify Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,299 @@
|
|
|
1
|
-
#
|
|
1
|
+
# data-table
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Typed relational query toolkit for JavaScript runtimes.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **One API Across Databases**: Same query and relation APIs across PostgreSQL, MySQL, and SQLite adapters
|
|
8
|
+
- **Two Complementary Query Styles**: Use the chainable query builder for advanced queries or high-level database helpers for common CRUD
|
|
9
|
+
- **Type-Safe Reads**: Typed `select`, relation loading, and predicate keys
|
|
10
|
+
- **Validated Writes and Filters**: Values are parsed with your `remix/data-schema` definitions
|
|
11
|
+
- **Relation-First Queries**: `hasMany`, `hasOne`, `belongsTo`, `hasManyThrough`, and nested eager loading
|
|
12
|
+
- **Safe Scoped Writes**: `update`/`delete` with `orderBy`/`limit` run safely in a transaction
|
|
13
|
+
- **Raw SQL Escape Hatch**: Execute SQL directly with `db.exec(sql\`...\`)`
|
|
14
|
+
|
|
15
|
+
`data-table` gives you two complementary APIs:
|
|
16
|
+
|
|
17
|
+
- [**Query Builder**](#query-builder) for expressive joins, aggregates, eager loading, and scoped writes
|
|
18
|
+
- [**CRUD Helpers**](#crud-helpers) for common create/read/update/delete flows (`find`, `create`, `update`, `delete`)
|
|
19
|
+
|
|
20
|
+
Both APIs are type-safe and validate values using your [remix/data-schema](https://github.com/remix-run/remix/tree/main/packages/data-schema) definitions.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm i remix
|
|
26
|
+
npm i pg
|
|
27
|
+
# or
|
|
28
|
+
npm i mysql2
|
|
29
|
+
# or
|
|
30
|
+
npm i better-sqlite3
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
Define tables once, then create a database with an adapter.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Pool } from 'pg'
|
|
39
|
+
import * as s from 'remix/data-schema'
|
|
40
|
+
import { createDatabase, createTable, hasMany } from 'remix/data-table'
|
|
41
|
+
import { createPostgresDatabaseAdapter } from 'remix/data-table-postgres'
|
|
42
|
+
|
|
43
|
+
let users = createTable({
|
|
44
|
+
name: 'users',
|
|
45
|
+
columns: {
|
|
46
|
+
id: s.string(),
|
|
47
|
+
email: s.string(),
|
|
48
|
+
role: s.enum_(['customer', 'admin']),
|
|
49
|
+
created_at: s.number(),
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
let orders = createTable({
|
|
54
|
+
name: 'orders',
|
|
55
|
+
columns: {
|
|
56
|
+
id: s.string(),
|
|
57
|
+
user_id: s.string(),
|
|
58
|
+
status: s.enum_(['pending', 'processing', 'shipped', 'delivered']),
|
|
59
|
+
total: s.number(),
|
|
60
|
+
created_at: s.number(),
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
let userOrders = hasMany(users, orders)
|
|
65
|
+
|
|
66
|
+
let pool = new Pool({ connectionString: process.env.DATABASE_URL })
|
|
67
|
+
let db = createDatabase(createPostgresDatabaseAdapter(pool))
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Query Builder
|
|
71
|
+
|
|
72
|
+
Use `db.query(table)` when you need joins, custom shape selection, eager loading, or aggregate logic.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { eq, ilike } from 'remix/data-table'
|
|
76
|
+
|
|
77
|
+
let recentPendingOrders = await db
|
|
78
|
+
.query(orders)
|
|
79
|
+
.join(users, eq(orders.user_id, users.id))
|
|
80
|
+
.where({ status: 'pending' })
|
|
81
|
+
.where(ilike(users.email, '%@example.com'))
|
|
82
|
+
.select({
|
|
83
|
+
orderId: orders.id,
|
|
84
|
+
customerEmail: users.email,
|
|
85
|
+
total: orders.total,
|
|
86
|
+
placedAt: orders.created_at,
|
|
87
|
+
})
|
|
88
|
+
.orderBy(orders.created_at, 'desc')
|
|
89
|
+
.limit(20)
|
|
90
|
+
.all()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Load relations with relation-scoped filtering and ordering:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
let customers = await db
|
|
97
|
+
.query(users)
|
|
98
|
+
.where({ role: 'customer' })
|
|
99
|
+
.with({
|
|
100
|
+
recentOrders: userOrders.where({ status: 'shipped' }).orderBy('created_at', 'desc').limit(3),
|
|
101
|
+
})
|
|
102
|
+
.all()
|
|
103
|
+
|
|
104
|
+
// customers[0].recentOrders is fully typed
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Run scoped writes safely with the same chainable API:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
await db
|
|
111
|
+
.query(orders)
|
|
112
|
+
.where({ status: 'pending' })
|
|
113
|
+
.orderBy('created_at', 'asc')
|
|
114
|
+
.limit(100)
|
|
115
|
+
.update({ status: 'processing' })
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## CRUD Helpers
|
|
119
|
+
|
|
120
|
+
`data-table` provides helpers for common create/read/update/delete operations. Use these helpers for common operations without building a full query chain.
|
|
121
|
+
|
|
122
|
+
### Read operations
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { or } from 'remix/data-table'
|
|
126
|
+
|
|
127
|
+
let user = await db.find(users, 'u_001')
|
|
128
|
+
|
|
129
|
+
let firstPending = await db.findOne(orders, {
|
|
130
|
+
where: { status: 'pending' },
|
|
131
|
+
orderBy: ['created_at', 'asc'],
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
let page = await db.findMany(orders, {
|
|
135
|
+
where: or({ status: 'pending' }, { status: 'processing' }),
|
|
136
|
+
orderBy: [
|
|
137
|
+
['status', 'asc'],
|
|
138
|
+
['created_at', 'desc'],
|
|
139
|
+
],
|
|
140
|
+
limit: 50,
|
|
141
|
+
offset: 0,
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`where` accepts the same single-table object/predicate inputs as `query().where(...)`, and `orderBy` uses tuple form:
|
|
146
|
+
|
|
147
|
+
- `['column', 'asc' | 'desc']`
|
|
148
|
+
- `[['columnA', 'asc'], ['columnB', 'desc']]`
|
|
149
|
+
|
|
150
|
+
### Create helpers
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// Default: metadata (affectedRows/insertId)
|
|
154
|
+
let createResult = await db.create(users, {
|
|
155
|
+
id: 'u_002',
|
|
156
|
+
email: 'sam@example.com',
|
|
157
|
+
role: 'customer',
|
|
158
|
+
created_at: Date.now(),
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Return a typed row (with optional relations)
|
|
162
|
+
let createdUser = await db.create(
|
|
163
|
+
users,
|
|
164
|
+
{
|
|
165
|
+
id: 'u_003',
|
|
166
|
+
email: 'pat@example.com',
|
|
167
|
+
role: 'customer',
|
|
168
|
+
created_at: Date.now(),
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
returnRow: true,
|
|
172
|
+
with: { recentOrders: userOrders.orderBy('created_at', 'desc').limit(1) },
|
|
173
|
+
},
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
// Bulk insert metadata
|
|
177
|
+
let createManyResult = await db.createMany(orders, [
|
|
178
|
+
{ id: 'o_101', user_id: 'u_002', status: 'pending', total: 24.99, created_at: Date.now() },
|
|
179
|
+
{ id: 'o_102', user_id: 'u_003', status: 'pending', total: 48.5, created_at: Date.now() },
|
|
180
|
+
])
|
|
181
|
+
|
|
182
|
+
// Return inserted rows (requires adapter RETURNING support)
|
|
183
|
+
let insertedRows = await db.createMany(
|
|
184
|
+
orders,
|
|
185
|
+
[{ id: 'o_103', user_id: 'u_003', status: 'pending', total: 12, created_at: Date.now() }],
|
|
186
|
+
{ returnRows: true },
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`createMany`/`insertMany` throw when every row in the batch is empty (no explicit values).
|
|
191
|
+
|
|
192
|
+
### Update and delete helpers
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
let updatedUser = await db.update(users, 'u_003', { role: 'admin' })
|
|
196
|
+
|
|
197
|
+
let updateManyResult = await db.updateMany(
|
|
198
|
+
orders,
|
|
199
|
+
{ status: 'processing' },
|
|
200
|
+
{
|
|
201
|
+
where: { status: 'pending' },
|
|
202
|
+
orderBy: ['created_at', 'asc'],
|
|
203
|
+
limit: 25,
|
|
204
|
+
},
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
let deletedUser = await db.delete(users, 'u_002')
|
|
208
|
+
|
|
209
|
+
let deleteManyResult = await db.deleteMany(orders, {
|
|
210
|
+
where: { status: 'delivered' },
|
|
211
|
+
orderBy: [['created_at', 'asc']],
|
|
212
|
+
limit: 200,
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`db.update(...)` throws when the target row cannot be found.
|
|
217
|
+
|
|
218
|
+
Return behavior:
|
|
219
|
+
|
|
220
|
+
- `find`/`findOne` -> row or `null`
|
|
221
|
+
- `findMany` -> rows
|
|
222
|
+
- `create` -> `WriteResult` by default, row when `returnRow: true`
|
|
223
|
+
- `createMany` -> `WriteResult` by default, rows when `returnRows: true` (not supported in MySQL because it doesn't support `RETURNING`)
|
|
224
|
+
- `update` -> updated row (throws when target row is missing)
|
|
225
|
+
- `updateMany`/`deleteMany` -> `WriteResult`
|
|
226
|
+
- `delete` -> `boolean`
|
|
227
|
+
|
|
228
|
+
### Data Validation
|
|
229
|
+
|
|
230
|
+
For write operations, data validation happens before SQL is executed so invalid data does not get written to the database.
|
|
231
|
+
|
|
232
|
+
`data-table` treats each column schema as both:
|
|
233
|
+
|
|
234
|
+
- a runtime validator (is this input valid?)
|
|
235
|
+
- a parser (what normalized value should be written?)
|
|
236
|
+
|
|
237
|
+
If you're familiar with Zod, this is the same idea: schema-first validation where values are checked and parsed before use. In `data-table`, that parsing runs automatically on writes (`create`, `createMany`, `update`, `upsert`) so only schema-valid values are sent to the database. Invalid values and unknown columns fail fast before a write is attempted.
|
|
238
|
+
|
|
239
|
+
Tables are also [Standard Schema](https://standardschema.dev/)-compatible, so you can run the same validation explicitly with `remix/data-schema` before writing:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
import { parseSafe } from 'remix/data-schema'
|
|
243
|
+
|
|
244
|
+
let result = parseSafe(users, {
|
|
245
|
+
id: 'u_004',
|
|
246
|
+
email: 'new@example.com',
|
|
247
|
+
role: 'customer',
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
if (!result.success) {
|
|
251
|
+
// Handle validation issues
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Validation semantics match `create()`/`update()` input behavior:
|
|
256
|
+
|
|
257
|
+
- Partial objects are allowed
|
|
258
|
+
- Unknown columns fail validation
|
|
259
|
+
- Provided column values are parsed through each column schema
|
|
260
|
+
|
|
261
|
+
## Transactions
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
await db.transaction(async (tx) => {
|
|
265
|
+
let user = await tx.create(
|
|
266
|
+
users,
|
|
267
|
+
{ id: 'u_010', email: 'new@example.com', role: 'customer', created_at: Date.now() },
|
|
268
|
+
{ returnRow: true },
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
await tx.create(orders, {
|
|
272
|
+
id: 'o_500',
|
|
273
|
+
user_id: user.id,
|
|
274
|
+
status: 'pending',
|
|
275
|
+
total: 79,
|
|
276
|
+
created_at: Date.now(),
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Raw SQL Escape Hatch
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
import { rawSql, sql } from 'remix/data-table'
|
|
285
|
+
|
|
286
|
+
await db.exec(sql`select * from users where id = ${'u_001'}`)
|
|
287
|
+
await db.exec(rawSql('update users set role = ? where id = ?', ['admin', 'u_001']))
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Related Packages
|
|
291
|
+
|
|
292
|
+
- [`data-schema`](https://github.com/remix-run/remix/tree/main/packages/data-schema) - Schema definitions and parsing used by `data-table`
|
|
293
|
+
- [`data-table-postgres`](https://github.com/remix-run/remix/tree/main/packages/data-table-postgres) - PostgreSQL adapter
|
|
294
|
+
- [`data-table-mysql`](https://github.com/remix-run/remix/tree/main/packages/data-table-mysql) - MySQL adapter
|
|
295
|
+
- [`data-table-sqlite`](https://github.com/remix-run/remix/tree/main/packages/data-table-sqlite) - SQLite adapter
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
See [LICENSE](https://github.com/remix-run/remix/blob/main/LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { AdapterCapabilityOverrides, AdapterCapabilities, AdapterExecuteRequest, AdapterResult, AdapterStatement, DatabaseAdapter, TransactionOptions, TransactionToken, } from './lib/adapter.ts';
|
|
2
|
+
export { DataTableAdapterError, DataTableConstraintError, DataTableError, DataTableQueryError, DataTableValidationError, } from './lib/errors.ts';
|
|
3
|
+
export type { AnyRelation, AnyColumn, AnyTable, BelongsToOptions, ColumnReference, ColumnReferenceForQualifiedName, ColumnSchemas, HasManyOptions, HasManyThroughOptions, HasOneOptions, KeySelector, OrderByClause, OrderDirection, PrimaryKeyInput, Relation, RelationCardinality, RelationKind, RelationMapForTable, Table, TableColumnInput, TableColumnName, TableColumns, TableName, TablePrimaryKey, TableReference, TableRow, TableRowWith, TimestampConfig, TimestampOptions, } from './lib/table.ts';
|
|
4
|
+
export { belongsTo, columnMetadataKey, createTable, getTableColumns, getTableName, getTablePrimaryKey, getTableReference, getTableTimestamps, hasMany, hasManyThrough, hasOne, tableMetadataKey, timestampSchema, timestamps, } from './lib/table.ts';
|
|
5
|
+
export type { Predicate, WhereInput, WhereObject } from './lib/operators.ts';
|
|
6
|
+
export { and, between, eq, gt, gte, ilike, inList, isNull, like, lt, lte, ne, notInList, notNull, or, } from './lib/operators.ts';
|
|
7
|
+
export type { SqlStatement } from './lib/sql.ts';
|
|
8
|
+
export { rawSql, sql } from './lib/sql.ts';
|
|
9
|
+
export type { CountOptions, CreateManyResultOptions, CreateManyRowsOptions, CreateResultOptions, CreateRowOptions, Database, DeleteManyOptions, FindManyOptions, FindOneOptions, OrderByInput, OrderByTuple, QueryBuilderFor, QueryColumnTypesForTable, QueryForTable, QueryMethod, QueryTableInput, SingleTableColumn, SingleTableWhere, UpdateManyOptions, UpdateOptions, WriteResult, WriteRowResult, WriteRowsResult, } from './lib/database.ts';
|
|
10
|
+
export { createDatabase, QueryBuilder } from './lib/database.ts';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,iBAAiB,CAAA;AAExB,YAAY,EACV,WAAW,EACX,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,+BAA+B,EAC/B,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,KAAK,EACL,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,SAAS,EACT,eAAe,EACf,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,OAAO,EACP,cAAc,EACd,MAAM,EACN,gBAAgB,EAChB,eAAe,EACf,UAAU,GACX,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EACL,GAAG,EACH,OAAO,EACP,EAAE,EACF,EAAE,EACF,GAAG,EACH,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAI,EACJ,EAAE,EACF,GAAG,EACH,EAAE,EACF,SAAS,EACT,OAAO,EACP,EAAE,GACH,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAE1C,YAAY,EACV,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,wBAAwB,EACxB,aAAa,EACb,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,cAAc,EACd,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { DataTableAdapterError, DataTableConstraintError, DataTableError, DataTableQueryError, DataTableValidationError, } from "./lib/errors.js";
|
|
2
|
+
export { belongsTo, columnMetadataKey, createTable, getTableColumns, getTableName, getTablePrimaryKey, getTableReference, getTableTimestamps, hasMany, hasManyThrough, hasOne, tableMetadataKey, timestampSchema, timestamps, } from "./lib/table.js";
|
|
3
|
+
export { and, between, eq, gt, gte, ilike, inList, isNull, like, lt, lte, ne, notInList, notNull, or, } from "./lib/operators.js";
|
|
4
|
+
export { rawSql, sql } from "./lib/sql.js";
|
|
5
|
+
export { createDatabase, QueryBuilder } from "./lib/database.js";
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { AnyTable, OrderByClause } from './table.ts';
|
|
2
|
+
import type { Predicate } from './operators.ts';
|
|
3
|
+
import type { SqlStatement } from './sql.ts';
|
|
4
|
+
import type { Pretty } from './types.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Supported SQL join kinds.
|
|
7
|
+
*/
|
|
8
|
+
export type JoinType = 'inner' | 'left' | 'right';
|
|
9
|
+
/**
|
|
10
|
+
* Join configuration used in compiled select statements.
|
|
11
|
+
*/
|
|
12
|
+
export type JoinClause = {
|
|
13
|
+
type: JoinType;
|
|
14
|
+
table: AnyTable;
|
|
15
|
+
on: Predicate;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Selected output column with optional alias.
|
|
19
|
+
*/
|
|
20
|
+
export type SelectColumn = {
|
|
21
|
+
column: string;
|
|
22
|
+
alias: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Returning selection for write statements.
|
|
26
|
+
*/
|
|
27
|
+
export type ReturningSelection = '*' | string[];
|
|
28
|
+
/**
|
|
29
|
+
* Canonical select statement shape consumed by adapters.
|
|
30
|
+
*/
|
|
31
|
+
export type SelectStatement<table extends AnyTable = AnyTable> = {
|
|
32
|
+
kind: 'select';
|
|
33
|
+
table: table;
|
|
34
|
+
select: '*' | SelectColumn[];
|
|
35
|
+
distinct: boolean;
|
|
36
|
+
joins: JoinClause[];
|
|
37
|
+
where: Predicate[];
|
|
38
|
+
groupBy: string[];
|
|
39
|
+
having: Predicate[];
|
|
40
|
+
orderBy: OrderByClause[];
|
|
41
|
+
limit?: number;
|
|
42
|
+
offset?: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Canonical count statement shape consumed by adapters.
|
|
46
|
+
*/
|
|
47
|
+
export type CountStatement<table extends AnyTable = AnyTable> = {
|
|
48
|
+
kind: 'count';
|
|
49
|
+
table: table;
|
|
50
|
+
joins: JoinClause[];
|
|
51
|
+
where: Predicate[];
|
|
52
|
+
groupBy: string[];
|
|
53
|
+
having: Predicate[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Canonical exists statement shape consumed by adapters.
|
|
57
|
+
*/
|
|
58
|
+
export type ExistsStatement<table extends AnyTable = AnyTable> = {
|
|
59
|
+
kind: 'exists';
|
|
60
|
+
table: table;
|
|
61
|
+
joins: JoinClause[];
|
|
62
|
+
where: Predicate[];
|
|
63
|
+
groupBy: string[];
|
|
64
|
+
having: Predicate[];
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Canonical insert statement shape consumed by adapters.
|
|
68
|
+
*/
|
|
69
|
+
export type InsertStatement<table extends AnyTable = AnyTable> = {
|
|
70
|
+
kind: 'insert';
|
|
71
|
+
table: table;
|
|
72
|
+
values: Record<string, unknown>;
|
|
73
|
+
returning?: ReturningSelection;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Canonical bulk-insert statement shape consumed by adapters.
|
|
77
|
+
*/
|
|
78
|
+
export type InsertManyStatement<table extends AnyTable = AnyTable> = {
|
|
79
|
+
kind: 'insertMany';
|
|
80
|
+
table: table;
|
|
81
|
+
values: Record<string, unknown>[];
|
|
82
|
+
returning?: ReturningSelection;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Canonical update statement shape consumed by adapters.
|
|
86
|
+
*/
|
|
87
|
+
export type UpdateStatement<table extends AnyTable = AnyTable> = {
|
|
88
|
+
kind: 'update';
|
|
89
|
+
table: table;
|
|
90
|
+
changes: Record<string, unknown>;
|
|
91
|
+
where: Predicate[];
|
|
92
|
+
returning?: ReturningSelection;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Canonical delete statement shape consumed by adapters.
|
|
96
|
+
*/
|
|
97
|
+
export type DeleteStatement<table extends AnyTable = AnyTable> = {
|
|
98
|
+
kind: 'delete';
|
|
99
|
+
table: table;
|
|
100
|
+
where: Predicate[];
|
|
101
|
+
returning?: ReturningSelection;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Canonical upsert statement shape consumed by adapters.
|
|
105
|
+
*/
|
|
106
|
+
export type UpsertStatement<table extends AnyTable = AnyTable> = {
|
|
107
|
+
kind: 'upsert';
|
|
108
|
+
table: table;
|
|
109
|
+
values: Record<string, unknown>;
|
|
110
|
+
conflictTarget?: string[];
|
|
111
|
+
update?: Record<string, unknown>;
|
|
112
|
+
returning?: ReturningSelection;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Raw SQL statement execution descriptor.
|
|
116
|
+
*/
|
|
117
|
+
export type RawStatement = {
|
|
118
|
+
kind: 'raw';
|
|
119
|
+
sql: SqlStatement;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Union of all canonical statement shapes.
|
|
123
|
+
*/
|
|
124
|
+
export type AdapterStatement = SelectStatement | CountStatement | ExistsStatement | InsertStatement | InsertManyStatement | UpdateStatement | DeleteStatement | UpsertStatement | RawStatement;
|
|
125
|
+
/**
|
|
126
|
+
* Opaque transaction handle supplied by adapters.
|
|
127
|
+
*/
|
|
128
|
+
export type TransactionToken = {
|
|
129
|
+
id: string;
|
|
130
|
+
metadata?: Record<string, unknown>;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Transaction hints that adapters may apply when supported by the dialect.
|
|
134
|
+
*/
|
|
135
|
+
export type TransactionOptions = {
|
|
136
|
+
isolationLevel?: 'read uncommitted' | 'read committed' | 'repeatable read' | 'serializable';
|
|
137
|
+
readOnly?: boolean;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Adapter execution request payload.
|
|
141
|
+
*/
|
|
142
|
+
export type AdapterExecuteRequest = {
|
|
143
|
+
statement: AdapterStatement;
|
|
144
|
+
transaction?: TransactionToken;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Adapter execution result payload.
|
|
148
|
+
*/
|
|
149
|
+
export type AdapterResult = {
|
|
150
|
+
rows?: Record<string, unknown>[];
|
|
151
|
+
affectedRows?: number;
|
|
152
|
+
insertId?: unknown;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Declares adapter feature support.
|
|
156
|
+
*/
|
|
157
|
+
export type AdapterCapabilities = {
|
|
158
|
+
returning: boolean;
|
|
159
|
+
savepoints: boolean;
|
|
160
|
+
upsert: boolean;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Partial capabilities used to override adapter defaults.
|
|
164
|
+
*/
|
|
165
|
+
export type AdapterCapabilityOverrides = Pretty<Partial<AdapterCapabilities>>;
|
|
166
|
+
/**
|
|
167
|
+
* Runtime contract implemented by concrete database adapters.
|
|
168
|
+
*/
|
|
169
|
+
export interface DatabaseAdapter {
|
|
170
|
+
dialect: string;
|
|
171
|
+
capabilities: AdapterCapabilities;
|
|
172
|
+
execute(request: AdapterExecuteRequest): Promise<AdapterResult>;
|
|
173
|
+
beginTransaction(options?: TransactionOptions): Promise<TransactionToken>;
|
|
174
|
+
commitTransaction(token: TransactionToken): Promise<void>;
|
|
175
|
+
rollbackTransaction(token: TransactionToken): Promise<void>;
|
|
176
|
+
createSavepoint(token: TransactionToken, name: string): Promise<void>;
|
|
177
|
+
rollbackToSavepoint(token: TransactionToken, name: string): Promise<void>;
|
|
178
|
+
releaseSavepoint(token: TransactionToken, name: string): Promise<void>;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/lib/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|