MyUnisoft Events validator, schemas and types (useful to work with Webhooks).
- Node.js version 16 or higher
- Docker (for running tests).
This package is available in the Node Package Repository and can be easily installed with npm or yarn
$ npm i @myunisoft/events
# or
$ yarn add @myunisoft/events
An Event fully constituted is composed by a name
, an operation
and multiple objects such as data
, scope
and metadata
.
- The
name
identify the event. - The
operation
will define if it is a creation, update or deletion. - According to the name, we know the
data
and the differentmetadata.origin.method
related. - The
metadata
object is used to determine different information as the ecosystem, the entry point etc. - The
scope
will define the who.
export interface Scope {
schemaId: number;
firmId?: number | null;
firmSIRET?: number | null;
accountingFolderId?: number | null;
accountingFolderSIRET?: number | null;
accountingFolderRef?: string | null;
persPhysiqueId?: number | null;
}
export type Method = "POST" | "PATCH" | "PUT" | "DELETE";
export interface Metadata {
agent: string;
origin?: {
endpoint: string;
method: Method;
requestId?: string;
};
createdAt: number;
}
Define and validate an event.
import * as MyEvents, { 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"
}
};
MyEvents.validate<"connector">(event);
Define which operation the event has.
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"
}
};
if (isCreateOperation(event.operation)) {
// Do some code
}
if (isUpdateOperation(event.operation)) {
// Do some code
}
if (isDeleteOperation(event.operation)) {
// Do some code
}
There is the documentation of Dispatcher, and Incomer classes.
Throw an error if a given event is not internaly known.
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"]
export type EventOptions<K extends keyof EventsDefinition.Events> = {
scope: Scope;
metadata: Metadata;
} & EventsDefinition.Events[K];
const event: EventOptions<"connector"> = {
name: "connector",
operation: "CREATE",
scope: {
schemaId: 1
},
metadata: {
agent: "Node",
createdAt: Date.now(),
requestId: crypto.randomUUID();
},
data: {
id: 1,
code: "JFAC"
}
}
type TupleToObject<T extends readonly any[],
M extends Record<Exclude<keyof T, keyof any[]>, PropertyKey>> =
{ [K in Exclude<keyof T, keyof any[]> as M[K]]: T[K] };
export type EventsOptions<T extends (keyof EventsDefinition.Events)[] = (keyof EventsDefinition.Events)[]> = TupleToObject<[
...(EventOptions<T[number]>)[]
], []>;
const events: EventsOptions<["connector", "accountingFolder"]> = [
{
name: "connector",
operation: "CREATE",
scope: {
schemaId: 1
},
metadata: {
agent: "Node",
createdAt: Date.now(),
requestId: crypto.randomUUID();
},
data: {
id: 1,
code: "JFAC"
}
},
{
name: "accountingFolder",
operation: "CREATE",
scope: {
schemaId: 1
},
metadata: {
agent: "Windev",
createdAt: Date.now(),
requestId: crypto.randomUUID();
},
data: {
id: 1
}
}
];
const event: EventsOptions<["connector", "accountingFolder"]> = {
name: "connector",
operation: "CREATE",
scope: {
schemaId: 1
},
metadata: {
agent: "Node",
createdAt: Date.now(),
requestId: 0
},
data: {
id: 1,
code: "JFAC"
}
}
π See here for an example of exploiting webhooks with an http server.
π See here for an exhaustive list of MyUnisoft Events you can subscribe to.
β οΈ A Webhook can send multiple Events on a single HTTP POST request.
type WebhookResponse<K extends keyof EventTypes.Events> = {
scope: Scope;
webhookId: string;
createdAt: number;
} & EventTypes.Events[K];
export type WebhooksResponse<T extends (keyof EventTypes.Events)[] = (keyof EventTypes.Events)[]> = [
...(WebhookResponse<T[number]>)[]
];
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()
},
];
Thanks goes to these wonderful people (emoji key):
Nicolas Hallaert π» π |
Yefis π» π |
Gentilhomme π π‘οΈ |
MIT