@apisr/drizzle-model 0.0.1
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/.turbo/turbo-check-types.log +2 -0
- package/ROADMAP.md +1 -0
- package/TODO.md +64 -0
- package/drizzle.config.ts +11 -0
- package/package.json +35 -0
- package/src/index.ts +1 -0
- package/src/model/builder.ts +46 -0
- package/src/model/config.ts +35 -0
- package/src/model/core/joins.ts +279 -0
- package/src/model/core/projection.ts +47 -0
- package/src/model/core/runtime.ts +249 -0
- package/src/model/core/thenable.ts +85 -0
- package/src/model/core/transform.ts +45 -0
- package/src/model/core/where.ts +183 -0
- package/src/model/core/with.ts +28 -0
- package/src/model/dialect.ts +11 -0
- package/src/model/foreigns.ts +31 -0
- package/src/model/format.ts +19 -0
- package/src/model/index.ts +1 -0
- package/src/model/methods/exclude.ts +32 -0
- package/src/model/methods/include.ts +3 -0
- package/src/model/methods/insert.ts +16 -0
- package/src/model/methods/levels.ts +2 -0
- package/src/model/methods/query/where.ts +48 -0
- package/src/model/methods/return.ts +39 -0
- package/src/model/methods/select.ts +38 -0
- package/src/model/methods/update.ts +4 -0
- package/src/model/methods/upsert.ts +54 -0
- package/src/model/methods/with.ts +40 -0
- package/src/model/model.ts +148 -0
- package/src/model/options.ts +64 -0
- package/src/model/query/operations.ts +170 -0
- package/src/model/relation.ts +121 -0
- package/src/model/result.ts +91 -0
- package/src/model/shape.ts +8 -0
- package/src/model/table.ts +127 -0
- package/src/types.ts +16 -0
- package/tests/builder-v2-mysql.type-test.ts +40 -0
- package/tests/builder-v2.type-test.ts +343 -0
- package/tests/builder.test.ts +63 -0
- package/tests/db.ts +25 -0
- package/tests/find.test.ts +155 -0
- package/tests/insert.test.ts +233 -0
- package/tests/relations.ts +38 -0
- package/tests/schema.ts +49 -0
- package/tsconfig.json +36 -0
- package/tsdown.config.ts +12 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// import type { DrizzleInsertValues, IsDrizzleTable } from "@/types";
|
|
2
|
+
import type { RelationsRecord, TableRelationalConfig, TablesRelationalConfig } from "drizzle-orm/relations";
|
|
3
|
+
import type { IsTable, NormalizeTable, TableInsertValues } from "../table.ts";
|
|
4
|
+
|
|
5
|
+
export type MethodInsertValue<TTable extends TableRelationalConfig> = TableInsertValues<
|
|
6
|
+
NormalizeTable<TTable>
|
|
7
|
+
>;
|
|
8
|
+
|
|
9
|
+
export type MethodWithInsertValue<
|
|
10
|
+
TSchema extends TablesRelationalConfig,
|
|
11
|
+
TRelations extends RelationsRecord,
|
|
12
|
+
> = {
|
|
13
|
+
[Key in keyof TRelations]?: TableInsertValues<IsTable<
|
|
14
|
+
TSchema[TRelations[Key]["targetTableName"]]["table"]
|
|
15
|
+
>>
|
|
16
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SQL } from "drizzle-orm/sql";
|
|
2
|
+
import type { ModelIdentifier } from "../../model.ts";
|
|
3
|
+
import type { TableRelationalConfig, TablesRelationalConfig } from "drizzle-orm/relations";
|
|
4
|
+
import type { TableColumn, TableColumns, TableOneRelationsTableName } from "../../table.ts";
|
|
5
|
+
import type { MethodIncludeIdentifier } from "../include.ts";
|
|
6
|
+
import type { ColumnValue } from "../../query/operations.ts";
|
|
7
|
+
|
|
8
|
+
export type MethodWhereValue<
|
|
9
|
+
TSchema extends TablesRelationalConfig,
|
|
10
|
+
TTable extends TableRelationalConfig,
|
|
11
|
+
TValue = ModelIdentifier<TableOneRelationsTableName<TTable>> | SQL | MethodWhereColumns<TTable> | MethodWhereRelations<TSchema, TTable> | MethodIncludeIdentifier<any>
|
|
12
|
+
> =
|
|
13
|
+
// Is result of .include fn?
|
|
14
|
+
TValue extends MethodIncludeIdentifier<true>
|
|
15
|
+
? never
|
|
16
|
+
: (
|
|
17
|
+
// Is SQL?
|
|
18
|
+
TValue extends SQL
|
|
19
|
+
? TValue
|
|
20
|
+
// Is model?
|
|
21
|
+
: (TValue extends ModelIdentifier<TableOneRelationsTableName<TTable>>
|
|
22
|
+
? TValue
|
|
23
|
+
// Is columns where clauses?
|
|
24
|
+
: (TValue extends MethodWhereColumns<TTable>
|
|
25
|
+
? TValue
|
|
26
|
+
// Is relations
|
|
27
|
+
: (TValue extends MethodWhereRelations<TSchema, TTable>
|
|
28
|
+
? TValue
|
|
29
|
+
: never)
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export type MethodWhereRelations<TSchema extends TablesRelationalConfig, TTable extends TableRelationalConfig> = {
|
|
35
|
+
[TableName in keyof TTable["relations"]as TTable["relations"][TableName]["relationType"] extends "many" ? never : TableName]?: RelationWhere<
|
|
36
|
+
// Table
|
|
37
|
+
TSchema[
|
|
38
|
+
// Table name
|
|
39
|
+
TTable["relations"][TableName & string]["targetTableName"]
|
|
40
|
+
]
|
|
41
|
+
>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type RelationWhere<TTable extends TableRelationalConfig> = MethodWhereColumns<TTable>;
|
|
45
|
+
|
|
46
|
+
export type MethodWhereColumns<TTable extends TableRelationalConfig> = {
|
|
47
|
+
[ColumnName in keyof TableColumns<TTable>]?: ColumnValue<TableColumn<ColumnName & string, TTable>>
|
|
48
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ReturningIdDialects } from "../dialect.ts";
|
|
2
|
+
import type { InferModelFromColumns } from "drizzle-orm/table";
|
|
3
|
+
import type { Column } from "drizzle-orm";
|
|
4
|
+
import type { ModelConfig } from "../config.ts";
|
|
5
|
+
import type { ModelFormatValue } from "../format.ts";
|
|
6
|
+
|
|
7
|
+
// export type GetPrimarySerialOrDefaultKeys<TTable extends TableRelationalConfig, T extends IsDrizzleTable<TTable["table"]>["_"]["columns"] = IsDrizzleTable<TTable["table"]>["_"]["columns"]> = {
|
|
8
|
+
// [K in keyof T]: T[K]['_']['isPrimaryKey'] extends true
|
|
9
|
+
// ? (T[K]['_']['isAutoincrement'] extends true
|
|
10
|
+
// ? K
|
|
11
|
+
// : (T[K]['_']['hasRuntimeDefault'] extends true
|
|
12
|
+
// ? (T[K]['_']['isPrimaryKey'] extends true
|
|
13
|
+
// ? K
|
|
14
|
+
// : never)
|
|
15
|
+
// : never))
|
|
16
|
+
// : ((T[K]['_']['hasRuntimeDefault'] extends true
|
|
17
|
+
// ? (T[K]['_']['isPrimaryKey'] extends true
|
|
18
|
+
// ? K
|
|
19
|
+
// : never)
|
|
20
|
+
// : never));
|
|
21
|
+
// };
|
|
22
|
+
|
|
23
|
+
export type PrimaryKeyKeys<T extends Record<string, Column>> = {
|
|
24
|
+
[K in keyof T]: T[K]['_']['isPrimaryKey'] extends true ? K : never;
|
|
25
|
+
}[keyof T];
|
|
26
|
+
|
|
27
|
+
export type GetPrimarySerialOrDefaultKeys<T extends Record<string, Column>> = {
|
|
28
|
+
[K in PrimaryKeyKeys<T>]: T[K];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type MethodReturnResult<
|
|
32
|
+
TResultType extends string,
|
|
33
|
+
TConfig extends ModelConfig,
|
|
34
|
+
> =
|
|
35
|
+
TConfig["dialect"] extends ReturningIdDialects
|
|
36
|
+
? InferModelFromColumns<GetPrimarySerialOrDefaultKeys<TConfig["tableColumns"]>>
|
|
37
|
+
: (TResultType extends "many"
|
|
38
|
+
? ModelFormatValue<TConfig["tableOutput"], TConfig["optionsFormat"]>[]
|
|
39
|
+
: ModelFormatValue<TConfig["tableOutput"], TConfig["optionsFormat"]>);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { UnwrapArray } from "@/types.ts";
|
|
2
|
+
|
|
3
|
+
export type ResolveMethodSelectValue<
|
|
4
|
+
TValue extends Record<string, any>,
|
|
5
|
+
TResult extends Record<string, any>,
|
|
6
|
+
> = {
|
|
7
|
+
[Key in keyof TValue]: TValue[Key] extends object
|
|
8
|
+
? TResult[Key & string] extends (infer RItem)[]
|
|
9
|
+
? RItem extends Record<string, any>
|
|
10
|
+
? ResolveMethodSelectValue<TValue[Key], RItem>[]
|
|
11
|
+
: never
|
|
12
|
+
: TResult[Key & string] extends Record<string, any>
|
|
13
|
+
? ResolveMethodSelectValue<TValue[Key], TResult[Key & string]>
|
|
14
|
+
: never
|
|
15
|
+
: TResult[Key & string];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type MethodSelectResult<
|
|
19
|
+
TValue extends Record<string, any>,
|
|
20
|
+
TResult extends Record<string, any> | any[],
|
|
21
|
+
> = TResult extends any[]
|
|
22
|
+
? TResult extends (infer RItem)[]
|
|
23
|
+
? RItem extends Record<string, any>
|
|
24
|
+
? ResolveMethodSelectValue<TValue, RItem>[]
|
|
25
|
+
: ResolveMethodSelectValue<TValue, TResult>[]
|
|
26
|
+
: ResolveMethodSelectValue<TValue, TResult>
|
|
27
|
+
: ResolveMethodSelectValue<TValue, TResult>;
|
|
28
|
+
|
|
29
|
+
export type MethodSelectValue<TResult extends object> =
|
|
30
|
+
TResult extends readonly (infer U)[]
|
|
31
|
+
? U extends object
|
|
32
|
+
? MethodSelectValue<U>
|
|
33
|
+
: never
|
|
34
|
+
: {
|
|
35
|
+
[Key in keyof TResult]?: UnwrapArray<TResult[Key]> extends object
|
|
36
|
+
? MethodSelectValue<UnwrapArray<TResult[Key]>> | boolean
|
|
37
|
+
: boolean;
|
|
38
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { TableRelationalConfig, TablesRelationalConfig } from "drizzle-orm/relations";
|
|
2
|
+
import type { ModelConfig } from "../config.ts";
|
|
3
|
+
import type { MethodInsertValue } from "./insert.ts";
|
|
4
|
+
import type { MethodUpdateValue } from "./update.ts";
|
|
5
|
+
import type { GetPrimarySerialOrDefaultKeys } from "./return.ts";
|
|
6
|
+
import type { MethodWhereValue } from "./query/where.ts";
|
|
7
|
+
import type { SQL } from "drizzle-orm";
|
|
8
|
+
import type { Column } from "drizzle-orm";
|
|
9
|
+
import type { IsTable } from "../table.ts";
|
|
10
|
+
import type { AddUnionToValues } from "@/types.ts";
|
|
11
|
+
|
|
12
|
+
export type MethodUpsertValue<
|
|
13
|
+
TConfig extends ModelConfig,
|
|
14
|
+
TSchema extends TablesRelationalConfig = TConfig["schema"],
|
|
15
|
+
TTable extends TableRelationalConfig = TConfig["table"]
|
|
16
|
+
> = {
|
|
17
|
+
insert: MethodInsertValue<TTable>;
|
|
18
|
+
update: MethodUpsertUpdate<TTable>;
|
|
19
|
+
|
|
20
|
+
target?:
|
|
21
|
+
| (TConfig["primaryKeys"])
|
|
22
|
+
| (TConfig["primaryKeys"])[]
|
|
23
|
+
| Column
|
|
24
|
+
| Column[];
|
|
25
|
+
updateWhere?: MethodUpsertUpdateWhere<TSchema, TTable>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type MethodUpsertContext<
|
|
29
|
+
TTable extends TableRelationalConfig,
|
|
30
|
+
TFields extends string = (keyof IsTable<TTable["table"]>["_"]["columns"] & string)
|
|
31
|
+
> = {
|
|
32
|
+
excluded: (field: TFields) => SQL;
|
|
33
|
+
inserted: (field: TFields) => SQL;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type MethodUpsertContextFunction<TTable extends TableRelationalConfig, R> =
|
|
37
|
+
(c: MethodUpsertContext<TTable>) => R;
|
|
38
|
+
|
|
39
|
+
export type MethodUpsertUpdateValue<
|
|
40
|
+
TTable extends TableRelationalConfig,
|
|
41
|
+
> = AddUnionToValues<
|
|
42
|
+
MethodUpdateValue<TTable>,
|
|
43
|
+
SQL
|
|
44
|
+
>;
|
|
45
|
+
|
|
46
|
+
export type MethodUpsertUpdate<
|
|
47
|
+
TTable extends TableRelationalConfig,
|
|
48
|
+
> =
|
|
49
|
+
MethodUpsertUpdateValue<TTable> | MethodUpsertContextFunction<TTable, MethodUpsertUpdateValue<TTable>>;
|
|
50
|
+
|
|
51
|
+
export type MethodUpsertUpdateWhere<
|
|
52
|
+
TSchema extends TablesRelationalConfig,
|
|
53
|
+
TTable extends TableRelationalConfig
|
|
54
|
+
> = MethodUpsertContextFunction<TTable, MethodWhereValue<TSchema, TTable>>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
FindTargetTableInRelationalConfig,
|
|
3
|
+
RelationsRecord,
|
|
4
|
+
TableRelationalConfig,
|
|
5
|
+
TablesRelationalConfig,
|
|
6
|
+
} from "drizzle-orm/relations";
|
|
7
|
+
import type { ResolveRelationSelection } from "../relation.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Recursive type structure for defining nested relation selections in the .with() method.
|
|
11
|
+
*
|
|
12
|
+
* It maps relation keys to either a boolean (for simple inclusion) or a nested selection object.
|
|
13
|
+
*
|
|
14
|
+
* @typeParam TSchema - Full relational schema
|
|
15
|
+
* @typeParam TRelations - Record of relations for the current level
|
|
16
|
+
*/
|
|
17
|
+
export type MethodWithValue<
|
|
18
|
+
TSchema extends TablesRelationalConfig,
|
|
19
|
+
TRelations extends RelationsRecord,
|
|
20
|
+
> = {
|
|
21
|
+
[Key in keyof TRelations]?:
|
|
22
|
+
| boolean
|
|
23
|
+
| MethodWithValue<
|
|
24
|
+
TSchema,
|
|
25
|
+
FindTargetTableInRelationalConfig<TSchema, TRelations[Key]>["relations"]
|
|
26
|
+
>
|
|
27
|
+
| object;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type MethodWithResult<
|
|
31
|
+
TValue extends Record<string, any>,
|
|
32
|
+
TResult extends Record<string, any>,
|
|
33
|
+
TSchema extends TablesRelationalConfig,
|
|
34
|
+
TTable extends TableRelationalConfig,
|
|
35
|
+
TOutput = ResolveRelationSelection<TValue, TSchema, TTable>,
|
|
36
|
+
> = TResult extends any[]
|
|
37
|
+
? TResult extends (infer RItem)[]
|
|
38
|
+
? (TOutput & RItem)[]
|
|
39
|
+
: TOutput & TResult
|
|
40
|
+
: TOutput & TResult;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TableRelationalConfig,
|
|
3
|
+
TablesRelationalConfig,
|
|
4
|
+
} from "drizzle-orm/relations";
|
|
5
|
+
import type { MethodWithValue } from "./methods/with.ts";
|
|
6
|
+
import type { MethodInsertValue } from "./methods/insert.ts";
|
|
7
|
+
import type { ModelQueryResult, ModelMutateResult } from "./result.ts";
|
|
8
|
+
import type { MethodUpdateValue } from "./methods/update.ts";
|
|
9
|
+
import type { ModelDialect } from "./dialect.ts";
|
|
10
|
+
import type { MethodWhereValue } from "./methods/query/where.ts";
|
|
11
|
+
import type { ComposeModelOptions, ModelOptions, ResolveOptionsFormat, ResolveOptionsMethods } from "./options.ts";
|
|
12
|
+
import type { ModelConfig } from "./config.ts";
|
|
13
|
+
import type { Replace } from "../types.ts";
|
|
14
|
+
import type { MethodUpsertValue } from "./methods/upsert.ts";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Interface defining standard query methods available on a model.
|
|
18
|
+
*
|
|
19
|
+
* @typeParam TSchema - Full relational schema
|
|
20
|
+
* @typeParam TTable - Relational configuration for the current table
|
|
21
|
+
*/
|
|
22
|
+
export interface ModelMethods<
|
|
23
|
+
TConfig extends ModelConfig,
|
|
24
|
+
TSchema extends TablesRelationalConfig = TConfig["schema"],
|
|
25
|
+
TTable extends TableRelationalConfig = TConfig["table"],
|
|
26
|
+
TDialect extends ModelDialect = TConfig["dialect"]
|
|
27
|
+
> {
|
|
28
|
+
/**
|
|
29
|
+
* Fetches all rows for the current model query.
|
|
30
|
+
*/
|
|
31
|
+
findMany(): ModelQueryResult<
|
|
32
|
+
TConfig["tableOutput"][],
|
|
33
|
+
TConfig
|
|
34
|
+
>;
|
|
35
|
+
/**
|
|
36
|
+
* Fetches the first matching row for the current model query.
|
|
37
|
+
*/
|
|
38
|
+
findFirst(): ModelQueryResult<
|
|
39
|
+
TConfig["tableOutput"],
|
|
40
|
+
TConfig
|
|
41
|
+
>,
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Adds a where clause to the current model query.
|
|
45
|
+
*
|
|
46
|
+
* @param value - Where conditions for the model query
|
|
47
|
+
*/
|
|
48
|
+
where(value: MethodWhereValue<TConfig["schema"], TConfig["table"]>): Model<TConfig>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Inserts one or many rows into the model table.
|
|
52
|
+
*
|
|
53
|
+
* @param value - Insert payload or batch payload
|
|
54
|
+
*/
|
|
55
|
+
insert<TValue extends MethodInsertValue<TTable>>(value: TValue): ModelMutateResult<void, TConfig, TValue extends any[] ? "many" : "one">;
|
|
56
|
+
/**
|
|
57
|
+
* Updates rows that match the current model query.
|
|
58
|
+
*
|
|
59
|
+
* @param value - Update payload
|
|
60
|
+
*/
|
|
61
|
+
update<TValue extends MethodUpdateValue<TTable>>(value: TValue): ModelMutateResult<void, TConfig, "many">;
|
|
62
|
+
/**
|
|
63
|
+
* Deletes rows that match the current model query.
|
|
64
|
+
*/
|
|
65
|
+
delete(): ModelMutateResult<void, TConfig, "many">;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Inserts or updates rows based on conflict criteria.
|
|
69
|
+
*
|
|
70
|
+
* @param value - Upsert payload or batch payload
|
|
71
|
+
*/
|
|
72
|
+
upsert<TValue extends MethodUpsertValue<TConfig>>(value: TValue): ModelMutateResult<void, TConfig, TValue["insert"] extends any[] ? "many" : "one">;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Includes related entities in the current model query.
|
|
76
|
+
*
|
|
77
|
+
* @param value - Include configuration for relations
|
|
78
|
+
*/
|
|
79
|
+
include<TValue extends MethodWithValue<TSchema, TTable["relations"]>>(
|
|
80
|
+
value: TValue,
|
|
81
|
+
): TValue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ModelQueryMethods<
|
|
85
|
+
TConfig extends ModelConfig
|
|
86
|
+
> {
|
|
87
|
+
/**
|
|
88
|
+
* Extends the current model with additional options.
|
|
89
|
+
*
|
|
90
|
+
* @param config - Options to merge into the model
|
|
91
|
+
*/
|
|
92
|
+
extend<
|
|
93
|
+
TOptions extends ModelOptions<TConfig["schema"], TConfig["table"], TConfig["dialect"]>
|
|
94
|
+
>(config: TOptions): Model<
|
|
95
|
+
Replace<
|
|
96
|
+
TConfig,
|
|
97
|
+
{
|
|
98
|
+
options: ComposeModelOptions<
|
|
99
|
+
TOptions,
|
|
100
|
+
TConfig["options"]
|
|
101
|
+
>;
|
|
102
|
+
}
|
|
103
|
+
>
|
|
104
|
+
>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Binds a database client to the model.
|
|
108
|
+
*
|
|
109
|
+
* @param db - Database client instance
|
|
110
|
+
*/
|
|
111
|
+
db(db: any): Model<TConfig>;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Just base represenation of model. This type JUST made for more clearer types, not more...
|
|
116
|
+
*/
|
|
117
|
+
export type ModelBase<
|
|
118
|
+
TConfig extends ModelConfig
|
|
119
|
+
> = ModelMethods<TConfig>
|
|
120
|
+
& ModelQueryMethods<TConfig>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Main model interface for a table.
|
|
124
|
+
*
|
|
125
|
+
* Each column of the table is exposed as a strongly-typed field setter,
|
|
126
|
+
* allowing type-safe assignment of values when building or mutating models.
|
|
127
|
+
*
|
|
128
|
+
* This type is intended to be extended with query helpers and other
|
|
129
|
+
* model-level utilities.
|
|
130
|
+
*
|
|
131
|
+
* @typeParam TConfig - Config that includes all related information about tables, relations and etc...
|
|
132
|
+
*/
|
|
133
|
+
export type Model<
|
|
134
|
+
TConfig extends ModelConfig,
|
|
135
|
+
> = ModelIdentifier<TConfig["table"]["name"]>
|
|
136
|
+
& ModelBase<TConfig>
|
|
137
|
+
& ResolveOptionsMethods<TConfig["options"]["methods"]>
|
|
138
|
+
& {
|
|
139
|
+
$format: TConfig["options"]["format"];
|
|
140
|
+
$formatValue: ResolveOptionsFormat<TConfig["options"]["format"]>;
|
|
141
|
+
|
|
142
|
+
$$config: TConfig;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export type ModelIdentifier<ModelName> = {
|
|
146
|
+
$model: "model";
|
|
147
|
+
$modelName: ModelName;
|
|
148
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { TableRelationalConfig, TablesRelationalConfig } from "drizzle-orm/relations";
|
|
2
|
+
import type { ModelDialect } from "./dialect.ts";
|
|
3
|
+
import type { TableOutput } from "./table.ts";
|
|
4
|
+
import type { Fallback } from "../types.ts";
|
|
5
|
+
import type { MethodWhereValue } from "./methods/query/where.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Options to define a model
|
|
9
|
+
*/
|
|
10
|
+
export interface ModelOptions<
|
|
11
|
+
TSchema extends TablesRelationalConfig = TablesRelationalConfig,
|
|
12
|
+
TTable extends TableRelationalConfig = TableRelationalConfig,
|
|
13
|
+
TDialect extends ModelDialect = ModelDialect,
|
|
14
|
+
TSelf extends ModelOptions<any, any, any, TSelf> = ModelOptions<TSchema, TTable, TDialect, any>
|
|
15
|
+
> {
|
|
16
|
+
format?: ModelOptionFormat<TTable>;
|
|
17
|
+
where?: MethodWhereValue<TSchema, TTable>;
|
|
18
|
+
|
|
19
|
+
// TODO: Make zod schemas
|
|
20
|
+
// insertSchema?: any;
|
|
21
|
+
// updateSchema?: any;
|
|
22
|
+
|
|
23
|
+
// TODO: Maybe planned for future releases
|
|
24
|
+
// select?: MethodSelectValue<TableOutput<TTable>>;
|
|
25
|
+
// exclude?: MethodExcludeValue<TableOutput<TTable>>;
|
|
26
|
+
|
|
27
|
+
methods?: ModelMethodsFactory;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type ComposeModelOptions<
|
|
31
|
+
O1 extends ModelOptions,
|
|
32
|
+
O2 extends ModelOptions
|
|
33
|
+
> = Omit<O1, "format" | "methods"> & {
|
|
34
|
+
format: Fallback<O1["format"], O2["format"]>;
|
|
35
|
+
methods: MergeModelOptionsMethods<O1["methods"], O2["methods"]>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type ModelOptionFormat<TTable extends TableRelationalConfig> = {
|
|
39
|
+
bivarianceHack(output: TableOutput<TTable>): any;
|
|
40
|
+
}["bivarianceHack"];
|
|
41
|
+
// export type ModelMethodsFactory = {
|
|
42
|
+
// bivarianceHack(): Record<string, any>;
|
|
43
|
+
// }["bivarianceHack"];
|
|
44
|
+
export type ModelMethodsFactory = Record<string, any>;
|
|
45
|
+
|
|
46
|
+
export type ResolveOptionsMethods<TFactory extends ModelMethodsFactory | undefined> =
|
|
47
|
+
(TFactory extends ModelMethodsFactory
|
|
48
|
+
? TFactory
|
|
49
|
+
: {});
|
|
50
|
+
|
|
51
|
+
export type ResolveOptionsFormat<TFormat> =
|
|
52
|
+
TFormat extends (...args: any[]) => any
|
|
53
|
+
? ReturnType<TFormat>
|
|
54
|
+
: undefined;
|
|
55
|
+
|
|
56
|
+
export type MergeModelOptionsMethods<
|
|
57
|
+
M1 extends ModelMethodsFactory | undefined,
|
|
58
|
+
M2 extends ModelMethodsFactory | undefined
|
|
59
|
+
> =
|
|
60
|
+
M1 extends ModelMethodsFactory
|
|
61
|
+
? M2 extends ModelMethodsFactory
|
|
62
|
+
? Omit<M2, keyof M1> & M1
|
|
63
|
+
: M1
|
|
64
|
+
: M2;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { Column, SQL } from "drizzle-orm";
|
|
2
|
+
|
|
3
|
+
export type DrizzleColumnDataType<TColumn extends Column> = TColumn["_"]["data"];
|
|
4
|
+
|
|
5
|
+
export type EscapedValue<T> =
|
|
6
|
+
| {
|
|
7
|
+
equal: T;
|
|
8
|
+
}
|
|
9
|
+
| {
|
|
10
|
+
__kind: "esc-op";
|
|
11
|
+
op: {
|
|
12
|
+
bivarianceHack(column: any, value: T): any;
|
|
13
|
+
}["bivarianceHack"];
|
|
14
|
+
value: T;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type OpValue<T> = T | SQL | EscapedValue<T>;
|
|
18
|
+
|
|
19
|
+
export type ColumnOpsBase<T> = {
|
|
20
|
+
eq?: OpValue<T>;
|
|
21
|
+
equal?: OpValue<T>;
|
|
22
|
+
not?: OpValue<T>;
|
|
23
|
+
in?: OpValue<T>[];
|
|
24
|
+
nin?: OpValue<T>[];
|
|
25
|
+
isNull?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type NumberOps = {
|
|
29
|
+
gt?: OpValue<number>;
|
|
30
|
+
gte?: OpValue<number>;
|
|
31
|
+
lt?: OpValue<number>;
|
|
32
|
+
lte?: OpValue<number>;
|
|
33
|
+
between?: [OpValue<number>, OpValue<number>];
|
|
34
|
+
notBetween?: [OpValue<number>, OpValue<number>];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type StringOps = {
|
|
38
|
+
like?: OpValue<string>;
|
|
39
|
+
ilike?: OpValue<string>;
|
|
40
|
+
startsWith?: OpValue<string>;
|
|
41
|
+
endsWith?: OpValue<string>;
|
|
42
|
+
contains?: OpValue<string>;
|
|
43
|
+
regex?: OpValue<string>;
|
|
44
|
+
notRegex?: OpValue<string>;
|
|
45
|
+
length?: NumberOps;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type BoolOps = {
|
|
49
|
+
isTrue?: boolean;
|
|
50
|
+
isFalse?: boolean;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type DateOps = {
|
|
54
|
+
before?: OpValue<Date | string>;
|
|
55
|
+
after?: OpValue<Date | string>;
|
|
56
|
+
on?: OpValue<Date | string>;
|
|
57
|
+
notOn?: OpValue<Date | string>;
|
|
58
|
+
between?: [OpValue<Date | string>, OpValue<Date | string>];
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type JsonOps<T> = {
|
|
62
|
+
has?: T;
|
|
63
|
+
hasAny?: T[];
|
|
64
|
+
hasAll?: T[];
|
|
65
|
+
len?: NumberOps;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type LogicalOps<TColumn extends Column> = {
|
|
69
|
+
or?: ColumnValue<TColumn>[];
|
|
70
|
+
and?: ColumnValue<TColumn>[];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type TypeOps<T> = T extends number
|
|
74
|
+
? NumberOps
|
|
75
|
+
: T extends string
|
|
76
|
+
? StringOps
|
|
77
|
+
: T extends boolean
|
|
78
|
+
? BoolOps
|
|
79
|
+
: T extends Date
|
|
80
|
+
? DateOps
|
|
81
|
+
: T extends any[]
|
|
82
|
+
? JsonOps<T[number]>
|
|
83
|
+
: {};
|
|
84
|
+
|
|
85
|
+
export type ColumnOps<
|
|
86
|
+
TColumn extends Column,
|
|
87
|
+
TDataType extends DrizzleColumnDataType<TColumn>,
|
|
88
|
+
> = ColumnOpsBase<TDataType> & TypeOps<TDataType> & LogicalOps<TColumn>;
|
|
89
|
+
|
|
90
|
+
export type ColumnValue<
|
|
91
|
+
TColumn extends Column,
|
|
92
|
+
TDataType extends
|
|
93
|
+
DrizzleColumnDataType<TColumn> = DrizzleColumnDataType<TColumn>,
|
|
94
|
+
> = ColumnOps<TColumn, TDataType> | EscapedValue<TDataType>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Escapes a value from the query DSL and forces it to be compiled using
|
|
98
|
+
* a specific comparison operator.
|
|
99
|
+
*
|
|
100
|
+
* This function exists as an explicit escape hatch for cases where:
|
|
101
|
+
* - the default DSL operators are insufficient
|
|
102
|
+
* - Drizzle ORM operators should be used directly
|
|
103
|
+
* - complex types (e.g. Date, objects, custom classes) need safe handling
|
|
104
|
+
*
|
|
105
|
+
* There are two supported forms:
|
|
106
|
+
*
|
|
107
|
+
* 1) Implicit equality (default behavior):
|
|
108
|
+
* ```ts
|
|
109
|
+
* where({ name: esc("Alex") })
|
|
110
|
+
* ```
|
|
111
|
+
* Compiles to:
|
|
112
|
+
* ```ts
|
|
113
|
+
* {
|
|
114
|
+
* eq: "Alex"
|
|
115
|
+
* }
|
|
116
|
+
* // In drizzle: eq(column, "Alex")
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* 2) Explicit operator (Drizzle-style):
|
|
120
|
+
* ```ts
|
|
121
|
+
* where({ age: esc(gte, 18) })
|
|
122
|
+
* ```
|
|
123
|
+
* Compiles to:
|
|
124
|
+
* ```ts
|
|
125
|
+
* gte(column, 18)
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* The column is injected later during query compilation.
|
|
129
|
+
* `esc` does NOT execute the operator immediately.
|
|
130
|
+
*
|
|
131
|
+
* @typeParam T - The value type being compared against the column
|
|
132
|
+
*
|
|
133
|
+
* @param value - Value to compare using implicit equality
|
|
134
|
+
*
|
|
135
|
+
* @returns An internal escaped descriptor consumed by the query compiler
|
|
136
|
+
*/
|
|
137
|
+
export function esc<T>(value: T): EscapedValue<T>;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Escapes a value from the query DSL and forces it to be compiled using
|
|
141
|
+
* the provided binary operator.
|
|
142
|
+
*
|
|
143
|
+
* This overload allows reuse of Drizzle ORM operators that normally
|
|
144
|
+
* require the column as the first argument.
|
|
145
|
+
*
|
|
146
|
+
* @typeParam T - The value type expected by the operator
|
|
147
|
+
*
|
|
148
|
+
* @param op - A binary comparison operator (e.g. eq, gte, ilike)
|
|
149
|
+
* @param value - Value to pass as the operator's right-hand side
|
|
150
|
+
*
|
|
151
|
+
* @returns An internal escaped descriptor consumed by the query compiler
|
|
152
|
+
*/
|
|
153
|
+
export function esc<T>(
|
|
154
|
+
op: (column: any, value: T) => any,
|
|
155
|
+
value: T
|
|
156
|
+
): EscapedValue<T>;
|
|
157
|
+
|
|
158
|
+
export function esc<T>(arg1: any, arg2?: any): EscapedValue<T> {
|
|
159
|
+
if (typeof arg1 === "function") {
|
|
160
|
+
return {
|
|
161
|
+
__kind: "esc-op",
|
|
162
|
+
op: arg1 as (column: any, value: T) => any,
|
|
163
|
+
value: arg2 as T,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
equal: arg1,
|
|
169
|
+
};
|
|
170
|
+
}
|