https://github.com/myunisoft/events
Events and Webhooks utilities and documentation
https://github.com/myunisoft/events
Last synced: about 1 year ago
JSON representation
Events and Webhooks utilities and documentation
- Host: GitHub
- URL: https://github.com/myunisoft/events
- Owner: MyUnisoft
- License: mit
- Created: 2022-03-29T11:56:15.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2025-05-07T12:55:52.000Z (about 1 year ago)
- Last Synced: 2025-05-07T13:49:27.347Z (about 1 year ago)
- Language: TypeScript
- Homepage:
- Size: 787 KB
- Stars: 6
- Watchers: 0
- Forks: 0
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
Events
MyUnisoft Events validator, schemas and types (useful to work with Webhooks).
## 🚧 Requirements
- [Node.js](https://nodejs.org/en/) version 18 or higher
- Docker (for running tests).
## 🚀 Getting Started
This package is available in the Node Package Repository and can be easily installed with [npm](https://doc.npmjs.com/getting-started/what-is-npm) or [yarn](https://yarnpkg.com)
```bash
$ npm i @myunisoft/events
# or
$ yarn add @myunisoft/events
```
Configure environment variables
| variable | description | default |
| --- | --- | --- |
| `MYUNISOFT_EVENTS_LOGGER_MODE` | Set log level for the default logger | `info` |
| Dispatcher |
| `MYUNISOFT_DISPATCHER_IDLE_TIME` | Interval threshold when Dispatcher become idle | `600_000` |
| `MYUNISOFT_DISPATCHER_CHECK_LAST_ACTIVITY_INTERVAL` | Dispatcher checking last activity interval | `120_000` |
| `MYUNISOFT_DISPATCHER_BACKUP_TRANSACTION_STORE_NAME` | Default name for backup transaction store | `backup` |
| `MYUNISOFT_DISPATCHER_INIT_TIMEOUT` | Dispatcher initialisation timeout | `3_500` |
| `MYUNISOFT_DISPATCHER_PING_INTERVAL` | Dispatcher ping interval | `3_500` |
| Incomer |
| `MYUNISOFT_INCOMER_INIT_TIMEOUT` | Incomer initialisation timeout | `3_500` |
| `MYUNISOFT_EVENTS_INIT_EXTERNAL` | Whenever Incomer should initialize an external Dispatcher | `false` |
| `MYUNISOFT_INCOMER_MAX_PING_INTERVAL` | Maximum ping interval | `60_000` |
| `MYUNISOFT_INCOMER_PUBLISH_INTERVAL` | Publish interval | `60_000` |
| `MYUNISOFT_INCOMER_IS_DISPATCHER` | Weither Incomer is a Dispatcher | `false` |
Some options takes the lead over environment variables.
For instance with: `new Incomer({ dispatcherInactivityOptions: { maxPingInterval: 900_000 }})` the max ping interval will be `900_000` even if `MYUNISOFT_INCOMER_MAX_PING_INTERVAL` variable is set.
## 📚 Usage example
```ts
import * as Events, { type EventOptions } from "@myunisoft/events";
const event: EventOptions<"connector"> = {
name: "connector",
operation: "CREATE",
scope: {
schemaId: 1
},
metadata: {
agent: "Node",
origin: {
endpoint: "http://localhost:12080/api/v1/my-custom-feature",
method: "POST",
requestId: crypto.randomUUID();
},
createdAt: Date.now()
},
data: {
id: "1",
code: "JFAC"
}
};
Events.validate(event);
```
You can also use additional APIs to validate and narrow the data type depending on the operation:
```ts
if (Events.isCreateOperation(event.operation)) {
// Do some code
}
else if (Events.isUpdateOperation(event.operation)) {
// Do some code
}
else if (Events.isDeleteOperation(event.operation)) {
// Do some code
}
```
> [!NOTE]
> 👀 See [**here**](./docs/events.md) for the exhaustive list of Events.
## 💡 What is an Event?
A fully constituted event is composed of a `name`, an `operation`, and multiple objects such as `data`, `scope` and `metadata`.
- The `name` identifies the event.
- The `operation` defines if it is a creation, update, or deletion.
- Based on the name, we know the **data** and the different `metadata.origin.method` related to it.
- The `metadata` object is used to determine various pieces of information, such as the entry point.
- The `scope` defines the **who**.
```ts
export interface Scope {
schemaId: number;
firmId?: number | null;
firmSIRET?: number | null;
accountingFolderId?: number | null;
accountingFolderSIRET?: number | null;
accountingFolderRef?: string | null;
persPhysiqueId?: number | null;
}
export interface Metadata {
agent: string;
origin?: {
endpoint: string;
method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | "HEAD" | "OPTIONS" | (string & {});
requestId?: string;
};
createdAt: number;
}
```
## API
- [Dispatcher](./docs/class/dispatcher.md)
- [Incomer](./docs/class/incomer.md)
### validate< T extends keyof Events >(options: EventOptions): void
Throw an error if a given event is not recognized internally.
### isCreateOperation< T extends keyof Events >(operation: EventOptions["operation"]): operation is Operation["create"]
### isUpdateOperation< T extends keyof Events >(operation: EventOptions["operation"]): operation is Operation["update"]
### isDeleteOperation< T extends keyof Events >(operation: EventOptions["operation"]): operation is Operation["delete"]
---
EventOptions is described by the following type:
```ts
export type EventOptions = {
scope: Scope;
metadata: Metadata;
} & EventsDefinition.Events[K];
```
## Exploiting Webhooks
👀 See [**the root example/fastify**](./example/fastify/feature/webhook.ts) for an example of utilizing webhooks with an HTTP server.
In TypeScript, webhooks can be described using the `WebhookResponse` type:
```ts
import type { WebhookResponse } from "@myunisoft/events";
const response: WebhooksResponse<["connector", "accountingFolder"]> = [
{
name: "connector",
operation: "CREATE",
scope: {
schemaId: 1
},
data: {
id: 1,
code: "JFAC"
},
webhookId: "1",
createdAt: Date.now()
},
{
name: "accountingFolder",
operation: "CREATE",
scope: {
schemaId: 1
},
data: {
id: 1
},
webhookId: "2",
createdAt: Date.now()
},
];
```
Webhook JSON Schema
```json
{
"description": "Webhook",
"type": "array",
"items": {
"type": "object",
"properties": {
"scope": {
"$ref": "Scope"
},
"webhookId": {
"type": "string"
},
"createdAt": {
"type": "number"
},
"name": {
"type": "string",
"description": "event related name"
},
"operation": {
"type": "string",
"description": "event related operation",
"enum": ["CREATE", "UPDATE", "DELETE", "VOID"]
},
"data": {
"type": "object",
"description": "event related data",
"properties": {
"id": {
"type": "string"
},
"required": ["id"],
"additionalProperties": true
}
}
},
"required": ["scope", "webhookId", "createdAt", "name", "operation", "data"],
"additionalProperties": false
}
}
```
## Contributors ✨
[](#contributors-)
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

Nicolas Hallaert
💻 📖 ⚠️

Yefis
💻 📖

Gentilhomme
📖

PierreDemailly
💻 📖
## License
MIT