@xata.io/drizzle 0.0.0-alpha.vcf8f11cade1aeb5e318fc16f42ddc96e46b17b8e → 0.0.0-alpha.vcfebdb3456448b48e0e754c70082ac82ec57911e
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 +14 -3
- package/CHANGELOG.md +51 -3
- package/dist/index.cjs +54 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +22 -13
- package/dist/index.mjs +56 -43
- package/dist/index.mjs.map +1 -1
- package/dist/pg.cjs +212 -0
- package/dist/pg.cjs.map +1 -0
- package/dist/pg.d.ts +61 -0
- package/dist/pg.mjs +206 -0
- package/dist/pg.mjs.map +1 -0
- package/package.json +11 -6
- package/test/{pg.test.ts → drizzle.test.ts} +269 -262
@@ -1,6 +1,6 @@
|
|
1
1
|
import { BaseClient, HostProvider, parseProviderString, XataApiClient } from '@xata.io/client';
|
2
2
|
import 'dotenv/config';
|
3
|
-
import { desc, eq, gt, gte, or, placeholder, sql
|
3
|
+
import { desc, DrizzleError, eq, gt, gte, or, placeholder, sql } from 'drizzle-orm';
|
4
4
|
import { Client } from 'pg';
|
5
5
|
import { afterAll, afterEach, beforeAll, beforeEach, describe, expectTypeOf, test } from 'vitest';
|
6
6
|
import { drizzle as drizzlePg, type XataDatabase } from '../src/pg';
|
@@ -9,7 +9,7 @@ import * as schema from './schema';
|
|
9
9
|
|
10
10
|
const { usersTable, postsTable, commentsTable, usersToGroupsTable, groupsTable } = schema;
|
11
11
|
|
12
|
-
const ENABLE_LOGGING =
|
12
|
+
const ENABLE_LOGGING = false;
|
13
13
|
|
14
14
|
declare module 'vitest' {
|
15
15
|
export interface TestContext {
|
@@ -25,10 +25,13 @@ if (apiKey === '') throw new Error('XATA_API_KEY environment variable is not set
|
|
25
25
|
const workspace = (process.env.XATA_WORKSPACE ?? '').split('-').pop() ?? '';
|
26
26
|
if (workspace === '') throw new Error('XATA_WORKSPACE environment variable is not set');
|
27
27
|
|
28
|
-
const region = process.env.XATA_REGION || 'eu-west-1';
|
29
|
-
|
30
28
|
const host = parseProviderString(process.env.XATA_API_PROVIDER) ?? 'production';
|
31
29
|
|
30
|
+
// TODO: Branches for pgroll only work in some regions for now
|
31
|
+
// const region = process.env.XATA_REGION || 'us-east-1';
|
32
|
+
const region =
|
33
|
+
host === 'production' ? 'us-east-1' : host === 'staging' ? 'eu-west-1' : process.env.XATA_REGION || 'us-east-1';
|
34
|
+
|
32
35
|
const database = `drizzle-test-${Math.random().toString(36).substring(7)}`;
|
33
36
|
|
34
37
|
const api = new XataApiClient({ apiKey, host, clientName: 'sdk-tests' });
|
@@ -48,27 +51,47 @@ function getDomain(host: HostProvider) {
|
|
48
51
|
}
|
49
52
|
}
|
50
53
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
function getDrizzleClient(type: string, branch: string) {
|
55
|
+
if (type === 'http') {
|
56
|
+
const xata = new BaseClient({
|
57
|
+
apiKey,
|
58
|
+
host,
|
59
|
+
clientName: 'sdk-tests',
|
60
|
+
databaseURL: `https://${workspace}.${region}.${getDomain(host)}/db/${database}`,
|
61
|
+
branch
|
62
|
+
});
|
58
63
|
|
59
|
-
|
64
|
+
return { db: drizzleHttp(xata, { schema, logger: ENABLE_LOGGING }) };
|
65
|
+
} else if (type === 'pg') {
|
66
|
+
const client = new Client({
|
67
|
+
connectionString: `postgresql://${workspace}:${apiKey}@${region}.sql.${getDomain(
|
68
|
+
host
|
69
|
+
)}:5432/${database}:${branch}`,
|
70
|
+
ssl: true
|
71
|
+
});
|
60
72
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
73
|
+
return { db: drizzlePg(client, { schema, logger: ENABLE_LOGGING }), client };
|
74
|
+
} else {
|
75
|
+
throw new Error(`Unknown type: ${type}`);
|
76
|
+
}
|
77
|
+
}
|
66
78
|
|
67
|
-
|
68
|
-
|
79
|
+
describe.concurrent.each([{ type: 'pg' }, { type: 'http' }])('Drizzle $type', ({ type }) => {
|
80
|
+
beforeAll(async () => {
|
81
|
+
await api.databases.createDatabase({
|
82
|
+
pathParams: { workspaceId: workspace, dbName: database },
|
83
|
+
body: { region, branchName: 'main' },
|
84
|
+
headers: { 'X-Features': 'feat-pgroll-migrations=1' }
|
85
|
+
});
|
69
86
|
|
70
|
-
|
71
|
-
|
87
|
+
await waitForReplication();
|
88
|
+
|
89
|
+
// For now, run the migrations via wire protocol
|
90
|
+
const { client, db } = getDrizzleClient('pg', 'main');
|
91
|
+
await client?.connect();
|
92
|
+
|
93
|
+
await db.execute(
|
94
|
+
sql`
|
72
95
|
CREATE TABLE "users" (
|
73
96
|
"id" serial PRIMARY KEY NOT NULL,
|
74
97
|
"name" text NOT NULL,
|
@@ -76,27 +99,27 @@ beforeAll(async () => {
|
|
76
99
|
"invited_by" int REFERENCES "users"("id")
|
77
100
|
);
|
78
101
|
`
|
79
|
-
|
80
|
-
|
81
|
-
|
102
|
+
);
|
103
|
+
await db.execute(
|
104
|
+
sql`
|
82
105
|
CREATE TABLE IF NOT EXISTS "groups" (
|
83
106
|
"id" serial PRIMARY KEY NOT NULL,
|
84
107
|
"name" text NOT NULL,
|
85
108
|
"description" text
|
86
109
|
);
|
87
110
|
`
|
88
|
-
|
89
|
-
|
90
|
-
|
111
|
+
);
|
112
|
+
await db.execute(
|
113
|
+
sql`
|
91
114
|
CREATE TABLE IF NOT EXISTS "users_to_groups" (
|
92
115
|
"id" serial PRIMARY KEY NOT NULL,
|
93
116
|
"user_id" int REFERENCES "users"("id"),
|
94
117
|
"group_id" int REFERENCES "groups"("id")
|
95
118
|
);
|
96
119
|
`
|
97
|
-
|
98
|
-
|
99
|
-
|
120
|
+
);
|
121
|
+
await db.execute(
|
122
|
+
sql`
|
100
123
|
CREATE TABLE IF NOT EXISTS "posts" (
|
101
124
|
"id" serial PRIMARY KEY NOT NULL,
|
102
125
|
"content" text NOT NULL,
|
@@ -104,9 +127,9 @@ beforeAll(async () => {
|
|
104
127
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
105
128
|
);
|
106
129
|
`
|
107
|
-
|
108
|
-
|
109
|
-
|
130
|
+
);
|
131
|
+
await db.execute(
|
132
|
+
sql`
|
110
133
|
CREATE TABLE IF NOT EXISTS "comments" (
|
111
134
|
"id" serial PRIMARY KEY NOT NULL,
|
112
135
|
"content" text NOT NULL,
|
@@ -115,9 +138,9 @@ beforeAll(async () => {
|
|
115
138
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
116
139
|
);
|
117
140
|
`
|
118
|
-
|
119
|
-
|
120
|
-
|
141
|
+
);
|
142
|
+
await db.execute(
|
143
|
+
sql`
|
121
144
|
CREATE TABLE IF NOT EXISTS "comment_likes" (
|
122
145
|
"id" serial PRIMARY KEY NOT NULL,
|
123
146
|
"creator" int REFERENCES "users"("id"),
|
@@ -125,49 +148,32 @@ beforeAll(async () => {
|
|
125
148
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL
|
126
149
|
);
|
127
150
|
`
|
128
|
-
|
151
|
+
);
|
129
152
|
|
130
|
-
|
131
|
-
});
|
153
|
+
await client?.end();
|
154
|
+
});
|
132
155
|
|
133
|
-
afterAll(async () => {
|
134
|
-
|
135
|
-
});
|
156
|
+
afterAll(async () => {
|
157
|
+
await api.databases.deleteDatabase({ pathParams: { workspaceId: workspace, dbName: database } });
|
158
|
+
});
|
136
159
|
|
137
|
-
describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type', ({ type }) => {
|
138
160
|
beforeEach(async (ctx) => {
|
139
161
|
ctx.branch = `test-${Math.random().toString(36).substring(7)}`;
|
140
|
-
await api.
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
ctx.db = drizzleHttp(xata, { schema, logger: ENABLE_LOGGING });
|
152
|
-
} else if (type === 'pg') {
|
153
|
-
ctx.client = new Client({
|
154
|
-
connectionString: `postgresql://${workspace}:${apiKey}@${region}.sql.${getDomain(host)}:5432/${database}:${
|
155
|
-
ctx.branch
|
156
|
-
}`,
|
157
|
-
// Not sure why, but we are getting `error: SSL required` sometimes
|
158
|
-
ssl: { rejectUnauthorized: false }
|
159
|
-
});
|
160
|
-
|
161
|
-
await ctx.client.connect();
|
162
|
-
ctx.db = drizzlePg(ctx.client, { schema, logger: ENABLE_LOGGING });
|
163
|
-
} else {
|
164
|
-
throw new Error(`Unknown type: ${type}`);
|
165
|
-
}
|
162
|
+
await api.branch.createBranch({
|
163
|
+
pathParams: { workspace, region, dbBranchName: `${database}:${ctx.branch}` },
|
164
|
+
body: { from: 'main' }
|
165
|
+
});
|
166
|
+
|
167
|
+
const { db, client } = getDrizzleClient(type, ctx.branch);
|
168
|
+
await client?.connect();
|
169
|
+
|
170
|
+
ctx.db = db;
|
171
|
+
ctx.client = client;
|
166
172
|
});
|
167
173
|
|
168
174
|
afterEach(async (ctx) => {
|
169
175
|
await ctx.client?.end();
|
170
|
-
await api.
|
176
|
+
await api.branch.deleteBranch({ pathParams: { workspace, region, dbBranchName: `${database}:${ctx.branch}` } });
|
171
177
|
});
|
172
178
|
|
173
179
|
/*
|
@@ -887,133 +893,6 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
887
893
|
});
|
888
894
|
});
|
889
895
|
|
890
|
-
test.skip('[Find Many] Get users with posts in transaction', async (ctx) => {
|
891
|
-
let usersWithPosts: {
|
892
|
-
id: number;
|
893
|
-
name: string;
|
894
|
-
verified: boolean;
|
895
|
-
invitedBy: number | null;
|
896
|
-
posts: {
|
897
|
-
id: number;
|
898
|
-
content: string;
|
899
|
-
ownerId: number | null;
|
900
|
-
createdAt: Date;
|
901
|
-
}[];
|
902
|
-
}[] = [];
|
903
|
-
|
904
|
-
await ctx.db.transaction(async (tx) => {
|
905
|
-
await tx.insert(usersTable).values([
|
906
|
-
{ id: 1, name: 'Dan' },
|
907
|
-
{ id: 2, name: 'Andrew' },
|
908
|
-
{ id: 3, name: 'Alex' }
|
909
|
-
]);
|
910
|
-
|
911
|
-
await tx.insert(postsTable).values([
|
912
|
-
{ ownerId: 1, content: 'Post1' },
|
913
|
-
{ ownerId: 1, content: 'Post1.1' },
|
914
|
-
{ ownerId: 2, content: 'Post2' },
|
915
|
-
{ ownerId: 3, content: 'Post3' }
|
916
|
-
]);
|
917
|
-
|
918
|
-
usersWithPosts = await tx.query.usersTable.findMany({
|
919
|
-
where: ({ id }, { eq }) => eq(id, 1),
|
920
|
-
with: {
|
921
|
-
posts: {
|
922
|
-
where: ({ id }, { eq }) => eq(id, 1)
|
923
|
-
}
|
924
|
-
}
|
925
|
-
});
|
926
|
-
});
|
927
|
-
|
928
|
-
expectTypeOf(usersWithPosts).toEqualTypeOf<
|
929
|
-
{
|
930
|
-
id: number;
|
931
|
-
name: string;
|
932
|
-
verified: boolean;
|
933
|
-
invitedBy: number | null;
|
934
|
-
posts: {
|
935
|
-
id: number;
|
936
|
-
content: string;
|
937
|
-
ownerId: number | null;
|
938
|
-
createdAt: Date;
|
939
|
-
}[];
|
940
|
-
}[]
|
941
|
-
>();
|
942
|
-
|
943
|
-
ctx.expect(usersWithPosts.length).eq(1);
|
944
|
-
ctx.expect(usersWithPosts[0]?.posts.length).eq(1);
|
945
|
-
|
946
|
-
ctx.expect(usersWithPosts[0]).toEqual({
|
947
|
-
id: 1,
|
948
|
-
name: 'Dan',
|
949
|
-
verified: false,
|
950
|
-
invitedBy: null,
|
951
|
-
posts: [{ id: 1, ownerId: 1, content: 'Post1', createdAt: usersWithPosts[0]?.posts[0]?.createdAt }]
|
952
|
-
});
|
953
|
-
});
|
954
|
-
|
955
|
-
test.skip('[Find Many] Get users with posts in rollbacked transaction', async (ctx) => {
|
956
|
-
let usersWithPosts: {
|
957
|
-
id: number;
|
958
|
-
name: string;
|
959
|
-
verified: boolean;
|
960
|
-
invitedBy: number | null;
|
961
|
-
posts: {
|
962
|
-
id: number;
|
963
|
-
content: string;
|
964
|
-
ownerId: number | null;
|
965
|
-
createdAt: Date;
|
966
|
-
}[];
|
967
|
-
}[] = [];
|
968
|
-
|
969
|
-
await ctx
|
970
|
-
.expect(
|
971
|
-
ctx.db.transaction(async (tx) => {
|
972
|
-
await tx.insert(usersTable).values([
|
973
|
-
{ id: 1, name: 'Dan' },
|
974
|
-
{ id: 2, name: 'Andrew' },
|
975
|
-
{ id: 3, name: 'Alex' }
|
976
|
-
]);
|
977
|
-
|
978
|
-
await tx.insert(postsTable).values([
|
979
|
-
{ ownerId: 1, content: 'Post1' },
|
980
|
-
{ ownerId: 1, content: 'Post1.1' },
|
981
|
-
{ ownerId: 2, content: 'Post2' },
|
982
|
-
{ ownerId: 3, content: 'Post3' }
|
983
|
-
]);
|
984
|
-
|
985
|
-
tx.rollback();
|
986
|
-
|
987
|
-
usersWithPosts = await tx.query.usersTable.findMany({
|
988
|
-
where: ({ id }, { eq }) => eq(id, 1),
|
989
|
-
with: {
|
990
|
-
posts: {
|
991
|
-
where: ({ id }, { eq }) => eq(id, 1)
|
992
|
-
}
|
993
|
-
}
|
994
|
-
});
|
995
|
-
})
|
996
|
-
)
|
997
|
-
.rejects.toThrowError(new TransactionRollbackError());
|
998
|
-
|
999
|
-
expectTypeOf(usersWithPosts).toEqualTypeOf<
|
1000
|
-
{
|
1001
|
-
id: number;
|
1002
|
-
name: string;
|
1003
|
-
verified: boolean;
|
1004
|
-
invitedBy: number | null;
|
1005
|
-
posts: {
|
1006
|
-
id: number;
|
1007
|
-
content: string;
|
1008
|
-
ownerId: number | null;
|
1009
|
-
createdAt: Date;
|
1010
|
-
}[];
|
1011
|
-
}[]
|
1012
|
-
>();
|
1013
|
-
|
1014
|
-
ctx.expect(usersWithPosts.length).eq(0);
|
1015
|
-
});
|
1016
|
-
|
1017
896
|
// select only custom
|
1018
897
|
test('[Find Many] Get only custom fields', async (ctx) => {
|
1019
898
|
await ctx.db.insert(usersTable).values([
|
@@ -1330,7 +1209,7 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1330
1209
|
columns: {},
|
1331
1210
|
where: gte(postsTable.id, 2),
|
1332
1211
|
extras: ({ content }) => ({
|
1333
|
-
|
1212
|
+
contentLower: sql<string>`lower(${content})`.as('content_lower')
|
1334
1213
|
})
|
1335
1214
|
}
|
1336
1215
|
},
|
@@ -1344,7 +1223,7 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1344
1223
|
| {
|
1345
1224
|
lowerName: string;
|
1346
1225
|
posts: {
|
1347
|
-
|
1226
|
+
contentLower: string;
|
1348
1227
|
}[];
|
1349
1228
|
}
|
1350
1229
|
| undefined
|
@@ -1354,7 +1233,7 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1354
1233
|
|
1355
1234
|
ctx.expect(usersWithPosts).toEqual({
|
1356
1235
|
lowerName: 'dan',
|
1357
|
-
posts: [{
|
1236
|
+
posts: [{ contentLower: 'post1.2' }, { contentLower: 'post1.3' }]
|
1358
1237
|
});
|
1359
1238
|
});
|
1360
1239
|
|
@@ -1465,41 +1344,43 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1465
1344
|
});
|
1466
1345
|
|
1467
1346
|
// columns {}
|
1468
|
-
test
|
1347
|
+
test('[Find Many] Get select {}', async (ctx) => {
|
1469
1348
|
await ctx.db.insert(usersTable).values([
|
1470
1349
|
{ id: 1, name: 'Dan' },
|
1471
1350
|
{ id: 2, name: 'Andrew' },
|
1472
1351
|
{ id: 3, name: 'Alex' }
|
1473
1352
|
]);
|
1474
1353
|
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
ctx.expect(users[2]).toEqual({});
|
1354
|
+
await ctx
|
1355
|
+
.expect(
|
1356
|
+
async () =>
|
1357
|
+
await ctx.db.query.usersTable.findMany({
|
1358
|
+
columns: {}
|
1359
|
+
})
|
1360
|
+
)
|
1361
|
+
.rejects.toThrow(DrizzleError);
|
1484
1362
|
});
|
1485
1363
|
|
1486
1364
|
// columns {}
|
1487
|
-
test
|
1365
|
+
test('[Find One] Get select {}', async (ctx) => {
|
1488
1366
|
await ctx.db.insert(usersTable).values([
|
1489
1367
|
{ id: 1, name: 'Dan' },
|
1490
1368
|
{ id: 2, name: 'Andrew' },
|
1491
1369
|
{ id: 3, name: 'Alex' }
|
1492
1370
|
]);
|
1493
1371
|
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1372
|
+
await ctx
|
1373
|
+
.expect(
|
1374
|
+
async () =>
|
1375
|
+
await ctx.db.query.usersTable.findFirst({
|
1376
|
+
columns: {}
|
1377
|
+
})
|
1378
|
+
)
|
1379
|
+
.rejects.toThrow(DrizzleError);
|
1499
1380
|
});
|
1500
1381
|
|
1501
1382
|
// deep select {}
|
1502
|
-
test
|
1383
|
+
test('[Find Many] Get deep select {}', async (ctx) => {
|
1503
1384
|
await ctx.db.insert(usersTable).values([
|
1504
1385
|
{ id: 1, name: 'Dan' },
|
1505
1386
|
{ id: 2, name: 'Andrew' },
|
@@ -1512,24 +1393,23 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1512
1393
|
{ ownerId: 3, content: 'Post3' }
|
1513
1394
|
]);
|
1514
1395
|
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
ctx.expect(users[2]).toEqual({ posts: [{}] });
|
1396
|
+
await ctx
|
1397
|
+
.expect(
|
1398
|
+
async () =>
|
1399
|
+
await ctx.db.query.usersTable.findMany({
|
1400
|
+
columns: {},
|
1401
|
+
with: {
|
1402
|
+
posts: {
|
1403
|
+
columns: {}
|
1404
|
+
}
|
1405
|
+
}
|
1406
|
+
})
|
1407
|
+
)
|
1408
|
+
.rejects.toThrow(DrizzleError);
|
1529
1409
|
});
|
1530
1410
|
|
1531
1411
|
// deep select {}
|
1532
|
-
test
|
1412
|
+
test('[Find One] Get deep select {}', async (ctx) => {
|
1533
1413
|
await ctx.db.insert(usersTable).values([
|
1534
1414
|
{ id: 1, name: 'Dan' },
|
1535
1415
|
{ id: 2, name: 'Andrew' },
|
@@ -1542,16 +1422,19 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
1542
1422
|
{ ownerId: 3, content: 'Post3' }
|
1543
1423
|
]);
|
1544
1424
|
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1425
|
+
await ctx
|
1426
|
+
.expect(
|
1427
|
+
async () =>
|
1428
|
+
await ctx.db.query.usersTable.findFirst({
|
1429
|
+
columns: {},
|
1430
|
+
with: {
|
1431
|
+
posts: {
|
1432
|
+
columns: {}
|
1433
|
+
}
|
1434
|
+
}
|
1435
|
+
})
|
1436
|
+
)
|
1437
|
+
.rejects.toThrow(DrizzleError);
|
1555
1438
|
});
|
1556
1439
|
|
1557
1440
|
/*
|
@@ -4116,14 +3999,118 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
4116
3999
|
});
|
4117
4000
|
});
|
4118
4001
|
|
4002
|
+
test('Get user with posts and posts with comments and comments with owner where exists', async (ctx) => {
|
4003
|
+
await ctx.db.insert(usersTable).values([
|
4004
|
+
{ id: 1, name: 'Dan' },
|
4005
|
+
{ id: 2, name: 'Andrew' },
|
4006
|
+
{ id: 3, name: 'Alex' }
|
4007
|
+
]);
|
4008
|
+
|
4009
|
+
await ctx.db.insert(postsTable).values([
|
4010
|
+
{ id: 1, ownerId: 1, content: 'Post1' },
|
4011
|
+
{ id: 2, ownerId: 2, content: 'Post2' },
|
4012
|
+
{ id: 3, ownerId: 3, content: 'Post3' }
|
4013
|
+
]);
|
4014
|
+
|
4015
|
+
await ctx.db.insert(commentsTable).values([
|
4016
|
+
{ postId: 1, content: 'Comment1', creator: 2 },
|
4017
|
+
{ postId: 2, content: 'Comment2', creator: 2 },
|
4018
|
+
{ postId: 3, content: 'Comment3', creator: 3 }
|
4019
|
+
]);
|
4020
|
+
|
4021
|
+
const response = await ctx.db.query.usersTable.findMany({
|
4022
|
+
with: {
|
4023
|
+
posts: {
|
4024
|
+
with: {
|
4025
|
+
comments: {
|
4026
|
+
with: {
|
4027
|
+
author: true
|
4028
|
+
}
|
4029
|
+
}
|
4030
|
+
}
|
4031
|
+
}
|
4032
|
+
},
|
4033
|
+
where: (table, { exists, eq }) =>
|
4034
|
+
exists(
|
4035
|
+
ctx.db
|
4036
|
+
.select({ one: sql`1` })
|
4037
|
+
.from(usersTable)
|
4038
|
+
.where(eq(sql`1`, table.id))
|
4039
|
+
)
|
4040
|
+
});
|
4041
|
+
|
4042
|
+
expectTypeOf(response).toEqualTypeOf<
|
4043
|
+
{
|
4044
|
+
id: number;
|
4045
|
+
name: string;
|
4046
|
+
verified: boolean;
|
4047
|
+
invitedBy: number | null;
|
4048
|
+
posts: {
|
4049
|
+
id: number;
|
4050
|
+
content: string;
|
4051
|
+
ownerId: number | null;
|
4052
|
+
createdAt: Date;
|
4053
|
+
comments: {
|
4054
|
+
id: number;
|
4055
|
+
content: string;
|
4056
|
+
createdAt: Date;
|
4057
|
+
creator: number | null;
|
4058
|
+
postId: number | null;
|
4059
|
+
author: {
|
4060
|
+
id: number;
|
4061
|
+
name: string;
|
4062
|
+
verified: boolean;
|
4063
|
+
invitedBy: number | null;
|
4064
|
+
} | null;
|
4065
|
+
}[];
|
4066
|
+
}[];
|
4067
|
+
}[]
|
4068
|
+
>();
|
4069
|
+
|
4070
|
+
ctx.expect(response.length).eq(1);
|
4071
|
+
ctx.expect(response[0]?.posts.length).eq(1);
|
4072
|
+
|
4073
|
+
ctx.expect(response[0]?.posts[0]?.comments.length).eq(1);
|
4074
|
+
|
4075
|
+
ctx.expect(response[0]).toEqual({
|
4076
|
+
id: 1,
|
4077
|
+
name: 'Dan',
|
4078
|
+
verified: false,
|
4079
|
+
invitedBy: null,
|
4080
|
+
posts: [
|
4081
|
+
{
|
4082
|
+
id: 1,
|
4083
|
+
ownerId: 1,
|
4084
|
+
content: 'Post1',
|
4085
|
+
createdAt: response[0]?.posts[0]?.createdAt,
|
4086
|
+
comments: [
|
4087
|
+
{
|
4088
|
+
id: 1,
|
4089
|
+
content: 'Comment1',
|
4090
|
+
creator: 2,
|
4091
|
+
author: {
|
4092
|
+
id: 2,
|
4093
|
+
name: 'Andrew',
|
4094
|
+
verified: false,
|
4095
|
+
invitedBy: null
|
4096
|
+
},
|
4097
|
+
postId: 1,
|
4098
|
+
createdAt: response[0]?.posts[0]?.comments[0]?.createdAt
|
4099
|
+
}
|
4100
|
+
]
|
4101
|
+
}
|
4102
|
+
]
|
4103
|
+
});
|
4104
|
+
});
|
4105
|
+
|
4119
4106
|
/*
|
4120
|
-
One three-level relation + 1 first-level
|
4107
|
+
One three-level relation + 1 first-level relation
|
4121
4108
|
1. users+posts+comments+comment_owner
|
4122
4109
|
2. users+users
|
4123
4110
|
*/
|
4124
4111
|
|
4125
4112
|
/*
|
4126
|
-
One four-level relation users+posts+comments+
|
4113
|
+
One four-level relation users+posts+comments+comment_likes
|
4127
4114
|
*/
|
4128
4115
|
|
4129
4116
|
/*
|
@@ -4158,9 +4145,11 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
4158
4145
|
columns: {},
|
4159
4146
|
with: {
|
4160
4147
|
group: true
|
4161
|
-
}
|
4148
|
+
},
|
4149
|
+
orderBy: usersToGroupsTable.userId
|
4162
4150
|
}
|
4163
|
-
}
|
4151
|
+
},
|
4152
|
+
orderBy: usersTable.id
|
4164
4153
|
});
|
4165
4154
|
|
4166
4155
|
expectTypeOf(response).toEqualTypeOf<
|
@@ -4224,22 +4213,22 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
4224
4213
|
name: 'Alex',
|
4225
4214
|
verified: false,
|
4226
4215
|
invitedBy: null,
|
4227
|
-
usersToGroups: [
|
4216
|
+
usersToGroups: ctx.expect.arrayContaining([
|
4228
4217
|
{
|
4229
4218
|
group: {
|
4230
|
-
id:
|
4231
|
-
name: '
|
4219
|
+
id: 2,
|
4220
|
+
name: 'Group2',
|
4232
4221
|
description: null
|
4233
4222
|
}
|
4234
4223
|
},
|
4235
4224
|
{
|
4236
4225
|
group: {
|
4237
|
-
id:
|
4238
|
-
name: '
|
4226
|
+
id: 3,
|
4227
|
+
name: 'Group3',
|
4239
4228
|
description: null
|
4240
4229
|
}
|
4241
4230
|
}
|
4242
|
-
]
|
4231
|
+
])
|
4243
4232
|
});
|
4244
4233
|
});
|
4245
4234
|
|
@@ -6035,7 +6024,8 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
6035
6024
|
lower: sql<string>`lower(${groupsTable.name})`.as('lower_name')
|
6036
6025
|
}
|
6037
6026
|
}
|
6038
|
-
}
|
6027
|
+
},
|
6028
|
+
orderBy: usersToGroupsTable.groupId
|
6039
6029
|
}
|
6040
6030
|
}
|
6041
6031
|
});
|
@@ -6111,17 +6101,17 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
6111
6101
|
usersToGroups: [
|
6112
6102
|
{
|
6113
6103
|
group: {
|
6114
|
-
id:
|
6115
|
-
name: '
|
6116
|
-
lower: '
|
6104
|
+
id: 2,
|
6105
|
+
name: 'Group2',
|
6106
|
+
lower: 'group2',
|
6117
6107
|
description: null
|
6118
6108
|
}
|
6119
6109
|
},
|
6120
6110
|
{
|
6121
6111
|
group: {
|
6122
|
-
id:
|
6123
|
-
name: '
|
6124
|
-
lower: '
|
6112
|
+
id: 3,
|
6113
|
+
name: 'Group3',
|
6114
|
+
lower: 'group3',
|
6125
6115
|
description: null
|
6126
6116
|
}
|
6127
6117
|
}
|
@@ -6257,6 +6247,23 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
6257
6247
|
});
|
6258
6248
|
});
|
6259
6249
|
|
6250
|
+
test('Filter by columns not present in select', async (ctx) => {
|
6251
|
+
await ctx.db.insert(usersTable).values([
|
6252
|
+
{ id: 1, name: 'Dan' },
|
6253
|
+
{ id: 2, name: 'Andrew' },
|
6254
|
+
{ id: 3, name: 'Alex' }
|
6255
|
+
]);
|
6256
|
+
|
6257
|
+
const response = await ctx.db.query.usersTable.findFirst({
|
6258
|
+
columns: {
|
6259
|
+
id: true
|
6260
|
+
},
|
6261
|
+
where: eq(usersTable.name, 'Dan')
|
6262
|
+
});
|
6263
|
+
|
6264
|
+
ctx.expect(response).toEqual({ id: 1 });
|
6265
|
+
});
|
6266
|
+
|
6260
6267
|
test('.toSQL()', (ctx) => {
|
6261
6268
|
const query = ctx.db.query.usersTable.findFirst().toSQL();
|
6262
6269
|
|
@@ -6279,10 +6286,10 @@ describe.concurrent.each([{ type: 'pg' } /**{ type: 'http' }**/])('Drizzle $type
|
|
6279
6286
|
|
6280
6287
|
async function waitForReplication(): Promise<void> {
|
6281
6288
|
try {
|
6282
|
-
await api.branches.getBranchList({ workspace, database, region });
|
6283
|
-
} catch (error) {
|
6284
|
-
console.log(`Waiting for create database replication to finish...`);
|
6285
6289
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
6290
|
+
await api.branch.getBranchList({ pathParams: { workspace, dbName: database, region } });
|
6291
|
+
} catch (error) {
|
6292
|
+
console.log(`Replication not ready yet, retrying...`);
|
6286
6293
|
return await waitForReplication();
|
6287
6294
|
}
|
6288
6295
|
}
|