Skip to content

Commit 2489601

Browse files
committed
website API shareId compatibility updates
1 parent fdb9960 commit 2489601

File tree

4 files changed

+148
-12
lines changed

4 files changed

+148
-12
lines changed

src/app/api/websites/[websiteId]/route.ts

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
import { z } from 'zod';
2+
import { ENTITY_TYPE } from '@/lib/constants';
3+
import { uuid } from '@/lib/crypto';
24
import { parseRequest } from '@/lib/request';
3-
import { json, ok, unauthorized } from '@/lib/response';
5+
import { badRequest, json, ok, serverError, unauthorized } from '@/lib/response';
46
import { canDeleteWebsite, canUpdateWebsite, canViewWebsite } from '@/permissions';
5-
import { deleteWebsite, getWebsite, updateWebsite } from '@/queries/prisma';
7+
import {
8+
createShare,
9+
deleteSharesByEntityId,
10+
deleteWebsite,
11+
getShareByEntityId,
12+
getWebsite,
13+
updateWebsite,
14+
} from '@/queries/prisma';
615

716
export async function GET(
817
request: Request,
@@ -32,6 +41,7 @@ export async function POST(
3241
const schema = z.object({
3342
name: z.string().optional(),
3443
domain: z.string().optional(),
44+
shareId: z.string().max(50).nullable().optional(),
3545
});
3646

3747
const { auth, body, error } = await parseRequest(request, schema);
@@ -41,15 +51,41 @@ export async function POST(
4151
}
4252

4353
const { websiteId } = await params;
44-
const { name, domain } = body;
54+
const { name, domain, shareId } = body;
4555

4656
if (!(await canUpdateWebsite(auth, websiteId))) {
4757
return unauthorized();
4858
}
4959

50-
const website = await updateWebsite(websiteId, { name, domain });
51-
52-
return Response.json(website);
60+
try {
61+
const website = await updateWebsite(websiteId, { name, domain });
62+
63+
if (shareId === null) {
64+
await deleteSharesByEntityId(website.id);
65+
}
66+
67+
const share = shareId
68+
? await createShare({
69+
id: uuid(),
70+
entityId: websiteId,
71+
shareType: ENTITY_TYPE.website,
72+
name: website.name,
73+
slug: shareId,
74+
parameters: { overview: true, events: true },
75+
})
76+
: await getShareByEntityId(websiteId);
77+
78+
return json({
79+
...website,
80+
shareId: share?.slug ?? null,
81+
});
82+
} catch (e: any) {
83+
if (e.message.toLowerCase().includes('unique constraint')) {
84+
return badRequest({ message: 'That share ID is already taken.' });
85+
}
86+
87+
return serverError(e);
88+
}
5389
}
5490

5591
export async function DELETE(

src/app/api/websites/route.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { z } from 'zod';
2+
import { ENTITY_TYPE } from '@/lib/constants';
23
import { uuid } from '@/lib/crypto';
34
import { fetchAccount } from '@/lib/load';
45
import { getQueryFilters, parseRequest } from '@/lib/request';
56
import { json, unauthorized } from '@/lib/response';
67
import { pagingParams, searchParams } from '@/lib/schema';
78
import { canCreateTeamWebsite, canCreateWebsite } from '@/permissions';
8-
import { createWebsite, getWebsiteCount } from '@/queries/prisma';
9+
import { createShare, createWebsite, getWebsiteCount } from '@/queries/prisma';
910
import { getAllUserWebsitesIncludingTeamOwner, getUserWebsites } from '@/queries/prisma/website';
1011

1112
const CLOUD_WEBSITE_LIMIT = 3;
@@ -38,6 +39,7 @@ export async function POST(request: Request) {
3839
const schema = z.object({
3940
name: z.string().max(100),
4041
domain: z.string().max(500),
42+
shareId: z.string().max(50).nullable().optional(),
4143
teamId: z.uuid().nullable().optional(),
4244
id: z.uuid().nullable().optional(),
4345
});
@@ -48,7 +50,7 @@ export async function POST(request: Request) {
4850
return error();
4951
}
5052

51-
const { id, name, domain, teamId } = body;
53+
const { id, name, domain, shareId, teamId } = body;
5254

5355
if (process.env.CLOUD_MODE && !teamId) {
5456
const account = await fetchAccount(auth.user.id);
@@ -80,5 +82,19 @@ export async function POST(request: Request) {
8082

8183
const website = await createWebsite(data);
8284

83-
return json(website);
85+
const share = shareId
86+
? await createShare({
87+
id: uuid(),
88+
entityId: website.id,
89+
shareType: ENTITY_TYPE.website,
90+
name: website.name,
91+
slug: shareId,
92+
parameters: { overview: true, events: true },
93+
})
94+
: null;
95+
96+
return json({
97+
...website,
98+
shareId: share?.slug ?? null,
99+
});
84100
}

src/queries/prisma/share.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ export async function getShareByCode(slug: string) {
2222
});
2323
}
2424

25+
export async function getShareByEntityId(entityId: string) {
26+
return prisma.client.share.findFirst({
27+
where: {
28+
entityId,
29+
},
30+
orderBy: {
31+
createdAt: 'desc',
32+
},
33+
});
34+
}
35+
2536
export async function getSharesByEntityId(entityId: string, filters?: QueryFilters) {
2637
const { pagedQuery } = prisma;
2738

@@ -62,3 +73,11 @@ export async function updateShare(
6273
export async function deleteShare(shareId: string) {
6374
return prisma.client.share.delete({ where: { id: shareId } });
6475
}
76+
77+
export async function deleteSharesByEntityId(entityId: string) {
78+
return prisma.client.share.deleteMany({
79+
where: {
80+
entityId,
81+
},
82+
});
83+
}

src/queries/prisma/website.ts

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Prisma } from '@/generated/prisma/client';
1+
import type { Prisma, Website } from '@/generated/prisma/client';
22
import { ROLES } from '@/lib/constants';
33
import prisma from '@/lib/prisma';
44
import redis from '@/lib/redis';
@@ -9,11 +9,13 @@ export async function findWebsite(criteria: Prisma.WebsiteFindUniqueArgs) {
99
}
1010

1111
export async function getWebsite(websiteId: string) {
12-
return findWebsite({
12+
const website = await findWebsite({
1313
where: {
1414
id: websiteId,
1515
},
1616
});
17+
18+
return attachShareIdToWebsite(website);
1719
}
1820

1921
export async function getWebsites(criteria: Prisma.WebsiteFindManyArgs, filters: QueryFilters) {
@@ -31,7 +33,9 @@ export async function getWebsites(criteria: Prisma.WebsiteFindManyArgs, filters:
3133
deletedAt: null,
3234
};
3335

34-
return pagedQuery('website', { ...criteria, where }, filters);
36+
const websites = await pagedQuery('website', { ...criteria, where }, filters);
37+
38+
return attachShareIdToWebsites(websites);
3539
}
3640

3741
export async function getAllUserWebsitesIncludingTeamOwner(userId: string, filters?: QueryFilters) {
@@ -203,6 +207,10 @@ export async function deleteWebsite(websiteId: string) {
203207
where: { websiteId },
204208
});
205209

210+
await tx.share.deleteMany({
211+
where: { entityId: websiteId },
212+
});
213+
206214
const website = cloudMode
207215
? await tx.website.update({
208216
data: {
@@ -236,3 +244,60 @@ export async function getWebsiteCount(userId: string) {
236244
},
237245
});
238246
}
247+
248+
export async function attachShareIdToWebsite(website: Website) {
249+
const share = await prisma.client.share.findFirst({
250+
where: {
251+
entityId: website.id,
252+
},
253+
orderBy: {
254+
createdAt: 'desc',
255+
},
256+
select: {
257+
slug: true,
258+
},
259+
});
260+
261+
return {
262+
...website,
263+
shareId: share?.slug ?? null,
264+
};
265+
}
266+
267+
export async function attachShareIdToWebsites(websites: {
268+
data: any;
269+
count: any;
270+
page: number;
271+
pageSize: number;
272+
orderBy: string;
273+
search: string;
274+
}) {
275+
const websiteIds = websites.data.map(website => website.id);
276+
277+
if (websiteIds.length === 0) {
278+
return {
279+
...websites,
280+
data: websites.data.map(website => ({ ...website, shareId: null })),
281+
};
282+
}
283+
284+
const shares = await prisma.client.share.findMany({
285+
where: {
286+
entityId: { in: websiteIds },
287+
},
288+
distinct: ['entityId'],
289+
orderBy: {
290+
createdAt: 'desc',
291+
},
292+
});
293+
294+
const shareByWebsiteId = new Map(shares.map(share => [share.entityId, share.slug]));
295+
296+
return {
297+
...websites,
298+
data: websites.data.map(website => ({
299+
...website,
300+
shareId: shareByWebsiteId.get(website.id) ?? null,
301+
})),
302+
};
303+
}

0 commit comments

Comments
 (0)