metal-orm 1.1.11 → 1.1.16
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 +758 -769
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +100 -96
- package/scripts/generate-entities/schema.mjs +122 -122
- package/scripts/generate-entities/tree-detection.mjs +92 -92
- package/scripts/inflection/pt-br.mjs +468 -468
- package/scripts/run-eslint.mjs +33 -34
- package/scripts/show-sql-seed.sql +102 -0
- package/scripts/show-sql.mjs +321 -325
- package/src/codegen/naming-strategy.ts +54 -54
- package/src/codegen/typescript.ts +482 -482
- package/src/core/ast/adapters.ts +1 -1
- package/src/core/ast/builders.ts +123 -123
- package/src/core/ast/expression-builders.ts +745 -745
- package/src/core/ast/expression-nodes.ts +304 -304
- package/src/core/ast/expression-visitor.ts +212 -212
- package/src/core/ast/expression.ts +20 -20
- package/src/core/ast/helpers.ts +14 -14
- package/src/core/ast/join.ts +18 -18
- package/src/core/ast/query.ts +200 -200
- package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/render-reference.test.ts +70 -70
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
- package/src/core/ddl/introspect/catalogs/index.ts +5 -5
- package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
- package/src/core/ddl/introspect/context.ts +15 -15
- package/src/core/ddl/introspect/functions/postgres.ts +35 -35
- package/src/core/ddl/introspect/registry.ts +40 -40
- package/src/core/ddl/introspect/run-select.ts +35 -35
- package/src/core/ddl/introspect/utils.ts +56 -56
- package/src/core/ddl/naming-strategy.ts +16 -16
- package/src/core/ddl/schema-dialect.ts +56 -56
- package/src/core/ddl/schema-diff.ts +234 -234
- package/src/core/ddl/schema-generator.ts +1 -1
- package/src/core/ddl/schema-introspect.ts +25 -25
- package/src/core/ddl/sql-writing.ts +171 -171
- package/src/core/dialect/abstract.ts +541 -541
- package/src/core/dialect/base/cte-compiler.ts +33 -33
- package/src/core/dialect/base/function-table-formatter.ts +103 -103
- package/src/core/dialect/base/groupby-compiler.ts +21 -21
- package/src/core/dialect/base/join-compiler.ts +25 -25
- package/src/core/dialect/base/orderby-compiler.ts +35 -35
- package/src/core/dialect/base/pagination-strategy.ts +32 -32
- package/src/core/dialect/base/returning-strategy.ts +57 -57
- package/src/core/dialect/base/sql-dialect.ts +294 -294
- package/src/core/dialect/dialect-factory.ts +91 -91
- package/src/core/dialect/mssql/functions.ts +120 -120
- package/src/core/dialect/mssql/index.ts +317 -317
- package/src/core/dialect/mysql/functions.ts +103 -103
- package/src/core/dialect/mysql/index.ts +105 -105
- package/src/core/dialect/postgres/functions.ts +108 -108
- package/src/core/dialect/postgres/index.ts +91 -91
- package/src/core/dialect/sqlite/functions.ts +129 -129
- package/src/core/dialect/sqlite/index.ts +67 -67
- package/src/core/driver/database-driver.ts +19 -19
- package/src/core/driver/mssql-driver.ts +23 -23
- package/src/core/driver/mysql-driver.ts +23 -23
- package/src/core/driver/postgres-driver.ts +23 -23
- package/src/core/driver/sqlite-driver.ts +23 -23
- package/src/core/execution/db-executor.ts +92 -92
- package/src/core/execution/executors/better-sqlite3-executor.ts +90 -90
- package/src/core/execution/executors/mssql-executor.ts +184 -184
- package/src/core/execution/executors/mysql-executor.ts +88 -88
- package/src/core/execution/executors/postgres-executor.ts +26 -26
- package/src/core/execution/executors/sqlite-executor.ts +42 -42
- package/src/core/execution/pooling/pool-types.ts +30 -30
- package/src/core/execution/pooling/pool.ts +275 -275
- package/src/core/functions/array.ts +35 -35
- package/src/core/functions/control-flow.ts +79 -79
- package/src/core/functions/datetime.ts +237 -237
- package/src/core/functions/json.ts +70 -70
- package/src/core/functions/numeric.ts +297 -297
- package/src/core/functions/text.ts +334 -334
- package/src/core/functions/types.ts +33 -33
- package/src/core/hydration/types.ts +51 -51
- package/src/core/sql/sql-operator-config.ts +39 -39
- package/src/core/sql/sql.ts +152 -152
- package/src/decorators/column-decorator.ts +87 -87
- package/src/decorators/decorator-metadata.ts +143 -143
- package/src/decorators/entity.ts +93 -93
- package/src/decorators/index.ts +39 -39
- package/src/decorators/relations.ts +231 -231
- package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
- package/src/decorators/transformers/transformer-decorators.ts +134 -134
- package/src/decorators/transformers/transformer-executor.ts +171 -171
- package/src/decorators/transformers/transformer-metadata.ts +73 -73
- package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
- package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
- package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
- package/src/decorators/validators/country-validator-registry.ts +64 -64
- package/src/decorators/validators/country-validators-decorators.ts +203 -203
- package/src/decorators/validators/country-validators.ts +105 -105
- package/src/decorators/validators/validator-metadata.ts +59 -59
- package/src/dto/dto-types.ts +226 -226
- package/src/dto/filter-types.ts +141 -141
- package/src/dto/index.ts +95 -95
- package/src/dto/openapi/generators/base.ts +29 -29
- package/src/dto/openapi/generators/column.ts +37 -37
- package/src/dto/openapi/generators/dto.ts +91 -91
- package/src/dto/openapi/generators/filter.ts +75 -75
- package/src/dto/openapi/generators/nested-dto.ts +618 -618
- package/src/dto/openapi/generators/pagination.ts +111 -111
- package/src/dto/openapi/generators/relation-filter.ts +228 -228
- package/src/dto/openapi/index.ts +12 -12
- package/src/dto/openapi/types.ts +101 -101
- package/src/dto/openapi/utilities.ts +95 -95
- package/src/dto/pagination-utils.ts +150 -150
- package/src/dto/transform.ts +197 -197
- package/src/index.ts +86 -86
- package/src/orm/als.ts +58 -58
- package/src/orm/domain-event-bus.ts +119 -119
- package/src/orm/entity-context.ts +86 -86
- package/src/orm/entity-materializer.ts +159 -159
- package/src/orm/entity-meta.ts +97 -97
- package/src/orm/entity-registry.ts +39 -39
- package/src/orm/entity-relation-cache.ts +39 -39
- package/src/orm/execute.ts +194 -194
- package/src/orm/execution-context.ts +18 -18
- package/src/orm/hydration-context.ts +26 -26
- package/src/orm/hydration.ts +112 -112
- package/src/orm/identity-map.ts +61 -61
- package/src/orm/interceptor-pipeline.ts +16 -16
- package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
- package/src/orm/lazy-batch/belongs-to.ts +108 -108
- package/src/orm/lazy-batch/has-many.ts +69 -69
- package/src/orm/lazy-batch/has-one.ts +68 -68
- package/src/orm/lazy-batch/shared.ts +125 -125
- package/src/orm/orm-session.ts +620 -620
- package/src/orm/orm.ts +34 -34
- package/src/orm/pooled-executor-factory.ts +121 -121
- package/src/orm/query-logger.ts +40 -40
- package/src/orm/relation-change-processor.ts +420 -420
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -156
- package/src/orm/relations/morph-one.ts +151 -151
- package/src/orm/relations/morph-to.ts +162 -162
- package/src/orm/runtime-types.ts +92 -92
- package/src/orm/save-graph.ts +561 -561
- package/src/orm/transaction-runner.ts +24 -24
- package/src/orm/unit-of-work.ts +426 -426
- package/src/query/index.ts +69 -69
- package/src/query/target.ts +46 -46
- package/src/query-builder/column-selector.ts +81 -81
- package/src/query-builder/delete.ts +141 -141
- package/src/query-builder/insert-query-state.ts +149 -149
- package/src/query-builder/insert.ts +117 -117
- package/src/query-builder/query-ast-service.ts +287 -287
- package/src/query-builder/query-resolution.ts +78 -78
- package/src/query-builder/raw-column-parser.ts +38 -38
- package/src/query-builder/relation-filter-utils.ts +153 -153
- package/src/query-builder/relation-join-planner.ts +10 -10
- package/src/query-builder/relation-manager.ts +87 -87
- package/src/query-builder/relation-projection-helper.ts +102 -102
- package/src/query-builder/relation-types.ts +9 -9
- package/src/query-builder/relation-utils.ts +15 -15
- package/src/query-builder/select/cte-facet.ts +40 -40
- package/src/query-builder/select/from-facet.ts +80 -80
- package/src/query-builder/select/join-facet.ts +62 -62
- package/src/query-builder/select/predicate-facet.ts +104 -104
- package/src/query-builder/select/projection-facet.ts +70 -70
- package/src/query-builder/select/relation-facet.ts +81 -81
- package/src/query-builder/select/setop-facet.ts +36 -36
- package/src/query-builder/select-helpers.ts +1 -1
- package/src/query-builder/select-query-builder-deps.ts +130 -130
- package/src/query-builder/select-query-state.ts +207 -207
- package/src/query-builder/update.ts +151 -151
- package/src/schema/column-types.ts +322 -322
- package/src/schema/table-guards.ts +37 -37
- package/src/schema/table.ts +281 -281
- package/src/tree/index.ts +13 -13
- package/src/tree/nested-set-strategy.ts +545 -545
- package/src/tree/tree-decorator.ts +397 -397
- package/src/tree/tree-manager.ts +754 -754
- package/src/tree/tree-query.ts +427 -427
- package/src/tree/tree-types.ts +299 -299
package/src/dto/filter-types.ts
CHANGED
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filter types for building type-safe query filters from JSON input.
|
|
3
|
-
* Designed for REST API query parameters.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { TableDef } from '../schema/table.js';
|
|
7
|
-
import type { ColumnDef, ColumnType } from '../schema/column-types.js';
|
|
8
|
-
import type { EntityConstructor } from '../orm/entity-metadata.js';
|
|
9
|
-
|
|
10
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
-
// Entity support: Extract columns from entity constructor
|
|
12
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Checks if a type is a TableDef.
|
|
16
|
-
*/
|
|
17
|
-
type IsTableDef<T> = T extends { name: string; columns: Record<string, unknown> } ? true : false;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Maps TypeScript types to SQL column types for EntityConstructor columns.
|
|
21
|
-
*/
|
|
22
|
-
type TsTypeToColumnType<T> =
|
|
23
|
-
T extends string ? 'VARCHAR' :
|
|
24
|
-
T extends number ? 'INT' :
|
|
25
|
-
T extends boolean ? 'BOOLEAN' :
|
|
26
|
-
T extends Date ? 'TIMESTAMP' :
|
|
27
|
-
'VARCHAR';
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Extracts the column map from either a TableDef or EntityConstructor.
|
|
31
|
-
* For EntityConstructor, infers column type from TypeScript property type.
|
|
32
|
-
*/
|
|
33
|
-
type ExtractColumns<T> = IsTableDef<T> extends true
|
|
34
|
-
? T extends TableDef<infer C> ? C : never
|
|
35
|
-
: T extends EntityConstructor<infer E>
|
|
36
|
-
? {
|
|
37
|
-
[K in keyof E]: ColumnDef<TsTypeToColumnType<E[K]>, E[K]>;
|
|
38
|
-
}
|
|
39
|
-
: never;
|
|
40
|
-
|
|
41
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
-
// Scalar filter types per data type
|
|
43
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Filter operators for string columns.
|
|
47
|
-
*/
|
|
48
|
-
export interface StringFilter {
|
|
49
|
-
equals?: string;
|
|
50
|
-
not?: string;
|
|
51
|
-
in?: string[];
|
|
52
|
-
notIn?: string[];
|
|
53
|
-
contains?: string;
|
|
54
|
-
startsWith?: string;
|
|
55
|
-
endsWith?: string;
|
|
56
|
-
/** Case-insensitive matching (for contains, startsWith, endsWith) */
|
|
57
|
-
mode?: 'default' | 'insensitive';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Filter operators for numeric columns (number, bigint).
|
|
62
|
-
*/
|
|
63
|
-
export interface NumberFilter {
|
|
64
|
-
equals?: number;
|
|
65
|
-
not?: number;
|
|
66
|
-
in?: number[];
|
|
67
|
-
notIn?: number[];
|
|
68
|
-
lt?: number;
|
|
69
|
-
lte?: number;
|
|
70
|
-
gt?: number;
|
|
71
|
-
gte?: number;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Filter operators for boolean columns.
|
|
76
|
-
*/
|
|
77
|
-
export interface BooleanFilter {
|
|
78
|
-
equals?: boolean;
|
|
79
|
-
not?: boolean;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Filter operators for date/datetime columns.
|
|
84
|
-
* Accepts ISO date strings.
|
|
85
|
-
*/
|
|
86
|
-
export interface DateFilter {
|
|
87
|
-
equals?: string;
|
|
88
|
-
not?: string;
|
|
89
|
-
in?: string[];
|
|
90
|
-
notIn?: string[];
|
|
91
|
-
lt?: string;
|
|
92
|
-
lte?: string;
|
|
93
|
-
gt?: string;
|
|
94
|
-
gte?: string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
98
|
-
// Type mapping: ColumnDef → appropriate filter type
|
|
99
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
100
|
-
|
|
101
|
-
type NormalizedType<T extends ColumnDef> = Lowercase<T['type'] & string>;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Maps a column definition to its appropriate filter type.
|
|
105
|
-
*/
|
|
106
|
-
export type FieldFilter<TCol extends ColumnDef> =
|
|
107
|
-
NormalizedType<TCol> extends 'int' | 'integer' | 'bigint' | 'decimal' | 'float' | 'double'
|
|
108
|
-
? NumberFilter
|
|
109
|
-
: NormalizedType<TCol> extends 'boolean'
|
|
110
|
-
? BooleanFilter
|
|
111
|
-
: NormalizedType<TCol> extends 'date' | 'datetime' | 'timestamp' | 'timestamptz'
|
|
112
|
-
? DateFilter
|
|
113
|
-
: StringFilter; // default to string for varchar, text, uuid, etc.
|
|
114
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Filter types for building type-safe query filters from JSON input.
|
|
3
|
+
* Designed for REST API query parameters.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { TableDef } from '../schema/table.js';
|
|
7
|
+
import type { ColumnDef, ColumnType } from '../schema/column-types.js';
|
|
8
|
+
import type { EntityConstructor } from '../orm/entity-metadata.js';
|
|
9
|
+
|
|
10
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// Entity support: Extract columns from entity constructor
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Checks if a type is a TableDef.
|
|
16
|
+
*/
|
|
17
|
+
type IsTableDef<T> = T extends { name: string; columns: Record<string, unknown> } ? true : false;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Maps TypeScript types to SQL column types for EntityConstructor columns.
|
|
21
|
+
*/
|
|
22
|
+
type TsTypeToColumnType<T> =
|
|
23
|
+
T extends string ? 'VARCHAR' :
|
|
24
|
+
T extends number ? 'INT' :
|
|
25
|
+
T extends boolean ? 'BOOLEAN' :
|
|
26
|
+
T extends Date ? 'TIMESTAMP' :
|
|
27
|
+
'VARCHAR';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Extracts the column map from either a TableDef or EntityConstructor.
|
|
31
|
+
* For EntityConstructor, infers column type from TypeScript property type.
|
|
32
|
+
*/
|
|
33
|
+
type ExtractColumns<T> = IsTableDef<T> extends true
|
|
34
|
+
? T extends TableDef<infer C> ? C : never
|
|
35
|
+
: T extends EntityConstructor<infer E>
|
|
36
|
+
? {
|
|
37
|
+
[K in keyof E]: ColumnDef<TsTypeToColumnType<E[K]>, E[K]>;
|
|
38
|
+
}
|
|
39
|
+
: never;
|
|
40
|
+
|
|
41
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
+
// Scalar filter types per data type
|
|
43
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Filter operators for string columns.
|
|
47
|
+
*/
|
|
48
|
+
export interface StringFilter {
|
|
49
|
+
equals?: string;
|
|
50
|
+
not?: string;
|
|
51
|
+
in?: string[];
|
|
52
|
+
notIn?: string[];
|
|
53
|
+
contains?: string;
|
|
54
|
+
startsWith?: string;
|
|
55
|
+
endsWith?: string;
|
|
56
|
+
/** Case-insensitive matching (for contains, startsWith, endsWith) */
|
|
57
|
+
mode?: 'default' | 'insensitive';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Filter operators for numeric columns (number, bigint).
|
|
62
|
+
*/
|
|
63
|
+
export interface NumberFilter {
|
|
64
|
+
equals?: number;
|
|
65
|
+
not?: number;
|
|
66
|
+
in?: number[];
|
|
67
|
+
notIn?: number[];
|
|
68
|
+
lt?: number;
|
|
69
|
+
lte?: number;
|
|
70
|
+
gt?: number;
|
|
71
|
+
gte?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Filter operators for boolean columns.
|
|
76
|
+
*/
|
|
77
|
+
export interface BooleanFilter {
|
|
78
|
+
equals?: boolean;
|
|
79
|
+
not?: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Filter operators for date/datetime columns.
|
|
84
|
+
* Accepts ISO date strings.
|
|
85
|
+
*/
|
|
86
|
+
export interface DateFilter {
|
|
87
|
+
equals?: string;
|
|
88
|
+
not?: string;
|
|
89
|
+
in?: string[];
|
|
90
|
+
notIn?: string[];
|
|
91
|
+
lt?: string;
|
|
92
|
+
lte?: string;
|
|
93
|
+
gt?: string;
|
|
94
|
+
gte?: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
98
|
+
// Type mapping: ColumnDef → appropriate filter type
|
|
99
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
type NormalizedType<T extends ColumnDef> = Lowercase<T['type'] & string>;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Maps a column definition to its appropriate filter type.
|
|
105
|
+
*/
|
|
106
|
+
export type FieldFilter<TCol extends ColumnDef> =
|
|
107
|
+
NormalizedType<TCol> extends 'int' | 'integer' | 'bigint' | 'decimal' | 'float' | 'double'
|
|
108
|
+
? NumberFilter
|
|
109
|
+
: NormalizedType<TCol> extends 'boolean'
|
|
110
|
+
? BooleanFilter
|
|
111
|
+
: NormalizedType<TCol> extends 'date' | 'datetime' | 'timestamp' | 'timestamptz'
|
|
112
|
+
? DateFilter
|
|
113
|
+
: StringFilter; // default to string for varchar, text, uuid, etc.
|
|
114
|
+
|
|
115
115
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
116
116
|
// SimpleWhereInput: field-only filters (no AND/OR/NOT logic)
|
|
117
117
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -136,33 +136,33 @@ export type WhereInput<T extends TableDef | EntityConstructor> =
|
|
|
136
136
|
| ColumnFilter<T>
|
|
137
137
|
| RelationFilterInput<T>
|
|
138
138
|
| (ColumnFilter<T> & RelationFilterInput<T>);
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Restricted where input - only specified columns are filterable.
|
|
142
|
-
* Use this to limit which fields can be filtered via API.
|
|
143
|
-
*
|
|
144
|
-
* Works with both TableDef and EntityConstructor.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```ts
|
|
148
|
-
* // With TableDef - only allow filtering by name and email
|
|
149
|
-
* type UserFilter = SimpleWhereInput<typeof usersTable, 'name' | 'email'>;
|
|
150
|
-
*
|
|
151
|
-
* // With Entity class
|
|
152
|
-
* type UserFilter = SimpleWhereInput<User, 'name' | 'email'>;
|
|
153
|
-
*
|
|
154
|
-
* // Request: { "name": { "contains": "john" }, "email": { "endsWith": "@gmail.com" } }
|
|
155
|
-
* ```
|
|
156
|
-
*/
|
|
157
|
-
export type SimpleWhereInput<
|
|
158
|
-
T extends TableDef | EntityConstructor,
|
|
159
|
-
K extends keyof ExtractColumns<T>
|
|
160
|
-
> = {
|
|
161
|
-
[P in K]?: ExtractColumns<T>[P] extends ColumnDef<ColumnType, unknown>
|
|
162
|
-
? FieldFilter<ExtractColumns<T>[P]>
|
|
163
|
-
: FieldFilter<ColumnDef<ColumnType, unknown>>;
|
|
164
|
-
};
|
|
165
|
-
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Restricted where input - only specified columns are filterable.
|
|
142
|
+
* Use this to limit which fields can be filtered via API.
|
|
143
|
+
*
|
|
144
|
+
* Works with both TableDef and EntityConstructor.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* // With TableDef - only allow filtering by name and email
|
|
149
|
+
* type UserFilter = SimpleWhereInput<typeof usersTable, 'name' | 'email'>;
|
|
150
|
+
*
|
|
151
|
+
* // With Entity class
|
|
152
|
+
* type UserFilter = SimpleWhereInput<User, 'name' | 'email'>;
|
|
153
|
+
*
|
|
154
|
+
* // Request: { "name": { "contains": "john" }, "email": { "endsWith": "@gmail.com" } }
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export type SimpleWhereInput<
|
|
158
|
+
T extends TableDef | EntityConstructor,
|
|
159
|
+
K extends keyof ExtractColumns<T>
|
|
160
|
+
> = {
|
|
161
|
+
[P in K]?: ExtractColumns<T>[P] extends ColumnDef<ColumnType, unknown>
|
|
162
|
+
? FieldFilter<ExtractColumns<T>[P]>
|
|
163
|
+
: FieldFilter<ColumnDef<ColumnType, unknown>>;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
166
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
167
167
|
// Relation filter types
|
|
168
168
|
// ─────────────────────────────────────────────────────────────────────────────
|
package/src/dto/index.ts
CHANGED
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DTO (Data Transfer Object) module for metal-orm.
|
|
3
|
-
*
|
|
4
|
-
* Provides type utilities and runtime helpers for building REST APIs
|
|
5
|
-
* with automatic DTO generation from entity/table definitions.
|
|
6
|
-
*
|
|
7
|
-
* Supports both TableDef and Entity classes as type sources.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* import { Dto, WithRelations, CreateDto, UpdateDto, SimpleWhereInput, applyFilter, PagedResponse, toPagedResponse } from 'metal-orm/dto';
|
|
12
|
-
*
|
|
13
|
-
* // Using Entity classes
|
|
14
|
-
* type UserResponse = Dto<User, 'passwordHash'>;
|
|
15
|
-
* type PostResponse = Dto<Post, 'authorId'>;
|
|
16
|
-
* type UserWithPosts = WithRelations<UserResponse, { posts: PostResponse[] }>;
|
|
17
|
-
* type CreateUserDto = CreateDto<User>;
|
|
18
|
-
* type UpdateUserDto = UpdateDto<User>;
|
|
19
|
-
* type UserFilter = SimpleWhereInput<User, 'name' | 'email'>;
|
|
20
|
-
*
|
|
21
|
-
* // Enhanced pagination
|
|
22
|
-
* type UsersPagedResponse = PagedResponse<UserResponse>;
|
|
23
|
-
*
|
|
24
|
-
* // Using TableDef directly
|
|
25
|
-
* type UserResponse = Dto<typeof UserTable, 'passwordHash'>;
|
|
26
|
-
* type PostResponse = Dto<typeof PostTable, 'authorId'>;
|
|
27
|
-
* type UserWithPosts = WithRelations<UserResponse, { posts: PostResponse[] }>;
|
|
28
|
-
* type CreateUserDto = CreateDto<typeof UserTable>;
|
|
29
|
-
* type UpdateUserDto = UpdateDto<typeof UserTable>;
|
|
30
|
-
* type UserFilter = SimpleWhereInput<typeof UserTable, 'name' | 'email'>;
|
|
31
|
-
*
|
|
32
|
-
* // Apply filter in controller
|
|
33
|
-
* let query = selectFromEntity(User);
|
|
34
|
-
* query = applyFilter(query, User, where);
|
|
35
|
-
*
|
|
36
|
-
* // Apply enhanced pagination
|
|
37
|
-
* const basic = await qb.executePaged(session, { page: 2, pageSize: 20 });
|
|
38
|
-
* const response = toPagedResponse(basic);
|
|
39
|
-
* // → { items: [...], totalItems: 150, page: 2, pageSize: 20,
|
|
40
|
-
* // totalPages: 8, hasNextPage: true, hasPrevPage: true }
|
|
41
|
-
* ```
|
|
42
|
-
*
|
|
43
|
-
* @packageDocumentation
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
// DTO type utilities
|
|
47
|
-
export type {
|
|
48
|
-
Simplify,
|
|
49
|
-
Dto,
|
|
50
|
-
WithRelations,
|
|
51
|
-
CreateDto,
|
|
52
|
-
UpdateDto,
|
|
53
|
-
PagedResponse
|
|
54
|
-
} from './dto-types.js';
|
|
55
|
-
|
|
56
|
-
// Filter types
|
|
57
|
-
export type {
|
|
58
|
-
StringFilter,
|
|
59
|
-
NumberFilter,
|
|
60
|
-
BooleanFilter,
|
|
61
|
-
DateFilter,
|
|
62
|
-
FieldFilter,
|
|
63
|
-
WhereInput,
|
|
64
|
-
SimpleWhereInput,
|
|
65
|
-
FilterOperator,
|
|
66
|
-
FilterValue,
|
|
67
|
-
RelationFilter
|
|
68
|
-
} from './filter-types.js';
|
|
69
|
-
|
|
70
|
-
// Runtime filter application
|
|
71
|
-
export {
|
|
72
|
-
applyFilter,
|
|
73
|
-
buildFilterExpression
|
|
74
|
-
} from './apply-filter.js';
|
|
75
|
-
|
|
76
|
-
// ApplyFilter options type
|
|
77
|
-
export type {
|
|
78
|
-
ApplyFilterOptions
|
|
79
|
-
} from './apply-filter.js';
|
|
80
|
-
|
|
81
|
-
// Transformation utilities
|
|
82
|
-
export {
|
|
83
|
-
toResponse,
|
|
84
|
-
toResponseBuilder,
|
|
85
|
-
withDefaults,
|
|
86
|
-
withDefaultsBuilder,
|
|
87
|
-
exclude,
|
|
88
|
-
pick,
|
|
89
|
-
mapFields
|
|
90
|
-
} from './transform.js';
|
|
91
|
-
|
|
92
|
-
// Pagination utilities
|
|
1
|
+
/**
|
|
2
|
+
* DTO (Data Transfer Object) module for metal-orm.
|
|
3
|
+
*
|
|
4
|
+
* Provides type utilities and runtime helpers for building REST APIs
|
|
5
|
+
* with automatic DTO generation from entity/table definitions.
|
|
6
|
+
*
|
|
7
|
+
* Supports both TableDef and Entity classes as type sources.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Dto, WithRelations, CreateDto, UpdateDto, SimpleWhereInput, applyFilter, PagedResponse, toPagedResponse } from 'metal-orm/dto';
|
|
12
|
+
*
|
|
13
|
+
* // Using Entity classes
|
|
14
|
+
* type UserResponse = Dto<User, 'passwordHash'>;
|
|
15
|
+
* type PostResponse = Dto<Post, 'authorId'>;
|
|
16
|
+
* type UserWithPosts = WithRelations<UserResponse, { posts: PostResponse[] }>;
|
|
17
|
+
* type CreateUserDto = CreateDto<User>;
|
|
18
|
+
* type UpdateUserDto = UpdateDto<User>;
|
|
19
|
+
* type UserFilter = SimpleWhereInput<User, 'name' | 'email'>;
|
|
20
|
+
*
|
|
21
|
+
* // Enhanced pagination
|
|
22
|
+
* type UsersPagedResponse = PagedResponse<UserResponse>;
|
|
23
|
+
*
|
|
24
|
+
* // Using TableDef directly
|
|
25
|
+
* type UserResponse = Dto<typeof UserTable, 'passwordHash'>;
|
|
26
|
+
* type PostResponse = Dto<typeof PostTable, 'authorId'>;
|
|
27
|
+
* type UserWithPosts = WithRelations<UserResponse, { posts: PostResponse[] }>;
|
|
28
|
+
* type CreateUserDto = CreateDto<typeof UserTable>;
|
|
29
|
+
* type UpdateUserDto = UpdateDto<typeof UserTable>;
|
|
30
|
+
* type UserFilter = SimpleWhereInput<typeof UserTable, 'name' | 'email'>;
|
|
31
|
+
*
|
|
32
|
+
* // Apply filter in controller
|
|
33
|
+
* let query = selectFromEntity(User);
|
|
34
|
+
* query = applyFilter(query, User, where);
|
|
35
|
+
*
|
|
36
|
+
* // Apply enhanced pagination
|
|
37
|
+
* const basic = await qb.executePaged(session, { page: 2, pageSize: 20 });
|
|
38
|
+
* const response = toPagedResponse(basic);
|
|
39
|
+
* // → { items: [...], totalItems: 150, page: 2, pageSize: 20,
|
|
40
|
+
* // totalPages: 8, hasNextPage: true, hasPrevPage: true }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @packageDocumentation
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
// DTO type utilities
|
|
47
|
+
export type {
|
|
48
|
+
Simplify,
|
|
49
|
+
Dto,
|
|
50
|
+
WithRelations,
|
|
51
|
+
CreateDto,
|
|
52
|
+
UpdateDto,
|
|
53
|
+
PagedResponse
|
|
54
|
+
} from './dto-types.js';
|
|
55
|
+
|
|
56
|
+
// Filter types
|
|
57
|
+
export type {
|
|
58
|
+
StringFilter,
|
|
59
|
+
NumberFilter,
|
|
60
|
+
BooleanFilter,
|
|
61
|
+
DateFilter,
|
|
62
|
+
FieldFilter,
|
|
63
|
+
WhereInput,
|
|
64
|
+
SimpleWhereInput,
|
|
65
|
+
FilterOperator,
|
|
66
|
+
FilterValue,
|
|
67
|
+
RelationFilter
|
|
68
|
+
} from './filter-types.js';
|
|
69
|
+
|
|
70
|
+
// Runtime filter application
|
|
71
|
+
export {
|
|
72
|
+
applyFilter,
|
|
73
|
+
buildFilterExpression
|
|
74
|
+
} from './apply-filter.js';
|
|
75
|
+
|
|
76
|
+
// ApplyFilter options type
|
|
77
|
+
export type {
|
|
78
|
+
ApplyFilterOptions
|
|
79
|
+
} from './apply-filter.js';
|
|
80
|
+
|
|
81
|
+
// Transformation utilities
|
|
82
|
+
export {
|
|
83
|
+
toResponse,
|
|
84
|
+
toResponseBuilder,
|
|
85
|
+
withDefaults,
|
|
86
|
+
withDefaultsBuilder,
|
|
87
|
+
exclude,
|
|
88
|
+
pick,
|
|
89
|
+
mapFields
|
|
90
|
+
} from './transform.js';
|
|
91
|
+
|
|
92
|
+
// Pagination utilities
|
|
93
93
|
export {
|
|
94
94
|
toPagedResponse,
|
|
95
95
|
toPagedResponseBuilder,
|
|
@@ -107,6 +107,6 @@ export {
|
|
|
107
107
|
export type {
|
|
108
108
|
ExecuteFilteredPagedOptions
|
|
109
109
|
} from './execute-filtered-paged.js';
|
|
110
|
-
|
|
111
|
-
// OpenAPI 3.1 Schema generation
|
|
112
|
-
export * from './openapi/index.js';
|
|
110
|
+
|
|
111
|
+
// OpenAPI 3.1 Schema generation
|
|
112
|
+
export * from './openapi/index.js';
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import type { TableDef } from '../../../schema/table.js';
|
|
2
|
-
import type { ColumnDef } from '../../../schema/column-types.js';
|
|
3
|
-
import type { EntityConstructor } from '../../../orm/entity-metadata.js';
|
|
4
|
-
import { getEntityMetadata } from '../../../orm/entity-metadata.js';
|
|
5
|
-
|
|
6
|
-
export function isTableDef(target: TableDef | EntityConstructor): target is TableDef {
|
|
7
|
-
return 'columns' in target && 'name' in target;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function getColumnMap(target: TableDef | EntityConstructor): Record<string, ColumnDef> {
|
|
11
|
-
if (isTableDef(target)) {
|
|
12
|
-
return target.columns;
|
|
13
|
-
}
|
|
14
|
-
const meta = getEntityMetadata(target);
|
|
15
|
-
if (meta && meta.columns) {
|
|
16
|
-
const columns: Record<string, ColumnDef> = {};
|
|
17
|
-
for (const [key, def] of Object.entries(meta.columns)) {
|
|
18
|
-
columns[key] = {
|
|
19
|
-
...def as object,
|
|
20
|
-
name: key,
|
|
21
|
-
table: meta.tableName
|
|
22
|
-
} as ColumnDef;
|
|
23
|
-
}
|
|
24
|
-
return columns;
|
|
25
|
-
}
|
|
26
|
-
return {};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type TargetType<T extends TableDef | EntityConstructor> = T;
|
|
1
|
+
import type { TableDef } from '../../../schema/table.js';
|
|
2
|
+
import type { ColumnDef } from '../../../schema/column-types.js';
|
|
3
|
+
import type { EntityConstructor } from '../../../orm/entity-metadata.js';
|
|
4
|
+
import { getEntityMetadata } from '../../../orm/entity-metadata.js';
|
|
5
|
+
|
|
6
|
+
export function isTableDef(target: TableDef | EntityConstructor): target is TableDef {
|
|
7
|
+
return 'columns' in target && 'name' in target;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getColumnMap(target: TableDef | EntityConstructor): Record<string, ColumnDef> {
|
|
11
|
+
if (isTableDef(target)) {
|
|
12
|
+
return target.columns;
|
|
13
|
+
}
|
|
14
|
+
const meta = getEntityMetadata(target);
|
|
15
|
+
if (meta && meta.columns) {
|
|
16
|
+
const columns: Record<string, ColumnDef> = {};
|
|
17
|
+
for (const [key, def] of Object.entries(meta.columns)) {
|
|
18
|
+
columns[key] = {
|
|
19
|
+
...def as object,
|
|
20
|
+
name: key,
|
|
21
|
+
table: meta.tableName
|
|
22
|
+
} as ColumnDef;
|
|
23
|
+
}
|
|
24
|
+
return columns;
|
|
25
|
+
}
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type TargetType<T extends TableDef | EntityConstructor> = T;
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import type { ColumnDef } from '../../../schema/column-types.js';
|
|
2
|
-
import type { OpenApiSchema, OpenApiDialect } from '../types.js';
|
|
3
|
-
import { columnTypeToOpenApiType, columnTypeToOpenApiFormat } from '../type-mappings.js';
|
|
4
|
-
import { applyNullability, isNullableColumn } from '../utilities.js';
|
|
5
|
-
|
|
6
|
-
export function columnToOpenApiSchema(
|
|
7
|
-
col: ColumnDef,
|
|
8
|
-
dialect: OpenApiDialect = 'openapi-3.1'
|
|
9
|
-
): OpenApiSchema {
|
|
10
|
-
const schema: OpenApiSchema = {
|
|
11
|
-
type: columnTypeToOpenApiType(col),
|
|
12
|
-
format: columnTypeToOpenApiFormat(col),
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const nullable = isNullableColumn(col);
|
|
16
|
-
const result = applyNullability(schema, nullable, dialect);
|
|
17
|
-
|
|
18
|
-
if (col.comment) {
|
|
19
|
-
result.description = col.comment;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (col.type.toUpperCase() === 'ENUM' && col.args && Array.isArray(col.args) && col.args.every(v => typeof v === 'string')) {
|
|
23
|
-
result.enum = col.args as string[];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const args = col.args;
|
|
27
|
-
if (args && args.length > 0) {
|
|
28
|
-
if (col.type.toUpperCase() === 'VARCHAR' || col.type.toUpperCase() === 'CHAR') {
|
|
29
|
-
const length = args[0] as number;
|
|
30
|
-
if (length) {
|
|
31
|
-
result.example = 'a'.repeat(length);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
1
|
+
import type { ColumnDef } from '../../../schema/column-types.js';
|
|
2
|
+
import type { OpenApiSchema, OpenApiDialect } from '../types.js';
|
|
3
|
+
import { columnTypeToOpenApiType, columnTypeToOpenApiFormat } from '../type-mappings.js';
|
|
4
|
+
import { applyNullability, isNullableColumn } from '../utilities.js';
|
|
5
|
+
|
|
6
|
+
export function columnToOpenApiSchema(
|
|
7
|
+
col: ColumnDef,
|
|
8
|
+
dialect: OpenApiDialect = 'openapi-3.1'
|
|
9
|
+
): OpenApiSchema {
|
|
10
|
+
const schema: OpenApiSchema = {
|
|
11
|
+
type: columnTypeToOpenApiType(col),
|
|
12
|
+
format: columnTypeToOpenApiFormat(col),
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const nullable = isNullableColumn(col);
|
|
16
|
+
const result = applyNullability(schema, nullable, dialect);
|
|
17
|
+
|
|
18
|
+
if (col.comment) {
|
|
19
|
+
result.description = col.comment;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (col.type.toUpperCase() === 'ENUM' && col.args && Array.isArray(col.args) && col.args.every(v => typeof v === 'string')) {
|
|
23
|
+
result.enum = col.args as string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const args = col.args;
|
|
27
|
+
if (args && args.length > 0) {
|
|
28
|
+
if (col.type.toUpperCase() === 'VARCHAR' || col.type.toUpperCase() === 'CHAR') {
|
|
29
|
+
const length = args[0] as number;
|
|
30
|
+
if (length) {
|
|
31
|
+
result.example = 'a'.repeat(length);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
}
|