@alexmc2/create-express-api-starter 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -8
- package/dist/cli.js +80 -29
- package/dist/cli.js.map +1 -1
- package/package.json +14 -10
- package/templates/js/mvc/package.json.ejs +10 -10
- package/templates/js/simple/package.json.ejs +10 -10
- package/templates/ts/shared/.eslintrc.cjs.ejs +39 -0
- package/templates/ts/{mvc → shared}/package.json.ejs +22 -22
- package/templates/ts/shared/tsconfig.eslint.json.ejs +8 -0
- package/templates/ts/mvc/.eslintrc.cjs.ejs +0 -27
- package/templates/ts/simple/.env.example.ejs +0 -7
- package/templates/ts/simple/.eslintrc.cjs.ejs +0 -27
- package/templates/ts/simple/.gitignore.ejs +0 -6
- package/templates/ts/simple/__tests__/app.test.ts.ejs +0 -45
- package/templates/ts/simple/compose.yaml.ejs +0 -13
- package/templates/ts/simple/db/schema.sql.ejs +0 -8
- package/templates/ts/simple/db/seed.sql.ejs +0 -7
- package/templates/ts/simple/jest.config.js.ejs +0 -7
- package/templates/ts/simple/package.json.ejs +0 -51
- package/templates/ts/simple/scripts/dbCreate.js.ejs +0 -93
- package/templates/ts/simple/scripts/dbReset.js.ejs +0 -40
- package/templates/ts/simple/scripts/dbSeed.js.ejs +0 -62
- package/templates/ts/simple/scripts/dbSetup.js.ejs +0 -62
- package/templates/ts/simple/src/app.ts.ejs +0 -45
- package/templates/ts/simple/src/db/pool.ts.ejs +0 -17
- package/templates/ts/simple/src/errors/AppError.ts.ejs +0 -14
- package/templates/ts/simple/src/middleware/errorHandler.ts.ejs +0 -49
- package/templates/ts/simple/src/middleware/notFound.ts.ejs +0 -13
- package/templates/ts/simple/src/routes/health.ts.ejs +0 -13
- package/templates/ts/simple/src/server.ts.ejs +0 -15
- package/templates/ts/simple/src/utils/getPort.ts.ejs +0 -12
- package/templates/ts/simple/tsconfig.json.ejs +0 -13
- /package/templates/ts/{mvc → shared}/.env.example.ejs +0 -0
- /package/templates/ts/{mvc → shared}/.gitignore.ejs +0 -0
- /package/templates/ts/{mvc → shared}/__tests__/app.test.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/compose.yaml.ejs +0 -0
- /package/templates/ts/{mvc → shared}/db/schema.sql.ejs +0 -0
- /package/templates/ts/{mvc → shared}/db/seed.sql.ejs +0 -0
- /package/templates/ts/{mvc → shared}/jest.config.js.ejs +0 -0
- /package/templates/ts/{mvc → shared}/scripts/dbCreate.js.ejs +0 -0
- /package/templates/ts/{mvc → shared}/scripts/dbReset.js.ejs +0 -0
- /package/templates/ts/{mvc → shared}/scripts/dbSeed.js.ejs +0 -0
- /package/templates/ts/{mvc → shared}/scripts/dbSetup.js.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/app.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/db/pool.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/errors/AppError.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/middleware/errorHandler.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/middleware/notFound.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/routes/health.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/server.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/src/utils/getPort.ts.ejs +0 -0
- /package/templates/ts/{mvc → shared}/tsconfig.json.ejs +0 -0
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Builds and configures the Express app (middleware, routes, and error pipeline).
|
|
2
|
-
<% } %>
|
|
3
|
-
import cors from 'cors';
|
|
4
|
-
import express from 'express';
|
|
5
|
-
import helmet from 'helmet';
|
|
6
|
-
import morgan from 'morgan';
|
|
7
|
-
|
|
8
|
-
import errorHandler from './middleware/errorHandler';
|
|
9
|
-
import notFound from './middleware/notFound';
|
|
10
|
-
import healthRouter from './routes/health';
|
|
11
|
-
import usersRouter from './routes/users';
|
|
12
|
-
|
|
13
|
-
const app = express();
|
|
14
|
-
|
|
15
|
-
<% if (educational) { %>// Parse JSON request bodies so route handlers can read data from req.body.
|
|
16
|
-
// Without this middleware, req.body is undefined for JSON requests.
|
|
17
|
-
<% } %>app.use(express.json());
|
|
18
|
-
<% if (educational) { %>// Enable CORS so browser clients on other origins can call this API.
|
|
19
|
-
<% } %>app.use(cors());
|
|
20
|
-
<% if (educational) { %>// Add common HTTP security headers.
|
|
21
|
-
// Helmet applies safe defaults that reduce exposure to common web attacks.
|
|
22
|
-
<% } %>app.use(helmet());
|
|
23
|
-
<% if (educational) { %>// Log each request in development format to make local debugging easier.
|
|
24
|
-
<% } %>app.use(morgan('dev'));
|
|
25
|
-
|
|
26
|
-
<% if (educational) { %>// Provide a simple root endpoint so visiting the API URL in a browser
|
|
27
|
-
// shows available routes instead of an immediate 404 response.
|
|
28
|
-
<% } %>app.get('/', (_req, res) => {
|
|
29
|
-
res.json({
|
|
30
|
-
message: 'API is running',
|
|
31
|
-
endpoints: {
|
|
32
|
-
health: 'GET /health',
|
|
33
|
-
users: 'GET /api/users',
|
|
34
|
-
createUser: 'POST /api/users'
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
app.use('/health', healthRouter);
|
|
40
|
-
app.use('/api/users', usersRouter);
|
|
41
|
-
|
|
42
|
-
app.use(notFound);
|
|
43
|
-
app.use(errorHandler);
|
|
44
|
-
|
|
45
|
-
export default app;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Creates and exports a shared PostgreSQL connection pool for repository queries.
|
|
2
|
-
<% } %>
|
|
3
|
-
<% if (educational) { %>// Create one shared connection pool for the whole application.
|
|
4
|
-
// Reusing connections is faster and avoids exhausting database limits.
|
|
5
|
-
<% } %>import { Pool } from 'pg';
|
|
6
|
-
|
|
7
|
-
const databaseUrl = process.env.DATABASE_URL;
|
|
8
|
-
|
|
9
|
-
if (!databaseUrl) {
|
|
10
|
-
throw new Error('DATABASE_URL is required for Postgres mode.');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const pool = new Pool({
|
|
14
|
-
connectionString: databaseUrl
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
export default pool;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Defines an AppError class for expected API errors that include HTTP status codes.
|
|
2
|
-
<% } %>
|
|
3
|
-
<% if (educational) { %>// A custom error class for handling API errors. By extending JavaScript's
|
|
4
|
-
// built-in Error class, we ensure that stack traces are generated correctly
|
|
5
|
-
// and that the error handler can distinguish between anticipated API
|
|
6
|
-
// errors and unexpected application failures.
|
|
7
|
-
<% } %>export default class AppError extends Error {
|
|
8
|
-
status: number;
|
|
9
|
-
|
|
10
|
-
constructor(status: number, message: string) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.status = status;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Converts thrown errors into consistent JSON HTTP responses for clients.
|
|
2
|
-
<% } %>
|
|
3
|
-
import type { ErrorRequestHandler } from 'express';
|
|
4
|
-
|
|
5
|
-
interface HttpError extends Error {
|
|
6
|
-
status?: number;
|
|
7
|
-
code?: string;
|
|
8
|
-
detail?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
<% if (educational) { %>// Express treats middleware with four parameters as an error handler.
|
|
12
|
-
// Any error passed to next(error) in the app is routed to this function.
|
|
13
|
-
<% } %>const errorHandler: ErrorRequestHandler = (error: HttpError, _req, res, _next) => {
|
|
14
|
-
<% if (educational) { %> // PostgreSQL error code 23505 means a UNIQUE constraint was violated.
|
|
15
|
-
// Returning HTTP 409 tells clients that the request conflicts with existing data.
|
|
16
|
-
<% } %> if (error?.code === '23505') {
|
|
17
|
-
const detail = typeof error?.detail === 'string' ? error.detail : '';
|
|
18
|
-
const message = detail.includes('email')
|
|
19
|
-
? 'A user with this email already exists.'
|
|
20
|
-
: 'A record with this value already exists.';
|
|
21
|
-
|
|
22
|
-
return res.status(409).json({
|
|
23
|
-
status: 409,
|
|
24
|
-
message
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const status = Number.isInteger(error?.status) ? (error.status as number) : 500;
|
|
29
|
-
const message = typeof error?.message === 'string' ? error.message : 'Internal server error.';
|
|
30
|
-
|
|
31
|
-
const payload: {
|
|
32
|
-
status: number;
|
|
33
|
-
message: string;
|
|
34
|
-
stack?: string;
|
|
35
|
-
} = {
|
|
36
|
-
status,
|
|
37
|
-
message
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
<% if (educational) { %> // Include stack traces in development to speed up debugging.
|
|
41
|
-
// Omit them in production so internal implementation details stay private.
|
|
42
|
-
<% } %> if (process.env.NODE_ENV === 'development' && typeof error?.stack === 'string') {
|
|
43
|
-
payload.stack = error.stack;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
res.status(status).json(payload);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default errorHandler;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Handles unmatched routes by forwarding a 404 error to the central error handler.
|
|
2
|
-
<% } %>
|
|
3
|
-
import type { RequestHandler } from 'express';
|
|
4
|
-
|
|
5
|
-
import AppError from '../errors/AppError';
|
|
6
|
-
|
|
7
|
-
<% if (educational) { %>// This middleware runs only when no route matched the request.
|
|
8
|
-
// It forwards a 404 error to the central error handler for a uniform response.
|
|
9
|
-
<% } %>const notFound: RequestHandler = (_req, _res, next) => {
|
|
10
|
-
next(new AppError(404, 'Route not found.'));
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export default notFound;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Registers the health-check route used to confirm the API process is running.
|
|
2
|
-
<% } %>
|
|
3
|
-
import { Router } from 'express';
|
|
4
|
-
|
|
5
|
-
const router = Router();
|
|
6
|
-
|
|
7
|
-
<% if (educational) { %>// Health-check endpoint used by monitors, load balancers, and container
|
|
8
|
-
// platforms to verify that the API process is running.
|
|
9
|
-
<% } %>router.get('/', (_req, res) => {
|
|
10
|
-
res.status(200).json({ ok: true });
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
export default router;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Application entry point that loads environment variables and starts the HTTP server.
|
|
2
|
-
<% } %>
|
|
3
|
-
<% if (educational) { %>// Load variables from .env before other modules read process.env values.
|
|
4
|
-
<% } %>import 'dotenv/config';
|
|
5
|
-
|
|
6
|
-
import app from './app';
|
|
7
|
-
import { getPort } from './utils/getPort';
|
|
8
|
-
|
|
9
|
-
<% if (educational) { %>// Read the server port from PORT, defaulting to 3000 for local development.
|
|
10
|
-
<% } %>const port = getPort(process.env.PORT, 3000);
|
|
11
|
-
|
|
12
|
-
<% if (educational) { %>// Start the HTTP server and listen for incoming requests.
|
|
13
|
-
<% } %>app.listen(port, () => {
|
|
14
|
-
console.log(`Server listening on port ${port}`);
|
|
15
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<% if (educational) { %>// File overview: Parses PORT into a usable integer with a safe fallback.
|
|
2
|
-
<% } %>
|
|
3
|
-
<% if (educational) { %>// Keep this helper small and pure so entrypoint code stays easy to scan.
|
|
4
|
-
<% } %>export function getPort(value: string | undefined, fallback = 3000): number {
|
|
5
|
-
const parsed = Number(value);
|
|
6
|
-
|
|
7
|
-
if (Number.isInteger(parsed) && parsed > 0) {
|
|
8
|
-
return parsed;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return fallback;
|
|
12
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|