diff --git a/.dockerignore b/.dockerignore index c6ff9ac8..876e20a0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -22,4 +22,5 @@ next-env.d.ts *.log .machinelogs*.json *-audit.json -config \ No newline at end of file +config +package-lock.json diff --git a/.gitignore b/.gitignore index cf8f14d9..34366f74 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ next-env.d.ts *-audit.json migrations package-lock.json +tsconfig.tsbuildinfo diff --git a/Dockerfile b/Dockerfile index d7385b63..a9e95bc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,9 @@ FROM node:20-alpine AS builder WORKDIR /app -COPY package*.json ./ +COPY package.json ./ -RUN npm ci +RUN npm install COPY . . @@ -16,9 +16,9 @@ RUN apk add --no-cache curl WORKDIR /app -COPY package*.json ./ +COPY package.json ./ -RUN npm ci --only=production +RUN npm install --omit=dev COPY --from=builder /app/.next ./.next COPY --from=builder /app/dist ./dist diff --git a/Makefile b/Makefile index 2399d018..abf81e04 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: docker build -t pangolin . test: - docker run -it -p 3000:3000 -p 3001:3001 --env-file=.env-docker -v ./config:/config pangolin + docker run -it -p 3000:3000 -p 3001:3001 --env-file=.env -v ./config:/app/config pangolin clean: - docker rmi pangolin \ No newline at end of file + docker rmi pangolin diff --git a/package.json b/package.json index 0d3ef7b9..f4080bbe 100644 --- a/package.json +++ b/package.json @@ -2,17 +2,19 @@ "name": "@fossorial/pangolin", "version": "0.1.0", "private": true, + "type": "module", "scripts": { "dev": "dotenvx run -- tsx watch server/index.ts", "db:generate": "drizzle-kit generate", "db:push": "npx tsx server/db/migrate.ts", "db:hydrate": "npx tsx scripts/hydrate.ts", "db:studio": "drizzle-kit studio", - "build": "next build && tsc --project tsconfig.json && tsc-alias -p tsconfig.json", - "start": "ENVIRONMENT=prod node dist/server/index.js", + "build": "mkdir -p dist && next build && node scripts/esbuild.mjs -e server/index.ts -o dist/server.mjs", + "start": "ENVIRONMENT=prod node dist/server.mjs", "email": "email dev --dir server/emails/templates --port 3002" }, "dependencies": { + "@esbuild-plugins/tsconfig-paths": "0.1.2", "@hookform/resolvers": "3.9.0", "@lucia-auth/adapter-drizzle": "1.1.0", "@node-rs/argon2": "1.8.3", @@ -28,8 +30,11 @@ "cookie-parser": "1.4.6", "cors": "2.8.5", "drizzle-orm": "0.33.0", + "esbuild": "0.20.1", + "esbuild-node-externals": "1.13.0", "express": "4.21.0", "express-rate-limit": "7.4.0", + "glob": "11.0.0", "helmet": "7.1.0", "http-errors": "2.0.0", "lucia": "3.2.0", @@ -41,10 +46,12 @@ "react": "^18", "react-dom": "^18", "react-hook-form": "7.53.0", + "rebuild": "0.1.2", "tailwind-merge": "2.5.3", "tailwindcss-animate": "1.0.7", "winston": "3.14.2", "winston-daily-rotate-file": "5.0.0", + "yargs": "17.7.2", "zod": "3.23.8", "zod-validation-error": "3.4.0" }, @@ -58,6 +65,7 @@ "@types/nodemailer": "6.4.16", "@types/react": "^18", "@types/react-dom": "^18", + "@types/yargs": "17.0.33", "drizzle-kit": "0.24.2", "eslint": "^8", "eslint-config-next": "14.2.13", diff --git a/scripts/esbuild.mjs b/scripts/esbuild.mjs new file mode 100644 index 00000000..5afdc211 --- /dev/null +++ b/scripts/esbuild.mjs @@ -0,0 +1,74 @@ +import esbuild from "esbuild"; +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; +import { nodeExternalsPlugin } from "esbuild-node-externals"; +// import { glob } from "glob"; +// import path from "path"; + +const banner = ` +// patch __dirname +// import { fileURLToPath } from "url"; +// import path from "path"; +// const __filename = fileURLToPath(import.meta.url); +// const __dirname = path.dirname(__filename); + +// allow top level await +import { createRequire as topLevelCreateRequire } from "module"; +const require = topLevelCreateRequire(import.meta.url); +`; + +const argv = yargs(hideBin(process.argv)) + .usage("Usage: $0 -entry [string] -out [string]") + .option("entry", { + alias: "e", + describe: "Entry point file", + type: "string", + demandOption: true, + }) + .option("out", { + alias: "o", + describe: "Output file path", + type: "string", + demandOption: true, + }) + .help() + .alias("help", "h").argv; + +// generate a list of all package.json files in the monorepo +function getPackagePaths() { + // const packagePaths = []; + // const packageGlob = "package.json"; + // const packageJsonFiles = glob.sync(packageGlob); + // for (const packageJsonFile of packageJsonFiles) { + // packagePaths.push(path.dirname(packageJsonFile) + "/package.json"); + // } + // return packagePaths; + return ["package.json"]; +} + +esbuild + .build({ + entryPoints: [argv.entry], + bundle: true, + outfile: argv.out, + format: "esm", + banner: { + js: banner, + }, + platform: "node", + external: ["body-parser"], + plugins: [ + nodeExternalsPlugin({ + packagePath: getPackagePaths(), + }), + ], + sourcemap: false, + target: "node20", + }) + .then(() => { + console.log("Build completed successfully"); + }) + .catch((error) => { + console.error("Build failed:", error); + process.exit(1); + }); diff --git a/server/db/index.ts b/server/db/index.ts index 206a4d24..c25c2bea 100644 --- a/server/db/index.ts +++ b/server/db/index.ts @@ -4,9 +4,9 @@ import * as schema from "@server/db/schema"; import environment from "@server/environment"; import path from "path"; -const sqlite = new Database( - path.join(environment.CONFIG_PATH, "db", "db.sqlite"), -); +const location = path.join(environment.CONFIG_PATH, "db", "db.sqlite"); + +const sqlite = new Database(location); export const db = drizzle(sqlite, { schema }); export default db; diff --git a/server/index.ts b/server/index.ts index 189c2e99..ff432824 100644 --- a/server/index.ts +++ b/server/index.ts @@ -26,7 +26,7 @@ app.prepare().then(() => { // External server const externalServer = express(); - externalServer.use(helmet()); + // externalServer.use(helmet()); // Disabled because causes issues with Next.js externalServer.use(cors()); externalServer.use(cookieParser()); externalServer.use(express.json()); diff --git a/src/app/globals.css b/src/app/globals.css index e9b325d8..5965ac69 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,47 +3,47 @@ @tailwind utilities; @layer base { :root { - --background: 30 21% 95%; - --foreground: 30 5% 10%; - --card: 30 21% 90%; - --card-foreground: 30 5% 15%; - --popover: 30 21% 95%; - --popover-foreground: 30 95% 10%; - --primary: 30 22% 47%; + --background: 28.4 100% 100%; + --foreground: 28.4 5% 10%; + --card: 28.4 50% 100%; + --card-foreground: 28.4 5% 15%; + --popover: 28.4 100% 100%; + --popover-foreground: 28.4 100% 10%; + --primary: 28.4 72.5% 25.7%; --primary-foreground: 0 0% 100%; - --secondary: 30 21% 72%; + --secondary: 28.4 30% 90%; --secondary-foreground: 0 0% 0%; - --muted: -8 21% 85%; - --muted-foreground: 30 5% 40%; - --accent: -8 21% 80%; - --accent-foreground: 30 5% 15%; - --destructive: 0 50% 50%; - --destructive-foreground: 30 5% 90%; - --border: 30 21% 72%; - --input: 30 21% 50%; - --ring: 30 22% 47%; + --muted: -9.600000000000001 30% 95%; + --muted-foreground: 28.4 5% 40%; + --accent: -9.600000000000001 30% 90%; + --accent-foreground: 28.4 5% 15%; + --destructive: 0 100% 50%; + --destructive-foreground: 28.4 5% 100%; + --border: 28.4 30% 82%; + --input: 28.4 30% 50%; + --ring: 28.4 72.5% 25.7%; --radius: 0rem; } .dark { - --background: 30 21% 10%; - --foreground: 30 5% 90%; - --card: 30 21% 10%; - --card-foreground: 30 5% 90%; - --popover: 30 21% 5%; - --popover-foreground: 30 5% 90%; - --primary: 30 22% 47%; + --background: 28.4 50% 10%; + --foreground: 28.4 5% 100%; + --card: 28.4 50% 10%; + --card-foreground: 28.4 5% 100%; + --popover: 28.4 50% 5%; + --popover-foreground: 28.4 5% 100%; + --primary: 28.4 72.5% 25.7%; --primary-foreground: 0 0% 100%; - --secondary: 30 21% 20%; + --secondary: 28.4 30% 20%; --secondary-foreground: 0 0% 100%; - --muted: -8 21% 25%; - --muted-foreground: 30 5% 65%; - --accent: -8 21% 25%; - --accent-foreground: 30 5% 90%; - --destructive: 0 50% 50%; - --destructive-foreground: 30 5% 90%; - --border: 30 21% 50%; - --input: 30 21% 50%; - --ring: 30 22% 47%; + --muted: -9.600000000000001 30% 25%; + --muted-foreground: 28.4 5% 65%; + --accent: -9.600000000000001 30% 25%; + --accent-foreground: 28.4 5% 95%; + --destructive: 0 100% 50%; + --destructive-foreground: 28.4 5% 100%; + --border: 28.4 30% 50%; + --input: 28.4 30% 50%; + --ring: 28.4 72.5% 25.7%; --radius: 0rem; } } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 06b09549..8ca3ad2b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,19 +1,24 @@ import type { Metadata } from "next"; import "./globals.css"; +import { Noto_Sans } from "next/font/google"; export const metadata: Metadata = { title: "Pangolin", description: "", }; +const inter = Noto_Sans({ subsets: ["latin"] }); + export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( - - {children} + + +
{children}
+ ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 60c661d9..430093a3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,3 @@ export default function Page() { - return ( - <> -

Hello world

- - ); + return <>; } diff --git a/tsconfig.server.json b/tsconfig.server.json deleted file mode 100644 index e08c2ae2..00000000 --- a/tsconfig.server.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "outDir": "./dist", - "noEmit": false, - "baseUrl": ".", - "paths": { - "@server/*": ["./server/*"] - } - }, - "include": ["**/*.ts"] -}