Skip to content

Commit 71a6900

Browse files
feat/chore/breaking-changes!: move remaining backends to Hono, massive cleanup (#447)
## What does this PR do? Moves remaining backends to Hono Massive Cleanup of everything Preparation for removing Nuxt app from main branch and do hot-fixes only on prod <!-- If there isn't an issue for this PR, please re-review our Contributing Guide and create an issue --> ## Type of change <!-- Please mark the relevant points by using [x] --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] Chore (refactoring code, technical debt, workflow improvements) - [x] Enhancement (small improvements) - [ ] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [x] This change requires a documentation update ## Checklist <!-- We're starting to get more and more contributions. Please help us making this efficient for all of us and go through this checklist. Please tick off what you did --> ### Required - [ ] Read [Contributing Guide](https://github.com/un/inbox/blob/main/CONTRIBUTING.md) - [ ] Self-reviewed my own code - [ ] Tested my code in a local environment - [ ] Commented on my code in hard-to-understand areas - [ ] Checked for warnings, there are none - [ ] Removed all `console.logs` - [ ] Merged the latest changes from main onto my branch with `git pull origin main` - [ ] My changes don't cause any responsiveness issues ### Appreciated - [ ] If a UI change was made: Added a screen recording or screenshots to this PR - [ ] Updated the UnInbox Docs if changes were necessary
1 parent 9d8af78 commit 71a6900

File tree

132 files changed

+1388
-2675
lines changed

Some content is hidden

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

132 files changed

+1388
-2675
lines changed

.npmrc

-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
shamefully-hoist=true
21
auto-install-peers=true

.prettierignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ node_modules
22
.turbo
33
.pnpm-store
44
.nuxt
5-
pnpm-lock.yaml
5+
pnpm-lock.yaml
6+
.next
7+
packages/database/migrations

apps/mail-bridge/package.json

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "@u22n/mail-bridge",
33
"private": true,
4-
"types": "types.ts",
54
"type": "module",
6-
"engines": {
7-
"node": ">=20",
8-
"pnpm": ">=8"
5+
"exports": {
6+
"./trpc": {
7+
"types": "./trpc/index.ts"
8+
}
99
},
1010
"scripts": {
1111
"dev": "tsx watch --clear-screen=false app.ts",
@@ -25,17 +25,16 @@
2525
"@u22n/realtime": "workspace:^",
2626
"@u22n/tiptap": "workspace:^",
2727
"@u22n/tsconfig": "^0.0.2",
28-
"@u22n/types": "workspace:*",
2928
"@u22n/utils": "workspace:*",
30-
"drizzle-kit": "^0.20.17",
3129
"drizzle-orm": "^0.30.3",
3230
"hono": "^4.2.8",
3331
"mailauth": "^4.6.5",
3432
"mailparser": "^3.6.9",
3533
"mysql2": "^3.9.7",
34+
"nanoid": "^5.0.6",
3635
"nodemailer": "^6.9.13",
3736
"superjson": "^2.2.1",
38-
"zod": "^3.22.4"
37+
"zod": "^3.23.8"
3938
},
4039
"devDependencies": {
4140
"@types/node": "^20.12.7",

apps/platform/.gitignore

-7
This file was deleted.

apps/platform/app.ts

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import type { Ctx } from './ctx';
2+
import { env } from './env';
3+
import { Hono } from 'hono';
4+
import { serve } from '@hono/node-server';
5+
import { cors } from 'hono/cors';
6+
import { authApi } from './routes/auth';
7+
import { realtimeApi } from './routes/realtime';
8+
import { trpcPlatformRouter } from './trpc';
9+
import { db } from '@u22n/database';
10+
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
11+
import { authMiddleware } from './middlewares';
12+
13+
const app = new Hono<Ctx>();
14+
15+
// CORS middleware
16+
app.use(
17+
'*',
18+
cors({
19+
origin: env.WEBAPP_URL,
20+
credentials: true
21+
})
22+
);
23+
24+
// Auth middleware
25+
app.use('*', authMiddleware);
26+
27+
// Health check endpoint
28+
app.get('/', (c) => c.json({ status: "I'm Alive 🏝️" }));
29+
30+
// Routes
31+
app.route('/auth', authApi);
32+
app.route('/realtime', realtimeApi);
33+
34+
// TRPC handler
35+
app.use('/trpc/*', async (c) =>
36+
fetchRequestHandler({
37+
router: trpcPlatformRouter,
38+
createContext: () => ({
39+
db,
40+
account: c.get('account'),
41+
org: null,
42+
event: c
43+
}),
44+
endpoint: '/trpc',
45+
req: c.req.raw
46+
}).then((res) => c.body(res.body, res))
47+
);
48+
49+
// 404 handler
50+
app.notFound((c) => c.json({ message: 'Not Found' }, 404));
51+
52+
serve({
53+
fetch: app.fetch,
54+
port: env.PORT
55+
}).on('listening', () => {
56+
console.info(`Server listening on port ${env.PORT}`);
57+
});

packages/types/index.ts apps/platform/ctx.ts

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1+
import type { HttpBindings } from '@hono/node-server';
12
import type { DatabaseSession } from 'lucia';
3+
4+
export type Ctx = {
5+
Bindings: HttpBindings;
6+
Variables: {
7+
account: {
8+
id: number;
9+
session: any;
10+
} | null;
11+
};
12+
};
13+
214
export type OrgContext = {
315
id: number;
416
publicId: string;
@@ -12,16 +24,8 @@ export type OrgContext = {
1224
role: 'admin' | 'member';
1325
}[];
1426
} | null;
27+
1528
export type AccountContext = {
1629
id: number;
1730
session: DatabaseSession;
1831
} | null;
19-
export type AuthH3SessionData = {
20-
isUserLoggedIn: boolean;
21-
userId?: number | null;
22-
};
23-
export interface MailDomainEntries {
24-
name: string;
25-
postalId: string;
26-
}
27-
export type { TrpcMailBridgeRouter } from '../../apps/mail-bridge';

apps/platform/env.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { createEnv } from '@t3-oss/env-core';
2+
import { z } from 'zod';
3+
4+
const stringToJSON = z.string().transform((str, ctx) => {
5+
try {
6+
return JSON.parse(str) as unknown;
7+
} catch (e) {
8+
ctx.addIssue({ code: 'custom', message: 'Invalid JSON' });
9+
return z.NEVER;
10+
}
11+
});
12+
13+
export const env = createEnv({
14+
server: {
15+
WEBAPP_URL: z.string().url(),
16+
APP_NAME: z.string().min(1).default('UnInbox'),
17+
PRIMARY_DOMAIN: z.string(),
18+
REALTIME_HOST: z.string().min(1),
19+
REALTIME_PORT: z.string(),
20+
REALTIME_APP_ID: z.string().min(1),
21+
REALTIME_APP_KEY: z.string().min(1),
22+
REALTIME_APP_SECRET: z.string().min(1),
23+
MAILBRIDGE_URL: z.string().url(),
24+
MAILBRIDGE_KEY: z.string().min(1),
25+
MAILBRIDGE_POSTAL_SERVERS_DNS_ROOT_URL: z.string().min(1),
26+
MAILBRIDGE_POSTAL_LOCAL_MODE: z.coerce.boolean().default(false),
27+
MAIL_DOMAINS: stringToJSON.pipe(
28+
z.object({
29+
free: z.array(z.string()),
30+
premium: z.array(z.string()),
31+
fwd: z.array(z.string())
32+
})
33+
),
34+
MAILBRIDGE_TRANSACTIONAL_CREDENTIALS: stringToJSON.pipe(
35+
z.object({
36+
apiUrl: z.string().url(),
37+
apiKey: z.string().min(1),
38+
sendAsName: z.string().min(1),
39+
sendAsEmail: z.string().email()
40+
})
41+
),
42+
STORAGE_URL: z.string().url(),
43+
STORAGE_KEY: z.string().min(1),
44+
DB_REDIS_CONNECTION_STRING: z.string().min(1),
45+
UNKEY_ROOT_KEY: z.string().nullable().default(null),
46+
EE_LICENSE_KEY: z.string().nullable().default(null),
47+
BILLING_KEY: z.string().nullable().default(null),
48+
BILLING_URL: z.string().url().nullable().default(null),
49+
PORT: z.coerce.number().int().min(1).max(65535).default(3300),
50+
NODE_ENV: z.enum(['development', 'production']).default('development')
51+
},
52+
client: {},
53+
clientPrefix: '_', // Not used, just for making TS happy
54+
runtimeEnv: process.env
55+
});

apps/platform/middleware/01.cors.ts

-29
This file was deleted.

apps/platform/middleware/02.auth.ts

-24
This file was deleted.

apps/platform/middlewares.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getCookie } from 'hono/cookie';
2+
import { storage } from './storage';
3+
import { createMiddleware } from 'hono/factory';
4+
import type { Ctx } from './ctx';
5+
6+
export const authMiddleware = createMiddleware<Ctx>(async (c, next) => {
7+
const sessionCookie = getCookie(c, 'unsession');
8+
if (!sessionCookie) {
9+
c.set('account', null);
10+
await next();
11+
} else {
12+
const sessionObject = await storage.session.getItem(sessionCookie);
13+
if (!sessionObject) {
14+
c.set('account', null);
15+
await next();
16+
} else {
17+
c.set('account', {
18+
// @ts-expect-error, not typed properly yet
19+
id: Number(sessionObject.attributes.account.id),
20+
session: sessionObject
21+
});
22+
await next();
23+
}
24+
}
25+
});

apps/platform/nitro.config.ts

-95
This file was deleted.

0 commit comments

Comments
 (0)