Author: César Casas LinkedIn: César Casas Website: s42core.com
s42-core
is a powerful and flexible Node.js library designed to streamline the development of applications, particularly those utilizing microservices and cell-based architectures. The library simplifies the creation of monorepos and supports the development of small, reusable software components (atoms).
s42-core
is built with microservices and cell-based architectures in mind, allowing you to create highly modular and scalable applications. Each microservice or cell can operate independently, facilitating easier maintenance and updates.
The classes provided by s42-core
can be used independently and are agnostic to any specific framework. This means you can seamlessly integrate them with Express, Nest.js, Fastify, and other frameworks of your choice.
Applications developed with s42-core
benefit from exceptional performance, making it suitable for high-demand environments.
Creating and managing a monorepo with s42-core
is straightforward and efficient. The library encourages the creation of small, modular components that can be easily shared and reused across your projects.
s42-core
simplifies the setup and management of monorepos, promoting code reuse and modular development. You can easily share common components and services across multiple projects within a single repository.
With s42-core
, you can quickly develop microservices that are easy to deploy and maintain. The library provides essential utilities for handling HTTP requests, managing dependencies, and interacting with databases.
The library supports the creation of small, reusable software components, or atoms, which can be combined to build more complex functionality. This approach enhances code maintainability and scalability.
For detailed information on each class and module provided by s42-core
, refer to the following documentation files:
- CLUSTER.md
- CONTROLLER.md
- DEPENDENCIES.md
- EVENTSDOMAIN.md
- JSONPARSE.md
- MONGODB.md
- REDISDB.md
- ROUTECONTROLLERS.md
- SHUTDOWN.md
- TEST.md
By leveraging s42-core
, you can rapidly develop high-performance applications with a clean and modular architecture, integrating seamlessly with your existing frameworks and tools.
Installing s42-core
is simple. You can add it to your project using your preferred package manager.
npm install s42-core
Here's a simple example of how to implement a microservice using s42-core:
import { createServer } from 'node:http'
import { Shutdown, Cluster, EventsDomain, Dependencies, RedisClient } from 's42-core'
import { listenEventsDomain } from './eventsDomain/Listeners'
import { Router } from './routers.js'
Cluster(
2,
async (pid, uuid) => {
console.info('initializing: ', pid, uuid)
const redisInstance = RedisClient.getInstance(process.env.REDIS_URI)
const eventsDomain = EventsDomain.getInstance(redisInstance, uuid)
Dependencies.add<EventsDomain>('eventsDomain', eventsDomain)
Dependencies.add<RedisClient>('redisInstance', redisInstance)
listenEventsDomain(eventsDomain)
const server = createServer(Router)
server.listen(process.env.PORT, () =>
console.info(`ready on *:${process.env.PORT} : PID: ${pid}`),
)
Shutdown([eventsDomain.close, redisInstance.close])
},
() => {
console.info('Error trying start servers')
},
)
eventsDomain/Listeners
import { type EventsDomain } from 's42-core'
type UsersCreated = {
email: string
firstName: string
lastName: string
lang: 'en' | 'es' | 'it' | 'fr'
template: string
}
export function listenEventsDomain(eventsDomain: EventsDomain) {
eventsDomain.listenEvent<UsersCreated>(
'users.created',
async (payload: UsersCreated) => {
try {
console.info('Email sent successfully:', payload)
} catch (error) {
console.error('Error sending email:', error)
}
},
)
}
import { Dependencies, type MongoClient, type EventsDomain, Controller } from 's42-core'
import { z } from 'zod'
const TypeUser = z.object({
firstName: z.string(),
lastName: z.string(),
email: z.string().email(),
})
export const userController = new Controller()
.setPath('/users/create')
.post()
.use(async (req, res, next) => {
console.info('This is a mws: ', req.query)
next()
})
.use(async (req, res) => {
const db = Dependencies.get<MongoClient>('db') as MongoClient
const eventsDomain = Dependencies.get<EventsDomain>('eventsDomain') as EventsDomain
try {
const data = req.body
TypeUser.parse(data)
await db.getCollection('users').insertOne({
...data,
remoteIp: req.realIp,
added: new Date(),
headers: req.headers,
})
eventsDomain.emitEvent('users.created', { ...data })
res.json({ ok: true })
} catch (error) {
res.jsonError({ ok: false, msg: error })
}
})
import { createServer } from 'node:http'
import {
Shutdown,
Cluster,
Dependencies,
MongoClient,
RedisClient,
EventsDomain,
RouteControllers,
} from 's42-core'
import { userController, healthController } from './controllers'
const port = process.env.PORT ?? 3000
Cluster(
1,
async (pid, uuid) => {
console.info('initializing: ', pid, uuid)
const mongoClient = MongoClient.getInstance({
connectionString: String(process.env?.MONGO_URI),
database: String(process.env?.MONGO_DB),
})
await mongoClient.connect()
const redisClient = RedisClient.getInstance('localhost')
const eventsDomain = EventsDomain.getInstance(redisClient, uuid)
Dependencies.add<MongoClient>('db', mongoClient)
Dependencies.add<RedisClient>('redis', redisClient)
Dependencies.add<EventsDomain>('eventsDomain', eventsDomain)
const routerControllers = RouteControllers.getInstance([
userController,
healthController,
])
const server = createServer(routerControllers.getCallback())
server.listen(port, () => {
console.info(`ready on *:${port}`)
})
Shutdown([mongoClient.close, redisClient.close, eventsDomain.close])
},
() => {
console.info('Error trying start servers')
},
)
s42-core is designed to work seamlessly within a monorepo. Here's a basic structure for a monorepo that includes multiple microservices:
monorepo/
│
├── microservices/
│ ├── service1/
│ │ ├── package.json
│ │ └── src/
│ ├── service2/
│ │ ├── package.json
│ │ └── src/
│ └── service3/
│ ├── package.json
│ └── src/
│
├── package.json
├── tsconfig.json
└── README.md
For more detailed documentation, please refer to the individual markdown files listed above.
2024 César Casas - LinkedIn