@simplysm/orm-common 14.0.1 → 14.0.4
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 +135 -0
- package/dist/exec/queryable.js +18 -18
- package/dist/exec/queryable.js.map +1 -1
- package/dist/expr/expr.d.ts +102 -102
- package/dist/expr/expr.js +105 -105
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +17 -17
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +26 -26
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +14 -14
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +67 -67
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +13 -13
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +47 -47
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/factory/relation-builder.d.ts +8 -8
- package/dist/schema/factory/relation-builder.js +9 -9
- package/dist/schema/factory/relation-builder.js.map +1 -1
- package/dist/schema/view-builder.js +2 -2
- package/dist/schema/view-builder.js.map +1 -1
- package/dist/types/column.d.ts +21 -21
- package/dist/types/column.js +5 -5
- package/dist/utils/result-parser.d.ts +11 -11
- package/dist/utils/result-parser.js +48 -48
- package/dist/utils/result-parser.js.map +1 -1
- package/docs/core.md +206 -0
- package/docs/expression.md +217 -0
- package/docs/query-builder.md +126 -0
- package/docs/queryable.md +236 -0
- package/docs/schema-builders.md +352 -0
- package/docs/types.md +501 -0
- package/package.json +7 -3
- package/src/exec/queryable.ts +18 -18
- package/src/expr/expr.ts +105 -105
- package/src/query-builder/mssql/mssql-expr-renderer.ts +17 -17
- package/src/query-builder/mssql/mssql-query-builder.ts +26 -26
- package/src/query-builder/mysql/mysql-expr-renderer.ts +14 -14
- package/src/query-builder/mysql/mysql-query-builder.ts +67 -67
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +13 -13
- package/src/query-builder/postgresql/postgresql-query-builder.ts +47 -47
- package/src/schema/factory/relation-builder.ts +9 -9
- package/src/schema/view-builder.ts +2 -2
- package/src/types/column.ts +23 -23
- package/src/utils/result-parser.ts +49 -49
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Queryable / Executable
|
|
2
|
+
|
|
3
|
+
Type-safe query builder and stored procedure executor.
|
|
4
|
+
|
|
5
|
+
## Queryable
|
|
6
|
+
|
|
7
|
+
Chainable query builder class for constructing SELECT, INSERT, UPDATE, DELETE, and UPSERT queries against tables/views.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
class Queryable<TData extends DataRecord, TFrom extends TableBuilder | never> {
|
|
11
|
+
constructor(readonly meta: QueryableMeta<TData>);
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Type Parameters:**
|
|
16
|
+
|
|
17
|
+
| Parameter | Description |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `TData` | Query result data type |
|
|
20
|
+
| `TFrom` | Source table builder type. `never` for views/subqueries (no CUD operations). |
|
|
21
|
+
|
|
22
|
+
### SELECT / Options
|
|
23
|
+
|
|
24
|
+
| Method | Signature | Description |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `select` | `(fn: (cols) => R) => Queryable<UnwrapQueryableRecord<R>, never>` | Project specific columns. Replaces the default column set. |
|
|
27
|
+
| `distinct` | `() => Queryable<TData, never>` | Apply DISTINCT to remove duplicate rows. |
|
|
28
|
+
| `lock` | `() => Queryable<TData, TFrom>` | Apply row lock (FOR UPDATE) within a transaction. |
|
|
29
|
+
|
|
30
|
+
### Filtering
|
|
31
|
+
|
|
32
|
+
| Method | Signature | Description |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `where` | `(predicate: (cols) => WhereExprUnit[]) => Queryable<TData, TFrom>` | Add WHERE conditions. Multiple calls are combined with AND. |
|
|
35
|
+
| `search` | `(fn: (cols) => ExprUnit<string>[], searchText: string) => Queryable<TData, TFrom>` | Full-text search across columns. Supports `+required`, `-excluded`, `"exact phrase"`, and `*` wildcards. See `parseSearchQuery`. |
|
|
36
|
+
|
|
37
|
+
### Sorting / Pagination
|
|
38
|
+
|
|
39
|
+
| Method | Signature | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `orderBy` | `(fn: (cols) => ExprUnit, orderBy?: "ASC" \| "DESC") => Queryable<TData, TFrom>` | Add ORDER BY. Multiple calls append in order. Default: ASC. |
|
|
42
|
+
| `top` | `(count: number) => Queryable<TData, TFrom>` | Limit to N rows (works without ORDER BY). |
|
|
43
|
+
| `limit` | `(skip: number, take: number) => Queryable<TData, TFrom>` | Pagination (OFFSET/LIMIT). Requires `orderBy()` first. |
|
|
44
|
+
|
|
45
|
+
### Grouping
|
|
46
|
+
|
|
47
|
+
| Method | Signature | Description |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `groupBy` | `(fn: (cols) => ExprUnit[]) => Queryable<TData, never>` | GROUP BY columns. |
|
|
50
|
+
| `having` | `(predicate: (cols) => WhereExprUnit[]) => Queryable<TData, never>` | HAVING filter (after GROUP BY). |
|
|
51
|
+
|
|
52
|
+
### JOIN
|
|
53
|
+
|
|
54
|
+
| Method | Signature | Description |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `join` | `(as, fn: (qr, cols) => Queryable<R>) => Queryable<TData & { [as]?: R[] }, TFrom>` | LEFT OUTER JOIN (1:N). Result added as array property. |
|
|
57
|
+
| `joinSingle` | `(as, fn: (qr, cols) => Queryable<R>) => Queryable<TData & { [as]?: R }, TFrom>` | LEFT OUTER JOIN (N:1 or 1:1). Result added as single object. |
|
|
58
|
+
| `include` | `(fn: (item: PathProxy) => PathProxy) => Queryable<TData, TFrom>` | Auto-JOIN based on FK/relation definitions. Supports nested paths (e.g., `p.author.company`). |
|
|
59
|
+
|
|
60
|
+
### Subquery / UNION / Recursive
|
|
61
|
+
|
|
62
|
+
| Method | Signature | Description |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `wrap` | `() => Queryable<TData, never>` | Wrap current query as subquery. Required before `count()` after `distinct()`/`groupBy()`. |
|
|
65
|
+
| `static union` | `(...queries: Queryable[]) => Queryable<TData, never>` | Combine 2+ Queryables with UNION. |
|
|
66
|
+
| `recursive` | `(fn: (cte: RecursiveQueryable) => Queryable) => Queryable<TData, never>` | Generate a recursive CTE (WITH RECURSIVE). For hierarchical data. |
|
|
67
|
+
|
|
68
|
+
### Execution (SELECT)
|
|
69
|
+
|
|
70
|
+
| Method | Signature | Description |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `execute` | `() => Promise<TData[]>` | Execute SELECT and return result array. |
|
|
73
|
+
| `single` | `() => Promise<TData \| undefined>` | Return single result. Throws if more than one. |
|
|
74
|
+
| `first` | `() => Promise<TData \| undefined>` | Return first result (even if multiple exist). |
|
|
75
|
+
| `count` | `(fn?) => Promise<number>` | Return row count. Throws after `distinct()`/`groupBy()` (use `wrap()` first). |
|
|
76
|
+
| `exists` | `() => Promise<boolean>` | Check if any matching data exists. |
|
|
77
|
+
|
|
78
|
+
### Execution (INSERT)
|
|
79
|
+
|
|
80
|
+
| Method | Signature | Description |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `insert` | `(records: TFrom["$inferInsert"][]) => Promise<void>` | Insert records. Auto-chunks at 1000 for MSSQL. |
|
|
83
|
+
| `insert` | `(records, outputColumns: K[]) => Promise<Pick<...>[]>` | Insert and return specified output columns. |
|
|
84
|
+
| `insertIfNotExists` | `(record: TFrom["$inferInsert"]) => Promise<void>` | Insert only if WHERE condition matches no rows. |
|
|
85
|
+
| `insertIfNotExists` | `(record, outputColumns: K[]) => Promise<Pick<...>>` | Insert if not exists and return output columns. |
|
|
86
|
+
| `insertInto` | `(targetTable: TableBuilder) => Promise<void>` | INSERT INTO ... SELECT from current query. |
|
|
87
|
+
| `insertInto` | `(targetTable, outputColumns: K[]) => Promise<Pick<...>[]>` | INSERT INTO with output columns. |
|
|
88
|
+
|
|
89
|
+
### Execution (UPDATE / DELETE)
|
|
90
|
+
|
|
91
|
+
| Method | Signature | Description |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `update` | `(recordFwd: (cols) => WriteRecord) => Promise<void>` | Update matching records. Use `expr.val()` for literal values. |
|
|
94
|
+
| `update` | `(recordFwd, outputColumns: K[]) => Promise<Pick<...>[]>` | Update and return output columns. |
|
|
95
|
+
| `delete` | `() => Promise<void>` | Delete matching records. |
|
|
96
|
+
| `delete` | `(outputColumns: K[]) => Promise<Pick<...>[]>` | Delete and return output columns. |
|
|
97
|
+
|
|
98
|
+
### Execution (UPSERT)
|
|
99
|
+
|
|
100
|
+
| Method | Signature | Description |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| `upsert` | `(updateFn: (cols) => WriteRecord) => Promise<void>` | Update if exists, insert otherwise (same data). |
|
|
103
|
+
| `upsert` | `(updateFn, insertFn) => Promise<void>` | Update/insert with different data. |
|
|
104
|
+
| `upsert` | `(updateFn, insertFn?, outputColumns?: K[]) => Promise<Pick<...>[] \| void>` | Upsert with optional output columns. |
|
|
105
|
+
|
|
106
|
+
### QueryDef Generators
|
|
107
|
+
|
|
108
|
+
Each execution method has a corresponding `get*QueryDef` method:
|
|
109
|
+
|
|
110
|
+
- `getSelectQueryDef(): SelectQueryDef`
|
|
111
|
+
- `getInsertQueryDef(records, outputColumns?): InsertQueryDef`
|
|
112
|
+
- `getInsertIfNotExistsQueryDef(record, outputColumns?): InsertIfNotExistsQueryDef`
|
|
113
|
+
- `getInsertIntoQueryDef(targetTable, outputColumns?): InsertIntoQueryDef`
|
|
114
|
+
- `getUpdateQueryDef(recordFwd, outputColumns?): UpdateQueryDef`
|
|
115
|
+
- `getDeleteQueryDef(outputColumns?): DeleteQueryDef`
|
|
116
|
+
- `getUpsertQueryDef(updateRecordFn, insertRecordFn, outputColumns?): UpsertQueryDef`
|
|
117
|
+
- `getResultMeta(outputColumns?): ResultMeta`
|
|
118
|
+
|
|
119
|
+
## QueryableRecord
|
|
120
|
+
|
|
121
|
+
Maps data record fields to `ExprUnit` wrappers for type-safe expression building. Nested objects and arrays are recursively mapped.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
type QueryableRecord<TData extends DataRecord> = {
|
|
125
|
+
[K in keyof TData]: TData[K] extends ColumnPrimitive
|
|
126
|
+
? ExprUnit<TData[K]>
|
|
127
|
+
: TData[K] extends (infer U)[]
|
|
128
|
+
? U extends DataRecord ? QueryableRecord<U>[] : never
|
|
129
|
+
: TData[K] extends DataRecord ? QueryableRecord<TData[K]> : never;
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## QueryableWriteRecord
|
|
134
|
+
|
|
135
|
+
Maps data fields to `ExprInput` for write operations (INSERT/UPDATE).
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
type QueryableWriteRecord<TData> = {
|
|
139
|
+
[K in keyof TData]: TData[K] extends ColumnPrimitive ? ExprInput<TData[K]> : never;
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## NullableQueryableRecord
|
|
144
|
+
|
|
145
|
+
Same as `QueryableRecord` but all primitive fields include `| undefined` (for LEFT JOIN null propagation).
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
type NullableQueryableRecord<TData extends DataRecord> = {
|
|
149
|
+
[K in keyof TData]: TData[K] extends ColumnPrimitive
|
|
150
|
+
? ExprUnit<TData[K] | undefined>
|
|
151
|
+
: /* recursive for nested records */;
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## getMatchedPrimaryKeys
|
|
156
|
+
|
|
157
|
+
Returns the primary key columns of a target table matched to foreign key columns.
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
function getMatchedPrimaryKeys(
|
|
161
|
+
fkCols: string[],
|
|
162
|
+
targetTable: TableBuilder<any, any>,
|
|
163
|
+
): string[];
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Executable
|
|
167
|
+
|
|
168
|
+
Stored procedure execution wrapper class.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
class Executable<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord> {
|
|
172
|
+
constructor(db: DbContextBase, builder: ProcedureBuilder<TParams, TReturns>);
|
|
173
|
+
|
|
174
|
+
getExecProcQueryDef(params?: InferColumnExprs<TParams>): ExecProcQueryDef;
|
|
175
|
+
execute(params: InferColumnExprs<TParams>): Promise<InferColumnExprs<TReturns>[][]>;
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Example:**
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
const result = await db.getUserById().execute({ userId: 1n });
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## executable
|
|
186
|
+
|
|
187
|
+
Factory function that creates an `Executable` accessor for a `ProcedureBuilder`.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
function executable<TParams, TReturns>(
|
|
191
|
+
db: DbContextBase,
|
|
192
|
+
builder: ProcedureBuilder<TParams, TReturns>,
|
|
193
|
+
): () => Executable<TParams, TReturns>;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## ParsedSearchQuery
|
|
197
|
+
|
|
198
|
+
Result of `parseSearchQuery()`.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
interface ParsedSearchQuery {
|
|
202
|
+
or: string[]; // OR conditions (LIKE patterns)
|
|
203
|
+
must: string[]; // AND conditions (+ prefix or quoted)
|
|
204
|
+
not: string[]; // NOT conditions (- prefix)
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## parseSearchQuery
|
|
209
|
+
|
|
210
|
+
Parses a search query string into SQL LIKE patterns.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
function parseSearchQuery(searchText: string): ParsedSearchQuery;
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Search Syntax:**
|
|
217
|
+
|
|
218
|
+
| Syntax | Meaning | Example |
|
|
219
|
+
|---|---|---|
|
|
220
|
+
| `term1 term2` | OR (match any) | `apple banana` |
|
|
221
|
+
| `+term` | Required (AND) | `+apple +banana` |
|
|
222
|
+
| `-term` | Excluded (NOT) | `apple -banana` |
|
|
223
|
+
| `"exact phrase"` | Exact phrase match (required) | `"delicious fruit"` |
|
|
224
|
+
| `*` | Wildcard | `app*` produces `app%` |
|
|
225
|
+
|
|
226
|
+
**Escape Sequences:** `\\` (literal `\`), `\*`, `\%`, `\"`, `\+`, `\-`
|
|
227
|
+
|
|
228
|
+
**Example:**
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
parseSearchQuery('apple "delicious fruit" -banana +strawberry');
|
|
232
|
+
// { or: ["%apple%"], must: ["%delicious fruit%", "%strawberry%"], not: ["%banana%"] }
|
|
233
|
+
|
|
234
|
+
parseSearchQuery('app* test');
|
|
235
|
+
// { or: ["app%", "%test%"], must: [], not: [] }
|
|
236
|
+
```
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# Schema Builders
|
|
2
|
+
|
|
3
|
+
Fluent API builders for defining tables, views, procedures, columns, indexes, and relations.
|
|
4
|
+
|
|
5
|
+
## Table (function)
|
|
6
|
+
|
|
7
|
+
Factory function that creates a `TableBuilder`.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
function Table(name: string): TableBuilder<{}, {}>;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## TableBuilder
|
|
14
|
+
|
|
15
|
+
Database table definition builder with fluent API for columns, primary keys, indexes, and relations.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
class TableBuilder<TColumns extends ColumnBuilderRecord, TRelations extends RelationBuilderRecord> {
|
|
19
|
+
readonly $columns: TColumns;
|
|
20
|
+
readonly $relations: TRelations;
|
|
21
|
+
readonly $inferSelect: InferColumns<TColumns> & InferDeepRelations<TRelations>;
|
|
22
|
+
readonly $inferColumns: InferColumns<TColumns>;
|
|
23
|
+
readonly $inferInsert: InferInsertColumns<TColumns>;
|
|
24
|
+
readonly $inferUpdate: InferUpdateColumns<TColumns>;
|
|
25
|
+
|
|
26
|
+
constructor(readonly meta: {
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
database?: string;
|
|
30
|
+
schema?: string;
|
|
31
|
+
columns?: TColumns;
|
|
32
|
+
primaryKey?: (keyof TColumns & string)[];
|
|
33
|
+
relations?: TRelations;
|
|
34
|
+
indexes?: IndexBuilder<(keyof TColumns & string)[]>[];
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Methods
|
|
40
|
+
|
|
41
|
+
| Method | Signature | Description |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| `description` | `(desc: string) => TableBuilder` | Set table description (DDL comment) |
|
|
44
|
+
| `database` | `(db: string) => TableBuilder` | Set database name |
|
|
45
|
+
| `schema` | `(schema: string) => TableBuilder` | Set schema name (MSSQL/PostgreSQL) |
|
|
46
|
+
| `columns` | `(fn: (c: ColumnFactory) => TNewCols) => TableBuilder<TNewCols, TRelations>` | Define columns using the column factory |
|
|
47
|
+
| `primaryKey` | `(...columns: string[]) => TableBuilder` | Set primary key (composite supported) |
|
|
48
|
+
| `indexes` | `(fn: (i: IndexFactory) => IndexBuilder[]) => TableBuilder` | Define indexes |
|
|
49
|
+
| `relations` | `(fn: (r: RelationFactory) => T) => TableBuilder<TColumns, T>` | Define relationships |
|
|
50
|
+
|
|
51
|
+
**Example:**
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const User = Table("User")
|
|
55
|
+
.database("mydb")
|
|
56
|
+
.columns((c) => ({
|
|
57
|
+
id: c.bigint().autoIncrement(),
|
|
58
|
+
name: c.varchar(100),
|
|
59
|
+
email: c.varchar(200).nullable(),
|
|
60
|
+
status: c.varchar(20).default("active"),
|
|
61
|
+
}))
|
|
62
|
+
.primaryKey("id")
|
|
63
|
+
.indexes((i) => [i.index("email").unique()])
|
|
64
|
+
.relations((r) => ({
|
|
65
|
+
posts: r.foreignKeyTarget(() => Post, "author"),
|
|
66
|
+
}));
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## View (function)
|
|
70
|
+
|
|
71
|
+
Factory function that creates a `ViewBuilder`.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
function View(name: string): ViewBuilder<any, {}, {}>;
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## ViewBuilder
|
|
78
|
+
|
|
79
|
+
Database view definition builder.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
class ViewBuilder<TDbContext, TData extends DataRecord, TRelations extends RelationBuilderRecord> {
|
|
83
|
+
readonly $relations: TRelations;
|
|
84
|
+
readonly $inferSelect: TData;
|
|
85
|
+
|
|
86
|
+
constructor(readonly meta: {
|
|
87
|
+
name: string;
|
|
88
|
+
description?: string;
|
|
89
|
+
database?: string;
|
|
90
|
+
schema?: string;
|
|
91
|
+
viewFn?: (db: TDbContext) => Queryable<TData, any>;
|
|
92
|
+
relations?: TRelations;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Methods
|
|
98
|
+
|
|
99
|
+
| Method | Signature | Description |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `description` | `(desc: string) => ViewBuilder` | Set view description |
|
|
102
|
+
| `database` | `(db: string) => ViewBuilder` | Set database name |
|
|
103
|
+
| `schema` | `(schema: string) => ViewBuilder` | Set schema name |
|
|
104
|
+
| `query` | `(viewFn: (db: TDb) => Queryable) => ViewBuilder` | Define view query |
|
|
105
|
+
| `relations` | `(fn: (r: RelationFactory) => T) => ViewBuilder` | Define relationships |
|
|
106
|
+
|
|
107
|
+
**Example:**
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const ActiveUsers = View("ActiveUsers")
|
|
111
|
+
.database("mydb")
|
|
112
|
+
.query((db: MyDb) =>
|
|
113
|
+
db.user()
|
|
114
|
+
.where((u) => [expr.eq(u.status, "active")])
|
|
115
|
+
.select((u) => ({ id: u.id, name: u.name }))
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Procedure (function)
|
|
120
|
+
|
|
121
|
+
Factory function that creates a `ProcedureBuilder`.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
function Procedure(name: string): ProcedureBuilder<never, never>;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## ProcedureBuilder
|
|
128
|
+
|
|
129
|
+
Stored procedure definition builder.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
class ProcedureBuilder<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord> {
|
|
133
|
+
readonly $params: TParams;
|
|
134
|
+
readonly $returns: TReturns;
|
|
135
|
+
|
|
136
|
+
constructor(readonly meta: {
|
|
137
|
+
name: string;
|
|
138
|
+
description?: string;
|
|
139
|
+
database?: string;
|
|
140
|
+
schema?: string;
|
|
141
|
+
params?: TParams;
|
|
142
|
+
returns?: TReturns;
|
|
143
|
+
query?: string;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Methods
|
|
149
|
+
|
|
150
|
+
| Method | Signature | Description |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| `description` | `(desc: string) => ProcedureBuilder` | Set procedure description |
|
|
153
|
+
| `database` | `(db: string) => ProcedureBuilder` | Set database name |
|
|
154
|
+
| `schema` | `(schema: string) => ProcedureBuilder` | Set schema name |
|
|
155
|
+
| `params` | `(fn: (c: ColumnFactory) => T) => ProcedureBuilder<T, TReturns>` | Define input parameters |
|
|
156
|
+
| `returns` | `(fn: (c: ColumnFactory) => T) => ProcedureBuilder<TParams, T>` | Define return columns |
|
|
157
|
+
| `body` | `(sql: string) => ProcedureBuilder` | Set procedure body SQL |
|
|
158
|
+
|
|
159
|
+
**Example:**
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const GetUserById = Procedure("GetUserById")
|
|
163
|
+
.database("mydb")
|
|
164
|
+
.params((c) => ({ userId: c.bigint() }))
|
|
165
|
+
.returns((c) => ({ id: c.bigint(), name: c.varchar(100) }))
|
|
166
|
+
.body("SELECT id, name FROM User WHERE id = userId");
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## ColumnBuilder
|
|
170
|
+
|
|
171
|
+
Column definition builder used inside `TableBuilder.columns()`.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
class ColumnBuilder<TValue extends ColumnPrimitive, TMeta extends ColumnMeta> {
|
|
175
|
+
constructor(readonly meta: TMeta);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Methods
|
|
180
|
+
|
|
181
|
+
| Method | Signature | Description |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| `autoIncrement` | `() => ColumnBuilder` | Set auto-increment. Makes column optional in INSERT. |
|
|
184
|
+
| `nullable` | `() => ColumnBuilder<TValue \| undefined, ...>` | Allow NULL. Adds `undefined` to value type. |
|
|
185
|
+
| `default` | `(value: TValue) => ColumnBuilder` | Set default value. Makes column optional in INSERT. |
|
|
186
|
+
| `description` | `(desc: string) => ColumnBuilder` | Set column description (DDL comment) |
|
|
187
|
+
|
|
188
|
+
## createColumnFactory
|
|
189
|
+
|
|
190
|
+
Returns a column factory object with methods for all supported data types.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
function createColumnFactory(): {
|
|
194
|
+
int(): ColumnBuilder<number, ...>;
|
|
195
|
+
bigint(): ColumnBuilder<number, ...>;
|
|
196
|
+
float(): ColumnBuilder<number, ...>;
|
|
197
|
+
double(): ColumnBuilder<number, ...>;
|
|
198
|
+
decimal(precision: number, scale?: number): ColumnBuilder<number, ...>;
|
|
199
|
+
varchar(length: number): ColumnBuilder<string, ...>;
|
|
200
|
+
char(length: number): ColumnBuilder<string, ...>;
|
|
201
|
+
text(): ColumnBuilder<string, ...>;
|
|
202
|
+
binary(): ColumnBuilder<Bytes, ...>;
|
|
203
|
+
boolean(): ColumnBuilder<boolean, ...>;
|
|
204
|
+
datetime(): ColumnBuilder<DateTime, ...>;
|
|
205
|
+
date(): ColumnBuilder<DateOnly, ...>;
|
|
206
|
+
time(): ColumnBuilder<Time, ...>;
|
|
207
|
+
uuid(): ColumnBuilder<Uuid, ...>;
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## IndexBuilder
|
|
212
|
+
|
|
213
|
+
Index definition builder used inside `TableBuilder.indexes()`.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
class IndexBuilder<TKeys extends string[]> {
|
|
217
|
+
constructor(readonly meta: {
|
|
218
|
+
columns: TKeys;
|
|
219
|
+
name?: string;
|
|
220
|
+
unique?: boolean;
|
|
221
|
+
orderBy?: { [K in keyof TKeys]: "ASC" | "DESC" };
|
|
222
|
+
description?: string;
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Methods
|
|
228
|
+
|
|
229
|
+
| Method | Signature | Description |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| `name` | `(name: string) => IndexBuilder` | Set custom index name |
|
|
232
|
+
| `unique` | `() => IndexBuilder` | Mark as unique index |
|
|
233
|
+
| `orderBy` | `(...orderBy: ("ASC" \| "DESC")[]) => IndexBuilder` | Set column sort order |
|
|
234
|
+
| `description` | `(description: string) => IndexBuilder` | Set index description |
|
|
235
|
+
|
|
236
|
+
## createIndexFactory
|
|
237
|
+
|
|
238
|
+
Returns an index factory with the `index(...columns)` method.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
function createIndexFactory<TColumnKey extends string>(): {
|
|
242
|
+
index<TKeys extends TColumnKey[]>(...columns: TKeys): IndexBuilder<TKeys>;
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## ForeignKeyBuilder
|
|
247
|
+
|
|
248
|
+
Foreign key relation builder (N:1). Creates a real FK constraint in the database.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
class ForeignKeyBuilder<TOwner extends TableBuilder, TTargetFn extends () => TableBuilder> {
|
|
252
|
+
constructor(readonly meta: {
|
|
253
|
+
ownerFn: () => TOwner;
|
|
254
|
+
columns: string[];
|
|
255
|
+
targetFn: TTargetFn;
|
|
256
|
+
description?: string;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
description(desc: string): ForeignKeyBuilder;
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## ForeignKeyTargetBuilder
|
|
264
|
+
|
|
265
|
+
Foreign key reverse-reference builder (1:N). Loaded as array by default, call `.single()` for 1:1.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
class ForeignKeyTargetBuilder<TTargetTableFn extends () => TableBuilder, TIsSingle extends boolean> {
|
|
269
|
+
constructor(readonly meta: {
|
|
270
|
+
targetTableFn: TTargetTableFn;
|
|
271
|
+
relationName: string;
|
|
272
|
+
description?: string;
|
|
273
|
+
isSingle?: TIsSingle;
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
description(desc: string): ForeignKeyTargetBuilder;
|
|
277
|
+
single(): ForeignKeyTargetBuilder<TTargetTableFn, true>;
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## RelationKeyBuilder
|
|
282
|
+
|
|
283
|
+
Logical relation builder (N:1). Same as `ForeignKeyBuilder` but does NOT create a FK constraint in the database. Usable from both Tables and Views.
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
class RelationKeyBuilder<TOwner, TTargetFn extends () => TableBuilder | ViewBuilder> {
|
|
287
|
+
constructor(readonly meta: {
|
|
288
|
+
ownerFn: () => TOwner;
|
|
289
|
+
columns: string[];
|
|
290
|
+
targetFn: TTargetFn;
|
|
291
|
+
description?: string;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
description(desc: string): RelationKeyBuilder;
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## RelationKeyTargetBuilder
|
|
299
|
+
|
|
300
|
+
Logical reverse-reference builder (1:N). Same as `ForeignKeyTargetBuilder` but without FK constraint. Usable from both Tables and Views.
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
class RelationKeyTargetBuilder<TTargetTableFn, TIsSingle extends boolean> {
|
|
304
|
+
constructor(readonly meta: {
|
|
305
|
+
targetTableFn: TTargetTableFn;
|
|
306
|
+
relationName: string;
|
|
307
|
+
description?: string;
|
|
308
|
+
isSingle?: TIsSingle;
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
description(desc: string): RelationKeyTargetBuilder;
|
|
312
|
+
single(): RelationKeyTargetBuilder<TTargetTableFn, true>;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## createRelationFactory
|
|
317
|
+
|
|
318
|
+
Returns a relation factory. Tables get both FK and RelationKey methods; Views get only RelationKey methods.
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
function createRelationFactory<TOwner, TColumnKey extends string>(
|
|
322
|
+
ownerFn: () => TOwner,
|
|
323
|
+
): TOwner extends TableBuilder
|
|
324
|
+
? RelationFkFactory & RelationRkFactory
|
|
325
|
+
: RelationRkFactory;
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Factory methods (Table):**
|
|
329
|
+
|
|
330
|
+
| Method | Description |
|
|
331
|
+
|---|---|
|
|
332
|
+
| `foreignKey(columns, targetFn)` | N:1 FK relation (creates DB constraint) |
|
|
333
|
+
| `foreignKeyTarget(targetTableFn, relationName)` | 1:N FK reverse-reference |
|
|
334
|
+
| `relationKey(columns, targetFn)` | N:1 logical relation (no DB constraint) |
|
|
335
|
+
| `relationKeyTarget(targetTableFn, relationName)` | 1:N logical reverse-reference |
|
|
336
|
+
|
|
337
|
+
## Type Utilities
|
|
338
|
+
|
|
339
|
+
| Type | Description |
|
|
340
|
+
|---|---|
|
|
341
|
+
| `ColumnBuilderRecord` | `Record<string, ColumnBuilder<ColumnPrimitive, ColumnMeta>>` |
|
|
342
|
+
| `RelationBuilderRecord` | `Record<string, ForeignKeyBuilder \| ForeignKeyTargetBuilder \| RelationKeyBuilder \| RelationKeyTargetBuilder>` |
|
|
343
|
+
| `InferColumns<T>` | Infer runtime value types from column builders |
|
|
344
|
+
| `InferColumnExprs<T>` | Infer `ExprInput` types from column builders |
|
|
345
|
+
| `InferInsertColumns<T>` | INSERT type: required fields + optional for autoIncrement/nullable/default |
|
|
346
|
+
| `InferUpdateColumns<T>` | UPDATE type: all fields optional |
|
|
347
|
+
| `RequiredInsertKeys<T>` | Extract required INSERT column keys |
|
|
348
|
+
| `OptionalInsertKeys<T>` | Extract optional INSERT column keys |
|
|
349
|
+
| `DataToColumnBuilderRecord<T>` | Convert data record to column builder record |
|
|
350
|
+
| `ExtractRelationTarget<T>` | Extract target type from FK/RelationKey (single object) |
|
|
351
|
+
| `ExtractRelationTargetResult<T>` | Extract target type from FKTarget/RelationKeyTarget (array or single) |
|
|
352
|
+
| `InferDeepRelations<T>` | Deep relation type inference (all optional) |
|