@fragno-dev/db 0.0.1 → 0.1.0
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-build.log +137 -13
- package/.turbo/turbo-test.log +36 -0
- package/CHANGELOG.md +7 -0
- package/dist/adapters/adapters.d.ts +18 -0
- package/dist/adapters/adapters.d.ts.map +1 -0
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +21 -0
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -0
- package/dist/adapters/drizzle/drizzle-adapter.js +62 -0
- package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -0
- package/dist/adapters/drizzle/drizzle-query.d.ts +17 -0
- package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -0
- package/dist/adapters/drizzle/drizzle-query.js +139 -0
- package/dist/adapters/drizzle/drizzle-query.js.map +1 -0
- package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +9 -0
- package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +1 -0
- package/dist/adapters/drizzle/drizzle-uow-compiler.js +300 -0
- package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -0
- package/dist/adapters/drizzle/drizzle-uow-decoder.js +82 -0
- package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -0
- package/dist/adapters/drizzle/drizzle-uow-executor.js +125 -0
- package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -0
- package/dist/adapters/drizzle/generate.js +273 -0
- package/dist/adapters/drizzle/generate.js.map +1 -0
- package/dist/adapters/drizzle/join-column-utils.js +28 -0
- package/dist/adapters/drizzle/join-column-utils.js.map +1 -0
- package/dist/adapters/drizzle/shared.js +11 -0
- package/dist/adapters/drizzle/shared.js.map +1 -0
- package/dist/adapters/kysely/kysely-adapter.d.ts +23 -0
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -0
- package/dist/adapters/kysely/kysely-adapter.js +119 -0
- package/dist/adapters/kysely/kysely-adapter.js.map +1 -0
- package/dist/adapters/kysely/kysely-query-builder.js +306 -0
- package/dist/adapters/kysely/kysely-query-builder.js.map +1 -0
- package/dist/adapters/kysely/kysely-query-compiler.js +67 -0
- package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -0
- package/dist/adapters/kysely/kysely-query.js +158 -0
- package/dist/adapters/kysely/kysely-query.js.map +1 -0
- package/dist/adapters/kysely/kysely-uow-compiler.js +139 -0
- package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -0
- package/dist/adapters/kysely/kysely-uow-executor.js +89 -0
- package/dist/adapters/kysely/kysely-uow-executor.js.map +1 -0
- package/dist/adapters/kysely/migration/execute.js +176 -0
- package/dist/adapters/kysely/migration/execute.js.map +1 -0
- package/dist/fragment.d.ts +54 -0
- package/dist/fragment.d.ts.map +1 -0
- package/dist/fragment.js +92 -0
- package/dist/fragment.js.map +1 -0
- package/dist/id.d.ts +2 -0
- package/dist/migration-engine/auto-from-schema.js +116 -0
- package/dist/migration-engine/auto-from-schema.js.map +1 -0
- package/dist/migration-engine/create.d.ts +41 -0
- package/dist/migration-engine/create.d.ts.map +1 -0
- package/dist/migration-engine/create.js +58 -0
- package/dist/migration-engine/create.js.map +1 -0
- package/dist/migration-engine/shared.d.ts +90 -0
- package/dist/migration-engine/shared.d.ts.map +1 -0
- package/dist/migration-engine/shared.js +8 -0
- package/dist/migration-engine/shared.js.map +1 -0
- package/dist/mod.d.ts +55 -2
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +111 -2
- package/dist/mod.js.map +1 -1
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js +108 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column-builder.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js +55 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/column.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js +18 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/entity.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js +183 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/common.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js +58 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/columns/enum.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js +68 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/foreign-keys.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js +56 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/unique-constraint.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js +65 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/pg-core/utils/array.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js +81 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/conditions.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js +13 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/expressions/select.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js +10 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/functions/aggregate.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js +372 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/sql/sql.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js +23 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/subquery.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js +62 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js +6 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/table.utils.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js +8 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing-utils.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js +8 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/tracing.js.map +1 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js +6 -0
- package/dist/node_modules/.bun/drizzle-orm@0.44.6_4fae081eecb963e2/node_modules/drizzle-orm/view-common.js.map +1 -0
- package/dist/query/condition-builder.d.ts +41 -0
- package/dist/query/condition-builder.d.ts.map +1 -0
- package/dist/query/condition-builder.js +93 -0
- package/dist/query/condition-builder.js.map +1 -0
- package/dist/query/cursor.d.ts +88 -0
- package/dist/query/cursor.d.ts.map +1 -0
- package/dist/query/cursor.js +103 -0
- package/dist/query/cursor.js.map +1 -0
- package/dist/query/orm/orm.d.ts +18 -0
- package/dist/query/orm/orm.d.ts.map +1 -0
- package/dist/query/orm/orm.js +48 -0
- package/dist/query/orm/orm.js.map +1 -0
- package/dist/query/query.d.ts +79 -0
- package/dist/query/query.d.ts.map +1 -0
- package/dist/query/query.js +1 -0
- package/dist/query/result-transform.js +155 -0
- package/dist/query/result-transform.js.map +1 -0
- package/dist/query/unit-of-work.d.ts +435 -0
- package/dist/query/unit-of-work.d.ts.map +1 -0
- package/dist/query/unit-of-work.js +549 -0
- package/dist/query/unit-of-work.js.map +1 -0
- package/dist/schema/create.d.ts +273 -116
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +410 -222
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/serialize.js +101 -0
- package/dist/schema/serialize.js.map +1 -0
- package/dist/schema-generator/schema-generator.d.ts +15 -0
- package/dist/schema-generator/schema-generator.d.ts.map +1 -0
- package/dist/shared/providers.d.ts +6 -0
- package/dist/shared/providers.d.ts.map +1 -0
- package/dist/util/import-generator.js +26 -0
- package/dist/util/import-generator.js.map +1 -0
- package/dist/util/parse.js +15 -0
- package/dist/util/parse.js.map +1 -0
- package/dist/util/types.d.ts +8 -0
- package/dist/util/types.d.ts.map +1 -0
- package/package.json +63 -2
- package/src/adapters/adapters.ts +22 -0
- package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +433 -0
- package/src/adapters/drizzle/drizzle-adapter.test.ts +122 -0
- package/src/adapters/drizzle/drizzle-adapter.ts +118 -0
- package/src/adapters/drizzle/drizzle-query.ts +234 -0
- package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +1084 -0
- package/src/adapters/drizzle/drizzle-uow-compiler.ts +546 -0
- package/src/adapters/drizzle/drizzle-uow-decoder.ts +165 -0
- package/src/adapters/drizzle/drizzle-uow-executor.ts +213 -0
- package/src/adapters/drizzle/generate.test.ts +643 -0
- package/src/adapters/drizzle/generate.ts +481 -0
- package/src/adapters/drizzle/join-column-utils.test.ts +79 -0
- package/src/adapters/drizzle/join-column-utils.ts +39 -0
- package/src/adapters/drizzle/migrate-drizzle.test.ts +226 -0
- package/src/adapters/drizzle/shared.ts +22 -0
- package/src/adapters/drizzle/test-utils.ts +56 -0
- package/src/adapters/kysely/kysely-adapter-pglite.test.ts +789 -0
- package/src/adapters/kysely/kysely-adapter.ts +196 -0
- package/src/adapters/kysely/kysely-query-builder.test.ts +1344 -0
- package/src/adapters/kysely/kysely-query-builder.ts +611 -0
- package/src/adapters/kysely/kysely-query-compiler.ts +124 -0
- package/src/adapters/kysely/kysely-query.ts +254 -0
- package/src/adapters/kysely/kysely-uow-compiler.test.ts +916 -0
- package/src/adapters/kysely/kysely-uow-compiler.ts +271 -0
- package/src/adapters/kysely/kysely-uow-executor.ts +149 -0
- package/src/adapters/kysely/kysely-uow-joins.test.ts +811 -0
- package/src/adapters/kysely/migration/execute-mysql.test.ts +1173 -0
- package/src/adapters/kysely/migration/execute-postgres.test.ts +2657 -0
- package/src/adapters/kysely/migration/execute.ts +382 -0
- package/src/adapters/kysely/migration/kysely-migrator.test.ts +197 -0
- package/src/fragment.test.ts +287 -0
- package/src/fragment.ts +198 -0
- package/src/migration-engine/auto-from-schema.test.ts +118 -58
- package/src/migration-engine/auto-from-schema.ts +103 -32
- package/src/migration-engine/create.test.ts +34 -46
- package/src/migration-engine/create.ts +41 -26
- package/src/migration-engine/shared.ts +26 -6
- package/src/mod.ts +197 -1
- package/src/query/condition-builder.test.ts +379 -0
- package/src/query/condition-builder.ts +294 -0
- package/src/query/cursor.test.ts +296 -0
- package/src/query/cursor.ts +147 -0
- package/src/query/orm/orm.ts +92 -0
- package/src/query/query-type.test.ts +429 -0
- package/src/query/query.ts +200 -0
- package/src/query/result-transform.test.ts +795 -0
- package/src/query/result-transform.ts +247 -0
- package/src/query/unit-of-work-types.test.ts +192 -0
- package/src/query/unit-of-work.test.ts +947 -0
- package/src/query/unit-of-work.ts +1199 -0
- package/src/schema/create.test.ts +653 -110
- package/src/schema/create.ts +708 -337
- package/src/schema/serialize.test.ts +559 -0
- package/src/schema/serialize.ts +359 -0
- package/src/schema-generator/schema-generator.ts +12 -0
- package/src/shared/config.ts +0 -8
- package/src/util/import-generator.ts +28 -0
- package/src/util/parse.ts +16 -0
- package/src/util/types.ts +4 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +11 -1
- package/vitest.config.ts +3 -0
- /package/dist/{cuid.js → id.js} +0 -0
- /package/src/{cuid.ts → id.ts} +0 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { describe, expectTypeOf, it } from "vitest";
|
|
2
|
+
import { column, FragnoId, idColumn, referenceColumn, schema } from "../schema/create";
|
|
3
|
+
import type {
|
|
4
|
+
AbstractQuery,
|
|
5
|
+
FindFirstOptions,
|
|
6
|
+
FindManyOptions,
|
|
7
|
+
JoinBuilder,
|
|
8
|
+
OrderBy,
|
|
9
|
+
SelectClause,
|
|
10
|
+
TableToInsertValues,
|
|
11
|
+
} from "./query";
|
|
12
|
+
import type { ConditionBuilder } from "./condition-builder";
|
|
13
|
+
|
|
14
|
+
describe("query type tests", () => {
|
|
15
|
+
// Create test schema
|
|
16
|
+
const _testSchema = schema((s) => {
|
|
17
|
+
return s
|
|
18
|
+
.addTable("users", (t) => {
|
|
19
|
+
return t
|
|
20
|
+
.addColumn("_id", idColumn())
|
|
21
|
+
.addColumn("name", column("string"))
|
|
22
|
+
.addColumn("email", column("string"))
|
|
23
|
+
.addColumn("age", column("integer").nullable())
|
|
24
|
+
.addColumn("isActive", column("bool"));
|
|
25
|
+
})
|
|
26
|
+
.addTable("posts", (t) => {
|
|
27
|
+
return t
|
|
28
|
+
.addColumn("_id", idColumn())
|
|
29
|
+
.addColumn("title", column("string"))
|
|
30
|
+
.addColumn("content", column("string"))
|
|
31
|
+
.addColumn("userId", column("string"))
|
|
32
|
+
.addColumn("publishedAt", column("timestamp").nullable())
|
|
33
|
+
.addColumn("viewCount", column("integer"));
|
|
34
|
+
})
|
|
35
|
+
.addTable("comments", (t) => {
|
|
36
|
+
return t
|
|
37
|
+
.addColumn("_id", idColumn())
|
|
38
|
+
.addColumn("postId", column("string"))
|
|
39
|
+
.addColumn("authorId", column("string"))
|
|
40
|
+
.addColumn("text", column("string"))
|
|
41
|
+
.addColumn("likes", column("integer").nullable());
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
type TestSchema = typeof _testSchema;
|
|
46
|
+
|
|
47
|
+
describe("SelectClause", () => {
|
|
48
|
+
it("should allow true for selecting all columns", () => {
|
|
49
|
+
expectTypeOf<true>().toExtend<SelectClause<TestSchema["tables"]["users"]>>();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should allow array of column names", () => {
|
|
53
|
+
expectTypeOf<["name", "email"]>().toExtend<SelectClause<TestSchema["tables"]["users"]>>();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should not allow invalid column names", () => {
|
|
57
|
+
expectTypeOf<["invalid"]>().not.toEqualTypeOf<SelectClause<TestSchema["tables"]["users"]>>();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("OrderBy", () => {
|
|
62
|
+
it("should allow column name with direction", () => {
|
|
63
|
+
expectTypeOf<["name", "asc"]>().toExtend<
|
|
64
|
+
OrderBy<keyof TestSchema["tables"]["users"]["columns"]>
|
|
65
|
+
>();
|
|
66
|
+
expectTypeOf<["age", "desc"]>().toExtend<
|
|
67
|
+
OrderBy<keyof TestSchema["tables"]["users"]["columns"]>
|
|
68
|
+
>();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("FindManyOptions", () => {
|
|
73
|
+
it("should not allow offset when IsRoot is false", () => {
|
|
74
|
+
type _NonRootOptions = FindManyOptions<TestSchema["tables"]["users"], true, object, false>;
|
|
75
|
+
|
|
76
|
+
expectTypeOf<_NonRootOptions>().not.toHaveProperty("offset");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe("FindFirstOptions", () => {
|
|
81
|
+
it("should omit limit from FindManyOptions", () => {
|
|
82
|
+
expectTypeOf<FindFirstOptions<TestSchema["tables"]["users"]>>().not.toHaveProperty("limit");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should omit orderBy and offset when IsRoot is false", () => {
|
|
86
|
+
type _NonRootOptions = FindFirstOptions<TestSchema["tables"]["users"], true, object, false>;
|
|
87
|
+
|
|
88
|
+
expectTypeOf<_NonRootOptions>().not.toHaveProperty("limit");
|
|
89
|
+
expectTypeOf<_NonRootOptions>().not.toHaveProperty("orderBy");
|
|
90
|
+
expectTypeOf<_NonRootOptions>().not.toHaveProperty("offset");
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("AbstractQuery methods", () => {
|
|
95
|
+
type Query = AbstractQuery<TestSchema>;
|
|
96
|
+
|
|
97
|
+
describe("findFirst", () => {
|
|
98
|
+
it("should return all columns when select is true or undefined", () => {
|
|
99
|
+
const _query = {} as Query;
|
|
100
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"users">>>;
|
|
101
|
+
|
|
102
|
+
expectTypeOf<Result>().toExtend<{
|
|
103
|
+
_id: FragnoId;
|
|
104
|
+
name: string;
|
|
105
|
+
email: string;
|
|
106
|
+
age: number | null;
|
|
107
|
+
isActive: boolean;
|
|
108
|
+
} | null>();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("should return selected columns only", () => {
|
|
112
|
+
const _query = {} as Query;
|
|
113
|
+
|
|
114
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"users", ["name", "email"]>>>;
|
|
115
|
+
|
|
116
|
+
expectTypeOf<Result>().toExtend<{
|
|
117
|
+
name: string;
|
|
118
|
+
email: string;
|
|
119
|
+
} | null>();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("should handle nullable columns correctly", () => {
|
|
123
|
+
const _query = {} as Query;
|
|
124
|
+
|
|
125
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"users", ["age"]>>>;
|
|
126
|
+
type NonNullResult = Exclude<Result, null>;
|
|
127
|
+
|
|
128
|
+
expectTypeOf<NonNullResult>().toMatchTypeOf<{ age: number | null }>();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe("find", () => {
|
|
133
|
+
it("should return array of all columns when select is true or undefined", () => {
|
|
134
|
+
const _query = {} as Query;
|
|
135
|
+
type Result = Awaited<ReturnType<typeof _query.find<"users">>>;
|
|
136
|
+
|
|
137
|
+
expectTypeOf<Result>().toExtend<
|
|
138
|
+
{
|
|
139
|
+
_id: FragnoId;
|
|
140
|
+
name: string;
|
|
141
|
+
email: string;
|
|
142
|
+
age: number | null;
|
|
143
|
+
isActive: boolean;
|
|
144
|
+
}[]
|
|
145
|
+
>();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should return array of selected columns only", () => {
|
|
149
|
+
const _query = {} as Query;
|
|
150
|
+
|
|
151
|
+
type Result = Awaited<ReturnType<typeof _query.find<"users", ["name", "email"], object>>>;
|
|
152
|
+
|
|
153
|
+
expectTypeOf<Result>().toExtend<
|
|
154
|
+
{
|
|
155
|
+
name: string;
|
|
156
|
+
email: string;
|
|
157
|
+
}[]
|
|
158
|
+
>();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe("create", () => {
|
|
163
|
+
it("should require non-nullable columns and allow omitting nullable columns", () => {
|
|
164
|
+
const _query = {} as Query;
|
|
165
|
+
|
|
166
|
+
type Params = Parameters<typeof _query.create<"users">>[1];
|
|
167
|
+
|
|
168
|
+
// TODO: This could be better
|
|
169
|
+
expectTypeOf<{
|
|
170
|
+
[x: string]: unknown;
|
|
171
|
+
age?: number | null | undefined;
|
|
172
|
+
_id: FragnoId;
|
|
173
|
+
name: string;
|
|
174
|
+
email: string;
|
|
175
|
+
isActive: boolean;
|
|
176
|
+
}>().toExtend<Params>();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should return the created ID", () => {
|
|
180
|
+
const _query = {} as Query;
|
|
181
|
+
type Result = Awaited<ReturnType<typeof _query.create<"users">>>;
|
|
182
|
+
|
|
183
|
+
expectTypeOf<Result>().toEqualTypeOf<FragnoId>();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("should handle posts table correctly", () => {
|
|
187
|
+
const _query = {} as Query;
|
|
188
|
+
|
|
189
|
+
type Params = Parameters<typeof _query.create<"posts">>[1];
|
|
190
|
+
|
|
191
|
+
expectTypeOf<{
|
|
192
|
+
publishedAt?: Date | null | undefined;
|
|
193
|
+
likes?: number | null | undefined;
|
|
194
|
+
_id: FragnoId;
|
|
195
|
+
title: string;
|
|
196
|
+
content: string;
|
|
197
|
+
userId: string;
|
|
198
|
+
viewCount: number;
|
|
199
|
+
}>().toExtend<Params>();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("createMany", () => {
|
|
204
|
+
it("should accept array of insert values", () => {
|
|
205
|
+
const _query = {} as Query;
|
|
206
|
+
|
|
207
|
+
type Params = Parameters<typeof _query.createMany<"users">>[1];
|
|
208
|
+
|
|
209
|
+
expectTypeOf<
|
|
210
|
+
{
|
|
211
|
+
name: string;
|
|
212
|
+
age?: number | null | undefined;
|
|
213
|
+
_id: FragnoId;
|
|
214
|
+
email: string;
|
|
215
|
+
isActive: boolean;
|
|
216
|
+
}[]
|
|
217
|
+
>().toExtend<Params>();
|
|
218
|
+
|
|
219
|
+
type Result = Awaited<ReturnType<typeof _query.createMany<"users">>>;
|
|
220
|
+
// createMany returns array of IDs
|
|
221
|
+
expectTypeOf<Result>().toEqualTypeOf<FragnoId[]>();
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe("updateMany", () => {
|
|
226
|
+
it("should accept a builder function", () => {
|
|
227
|
+
const _query = {} as Query;
|
|
228
|
+
|
|
229
|
+
// updateMany accepts a builder function, not an options object
|
|
230
|
+
type Params = Parameters<typeof _query.updateMany<"users">>;
|
|
231
|
+
|
|
232
|
+
// Check that updateMany takes correct parameters
|
|
233
|
+
expectTypeOf<Params[0]>().toEqualTypeOf<"users">();
|
|
234
|
+
expectTypeOf<Params[1]>().toBeFunction();
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
describe("table name type checking", () => {
|
|
240
|
+
it("should only allow valid table names", () => {
|
|
241
|
+
const _query = {} as AbstractQuery<TestSchema>;
|
|
242
|
+
|
|
243
|
+
// Valid table names
|
|
244
|
+
type UsersParam = Parameters<typeof _query.find<"users">>;
|
|
245
|
+
type PostsParam = Parameters<typeof _query.find<"posts">>;
|
|
246
|
+
type CommentsParam = Parameters<typeof _query.find<"comments">>;
|
|
247
|
+
|
|
248
|
+
expectTypeOf<UsersParam>().not.toEqualTypeOf<never>();
|
|
249
|
+
expectTypeOf<PostsParam>().not.toEqualTypeOf<never>();
|
|
250
|
+
expectTypeOf<CommentsParam>().not.toEqualTypeOf<never>();
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
describe("column type inference", () => {
|
|
255
|
+
it("should correctly infer column types for users table", () => {
|
|
256
|
+
const _query = {} as AbstractQuery<TestSchema>;
|
|
257
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"users">>>;
|
|
258
|
+
type User = Exclude<Result, null>;
|
|
259
|
+
|
|
260
|
+
expectTypeOf<User["_id"]>().toEqualTypeOf<FragnoId>();
|
|
261
|
+
expectTypeOf<User["name"]>().toEqualTypeOf<string>();
|
|
262
|
+
expectTypeOf<User["email"]>().toEqualTypeOf<string>();
|
|
263
|
+
expectTypeOf<User["age"]>().toEqualTypeOf<number | null>();
|
|
264
|
+
expectTypeOf<User["isActive"]>().toEqualTypeOf<boolean>();
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("should correctly infer column types for posts table", () => {
|
|
268
|
+
const _query = {} as AbstractQuery<TestSchema>;
|
|
269
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"posts">>>;
|
|
270
|
+
type Post = Exclude<Result, null>;
|
|
271
|
+
|
|
272
|
+
expectTypeOf<Post["_id"]>().toEqualTypeOf<FragnoId>();
|
|
273
|
+
expectTypeOf<Post["title"]>().toEqualTypeOf<string>();
|
|
274
|
+
expectTypeOf<Post["content"]>().toEqualTypeOf<string>();
|
|
275
|
+
expectTypeOf<Post["userId"]>().toEqualTypeOf<string>();
|
|
276
|
+
expectTypeOf<Post["publishedAt"]>().toEqualTypeOf<Date | null>();
|
|
277
|
+
expectTypeOf<Post["viewCount"]>().toEqualTypeOf<number>();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("should correctly infer column types for comments table", () => {
|
|
281
|
+
const _query = {} as AbstractQuery<TestSchema>;
|
|
282
|
+
type Result = Awaited<ReturnType<typeof _query.findFirst<"comments">>>;
|
|
283
|
+
type Comment = Exclude<Result, null>;
|
|
284
|
+
|
|
285
|
+
expectTypeOf<Comment["_id"]>().toEqualTypeOf<FragnoId>();
|
|
286
|
+
expectTypeOf<Comment["postId"]>().toEqualTypeOf<string>();
|
|
287
|
+
expectTypeOf<Comment["authorId"]>().toEqualTypeOf<string>();
|
|
288
|
+
expectTypeOf<Comment["text"]>().toEqualTypeOf<string>();
|
|
289
|
+
expectTypeOf<Comment["likes"]>().toEqualTypeOf<number | null>();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe("complex scenarios", () => {
|
|
294
|
+
it("should handle multiple table operations with correct types", () => {
|
|
295
|
+
const _query = {} as AbstractQuery<TestSchema>;
|
|
296
|
+
|
|
297
|
+
// Create user return type
|
|
298
|
+
type UserResult = Awaited<ReturnType<typeof _query.create<"users">>>;
|
|
299
|
+
expectTypeOf<UserResult>().toEqualTypeOf<FragnoId>();
|
|
300
|
+
|
|
301
|
+
// Create post return type
|
|
302
|
+
type PostResult = Awaited<ReturnType<typeof _query.create<"posts">>>;
|
|
303
|
+
expectTypeOf<PostResult>().toEqualTypeOf<FragnoId>();
|
|
304
|
+
|
|
305
|
+
// Find posts by user return type
|
|
306
|
+
type UserPostsResult = Awaited<
|
|
307
|
+
ReturnType<typeof _query.find<"posts", ["title", "viewCount"], object>>
|
|
308
|
+
>;
|
|
309
|
+
|
|
310
|
+
expectTypeOf<UserPostsResult>().toExtend<
|
|
311
|
+
{
|
|
312
|
+
title: string;
|
|
313
|
+
viewCount: number;
|
|
314
|
+
}[]
|
|
315
|
+
>();
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe("join", () => {
|
|
320
|
+
const userSchema = schema((s) => {
|
|
321
|
+
return s
|
|
322
|
+
.addTable("users", (t) => {
|
|
323
|
+
return t.addColumn("id", idColumn()).addColumn("name", column("string"));
|
|
324
|
+
})
|
|
325
|
+
.addTable("posts", (t) => {
|
|
326
|
+
return t
|
|
327
|
+
.addColumn("id", idColumn())
|
|
328
|
+
.addColumn("title", column("string"))
|
|
329
|
+
.addColumn("userId", referenceColumn());
|
|
330
|
+
})
|
|
331
|
+
.addTable("tags", (t) => {
|
|
332
|
+
return t.addColumn("id", idColumn()).addColumn("name", column("string"));
|
|
333
|
+
})
|
|
334
|
+
.addReference("author", {
|
|
335
|
+
type: "one",
|
|
336
|
+
from: { table: "posts", column: "userId" },
|
|
337
|
+
to: { table: "users", column: "id" },
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it("should handle join correctly", () => {
|
|
342
|
+
const _table = userSchema.tables.posts;
|
|
343
|
+
const _relations = _table.relations;
|
|
344
|
+
|
|
345
|
+
type _Relations = typeof _table.relations;
|
|
346
|
+
type Builder1 = JoinBuilder<typeof _table>;
|
|
347
|
+
|
|
348
|
+
expectTypeOf<Builder1>().toExtend<{
|
|
349
|
+
author: () => void;
|
|
350
|
+
}>();
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("FragnoId support", () => {
|
|
355
|
+
it("should accept FragnoId in insert values for id column", () => {
|
|
356
|
+
const fragnoId = FragnoId.fromExternal("user123", 0);
|
|
357
|
+
const _values: TableToInsertValues<typeof _testSchema.tables.users> = {
|
|
358
|
+
_id: fragnoId,
|
|
359
|
+
name: "John",
|
|
360
|
+
email: "john@example.com",
|
|
361
|
+
isActive: true,
|
|
362
|
+
};
|
|
363
|
+
// Verify the type accepts both string and FragnoId
|
|
364
|
+
type IdType = TableToInsertValues<typeof _testSchema.tables.users>["_id"];
|
|
365
|
+
expectTypeOf<string>().toExtend<IdType>();
|
|
366
|
+
expectTypeOf<FragnoId>().toExtend<IdType>();
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("should accept string in insert values for id column", () => {
|
|
370
|
+
const _values: TableToInsertValues<typeof _testSchema.tables.users> = {
|
|
371
|
+
_id: "user123",
|
|
372
|
+
name: "John",
|
|
373
|
+
email: "john@example.com",
|
|
374
|
+
isActive: true,
|
|
375
|
+
};
|
|
376
|
+
// Verify string is accepted
|
|
377
|
+
type IdType = TableToInsertValues<typeof _testSchema.tables.users>["_id"];
|
|
378
|
+
expectTypeOf<string>().toExtend<IdType>();
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("should accept FragnoId in where conditions", () => {
|
|
382
|
+
const fragnoId = FragnoId.fromExternal("user123", 0);
|
|
383
|
+
// This should compile without errors
|
|
384
|
+
const condition = (eb: ConditionBuilder<typeof _testSchema.tables.users.columns>) =>
|
|
385
|
+
eb("_id", "=", fragnoId);
|
|
386
|
+
expectTypeOf(condition).toBeFunction();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("should accept FragnoId in array where conditions", () => {
|
|
390
|
+
const fragnoId1 = FragnoId.fromExternal("user123", 0);
|
|
391
|
+
const fragnoId2 = FragnoId.fromExternal("user456", 0);
|
|
392
|
+
// This should compile without errors
|
|
393
|
+
const condition = (eb: ConditionBuilder<typeof _testSchema.tables.users.columns>) =>
|
|
394
|
+
eb("_id", "in", [fragnoId1, fragnoId2, "user789"]);
|
|
395
|
+
expectTypeOf(condition).toBeFunction();
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
it("should accept FragnoId with both external and internal IDs", () => {
|
|
399
|
+
const fragnoId = new FragnoId({
|
|
400
|
+
externalId: "user123",
|
|
401
|
+
internalId: 1n,
|
|
402
|
+
version: 1,
|
|
403
|
+
});
|
|
404
|
+
const _values: TableToInsertValues<typeof _testSchema.tables.posts> = {
|
|
405
|
+
_id: fragnoId,
|
|
406
|
+
title: "Test Post",
|
|
407
|
+
content: "Content",
|
|
408
|
+
userId: "user123",
|
|
409
|
+
viewCount: 0,
|
|
410
|
+
};
|
|
411
|
+
// Verify FragnoId is accepted for id columns
|
|
412
|
+
type IdType = TableToInsertValues<typeof _testSchema.tables.posts>["_id"];
|
|
413
|
+
expectTypeOf<FragnoId>().toExtend<IdType>();
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it("should not accept FragnoId for non-id columns", () => {
|
|
417
|
+
const _values: TableToInsertValues<typeof _testSchema.tables.users> = {
|
|
418
|
+
_id: "user123",
|
|
419
|
+
name: "John",
|
|
420
|
+
email: "john@example.com",
|
|
421
|
+
isActive: true,
|
|
422
|
+
};
|
|
423
|
+
// This should be a type error if we try to use FragnoId for name
|
|
424
|
+
type NameType = TableToInsertValues<typeof _testSchema.tables.users>["name"];
|
|
425
|
+
expectTypeOf<NameType>().toExtend<string>();
|
|
426
|
+
expectTypeOf<NameType>().not.toExtend<FragnoId>();
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
});
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { IdColumn, AnySchema, AnyTable, Relation, FragnoId } from "../schema/create";
|
|
2
|
+
import type { Condition, ConditionBuilder } from "./condition-builder";
|
|
3
|
+
import type {
|
|
4
|
+
UnitOfWork,
|
|
5
|
+
FindBuilder,
|
|
6
|
+
UpdateBuilder,
|
|
7
|
+
DeleteBuilder,
|
|
8
|
+
UpdateManyBuilder,
|
|
9
|
+
} from "./unit-of-work";
|
|
10
|
+
import type { Prettify } from "../util/types";
|
|
11
|
+
|
|
12
|
+
export type AnySelectClause = SelectClause<AnyTable>;
|
|
13
|
+
|
|
14
|
+
export type SelectClause<T extends AnyTable> = true | (keyof T["columns"])[];
|
|
15
|
+
|
|
16
|
+
export type RawColumnValues<T extends AnyTable> = {
|
|
17
|
+
[K in keyof T["columns"] as string extends K ? never : K]: T["columns"][K]["$out"];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TableToColumnValues<T extends AnyTable> = RawColumnValues<T>;
|
|
21
|
+
|
|
22
|
+
type PickNullable<T> = {
|
|
23
|
+
[P in keyof T as null extends T[P] ? P : never]: T[P];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type PickNotNullable<T> = {
|
|
27
|
+
[P in keyof T as null extends T[P] ? never : P]: T[P];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type RawInsertValues<T extends AnyTable> = {
|
|
31
|
+
[K in keyof T["columns"] as string extends K ? never : K]: T["columns"][K]["$in"];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type TableToInsertValues<T extends AnyTable> = Prettify<
|
|
35
|
+
Partial<PickNullable<RawInsertValues<T>>> & PickNotNullable<RawInsertValues<T>>
|
|
36
|
+
>;
|
|
37
|
+
|
|
38
|
+
export type TableToUpdateValues<T extends AnyTable> = {
|
|
39
|
+
[K in keyof T["columns"] as string extends K ? never : K]?: T["columns"][K] extends IdColumn
|
|
40
|
+
? never
|
|
41
|
+
: T["columns"][K]["$in"];
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
type MainSelectResult<S extends SelectClause<T>, T extends AnyTable> = S extends true
|
|
45
|
+
? TableToColumnValues<T>
|
|
46
|
+
: S extends (keyof T["columns"])[]
|
|
47
|
+
? {
|
|
48
|
+
[K in S[number] as string extends K ? never : K]: K extends keyof T["columns"]
|
|
49
|
+
? T["columns"][K]["$out"]
|
|
50
|
+
: never;
|
|
51
|
+
}
|
|
52
|
+
: never;
|
|
53
|
+
|
|
54
|
+
export type SelectResult<
|
|
55
|
+
T extends AnyTable,
|
|
56
|
+
JoinOut,
|
|
57
|
+
Select extends SelectClause<T>,
|
|
58
|
+
> = MainSelectResult<Select, T> & JoinOut;
|
|
59
|
+
|
|
60
|
+
interface MapRelationType<Type> {
|
|
61
|
+
one: Type | null;
|
|
62
|
+
many: Type[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type JoinBuilder<T extends AnyTable, Out = {}> = {
|
|
66
|
+
[K in keyof T["relations"]]: T["relations"][K] extends Relation<infer Type, infer Target>
|
|
67
|
+
? <Select extends SelectClause<Target> = true, JoinOut = {}>(
|
|
68
|
+
options?: FindManyOptions<Target, Select, JoinOut, false>,
|
|
69
|
+
) => JoinBuilder<
|
|
70
|
+
T,
|
|
71
|
+
Out & {
|
|
72
|
+
[$K in K]: MapRelationType<SelectResult<Target, JoinOut, Select>>[Type];
|
|
73
|
+
}
|
|
74
|
+
>
|
|
75
|
+
: never;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type OrderBy<Column = string> = [columnName: Column, "asc" | "desc"];
|
|
79
|
+
|
|
80
|
+
export type FindFirstOptions<
|
|
81
|
+
T extends AnyTable = AnyTable,
|
|
82
|
+
Select extends SelectClause<T> = SelectClause<T>,
|
|
83
|
+
JoinOut = {},
|
|
84
|
+
IsRoot extends boolean = true,
|
|
85
|
+
> = Omit<
|
|
86
|
+
FindManyOptions<T, Select, JoinOut, IsRoot>,
|
|
87
|
+
IsRoot extends true ? "limit" : "limit" | "offset" | "orderBy"
|
|
88
|
+
>;
|
|
89
|
+
|
|
90
|
+
export type FindManyOptions<
|
|
91
|
+
T extends AnyTable = AnyTable,
|
|
92
|
+
Select extends SelectClause<T> = SelectClause<T>,
|
|
93
|
+
_JoinOut = {},
|
|
94
|
+
IsRoot extends boolean = true,
|
|
95
|
+
> = {
|
|
96
|
+
select?: Select;
|
|
97
|
+
where?: (eb: ConditionBuilder<T["columns"]>) => Condition | boolean;
|
|
98
|
+
limit?: number;
|
|
99
|
+
orderBy?: OrderBy<keyof T["columns"]> | OrderBy<keyof T["columns"]>[];
|
|
100
|
+
join?: (jb: JoinBuilder<T>) => void;
|
|
101
|
+
} & (IsRoot extends true
|
|
102
|
+
? {
|
|
103
|
+
// drizzle doesn't support `offset` in join queries (this may be changed in future, we can add it back)
|
|
104
|
+
offset?: number;
|
|
105
|
+
}
|
|
106
|
+
: {});
|
|
107
|
+
|
|
108
|
+
export interface AbstractQuery<TSchema extends AnySchema, TUOWConfig = void> {
|
|
109
|
+
/**
|
|
110
|
+
* Find multiple records using a builder pattern
|
|
111
|
+
*/
|
|
112
|
+
find: <
|
|
113
|
+
TableName extends keyof TSchema["tables"] & string,
|
|
114
|
+
Select extends SelectClause<TSchema["tables"][TableName]> = true,
|
|
115
|
+
JoinOut = {},
|
|
116
|
+
>(
|
|
117
|
+
table: TableName,
|
|
118
|
+
builderFn?: (
|
|
119
|
+
builder: Omit<FindBuilder<TSchema["tables"][TableName]>, "build">,
|
|
120
|
+
) => Omit<FindBuilder<TSchema["tables"][TableName], Select, JoinOut>, "build">,
|
|
121
|
+
) => Promise<SelectResult<TSchema["tables"][TableName], JoinOut, Select>[]>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Find the first record matching the criteria
|
|
125
|
+
* Implemented as a wrapper around find() with pageSize(1)
|
|
126
|
+
*/
|
|
127
|
+
findFirst: <
|
|
128
|
+
TableName extends keyof TSchema["tables"] & string,
|
|
129
|
+
Select extends SelectClause<TSchema["tables"][TableName]> = true,
|
|
130
|
+
JoinOut = {},
|
|
131
|
+
>(
|
|
132
|
+
table: TableName,
|
|
133
|
+
builderFn?: (
|
|
134
|
+
builder: Omit<FindBuilder<TSchema["tables"][TableName]>, "build">,
|
|
135
|
+
) => Omit<FindBuilder<TSchema["tables"][TableName], Select, JoinOut>, "build">,
|
|
136
|
+
) => Promise<SelectResult<TSchema["tables"][TableName], JoinOut, Select> | null>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Create a single record
|
|
140
|
+
* @returns The ID of the created record
|
|
141
|
+
*/
|
|
142
|
+
create: <TableName extends keyof TSchema["tables"] & string>(
|
|
143
|
+
table: TableName,
|
|
144
|
+
values: TableToInsertValues<TSchema["tables"][TableName]>,
|
|
145
|
+
) => Promise<FragnoId>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Create multiple records
|
|
149
|
+
* @returns Array of IDs of the created records
|
|
150
|
+
*/
|
|
151
|
+
createMany: <TableName extends keyof TSchema["tables"] & string>(
|
|
152
|
+
table: TableName,
|
|
153
|
+
values: TableToInsertValues<TSchema["tables"][TableName]>[],
|
|
154
|
+
) => Promise<FragnoId[]>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Update a single record by ID
|
|
158
|
+
* Note: you cannot update the id of a row, some databases don't support that (including MongoDB).
|
|
159
|
+
*/
|
|
160
|
+
update: <TableName extends keyof TSchema["tables"] & string>(
|
|
161
|
+
table: TableName,
|
|
162
|
+
id: FragnoId | string,
|
|
163
|
+
builderFn: (
|
|
164
|
+
builder: Omit<UpdateBuilder<TSchema["tables"][TableName]>, "build" | "check">,
|
|
165
|
+
) => Omit<UpdateBuilder<TSchema["tables"][TableName]>, "build">,
|
|
166
|
+
) => Promise<void>;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Update multiple records matching a where clause
|
|
170
|
+
* Note: you cannot update the id of a row, some databases don't support that (including MongoDB).
|
|
171
|
+
*/
|
|
172
|
+
updateMany: <TableName extends keyof TSchema["tables"] & string>(
|
|
173
|
+
table: TableName,
|
|
174
|
+
builderFn: (builder: UpdateManyBuilder<TSchema["tables"][TableName]>) => void,
|
|
175
|
+
) => Promise<void>;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Delete a single record by ID
|
|
179
|
+
*/
|
|
180
|
+
delete: <TableName extends keyof TSchema["tables"] & string>(
|
|
181
|
+
table: TableName,
|
|
182
|
+
id: FragnoId | string,
|
|
183
|
+
builderFn?: (builder: Omit<DeleteBuilder, "build">) => Omit<DeleteBuilder, "build" | "check">,
|
|
184
|
+
) => Promise<void>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Delete multiple records matching a where clause
|
|
188
|
+
*/
|
|
189
|
+
deleteMany: <TableName extends keyof TSchema["tables"] & string>(
|
|
190
|
+
table: TableName,
|
|
191
|
+
builderFn: (
|
|
192
|
+
builder: Omit<FindBuilder<TSchema["tables"][TableName]>, "build" | "check">,
|
|
193
|
+
) => void,
|
|
194
|
+
) => Promise<void>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Create a Unit of Work bound to this query engine
|
|
198
|
+
*/
|
|
199
|
+
createUnitOfWork: (name?: string, config?: TUOWConfig) => UnitOfWork<TSchema, []>;
|
|
200
|
+
}
|