Skip to content
This repository was archived by the owner on Oct 30, 2024. It is now read-only.

Commit 98ea0ba

Browse files
committed
feat(sql): use TypedSQL for all queryRaw and kysely queries
1 parent bdfe8e1 commit 98ea0ba

14 files changed

+113
-2117
lines changed

package-lock.json

+48-2,006
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"dx:down": "docker compose -f docker/development/compose.yml down",
1919
"ci": "turbo run test:e2e",
2020
"prisma:generate": "npm run with:env -- npm run prisma:generate -w @documenso/prisma",
21+
"prisma:generate-sql": "npm run with:env -- npm run prisma:generate-sql -w @documenso/prisma",
2122
"prisma:migrate-dev": "npm run with:env -- npm run prisma:migrate-dev -w @documenso/prisma",
2223
"prisma:migrate-deploy": "npm run with:env -- npm run prisma:migrate-deploy -w @documenso/prisma",
2324
"prisma:migrate-reset": "npm run with:env -- npm run prisma:migrate-reset -w @documenso/prisma",

packages/lib/package.json

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"clean": "rimraf node_modules"
1717
},
1818
"dependencies": {
19-
"@auth/kysely-adapter": "^0.6.0",
2019
"@aws-sdk/client-s3": "^3.410.0",
2120
"@aws-sdk/cloudfront-signer": "^3.410.0",
2221
"@aws-sdk/s3-request-presigner": "^3.410.0",
@@ -37,7 +36,6 @@
3736
"@upstash/redis": "^1.20.6",
3837
"@vvo/tzdb": "^6.117.0",
3938
"inngest": "^3.19.13",
40-
"kysely": "^0.26.3",
4139
"luxon": "^3.4.0",
4240
"micro": "^10.0.1",
4341
"nanoid": "^4.0.2",
@@ -59,4 +57,4 @@
5957
"@types/luxon": "^3.3.1",
6058
"@types/pg": "^8.11.4"
6159
}
62-
}
60+
}

packages/lib/server-only/admin/get-users-stats.ts

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DateTime } from 'luxon';
22

3-
import { prisma } from '@documenso/prisma';
3+
import { SQL, prisma } from '@documenso/prisma';
44
import { DocumentStatus, SubscriptionStatus } from '@documenso/prisma/client';
55

66
export const getUsersCount = async () => {
@@ -56,23 +56,8 @@ export type GetUserWithDocumentMonthlyGrowth = Array<{
5656
signed_count: number;
5757
}>;
5858

59-
type GetUserWithDocumentMonthlyGrowthQueryResult = Array<{
60-
month: Date;
61-
count: bigint;
62-
signed_count: bigint;
63-
}>;
64-
6559
export const getUserWithSignedDocumentMonthlyGrowth = async () => {
66-
const result = await prisma.$queryRaw<GetUserWithDocumentMonthlyGrowthQueryResult>`
67-
SELECT
68-
DATE_TRUNC('month', "Document"."createdAt") AS "month",
69-
COUNT(DISTINCT "Document"."userId") as "count",
70-
COUNT(DISTINCT CASE WHEN "Document"."status" = 'COMPLETED' THEN "Document"."userId" END) as "signed_count"
71-
FROM "Document"
72-
GROUP BY "month"
73-
ORDER BY "month" DESC
74-
LIMIT 12
75-
`;
60+
const result = await prisma.$queryRawTyped(SQL.userWithSignedDocumentMonthlyGrowth());
7661

7762
return result.map((row) => ({
7863
month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'),

packages/lib/server-only/user/get-monthly-completed-document.ts

+2-20
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,9 @@
11
import { DateTime } from 'luxon';
22

3-
import { kyselyPrisma, sql } from '@documenso/prisma';
4-
import { DocumentStatus } from '@documenso/prisma/client';
3+
import { SQL, prisma } from '@documenso/prisma';
54

65
export const getCompletedDocumentsMonthly = async () => {
7-
const qb = kyselyPrisma.$kysely
8-
.selectFrom('Document')
9-
.select(({ fn }) => [
10-
fn<Date>('DATE_TRUNC', [sql.lit('MONTH'), 'Document.updatedAt']).as('month'),
11-
fn.count('id').as('count'),
12-
fn
13-
.sum(fn.count('id'))
14-
// Feels like a bug in the Kysely extension but I just can not do this orderBy in a type-safe manner
15-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
16-
.over((ob) => ob.orderBy(fn('DATE_TRUNC', [sql.lit('MONTH'), 'Document.updatedAt']) as any))
17-
.as('cume_count'),
18-
])
19-
.where(() => sql`"Document"."status" = ${DocumentStatus.COMPLETED}::"DocumentStatus"`)
20-
.groupBy('month')
21-
.orderBy('month', 'desc')
22-
.limit(12);
23-
24-
const result = await qb.execute();
6+
const result = await prisma.$queryRawTyped(SQL.completedDocumentsMonthly());
257

268
return result.map((row) => ({
279
month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'),

packages/lib/server-only/user/get-signer-conversion.ts

+2-19
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,9 @@
11
import { DateTime } from 'luxon';
22

3-
import { kyselyPrisma, sql } from '@documenso/prisma';
3+
import { SQL, prisma } from '@documenso/prisma';
44

55
export const getSignerConversionMonthly = async () => {
6-
const qb = kyselyPrisma.$kysely
7-
.selectFrom('Recipient')
8-
.innerJoin('User', 'Recipient.email', 'User.email')
9-
.select(({ fn }) => [
10-
fn<Date>('DATE_TRUNC', [sql.lit('MONTH'), 'User.createdAt']).as('month'),
11-
fn.count('Recipient.email').distinct().as('count'),
12-
fn
13-
.sum(fn.count('Recipient.email').distinct())
14-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
15-
.over((ob) => ob.orderBy(fn('DATE_TRUNC', [sql.lit('MONTH'), 'User.createdAt']) as any))
16-
.as('cume_count'),
17-
])
18-
.where('Recipient.signedAt', 'is not', null)
19-
.where('Recipient.signedAt', '<', (eb) => eb.ref('User.createdAt'))
20-
.groupBy(({ fn }) => fn('DATE_TRUNC', [sql.lit('MONTH'), 'User.createdAt']))
21-
.orderBy('month', 'desc');
22-
23-
const result = await qb.execute();
6+
const result = await prisma.$queryRawTyped(SQL.signerConversionMonthly());
247

258
return result.map((row) => ({
269
month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'),

packages/lib/server-only/user/get-user-monthly-growth.ts

+2-18
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,9 @@
11
import { DateTime } from 'luxon';
22

3-
import { kyselyPrisma, sql } from '@documenso/prisma';
3+
import { SQL, prisma } from '@documenso/prisma';
44

55
export const getUserMonthlyGrowth = async () => {
6-
const qb = kyselyPrisma.$kysely
7-
.selectFrom('User')
8-
.select(({ fn }) => [
9-
fn<Date>('DATE_TRUNC', [sql.lit('MONTH'), 'User.createdAt']).as('month'),
10-
fn.count('id').as('count'),
11-
fn
12-
.sum(fn.count('id'))
13-
// Feels like a bug in the Kysely extension but I just can not do this orderBy in a type-safe manner
14-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
15-
.over((ob) => ob.orderBy(fn('DATE_TRUNC', [sql.lit('MONTH'), 'User.createdAt']) as any))
16-
.as('cume_count'),
17-
])
18-
.groupBy('month')
19-
.orderBy('month', 'desc')
20-
.limit(12);
21-
22-
const result = await qb.execute();
6+
const result = await prisma.$queryRawTyped(SQL.userMonthlyGrowth());
237

248
return result.map((row) => ({
259
month: DateTime.fromJSDate(row.month).toFormat('yyyy-MM'),

packages/prisma/index.ts

+17-24
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,25 @@
11
import { PrismaClient } from '@prisma/client';
2-
import { withOptimize } from '@prisma/extension-optimize';
3-
import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from 'kysely';
4-
import kyselyExtension from 'prisma-extension-kysely';
52

6-
import type { DB } from './generated/types';
73
import { getDatabaseUrl } from './helper';
4+
import {
5+
completedDocumentsMonthly,
6+
signerConversionMonthly,
7+
userMonthlyGrowth,
8+
userWithSignedDocumentMonthlyGrowth,
9+
} from './node_modules/.prisma/client/sql';
810
import { remember } from './utils/remember';
911

10-
export const prisma = remember('prisma', () =>
11-
new PrismaClient({
12-
datasourceUrl: getDatabaseUrl(),
13-
}).$extends(withOptimize()),
14-
);
15-
16-
export const kyselyPrisma = remember('kyselyPrisma', () =>
17-
prisma.$extends(
18-
kyselyExtension({
19-
kysely: (driver) =>
20-
new Kysely<DB>({
21-
dialect: {
22-
createAdapter: () => new PostgresAdapter(),
23-
createDriver: () => driver,
24-
createIntrospector: (db) => new PostgresIntrospector(db),
25-
createQueryCompiler: () => new PostgresQueryCompiler(),
26-
},
27-
}),
12+
export const prisma = remember(
13+
'prisma',
14+
() =>
15+
new PrismaClient({
16+
datasourceUrl: getDatabaseUrl(),
2817
}),
29-
),
3018
);
3119

32-
export { sql } from 'kysely';
20+
export const SQL = {
21+
completedDocumentsMonthly,
22+
signerConversionMonthly,
23+
userMonthlyGrowth,
24+
userWithSignedDocumentMonthlyGrowth,
25+
};

packages/prisma/package.json

+3-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"clean": "rimraf node_modules",
1212
"post-install": "prisma generate",
1313
"prisma:generate": "prisma generate",
14+
"prisma:generate-sql": "prisma generate --sql",
1415
"prisma:migrate-dev": "prisma migrate dev --skip-seed",
1516
"prisma:migrate-deploy": "prisma migrate deploy",
1617
"prisma:migrate-reset": "prisma migrate reset",
@@ -21,17 +22,13 @@
2122
"seed": "tsx ./seed-database.ts"
2223
},
2324
"dependencies": {
24-
"@prisma/client": "5.17.0",
25-
"kysely": "^0.27.3",
26-
"prisma": "5.17.0",
27-
"prisma-extension-kysely": "^2.1.0",
25+
"@prisma/client": "5.18.0-integration-feat-typed-sql.1",
26+
"prisma": "5.18.0-integration-feat-typed-sql.1",
2827
"ts-pattern": "^5.0.6"
2928
},
3029
"devDependencies": {
31-
"@prisma/extension-optimize": "^0.10.0",
3230
"dotenv": "^16.3.1",
3331
"dotenv-cli": "^7.3.0",
34-
"prisma-kysely": "^1.8.0",
3532
"tsx": "^4.11.0",
3633
"typescript": "5.2.2"
3734
}

packages/prisma/schema.prisma

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
generator kysely {
2-
provider = "prisma-kysely"
3-
}
4-
51
generator client {
62
provider = "prisma-client-js"
73
previewFeatures = ["tracing"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
SELECT
2+
DATE_TRUNC('month', "updatedAt") AS "month",
3+
COUNT("id") as "count",
4+
SUM(COUNT("id")) OVER (ORDER BY DATE_TRUNC('month', "updatedAt")) as "cume_count"
5+
FROM "Document"
6+
WHERE "status" = 'COMPLETED'
7+
GROUP BY "month"
8+
ORDER BY "month" DESC
9+
LIMIT 12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
SELECT
2+
DATE_TRUNC('month', "User"."createdAt") AS "month",
3+
COUNT(DISTINCT "Recipient"."email") as "count",
4+
SUM(COUNT(DISTINCT "Recipient"."email")) OVER (ORDER BY DATE_TRUNC('month', "User"."createdAt")) as "cume_count"
5+
FROM "Recipient"
6+
INNER JOIN "User" ON "Recipient"."email" = "User"."email"
7+
WHERE "Recipient"."signedAt" IS NOT NULL
8+
AND "Recipient"."signedAt" < "User"."createdAt"
9+
GROUP BY DATE_TRUNC('month', "User"."createdAt")
10+
ORDER BY "month" DESC
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
SELECT
2+
DATE_TRUNC('MONTH', "User"."createdAt") AS "month",
3+
COUNT("id") AS "count",
4+
SUM(COUNT("id")) OVER (ORDER BY DATE_TRUNC('MONTH', "User"."createdAt")) AS "cume_count"
5+
FROM "User"
6+
GROUP BY "month"
7+
ORDER BY "month" DESC
8+
LIMIT 12;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
SELECT
2+
DATE_TRUNC('month', "Document"."createdAt") AS "month",
3+
COUNT(DISTINCT "Document"."userId") as "count",
4+
COUNT(DISTINCT CASE WHEN "Document"."status" = 'COMPLETED' THEN "Document"."userId" END) as "signed_count"
5+
FROM "Document"
6+
GROUP BY "month"
7+
ORDER BY "month" DESC
8+
LIMIT 12

0 commit comments

Comments
 (0)