Initial commit
This commit is contained in:
25
artifacts/api-server/.replit-artifact/artifact.toml
Normal file
25
artifacts/api-server/.replit-artifact/artifact.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
kind = "api"
|
||||
previewPath = "/api" # TODO - should be excluded from preview in the first place
|
||||
title = "API Server"
|
||||
version = "1.0.0"
|
||||
id = "3B4_FFSkEVBkAeYMFRJ2e"
|
||||
|
||||
[[services]]
|
||||
localPort = 8080
|
||||
name = "API Server"
|
||||
paths = ["/api"]
|
||||
|
||||
[services.development]
|
||||
run = "pnpm --filter @workspace/api-server run dev"
|
||||
|
||||
[services.production]
|
||||
build = "pnpm --filter @workspace/api-server run build"
|
||||
|
||||
[services.production.run]
|
||||
args = ["node", "artifacts/api-server/dist/index.cjs"]
|
||||
|
||||
[services.production.run.env]
|
||||
PORT = "8080"
|
||||
|
||||
[services.production.health.startup]
|
||||
path = "/api/healthz"
|
||||
75
artifacts/api-server/build.ts
Normal file
75
artifacts/api-server/build.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { build as esbuild } from "esbuild";
|
||||
import { rm, readFile } from "fs/promises";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// server deps to bundle to reduce openat(2) syscalls
|
||||
// which helps cold start times without risking some
|
||||
// packages that are not bundle compatible
|
||||
const allowlist = [
|
||||
"@google/generative-ai",
|
||||
"axios",
|
||||
"connect-pg-simple",
|
||||
"cors",
|
||||
"date-fns",
|
||||
"drizzle-orm",
|
||||
"drizzle-zod",
|
||||
"express",
|
||||
"express-rate-limit",
|
||||
"express-session",
|
||||
"jsonwebtoken",
|
||||
"memorystore",
|
||||
"multer",
|
||||
"nanoid",
|
||||
"nodemailer",
|
||||
"openai",
|
||||
"passport",
|
||||
"passport-local",
|
||||
"pg",
|
||||
"stripe",
|
||||
"uuid",
|
||||
"ws",
|
||||
"xlsx",
|
||||
"zod",
|
||||
"zod-validation-error",
|
||||
];
|
||||
|
||||
async function buildAll() {
|
||||
const distDir = path.resolve(__dirname, "dist");
|
||||
await rm(distDir, { recursive: true, force: true });
|
||||
|
||||
console.log("building server...");
|
||||
const pkgPath = path.resolve(__dirname, "package.json");
|
||||
const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
|
||||
const allDeps = [
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
...Object.keys(pkg.devDependencies || {}),
|
||||
];
|
||||
const externals = allDeps.filter(
|
||||
(dep) =>
|
||||
!allowlist.includes(dep) &&
|
||||
!(pkg.dependencies?.[dep]?.startsWith("workspace:")),
|
||||
);
|
||||
|
||||
await esbuild({
|
||||
entryPoints: [path.resolve(__dirname, "src/index.ts")],
|
||||
platform: "node",
|
||||
bundle: true,
|
||||
format: "cjs",
|
||||
outfile: path.resolve(distDir, "index.cjs"),
|
||||
define: {
|
||||
"process.env.NODE_ENV": '"production"',
|
||||
},
|
||||
minify: true,
|
||||
external: externals,
|
||||
logLevel: "info",
|
||||
});
|
||||
}
|
||||
|
||||
buildAll().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
27
artifacts/api-server/package.json
Normal file
27
artifacts/api-server/package.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "@workspace/api-server",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "NODE_ENV=development tsx ./src/index.ts",
|
||||
"build": "tsx ./build.ts",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@workspace/db": "workspace:*",
|
||||
"@workspace/api-zod": "workspace:*",
|
||||
"drizzle-orm": "catalog:",
|
||||
"express": "^5",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/cookie-parser": "^1.4.10",
|
||||
"esbuild": "^0.27.3",
|
||||
"tsx": "catalog:"
|
||||
}
|
||||
}
|
||||
13
artifacts/api-server/src/app.ts
Normal file
13
artifacts/api-server/src/app.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import express, { type Express } from "express";
|
||||
import cors from "cors";
|
||||
import router from "./routes";
|
||||
|
||||
const app: Express = express();
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
app.use("/api", router);
|
||||
|
||||
export default app;
|
||||
19
artifacts/api-server/src/index.ts
Normal file
19
artifacts/api-server/src/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import app from "./app";
|
||||
|
||||
const rawPort = process.env["PORT"];
|
||||
|
||||
if (!rawPort) {
|
||||
throw new Error(
|
||||
"PORT environment variable is required but was not provided.",
|
||||
);
|
||||
}
|
||||
|
||||
const port = Number(rawPort);
|
||||
|
||||
if (Number.isNaN(port) || port <= 0) {
|
||||
throw new Error(`Invalid PORT value: "${rawPort}"`);
|
||||
}
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
||||
0
artifacts/api-server/src/lib/.gitkeep
Normal file
0
artifacts/api-server/src/lib/.gitkeep
Normal file
0
artifacts/api-server/src/middlewares/.gitkeep
Normal file
0
artifacts/api-server/src/middlewares/.gitkeep
Normal file
11
artifacts/api-server/src/routes/health.ts
Normal file
11
artifacts/api-server/src/routes/health.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Router, type IRouter } from "express";
|
||||
import { HealthCheckResponse } from "@workspace/api-zod";
|
||||
|
||||
const router: IRouter = Router();
|
||||
|
||||
router.get("/healthz", (_req, res) => {
|
||||
const data = HealthCheckResponse.parse({ status: "ok" });
|
||||
res.json(data);
|
||||
});
|
||||
|
||||
export default router;
|
||||
8
artifacts/api-server/src/routes/index.ts
Normal file
8
artifacts/api-server/src/routes/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Router, type IRouter } from "express";
|
||||
import healthRouter from "./health";
|
||||
|
||||
const router: IRouter = Router();
|
||||
|
||||
router.use(healthRouter);
|
||||
|
||||
export default router;
|
||||
17
artifacts/api-server/tsconfig.json
Normal file
17
artifacts/api-server/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../lib/db"
|
||||
},
|
||||
{
|
||||
"path": "../../lib/api-zod"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user