diff --git a/.all-contributorsrc b/.all-contributorsrc
index 731a3156..6a4ca0f1 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -32,8 +32,7 @@
"avatar_url": "https://avatars.githubusercontent.com/u/4438263?v=4",
"profile": "https://www.linkedin.com/in/thomas-gentilhomme/",
"contributions": [
- "doc",
- "security"
+ "doc"
]
}
],
diff --git a/README.md b/README.md
index b945639c..948d96b2 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,13 @@
-
-## Requirements
+## 🚧 Requirements
+
- [Node.js](https://nodejs.org/en/) version 14 or higher
-## Getting Started
+## 🚀 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)
@@ -26,32 +26,55 @@ $ npm i @myunisoft/events
$ yarn add @myunisoft/events
```
-## Usage
+## 📚 Usage
-### validateEventData
+> How is define an Event & how to validate it.
```ts
-import { EventsDefinition, validateEventData } from "@myunisoft/events";
+import * as MyEvents from "@myunisoft/events";
-const event: EventsDefinition.AccountingFolder = {
- name: "accountingFolder",
+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"
+ },
+ createdAt: Date.now().toLocaleString()
+ },
data: {
- accountingFolderId: 1
+ id: 1,
+ code: "JFAC"
}
};
-validateEventData<"connector" | "accountingFolder">(event);
+MyEvents.validate<"connector">({ name: event.name, operation: event.operation, data: event.data });
```
+---
+
+
+> Specifying valide Events registring an endpoint related to Webhooks.
+
+[**Here**](./example/fastify/feature/webhook.ts) is an example
+
+
## API
-### validateEventData< T extends keyof EventsDefinition.Events >(options: EventsDefinition.Events[ T ]): void
+### validate< T extends keyof Events >(options: Events[ T ]): void
Throw an error if a given event is not internaly known.
-## Types
+## Events
-- [Events descriptions](./docs/events.md)
+An Event fully constitued is composed by a `name`, a `data` object, a `scope` object, and a `metadata` object.
+- The `name` identify the event.
+- According to the name, we know the `data` and the differentes `metadata.origin.method` related.
+- The `metadata` object is used to determine differentes informations as the ecosystem, the entry point etc.
```ts
export interface Scope {
@@ -60,18 +83,66 @@ export interface Scope {
accountingFolderId?: number;
}
-export type Method = "POST" | "PATCH" | "PUT" | "DELETE";
-
export interface Metadata {
agent: string;
origin?: {
endpoint: string;
- method: Method;
+ method: "POST" | "PATCH" | "PUT" | "DELETE";
};
createdAt: string;
}
```
+**Below is an exhaustive list of the MyUnisoft Events available**
+
+Connector
+
+[JSON Schema](./docs/json-schema/events/connector.md)
+
+```ts
+export interface Connector {
+ name: "connector";
+ operation: "CREATE" | "UPDATE" | "DELETE";
+ data: {
+ id: string;
+ code: string;
+ };
+}
+```
+
+| Operation | Agent | Payload |
+|---|---|---|
+| CREATE | Node | {
id: string;
code: string;
}
|
+| UPDATE | Node | {
id: string;
code: string;
}
|
+| DELETE | Node | {
id: string;
code: string;
}
|
+
+
+
+
+
+AccountingFolder
+
+[JSON Schema](./docs/json-schema/events/accountingFolder.md)
+
+```ts
+export interface AccountingFolder {
+ name: "accountingFolder";
+ operation: "CREATE";
+ data: {
+ id: string;
+ };
+}
+```
+
+| Operation | Agent | Payload |
+|---|---|---|
+| CREATE | Windev | {
id: string;
}
|
+
+
+
+
+## Types
+
EventOptions
```ts
@@ -99,7 +170,7 @@ const event: EventOptions<"connector"> = {
-EventOptions
+EventsOptions
```ts
type TupleToObject = {
WebhooksResponse
```ts
-type WebhookResponse = {
+type WebhookResponse = {
scope: Scope;
webhookId: string;
createdAt: number;
-} & EventsDefinition.Events[K];
+} & EventTypes.Events[K];
-export type WebhooksResponse = [
+export type WebhooksResponse = [
...(WebhookResponse)[]
];
@@ -203,6 +274,8 @@ const response: WebhooksResponse<["connector", "accountingFolder"]> = [
```
+
+
## Contributors ✨
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index 78d52c28..00000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,16 +0,0 @@
-This project participates in the Responsible Disclosure Policy program for the Node.js Security Ecosystem.
-
-# Responsible Disclosure Policy
-
-A responsible disclosure policy helps protect the project and its users from security vulnerabilities discovered in the project’s scope by employing a process where vulnerabilities are publicly disclosed after a reasonable time period to allow patching the vulnerability.
-
-All security bugs are taken seriously and are considered as top priority.
-Your efforts to responsibly disclose your findings are appreciated and will be taken into account to acknowledge your contributions.
-
-
-## Reporting a Security Issue
-
-Any security related issue should be reported to the [Node.js Ecosystem](https://hackerone.com/nodejs-ecosystem
-) program hosted on HackerOne which follows the [3rd party responsible disclosure process](https://github.com/nodejs/security-wg/blob/master/processes/third_party_vuln_process.md) set by the Node.js Security WG. One may also directly contact the project’s maintainers, but through the HackerOne program the Security WG members will take care of triaging the vulnerability and invite project maintainers to participate in the report.
-
-As an alternative method, vulnerabilities can also be reported by emailing security-ecosystem@nodejs.org.
\ No newline at end of file
diff --git a/docs/events.md b/docs/events.md
deleted file mode 100644
index 47269693..00000000
--- a/docs/events.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Events Descriptions
-
-```ts
-export interface Events {
- accountingFolder: AccountingFolder;
- connector: Connector;
-}
-```
-
-## connector
-
-[JSON Schema](./json-schema/events/connector.json)
-
-```ts
-export interface Connector {
- name: "connector";
- operation: "CREATE" | "UPDATE" | "DELETE";
- data: {
- id: string;
- code: string;
- };
-}
-```
-
-| Operation | Agent | Payload |
-|---|---|---|
-| CREATE | Node | ```{ id: string ; code: string; }``` |
-| UPDATE | Node | ```{ id: string ; code: string; }``` |
-| DELETE | Node | ```{ id: string ; code: string; }``` |
-
----
-
-## accountingFolder
-
-[JSON Schema](./json-schema/events/accountingFolder.json)
-
-```ts
-export interface AccountingFolder {
- name: "accountingFolder";
- operation: "CREATE";
- data: {
- id: string;
- };
-}
-```
-
-| Operation | Agent | Payload |
-|---|---|---|
-| CREATE | Windev | ```{ id: string ;}``` |
diff --git a/docs/json-schema/events/accountingFolder.json b/docs/json-schema/events/accountingFolder.md
similarity index 97%
rename from docs/json-schema/events/accountingFolder.json
rename to docs/json-schema/events/accountingFolder.md
index 1bece357..a6688672 100644
--- a/docs/json-schema/events/accountingFolder.json
+++ b/docs/json-schema/events/accountingFolder.md
@@ -1,3 +1,4 @@
+```json
{
"description": "AccountingFolder event",
"type": "object",
@@ -27,3 +28,4 @@
},
"required": ["name", "operation", "scope", "metadata", "data"]
}
+```
diff --git a/docs/json-schema/events/connector.json b/docs/json-schema/events/connector.md
similarity index 98%
rename from docs/json-schema/events/connector.json
rename to docs/json-schema/events/connector.md
index 304aff8c..eaeb00a0 100644
--- a/docs/json-schema/events/connector.json
+++ b/docs/json-schema/events/connector.md
@@ -1,3 +1,4 @@
+```json
{
"description": "Connector event",
"type": "object",
@@ -28,3 +29,4 @@
},
"required": ["name", "operation", "scope", "metadata", "data"]
}
+```
diff --git a/docs/json-schema/metadata.json b/docs/json-schema/metadata.md
similarity index 97%
rename from docs/json-schema/metadata.json
rename to docs/json-schema/metadata.md
index 46324567..4575d3dc 100644
--- a/docs/json-schema/metadata.json
+++ b/docs/json-schema/metadata.md
@@ -1,3 +1,4 @@
+```json
{
"$id": "Metadata",
"description": "Object related to the metadata of an event",
@@ -25,3 +26,4 @@
},
"required": ["agent", "createdAt"]
}
+```
diff --git a/docs/json-schema/scope.json b/docs/json-schema/scope.md
similarity index 96%
rename from docs/json-schema/scope.json
rename to docs/json-schema/scope.md
index ce0b25dc..4d485877 100644
--- a/docs/json-schema/scope.json
+++ b/docs/json-schema/scope.md
@@ -1,3 +1,4 @@
+```json
{
"$id": "Scope",
"description": "Object related to the scope of an event",
@@ -15,3 +16,4 @@
},
"required": ["schemaId"]
}
+```
diff --git a/example/fastify/app.ts b/example/fastify/app.ts
new file mode 100644
index 00000000..92863553
--- /dev/null
+++ b/example/fastify/app.ts
@@ -0,0 +1,37 @@
+
+// Import Third-party Dependencies
+import fastify from "fastify";
+
+// Import Types
+import { FastifyInstance } from "fastify/types/instance";
+
+// Import Internal Dependencies
+import { webhooksAPI } from "./feature/webhook";
+
+export function buildServer(): FastifyInstance {
+ const app = fastify({
+ logger: {
+ level: "info",
+ transport: {
+ target: "pino-pretty"
+ }
+ }
+ });
+
+ app.register(webhooksAPI, { prefix: "api/v1" });
+
+ return app;
+}
+const server = buildServer();
+
+server.listen({
+ port: process.env.PORT ? Number(process.env.PORT) : 12080,
+ host: process.env.HOST ?? "localhost"
+}, function httpListeningCallback(err, addr) {
+ if (err) {
+ server.log.error(err);
+ process.exit(1);
+ }
+
+ server.log.info(`Server listening on ${addr}`);
+});
diff --git a/example/fastify/feature/webhook.ts b/example/fastify/feature/webhook.ts
new file mode 100644
index 00000000..09626e0c
--- /dev/null
+++ b/example/fastify/feature/webhook.ts
@@ -0,0 +1,31 @@
+// Import Internal Dependencies
+import * as MyEvents from "../../../src/index";
+
+// Import types
+import {
+ FastifyRequest,
+ FastifyReply,
+ FastifyInstance
+} from "fastify";
+
+export async function webhooksAPI(server: FastifyInstance) {
+ server.post("/anyEvents", getAnyWebhooks);
+ server.post("/connector", getConnectorWebhooks);
+}
+
+type GetAnyWebhooksRequest = FastifyRequest<{
+ Body: MyEvents.WebhooksResponse;
+}>;
+
+async function getAnyWebhooks(req: GetAnyWebhooksRequest, reply: FastifyReply) {
+ // Do some code
+}
+
+type GetConnectorWebhooksRequest = FastifyRequest<{
+ Body: MyEvents.WebhooksResponse<["connector"]>;
+}>;
+
+async function getConnectorWebhooks(req: GetConnectorWebhooksRequest, reply: FastifyReply) {
+ // Do some code
+}
+
diff --git a/package.json b/package.json
index beae407b..64779808 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,8 @@
"jest": "^27.5.1",
"@types/jest": "^27.4.1",
"ts-jest": "^27.1.4",
- "typescript": "^4.6.3"
+ "typescript": "^4.6.3",
+ "fastify": "^4.3.0",
+ "dotenv": "^16.0.0"
}
}
diff --git a/src/index.ts b/src/index.ts
index c0344f08..ff23c303 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,10 +2,9 @@
import { events } from "./utils/index";
// Import Types
-import { EventsDefinition } from "./types/index";
+import { Events } from "./types/index";
-export function validateEventData(options: EventsDefinition.Events[T]) {
+export function validate(options: Events[T]) {
const { name, operation, data } = options;
if (!events.has(name)) {
@@ -23,5 +22,6 @@ keyof EventsDefinition.Events>(options: EventsDefinition.Events[T]) {
}
}
-export * as EventSchemas from "./schema";
-export * as EventTypes from "./types/index";
+export * as Schema from "./schema";
+export * from "./types/index";
+export { events } from "./utils/index";
diff --git a/src/types/index.ts b/src/types/index.ts
index f295b86c..9db517ec 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,5 +1,5 @@
// Import Internal Dependencies
-import * as EventsDefinition from "./events";
+import { Events } from "./events";
export interface Scope {
schemaId: number;
@@ -18,27 +18,27 @@ export interface Metadata {
createdAt: string;
}
-export type EventOptions = {
+export type EventOptions = {
scope: Scope;
metadata: Metadata;
-} & EventsDefinition.Events[K];
+} & Events[K];
type TupleToObject, PropertyKey>> =
{ [K in Exclude as M[K]]: T[K] };
-export type EventsOptions = TupleToObject<[
+export type EventsOptions = TupleToObject<[
...(EventOptions)[]
], []>;
-type WebhookResponse = {
+type WebhookResponse = {
scope: Scope;
webhookId: number;
createdAt: string;
-} & EventsDefinition.Events[K];
+} & Events[K];
-export type WebhooksResponse = [
+export type WebhooksResponse = [
...(WebhookResponse)[]
];
-export { EventsDefinition };
+export * from "./events";
diff --git a/test/UT/index.spec.ts b/test/UT/index.spec.ts
index c3e40bfa..a9530736 100644
--- a/test/UT/index.spec.ts
+++ b/test/UT/index.spec.ts
@@ -1,12 +1,9 @@
// Import Internal Dependencies
-import { validateEventData, EventTypes } from "../../src/index";
+import * as MyEvents from "../../src/index";
-// Import Types
-import { EventsDefinition } from "../../src/types/index";
-
-describe("validateEventData", () => {
+describe("validate", () => {
test("Casting no events name, it should take any events", () => {
- const event: EventsDefinition.Connector = {
+ const event: MyEvents.Connector = {
name: "connector",
operation: "CREATE",
data: {
@@ -15,11 +12,11 @@ describe("validateEventData", () => {
}
};
- expect(() => validateEventData(event)).not.toThrow();
+ expect(() => MyEvents.validate(event)).not.toThrow();
});
test("Casting events name, it should only take the specified events", () => {
- const event: EventTypes.EventOptions<"connector"> = {
+ const event: MyEvents.EventOptions<"connector"> = {
name: "connector",
operation: "CREATE",
metadata: {
@@ -37,7 +34,7 @@ describe("validateEventData", () => {
}
};
- expect(() => validateEventData<"connector">(event)).not.toThrow();
+ expect(() => MyEvents.validate<"connector">(event)).not.toThrow();
});
test("Given a wrong event name, it should throw", () => {
@@ -47,7 +44,7 @@ describe("validateEventData", () => {
data: {}
};
- expect(() => validateEventData(event as any)).toThrow(`Unknown "event": ${event.name}`);
+ expect(() => MyEvents.validate(event as any)).toThrow(`Unknown "event": ${event.name}`);
});
test("Given a wrong operation according to the event name, it should throw", () => {
@@ -59,7 +56,7 @@ describe("validateEventData", () => {
}
};
- expect(() => validateEventData(event as any))
+ expect(() => MyEvents.validate(event as any))
.toThrow(`Unknown "operation": ${event.operation} for the "event": ${event.name}`);
});
@@ -70,7 +67,7 @@ describe("validateEventData", () => {
data: {}
};
- expect(() => validateEventData(event as any))
+ expect(() => MyEvents.validate(event as any))
.toThrow(`Wrong data for the "operation": ${event.operation} on "event": ${event.name}`);
});
});
diff --git a/test/UT/utils/index.spec.ts b/test/UT/utils/index.spec.ts
index a61e39fd..efff36fa 100644
--- a/test/UT/utils/index.spec.ts
+++ b/test/UT/utils/index.spec.ts
@@ -1,5 +1,5 @@
// Import Internal Dependencies
-import { events } from "../../../src/utils/index";
+import { events } from "../../../src/index";
describe("events", () => {
test("events should be defined", () => {