MangoJS Quick Start Tutorial
Goal: Set up a MangoJS application with a single endpoint in 10 minutes
Prerequisites​
npm install @theunionsquare/mangojs-core
npm install inversify reflect-metadata typeorm express dotenv
npm install -D typescript @types/node @types/express
Step 1: Create Entity​
File: src/db/models/Post.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
} from "typeorm";
@Entity("posts")
export class Post {
@PrimaryGeneratedColumn("uuid")
uid: string;
@Column({ type: "varchar", length: 255 })
title: string;
@Column({ type: "text" })
content: string;
@CreateDateColumn()
created_at: Date;
}
File: src/db/models/index.ts
export { Post } from "./Post";
Step 2: Create Service​
File: src/services/post.service.ts
import { injectable, inject, LazyServiceIdentifier } from "inversify";
import { EntityManager } from "typeorm";
import { INVERSITY_TYPES, Persistence } from "@theunionsquare/mangojs-core";
import { Post } from "../db/models";
@injectable()
export class PostService {
@inject(new LazyServiceIdentifier(() => INVERSITY_TYPES.PersistenceContext))
private _persistenceContext: Persistence.IPersistenceContext;
public async getAllPosts(): Promise<Post[]> {
return await this._persistenceContext.inTransaction(
async (em: EntityManager) => {
return await em.find(Post, { order: { created_at: "DESC" } });
},
);
}
}
File: src/services/index.ts
export { PostService } from "./post.service";
Step 3: Create Controller​
File: src/routes/v1/posts/posts.controller.ts
import {
Controller,
Get,
Errors,
Utils,
Container,
} from "@theunionsquare/mangojs-core";
import { Request, Response } from "express";
import { PostService } from "../../../services";
@Controller("/api/v1/posts")
export class PostController {
@Get("/")
public async getPosts(req: Request, res: Response): Promise<Response> {
const logRequest = new Utils.LogRequest(res);
try {
const postService = Container.ContainerRegistry.getDefault().get<PostService>(PostService);
const posts = await postService.getAllPosts();
return res.status(200).send({
ok: true,
timestamp: logRequest.timestamp,
requestId: logRequest.requestId,
data: posts,
});
} catch (error: unknown) {
return Errors.errorHandler(res, error as Error);
}
}
}
File: src/routes/v1/index.ts
import { PostController } from "./posts/posts.controller";
export const routes = [PostController];
File: src/routes/index.ts
export { routes } from "./v1";
Step 4: Configure Container​
File: src/inversify.config.ts
import { Container } from "@theunionsquare/mangojs-core";
import { Post } from "./db/models";
import { PostService } from "./services";
import dotenv from "dotenv";
dotenv.config();
// Build and register the default container
Container.ContainerBuilder.create()
// Core: Logger
.withCore({ loggerName: "blog-api", logLevel: "debug" })
// Database: PostgreSQL with entities
.withPostgres({
connection: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || "5432"),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
},
entities: [Post],
})
// App services
.bind(PostService).toSelf()
.build();
Key points:
ContainerBuilder.create()creates and registers a default container.withCore()binds the logger factory.withPostgres()binds database manager and persistence context.bind(Service).toSelf()registers your application services.build()finalizes and registers the container inContainerRegistry
Step 5: Create Entry Point​
File: src/index.ts
import "reflect-metadata";
import "./inversify.config"; // Initialize container first
import { ServerBuilder, Container } from "@theunionsquare/mangojs-core";
import { routes } from "./routes";
async function bootstrap() {
const server = new ServerBuilder()
.setContainer(Container.ContainerRegistry.getDefault())
.setPort(3000)
.registerControllers(routes)
.build();
await server.start();
console.log("Server running on http://localhost:3000");
}
bootstrap();
Step 6: Test​
# Start server
npm run dev
# Test endpoint
curl http://localhost:3000/api/v1/posts
Project Structure​
src/
├── db/models/
│ ├── Post.ts
│ └── index.ts
├── services/
│ ├── post.service.ts
│ └── index.ts
├── routes/
│ ├── v1/
│ │ ├── posts/
│ │ │ └── posts.controller.ts
│ │ └── index.ts
│ └── index.ts
├── inversify.config.ts
└── index.ts
Next Steps​
- Database Layer - Add relationships, migrations
- Service Layer - Transactions, error handling
- Controller Layer - More endpoints, authorization
- Dependency Injection - Advanced container patterns
- Decorators - Auth, middleware decorators