Boilerplate for starting node.js and typescript servers already with yarn.
Current Node version targeted, v14+.
I really hate boilerplates that throw a lot of stuff that you need to learn in, I like boilerplates that just stay out of the way and organize only what's really a pain in the ass. I hope this to be it.
- fastify 🚀
- fastify-swagger 📚
- (NEW!) Auto-documentation generated from typescript types!
generateSchemasFromTS.ts🤯yarn gen:schema
npx degit pedropalhari/node-ts-fastify-boilerplate project_name
yarn start: runs the distributed copy ondist/index.jsyarn dev: starts the typescript compiler on watch mode (tsc -w)- in
tsconfig.jsonyou can set the properties onoutDirandrootDir
- in
yarn build: builds the code, incrementallyyarn gen:schema: generates JSON schema to be used for validation.
To use this boilerplate fully, there's only a few rules to abide by:
- Create a new file in
routes/.
// routes/Example.ts
import { FastifyApp } from "../types/common";
export function initExampleRoutes(app: FastifyApp, service: {}) {
app.post("/route", async (req, res) => {
return res.send({
echo: "not yet",
});
});
}- Add it to
index.tsto theRouterwith the prefix you want.
// index.ts
/**
* Route array with prefixes
*/
const Routes: Route[] = [
{
init: initExampleRoutes,
prefix: "/example",
},
];- Create a type in the
types/folder. The type must end inIRoute!- I'm using typescript-json-schema, that is a little bit heavy on generating JSON schemas.
// types/ExampleTypes.d.ts
export interface Example {
exampleParam: string;
}
export interface ExampleBodyIRoute {
example: Example;
arr: string[];
}-
Run
yarn gen:schema- For each
IRoutetype it will create a.jsonfile onschemas/ - It also compiles all schemas into
schemas/definitions.jsonso we can use any types from the project, not any from thetypes/folder. - And for the last part it adds a nice import map so you can do
{type}Schemaand autocomplete.
- For each
-
Add the type and generated schema to the route:
// routes/Example.ts
import { FastifyApp } from "../types/common";
import { ExampleBodyIRoute } from "../types/ExampleTypes"; // <-- Here!
import { ExampleBodySchema } from "../schemas/GeneratedSchemas";
export function initExampleRoutes(app: FastifyApp, {}: Services) {
app.post<{
Body: ExampleBodyIRoute; // <-- Here!
}>(
"/route",
{
schema: {
body: ExampleBodySchema, // <-- Here!
},
},
async (req, res) => {
let { example, arr } = req.body;
return res.send({
echo: { example, arr },
});
}
);
}// services/Mongo.ts
import { Collection, MongoClient } from "mongodb";
// Connection URL
const URL = "mongodb://localhost:27017";
// Database Name
const dbName = "myproject";
interface User {
username: string;
password: string;
}
interface Email {
recipient: string;
delay: number;
}
export interface DBCollections {
user: Collection<User>;
emails: Collection<Email>;
}
export async function initMongoDB(): Promise<DBCollections> {
// Create a new MongoClient
const client = new MongoClient(URL);
await client.connect();
const db = client.db(dbName);
return {
user: db.collection("user"),
emails: db.collection("email"),
};
}Then on types/common.d.ts, index.ts and the routes/*.ts
//types/common.d.ts
export interface Services {
db: DBCollections;
}
//index.ts
async function main() {
initDocumentation(app, API_VERSION);
let db = await initMongoDB(); // <-- Here!
//...
// Initialize all the routes in the array, passing the db for
// operations and the app for creating handlers
Routes.forEach((route) => {
app.register((app, opts, done) => {
route.init(app, { db }); // <-- Here!
//...
});
});
}
// routes/*.ts
export function initExampleRoutes(app: FastifyApp, { db }: Services) {
//...
let queryResult = await db.user.findOne({});
}Made by me, for me, so I can build services faster. Feel free to use, expand and contact me!