Skip to content

Commit a153d7f

Browse files
committed
chore: refactor platform and use path aliases
1 parent 4059519 commit a153d7f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+432
-642
lines changed

apps/platform/app.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Ctx } from './ctx';
1+
import type { Ctx, TrpcContext } from './ctx';
22
import { env } from './env';
33
import { Hono } from 'hono';
44
import { serve } from '@hono/node-server';
@@ -42,12 +42,13 @@ app.use(
4242
'/trpc/*',
4343
trpcServer({
4444
router: trpcPlatformRouter,
45-
createContext: (_, c) => ({
46-
db,
47-
account: c.get('account'),
48-
org: null,
49-
event: c
50-
})
45+
createContext: (_, c) =>
46+
({
47+
db,
48+
account: c.get('account'),
49+
org: null,
50+
event: c
51+
}) satisfies TrpcContext
5152
})
5253
);
5354

apps/platform/ctx.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import type { HttpBindings } from '@hono/node-server';
2+
import type { DBType } from '@u22n/database';
3+
import type { Context } from 'hono';
24
import type { DatabaseSession } from 'lucia';
35

46
export type Ctx = {
57
Bindings: HttpBindings;
68
Variables: {
7-
account: {
8-
id: number;
9-
session: any;
10-
} | null;
9+
account: AccountContext;
1110
};
1211
};
1312

@@ -29,3 +28,10 @@ export type AccountContext = {
2928
id: number;
3029
session: DatabaseSession;
3130
} | null;
31+
32+
export type TrpcContext = {
33+
db: DBType;
34+
account: AccountContext;
35+
org: OrgContext;
36+
event: Context<Ctx>;
37+
};

apps/platform/middlewares.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ export const authMiddleware = createMiddleware<Ctx>(async (c, next) => {
1515
await next();
1616
} else {
1717
c.set('account', {
18-
// @ts-expect-error, not typed properly yet
19-
id: Number(sessionObject.attributes.account.id),
18+
id: sessionObject.attributes.account.id,
2019
session: sessionObject
2120
});
2221
await next();

apps/platform/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
"scripts": {
66
"dev": "tsx watch --clear-screen=false app.ts",
77
"start": "node --import=tsx app.ts",
8+
"build": "echo 'No build step configured'",
89
"check": "tsc --noEmit"
910
},
11+
"exports": {
12+
"./trpc": {
13+
"types": "./trpc/index.ts"
14+
}
15+
},
1016
"dependencies": {
1117
"@hono/node-server": "^1.11.1",
1218
"@hono/trpc-server": "^0.3.1",

apps/platform/routes/auth.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { Hono } from 'hono';
2-
import type { Ctx } from '../ctx';
3-
import { lucia } from '../utils/auth';
2+
import type { Ctx } from '~platform/ctx';
3+
import { lucia } from '~platform/utils/auth';
44
import { setCookie } from 'hono/cookie';
55

66
export const authApi = new Hono<Ctx>();
77

88
authApi.get('/status', async (c) => {
99
const account = c.get('account');
10-
if (!account || !account.id) {
10+
if (!account) {
1111
return c.json({ authStatus: 'unauthenticated' });
1212
}
1313
return c.json({ authStatus: 'authenticated' });
1414
});
1515

1616
authApi.post('/logout', async (c) => {
1717
const account = c.get('account');
18-
if (!account || !account.id || !account.session || !account.session.id) {
18+
if (!account) {
1919
return c.json({ ok: true });
2020
}
2121
const sessionId = account.session.id;

apps/platform/routes/realtime.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Hono } from 'hono';
2-
import type { Ctx } from '../ctx';
2+
import type { Ctx } from '~platform/ctx';
33
import { zValidator } from '@hono/zod-validator';
44
import { z } from 'zod';
5-
import { validateOrgShortCode } from '../utils/orgShortCode';
5+
import { validateOrgShortCode } from '~platform/utils/orgShortCode';
66
import { db } from '@u22n/database';
77
import { and, eq } from '@u22n/database/orm';
88
import { orgMembers } from '@u22n/database/schema';
9-
import { realtime } from '../utils/realtime';
9+
import { realtime } from '~platform/utils/realtime';
1010

1111
export const realtimeApi = new Hono<Ctx>();
1212

apps/platform/storage.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import { env } from './env';
22
import { ms } from 'itty-time';
33
import redisDriver from 'unstorage/drivers/redis';
4-
import { createStorage } from 'unstorage';
4+
import { createStorage, type StorageValue } from 'unstorage';
5+
import type { DatabaseSession } from 'lucia';
6+
import type { OrgContext } from './ctx';
57

6-
const createCachedStorage = (base: string, ttl: number) =>
7-
createStorage({
8+
const createCachedStorage = <T extends StorageValue = StorageValue>(
9+
base: string,
10+
ttl: number
11+
) =>
12+
createStorage<T>({
813
driver: redisDriver({
914
url: env.DB_REDIS_CONNECTION_STRING,
1015
ttl,
@@ -14,8 +19,8 @@ const createCachedStorage = (base: string, ttl: number) =>
1419

1520
export const storage = {
1621
auth: createCachedStorage('auth', ms('5 minutes')),
17-
orgContext: createCachedStorage('org-context', ms('12 hours')),
18-
session: createCachedStorage(
22+
orgContext: createCachedStorage<OrgContext>('org-context', ms('12 hours')),
23+
session: createCachedStorage<DatabaseSession>(
1924
'sessions',
2025
env.NODE_ENV === 'development' ? ms('12 hours') : ms('30 days')
2126
)

apps/platform/trpc/routers/authRouter/passkeyRouter.ts

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { z } from 'zod';
2-
import { router, publicRateLimitedProcedure } from '../../trpc';
2+
import { router, publicRateLimitedProcedure } from '~platform/trpc/trpc';
33
import { eq } from '@u22n/database/orm';
44
import { accounts } from '@u22n/database/schema';
55
import { TRPCError } from '@trpc/server';
@@ -13,13 +13,16 @@ import {
1313
typeIdValidator,
1414
zodSchemas
1515
} from '@u22n/utils';
16-
import { UAParser } from 'ua-parser-js';
17-
import { usePasskeys } from '../../../utils/auth/passkeys';
18-
import { usePasskeysDb } from '../../../utils/auth/passkeyDbAdaptor';
19-
import { lucia } from '../../../utils/auth';
16+
import {
17+
verifyRegistrationResponse,
18+
generateRegistrationOptions,
19+
generateAuthenticationOptions,
20+
verifyAuthenticationResponse
21+
} from '~platform/utils/auth/passkeys';
22+
import { createAuthenticator } from '~platform/utils/auth/passkeyUtils';
2023
import { validateUsername } from './signupRouter';
21-
import { createLuciaSessionCookie } from '../../../utils/session';
22-
import { env } from '../../../env';
24+
import { createLuciaSessionCookie } from '~platform/utils/session';
25+
import { env } from '~platform/env';
2326
import { ms } from 'itty-time';
2427
import { getCookie, setCookie } from 'hono/cookie';
2528

@@ -42,7 +45,7 @@ export const passkeyRouter = router({
4245
}
4346

4447
const publicId = typeIdGenerator('account');
45-
const passkeyOptions = await usePasskeys.generateRegistrationOptions({
48+
const passkeyOptions = await generateRegistrationOptions({
4649
userDisplayName: username,
4750
username: username,
4851
accountPublicId: publicId
@@ -63,7 +66,7 @@ export const passkeyRouter = router({
6366
const registrationResponse =
6467
input.registrationResponseRaw as RegistrationResponseJSON;
6568

66-
const passkeyVerification = await usePasskeys.verifyRegistrationResponse({
69+
const passkeyVerification = await verifyRegistrationResponse({
6770
registrationResponse: registrationResponse,
6871
publicId: input.publicId
6972
});
@@ -104,7 +107,7 @@ export const passkeyRouter = router({
104107
});
105108
}
106109

107-
const insertPasskey = await usePasskeysDb.createAuthenticator(
110+
const insertPasskey = await createAuthenticator(
108111
{
109112
accountId: Number(newAccount.insertId),
110113
credentialID: passkeyVerification.registrationInfo.credentialID,
@@ -137,12 +140,12 @@ export const passkeyRouter = router({
137140
}
138141
});
139142

140-
const cookie = await createLuciaSessionCookie(ctx.event, {
143+
await createLuciaSessionCookie(ctx.event, {
141144
accountId,
142145
username: input.username,
143146
publicId: input.publicId
144147
});
145-
setCookie(ctx.event, cookie.name, cookie.value, cookie.attributes);
148+
146149
return { success: true };
147150
}),
148151

@@ -160,7 +163,7 @@ export const passkeyRouter = router({
160163
maxAge: ms('5 minutes'),
161164
domain: env.PRIMARY_DOMAIN
162165
});
163-
const passkeyOptions = await usePasskeys.generateAuthenticationOptions({
166+
const passkeyOptions = await generateAuthenticationOptions({
164167
authChallengeId: authChallengeId
165168
});
166169

@@ -187,11 +190,10 @@ export const passkeyRouter = router({
187190
});
188191
}
189192

190-
const passkeyVerification =
191-
await usePasskeys.verifyAuthenticationResponse({
192-
authenticationResponse: verificationResponse,
193-
authChallengeId: challengeCookie
194-
});
193+
const passkeyVerification = await verifyAuthenticationResponse({
194+
authenticationResponse: verificationResponse,
195+
authChallengeId: challengeCookie
196+
});
195197

196198
if (
197199
!passkeyVerification.result.verified ||
@@ -231,26 +233,11 @@ export const passkeyRouter = router({
231233
});
232234
}
233235

234-
const { device, os } = UAParser(event.req.header('User-Agent'));
235-
const userDevice =
236-
device.type === 'mobile' ? device.toString() : device.vendor;
237-
238-
const accountSession = await lucia.createSession(account.id, {
239-
account: {
240-
id: account.id,
241-
username: account.username,
242-
publicId: account.publicId
243-
},
244-
device: userDevice || 'Unknown',
245-
os: os.name || 'Unknown'
236+
await createLuciaSessionCookie(ctx.event, {
237+
accountId: account.id,
238+
username: account.username,
239+
publicId: account.publicId
246240
});
247-
const cookie = lucia.createSessionCookie(accountSession.id);
248-
setCookie(event, cookie.name, cookie.value, cookie.attributes);
249-
250-
await db
251-
.update(accounts)
252-
.set({ lastLoginAt: new Date() })
253-
.where(eq(accounts.id, account.id));
254241

255242
const defaultOrg = account.orgMemberships.sort((a, b) => a.id - b.id)[0]
256243
?.org.shortcode;

apps/platform/trpc/routers/authRouter/passwordRouter.ts

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
router,
55
accountProcedure,
66
publicRateLimitedProcedure
7-
} from '../../trpc';
7+
} from '~platform/trpc/trpc';
88
import { eq } from '@u22n/database/orm';
99
import { accounts } from '@u22n/database/schema';
1010
import {
@@ -14,14 +14,14 @@ import {
1414
strongPasswordSchema
1515
} from '@u22n/utils';
1616
import { TRPCError } from '@trpc/server';
17-
import { lucia } from '../../../utils/auth';
17+
import { lucia } from '~platform/utils/auth';
1818
import { validateUsername } from './signupRouter';
19-
import { createLuciaSessionCookie } from '../../../utils/session';
19+
import { createLuciaSessionCookie } from '~platform/utils/session';
2020
import { decodeHex } from 'oslo/encoding';
2121
import { TOTPController } from 'oslo/otp';
2222
import { setCookie, getCookie, deleteCookie } from 'hono/cookie';
23-
import { env } from '../../../env';
24-
import { storage } from '../../../storage';
23+
import { env } from '~platform/env';
24+
import { storage } from '~platform/storage';
2525

2626
export const passwordRouter = router({
2727
/**
@@ -36,7 +36,7 @@ export const passwordRouter = router({
3636
)
3737
.mutation(async ({ ctx, input }) => {
3838
const { username, password } = input;
39-
const { db, event } = ctx;
39+
const { db } = ctx;
4040

4141
const { accountId, publicId } = await db.transaction(async (tx) => {
4242
try {
@@ -66,18 +66,12 @@ export const passwordRouter = router({
6666
}
6767
});
6868

69-
const cookie = await createLuciaSessionCookie(ctx.event, {
69+
await createLuciaSessionCookie(ctx.event, {
7070
accountId,
7171
username,
7272
publicId
7373
});
7474

75-
setCookie(event, cookie.name, cookie.value, cookie.attributes);
76-
await db
77-
.update(accounts)
78-
.set({ lastLoginAt: new Date() })
79-
.where(eq(accounts.id, accountId));
80-
8175
return { success: true };
8276
}),
8377

@@ -164,20 +158,14 @@ export const passwordRouter = router({
164158
}
165159
);
166160

167-
const cookie = await createLuciaSessionCookie(event, {
161+
await createLuciaSessionCookie(event, {
168162
accountId,
169163
username,
170164
publicId
171165
});
172166

173-
setCookie(event, cookie.name, cookie.value, cookie.attributes);
174167
deleteCookie(event, 'un-2fa-challenge');
175168

176-
await db
177-
.update(accounts)
178-
.set({ lastLoginAt: new Date() })
179-
.where(eq(accounts.id, accountId));
180-
181169
return { success: true, error: null, recoveryCode };
182170
}),
183171

@@ -296,17 +284,11 @@ export const passwordRouter = router({
296284
if (validPassword && otpValid) {
297285
const { id: accountId, username, publicId } = userResponse;
298286

299-
const cookie = await createLuciaSessionCookie(event, {
287+
await createLuciaSessionCookie(event, {
300288
accountId,
301289
username,
302290
publicId
303291
});
304-
setCookie(event, cookie.name, cookie.value, cookie.attributes);
305-
306-
await db
307-
.update(accounts)
308-
.set({ lastLoginAt: new Date() })
309-
.where(eq(accounts.id, userResponse.id));
310292

311293
const defaultOrg = userResponse.orgMemberships.sort(
312294
(a, b) => a.id - b.id
@@ -400,13 +382,12 @@ export const passwordRouter = router({
400382
await lucia.invalidateUserSessions(accountId);
401383
}
402384

403-
const cookie = await createLuciaSessionCookie(event, {
385+
await createLuciaSessionCookie(event, {
404386
accountId,
405387
username: accountData.username,
406388
publicId: accountData.publicId
407389
});
408390

409-
setCookie(event, cookie.name, cookie.value, cookie.attributes);
410391
return { success: true };
411392
})
412393
});

0 commit comments

Comments
 (0)