metal-orm 1.0.58 → 1.0.59
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 +34 -31
- package/dist/index.cjs +1463 -1003
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +148 -129
- package/dist/index.d.ts +148 -129
- package/dist/index.js +1459 -1003
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ddl/schema-generator.ts +44 -1
- package/src/decorators/bootstrap.ts +183 -146
- package/src/decorators/column-decorator.ts +8 -49
- package/src/decorators/decorator-metadata.ts +10 -46
- package/src/decorators/entity.ts +30 -40
- package/src/decorators/relations.ts +30 -56
- package/src/orm/entity-hydration.ts +72 -0
- package/src/orm/entity-meta.ts +13 -11
- package/src/orm/entity-metadata.ts +240 -238
- package/src/orm/entity-relation-cache.ts +39 -0
- package/src/orm/entity-relations.ts +207 -0
- package/src/orm/entity.ts +124 -410
- package/src/orm/execute.ts +4 -4
- package/src/orm/lazy-batch/belongs-to-many.ts +134 -0
- package/src/orm/lazy-batch/belongs-to.ts +108 -0
- package/src/orm/lazy-batch/has-many.ts +69 -0
- package/src/orm/lazy-batch/has-one.ts +68 -0
- package/src/orm/lazy-batch/shared.ts +125 -0
- package/src/orm/lazy-batch.ts +4 -492
- package/src/orm/relations/many-to-many.ts +2 -1
- package/src/query-builder/relation-cte-builder.ts +63 -0
- package/src/query-builder/relation-filter-utils.ts +159 -0
- package/src/query-builder/relation-include-strategies.ts +177 -0
- package/src/query-builder/relation-join-planner.ts +80 -0
- package/src/query-builder/relation-service.ts +119 -479
- package/src/query-builder/relation-types.ts +41 -10
- package/src/query-builder/select/projection-facet.ts +23 -23
- package/src/query-builder/select/select-operations.ts +145 -0
- package/src/query-builder/select.ts +351 -422
- package/src/schema/relation.ts +22 -18
- package/src/schema/table.ts +22 -9
- package/src/schema/types.ts +14 -12
package/README.md
CHANGED
|
@@ -102,9 +102,9 @@ Full docs live in the `docs/` folder:
|
|
|
102
102
|
- **Typed temporal columns**: `col.date()` / `col.datetime()` / `col.timestamp()` default to `string` but accept a generic when your driver returns `Date` (e.g. `col.date<Date>()`).
|
|
103
103
|
- **Fluent query builder** over a real SQL AST
|
|
104
104
|
(`SelectQueryBuilder`, `InsertQueryBuilder`, `UpdateQueryBuilder`, `DeleteQueryBuilder`).
|
|
105
|
-
- **Advanced SQL**: CTEs, aggregates, window functions, subqueries, bitwise operators (`&`, `|`, `^`, `<<`, `>>`), JSON, CASE, EXISTS, and the full SQL function catalog (e.g. `STDDEV`, `VARIANCE`, `LOG2`, `CBRT`, `COALESCE`, `NULLIF`, `GREATEST`, `LEAST`, `IFNULL`, `LOCALTIME`, `LOCALTIMESTAMP`, `AGE`).
|
|
106
|
-
- **Table-valued functions**: use the new `tvf(key, …)` helper when you want portable intents such as `ARRAY_UNNEST`, letting the dialects’ `TableFunctionStrategy` renderers emit dialect-specific syntax (`LATERAL`/`WITH ORDINALITY`, alias validation, quoting, etc.). `fnTable()` remains available as the raw escape hatch when you need to emit a specific SQL function directly.
|
|
107
|
-
- **String helpers**: `lower`, `upper`, `trim`, `ltrim/rtrim`, `concat/concatWs`, `substr/left/right`, `position/instr/locate`, `replace`, `repeat`, `lpad/rpad`, `space`, and more with dialect-aware rendering.
|
|
105
|
+
- **Advanced SQL**: CTEs, aggregates, window functions, subqueries, bitwise operators (`&`, `|`, `^`, `<<`, `>>`), JSON, CASE, EXISTS, and the full SQL function catalog (e.g. `STDDEV`, `VARIANCE`, `LOG2`, `CBRT`, `COALESCE`, `NULLIF`, `GREATEST`, `LEAST`, `IFNULL`, `LOCALTIME`, `LOCALTIMESTAMP`, `AGE`).
|
|
106
|
+
- **Table-valued functions**: use the new `tvf(key, …)` helper when you want portable intents such as `ARRAY_UNNEST`, letting the dialects’ `TableFunctionStrategy` renderers emit dialect-specific syntax (`LATERAL`/`WITH ORDINALITY`, alias validation, quoting, etc.). `fnTable()` remains available as the raw escape hatch when you need to emit a specific SQL function directly.
|
|
107
|
+
- **String helpers**: `lower`, `upper`, `trim`, `ltrim/rtrim`, `concat/concatWs`, `substr/left/right`, `position/instr/locate`, `replace`, `repeat`, `lpad/rpad`, `space`, and more with dialect-aware rendering.
|
|
108
108
|
- **Set operations**: `union`, `unionAll`, `intersect`, `except` across all dialects (ORDER/LIMIT apply to the combined result; hydration is disabled for compound queries so rows are returned as-is without collapsing duplicates).
|
|
109
109
|
- **Expression builders**: `eq`, `and`, `or`, `between`, `inList`, `exists`, `jsonPath`, `caseWhen`, window functions like `rowNumber`, `rank`, `lag`, `lead`, etc., all backed by typed AST nodes.
|
|
110
110
|
- **Relation-aware hydration**: turn flat rows into nested objects (`user.posts`, `user.roles`, etc.) using a hydration plan derived from the AST metadata.
|
|
@@ -231,10 +231,10 @@ todos.columns.done.default = false;
|
|
|
231
231
|
const t = tableRef(todos);
|
|
232
232
|
|
|
233
233
|
// 2) Build a simple query
|
|
234
|
-
const listOpenTodos = selectFrom(todos)
|
|
235
|
-
.select('id', 'title', 'done')
|
|
236
|
-
.where(eq(t.done, false))
|
|
237
|
-
.orderBy(t.id, 'ASC');
|
|
234
|
+
const listOpenTodos = selectFrom(todos)
|
|
235
|
+
.select('id', 'title', 'done')
|
|
236
|
+
.where(eq(t.done, false))
|
|
237
|
+
.orderBy(t.id, 'ASC');
|
|
238
238
|
|
|
239
239
|
// 3) Compile to SQL + params
|
|
240
240
|
const dialect = new MySqlDialect();
|
|
@@ -244,21 +244,21 @@ const { sql, params } = listOpenTodos.compile(dialect);
|
|
|
244
244
|
const connection = await mysql.createConnection({ /* ... */ });
|
|
245
245
|
const [rows] = await connection.execute(sql, params);
|
|
246
246
|
|
|
247
|
-
console.log(rows);
|
|
248
|
-
// [
|
|
249
|
-
// { id: 1, title: 'Write docs', done: 0 },
|
|
250
|
-
// { id: 2, title: 'Ship feature', done: 0 },
|
|
251
|
-
// ]
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
If you keep a reusable array of column names (e.g. shared across helpers or pulled from config), you can spread it into `.select(...)` since the method accepts rest arguments:
|
|
255
|
-
|
|
256
|
-
```ts
|
|
257
|
-
const defaultColumns = ['id', 'title', 'done'] as const;
|
|
258
|
-
const listOpenTodos = selectFrom(todos).select(...defaultColumns);
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
That's it: schema, query, SQL, done.
|
|
247
|
+
console.log(rows);
|
|
248
|
+
// [
|
|
249
|
+
// { id: 1, title: 'Write docs', done: 0 },
|
|
250
|
+
// { id: 2, title: 'Ship feature', done: 0 },
|
|
251
|
+
// ]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
If you keep a reusable array of column names (e.g. shared across helpers or pulled from config), you can spread it into `.select(...)` since the method accepts rest arguments:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
const defaultColumns = ['id', 'title', 'done'] as const;
|
|
258
|
+
const listOpenTodos = selectFrom(todos).select(...defaultColumns);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
That's it: schema, query, SQL, done.
|
|
262
262
|
|
|
263
263
|
If you are using the Level 2 runtime (`OrmSession`), `SelectQueryBuilder` also provides `count(session)` and `executePaged(session, { page, pageSize })` for common pagination patterns.
|
|
264
264
|
|
|
@@ -275,7 +275,7 @@ const listOpenTodos = selectFrom(todos)
|
|
|
275
275
|
.orderBy(t.id, 'ASC');
|
|
276
276
|
```
|
|
277
277
|
|
|
278
|
-
`select`, `include` (with `columns`), `includePick`, `selectColumnsDeep`, the `sel()` helpers for tables, and `esel()` for entities all build typed selection maps without repeating `table.columns.*`. Use those helpers when building query selections and reserve `table.columns.*` for schema definition, relations, or rare cases where you need a column reference outside of a picker. See the [Query Builder docs](./docs/query-builder.md#selection-helpers) for the reference, examples, and best practices for these helpers.
|
|
278
|
+
`select`, `include` (with `columns`), `includePick`, `selectColumnsDeep`, the `sel()` helpers for tables, and `esel()` for entities all build typed selection maps without repeating `table.columns.*`. Use those helpers when building query selections and reserve `table.columns.*` for schema definition, relations, or rare cases where you need a column reference outside of a picker. See the [Query Builder docs](./docs/query-builder.md#selection-helpers) for the reference, examples, and best practices for these helpers.
|
|
279
279
|
|
|
280
280
|
#### Ergonomic column access (opt-in) with `tableRef`
|
|
281
281
|
|
|
@@ -459,17 +459,20 @@ What the runtime gives you:
|
|
|
459
459
|
- Relation tracking (add/remove/sync on collections).
|
|
460
460
|
- Cascades on relations: `'all' | 'persist' | 'remove' | 'link'`.
|
|
461
461
|
- Single flush: `session.commit()` figures out inserts, updates, deletes, and pivot changes.
|
|
462
|
-
- Column pickers to stay DRY: `select` on the root table, `include` (with `columns`) or `includePick` on relations, and `selectColumnsDeep` or the `sel`/`esel` helpers to build typed selection maps without repeating `table.columns.*`.
|
|
462
|
+
- Column pickers to stay DRY: `select` on the root table, `include` (with `columns`) or `includePick` on relations, and `selectColumnsDeep` or the `sel`/`esel` helpers to build typed selection maps without repeating `table.columns.*`.
|
|
463
|
+
- Tip: if you assign relations after `defineTable`, use `setRelations(table, { ... })` so TypeScript can validate `include(..., { columns: [...] })` and pivot columns. See `docs/query-builder.md`.
|
|
463
464
|
|
|
464
465
|
<a id="level-3"></a>
|
|
465
466
|
### Level 3: Decorator entities ✨
|
|
466
467
|
|
|
467
|
-
Finally, you can describe your models with decorators and still use the same runtime and query builder.
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
468
|
+
Finally, you can describe your models with decorators and still use the same runtime and query builder.
|
|
469
|
+
|
|
470
|
+
The decorator layer is built on the TC39 Stage 3 standard (TypeScript 5.6+), so you simply decorate class fields (or accessors if you need custom logic) and the standard `ClassFieldDecoratorContext` keeps a metadata bag on `context.metadata`/`Symbol.metadata`. `@Entity` reads that bag when it runs and builds your `TableDef`s—no `experimentalDecorators`, parameter decorators, or extra polyfills required.
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
import mysql from 'mysql2/promise';
|
|
474
|
+
import {
|
|
475
|
+
Orm,
|
|
473
476
|
OrmSession,
|
|
474
477
|
MySqlDialect,
|
|
475
478
|
col,
|
|
@@ -550,7 +553,7 @@ user.posts.add({ title: 'From decorators' });
|
|
|
550
553
|
await session.commit();
|
|
551
554
|
```
|
|
552
555
|
|
|
553
|
-
Tip: to keep selections terse, use `select`, `include` (with `columns`), or the `sel`/`esel` helpers instead of spelling `table.columns.*` over and over.
|
|
556
|
+
Tip: to keep selections terse, use `select`, `include` (with `columns`), or the `sel`/`esel` helpers instead of spelling `table.columns.*` over and over.
|
|
554
557
|
|
|
555
558
|
This level is nice when:
|
|
556
559
|
|