@simplysm/orm-common 14.0.22 → 14.0.24
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/package.json +3 -4
- package/README.md +0 -170
- package/docs/core.md +0 -217
- package/docs/expression.md +0 -220
- package/docs/query-builder.md +0 -150
- package/docs/queryable.md +0 -261
- package/docs/schema-builders.md +0 -288
- package/docs/types.md +0 -481
package/docs/query-builder.md
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
# Query Builder
|
|
2
|
-
|
|
3
|
-
Transforms `QueryDef` AST into dialect-specific SQL strings.
|
|
4
|
-
|
|
5
|
-
## createQueryBuilder
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
function createQueryBuilder(dialect: Dialect): QueryBuilderBase
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Factory function that creates a dialect-specific QueryBuilder instance.
|
|
12
|
-
|
|
13
|
-
| Parameter | Type | Description |
|
|
14
|
-
|-----------|------|-------------|
|
|
15
|
-
| `dialect` | `"mysql" \| "mssql" \| "postgresql"` | Target DBMS dialect |
|
|
16
|
-
|
|
17
|
-
Returns `MysqlQueryBuilder`, `MssqlQueryBuilder`, or `PostgresqlQueryBuilder`.
|
|
18
|
-
|
|
19
|
-
## QueryBuilderBase
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
abstract class QueryBuilderBase {
|
|
23
|
-
build(def: QueryDef): QueryBuildResult;
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Abstract base class for rendering `QueryDef` AST to SQL. Implements common dispatch logic; dialect-specific differences are handled by abstract methods in subclasses.
|
|
28
|
-
|
|
29
|
-
| Method | Signature | Description |
|
|
30
|
-
|--------|-----------|-------------|
|
|
31
|
-
| `build` | `(def: QueryDef) => QueryBuildResult` | Convert any QueryDef to SQL |
|
|
32
|
-
|
|
33
|
-
`QueryBuildResult` contains:
|
|
34
|
-
|
|
35
|
-
| Field | Type | Description |
|
|
36
|
-
|-------|------|-------------|
|
|
37
|
-
| `sql` | `string` | Generated SQL string |
|
|
38
|
-
| `resultSetIndex` | `number?` | Result set index for multi-statement queries |
|
|
39
|
-
| `resultSetStride` | `number?` | Stride for extracting results from multi-statement queries |
|
|
40
|
-
|
|
41
|
-
## Dialect-Specific Query Builders
|
|
42
|
-
|
|
43
|
-
### MysqlQueryBuilder
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
class MysqlQueryBuilder extends QueryBuilderBase
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
MySQL 8.0.14+ query builder. Handles MySQL-specific syntax such as backtick quoting, `<=>` for NULL-safe equality, `LIMIT ... OFFSET`, `LOAD DATA LOCAL INFILE`, etc.
|
|
50
|
-
|
|
51
|
-
### MssqlQueryBuilder
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
class MssqlQueryBuilder extends QueryBuilderBase
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
MSSQL 2012+ query builder. Handles bracket quoting, `TOP`, `OFFSET ... FETCH NEXT`, `MERGE` for upsert, `SET IDENTITY_INSERT`, etc.
|
|
58
|
-
|
|
59
|
-
### PostgresqlQueryBuilder
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
class PostgresqlQueryBuilder extends QueryBuilderBase
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
PostgreSQL 9.0+ query builder. Handles double-quote quoting, `LIMIT ... OFFSET`, `ON CONFLICT` for upsert, `COPY FROM STDIN`, etc.
|
|
66
|
-
|
|
67
|
-
## ExprRendererBase
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
abstract class ExprRendererBase {
|
|
71
|
-
renderExpr(expr: Expr): string;
|
|
72
|
-
renderWhereExpr(expr: WhereExpr): string;
|
|
73
|
-
}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Abstract base class for rendering `Expr` and `WhereExpr` AST nodes to SQL fragments. Each QueryBuilder uses a corresponding ExprRenderer.
|
|
77
|
-
|
|
78
|
-
| Method | Signature | Description |
|
|
79
|
-
|--------|-----------|-------------|
|
|
80
|
-
| `renderExpr` | `(expr: Expr) => string` | Render a value/function expression to SQL |
|
|
81
|
-
| `renderWhereExpr` | `(expr: WhereExpr) => string` | Render a WHERE condition expression to SQL |
|
|
82
|
-
|
|
83
|
-
## Dialect-Specific Expression Renderers
|
|
84
|
-
|
|
85
|
-
### MysqlExprRenderer
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
class MysqlExprRenderer extends ExprRendererBase
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
MySQL expression renderer. Uses `<=>` for NULL-safe equality, `IFNULL`, `LOCATE`, MySQL `DATE_FORMAT` patterns, etc.
|
|
92
|
-
|
|
93
|
-
### MssqlExprRenderer
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
class MssqlExprRenderer extends ExprRendererBase
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
MSSQL expression renderer. Uses `IIF`, `CHARINDEX`, `FORMAT` for date formatting, `DATALENGTH` for byte length, etc.
|
|
100
|
-
|
|
101
|
-
### PostgresqlExprRenderer
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
class PostgresqlExprRenderer extends ExprRendererBase
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
PostgreSQL expression renderer. Uses `IS NOT DISTINCT FROM` for NULL-safe equality, `POSITION`, `TO_CHAR` for date formatting, `OCTET_LENGTH`, etc.
|
|
108
|
-
|
|
109
|
-
## parseQueryResult
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
async function parseQueryResult<TRecord>(
|
|
113
|
-
rawResults: Record<string, unknown>[],
|
|
114
|
-
meta: ResultMeta,
|
|
115
|
-
): Promise<TRecord[] | undefined>
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Parses raw database query results into typed TypeScript objects. Handles:
|
|
119
|
-
|
|
120
|
-
- **Type conversion**: Converts raw values (strings, numbers) to proper TypeScript types (`DateTime`, `DateOnly`, `Uuid`, etc.) based on `ResultMeta.columns`
|
|
121
|
-
- **JOIN nesting**: Flattens `"posts.id"` keys into nested `{ posts: { id: ... } }` objects
|
|
122
|
-
- **Grouping**: Groups rows by non-JOIN columns, collecting JOIN data into arrays (1:N) or single objects (1:1)
|
|
123
|
-
- **Event loop yielding**: Yields to the event loop every 100 records for large result sets
|
|
124
|
-
|
|
125
|
-
| Parameter | Type | Description |
|
|
126
|
-
|-----------|------|-------------|
|
|
127
|
-
| `rawResults` | `Record<string, unknown>[]` | Raw DB result rows |
|
|
128
|
-
| `meta` | `ResultMeta` | Column types and JOIN structure info |
|
|
129
|
-
|
|
130
|
-
Returns `undefined` if the input is empty or all records parse to empty objects.
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
// Simple type parsing
|
|
134
|
-
const raw = [{ id: "1", createdAt: "2026-01-07T10:00:00.000Z" }];
|
|
135
|
-
const meta = { columns: { id: "number", createdAt: "DateTime" }, joins: {} };
|
|
136
|
-
const result = await parseQueryResult(raw, meta);
|
|
137
|
-
// [{ id: 1, createdAt: DateTime(...) }]
|
|
138
|
-
|
|
139
|
-
// JOIN nesting
|
|
140
|
-
const raw = [
|
|
141
|
-
{ id: 1, name: "User1", "posts.id": 10, "posts.title": "Post1" },
|
|
142
|
-
{ id: 1, name: "User1", "posts.id": 11, "posts.title": "Post2" },
|
|
143
|
-
];
|
|
144
|
-
const meta = {
|
|
145
|
-
columns: { id: "number", name: "string", "posts.id": "number", "posts.title": "string" },
|
|
146
|
-
joins: { posts: { isSingle: false } },
|
|
147
|
-
};
|
|
148
|
-
const result = await parseQueryResult(raw, meta);
|
|
149
|
-
// [{ id: 1, name: "User1", posts: [{ id: 10, title: "Post1" }, { id: 11, title: "Post2" }] }]
|
|
150
|
-
```
|
package/docs/queryable.md
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
# Queryable / Executable
|
|
2
|
-
|
|
3
|
-
Type-safe query builder and stored procedure executor.
|
|
4
|
-
|
|
5
|
-
## Queryable
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
class Queryable<TData extends DataRecord, TFrom extends TableBuilder<any, any> | never> {
|
|
9
|
-
constructor(readonly meta: QueryableMeta<TData>);
|
|
10
|
-
}
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Fluent query builder for composing SELECT, INSERT, UPDATE, DELETE, and UPSERT queries. All methods return new Queryable instances (immutable chaining).
|
|
14
|
-
|
|
15
|
-
- `TData` - Query result data type
|
|
16
|
-
- `TFrom` - Source table (required for CUD operations, `never` for read-only)
|
|
17
|
-
|
|
18
|
-
### Option Methods (SELECT / DISTINCT / LOCK)
|
|
19
|
-
|
|
20
|
-
| Method | Signature | Description |
|
|
21
|
-
|--------|-----------|-------------|
|
|
22
|
-
| `select` | `<R>(fn: (cols: QueryableRecord<TData>) => R) => Queryable<UnwrapQueryableRecord<R>, never>` | Specify columns to SELECT |
|
|
23
|
-
| `distinct` | `() => Queryable<TData, never>` | Apply DISTINCT |
|
|
24
|
-
| `lock` | `() => Queryable<TData, TFrom>` | Apply FOR UPDATE row lock |
|
|
25
|
-
|
|
26
|
-
### Restrict Methods (TOP / LIMIT)
|
|
27
|
-
|
|
28
|
-
| Method | Signature | Description |
|
|
29
|
-
|--------|-----------|-------------|
|
|
30
|
-
| `top` | `(count: number) => Queryable<TData, TFrom>` | Select top N rows |
|
|
31
|
-
| `limit` | `(skip: number, take: number) => Queryable<TData, TFrom>` | Pagination (requires orderBy) |
|
|
32
|
-
|
|
33
|
-
### Sorting (ORDER BY)
|
|
34
|
-
|
|
35
|
-
| Method | Signature | Description |
|
|
36
|
-
|--------|-----------|-------------|
|
|
37
|
-
| `orderBy` | `(fn: (cols) => ExprUnit, orderBy?: "ASC" \| "DESC") => Queryable<TData, TFrom>` | Add sort condition (stackable) |
|
|
38
|
-
|
|
39
|
-
### Filtering (WHERE)
|
|
40
|
-
|
|
41
|
-
| Method | Signature | Description |
|
|
42
|
-
|--------|-----------|-------------|
|
|
43
|
-
| `where` | `(predicate: (cols) => WhereExprUnit[]) => Queryable<TData, TFrom>` | Add WHERE conditions (stackable, AND) |
|
|
44
|
-
| `search` | `(fn: (cols) => ExprUnit<string\|undefined>[], searchText: string) => Queryable<TData, TFrom>` | Full-text search across columns |
|
|
45
|
-
|
|
46
|
-
### Grouping (GROUP BY / HAVING)
|
|
47
|
-
|
|
48
|
-
| Method | Signature | Description |
|
|
49
|
-
|--------|-----------|-------------|
|
|
50
|
-
| `groupBy` | `(fn: (cols) => ExprUnit[]) => Queryable<TData, never>` | Group by columns |
|
|
51
|
-
| `having` | `(predicate: (cols) => WhereExprUnit[]) => Queryable<TData, never>` | Filter groups |
|
|
52
|
-
|
|
53
|
-
### JOIN
|
|
54
|
-
|
|
55
|
-
| Method | Signature | Description |
|
|
56
|
-
|--------|-----------|-------------|
|
|
57
|
-
| `join` | `<A, R>(as: A, fn: (qr: JoinQueryable, cols) => Queryable<R, any>) => Queryable<TData & { [K in A]?: R[] }, TFrom>` | LEFT OUTER JOIN (1:N, result as array) |
|
|
58
|
-
| `joinSingle` | `<A, R>(as: A, fn: (qr: JoinQueryable, cols) => Queryable<R, any>) => Queryable<TData & { [K in A]?: R }, TFrom>` | LEFT OUTER JOIN (N:1 or 1:1, result as single object) |
|
|
59
|
-
| `include` | `(fn: (item: PathProxy<TData>) => PathProxy) => Queryable<TData, TFrom>` | Auto-JOIN based on TableBuilder FK/FKT relations |
|
|
60
|
-
|
|
61
|
-
### Subquery / Union
|
|
62
|
-
|
|
63
|
-
| Method | Signature | Description |
|
|
64
|
-
|--------|-----------|-------------|
|
|
65
|
-
| `wrap` | `() => Queryable<TData, never>` | Wrap as subquery (needed for count after distinct/groupBy) |
|
|
66
|
-
| `Queryable.union` (static) | `(...queries: Queryable<TData, any>[]) => Queryable<TData, never>` | Combine queries with UNION (min 2) |
|
|
67
|
-
|
|
68
|
-
### Recursive CTE
|
|
69
|
-
|
|
70
|
-
| Method | Signature | Description |
|
|
71
|
-
|--------|-----------|-------------|
|
|
72
|
-
| `recursive` | `(fn: (cte: RecursiveQueryable<TData>) => Queryable<TData, any>) => Queryable<TData, never>` | Generate recursive CTE (WITH RECURSIVE) |
|
|
73
|
-
|
|
74
|
-
### Execution (SELECT)
|
|
75
|
-
|
|
76
|
-
| Method | Signature | Description |
|
|
77
|
-
|--------|-----------|-------------|
|
|
78
|
-
| `execute` | `() => Promise<TData[]>` | Execute SELECT and return results |
|
|
79
|
-
| `single` | `() => Promise<TData \| undefined>` | Return single result (throws if > 1) |
|
|
80
|
-
| `first` | `() => Promise<TData \| undefined>` | Return first result |
|
|
81
|
-
| `count` | `(fn?: (cols) => ExprUnit) => Promise<number>` | Count rows (throws after distinct/groupBy without wrap) |
|
|
82
|
-
| `exists` | `() => Promise<boolean>` | Check if any matching data exists |
|
|
83
|
-
|
|
84
|
-
### QueryDef Getters (SELECT)
|
|
85
|
-
|
|
86
|
-
| Method | Signature | Description |
|
|
87
|
-
|--------|-----------|-------------|
|
|
88
|
-
| `getSelectQueryDef` | `() => SelectQueryDef` | Get the SELECT QueryDef AST |
|
|
89
|
-
| `getResultMeta` | `(outputColumns?: string[]) => ResultMeta` | Get result parsing metadata |
|
|
90
|
-
|
|
91
|
-
### INSERT
|
|
92
|
-
|
|
93
|
-
| Method | Signature | Description |
|
|
94
|
-
|--------|-----------|-------------|
|
|
95
|
-
| `insert` | `(records: TFrom["$inferInsert"][]) => Promise<void>` | Insert records (auto-chunks per 1000) |
|
|
96
|
-
| `insert` | `(records, outputColumns: K[]) => Promise<Pick<...>[]>` | Insert with output columns |
|
|
97
|
-
| `insertIfNotExists` | `(record: TFrom["$inferInsert"]) => Promise<void>` | Insert if WHERE condition has no match |
|
|
98
|
-
| `insertIfNotExists` | `(record, outputColumns: K[]) => Promise<Pick<...>>` | Insert if not exists with output |
|
|
99
|
-
| `insertInto` | `(targetTable: TableBuilder) => Promise<void>` | INSERT INTO ... SELECT |
|
|
100
|
-
| `insertInto` | `(targetTable, outputColumns: K[]) => Promise<Pick<...>[]>` | INSERT INTO ... SELECT with output |
|
|
101
|
-
|
|
102
|
-
### UPDATE / DELETE
|
|
103
|
-
|
|
104
|
-
| Method | Signature | Description |
|
|
105
|
-
|--------|-----------|-------------|
|
|
106
|
-
| `update` | `(recordFwd: (cols) => QueryableWriteRecord) => Promise<void>` | Update matching rows |
|
|
107
|
-
| `update` | `(recordFwd, outputColumns: K[]) => Promise<Pick<...>[]>` | Update with output |
|
|
108
|
-
| `delete` | `() => Promise<void>` | Delete matching rows |
|
|
109
|
-
| `delete` | `(outputColumns: K[]) => Promise<Pick<...>[]>` | Delete with output |
|
|
110
|
-
|
|
111
|
-
### UPSERT
|
|
112
|
-
|
|
113
|
-
| Method | Signature | Description |
|
|
114
|
-
|--------|-----------|-------------|
|
|
115
|
-
| `upsert` | `(updateFn: (cols) => WriteRecord) => Promise<void>` | Update or insert (same data) |
|
|
116
|
-
| `upsert` | `(updateFn, insertFn) => Promise<void>` | Update or insert (different data) |
|
|
117
|
-
| `upsert` | `(updateFn, insertFn?, outputColumns?) => Promise<Pick<...>[] \| void>` | With output columns |
|
|
118
|
-
|
|
119
|
-
### DDL Helper
|
|
120
|
-
|
|
121
|
-
| Method | Signature | Description |
|
|
122
|
-
|--------|-----------|-------------|
|
|
123
|
-
| `switchFk` | `(enabled: boolean) => Promise<void>` | Enable/disable FK constraints on this table |
|
|
124
|
-
|
|
125
|
-
## queryable (factory)
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
function queryable<TBuilder extends TableBuilder<any, any> | ViewBuilder<any, any, any>>(
|
|
129
|
-
db: DbContextBase,
|
|
130
|
-
tableOrView: TBuilder,
|
|
131
|
-
as?: string,
|
|
132
|
-
): () => Queryable<TBuilder["$inferSelect"], TBuilder extends TableBuilder ? TBuilder : never>
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
Creates a factory function that returns a new Queryable instance each time it is called. Each call allocates a fresh alias via `db.getNextAlias()`.
|
|
136
|
-
|
|
137
|
-
## Executable
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
class Executable<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord> {
|
|
141
|
-
constructor(db: DbContextBase, builder: ProcedureBuilder<TParams, TReturns>);
|
|
142
|
-
getExecProcQueryDef(params?: InferColumnExprs<TParams>): { type: "execProc"; ... };
|
|
143
|
-
async execute(params: InferColumnExprs<TParams>): Promise<InferColumnExprs<TReturns>[][]>;
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Stored procedure execution wrapper.
|
|
148
|
-
|
|
149
|
-
| Method | Signature | Description |
|
|
150
|
-
|--------|-----------|-------------|
|
|
151
|
-
| `getExecProcQueryDef` | `(params?) => ExecProcQueryDef` | Build procedure execution QueryDef |
|
|
152
|
-
| `execute` | `(params) => Promise<T[][]>` | Execute the procedure |
|
|
153
|
-
|
|
154
|
-
## executable (factory)
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
function executable<TParams, TReturns>(
|
|
158
|
-
db: DbContextBase,
|
|
159
|
-
builder: ProcedureBuilder<TParams, TReturns>,
|
|
160
|
-
): () => Executable<TParams, TReturns>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Creates a factory function that returns a new Executable instance.
|
|
164
|
-
|
|
165
|
-
## parseSearchQuery
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
function parseSearchQuery(searchText: string): ParsedSearchQuery
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Parses a search query string into SQL LIKE patterns.
|
|
172
|
-
|
|
173
|
-
| Syntax | Meaning | Example |
|
|
174
|
-
|--------|---------|---------|
|
|
175
|
-
| `term1 term2` | OR (match any) | `apple banana` |
|
|
176
|
-
| `+term` | Required (AND) | `+apple +banana` |
|
|
177
|
-
| `-term` | Exclude (NOT) | `apple -banana` |
|
|
178
|
-
| `"exact phrase"` | Exact match (required) | `"delicious fruit"` |
|
|
179
|
-
| `*` | Wildcard | `app*` becomes `app%` |
|
|
180
|
-
|
|
181
|
-
Escape sequences: `\\` (literal `\`), `\*`, `\%`, `\"`, `\+`, `\-`.
|
|
182
|
-
|
|
183
|
-
## ParsedSearchQuery
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
interface ParsedSearchQuery {
|
|
187
|
-
or: string[]; // OR conditions - LIKE patterns
|
|
188
|
-
must: string[]; // AND conditions (+ prefix or quotes) - LIKE patterns
|
|
189
|
-
not: string[]; // NOT conditions (- prefix) - LIKE patterns
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## getMatchedPrimaryKeys
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
function getMatchedPrimaryKeys(
|
|
197
|
-
fkCols: string[],
|
|
198
|
-
targetTable: TableBuilder<any, any>,
|
|
199
|
-
): string[]
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Match FK column array with the target table's PK. Returns PK column name array. Throws if column counts do not match.
|
|
203
|
-
|
|
204
|
-
## QueryableRecord
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
type QueryableRecord<TData extends DataRecord> = {
|
|
208
|
-
[K in keyof TData]: TData[K] extends ColumnPrimitive
|
|
209
|
-
? ExprUnit<TData[K]>
|
|
210
|
-
: TData[K] extends (infer U)[]
|
|
211
|
-
? U extends DataRecord ? QueryableRecord<U>[] : never
|
|
212
|
-
: TData[K] extends DataRecord ? QueryableRecord<TData[K]> : ...
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Maps each field of a DataRecord to its corresponding ExprUnit proxy. Used as the column accessor type in Queryable callbacks.
|
|
217
|
-
|
|
218
|
-
## QueryableWriteRecord
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
type QueryableWriteRecord<TData> = {
|
|
222
|
-
[K in keyof TData]: TData[K] extends ColumnPrimitive ? ExprInput<TData[K]> : never;
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Maps each field to ExprInput for write operations (UPDATE, UPSERT).
|
|
227
|
-
|
|
228
|
-
## NullableQueryableRecord
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
type NullableQueryableRecord<TData extends DataRecord> = { ... }
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
Like QueryableRecord but all primitive fields become `ExprUnit<T | undefined>`. Used for LEFT JOIN results where all columns may be NULL.
|
|
235
|
-
|
|
236
|
-
## UnwrapQueryableRecord
|
|
237
|
-
|
|
238
|
-
```typescript
|
|
239
|
-
type UnwrapQueryableRecord<R> = {
|
|
240
|
-
[K in keyof R]: R[K] extends ExprUnit<infer T> ? T : ...
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Reverse-maps QueryableRecord back to a plain DataRecord. Used internally by `select()` to infer the resulting data type.
|
|
245
|
-
|
|
246
|
-
## PathProxy
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
type PathProxy<TObject> = {
|
|
250
|
-
[K in keyof TObject as TObject[K] extends ColumnPrimitive ? never : K]-?: PathProxy<UnwrapArray<TObject[K]>>;
|
|
251
|
-
} & { readonly [PATH_SYMBOL]: string[] }
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
Type-safe proxy for `include()` that only exposes non-primitive (relation) fields. Property access builds a path array internally.
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
// Only relation fields are accessible:
|
|
258
|
-
db.post().include((p) => p.author) // OK - author is a relation
|
|
259
|
-
db.post().include((p) => p.author.company) // OK - nested relation
|
|
260
|
-
// db.post().include((p) => p.title) // Compile error - title is string
|
|
261
|
-
```
|
package/docs/schema-builders.md
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
# Schema Builders
|
|
2
|
-
|
|
3
|
-
Fluent API builders for defining tables, views, procedures, columns, indexes, and relations.
|
|
4
|
-
|
|
5
|
-
## Table (function)
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
function Table(name: string): TableBuilder<{}, {}>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Creates a new TableBuilder with the given table name.
|
|
12
|
-
|
|
13
|
-
## TableBuilder
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
class TableBuilder<TColumns extends ColumnBuilderRecord, TRelations extends RelationBuilderRecord>
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Fluent API for defining database table schema including columns, primary key, indexes, and relations.
|
|
20
|
-
|
|
21
|
-
### Phantom Type Fields
|
|
22
|
-
|
|
23
|
-
| Field | Type | Description |
|
|
24
|
-
|-------|------|-------------|
|
|
25
|
-
| `$columns` | `TColumns` | Column definitions (type inference) |
|
|
26
|
-
| `$relations` | `TRelations` | Relation definitions (type inference) |
|
|
27
|
-
| `$inferSelect` | `InferColumns<TColumns> & InferDeepRelations<TRelations>` | Full SELECT type |
|
|
28
|
-
| `$inferColumns` | `InferColumns<TColumns>` | Column-only type |
|
|
29
|
-
| `$inferInsert` | `InferInsertColumns<TColumns>` | INSERT type (AI/nullable/default optional) |
|
|
30
|
-
| `$inferUpdate` | `InferUpdateColumns<TColumns>` | UPDATE type (all optional) |
|
|
31
|
-
|
|
32
|
-
### Constructor
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
constructor(readonly meta: {
|
|
36
|
-
name: string;
|
|
37
|
-
description?: string;
|
|
38
|
-
database?: string;
|
|
39
|
-
schema?: string;
|
|
40
|
-
columns?: TColumns;
|
|
41
|
-
primaryKey?: (keyof TColumns & string)[];
|
|
42
|
-
relations?: TRelations;
|
|
43
|
-
indexes?: IndexBuilder<(keyof TColumns & string)[]>[];
|
|
44
|
-
})
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Methods
|
|
48
|
-
|
|
49
|
-
| Method | Signature | Description |
|
|
50
|
-
|--------|-----------|-------------|
|
|
51
|
-
| `description` | `(desc: string) => TableBuilder` | Set table description (DDL comment) |
|
|
52
|
-
| `database` | `(db: string) => TableBuilder` | Set database name |
|
|
53
|
-
| `schema` | `(schema: string) => TableBuilder` | Set schema name (MSSQL/PostgreSQL) |
|
|
54
|
-
| `columns` | `<T>(fn: (c: ColumnFactory) => T) => TableBuilder<T, TRelations>` | Define columns via column factory |
|
|
55
|
-
| `primaryKey` | `(...columns: (keyof TColumns & string)[]) => TableBuilder` | Set primary key (single or composite) |
|
|
56
|
-
| `indexes` | `(fn: (i: IndexFactory) => IndexBuilder[]) => TableBuilder` | Define indexes |
|
|
57
|
-
| `relations` | `<T>(fn: (r: RelationFactory) => T) => TableBuilder<TColumns, T>` | Define FK and relation mappings |
|
|
58
|
-
|
|
59
|
-
## View (function)
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
function View(name: string): ViewBuilder<any, any, {}>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Creates a new ViewBuilder with the given view name.
|
|
66
|
-
|
|
67
|
-
## ViewBuilder
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
class ViewBuilder<TDbContext extends DbContextBase, TData extends DataRecord, TRelations extends RelationBuilderRecord>
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Fluent API for defining database view schema.
|
|
74
|
-
|
|
75
|
-
### Phantom Type Fields
|
|
76
|
-
|
|
77
|
-
| Field | Type | Description |
|
|
78
|
-
|-------|------|-------------|
|
|
79
|
-
| `$relations` | `TRelations` | Relation definitions |
|
|
80
|
-
| `$inferSelect` | `TData` | Full SELECT type |
|
|
81
|
-
|
|
82
|
-
### Methods
|
|
83
|
-
|
|
84
|
-
| Method | Signature | Description |
|
|
85
|
-
|--------|-----------|-------------|
|
|
86
|
-
| `description` | `(desc: string) => ViewBuilder` | Set view description |
|
|
87
|
-
| `database` | `(db: string) => ViewBuilder` | Set database name |
|
|
88
|
-
| `schema` | `(schema: string) => ViewBuilder` | Set schema name |
|
|
89
|
-
| `query` | `<TViewData, TDb>(viewFn: (db: TDb) => Queryable<TViewData, any>) => ViewBuilder<TDb, TViewData, TRelations>` | Define the view's SELECT query |
|
|
90
|
-
| `relations` | `<T>(fn: (r: RelationFactory) => T) => ViewBuilder` | Define relations (RelationKey only, no FK) |
|
|
91
|
-
|
|
92
|
-
## Procedure (function)
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
function Procedure(name: string): ProcedureBuilder<never, never>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Creates a new ProcedureBuilder with the given procedure name.
|
|
99
|
-
|
|
100
|
-
## ProcedureBuilder
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
class ProcedureBuilder<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord>
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
Fluent API for defining stored procedure schema.
|
|
107
|
-
|
|
108
|
-
### Phantom Type Fields
|
|
109
|
-
|
|
110
|
-
| Field | Type | Description |
|
|
111
|
-
|-------|------|-------------|
|
|
112
|
-
| `$params` | `TParams` | Parameter definitions |
|
|
113
|
-
| `$returns` | `TReturns` | Return type definitions |
|
|
114
|
-
|
|
115
|
-
### Methods
|
|
116
|
-
|
|
117
|
-
| Method | Signature | Description |
|
|
118
|
-
|--------|-----------|-------------|
|
|
119
|
-
| `description` | `(desc: string) => ProcedureBuilder` | Set procedure description |
|
|
120
|
-
| `database` | `(db: string) => ProcedureBuilder` | Set database name |
|
|
121
|
-
| `schema` | `(schema: string) => ProcedureBuilder` | Set schema name |
|
|
122
|
-
| `params` | `<T>(fn: (c: ColumnFactory) => T) => ProcedureBuilder<T, TReturns>` | Define input parameters |
|
|
123
|
-
| `returns` | `<T>(fn: (c: ColumnFactory) => T) => ProcedureBuilder<TParams, T>` | Define return columns |
|
|
124
|
-
| `body` | `(sql: string) => ProcedureBuilder` | Set procedure body SQL |
|
|
125
|
-
|
|
126
|
-
## ColumnBuilder
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnMeta> {
|
|
130
|
-
constructor(readonly meta: TMeta);
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Column definition builder with fluent API for type modifiers.
|
|
135
|
-
|
|
136
|
-
### Methods
|
|
137
|
-
|
|
138
|
-
| Method | Signature | Description |
|
|
139
|
-
|--------|-----------|-------------|
|
|
140
|
-
| `autoIncrement` | `() => ColumnBuilder<TValue, TMeta & { autoIncrement: true }>` | Set auto-increment (INSERT optional) |
|
|
141
|
-
| `nullable` | `() => ColumnBuilder<TValue \| undefined, TMeta & { nullable: true }>` | Allow NULL values |
|
|
142
|
-
| `default` | `(value: TValue) => ColumnBuilder<TValue, TMeta & { default: TValue }>` | Set default value (INSERT optional) |
|
|
143
|
-
| `description` | `(desc: string) => ColumnBuilder<TValue, TMeta & { description: string }>` | Set column description (DDL comment) |
|
|
144
|
-
|
|
145
|
-
## createColumnFactory
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
function createColumnFactory(): ColumnFactory
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Returns a column type factory object. Used inside `TableBuilder.columns()` and `ProcedureBuilder.params()/returns()`.
|
|
152
|
-
|
|
153
|
-
### Factory Methods
|
|
154
|
-
|
|
155
|
-
| Method | Signature | SQL Type | TypeScript Type |
|
|
156
|
-
|--------|-----------|----------|-----------------|
|
|
157
|
-
| `int` | `() => ColumnBuilder<number, ...>` | `INT` | `number` |
|
|
158
|
-
| `bigint` | `() => ColumnBuilder<number, ...>` | `BIGINT` | `number` |
|
|
159
|
-
| `float` | `() => ColumnBuilder<number, ...>` | `FLOAT` | `number` |
|
|
160
|
-
| `double` | `() => ColumnBuilder<number, ...>` | `DOUBLE` | `number` |
|
|
161
|
-
| `decimal` | `(precision, scale?) => ColumnBuilder<number, ...>` | `DECIMAL(p,s)` | `number` |
|
|
162
|
-
| `varchar` | `(length) => ColumnBuilder<string, ...>` | `VARCHAR(n)` | `string` |
|
|
163
|
-
| `char` | `(length) => ColumnBuilder<string, ...>` | `CHAR(n)` | `string` |
|
|
164
|
-
| `text` | `() => ColumnBuilder<string, ...>` | `TEXT` | `string` |
|
|
165
|
-
| `binary` | `() => ColumnBuilder<Bytes, ...>` | `LONGBLOB`/`BYTEA` | `Bytes` |
|
|
166
|
-
| `boolean` | `() => ColumnBuilder<boolean, ...>` | `TINYINT(1)`/`BIT`/`BOOLEAN` | `boolean` |
|
|
167
|
-
| `datetime` | `() => ColumnBuilder<DateTime, ...>` | `DATETIME` | `DateTime` |
|
|
168
|
-
| `date` | `() => ColumnBuilder<DateOnly, ...>` | `DATE` | `DateOnly` |
|
|
169
|
-
| `time` | `() => ColumnBuilder<Time, ...>` | `TIME` | `Time` |
|
|
170
|
-
| `uuid` | `() => ColumnBuilder<Uuid, ...>` | `BINARY(16)`/`UNIQUEIDENTIFIER`/`UUID` | `Uuid` |
|
|
171
|
-
|
|
172
|
-
## IndexBuilder
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
class IndexBuilder<TKeys extends string[]> {
|
|
176
|
-
constructor(readonly meta: {
|
|
177
|
-
columns: TKeys;
|
|
178
|
-
name?: string;
|
|
179
|
-
unique?: boolean;
|
|
180
|
-
orderBy?: { [K in keyof TKeys]: "ASC" | "DESC" };
|
|
181
|
-
description?: string;
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Methods
|
|
187
|
-
|
|
188
|
-
| Method | Signature | Description |
|
|
189
|
-
|--------|-----------|-------------|
|
|
190
|
-
| `name` | `(name: string) => IndexBuilder<TKeys>` | Set custom index name |
|
|
191
|
-
| `unique` | `() => IndexBuilder<TKeys>` | Mark as unique index |
|
|
192
|
-
| `orderBy` | `(...orderBy: ("ASC" \| "DESC")[]) => IndexBuilder<TKeys>` | Set sort order per column |
|
|
193
|
-
| `description` | `(desc: string) => IndexBuilder<TKeys>` | Set index description |
|
|
194
|
-
|
|
195
|
-
## createIndexFactory
|
|
196
|
-
|
|
197
|
-
```typescript
|
|
198
|
-
function createIndexFactory<TColumnKey extends string>(): { index: (...columns: TColumnKey[]) => IndexBuilder }
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
Returns an index factory. Used inside `TableBuilder.indexes()`.
|
|
202
|
-
|
|
203
|
-
## ForeignKeyBuilder
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
class ForeignKeyBuilder<TOwner extends TableBuilder<any, any>, TTargetFn extends () => TableBuilder<any, any>> {
|
|
207
|
-
constructor(readonly meta: {
|
|
208
|
-
ownerFn: () => TOwner;
|
|
209
|
-
columns: string[];
|
|
210
|
-
targetFn: TTargetFn;
|
|
211
|
-
description?: string;
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
N:1 FK relation builder. Creates an actual DB foreign key constraint.
|
|
217
|
-
|
|
218
|
-
`description` is configured via the factory function's `opts` parameter (3rd argument to `foreignKey()`), not via method chaining. This class has no methods — it is a data holder for relation metadata.
|
|
219
|
-
|
|
220
|
-
## ForeignKeyTargetBuilder
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
class ForeignKeyTargetBuilder<TTargetTableFn extends () => TableBuilder<any, any>, TIsSingle extends boolean> {
|
|
224
|
-
constructor(readonly meta: {
|
|
225
|
-
targetTableFn: TTargetTableFn;
|
|
226
|
-
relationName: string;
|
|
227
|
-
description?: string;
|
|
228
|
-
isSingle?: TIsSingle;
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
1:N FK reverse-reference builder. Loaded as array by default, single object with `{ single: true }` opts.
|
|
234
|
-
|
|
235
|
-
`description` and `single` are configured via the factory function's `opts` parameter (3rd argument to `foreignKeyTarget()`), not via method chaining. Method chaining was removed to prevent TS7022 in complex circular references.
|
|
236
|
-
|
|
237
|
-
This class has no methods — it is a data holder for relation metadata.
|
|
238
|
-
|
|
239
|
-
## RelationKeyBuilder
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
class RelationKeyBuilder<
|
|
243
|
-
TOwner extends TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
244
|
-
TTargetFn extends () => TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
245
|
-
>
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Logical N:1 relation builder (no DB FK constraint). Works with both Tables and Views.
|
|
249
|
-
|
|
250
|
-
`description` is configured via the factory function's `opts` parameter (3rd argument to `relationKey()`), not via method chaining. This class has no methods — it is a data holder for relation metadata.
|
|
251
|
-
|
|
252
|
-
## RelationKeyTargetBuilder
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
class RelationKeyTargetBuilder<
|
|
256
|
-
TTargetTableFn extends () => TableBuilder<any, any> | ViewBuilder<any, any, any>,
|
|
257
|
-
TIsSingle extends boolean,
|
|
258
|
-
>
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Logical 1:N reverse-reference builder (no DB FK constraint). Works with both Tables and Views.
|
|
262
|
-
|
|
263
|
-
`description` and `single` are configured via the factory function's `opts` parameter (3rd argument to `relationKeyTarget()`), not via method chaining.
|
|
264
|
-
|
|
265
|
-
This class has no methods — it is a data holder for relation metadata.
|
|
266
|
-
|
|
267
|
-
## createRelationFactory
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
function createRelationFactory<TOwner, TColumnKey extends string>(
|
|
271
|
-
ownerFn: () => TOwner,
|
|
272
|
-
): RelationFactory
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
Creates a relation factory. For `TableBuilder`: provides `foreignKey`, `foreignKeyTarget`, `relationKey`, `relationKeyTarget`. For `ViewBuilder`: provides only `relationKey`, `relationKeyTarget`.
|
|
276
|
-
|
|
277
|
-
### Factory Methods (Table)
|
|
278
|
-
|
|
279
|
-
| Method | Signature | Description |
|
|
280
|
-
|--------|-----------|-------------|
|
|
281
|
-
| `foreignKey` | `(columns, targetFn, opts?: { description?: string })` | N:1 FK (creates DB constraint) |
|
|
282
|
-
| `foreignKeyTarget` | `(targetTableFn, relationName, opts?: { single?: boolean; description?: string })` | 1:N FK reverse-reference. `{ single: true }` → 1:1 |
|
|
283
|
-
| `relationKey` | `(columns, targetFn, opts?: { description?: string })` | N:1 logical relation (no DB FK) |
|
|
284
|
-
| `relationKeyTarget` | `(targetTableFn, relationName, opts?: { single?: boolean; description?: string })` | 1:N logical reverse-reference. `{ single: true }` → 1:1 |
|
|
285
|
-
|
|
286
|
-
### Factory Methods (View)
|
|
287
|
-
|
|
288
|
-
Only `relationKey` and `relationKeyTarget` are available for ViewBuilder.
|