@axium/server 0.3.12 → 0.4.1
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/package.json +3 -2
- package/web/actions.ts +57 -0
- package/web/index.server.ts +2 -4
- package/web/routes/+page.server.ts +3 -8
- package/web/routes/+page.svelte +1 -1
- package/web/routes/email/+page.server.ts +4 -31
- package/web/routes/email/+page.svelte +2 -3
- package/web/routes/name/+page.server.ts +4 -31
- package/web/routes/name/+page.svelte +1 -1
- package/web/routes/signup/+page.server.ts +3 -26
- package/web/routes/signup/+page.svelte +1 -1
- package/web/utils.ts +26 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"kysely": "^0.27.5",
|
|
47
47
|
"logzen": "^0.6.2",
|
|
48
48
|
"pg": "^8.14.1",
|
|
49
|
-
"utilium": "^2.2.3"
|
|
49
|
+
"utilium": "^2.2.3",
|
|
50
|
+
"zod-validation-error": "^3.4.0"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
|
52
53
|
"@auth/sveltekit": "^1.8.0",
|
package/web/actions.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Registration, User } from '@axium/core/schemas';
|
|
2
|
+
import type { RequestEvent } from '@sveltejs/kit';
|
|
3
|
+
import { fail, redirect } from '@sveltejs/kit';
|
|
4
|
+
import { adapter, register } from '../dist/auth.js';
|
|
5
|
+
import { web } from '../dist/config.js';
|
|
6
|
+
import { parseForm } from './utils.js';
|
|
7
|
+
|
|
8
|
+
export async function editEmail(event: RequestEvent) {
|
|
9
|
+
const session = await event.locals.auth();
|
|
10
|
+
|
|
11
|
+
const [{ email }, error] = await parseForm(event, User.pick({ email: true }));
|
|
12
|
+
if (error) return error;
|
|
13
|
+
|
|
14
|
+
const user = await adapter.getUserByEmail(session.user.email);
|
|
15
|
+
if (!user) return fail(401, { email, error: 'You are not signed in' });
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
await adapter.updateUser({ id: user.id, email, image: user.image });
|
|
19
|
+
} catch (error: any) {
|
|
20
|
+
return fail(400, { email, error: typeof error === 'string' ? error : error.message });
|
|
21
|
+
}
|
|
22
|
+
redirect(303, web.prefix);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function editName(event: RequestEvent) {
|
|
26
|
+
const session = await event.locals.auth();
|
|
27
|
+
|
|
28
|
+
const [{ name }, error] = await parseForm(event, User.pick({ name: true }));
|
|
29
|
+
if (error) return error;
|
|
30
|
+
|
|
31
|
+
const user = await adapter.getUserByEmail(session.user.email);
|
|
32
|
+
if (!user) return fail(401, { name, error: 'You are not signed in' });
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await adapter.updateUser({ id: user.id, name, image: user.image });
|
|
36
|
+
} catch (error: any) {
|
|
37
|
+
return fail(400, { name, error: typeof error === 'string' ? error : error.message });
|
|
38
|
+
}
|
|
39
|
+
redirect(303, web.prefix);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function signup(event: RequestEvent) {
|
|
43
|
+
const [data, error] = await parseForm(event, Registration);
|
|
44
|
+
if (error) return error;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const { session } = await register(data);
|
|
48
|
+
event.cookies.set('session', session.sessionToken, {
|
|
49
|
+
path: '/',
|
|
50
|
+
expires: session.expires,
|
|
51
|
+
httpOnly: true,
|
|
52
|
+
});
|
|
53
|
+
return { ...data, success: true, data: session.sessionToken };
|
|
54
|
+
} catch (error: any) {
|
|
55
|
+
return fail(400, { ...data, error: typeof error === 'string' ? error : error.message });
|
|
56
|
+
}
|
|
57
|
+
}
|
package/web/index.server.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export *
|
|
2
|
-
export *
|
|
3
|
-
export * as name from './routes/name/+page.server.js';
|
|
4
|
-
export * as signup from './routes/signup/+page.server.js';
|
|
1
|
+
export * from './actions.js';
|
|
2
|
+
export * from './utils.js';
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import { redirect } from '@sveltejs/kit';
|
|
2
1
|
import { adapter } from '../../dist/auth.js';
|
|
3
|
-
import type { PageServerLoadEvent } from './$types.js';
|
|
4
2
|
import { web } from '../../dist/config.js';
|
|
3
|
+
import { loadSession } from '../utils.js';
|
|
4
|
+
import type { PageServerLoadEvent } from './$types.js';
|
|
5
5
|
|
|
6
6
|
export async function load(event: PageServerLoadEvent) {
|
|
7
|
-
const session = await event
|
|
8
|
-
|
|
9
|
-
if (!session) redirect(307, '/auth/signin');
|
|
10
|
-
if (!session.user.name) redirect(307, web.prefix + '/name');
|
|
11
|
-
|
|
7
|
+
const { session } = await loadSession(event);
|
|
12
8
|
const user = await adapter.getUserByEmail(session.user.email);
|
|
13
|
-
|
|
14
9
|
return { session, user, prefix: web.prefix };
|
|
15
10
|
}
|
package/web/routes/+page.svelte
CHANGED
|
@@ -1,32 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { adapter } from '../../../dist/auth.js';
|
|
4
|
-
import { web } from '../../../dist/config.js';
|
|
5
|
-
import { tryZod } from '../../utils.js';
|
|
6
|
-
import type { PageServerLoadEvent } from './$types.js';
|
|
1
|
+
import type { Actions } from '@sveltejs/kit';
|
|
2
|
+
import { editEmail } from '../../actions.js';
|
|
7
3
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
if (!session) redirect(307, '/auth/signin');
|
|
11
|
-
return { session };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const actions = {
|
|
15
|
-
async default(event) {
|
|
16
|
-
const session = await event.locals.auth();
|
|
17
|
-
|
|
18
|
-
const rawEmail = (await event.request.formData()).get('email');
|
|
19
|
-
const [email, error] = tryZod(z.string().email().safeParse(rawEmail));
|
|
20
|
-
if (error) return error;
|
|
21
|
-
|
|
22
|
-
const user = await adapter.getUserByEmail(session.user.email);
|
|
23
|
-
if (!user) return fail(500, { email, error: 'User does not exist' });
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
await adapter.updateUser({ id: user.id, email, image: user.image });
|
|
27
|
-
} catch (error: any) {
|
|
28
|
-
return fail(400, { email, error: typeof error === 'string' ? error : error.message });
|
|
29
|
-
}
|
|
30
|
-
redirect(303, web.prefix);
|
|
31
|
-
},
|
|
32
|
-
} satisfies Actions;
|
|
4
|
+
export { loadSession as load } from '../../utils.js';
|
|
5
|
+
export const actions = { default: editEmail } satisfies Actions;
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
import { enhance } from '$app/forms';
|
|
3
3
|
import '../../lib/styles.css';
|
|
4
4
|
let { form, data } = $props();
|
|
5
|
-
const { user } = data.session;
|
|
6
5
|
</script>
|
|
7
6
|
|
|
8
7
|
<svelte:head>
|
|
9
8
|
<title>Edit Email</title>
|
|
10
9
|
</svelte:head>
|
|
11
10
|
|
|
12
|
-
<div>
|
|
11
|
+
<div class="EditEmail">
|
|
13
12
|
<form method="POST" class="main" use:enhance>
|
|
14
13
|
{#if form?.error}
|
|
15
14
|
<div class="error">
|
|
@@ -18,7 +17,7 @@
|
|
|
18
17
|
{/if}
|
|
19
18
|
<div>
|
|
20
19
|
<label for="email">Email Address</label>
|
|
21
|
-
<input name="email" type="email" value={form?.email || user.email || ''} required />
|
|
20
|
+
<input name="email" type="email" value={form?.email || data.session.user.email || ''} required />
|
|
22
21
|
</div>
|
|
23
22
|
<button type="submit">Continue</button>
|
|
24
23
|
</form>
|
|
@@ -1,32 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { adapter } from '../../../dist/auth.js';
|
|
4
|
-
import { web } from '../../../dist/config.js';
|
|
5
|
-
import { tryZod } from '../../utils.js';
|
|
6
|
-
import type { PageServerLoadEvent } from './$types.js';
|
|
1
|
+
import type { Actions } from '@sveltejs/kit';
|
|
2
|
+
import { editName } from '../../actions.js';
|
|
7
3
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
if (!session) redirect(307, '/auth/signin');
|
|
11
|
-
return { session };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const actions = {
|
|
15
|
-
async default(event) {
|
|
16
|
-
const session = await event.locals.auth();
|
|
17
|
-
|
|
18
|
-
const rawName = (await event.request.formData()).get('name');
|
|
19
|
-
const [name, error] = tryZod(Name.safeParse(rawName));
|
|
20
|
-
if (error) error;
|
|
21
|
-
|
|
22
|
-
const user = await adapter.getUserByEmail(session.user.email);
|
|
23
|
-
if (!user) return fail(500, { name, error: 'User does not exist' });
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
await adapter.updateUser({ id: user.id, name, image: user.image });
|
|
27
|
-
} catch (error: any) {
|
|
28
|
-
return fail(400, { name, error: typeof error === 'string' ? error : error.message });
|
|
29
|
-
}
|
|
30
|
-
redirect(303, web.prefix);
|
|
31
|
-
},
|
|
32
|
-
} satisfies Actions;
|
|
4
|
+
export { loadSession as load } from '../../utils.js';
|
|
5
|
+
export const actions = { default: editName } satisfies Actions;
|
|
@@ -1,33 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { fail, redirect } from '@sveltejs/kit';
|
|
3
|
-
import * as auth from '../../../dist/auth.js';
|
|
1
|
+
import { redirect } from '@sveltejs/kit';
|
|
4
2
|
import * as config from '../../../dist/config.js';
|
|
3
|
+
import { signup } from '../../actions.js';
|
|
5
4
|
import type { Actions } from './$types.js';
|
|
6
5
|
|
|
7
6
|
export function load() {
|
|
8
7
|
if (!config.auth.credentials) return redirect(307, '/auth/signin');
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
export const actions = {
|
|
12
|
-
async default(event) {
|
|
13
|
-
const { data, success, error } = Registration.safeParse(Object.fromEntries(await event.request.formData()));
|
|
14
|
-
|
|
15
|
-
if (!success)
|
|
16
|
-
return fail(400, {
|
|
17
|
-
...data,
|
|
18
|
-
error: error.flatten().formErrors[0] || Object.values(error.flatten().fieldErrors).flat()[0],
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const { session } = await auth.register(data);
|
|
23
|
-
event.cookies.set('session', session.sessionToken, {
|
|
24
|
-
path: '/',
|
|
25
|
-
expires: session.expires,
|
|
26
|
-
httpOnly: true,
|
|
27
|
-
});
|
|
28
|
-
return { ...data, success: true, data: session.sessionToken };
|
|
29
|
-
} catch (error: any) {
|
|
30
|
-
return fail(400, { ...data, error: typeof error === 'string' ? error : error.message });
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
} satisfies Actions;
|
|
10
|
+
export const actions = { default: signup } satisfies Actions;
|
package/web/utils.ts
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Session } from '@auth/sveltekit';
|
|
2
|
+
import type { ActionFailure, RequestEvent } from '@sveltejs/kit';
|
|
3
|
+
import { fail, redirect } from '@sveltejs/kit';
|
|
2
4
|
import type * as z from 'zod';
|
|
5
|
+
import { fromError } from 'zod-validation-error';
|
|
6
|
+
import { web } from '../dist/config.js';
|
|
3
7
|
|
|
4
|
-
export function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
8
|
+
export async function loadSession(event: RequestEvent): Promise<{ session: Session }> {
|
|
9
|
+
const session = await event.locals.auth();
|
|
10
|
+
if (!session) redirect(307, '/auth/signin');
|
|
11
|
+
if (!session.user.name && event.url.pathname != web.prefix + '/name') redirect(307, web.prefix + '/name');
|
|
12
|
+
return { session };
|
|
9
13
|
}
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
16
|
+
export interface FormFail<S extends z.AnyZodObject> extends ActionFailure<z.infer<S> & { error: string }> {}
|
|
17
|
+
|
|
18
|
+
export async function parseForm<S extends z.AnyZodObject>(event: RequestEvent, schema: S): Promise<[z.infer<S>, FormFail<S> | null]> {
|
|
19
|
+
const formData = Object.fromEntries(await event.request.formData());
|
|
20
|
+
const { data, error, success } = schema.safeParse(formData);
|
|
21
|
+
|
|
22
|
+
if (success) return [data, null];
|
|
23
|
+
|
|
24
|
+
return [
|
|
25
|
+
data,
|
|
26
|
+
fail(400, {
|
|
27
|
+
...data,
|
|
28
|
+
error: fromError(error, { prefix: null }).toString(),
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
14
31
|
}
|