-
-
Notifications
You must be signed in to change notification settings - Fork 93
/
Copy path+server.ts
105 lines (87 loc) · 3.01 KB
/
+server.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { error } from '@sveltejs/kit';
import type { Config } from '@sveltejs/adapter-vercel';
import type { RequestHandler } from './$types';
import { ref, set, update } from 'firebase/database';
import { generateSlug } from 'random-word-slugs';
import { db, loadChatFromDb } from '$misc/firebase';
import type { Chat } from '$misc/shared';
import { respondToClient, throwIfUnset, getErrorMessage } from '$misc/error';
// this tells Vercel to run this function as https://vercel.com/docs/concepts/functions/edge-functions
export const config: Config = {
runtime: 'nodejs18.x'
};
export const GET: RequestHandler = async ({ url }) => {
const slug = url.searchParams.get('slug');
if (!slug) {
throw new Error('missing URL param: slug');
}
const chat = await loadChatFromDb(slug);
if (!chat) {
throw error(404, 'Chat not found');
}
// never send this to the client!
delete chat.updateToken;
return respondToClient(chat);
};
export const POST: RequestHandler = async ({ request }) => {
try {
const requestData = await request.json();
throwIfUnset('request data', requestData);
let slug: string = requestData.slug;
throwIfUnset('slug', slug);
const chat: Chat = requestData.chat;
throwIfUnset('chat', chat);
// The updateToken is like a "password" for later edits
let updateToken: string = chat.updateToken || generateSlug();
const savedDocument = await loadChatFromDb(slug);
// already saved
if (savedDocument) {
// updateToken is wrong or this slug has already been saved ("duplicate ID")
if (savedDocument.updateToken !== updateToken) {
// in this case we just create a new share
slug = generateSlug();
updateToken = generateSlug();
console.log(`Wrong update token for chat ${slug}. Creating new one: ${slug}`);
}
}
const documentToSave = {
...chat,
updateToken
};
// save to firebase
await set(ref(db, `sharedchats/${slug}`), documentToSave);
return respondToClient({ slug, updateToken });
} catch (err) {
throw error(500, getErrorMessage(err));
}
};
export const DELETE: RequestHandler = async ({ request }) => {
try {
// key: slug, value: updateToken
const requestData = (await request.json()) as { [key: string]: string };
throwIfUnset('request data', requestData);
if (!Object.keys(requestData)?.length) throw new Error('No docs to delete provided');
const updates: Record<string, any> = {};
const deleted: string[] = [];
for (const [slug, updateToken] of Object.entries(requestData)) {
const savedDocument = await loadChatFromDb(slug);
// already saved
if (savedDocument) {
// updateToken is wrong
if (savedDocument.updateToken !== updateToken) {
// in this case we just create a new share
throw new Error(`Wrong update token for chat ${slug}. Cannot delete.`);
}
updates[`sharedchats/${slug}`] = null;
deleted.push(slug);
}
}
if (deleted.length) {
// delete in firebase
await update(ref(db), updates);
}
return respondToClient({ deleted });
} catch (err) {
throw error(500, getErrorMessage(err));
}
};