@axium/server 0.8.0 → 0.9.0
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/dist/auth.d.ts +0 -10
- package/dist/auth.js +8 -16
- package/dist/cli.js +145 -38
- package/dist/config.d.ts +39 -474
- package/dist/config.js +53 -43
- package/dist/database.d.ts +3 -3
- package/dist/database.js +53 -24
- package/dist/plugins.d.ts +1 -0
- package/dist/plugins.js +1 -0
- package/package.json +10 -7
- package/web/api/metadata.ts +3 -3
- package/web/api/passkeys.ts +3 -3
- package/web/api/register.ts +4 -4
- package/web/api/session.ts +2 -2
- package/web/api/users.ts +29 -18
- package/web/api/utils.ts +2 -2
- package/web/hooks.server.ts +8 -2
- package/web/lib/ClipboardCopy.svelte +42 -0
- package/web/lib/FormDialog.svelte +9 -1
- package/web/lib/auth.ts +2 -2
- package/web/lib/icons/Icon.svelte +2 -6
- package/web/lib/styles.css +7 -1
- package/web/routes/[...path]/+page.server.ts +1 -1
- package/web/routes/[appId]/[...page]/+page.server.ts +1 -1
- package/web/routes/account/+page.svelte +115 -48
- package/web/routes/api/[...path]/+server.ts +2 -2
package/dist/database.d.ts
CHANGED
|
@@ -38,8 +38,7 @@ export interface Schema {
|
|
|
38
38
|
transports: AuthenticatorTransportFuture[];
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
export
|
|
42
|
-
}
|
|
41
|
+
export type Database = Kysely<Schema> & AsyncDisposable;
|
|
43
42
|
export declare let database: Database;
|
|
44
43
|
export declare function connect(): Database;
|
|
45
44
|
export interface Stats {
|
|
@@ -47,7 +46,7 @@ export interface Stats {
|
|
|
47
46
|
passkeys: number;
|
|
48
47
|
sessions: number;
|
|
49
48
|
}
|
|
50
|
-
export declare function count(table:
|
|
49
|
+
export declare function count<const T extends keyof Schema>(table: T): Promise<number>;
|
|
51
50
|
export declare function status(): Promise<Stats>;
|
|
52
51
|
export declare function statusText(): Promise<string>;
|
|
53
52
|
export interface OpOptions extends MaybeOutput {
|
|
@@ -65,6 +64,7 @@ export interface PluginShortcuts {
|
|
|
65
64
|
}
|
|
66
65
|
export declare function init(opt: InitOptions): Promise<void>;
|
|
67
66
|
export declare function check(opt: OpOptions): Promise<void>;
|
|
67
|
+
export declare function clean(opt: Partial<OpOptions>): Promise<void>;
|
|
68
68
|
/**
|
|
69
69
|
* Completely remove Axium from the database.
|
|
70
70
|
*/
|
package/dist/database.js
CHANGED
|
@@ -73,7 +73,9 @@ export function connect() {
|
|
|
73
73
|
}
|
|
74
74
|
export async function count(table) {
|
|
75
75
|
const db = connect();
|
|
76
|
-
return (await db.selectFrom(table)
|
|
76
|
+
return (await db.selectFrom(table)
|
|
77
|
+
.select(db.fn.countAll().as('count'))
|
|
78
|
+
.executeTakeFirstOrThrow()).count;
|
|
77
79
|
}
|
|
78
80
|
export async function status() {
|
|
79
81
|
return {
|
|
@@ -286,35 +288,62 @@ export async function check(opt) {
|
|
|
286
288
|
await result_2;
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
|
-
|
|
290
|
-
* Completely remove Axium from the database.
|
|
291
|
-
*/
|
|
292
|
-
export async function uninstall(opt) {
|
|
291
|
+
export async function clean(opt) {
|
|
293
292
|
_fixOutput(opt);
|
|
293
|
+
const done = () => opt.output('done');
|
|
294
|
+
const now = new Date();
|
|
294
295
|
const db = connect();
|
|
296
|
+
opt.output('start', 'Removing expired sessions');
|
|
297
|
+
await db.deleteFrom('sessions').where('sessions.expires', '<', now).execute().then(done);
|
|
298
|
+
opt.output('start', 'Removing expired verifications');
|
|
299
|
+
await db.deleteFrom('verifications').where('verifications.expires', '<', now).execute().then(done);
|
|
295
300
|
for (const plugin of plugins) {
|
|
296
|
-
if (!plugin.
|
|
301
|
+
if (!plugin.db_clean)
|
|
297
302
|
continue;
|
|
298
303
|
opt.output('plugin', plugin.name);
|
|
299
|
-
await plugin.
|
|
304
|
+
await plugin.db_clean(opt, db);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Completely remove Axium from the database.
|
|
309
|
+
*/
|
|
310
|
+
export async function uninstall(opt) {
|
|
311
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
312
|
+
try {
|
|
313
|
+
_fixOutput(opt);
|
|
314
|
+
const db = __addDisposableResource(env_3, connect(), true);
|
|
315
|
+
for (const plugin of plugins) {
|
|
316
|
+
if (!plugin.db_remove)
|
|
317
|
+
continue;
|
|
318
|
+
opt.output('plugin', plugin.name);
|
|
319
|
+
await plugin.db_remove(opt, db);
|
|
320
|
+
}
|
|
321
|
+
const _sql = (command, message) => run(opt, message, `sudo -u postgres psql -c "${command}"`);
|
|
322
|
+
await _sql('DROP DATABASE axium', 'Dropping database');
|
|
323
|
+
await _sql('REVOKE ALL PRIVILEGES ON SCHEMA public FROM axium', 'Revoking schema privileges');
|
|
324
|
+
await _sql('DROP USER axium', 'Dropping user');
|
|
325
|
+
await getHBA(opt)
|
|
326
|
+
.then(([content, writeBack]) => {
|
|
327
|
+
opt.output('start', 'Checking for Axium HBA configuration');
|
|
328
|
+
if (!content.includes(pgHba))
|
|
329
|
+
throw 'missing.';
|
|
330
|
+
opt.output('done');
|
|
331
|
+
opt.output('start', 'Removing Axium HBA configuration');
|
|
332
|
+
const newContent = content.replace(pgHba, '');
|
|
333
|
+
opt.output('done');
|
|
334
|
+
writeBack(newContent);
|
|
335
|
+
})
|
|
336
|
+
.catch(e => opt.output('warn', e));
|
|
337
|
+
}
|
|
338
|
+
catch (e_3) {
|
|
339
|
+
env_3.error = e_3;
|
|
340
|
+
env_3.hasError = true;
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
const result_3 = __disposeResources(env_3);
|
|
344
|
+
if (result_3)
|
|
345
|
+
await result_3;
|
|
300
346
|
}
|
|
301
|
-
await db.destroy();
|
|
302
|
-
const _sql = (command, message) => run(opt, message, `sudo -u postgres psql -c "${command}"`);
|
|
303
|
-
await _sql('DROP DATABASE axium', 'Dropping database');
|
|
304
|
-
await _sql('REVOKE ALL PRIVILEGES ON SCHEMA public FROM axium', 'Revoking schema privileges');
|
|
305
|
-
await _sql('DROP USER axium', 'Dropping user');
|
|
306
|
-
await getHBA(opt)
|
|
307
|
-
.then(([content, writeBack]) => {
|
|
308
|
-
opt.output('start', 'Checking for Axium HBA configuration');
|
|
309
|
-
if (!content.includes(pgHba))
|
|
310
|
-
throw 'missing.';
|
|
311
|
-
opt.output('done');
|
|
312
|
-
opt.output('start', 'Removing Axium HBA configuration');
|
|
313
|
-
const newContent = content.replace(pgHba, '');
|
|
314
|
-
opt.output('done');
|
|
315
|
-
writeBack(newContent);
|
|
316
|
-
})
|
|
317
|
-
.catch(e => opt.output('warn', e));
|
|
318
347
|
}
|
|
319
348
|
/**
|
|
320
349
|
* Removes all data from tables.
|
package/dist/plugins.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare const Plugin: z.ZodObject<{
|
|
|
9
9
|
db_init: z.ZodOptional<z.ZodCustom<(...args: unknown[]) => any, (...args: unknown[]) => any>>;
|
|
10
10
|
db_remove: z.ZodOptional<z.ZodCustom<(...args: unknown[]) => any, (...args: unknown[]) => any>>;
|
|
11
11
|
db_wipe: z.ZodOptional<z.ZodCustom<(...args: unknown[]) => any, (...args: unknown[]) => any>>;
|
|
12
|
+
db_clean: z.ZodOptional<z.ZodCustom<(...args: unknown[]) => any, (...args: unknown[]) => any>>;
|
|
12
13
|
}, z.core.$strip>;
|
|
13
14
|
export interface Plugin extends z.infer<typeof Plugin> {
|
|
14
15
|
}
|
package/dist/plugins.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axium/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"author": "James Prevett <axium@jamespre.dev> (https://jamespre.dev)",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"types": "dist/index.d.ts",
|
|
20
20
|
"exports": {
|
|
21
21
|
".": "./dist/index.js",
|
|
22
|
-
"./*": "./dist
|
|
22
|
+
"./*": "./dist/*.js",
|
|
23
23
|
"./web": "./web/index.js",
|
|
24
24
|
"./web/*": "./web/*"
|
|
25
25
|
},
|
|
@@ -33,18 +33,21 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsc"
|
|
35
35
|
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"@axium/core": ">=0.3.0",
|
|
38
|
+
"@axium/client": ">=0.0.2",
|
|
39
|
+
"utilium": "^2.3.8",
|
|
40
|
+
"zod": "^3.25.61"
|
|
41
|
+
},
|
|
36
42
|
"dependencies": {
|
|
37
43
|
"@simplewebauthn/server": "^13.1.1",
|
|
38
44
|
"@sveltejs/kit": "^2.20.2",
|
|
39
45
|
"@types/pg": "^8.11.11",
|
|
40
46
|
"commander": "^13.1.0",
|
|
41
|
-
"kysely": "^0.
|
|
47
|
+
"kysely": "^0.28.0",
|
|
42
48
|
"logzen": "^0.7.0",
|
|
43
49
|
"mime": "^4.0.7",
|
|
44
|
-
"pg": "^8.14.1"
|
|
45
|
-
"utilium": "^2.3.8",
|
|
46
|
-
"zod": "^3.25.61",
|
|
47
|
-
"@axium/core": ">=0.2.0"
|
|
50
|
+
"pg": "^8.14.1"
|
|
48
51
|
},
|
|
49
52
|
"devDependencies": {
|
|
50
53
|
"@sveltejs/adapter-node": "^5.2.12",
|
package/web/api/metadata.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Result } from '@axium/core/api';
|
|
2
2
|
import { requestMethods } from '@axium/core/requests';
|
|
3
|
-
import { config } from '@axium/server/config
|
|
4
|
-
import { plugins } from '@axium/server/plugins
|
|
5
|
-
import { addRoute, routes } from '@axium/server/routes
|
|
3
|
+
import { config } from '@axium/server/config';
|
|
4
|
+
import { plugins } from '@axium/server/plugins';
|
|
5
|
+
import { addRoute, routes } from '@axium/server/routes';
|
|
6
6
|
import { error } from '@sveltejs/kit';
|
|
7
7
|
import pkg from '../../package.json' with { type: 'json' };
|
|
8
8
|
|
package/web/api/passkeys.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Result } from '@axium/core/api';
|
|
2
2
|
import { PasskeyChangeable } from '@axium/core/schemas';
|
|
3
|
-
import { getPasskey } from '@axium/server/auth
|
|
4
|
-
import { database as db } from '@axium/server/database
|
|
5
|
-
import { addRoute } from '@axium/server/routes
|
|
3
|
+
import { getPasskey } from '@axium/server/auth';
|
|
4
|
+
import { database as db } from '@axium/server/database';
|
|
5
|
+
import { addRoute } from '@axium/server/routes';
|
|
6
6
|
import { error } from '@sveltejs/kit';
|
|
7
7
|
import { omit } from 'utilium';
|
|
8
8
|
import z from 'zod/v4';
|
package/web/api/register.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Register a new user. */
|
|
2
2
|
import type { Result } from '@axium/core/api';
|
|
3
3
|
import { APIUserRegistration } from '@axium/core/schemas';
|
|
4
|
-
import { createPasskey, getUser, getUserByEmail } from '@axium/server/auth
|
|
5
|
-
import config from '@axium/server/config
|
|
6
|
-
import { database as db, type Schema } from '@axium/server/database
|
|
7
|
-
import { addRoute } from '@axium/server/routes
|
|
4
|
+
import { createPasskey, getUser, getUserByEmail } from '@axium/server/auth';
|
|
5
|
+
import config from '@axium/server/config';
|
|
6
|
+
import { database as db, type Schema } from '@axium/server/database';
|
|
7
|
+
import { addRoute } from '@axium/server/routes';
|
|
8
8
|
import { generateRegistrationOptions, verifyRegistrationResponse } from '@simplewebauthn/server';
|
|
9
9
|
import { error, type RequestEvent } from '@sveltejs/kit';
|
|
10
10
|
import { randomUUID } from 'node:crypto';
|
package/web/api/session.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { authenticate } from '$lib/auth';
|
|
2
2
|
import type { Result } from '@axium/core/api';
|
|
3
|
-
import { connect, database as db } from '@axium/server/database
|
|
4
|
-
import { addRoute } from '@axium/server/routes
|
|
3
|
+
import { connect, database as db } from '@axium/server/database';
|
|
4
|
+
import { addRoute } from '@axium/server/routes';
|
|
5
5
|
import { error } from '@sveltejs/kit';
|
|
6
6
|
import { omit } from 'utilium';
|
|
7
7
|
import { getToken, stripUser } from './utils';
|
package/web/api/users.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/** Register a new passkey for a new or existing user. */
|
|
2
2
|
import type { Result } from '@axium/core/api';
|
|
3
|
-
import { PasskeyAuthenticationResponse, UserAuthOptions } from '@axium/core/schemas';
|
|
3
|
+
import { LogoutSessions, PasskeyAuthenticationResponse, UserAuthOptions } from '@axium/core/schemas';
|
|
4
4
|
import { UserChangeable, type User } from '@axium/core/user';
|
|
5
5
|
import {
|
|
6
6
|
createPasskey,
|
|
7
7
|
createVerification,
|
|
8
8
|
getPasskey,
|
|
9
9
|
getPasskeysByUserId,
|
|
10
|
-
getSession,
|
|
11
10
|
getSessions,
|
|
12
11
|
getUser,
|
|
13
12
|
useVerification,
|
|
14
|
-
} from '@axium/server/auth
|
|
15
|
-
import { config } from '@axium/server/config
|
|
16
|
-
import { connect, database as db } from '@axium/server/database
|
|
17
|
-
import { addRoute } from '@axium/server/routes
|
|
13
|
+
} from '@axium/server/auth';
|
|
14
|
+
import { config } from '@axium/server/config';
|
|
15
|
+
import { connect, database as db } from '@axium/server/database';
|
|
16
|
+
import { addRoute } from '@axium/server/routes';
|
|
18
17
|
import {
|
|
19
18
|
generateAuthenticationOptions,
|
|
20
19
|
generateRegistrationOptions,
|
|
@@ -282,32 +281,44 @@ addRoute({
|
|
|
282
281
|
await checkAuth(event, userId);
|
|
283
282
|
|
|
284
283
|
return (await getSessions(userId).catch(e => error(503, 'Failed to get sessions' + (config.debug ? ': ' + e : '')))).map(s =>
|
|
285
|
-
|
|
284
|
+
omit(s, 'token')
|
|
286
285
|
);
|
|
287
286
|
},
|
|
288
287
|
async DELETE(event: RequestEvent): Result<'DELETE', 'users/:id/sessions'> {
|
|
289
288
|
const { id: userId } = event.params;
|
|
290
|
-
const
|
|
289
|
+
const body = await parseBody(event, LogoutSessions);
|
|
291
290
|
|
|
292
|
-
await checkAuth(event, userId);
|
|
293
|
-
|
|
294
|
-
const session = await getSession(sessionId).catch(withError('Session does not exist', 404));
|
|
291
|
+
await checkAuth(event, userId, body.confirm_all);
|
|
295
292
|
|
|
296
|
-
|
|
293
|
+
const query = body.confirm_all ? db.deleteFrom('sessions') : db.deleteFrom('sessions').where('sessions.id', 'in', body.id);
|
|
297
294
|
|
|
298
|
-
await
|
|
299
|
-
.
|
|
300
|
-
.
|
|
301
|
-
.
|
|
302
|
-
.catch(withError('Failed to delete
|
|
295
|
+
const result = await query
|
|
296
|
+
.where('sessions.userId', '=', userId)
|
|
297
|
+
.returningAll()
|
|
298
|
+
.execute()
|
|
299
|
+
.catch(withError('Failed to delete one or more sessions'));
|
|
303
300
|
|
|
304
|
-
return;
|
|
301
|
+
return result.map(s => omit(s, 'token'));
|
|
305
302
|
},
|
|
306
303
|
});
|
|
307
304
|
|
|
308
305
|
addRoute({
|
|
309
306
|
path: '/api/users/:id/verify_email',
|
|
310
307
|
params,
|
|
308
|
+
async OPTIONS(event): Result<'OPTIONS', 'users/:id/verify_email'> {
|
|
309
|
+
const { id: userId } = event.params;
|
|
310
|
+
|
|
311
|
+
if (!config.auth.email_verification) return { enabled: false };
|
|
312
|
+
|
|
313
|
+
await checkAuth(event, userId);
|
|
314
|
+
|
|
315
|
+
const user = await getUser(userId);
|
|
316
|
+
if (!user) error(404, { message: 'User does not exist' });
|
|
317
|
+
|
|
318
|
+
if (!config.auth.email_verification) return { enabled: false };
|
|
319
|
+
|
|
320
|
+
return { enabled: true };
|
|
321
|
+
},
|
|
311
322
|
async GET(event): Result<'GET', 'users/:id/verify_email'> {
|
|
312
323
|
const { id: userId } = event.params;
|
|
313
324
|
|
package/web/api/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { userProtectedFields, userPublicFields, type User } from '@axium/core/user';
|
|
2
2
|
import type { NewSessionResponse } from '@axium/core/api';
|
|
3
|
-
import { createSession, getSessionAndUser, type UserInternal } from '@axium/server/auth
|
|
4
|
-
import { config } from '@axium/server/config
|
|
3
|
+
import { createSession, getSessionAndUser, type UserInternal } from '@axium/server/auth';
|
|
4
|
+
import { config } from '@axium/server/config';
|
|
5
5
|
import { error, type RequestEvent } from '@sveltejs/kit';
|
|
6
6
|
import { pick } from 'utilium';
|
|
7
7
|
import z from 'zod/v4';
|
package/web/hooks.server.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { loadDefaultConfigs } from '@axium/server/config
|
|
2
|
-
import {
|
|
1
|
+
import { loadDefaultConfigs } from '@axium/server/config';
|
|
2
|
+
import { clean, database } from '@axium/server/database';
|
|
3
|
+
import { _markDefaults } from '@axium/server/routes';
|
|
3
4
|
import './api/index.js';
|
|
4
5
|
|
|
5
6
|
_markDefaults();
|
|
6
7
|
await loadDefaultConfigs();
|
|
8
|
+
await clean({});
|
|
9
|
+
|
|
10
|
+
process.on('beforeExit', async () => {
|
|
11
|
+
await database.destroy();
|
|
12
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { fade } from 'svelte/transition';
|
|
3
|
+
import { wait } from 'utilium';
|
|
4
|
+
import Icon from './icons/Icon.svelte';
|
|
5
|
+
|
|
6
|
+
const { value, type = 'text/plain' }: { value: BlobPart; type?: string } = $props();
|
|
7
|
+
|
|
8
|
+
let success = $state(false);
|
|
9
|
+
|
|
10
|
+
async function onclick() {
|
|
11
|
+
const blob = new Blob([value], { type });
|
|
12
|
+
const item = new ClipboardItem({ [type]: blob });
|
|
13
|
+
await navigator.clipboard.write([item]);
|
|
14
|
+
success = true;
|
|
15
|
+
await wait(3000);
|
|
16
|
+
success = false;
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<button {onclick}>
|
|
21
|
+
{#if success}
|
|
22
|
+
<span transition:fade><Icon i="check" /></span>
|
|
23
|
+
{:else}
|
|
24
|
+
<span transition:fade><Icon i="copy" /></span>
|
|
25
|
+
{/if}
|
|
26
|
+
</button>
|
|
27
|
+
|
|
28
|
+
<style>
|
|
29
|
+
button {
|
|
30
|
+
position: relative;
|
|
31
|
+
display: inline-block;
|
|
32
|
+
width: 1em;
|
|
33
|
+
height: 1em;
|
|
34
|
+
border: none;
|
|
35
|
+
background: transparent;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
span {
|
|
39
|
+
position: absolute;
|
|
40
|
+
inset: 0;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { goto } from '$app/navigation';
|
|
3
|
+
import { page } from '$app/state';
|
|
3
4
|
import Dialog from './Dialog.svelte';
|
|
4
5
|
import './styles.css';
|
|
5
6
|
|
|
7
|
+
function resolveRedirectAfter() {
|
|
8
|
+
const maybe = page.url.searchParams.get('after');
|
|
9
|
+
if (!maybe || maybe == page.url.pathname) return '/';
|
|
10
|
+
for (const prefix of ['/api/']) if (maybe.startsWith(prefix)) return '/';
|
|
11
|
+
return maybe || '/';
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
let {
|
|
7
15
|
children,
|
|
8
16
|
dialog = $bindable(),
|
|
@@ -42,7 +50,7 @@
|
|
|
42
50
|
const data = Object.fromEntries(new FormData(e.currentTarget));
|
|
43
51
|
submit(data)
|
|
44
52
|
.then(result => {
|
|
45
|
-
if (pageMode) goto(
|
|
53
|
+
if (pageMode) goto(resolveRedirectAfter());
|
|
46
54
|
else dialog.close();
|
|
47
55
|
})
|
|
48
56
|
.catch((e: unknown) => {
|
package/web/lib/auth.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SessionInternal, UserInternal } from '@axium/server/auth
|
|
2
|
-
import { getSessionAndUser } from '@axium/server/auth
|
|
1
|
+
import type { SessionInternal, UserInternal } from '@axium/server/auth';
|
|
2
|
+
import { getSessionAndUser } from '@axium/server/auth';
|
|
3
3
|
import type { RequestEvent } from '@sveltejs/kit';
|
|
4
4
|
|
|
5
5
|
export async function authenticate(event: RequestEvent): Promise<(SessionInternal & { user: UserInternal | null }) | null> {
|
|
@@ -5,14 +5,10 @@
|
|
|
5
5
|
const urls = { light, solid, regular };
|
|
6
6
|
const { i } = $props();
|
|
7
7
|
|
|
8
|
-
const [style, id] = i.includes('/') ? i.split('/') : ['solid', i];
|
|
9
|
-
const url = urls[style];
|
|
8
|
+
const [style, id] = $derived(i.includes('/') ? i.split('/') : ['solid', i]);
|
|
9
|
+
const url = $derived(urls[style]);
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
|
-
<svelte:head>
|
|
13
|
-
<link rel="preload" href={url} />
|
|
14
|
-
</svelte:head>
|
|
15
|
-
|
|
16
12
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="1em" height="1em">
|
|
17
13
|
<use href="{url}#{id}" />
|
|
18
14
|
</svg>
|
package/web/lib/styles.css
CHANGED
|
@@ -4,6 +4,7 @@ body {
|
|
|
4
4
|
background-color: #222;
|
|
5
5
|
color: #bbb;
|
|
6
6
|
accent-color: #bbb;
|
|
7
|
+
overflow-y: scroll;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
.main {
|
|
@@ -15,7 +16,7 @@ body {
|
|
|
15
16
|
gap: 1em;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
.main-container:has(form.main) {
|
|
19
20
|
position: absolute;
|
|
20
21
|
inset: 0;
|
|
21
22
|
display: flex;
|
|
@@ -94,3 +95,8 @@ button:hover {
|
|
|
94
95
|
.danger:hover {
|
|
95
96
|
background-color: #633;
|
|
96
97
|
}
|
|
98
|
+
|
|
99
|
+
:disabled,
|
|
100
|
+
.disabled {
|
|
101
|
+
cursor: not-allowed;
|
|
102
|
+
}
|