You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+29-18Lines changed: 29 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -73,7 +73,7 @@ We use [Pino](https://www.npmjs.com/package/pino) for effective and high perform
73
73
This boilerplate follows ideas from multiple good software development practices sources like [layered architecture](http://wiki.c2.com/?FourLayerArchitecture), [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html), [Domain-Driven Design](https://www.domainlanguage.com/ddd/), among others. As such, even though it's not required, there are some patterns that are recommended and suggested that work well with the principles that make the boilerplate scalable and extensible. To mention some:
74
74
75
75
- We recommend the usage of entities, aggregates and value objects, and other patterns that are used to isolate domain-specific code from the rest of the application code, as mentioned in Domain-Driven Design. To create a standard and practical way to define invariants for entities and aggregates there is a function that can be imported from the [lib](#lib-and-shared-kernel) called `withInvariants`. Click here to read a brief [reference about Domain-Driven Design](https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf).
76
-
- To abstract the persistence layer of your application we recommend the usage of the [repository pattern](https://martinfowler.com/eaaCatalog/repository.html).
76
+
- To abstract the persistence layer of your application we recommend the usage of the [repository pattern](https://martinfowler.com/eaaCatalog/repository.html). An important fact to take note is that even though the example app in the boilerplate used Mongo, you're not required to use it in your application, you just need to create a module to connect to the database of your preference and implement repositories that communicate with this database
77
77
- To favor a more predictable and explicit definition of domain rules we favor immutable objects and pure functions to define business rules rather than classes. You'll see that most of the code does not expose classes to be used.
78
78
- To export and import domain-specific code we use [TypeScript namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html). We believe it helps in making the code that is imported from the domain easier to read since it will always be prefixed by the name of the context it concerns about, loosely inspired by [Elixir modules](https://elixir-lang.org/getting-started/modules-and-functions.html). We follow the pattern of adding a named export called Type to expose the entity/aggregate/value object from that given file.
79
79
@@ -114,31 +114,42 @@ Both the boot and stopping processes are defined as a sequence of lifecycle even
114
114
Boot:
115
115
116
116
1. Booting:
117
-
- The booting event is dispatched once the function bootstrap is called in `src/_boot/index.ts`
118
-
- The modules are invoked during this lifecycle step, so by the time each module is invoked this lifecycle event was already dispatched
119
-
- It's not possible for a module to hook into this event because it's run by the context to declare that the boot process is started
120
-
- Mostly for internal usage to prepare the rest of the boot process
117
+
118
+
- The booting event is dispatched once the function bootstrap is called in `src/_boot/index.ts`
119
+
- The modules are invoked during this lifecycle step, so by the time each module is invoked this lifecycle event was already dispatched
120
+
- It's not possible for a module to hook into this event because it's run by the context to declare that the boot process is started
121
+
- Mostly for internal usage to prepare the rest of the boot process
122
+
121
123
2. Booted:
122
-
- When this event is dispatched it's a message to let the modules know that all the modules were already invoked and had already hooked into the other lifecycle events
123
-
- This is a good place to register error handlers because every module has already registered its routes when they were invoked
124
-
- Use this event to do anything you might need after all the module constructors are done running
124
+
125
+
- When this event is dispatched it's a message to let the modules know that all the modules were already invoked and had already hooked into the other lifecycle events
126
+
- This is a good place to register error handlers because every module has already registered its routes when they were invoked
127
+
- Use this event to do anything you might need after all the module constructors are done running
128
+
125
129
3. Ready:
126
-
- This lifecycle event happens after all the listeners for the booted event were run
127
-
- This is the proper place to actually start things, like starting the server, make queue consumers start listening to messages, or waiting for commands in case the app is running in REPL mode
130
+
131
+
- This lifecycle event happens after all the listeners for the booted event were run
132
+
- This is the proper place to actually start things, like starting the server, make queue consumers start listening to messages, or waiting for commands in case the app is running in REPL mode
133
+
128
134
4. Running:
129
-
- After everything from the ready event is done, the app is now actually running
130
-
- A good usage for this lifecycle event is to know if the app is already prepared to be accessed during the setup of an automated test or offer info about the process in the console
135
+
136
+
- After everything from the ready event is done, the app is now actually running
137
+
- A good usage for this lifecycle event is to know if the app is already prepared to be accessed during the setup of an automated test or offer info about the process in the console
131
138
132
139
Stopping
133
140
134
141
1. Disposing
135
-
- It's during this lifecycle event that the cleanup functions returned by the modules will be run
136
-
- To make the cleanup process consistent, the cleanup functions are run in the inverse order their modules were passed to the bootstrap function. So if your app uses `bootstrap(database, server)`, during the disposing process the cleanup function of the server module will be called first and then the database one.
137
-
- As an example, this is where the server is stopped and the database connections are closed
138
-
- It's intended to be used to revert everything initialized during Booting lifecycle event
142
+
143
+
- It's during this lifecycle event that the cleanup functions returned by the modules will be run
144
+
- To make the cleanup process consistent, the cleanup functions are run in the inverse order their modules were passed to the bootstrap function. So if your app uses `bootstrap(database, server)`, during the disposing process the cleanup function of the server module will be called first and then the database one.
145
+
- As an example, this is where the server is stopped and the database connections are closed
146
+
- It's intended to be used to revert everything initialized during Booting lifecycle event
147
+
139
148
2. Disposed
140
-
- By the time Disposed event is dispatched, we expect that everything that keeps the process open is already finished, leaving it in a safe state to be terminated
141
-
- You could use this event to clean temporary files, for instance
149
+
150
+
- By the time Disposed event is dispatched, we expect that everything that keeps the process open is already finished, leaving it in a safe state to be terminated
151
+
- You could use this event to clean temporary files, for instance
152
+
142
153
3. The application should now be completely stopped and the process is terminated
143
154
144
155
To be able to hook into lifecycle events, access the property `app` in the object passed to the constructor of the modules. The `app` object contains a function for each lifecycle, prefixing it with the word `on`. So, for example, to hook into the Booted event, call `app.onBooted(callback)`.
0 commit comments