deploy-bbc 1.3.0 → 1.3.2

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 CHANGED
@@ -198,24 +198,38 @@ During setup, you'll be asked:
198
198
 
199
199
  ### Usage
200
200
 
201
- If you selected to dockerize your databases:
201
+ When you enable Docker during setup, a convenient `docker:dev` script is automatically added to your `package.json`.
202
+
203
+ #### Quick Start
202
204
 
203
205
  ```bash
204
- # Start only databases
206
+ # Start all Docker services (databases and/or backend)
207
+ bun run docker:dev
208
+ ```
209
+
210
+ This script runs `docker-compose up`, starting all services defined in your `docker-compose.yml`.
211
+
212
+ #### Manual Control
213
+
214
+ You can also use docker-compose directly for more control:
215
+
216
+ ```bash
217
+ # Start only specific services (e.g., databases only)
205
218
  docker-compose up postgres redis -d
206
219
 
207
220
  # Run your app locally
208
221
  bun run dev
209
222
  ```
210
223
 
211
- If you dockerized both databases and backend:
212
-
213
224
  ```bash
214
- # Start everything
215
- docker-compose up
216
-
217
- # Or in detached mode
225
+ # Start everything in detached mode
218
226
  docker-compose up -d
227
+
228
+ # View logs
229
+ docker-compose logs -f
230
+
231
+ # Stop services
232
+ docker-compose down
219
233
  ```
220
234
 
221
235
  ### SQLite with Docker
package/dist/index.js CHANGED
@@ -16800,7 +16800,7 @@ async function init_git(projectDir) {
16800
16800
  }
16801
16801
 
16802
16802
  // src/helpers/log-next-steps.ts
16803
- function log_next_steps(options, _cliResults) {
16803
+ function log_next_steps(options, cliResults) {
16804
16804
  const { appName, packages, projectDir } = options;
16805
16805
  const isCurrentDirectory = projectDir === process.cwd();
16806
16806
  console.log(`
@@ -16820,10 +16820,10 @@ function log_next_steps(options, _cliResults) {
16820
16820
  console.log(` ${source_default.gray("# Edit .env with your configuration")}`);
16821
16821
  console.log();
16822
16822
  stepNumber++;
16823
- const hasDocker = packages.includes("postgres" /* postgres */) || packages.includes("mysql" /* mysql */) || packages.includes("mongodb" /* mongodb */) || packages.includes("redis" /* redis */);
16823
+ const hasDocker = cliResults.flags.dockerizeDb || cliResults.flags.dockerizeBackend;
16824
16824
  if (hasDocker) {
16825
16825
  console.log(source_default.cyan(`${stepNumber}.`) + " Start Docker services:");
16826
- console.log(` ${source_default.gray("docker-compose up -d")}`);
16826
+ console.log(` ${source_default.gray("bun run docker:dev")}`);
16827
16827
  console.log();
16828
16828
  stepNumber++;
16829
16829
  }
@@ -16851,6 +16851,22 @@ function render_title(title) {
16851
16851
  ` + source_default.bold.cyan(`▸ ${title}`));
16852
16852
  }
16853
16853
 
16854
+ // src/utils/add-package-scripts.ts
16855
+ var import_fs_extra18 = __toESM(require_lib(), 1);
16856
+ import path24 from "path";
16857
+ async function add_package_scripts(projectDir, scripts) {
16858
+ const packageJsonPath = path24.join(projectDir, "package.json");
16859
+ const packageJson = await import_fs_extra18.default.readJson(packageJsonPath);
16860
+ if (!packageJson.scripts) {
16861
+ packageJson.scripts = {};
16862
+ }
16863
+ packageJson.scripts = {
16864
+ ...packageJson.scripts,
16865
+ ...scripts
16866
+ };
16867
+ await import_fs_extra18.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
16868
+ }
16869
+
16854
16870
  // src/helpers/create-project.ts
16855
16871
  async function create_project(cliResults) {
16856
16872
  try {
@@ -16877,6 +16893,9 @@ async function create_project(cliResults) {
16877
16893
  }
16878
16894
  if (cliResults.flags.dockerizeDb || cliResults.flags.dockerizeBackend) {
16879
16895
  await generate_docker_compose(installerOptions);
16896
+ await add_package_scripts(projectDir, {
16897
+ "docker:dev": "docker-compose up"
16898
+ });
16880
16899
  }
16881
16900
  }
16882
16901
  if (!cliResults.flags.noInstall) {
@@ -1,8 +1,9 @@
1
1
  import express from "express";
2
2
  import { logger as loggerMiddleware } from "./middleware/logger.js";
3
- import { errorHandler } from "./middleware/error.js";
3
+ import {error_handler} from "./middleware/error-handler.js";
4
4
  import routes from "./routes/index.js";
5
5
  import { config } from "./config/index.js";
6
+ import { success_handler } from "./middleware/succcess-handler.js";
6
7
 
7
8
  const app = express();
8
9
 
@@ -10,6 +11,7 @@ const app = express();
10
11
  app.use(express.json());
11
12
  app.use(express.urlencoded({ extended: true }));
12
13
  app.use(loggerMiddleware);
14
+ app.use(success_handler)
13
15
 
14
16
  // Routes
15
17
  app.use("/", routes);
@@ -20,7 +22,7 @@ app.get("/health", (req, res) => {
20
22
  });
21
23
 
22
24
  // Error handler (must be last)
23
- app.use(errorHandler);
25
+ app.use(error_handler);
24
26
 
25
27
  app.listen(config.port, () => {
26
28
  console.log(`🚀 Server running on http://localhost:${config.port}`);
@@ -0,0 +1,42 @@
1
+ import type { Request, Response, NextFunction } from "express";
2
+ import CustomError from "../utils/CustomError";
3
+
4
+ type TSendErrorAsResponse = {
5
+ error: Error | CustomError;
6
+ req: Request;
7
+ res: Response;
8
+ }
9
+
10
+ type TErrorResponse = {
11
+ message: string;
12
+ status_code: number;
13
+ stack?: string;
14
+ }
15
+
16
+ export const error_handler = (
17
+ err: Error | CustomError,
18
+ req: Request,
19
+ res: Response,
20
+ _next: NextFunction
21
+ ) => {
22
+
23
+ console.error(`Error: ${err.message}`, err);
24
+ //TODO: Update error handler based on type of database and type of validator
25
+ send_error_as_response({error:err,req,res})
26
+ };
27
+
28
+
29
+
30
+
31
+ const send_error_as_response =(
32
+ {error,req,res}: TSendErrorAsResponse
33
+ ) => {
34
+ //TODO: update send_error_as_response based on type of logger
35
+ const error_response: TErrorResponse = {
36
+ message: error.message,
37
+ status_code: error instanceof CustomError ? error.status_code : 500,
38
+ stack: error instanceof Error ? error.stack : undefined,
39
+ };
40
+
41
+ res.status(error_response.status_code).json(error_response);
42
+ };
@@ -0,0 +1,20 @@
1
+ import { NextFunction, Request, Response} from 'express'
2
+
3
+ type TSuccessHandler= {
4
+ req: Request,
5
+ res: Response,
6
+ next: NextFunction
7
+ }
8
+
9
+ export const success_handler = (
10
+ {req, res, next} : TSuccessHandler)=>{
11
+
12
+ const original_json = res.json
13
+
14
+ res.json = function (json: any): Response {
15
+ //TODO: logic to have logger and other success resposne parsing
16
+ return original_json.call(this,json)
17
+ }
18
+
19
+ next();
20
+ }
@@ -2,29 +2,24 @@
2
2
  * Common API response types
3
3
  */
4
4
 
5
- export interface ApiResponse<T = unknown> {
6
- success: boolean;
7
- data?: T;
8
- error?: string;
9
- message?: string;
10
- }
11
5
 
12
- export interface PaginatedResponse<T> extends ApiResponse<T[]> {
13
- pagination: {
14
- page: number;
15
- limit: number;
16
- total: number;
17
- totalPages: number;
18
- };
6
+ export type TApiSuccess<T =unknown> = {
7
+ data?: T;
8
+ message: string;
9
+ pagination?: TPaginationResponse
19
10
  }
20
11
 
21
- export interface ValidationError {
22
- field: string;
12
+ export type TApiError = {
13
+ status_code: number;
23
14
  message: string;
24
15
  }
25
16
 
26
- export interface ApiError {
27
- success: false;
28
- error: string;
29
- details?: ValidationError[];
17
+ export type TApiResponse<T = unknown> = TApiSuccess<T> | TApiError
18
+
19
+ export type TPaginationResponse = {
20
+ page: number;
21
+ limit: number;
22
+ total_pages: number;
23
+ total_count: number;
30
24
  }
25
+
@@ -0,0 +1,5 @@
1
+ export type TDocument<Tid = string> = {
2
+ _id: Tid
3
+ createdAt: Date
4
+ updatedAt: Date
5
+ }
@@ -2,25 +2,17 @@
2
2
  * User model types
3
3
  */
4
4
 
5
- export interface User {
6
- id: string;
7
- email: string;
8
- name: string;
9
- createdAt: Date;
10
- updatedAt: Date;
11
- }
5
+ import { TDocument } from "../common/mongodb.types";
6
+
12
7
 
13
- export interface CreateUserInput {
8
+
9
+ export type TUser<Tid= string> = TDocument<Tid> & {
14
10
  email: string;
15
11
  name: string;
16
12
  }
17
13
 
18
- export interface UpdateUserInput {
19
- email?: string;
20
- name?: string;
21
- }
14
+ export type TCreateUserInput = Pick<TUser, 'email' | 'name'>
15
+
16
+ export type TUpdateUserInput = Partial<Pick<TUser, 'email' | 'name'>>
22
17
 
23
- export type UserResponse = Omit<User, "createdAt" | "updatedAt"> & {
24
- createdAt: string;
25
- updatedAt: string;
26
- };
18
+ export type TUserResponse = Omit<TUser, "createdAt" | "updatedAt"> & Pick<TDocument, 'createdAt' | 'updatedAt'>
@@ -0,0 +1,17 @@
1
+ class CustomError extends Error {
2
+ status_code: number;
3
+
4
+ constructor(
5
+ message: string = 'Internal Server Error',
6
+ status_code: number = 500
7
+ ){
8
+ super(message);
9
+ this.status_code = status_code;
10
+
11
+ Object.setPrototypeOf(this, CustomError.prototype);
12
+
13
+ Error.captureStackTrace(this, this.constructor);
14
+ }
15
+ }
16
+
17
+ export default CustomError;
@@ -1,5 +1,12 @@
1
- import { config as dotenvConfig } from "dotenv";
1
+ import dotenv from 'dotenv'
2
+ import path from 'path'
2
3
 
3
- export function load_env(): void {
4
- dotenvConfig();
4
+ dotenv.config({path: path.resolve(__dirname, '../../.env')})
5
+
6
+ export type TEnv = {
7
+ port: number
5
8
  }
9
+
10
+ export const env: TEnv = {
11
+ port: parseInt(process.env.PORT || '8000');
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deploy-bbc",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "CLI to bootstrap production-ready backends with Bun (Best Backend Code)",
5
5
  "type": "module",
6
6
  "bin": {