@sundaysf/cli-v2 0.0.4 → 1.0.0
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 +178 -178
- package/dist/README.md +178 -178
- package/dist/bin/generators/class.js.map +1 -1
- package/dist/bin/generators/postman.js.map +1 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/templates/backend/.env.example +13 -13
- package/dist/templates/backend/.prettierignore +2 -2
- package/dist/templates/backend/Dockerfile +14 -14
- package/dist/templates/backend/README.md +18 -18
- package/dist/templates/backend/src/app.ts +34 -34
- package/dist/templates/backend/src/common/utils/environment.resolver.ts +3 -3
- package/dist/templates/backend/src/common/utils/version.resolver.ts +4 -4
- package/dist/templates/backend/src/controllers/health/health.controller.ts +23 -23
- package/dist/templates/backend/src/routes/health/health.router.ts +16 -16
- package/dist/templates/backend/src/routes/index.ts +57 -57
- package/dist/templates/backend/src/server.ts +16 -16
- package/dist/templates/backend/src/types.d.ts +10 -10
- package/dist/templates/backend-db-sql/.env.example +13 -13
- package/dist/templates/backend-db-sql/.prettierignore +2 -2
- package/dist/templates/backend-db-sql/Dockerfile +17 -17
- package/dist/templates/backend-db-sql/README.md +34 -34
- package/dist/templates/backend-db-sql/db/knexfile.ts +34 -33
- package/dist/templates/backend-db-sql/db/migrations/001_create_sundays_package_version.ts +12 -12
- package/dist/templates/backend-db-sql/db/seeds/001_sundays_package_version_seed.ts +10 -10
- package/dist/templates/backend-db-sql/db/src/KnexConnection.ts +74 -74
- package/dist/templates/backend-db-sql/db/src/d.types.ts +18 -18
- package/dist/templates/backend-db-sql/db/src/dao/sundays-package-version/sundays-package-version.dao.ts +71 -71
- package/dist/templates/backend-db-sql/db/src/index.ts +9 -9
- package/dist/templates/backend-db-sql/db/src/interfaces/sundays-package-version/sundays-package-version.interfaces.ts +6 -6
- package/dist/templates/backend-db-sql/db/tsconfig.json +16 -16
- package/dist/templates/backend-db-sql/src/app.ts +34 -34
- package/dist/templates/backend-db-sql/src/common/utils/environment.resolver.ts +3 -3
- package/dist/templates/backend-db-sql/src/common/utils/version.resolver.ts +4 -4
- package/dist/templates/backend-db-sql/src/controllers/health/health.controller.ts +23 -23
- package/dist/templates/backend-db-sql/src/routes/health/health.router.ts +16 -16
- package/dist/templates/backend-db-sql/src/routes/index.ts +57 -57
- package/dist/templates/backend-db-sql/src/server.ts +18 -18
- package/dist/templates/backend-db-sql/src/types.d.ts +10 -10
- package/dist/templates/db-sql/knexfile.ts +33 -33
- package/dist/templates/db-sql/migrations/001_create_sundays_package_version.ts +12 -12
- package/dist/templates/db-sql/seeds/001_sundays_package_version_seed.ts +10 -10
- package/dist/templates/db-sql/src/KnexConnection.ts +74 -74
- package/dist/templates/db-sql/src/d.types.ts +18 -18
- package/dist/templates/db-sql/src/dao/sundays-package-version/sundays-package-version.dao.ts +71 -71
- package/dist/templates/db-sql/src/index.ts +9 -9
- package/dist/templates/db-sql/src/interfaces/sundays-package-version/sundays-package-version.interfaces.ts +6 -6
- package/dist/templates/db-sql/tsconfig.json +16 -16
- package/dist/templates/module/CLAUDE.md +158 -158
- package/dist/templates/module/tsconfig.json +19 -19
- package/package.json +1 -1
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Sundays Framework Project
|
|
2
|
-
|
|
3
|
-
This directory contains the starter backend generated by the CLI.
|
|
4
|
-
|
|
5
|
-
## Quick start
|
|
6
|
-
|
|
7
|
-
1. Install dependencies:
|
|
8
|
-
```
|
|
9
|
-
npm install
|
|
10
|
-
```
|
|
11
|
-
2. Copy `.env.example` to `.env` and set your environment variables.
|
|
12
|
-
3. Start the development server:
|
|
13
|
-
```
|
|
14
|
-
npm run start:dev
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
The server will run on the port specified in your `.env` file.
|
|
18
|
-
|
|
1
|
+
# Sundays Framework Project
|
|
2
|
+
|
|
3
|
+
This directory contains the starter backend generated by the CLI.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
1. Install dependencies:
|
|
8
|
+
```
|
|
9
|
+
npm install
|
|
10
|
+
```
|
|
11
|
+
2. Copy `.env.example` to `.env` and set your environment variables.
|
|
12
|
+
3. Start the development server:
|
|
13
|
+
```
|
|
14
|
+
npm run start:dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The server will run on the port specified in your `.env` file.
|
|
18
|
+
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
import express, { type Express } from 'express';
|
|
3
|
-
import logger from 'morgan';
|
|
4
|
-
import cors from 'cors';
|
|
5
|
-
import { IndexRouter } from './routes/index';
|
|
6
|
-
import { errorMiddleware } from './middlewares/error/error.middleware';
|
|
7
|
-
import { getAllowedOrigins } from './common/config/origins/origins.config';
|
|
8
|
-
dotenv.config();
|
|
9
|
-
|
|
10
|
-
const app: Express = express();
|
|
11
|
-
|
|
12
|
-
app.use(
|
|
13
|
-
logger('tiny', {
|
|
14
|
-
skip: (req, _res) => {
|
|
15
|
-
return req.originalUrl.startsWith('/api/health');
|
|
16
|
-
},
|
|
17
|
-
})
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
app.use(
|
|
21
|
-
cors({
|
|
22
|
-
origin: getAllowedOrigins(),
|
|
23
|
-
credentials: true,
|
|
24
|
-
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
25
|
-
})
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
app.use(express.urlencoded({ extended: true }));
|
|
29
|
-
app.use(express.json());
|
|
30
|
-
|
|
31
|
-
app.use('/api', new IndexRouter().router);
|
|
32
|
-
|
|
33
|
-
app.use(errorMiddleware);
|
|
34
|
-
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import express, { type Express } from 'express';
|
|
3
|
+
import logger from 'morgan';
|
|
4
|
+
import cors from 'cors';
|
|
5
|
+
import { IndexRouter } from './routes/index';
|
|
6
|
+
import { errorMiddleware } from './middlewares/error/error.middleware';
|
|
7
|
+
import { getAllowedOrigins } from './common/config/origins/origins.config';
|
|
8
|
+
dotenv.config();
|
|
9
|
+
|
|
10
|
+
const app: Express = express();
|
|
11
|
+
|
|
12
|
+
app.use(
|
|
13
|
+
logger('tiny', {
|
|
14
|
+
skip: (req, _res) => {
|
|
15
|
+
return req.originalUrl.startsWith('/api/health');
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
app.use(
|
|
21
|
+
cors({
|
|
22
|
+
origin: getAllowedOrigins(),
|
|
23
|
+
credentials: true,
|
|
24
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
app.use(express.urlencoded({ extended: true }));
|
|
29
|
+
app.use(express.json());
|
|
30
|
+
|
|
31
|
+
app.use('/api', new IndexRouter().router);
|
|
32
|
+
|
|
33
|
+
app.use(errorMiddleware);
|
|
34
|
+
|
|
35
35
|
export default app;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const getServiceEnvironment = (): string => {
|
|
2
|
-
const serEnv: string = process.env.ENVIRONMENT || 'undefined';
|
|
3
|
-
return serEnv.charAt(0).toUpperCase() + serEnv.slice(1);
|
|
1
|
+
export const getServiceEnvironment = (): string => {
|
|
2
|
+
const serEnv: string = process.env.ENVIRONMENT || 'undefined';
|
|
3
|
+
return serEnv.charAt(0).toUpperCase() + serEnv.slice(1);
|
|
4
4
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const pjson = require('../../../package.json');
|
|
2
|
-
|
|
3
|
-
export const getServiceVersion = (): string => {
|
|
4
|
-
return pjson['version'];
|
|
1
|
+
const pjson = require('../../../package.json');
|
|
2
|
+
|
|
3
|
+
export const getServiceVersion = (): string => {
|
|
4
|
+
return pjson['version'];
|
|
5
5
|
};
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from 'express';
|
|
2
|
-
import { getServiceVersion } from '../../common/utils/version.resolver';
|
|
3
|
-
import { getServiceEnvironment } from '../../common/utils/environment.resolver';
|
|
4
|
-
|
|
5
|
-
export class HealthController {
|
|
6
|
-
public async getHealthStatus(
|
|
7
|
-
_req: Request,
|
|
8
|
-
res: Response,
|
|
9
|
-
next: NextFunction
|
|
10
|
-
): Promise<void> {
|
|
11
|
-
try {
|
|
12
|
-
const version: string = await getServiceVersion();
|
|
13
|
-
const environment: string = await getServiceEnvironment();
|
|
14
|
-
res.status(200).json({
|
|
15
|
-
success: true,
|
|
16
|
-
health: 'Up!',
|
|
17
|
-
version,
|
|
18
|
-
environment,
|
|
19
|
-
});
|
|
20
|
-
} catch (err: any) {
|
|
21
|
-
next(err);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
1
|
+
import { NextFunction, Request, Response } from 'express';
|
|
2
|
+
import { getServiceVersion } from '../../common/utils/version.resolver';
|
|
3
|
+
import { getServiceEnvironment } from '../../common/utils/environment.resolver';
|
|
4
|
+
|
|
5
|
+
export class HealthController {
|
|
6
|
+
public async getHealthStatus(
|
|
7
|
+
_req: Request,
|
|
8
|
+
res: Response,
|
|
9
|
+
next: NextFunction
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
try {
|
|
12
|
+
const version: string = await getServiceVersion();
|
|
13
|
+
const environment: string = await getServiceEnvironment();
|
|
14
|
+
res.status(200).json({
|
|
15
|
+
success: true,
|
|
16
|
+
health: 'Up!',
|
|
17
|
+
version,
|
|
18
|
+
environment,
|
|
19
|
+
});
|
|
20
|
+
} catch (err: any) {
|
|
21
|
+
next(err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
24
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import { HealthController } from '../../controllers/health/health.controller';
|
|
3
|
-
|
|
4
|
-
export class HealthRouter {
|
|
5
|
-
public router: Router = Router();
|
|
6
|
-
private readonly healthController: HealthController = new HealthController();
|
|
7
|
-
constructor() {
|
|
8
|
-
this.initRoutes();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private initRoutes(): void {
|
|
12
|
-
this.router.get(
|
|
13
|
-
'/',
|
|
14
|
-
this.healthController.getHealthStatus.bind(this.healthController)
|
|
15
|
-
);
|
|
16
|
-
}
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { HealthController } from '../../controllers/health/health.controller';
|
|
3
|
+
|
|
4
|
+
export class HealthRouter {
|
|
5
|
+
public router: Router = Router();
|
|
6
|
+
private readonly healthController: HealthController = new HealthController();
|
|
7
|
+
constructor() {
|
|
8
|
+
this.initRoutes();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
private initRoutes(): void {
|
|
12
|
+
this.router.get(
|
|
13
|
+
'/',
|
|
14
|
+
this.healthController.getHealthStatus.bind(this.healthController)
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
17
|
}
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
import { Router } from 'express';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
export class IndexRouter {
|
|
6
|
-
private _router: Router;
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
this._router = Router();
|
|
10
|
-
this.loadRoutes();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private loadRoutes(): void {
|
|
14
|
-
const routesPath = path.join(__dirname);
|
|
15
|
-
|
|
16
|
-
const folders = fs.readdirSync(routesPath).filter(file =>
|
|
17
|
-
fs.statSync(path.join(routesPath, file)).isDirectory()
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
folders.forEach(folder => {
|
|
21
|
-
const baseName = `${folder}.router`;
|
|
22
|
-
const tsPath = path.join(routesPath, folder, `${baseName}.ts`);
|
|
23
|
-
const jsPath = path.join(routesPath, folder, `${baseName}.js`);
|
|
24
|
-
|
|
25
|
-
let filePath = '';
|
|
26
|
-
if (fs.existsSync(tsPath)) {
|
|
27
|
-
filePath = tsPath;
|
|
28
|
-
} else if (fs.existsSync(jsPath)) {
|
|
29
|
-
filePath = jsPath;
|
|
30
|
-
} else {
|
|
31
|
-
console.warn(`[⚠] No route file found for: ${folder}`);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
const routeModule = require(filePath);
|
|
37
|
-
const RouterClass =
|
|
38
|
-
routeModule.default || Object.values(routeModule).find((e) => typeof e === 'function');
|
|
39
|
-
|
|
40
|
-
if (RouterClass) {
|
|
41
|
-
const instance = new (RouterClass as any)();
|
|
42
|
-
this._router.use(`/${folder}`, instance.router);
|
|
43
|
-
console.log(`[✔] Route mounted: /${folder} → ${path.basename(filePath)}`);
|
|
44
|
-
} else {
|
|
45
|
-
console.warn(`[⚠] No class exported in: ${filePath}`);
|
|
46
|
-
}
|
|
47
|
-
} catch (err) {
|
|
48
|
-
console.error(`[❌] Failed to load router at: ${filePath}`);
|
|
49
|
-
console.error(err);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
public get router(): Router {
|
|
55
|
-
return this._router;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export class IndexRouter {
|
|
6
|
+
private _router: Router;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this._router = Router();
|
|
10
|
+
this.loadRoutes();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private loadRoutes(): void {
|
|
14
|
+
const routesPath = path.join(__dirname);
|
|
15
|
+
|
|
16
|
+
const folders = fs.readdirSync(routesPath).filter(file =>
|
|
17
|
+
fs.statSync(path.join(routesPath, file)).isDirectory()
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
folders.forEach(folder => {
|
|
21
|
+
const baseName = `${folder}.router`;
|
|
22
|
+
const tsPath = path.join(routesPath, folder, `${baseName}.ts`);
|
|
23
|
+
const jsPath = path.join(routesPath, folder, `${baseName}.js`);
|
|
24
|
+
|
|
25
|
+
let filePath = '';
|
|
26
|
+
if (fs.existsSync(tsPath)) {
|
|
27
|
+
filePath = tsPath;
|
|
28
|
+
} else if (fs.existsSync(jsPath)) {
|
|
29
|
+
filePath = jsPath;
|
|
30
|
+
} else {
|
|
31
|
+
console.warn(`[⚠] No route file found for: ${folder}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const routeModule = require(filePath);
|
|
37
|
+
const RouterClass =
|
|
38
|
+
routeModule.default || Object.values(routeModule).find((e) => typeof e === 'function');
|
|
39
|
+
|
|
40
|
+
if (RouterClass) {
|
|
41
|
+
const instance = new (RouterClass as any)();
|
|
42
|
+
this._router.use(`/${folder}`, instance.router);
|
|
43
|
+
console.log(`[✔] Route mounted: /${folder} → ${path.basename(filePath)}`);
|
|
44
|
+
} else {
|
|
45
|
+
console.warn(`[⚠] No class exported in: ${filePath}`);
|
|
46
|
+
}
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error(`[❌] Failed to load router at: ${filePath}`);
|
|
49
|
+
console.error(err);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public get router(): Router {
|
|
55
|
+
return this._router;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
dotenv.config();
|
|
3
|
-
|
|
4
|
-
const envPort: string = process.env.PORT || '3005';
|
|
5
|
-
|
|
6
|
-
if (isNaN(parseInt(envPort))) {
|
|
7
|
-
throw new Error('The port must to be a number');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const PORT: number = parseInt(envPort);
|
|
11
|
-
|
|
12
|
-
(async () => { })().then(async () => {
|
|
13
|
-
const { default: app } = await import('./app');
|
|
14
|
-
app.listen(PORT, () => console.info(`Server up and running on port ${PORT}`));
|
|
15
|
-
});
|
|
16
|
-
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
dotenv.config();
|
|
3
|
+
|
|
4
|
+
const envPort: string = process.env.PORT || '3005';
|
|
5
|
+
|
|
6
|
+
if (isNaN(parseInt(envPort))) {
|
|
7
|
+
throw new Error('The port must to be a number');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const PORT: number = parseInt(envPort);
|
|
11
|
+
|
|
12
|
+
(async () => { })().then(async () => {
|
|
13
|
+
const { default: app } = await import('./app');
|
|
14
|
+
app.listen(PORT, () => console.info(`Server up and running on port ${PORT}`));
|
|
15
|
+
});
|
|
16
|
+
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Request, Response, NextFunction } from 'express';
|
|
2
|
-
|
|
3
|
-
export interface IBaseController {
|
|
4
|
-
getAll(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
5
|
-
getByUuid(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
6
|
-
create(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
7
|
-
update(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
8
|
-
patch(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
9
|
-
delete(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
10
|
-
}
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
|
|
3
|
+
export interface IBaseController {
|
|
4
|
+
getAll(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
5
|
+
getByUuid(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
6
|
+
create(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
7
|
+
update(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
8
|
+
patch(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
9
|
+
delete(req: Request, res: Response, next: NextFunction): Promise<void>;
|
|
10
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# Server
|
|
2
|
-
PORT=3098
|
|
3
|
-
ENVIRONMENT=local
|
|
4
|
-
|
|
5
|
-
# CORS (comma-separated origins with protocol)
|
|
6
|
-
CORS_ALLOWED_ORIGINS=http://localhost:3098
|
|
7
|
-
|
|
8
|
-
# Database
|
|
9
|
-
SQL_HOST=localhost
|
|
10
|
-
SQL_PORT=5432
|
|
11
|
-
SQL_USER=postgres
|
|
12
|
-
SQL_PASSWORD=
|
|
13
|
-
SQL_DB_NAME=mydb
|
|
1
|
+
# Server
|
|
2
|
+
PORT=3098
|
|
3
|
+
ENVIRONMENT=local
|
|
4
|
+
|
|
5
|
+
# CORS (comma-separated origins with protocol)
|
|
6
|
+
CORS_ALLOWED_ORIGINS=http://localhost:3098
|
|
7
|
+
|
|
8
|
+
# Database
|
|
9
|
+
SQL_HOST=localhost
|
|
10
|
+
SQL_PORT=5432
|
|
11
|
+
SQL_USER=postgres
|
|
12
|
+
SQL_PASSWORD=
|
|
13
|
+
SQL_DB_NAME=mydb
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
node_modules/
|
|
2
|
-
dist/
|
|
1
|
+
node_modules/
|
|
2
|
+
dist/
|
|
3
3
|
package-lock.json
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
FROM node:22-alpine AS builder
|
|
2
|
-
WORKDIR /var/api
|
|
3
|
-
COPY package*.json ./
|
|
4
|
-
RUN npm ci
|
|
5
|
-
COPY . .
|
|
6
|
-
RUN npm run build
|
|
7
|
-
RUN npm run db:build
|
|
8
|
-
|
|
9
|
-
FROM node:22-alpine
|
|
10
|
-
WORKDIR /var/api
|
|
11
|
-
COPY package*.json ./
|
|
12
|
-
RUN npm ci --omit=dev
|
|
13
|
-
COPY --from=builder /var/api/dist ./dist
|
|
14
|
-
COPY --from=builder /var/api/db/dist ./db/dist
|
|
15
|
-
COPY --from=builder /var/api/db/package.json ./db/package.json
|
|
16
|
-
EXPOSE 3098
|
|
17
|
-
CMD ["node", "dist/server.js"]
|
|
1
|
+
FROM node:22-alpine AS builder
|
|
2
|
+
WORKDIR /var/api
|
|
3
|
+
COPY package*.json ./
|
|
4
|
+
RUN npm ci
|
|
5
|
+
COPY . .
|
|
6
|
+
RUN npm run build
|
|
7
|
+
RUN npm run db:build
|
|
8
|
+
|
|
9
|
+
FROM node:22-alpine
|
|
10
|
+
WORKDIR /var/api
|
|
11
|
+
COPY package*.json ./
|
|
12
|
+
RUN npm ci --omit=dev
|
|
13
|
+
COPY --from=builder /var/api/dist ./dist
|
|
14
|
+
COPY --from=builder /var/api/db/dist ./db/dist
|
|
15
|
+
COPY --from=builder /var/api/db/package.json ./db/package.json
|
|
16
|
+
EXPOSE 3098
|
|
17
|
+
CMD ["node", "dist/server.js"]
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
# Sundays Framework Project
|
|
2
|
-
|
|
3
|
-
This directory contains the starter backend with embedded database module generated by the CLI.
|
|
4
|
-
|
|
5
|
-
## Quick start
|
|
6
|
-
|
|
7
|
-
1. Install dependencies:
|
|
8
|
-
```
|
|
9
|
-
npm install
|
|
10
|
-
```
|
|
11
|
-
2. Copy `.env.example` to `.env` and set your environment variables (especially the `SQL_*` database variables).
|
|
12
|
-
3. Run database migrations:
|
|
13
|
-
```
|
|
14
|
-
npm run migrate:deploy
|
|
15
|
-
```
|
|
16
|
-
4. Start the development server:
|
|
17
|
-
```
|
|
18
|
-
npm run start:dev
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The server will run on the port specified in your `.env` file.
|
|
22
|
-
|
|
23
|
-
## Database module
|
|
24
|
-
|
|
25
|
-
The `db/` directory contains an independently publishable Knex.js database module. It can be used as part of this backend or published separately as an npm package.
|
|
26
|
-
|
|
27
|
-
### Database commands
|
|
28
|
-
|
|
29
|
-
- `npm run migrate:create` - Create a new migration
|
|
30
|
-
- `npm run migrate:deploy` - Run pending migrations
|
|
31
|
-
- `npm run seed:create` - Create a new seed file
|
|
32
|
-
- `npm run seed:run` - Run seed files
|
|
33
|
-
- `npm run db:build` - Compile the database module
|
|
34
|
-
- `npm run db:publish` - Publish the database module to npm
|
|
1
|
+
# Sundays Framework Project
|
|
2
|
+
|
|
3
|
+
This directory contains the starter backend with embedded database module generated by the CLI.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
1. Install dependencies:
|
|
8
|
+
```
|
|
9
|
+
npm install
|
|
10
|
+
```
|
|
11
|
+
2. Copy `.env.example` to `.env` and set your environment variables (especially the `SQL_*` database variables).
|
|
12
|
+
3. Run database migrations:
|
|
13
|
+
```
|
|
14
|
+
npm run migrate:deploy
|
|
15
|
+
```
|
|
16
|
+
4. Start the development server:
|
|
17
|
+
```
|
|
18
|
+
npm run start:dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The server will run on the port specified in your `.env` file.
|
|
22
|
+
|
|
23
|
+
## Database module
|
|
24
|
+
|
|
25
|
+
The `db/` directory contains an independently publishable Knex.js database module. It can be used as part of this backend or published separately as an npm package.
|
|
26
|
+
|
|
27
|
+
### Database commands
|
|
28
|
+
|
|
29
|
+
- `npm run migrate:create` - Create a new migration
|
|
30
|
+
- `npm run migrate:deploy` - Run pending migrations
|
|
31
|
+
- `npm run seed:create` - Create a new seed file
|
|
32
|
+
- `npm run seed:run` - Run seed files
|
|
33
|
+
- `npm run db:build` - Compile the database module
|
|
34
|
+
- `npm run db:publish` - Publish the database module to npm
|
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
import type { Knex } from "knex";
|
|
2
|
-
import
|
|
3
|
-
dotenv
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
dotenv.config({ path: path.resolve(__dirname, "..", ".env") });
|
|
5
|
+
|
|
6
|
+
const isLocalhost = process.env.SQL_HOST === 'localhost' || process.env.SQL_HOST === '127.0.0.1';
|
|
7
|
+
const rejectUnauthorized = process.env.SQL_REJECT_UNAUTHORIZED !== 'false';
|
|
8
|
+
|
|
9
|
+
const sharedConfig: Knex.Config = {
|
|
10
|
+
client: "postgresql",
|
|
11
|
+
connection: {
|
|
12
|
+
database: process.env.SQL_DB_NAME,
|
|
13
|
+
user: process.env.SQL_USER,
|
|
14
|
+
password: process.env.SQL_PASSWORD,
|
|
15
|
+
host: process.env.SQL_HOST,
|
|
16
|
+
port: process.env.SQL_PORT ? +process.env.SQL_PORT : 5432,
|
|
17
|
+
ssl: isLocalhost ? false : { rejectUnauthorized },
|
|
18
|
+
},
|
|
19
|
+
pool: {
|
|
20
|
+
min: 2,
|
|
21
|
+
max: 10,
|
|
22
|
+
},
|
|
23
|
+
migrations: {
|
|
24
|
+
tableName: "knex_migrations",
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const config: { [key: string]: Knex.Config } = {
|
|
29
|
+
development: sharedConfig,
|
|
30
|
+
staging: sharedConfig,
|
|
31
|
+
production: sharedConfig,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default config;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { Knex } from "knex";
|
|
2
|
-
|
|
3
|
-
export async function up(knex: Knex): Promise<void> {
|
|
4
|
-
await knex.schema.createTable("sundays_package_version", (table) => {
|
|
5
|
-
table.increments("id").primary();
|
|
6
|
-
table.string("versionName").notNullable();
|
|
7
|
-
table.timestamps(true, true); // created_at, updated_at
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function down(knex: Knex): Promise<void> {
|
|
12
|
-
await knex.schema.dropTableIfExists("sundays_package_version");
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable("sundays_package_version", (table) => {
|
|
5
|
+
table.increments("id").primary();
|
|
6
|
+
table.string("versionName").notNullable();
|
|
7
|
+
table.timestamps(true, true); // created_at, updated_at
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function down(knex: Knex): Promise<void> {
|
|
12
|
+
await knex.schema.dropTableIfExists("sundays_package_version");
|
|
13
13
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Knex } from "knex";
|
|
2
|
-
|
|
3
|
-
export async function seed(knex: Knex): Promise<void> {
|
|
4
|
-
// Deletes ALL existing entries
|
|
5
|
-
await knex("sundays_package_version").del();
|
|
6
|
-
|
|
7
|
-
// Inserts seed entries
|
|
8
|
-
await knex("sundays_package_version").insert([
|
|
9
|
-
{ versionName: "1.0.0" }
|
|
10
|
-
]);
|
|
1
|
+
import { Knex } from "knex";
|
|
2
|
+
|
|
3
|
+
export async function seed(knex: Knex): Promise<void> {
|
|
4
|
+
// Deletes ALL existing entries
|
|
5
|
+
await knex("sundays_package_version").del();
|
|
6
|
+
|
|
7
|
+
// Inserts seed entries
|
|
8
|
+
await knex("sundays_package_version").insert([
|
|
9
|
+
{ versionName: "1.0.0" }
|
|
10
|
+
]);
|
|
11
11
|
}
|