https://github.com/qntfrd/applife
♻️ Handle the lifecyle of your application
https://github.com/qntfrd/applife
Last synced: about 2 months ago
JSON representation
♻️ Handle the lifecyle of your application
- Host: GitHub
- URL: https://github.com/qntfrd/applife
- Owner: qntfrd
- License: mit
- Created: 2021-10-16T14:51:50.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-10-29T17:55:19.000Z (7 months ago)
- Last Synced: 2024-10-29T19:12:25.665Z (7 months ago)
- Language: TypeScript
- Homepage:
- Size: 92.8 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 14
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# AppLife
♻️ Handle the lifecyle of your application
[](https://codecov.io/gh/qntfrd/applife)
## Getting started
```ts
import AL from "applife"const app = new AL({
// first load your environment
config: { up: loadenv },// when config is done, open pg connection
pg: {
needs: ["config"], // wait for config to have run
up: async ({ config }) => { // each steps receive the full context
const client = new Client();
await client.connect();
return client
},
down: ({ pg }) => pg.close(), // here pg is what was instanciated in `up`
after: "start" // will only close pg AFTER the up stage has been downed
},http: {
needs: ["config"],
up: ({ config }) => new Koa().use(/* ... */),
},socket: {
needs: ["http"],
up: ({ http, pg }) => new Server(require("http").createServer(http.callback()))
},start: {
needs: ["pg", "http", "socket"],
up: ({ http, config }) => http.listen(port),
down: ({ start }) => up.close()
}
})app.on("stopped", signal => console.log(`App stopped because ${signal} was received`))
app.start()
.then(({ config }) => console.log(`App started on port ${config.port}`))
.catch(e => console.error("Could not start app", e))
```This will start the `config` stage, then the `pg` and `http` stages, then the
`socket` stage and finally if the `start` stage.If your app receive `SIGINT`, `SIGTERM`, `unhandledRejection` or `uncaughtException`,
(or if you call `app.close()`), `start` will be downed first then `pg`.## API
### `AppLife#constructor(dependencies)`
Setup the the applife and load dependencies
- `T extends {[key: string]: unknown}` is the object that represent your state,
once fully loaded.`T` can be infered from usage.
For example if you have:```ts
const app = new Applife({
a: { up: () => Promise.resolve("A") },
b: { up: () => Promise.resolve(42) },
})
// T: { a: string, b: number }
```- `dependencies: {[key: keyof T]: dependency}`, an object that represent the list
of dependencies. The key is important as each dependency will receive `Pick`- `dependency` is an object with the following keys
- `needs?: keyof T | Array`: an optional array of steps which must
resolve BEFORE calling the `up` method- `up?: (loaded: Pick) => Promise`: the function to boot the current stage (once all in `needs` resolved).
This function takes all loaded properties and MUST return a promise.
`up` is optional because you may only want to specify a shutdown step.- `after?: keyof T | Array`: an optional array of steps which must
resolve BEFORE calling the `down` method- `down?: (loaded: Pick) => Promise`: The function
to call to gracefully shutdown this step.
This function will only be called AFTER all steps defined in `after`.
This MUST return a promise### `AppLife.start() => Promise`
Starts your application (run all the `up` functions) and returns loaded values.
If any dependency fails to load, `start` will throw a `Boot sequence failed` with
a list of all errors that were caught in `Error.details: Error[]`
The throw will occur AFTER all dependencies are successfuly unloaded`start` will return your resolved dependencies
### `AppLife.stop() => Promise`
Stop your application (run all the `down` functions).
`stop` will only stop a dependency that was started.
### `AppLife.run() => Promise`
Treat your application as if it were a one of application.
Basically is `app.start().then(() => app.stop())`
Handles dependencies error the same way `start` would.
### `emit stopped(reason)`
After the app stops, it emits the `stopped` event with one of the following reasons:
- `SIGTERM` received the `SIGTERM` signal
- `SIGINT` received the `SIGINT` signal
- `uncaughtException` an exception was not handled by your code
- `unhandledRejection` a promise rejection was not handled by your code
- `stop` - if the `stop` method was called