feat(backend): scaffold Express API with health and module layout
Add src/routes/notifications, services/pushService, models/device, scheduler stubs, and entrypoint with GET /health and startup log.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.env
|
||||
*.log
|
||||
1493
package-lock.json
generated
Normal file
1493
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "notification-wakeup-service",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "tsx watch src/index.ts",
|
||||
"start": "tsx src/index.ts",
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/node": "^22.10.0",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
20
src/index.ts
Normal file
20
src/index.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import express from "express";
|
||||
import { notificationsRouter } from "./routes/notifications.js";
|
||||
import { startScheduler } from "./scheduler.js";
|
||||
|
||||
const app = express();
|
||||
const port = Number(process.env.PORT) || 3000;
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
app.get("/health", (_req, res) => {
|
||||
res.status(200).json({ status: "ok" });
|
||||
});
|
||||
|
||||
app.use("/notifications", notificationsRouter);
|
||||
|
||||
startScheduler();
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log("* Running backend");
|
||||
});
|
||||
7
src/models/device.ts
Normal file
7
src/models/device.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface Device {
|
||||
id: string;
|
||||
pushToken: string;
|
||||
platform: "ios" | "android" | "web";
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
7
src/routes/notifications.ts
Normal file
7
src/routes/notifications.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Router } from "express";
|
||||
|
||||
export const notificationsRouter = Router();
|
||||
|
||||
notificationsRouter.get("/", (_req, res) => {
|
||||
res.json({ ok: true, resource: "notifications" });
|
||||
});
|
||||
16
src/scheduler.ts
Normal file
16
src/scheduler.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
let intervalId: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
export function startScheduler(): void {
|
||||
if (intervalId !== undefined) return;
|
||||
// TODO: replace with job queue or cron for wake-up checks
|
||||
intervalId = setInterval(() => {
|
||||
// placeholder tick
|
||||
}, 60_000);
|
||||
}
|
||||
|
||||
export function stopScheduler(): void {
|
||||
if (intervalId !== undefined) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = undefined;
|
||||
}
|
||||
}
|
||||
8
src/services/pushService.ts
Normal file
8
src/services/pushService.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { Device } from "../models/device.js";
|
||||
|
||||
export async function sendPushToDevice(
|
||||
_device: Device,
|
||||
_payload: Record<string, unknown>
|
||||
): Promise<void> {
|
||||
// TODO: integrate with push provider (FCM, APNs, etc.)
|
||||
}
|
||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user