@simplysm/orm-common 13.0.96 → 13.0.98
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 +209 -54
- package/docs/core.md +225 -0
- package/docs/expression.md +296 -0
- package/docs/query-builder.md +196 -0
- package/docs/queryable.md +578 -0
- package/docs/schema-builders.md +415 -0
- package/docs/types.md +445 -0
- package/docs/utilities.md +122 -0
- package/package.json +2 -2
- package/docs/ddl.md +0 -300
- package/docs/query.md +0 -644
- package/docs/schema.md +0 -325
package/docs/types.md
ADDED
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
# Types
|
|
2
|
+
|
|
3
|
+
TypeScript types for dialects, queries, expressions, columns, and results.
|
|
4
|
+
|
|
5
|
+
Source: `src/types/db.ts`, `src/types/column.ts`, `src/types/expr.ts`, `src/types/query-def.ts`
|
|
6
|
+
|
|
7
|
+
## Database Types
|
|
8
|
+
|
|
9
|
+
Source: `src/types/db.ts`
|
|
10
|
+
|
|
11
|
+
### Dialect
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
type Dialect = "mysql" | "mssql" | "postgresql";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- `mysql`: MySQL 8.0.14+
|
|
18
|
+
- `mssql`: Microsoft SQL Server 2012+
|
|
19
|
+
- `postgresql`: PostgreSQL 9.0+
|
|
20
|
+
|
|
21
|
+
### dialects
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
const dialects: Dialect[] = ["mysql", "mssql", "postgresql"];
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### QueryBuildResult
|
|
28
|
+
|
|
29
|
+
Return type of `QueryBuilderBase.build()`.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
interface QueryBuildResult {
|
|
33
|
+
/** Built SQL string */
|
|
34
|
+
sql: string;
|
|
35
|
+
/** Result set index to fetch results from (default: 0) */
|
|
36
|
+
resultSetIndex?: number;
|
|
37
|
+
/** Extract every Nth result set from multiple results */
|
|
38
|
+
resultSetStride?: number;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### IsolationLevel
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
type IsolationLevel =
|
|
46
|
+
| "READ_UNCOMMITTED"
|
|
47
|
+
| "READ_COMMITTED"
|
|
48
|
+
| "REPEATABLE_READ"
|
|
49
|
+
| "SERIALIZABLE";
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### DataRecord
|
|
53
|
+
|
|
54
|
+
Recursive record type for query results, supporting nested relations.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
type DataRecord = {
|
|
58
|
+
[key: string]: ColumnPrimitive | DataRecord | DataRecord[];
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### DbContextExecutor
|
|
63
|
+
|
|
64
|
+
Interface for actual DB connection and query execution. Implemented by `NodeDbContextExecutor` (server) or service client executors.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
interface DbContextExecutor {
|
|
68
|
+
connect(): Promise<void>;
|
|
69
|
+
close(): Promise<void>;
|
|
70
|
+
beginTransaction(isolationLevel?: IsolationLevel): Promise<void>;
|
|
71
|
+
commitTransaction(): Promise<void>;
|
|
72
|
+
rollbackTransaction(): Promise<void>;
|
|
73
|
+
executeDefs<T = DataRecord>(
|
|
74
|
+
defs: QueryDef[],
|
|
75
|
+
resultMetas?: (ResultMeta | undefined)[],
|
|
76
|
+
): Promise<T[][]>;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### ResultMeta
|
|
81
|
+
|
|
82
|
+
Metadata for query result transformation (type parsing and JOIN nesting).
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
interface ResultMeta {
|
|
86
|
+
/** Column name -> ColumnPrimitiveStr mapping */
|
|
87
|
+
columns: Record<string, ColumnPrimitiveStr>;
|
|
88
|
+
/** JOIN alias -> single/array indicator */
|
|
89
|
+
joins: Record<string, { isSingle: boolean }>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Migration
|
|
94
|
+
|
|
95
|
+
Database migration definition.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
interface Migration {
|
|
99
|
+
name: string;
|
|
100
|
+
up: (db: DbContextBase & DbContextDdlMethods) => Promise<void>;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Example:**
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const migrations: Migration[] = [
|
|
108
|
+
{
|
|
109
|
+
name: "20260105_001_create_user_table",
|
|
110
|
+
up: async (db) => {
|
|
111
|
+
await db.createTable(User);
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Column Types
|
|
120
|
+
|
|
121
|
+
Source: `src/types/column.ts`
|
|
122
|
+
|
|
123
|
+
### DataType
|
|
124
|
+
|
|
125
|
+
SQL data type definition (discriminated union).
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
type DataType =
|
|
129
|
+
| { type: "int" }
|
|
130
|
+
| { type: "bigint" }
|
|
131
|
+
| { type: "float" }
|
|
132
|
+
| { type: "double" }
|
|
133
|
+
| { type: "decimal"; precision: number; scale?: number }
|
|
134
|
+
| { type: "varchar"; length: number }
|
|
135
|
+
| { type: "char"; length: number }
|
|
136
|
+
| { type: "text" }
|
|
137
|
+
| { type: "binary" }
|
|
138
|
+
| { type: "boolean" }
|
|
139
|
+
| { type: "datetime" }
|
|
140
|
+
| { type: "date" }
|
|
141
|
+
| { type: "time" }
|
|
142
|
+
| { type: "uuid" };
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### ColumnPrimitiveMap
|
|
146
|
+
|
|
147
|
+
TypeScript type name to actual type mapping.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
type ColumnPrimitiveMap = {
|
|
151
|
+
string: string;
|
|
152
|
+
number: number;
|
|
153
|
+
boolean: boolean;
|
|
154
|
+
DateTime: DateTime;
|
|
155
|
+
DateOnly: DateOnly;
|
|
156
|
+
Time: Time;
|
|
157
|
+
Uuid: Uuid;
|
|
158
|
+
Bytes: Bytes;
|
|
159
|
+
};
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### ColumnPrimitiveStr
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
type ColumnPrimitiveStr = keyof ColumnPrimitiveMap;
|
|
166
|
+
// "string" | "number" | "boolean" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Bytes"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### ColumnPrimitive
|
|
170
|
+
|
|
171
|
+
All primitive types that can be stored in columns. `undefined` represents NULL.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
type ColumnPrimitive = ColumnPrimitiveMap[ColumnPrimitiveStr] | undefined;
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### ColumnMeta
|
|
178
|
+
|
|
179
|
+
Column metadata generated by `ColumnBuilder`.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
interface ColumnMeta {
|
|
183
|
+
type: ColumnPrimitiveStr;
|
|
184
|
+
dataType: DataType;
|
|
185
|
+
autoIncrement?: boolean;
|
|
186
|
+
nullable?: boolean;
|
|
187
|
+
default?: ColumnPrimitive;
|
|
188
|
+
description?: string;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### dataTypeStrToColumnPrimitiveStr
|
|
193
|
+
|
|
194
|
+
SQL DataType type string to TypeScript type name mapping.
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const dataTypeStrToColumnPrimitiveStr: {
|
|
198
|
+
int: "number";
|
|
199
|
+
bigint: "number";
|
|
200
|
+
float: "number";
|
|
201
|
+
double: "number";
|
|
202
|
+
decimal: "number";
|
|
203
|
+
varchar: "string";
|
|
204
|
+
char: "string";
|
|
205
|
+
text: "string";
|
|
206
|
+
binary: "Bytes";
|
|
207
|
+
boolean: "boolean";
|
|
208
|
+
datetime: "DateTime";
|
|
209
|
+
date: "DateOnly";
|
|
210
|
+
time: "Time";
|
|
211
|
+
uuid: "Uuid";
|
|
212
|
+
};
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### InferColumnPrimitiveFromDataType
|
|
216
|
+
|
|
217
|
+
Infer TypeScript type from `DataType`.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
type InferColumnPrimitiveFromDataType<TDataType extends DataType> =
|
|
221
|
+
ColumnPrimitiveMap[(typeof dataTypeStrToColumnPrimitiveStr)[TDataType["type"]]];
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### inferColumnPrimitiveStr (function)
|
|
225
|
+
|
|
226
|
+
Infer `ColumnPrimitiveStr` from a runtime value.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
function inferColumnPrimitiveStr(value: ColumnPrimitive): ColumnPrimitiveStr;
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Expression Types
|
|
235
|
+
|
|
236
|
+
Source: `src/types/expr.ts`
|
|
237
|
+
|
|
238
|
+
### DateUnit
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
type DateUnit = "year" | "month" | "day" | "hour" | "minute" | "second";
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Expr (union type)
|
|
245
|
+
|
|
246
|
+
Discriminated union of all expression AST node types. Used in `select()`, `orderBy()`, etc.
|
|
247
|
+
|
|
248
|
+
| Category | Types |
|
|
249
|
+
|----------|-------|
|
|
250
|
+
| Value | `ExprColumn`, `ExprValue`, `ExprRaw` |
|
|
251
|
+
| String | `ExprConcat`, `ExprLeft`, `ExprRight`, `ExprTrim`, `ExprPadStart`, `ExprReplace`, `ExprUpper`, `ExprLower`, `ExprLength`, `ExprByteLength`, `ExprSubstring`, `ExprIndexOf` |
|
|
252
|
+
| Numeric | `ExprAbs`, `ExprRound`, `ExprCeil`, `ExprFloor` |
|
|
253
|
+
| Date | `ExprYear`, `ExprMonth`, `ExprDay`, `ExprHour`, `ExprMinute`, `ExprSecond`, `ExprIsoWeek`, `ExprIsoWeekStartDate`, `ExprIsoYearMonth`, `ExprDateDiff`, `ExprDateAdd`, `ExprFormatDate` |
|
|
254
|
+
| Condition | `ExprCoalesce`, `ExprNullIf`, `ExprIs`, `ExprSwitch`, `ExprIf` |
|
|
255
|
+
| Aggregate | `ExprCount`, `ExprSum`, `ExprAvg`, `ExprMax`, `ExprMin` |
|
|
256
|
+
| Other | `ExprGreatest`, `ExprLeast`, `ExprRowNum`, `ExprRandom`, `ExprCast` |
|
|
257
|
+
| Window | `ExprWindow` |
|
|
258
|
+
| System | `ExprSubquery` |
|
|
259
|
+
|
|
260
|
+
### WhereExpr (union type)
|
|
261
|
+
|
|
262
|
+
Subset of `Expr` for WHERE clauses (comparison + logical operators).
|
|
263
|
+
|
|
264
|
+
| Category | Types |
|
|
265
|
+
|----------|-------|
|
|
266
|
+
| Comparison | `ExprEq`, `ExprGt`, `ExprLt`, `ExprGte`, `ExprLte`, `ExprBetween`, `ExprIsNull`, `ExprLike`, `ExprRegexp`, `ExprIn`, `ExprInQuery`, `ExprExists` |
|
|
267
|
+
| Logical | `ExprNot`, `ExprAnd`, `ExprOr` |
|
|
268
|
+
|
|
269
|
+
### Individual Expr Interfaces
|
|
270
|
+
|
|
271
|
+
Each expression type is a simple interface with a `type` discriminant:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface ExprColumn { type: "column"; path: string[]; }
|
|
275
|
+
interface ExprValue { type: "value"; value: ColumnPrimitive; }
|
|
276
|
+
interface ExprRaw { type: "raw"; sql: string; params: Expr[]; }
|
|
277
|
+
interface ExprEq { type: "eq"; source: Expr; target: Expr; }
|
|
278
|
+
interface ExprGt { type: "gt"; source: Expr; target: Expr; }
|
|
279
|
+
// ... etc.
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Window Function Types
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
type WinFn =
|
|
286
|
+
| WinFnRowNumber | WinFnRank | WinFnDenseRank | WinFnNtile
|
|
287
|
+
| WinFnLag | WinFnLead | WinFnFirstValue | WinFnLastValue
|
|
288
|
+
| WinFnSum | WinFnAvg | WinFnCount | WinFnMin | WinFnMax;
|
|
289
|
+
|
|
290
|
+
interface WinSpec {
|
|
291
|
+
partitionBy?: Expr[];
|
|
292
|
+
orderBy?: [Expr, ("ASC" | "DESC")?][];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
interface ExprWindow {
|
|
296
|
+
type: "window";
|
|
297
|
+
fn: WinFn;
|
|
298
|
+
spec: WinSpec;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Query Definition Types
|
|
305
|
+
|
|
306
|
+
Source: `src/types/query-def.ts`
|
|
307
|
+
|
|
308
|
+
### QueryDefObjectName
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
interface QueryDefObjectName {
|
|
312
|
+
database?: string;
|
|
313
|
+
schema?: string;
|
|
314
|
+
name: string;
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
DBMS-specific namespaces:
|
|
319
|
+
- MySQL: `database.name` (schema ignored)
|
|
320
|
+
- MSSQL: `database.schema.name` (schema defaults to dbo)
|
|
321
|
+
- PostgreSQL: `schema.name` (database is for connection only)
|
|
322
|
+
|
|
323
|
+
### QueryDef (union type)
|
|
324
|
+
|
|
325
|
+
Union of all query definition types:
|
|
326
|
+
|
|
327
|
+
**DML:** `SelectQueryDef`, `InsertQueryDef`, `InsertIfNotExistsQueryDef`, `InsertIntoQueryDef`, `UpdateQueryDef`, `DeleteQueryDef`, `UpsertQueryDef`
|
|
328
|
+
|
|
329
|
+
**DDL - Schema:** `ClearSchemaQueryDef`
|
|
330
|
+
|
|
331
|
+
**DDL - Table:** `CreateTableQueryDef`, `DropTableQueryDef`, `RenameTableQueryDef`, `TruncateQueryDef`
|
|
332
|
+
|
|
333
|
+
**DDL - Column:** `AddColumnQueryDef`, `DropColumnQueryDef`, `ModifyColumnQueryDef`, `RenameColumnQueryDef`
|
|
334
|
+
|
|
335
|
+
**DDL - Constraint:** `DropPrimaryKeyQueryDef`, `AddPrimaryKeyQueryDef`, `AddForeignKeyQueryDef`, `DropForeignKeyQueryDef`, `AddIndexQueryDef`, `DropIndexQueryDef`
|
|
336
|
+
|
|
337
|
+
**DDL - View/Procedure:** `CreateViewQueryDef`, `DropViewQueryDef`, `CreateProcQueryDef`, `DropProcQueryDef`, `ExecProcQueryDef`
|
|
338
|
+
|
|
339
|
+
**Utils:** `SwitchFkQueryDef`
|
|
340
|
+
|
|
341
|
+
**Meta:** `SchemaExistsQueryDef`
|
|
342
|
+
|
|
343
|
+
### SelectQueryDef
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
interface SelectQueryDef {
|
|
347
|
+
type: "select";
|
|
348
|
+
from?: QueryDefObjectName | SelectQueryDef | SelectQueryDef[] | string;
|
|
349
|
+
as: string;
|
|
350
|
+
select?: Record<string, Expr>;
|
|
351
|
+
distinct?: boolean;
|
|
352
|
+
top?: number;
|
|
353
|
+
lock?: boolean;
|
|
354
|
+
where?: WhereExpr[];
|
|
355
|
+
joins?: SelectQueryDefJoin[];
|
|
356
|
+
orderBy?: [Expr, ("ASC" | "DESC")?][];
|
|
357
|
+
limit?: [number, number];
|
|
358
|
+
groupBy?: Expr[];
|
|
359
|
+
having?: WhereExpr[];
|
|
360
|
+
with?: { name: string; base: SelectQueryDef; recursive: SelectQueryDef };
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### SelectQueryDefJoin
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
interface SelectQueryDefJoin extends SelectQueryDef {
|
|
368
|
+
isSingle?: boolean;
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### InsertQueryDef
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
interface InsertQueryDef {
|
|
376
|
+
type: "insert";
|
|
377
|
+
table: QueryDefObjectName;
|
|
378
|
+
records: Record<string, ColumnPrimitive>[];
|
|
379
|
+
overrideIdentity?: boolean;
|
|
380
|
+
output?: CudOutputDef;
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### UpdateQueryDef
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
interface UpdateQueryDef {
|
|
388
|
+
type: "update";
|
|
389
|
+
table: QueryDefObjectName;
|
|
390
|
+
as: string;
|
|
391
|
+
record: Record<string, Expr>;
|
|
392
|
+
top?: number;
|
|
393
|
+
where?: WhereExpr[];
|
|
394
|
+
joins?: SelectQueryDefJoin[];
|
|
395
|
+
limit?: [number, number];
|
|
396
|
+
output?: CudOutputDef;
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### DeleteQueryDef
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
interface DeleteQueryDef {
|
|
404
|
+
type: "delete";
|
|
405
|
+
table: QueryDefObjectName;
|
|
406
|
+
as: string;
|
|
407
|
+
top?: number;
|
|
408
|
+
where?: WhereExpr[];
|
|
409
|
+
joins?: SelectQueryDefJoin[];
|
|
410
|
+
limit?: [number, number];
|
|
411
|
+
output?: CudOutputDef;
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### UpsertQueryDef
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
interface UpsertQueryDef {
|
|
419
|
+
type: "upsert";
|
|
420
|
+
table: QueryDefObjectName;
|
|
421
|
+
existsSelectQuery: SelectQueryDef;
|
|
422
|
+
insertRecord: Record<string, Expr>;
|
|
423
|
+
updateRecord: Record<string, Expr>;
|
|
424
|
+
overrideIdentity?: boolean;
|
|
425
|
+
output?: CudOutputDef;
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### CudOutputDef
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
interface CudOutputDef {
|
|
433
|
+
columns: string[];
|
|
434
|
+
pkColNames: string[];
|
|
435
|
+
aiColName?: string;
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### DDL_TYPES
|
|
440
|
+
|
|
441
|
+
Constant array of all DDL type strings (for blocking DDL within transactions).
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
const DDL_TYPES: readonly DdlType[];
|
|
445
|
+
```
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Utilities
|
|
2
|
+
|
|
3
|
+
Result parsing helpers for transforming raw database output to typed TypeScript objects.
|
|
4
|
+
|
|
5
|
+
Source: `src/utils/result-parser.ts`
|
|
6
|
+
|
|
7
|
+
## parseQueryResult
|
|
8
|
+
|
|
9
|
+
Transform raw DB query results to TypeScript objects via `ResultMeta`. Handles type parsing, flat-to-nested transformation, and JOIN grouping.
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
async function parseQueryResult<TRecord>(
|
|
13
|
+
rawResults: Record<string, unknown>[],
|
|
14
|
+
meta: ResultMeta,
|
|
15
|
+
): Promise<TRecord[] | undefined>;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Parameters:**
|
|
19
|
+
|
|
20
|
+
- `rawResults` -- Raw result array from the database driver (flat key-value records)
|
|
21
|
+
- `meta` -- Type transformation and JOIN structure information (`ResultMeta`)
|
|
22
|
+
|
|
23
|
+
**Returns:**
|
|
24
|
+
|
|
25
|
+
- Type-transformed and nested result array, or `undefined` if input is empty or all records are empty after parsing
|
|
26
|
+
|
|
27
|
+
**Behavior:**
|
|
28
|
+
|
|
29
|
+
- **Type parsing** -- Converts raw values (strings from DB) to proper TypeScript types based on `meta.columns` mapping (e.g., `"1"` to `1` for number, `"2026-01-15T10:00:00Z"` to `DateTime`)
|
|
30
|
+
- **Flat-to-nested** -- Transforms dot-notation keys to nested objects (e.g., `"posts.id"` becomes `{ posts: { id: ... } }`)
|
|
31
|
+
- **JOIN grouping** -- Groups rows by non-JOIN columns, collecting JOIN data into arrays (1:N) or single objects (1:1)
|
|
32
|
+
- **Async** -- Yields to the event loop every 100 records to prevent blocking
|
|
33
|
+
- **Empty handling** -- Returns `undefined` for empty input or when all parsed records are empty objects
|
|
34
|
+
|
|
35
|
+
### Example: Simple Type Parsing
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const raw = [
|
|
39
|
+
{ id: "1", name: "Alice", createdAt: "2026-01-07T10:00:00.000Z" },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const meta: ResultMeta = {
|
|
43
|
+
columns: { id: "number", name: "string", createdAt: "DateTime" },
|
|
44
|
+
joins: {},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const result = await parseQueryResult(raw, meta);
|
|
48
|
+
// [{ id: 1, name: "Alice", createdAt: DateTime("2026-01-07T10:00:00.000Z") }]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Example: JOIN Result Nesting
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const raw = [
|
|
55
|
+
{ id: 1, name: "User1", "posts.id": 10, "posts.title": "Post1" },
|
|
56
|
+
{ id: 1, name: "User1", "posts.id": 11, "posts.title": "Post2" },
|
|
57
|
+
{ id: 2, name: "User2", "posts.id": 20, "posts.title": "Post3" },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const meta: ResultMeta = {
|
|
61
|
+
columns: {
|
|
62
|
+
id: "number",
|
|
63
|
+
name: "string",
|
|
64
|
+
"posts.id": "number",
|
|
65
|
+
"posts.title": "string",
|
|
66
|
+
},
|
|
67
|
+
joins: {
|
|
68
|
+
posts: { isSingle: false },
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const result = await parseQueryResult(raw, meta);
|
|
73
|
+
// [
|
|
74
|
+
// { id: 1, name: "User1", posts: [{ id: 10, title: "Post1" }, { id: 11, title: "Post2" }] },
|
|
75
|
+
// { id: 2, name: "User2", posts: [{ id: 20, title: "Post3" }] },
|
|
76
|
+
// ]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Example: Single JOIN (1:1)
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const raw = [
|
|
83
|
+
{ id: 1, title: "Post1", "author.id": 10, "author.name": "Alice" },
|
|
84
|
+
{ id: 2, title: "Post2", "author.id": 10, "author.name": "Alice" },
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const meta: ResultMeta = {
|
|
88
|
+
columns: {
|
|
89
|
+
id: "number",
|
|
90
|
+
title: "string",
|
|
91
|
+
"author.id": "number",
|
|
92
|
+
"author.name": "string",
|
|
93
|
+
},
|
|
94
|
+
joins: {
|
|
95
|
+
author: { isSingle: true },
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const result = await parseQueryResult(raw, meta);
|
|
100
|
+
// [
|
|
101
|
+
// { id: 1, title: "Post1", author: { id: 10, name: "Alice" } },
|
|
102
|
+
// { id: 2, title: "Post2", author: { id: 10, name: "Alice" } },
|
|
103
|
+
// ]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Type Parsing Rules
|
|
109
|
+
|
|
110
|
+
| ColumnPrimitiveStr | Input | Output |
|
|
111
|
+
|--------------------|-------|--------|
|
|
112
|
+
| `"number"` | `"123"` / `123` | `123` (throws if NaN) |
|
|
113
|
+
| `"string"` | any | `String(value)` |
|
|
114
|
+
| `"boolean"` | `0` / `"0"` / `false` | `false` |
|
|
115
|
+
| `"boolean"` | `1` / `"1"` / `true` | `true` |
|
|
116
|
+
| `"DateTime"` | ISO string | `DateTime.parse(value)` |
|
|
117
|
+
| `"DateOnly"` | date string | `DateOnly.parse(value)` |
|
|
118
|
+
| `"Time"` | time string | `Time.parse(value)` |
|
|
119
|
+
| `"Uuid"` | `Uint8Array` / string | `Uuid.fromBytes(value)` / `new Uuid(value)` |
|
|
120
|
+
| `"Bytes"` | `Uint8Array` / hex string | as-is / `bytes.fromHex(value)` |
|
|
121
|
+
|
|
122
|
+
`null` and `undefined` values are returned as `undefined` (keys are omitted from the result).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/orm-common",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.98",
|
|
4
4
|
"description": "Simplysm Package - ORM Module (common)",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -20,6 +20,6 @@
|
|
|
20
20
|
],
|
|
21
21
|
"sideEffects": false,
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@simplysm/core-common": "13.0.
|
|
23
|
+
"@simplysm/core-common": "13.0.98"
|
|
24
24
|
}
|
|
25
25
|
}
|