{"id":39155734,"url":"https://github.com/junekimdev/boilerplate-node-api","last_synced_at":"2026-01-17T21:57:48.528Z","repository":{"id":60686959,"uuid":"476208170","full_name":"junekimdev/boilerplate-node-api","owner":"junekimdev","description":"Boilerplate codes to build Restful API in NodeJS","archived":false,"fork":false,"pushed_at":"2025-02-04T09:05:39.000Z","size":809,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-04T10:19:36.119Z","etag":null,"topics":["expressjs","jwt","nodejs","postgres","push-notifications","restful-api","typescript","vapid"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/junekimdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-31T08:00:02.000Z","updated_at":"2025-02-04T09:04:31.000Z","dependencies_parsed_at":"2024-07-05T14:34:17.037Z","dependency_job_id":"61ed14c4-9685-4a7d-b6dc-b2917d773e07","html_url":"https://github.com/junekimdev/boilerplate-node-api","commit_stats":null,"previous_names":[],"tags_count":23,"template":true,"template_full_name":null,"purl":"pkg:github/junekimdev/boilerplate-node-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junekimdev%2Fboilerplate-node-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junekimdev%2Fboilerplate-node-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junekimdev%2Fboilerplate-node-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junekimdev%2Fboilerplate-node-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/junekimdev","download_url":"https://codeload.github.com/junekimdev/boilerplate-node-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junekimdev%2Fboilerplate-node-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28519182,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:55:29.170Z","status":"ssl_error","status_checked_at":"2026-01-17T18:55:03.375Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expressjs","jwt","nodejs","postgres","push-notifications","restful-api","typescript","vapid"],"created_at":"2026-01-17T21:57:44.853Z","updated_at":"2026-01-17T21:57:48.499Z","avatar_url":"https://github.com/junekimdev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Boilerplate-node-api\n\nBoilerplate codes to build Restful API in NodeJS\n\n[![CI](https://github.com/junekimdev/boilerplate-node-api/actions/workflows/CI.yml/badge.svg)](https://github.com/junekimdev/boilerplate-node-api/actions/workflows/CI.yml)\n[![codecov](https://codecov.io/gh/junekimdev/boilerplate-node-api/branch/master/graph/badge.svg?token=7HUOYC9KF4)](https://codecov.io/gh/junekimdev/boilerplate-node-api)\n![GitHub tag (latest SemVer pre-release)](https://img.shields.io/github/v/tag/junekimdev/boilerplate-node-api)\n![GitHub](https://img.shields.io/github/license/junekimdev/boilerplate-node-api)\n\n---\n\n## Table of Contents\n\n1. [Getting Started](#getting-started)\n1. [Tech Stack](#tech-stack)\n1. [Packages Used](#packages-used)\n1. [S/W Architecture](#sw-architecture)\n1. [Examples](#examples)\n1. [Code Generation](#code-generation)\n1. [What's Next?](#whats-next)\n1. [Authors](#authors)\n1. [License](#license)\n\n---\n\n## Getting Started\n\n### Prerequisite\n\nInstall latest Node.js LTS\n\u003chttps://nodejs.org/en/download/package-manager/\u003e\n\n- Debian\n\n```shell\nsudo apt update\nsudo apt install nodejs\nnodejs -v\n```\n\n- Windows\n\n```shell\nchoco install nodejs-lts\nnode --version\n```\n\nInstall PostgreSQL DB\n\n- Debian\n\n```shell\nsudo apt install postgresql\n```\n\n- Windows\n\n```shell\nchoco install postgresql\n```\n\n### Installation\n\n#### Clone the repo and install dependencies\n\n```shell\n# git clone will create a directory named myAppName\n# if the directory is already created, then use .(dot) instead of myAppName\ngit clone https://github.com/junekimdev/boilerplate-node-api.git \u003cmyAppName\u003e\ncd myAppName\nyarn\n```\n\n#### Make sure to remove `.git` directory to start afresh\n\n```shell\n# remove .git directory beforehand\ngit init\ngit add .\ngit commit -m \"Initial commit\"\ngit branch -M master\ngit remote add origin \u003cmyGitRepo\u003e\ngit push -u origin master\n```\n\n#### Add a file `.env` that includes environmental variables\n\nExample:\n\n```conf\n#NODE_ENV=production\nSERVICE_NAME=myservice\nPORT=3000\nCORS_ORIGIN=http://localhost:3000\n#TRUST_PROXY=172.17.0.0/16\n\n# DB\nPGHOST=localhost\nPGUSER=myservice\nPGDATABASE=myservicedb\nPGPASSWORD=securepassword\nPGPORT=5432\nDB_POOL_MAX=20\nDB_IDLE_TIMEOUT=30000\nDB_CONN_TIMEOUT=2000\n\n# Upload directory from the project root\nUPLOAD_ROOT=/data/upload\nPUBLIC_PROFILE_DIR=/images/profiles # within public directory\n\n# JWT\nJWT_PRI_FILENAME=es256_prv.pem\nJWT_PUB_FILENAME=es256_pub.pem\nJWT_ISS=jrn;;;auth;https://mycompany.com/auth\n\n#VAPID\nVAPID_SUBJECT=mailto:user@mycompany.com # this should be url or mailto\n#VAPID_PUB_KEY=\n#VAPID_PRI_KEY=\n```\n\n#### Initiate your PostgreSQL DB\n\nModify `init.sql` file to your liking except some SQLs between `REQUIRED`\n\n```shell\npsql -f init.sql\n```\n\n## Tech Stack\n\n- Backend language: Typescript(Javascript)\n- API documentation standard: openapi 3.0.3\n- Database: PostgreSQL\n- Access control: Basic Authorization \u0026 Bearer Authorization ([RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235))\n- Basic authorization scheme: email(which is username) and password as in [RFC 7617](https://datatracker.ietf.org/doc/html/rfc7617)\n- Bearer authorization scheme: JWT as in [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750)\n- Token signing algorithm: ES256, which is ECDSA using P-256 and SHA256\n- Public \u0026 private key format: PEM\n- Password hash algorithm and encoding: SHA256 with Base64 encoding\n- WebAPIs: Push API\n\n## Packages Used\n\n- JS engine: node.js\n- API engine: express.js\n- Body-parse middleware: express.js built-ins\n- multipart/form-data parser: busboy\n- header middleware: helmet.js\n- CORS middleware: cors\n- Logging middleware: pino.js\n- DBMS (for PostgreSQL): pg\n- Environmental variable loader: dotenv\n- Access-token (for JWT): jsonwebtoken\n- Push-notification: web-push\n- Unit Test: jest\n- Integration Test: jest \u0026 supertest\n\n## S/W Architecture\n\n### Directory Structure\n\n```text\nroot/\n├── package.json\n├── .env\n├── project_files\n├── public/\n│   └── static_files\n├── doc/\n|   ├── openapi.yaml\n│   └── document_files\n├── keys/\n│   └── key_files\n├── src/\n│   ├── server.ts\n│   ├── errorHandler.ts\n│   ├── api/\n│   │   ├── index.ts\n│   │   └── v1.ts\n│   ├── middleware/\n│   │   ├── basicAuth.ts\n│   │   ├── bearerAuth.ts\n│   │   ├── data_validator_files\n│   │   └── access_control_files\n│   ├── services/\n│   │   └── eachService/\n│   │       ├── index.ts\n│   │       ├── apiHandler.ts\n│   │       ├── provider.ts\n│   │       └── types.ts\n│   └── utils/\n│       ├── errors.ts\n│       └── utility_files\n└── test/\n    ├── test.config\n    ├── initTest.ts\n    ├── testData.sql\n    ├── unit/\n    │   ├── eachService/\n    │   │   ├── handler.test.ts\n    │   │   └── provider.test.ts\n    │   └── unit_test_files\n    ├── integration/\n    │   └── integration_test_files\n    └── coverage/\n        └── test_coverage_report_files\n```\n\n### Explanation of the Architecture\n\n1. `/public` serves static files\n1. `/doc` serves documents for the project\n1. `/doc/openapi.yaml`is API document according to OpenAPI 3.x Spec\n1. `/src` serves source codes of the API server\n1. `/src/server.ts` is the entry file for the server\n   - This sets up all middlewares\n   - This has the central error handler\n1. `/src/api/index.ts` selects API version and provides root router\n1. `/src/api/v1.ts` provides routing logic in the said version\n   - This connects API paths to services\n1. `/src/middleware/basicAuth.ts`is the basic authorization middleware\n   - This sets `userId` and `email` in `req.locals`\n1. `/src/middleware/bearerAuth.ts`is the bearer authorization middleware\n   - This sets decoded `accessToken` in `req.locals`\n1. `/services` holds services, which processes business logic\n1. `/services/eachService` should have descriptive names that clearly says what it does\n   - Recommended format: `verb + noun`\n   - CRUD verbs are great\n1. `/services/eachService/index.ts` decouples inside from outside\n1. `/services/eachService/apiHandler.ts` handles requests\n   - This MUST do:\n     - extracts data out of request `body`/`param`/`query`\n     - extracts data out of request `locals` passed by middleware\n     - validates data\n     - calls provider to process the data\n     - decides which HTTP status will send (REST API)\n     - decides which error to throw\n     - try-catch all internal errors and pass them to the central error handler\n1. `/services/eachService/provider.ts` provides the core of service by processing business logic\n   - This MAY do:\n     - interacts with DB or network to process data\n     - executes another file to process data such as python files, golang files, etc.\n1. `/services/eachService/types.ts` provides definitions of type that need for the service\n   - This MAY have: `IReqBody`,`IReqParam`,`IReqQuery`,`IReqLocals`,`IResBody`, etc.\n1. `/src/utils` holds utility files that are used across the project\n1. `/src/utils/errors.ts` defines:\n   - `class AppError` that extends `Error` class\n   - `errDef` object that holds pre-defined error descriptions ordered by status number\n   - `code` property in `errDef` object\n     - is Error-Identification-Code that you maintain within your organization\n     - can be used for analytics and for informing client\n\n## Examples\n\n### Database\n\n- [Database ER Diagram](./doc/database_ER_diagrams.md)\n- [Beginning SQLs](./init.sql)\n\n### User Types\n\n- [User Description](./doc/example_user_description.md)\n\n### Resource Name Schema\n\n- [JuneKim Resource Name Schema](./doc/JuneKim%20Resource%20Name%20Schema.md)\n\n## Code Generation\n\n### Adding a New Service\n\n```shell\nnode codegen.js -name=servicename\n```\n\nThis will create files according to the architecture explained above\n\n### Adding a New Public/Private Key Pair\n\n```shell\nnode keygen-es256.js -name=keyname\n```\n\nThis will create a ES256 key pair to be used\n\n### Generating a New VAPID key Pair\n\n```shell\n# Required web-push installed\nnode keygen-vapid.js\n```\n\nThis will append a VAPID key pair in `.env` file\n\n## What's Next?\n\n- Add **Redis** as a cache layer to implement cache-first fetching strategy\n- Add **node-cron** as a scheduler to execute timed tasks\n\n## Authors\n\n- **June Kim** - _Initial work_ - [Github](https://github.com/junekimdev)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunekimdev%2Fboilerplate-node-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjunekimdev%2Fboilerplate-node-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunekimdev%2Fboilerplate-node-api/lists"}