Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/typescript #2

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
.*
/docs/types
/node_modules
/package-lock.json
/yarn.lock
/yarn-error.log
*.tsbuildinfo
!.husky
!.prettierrc.yml
!.gitignore
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Here is the documentation:

## Quick example

Library and application authors define hooks, see [`./sample/lib.js`](https://github.com/adaltas/node-plug-and-play/blob/master/sample/lib.js):
Library and application authors define hooks, see [`./samples/simple-js/lib.js`](https://github.com/adaltas/node-plug-and-play/blob/master/samples/simple-js/lib.js):

```js
const plugandplay = require("plug-and-play");
Expand Down Expand Up @@ -63,7 +63,7 @@ module.exports = {
};
```

Users and pluging authors can now register their own hooks, see [`./sample/index.js`](https://github.com/adaltas/node-plug-and-play/blob/master/sample/error.js):
Users and pluging authors can now register their own hooks, see [`./samples/simple-js/index.js`](https://github.com/adaltas/node-plug-and-play/blob/master/samples/simple-js/index.js):

```js
const mysuperlibrary = require("./lib");
Expand Down
8 changes: 8 additions & 0 deletions dist/esm/error.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
declare class PlugableError extends Error {
code: string;
[index: string]: unknown;
constructor(code: string, message: string | (string | object)[], ...contexts: Record<string, unknown>[]);
}
export { PlugableError };
declare const _default: (code: string, message: string | (string | object)[], ...contexts: Record<string, unknown>[]) => PlugableError;
export default _default;
40 changes: 40 additions & 0 deletions dist/esm/error.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/esm/error.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

181 changes: 181 additions & 0 deletions dist/esm/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/**
* Represents a handler function for a hook.
*
* @typeParam T - The type of the arguments passed to the hook handler.
*
* @param args - The arguments passed to the hook handler.
* @param handler - The next hook handler in the chain.
*
* @returns A Promise or a value that represents the result of the hook handler.
* @remarks (TODO)
* Both args and handler are optional by nature.
* Differentiate the hook handlers from the user handlers
*/
export type Handler<T> = (args: T, handler: Handler<T>) => unknown | void | PromiseLike<unknown> | Handler<T>;
/**
* Represents a hook in the Plug-and-Play system.
*
* @typeParam T - The type of the arguments expected by the hook handlers.
* @property after - List of plugin names with hooks of the same name that should be executed after this hook. If a string is provided, it is coerced to an array.
* @property before - List of plugin names with hooks of the same name that should be executed before this hook. If a string is provided, it is coerced to an array.
* @property handler - The hook handler to be executed.
* @property name - Name to identify the hook.
*/
export interface Hook<T> {
after?: string | string[];
before?: string | string[];
handler: Handler<T>;
name?: PropertyKey;
}
/**
* Represents a normalized hook with standardized format.
*
* @typeParam T - The type of the arguments and return values of the hooks.
* @typeParam K - The type of the key of the hook in the record.
* @property after - An array of plugin names that this hook should be executed after.
* @property before - An array of plugin names that this hook should be executed before.
* @property handler - The handler function of the hook.
* @property name - The name of the hook.
* @property plugin - The name of the plugin that defines this hook.
* @property require - An array of plugin names that this plugin requires.
*/
export interface HookNormalized<T, K extends keyof T> {
after: string[];
before: string[];
handler: Handler<T[K]>;
name: K;
plugin?: string;
require?: string[];
}
/**
* Represents a plugin for the Plug-and-Play system.
*
* @typeParam T - Type of parameters expected by hook handlers.
* @property hooks - List of hooks identified by hook names. Each hook can be an array of hooks, a single hook, or a handler function.
* @property name - Name identifying the plugin by other plugin with the `after`, `before` and `require` properties.
* @property require - Names of the required plugins. If a required plugin is not registered, an error is thrown when the plugin is registered.
*/
export interface Plugin<T> {
hooks: {
[Name in keyof T]?: Hook<T[Name]>[] | Hook<T[Name]> | Handler<T[Name]>;
};
name?: PropertyKey;
require?: string | string[];
}
/**
* Represents a normalized plugin with standardized hooks.
*
* @typeParam T - The type of the arguments and return values of the hooks.
* @property hooks - Hooks associated with the plugin, normalized to a standardized format.
* @property name - Name identifying the plugin by other plugin with the `after`, `before` and `require` properties.
* @property require - Names of the required plugins. If a required plugin is not registered, an error is thrown when the plugin is registered.
*/
export interface PluginNormalized<T> {
hooks: {
[Name in keyof T]: HookNormalized<T, Name>[];
};
name: PropertyKey | undefined;
require: string[];
}
/**
* Represents the public API of the plugin system.
*
* @typeParam T - The type of the arguments and return values of the hooks.
*/
export interface Api<T, Chain = undefined> {
/**
* Execute a handler function and its associated hooks.
*
* @param options - Options for the synchroneous hook execution.
* @param options.args - Argument passed to the handler function as well as all hook handlers.
* @param options.handler - Function to decorate, receive the value associated with the `args` property.
* @param options.hooks - List of complementary hooks from the end user.
* @param options.name - Name of the hook to execute.
* @returns - A promise that resolves to the result of the final handler.
*/
call: <K extends keyof T>(options: {
args: T[K];
handler?: Handler<T[K]>;
hooks?: Hook<T[K]>[];
name: K;
}) => Promise<unknown>;
/**
* Execute a handler function and its associated hooks synchronously.
*
* @param options - Options for the asynchroneous hook execution.
* @param options.args - Argument passed to the handler function as well as all hook handlers.
* @param options.handler - Function to decorate, receive the value associated with the `args` property.
* @param options.hooks - List of complementary hooks from the end user.
* @param options.name - Name of the hook to execute.
* @returns - The result of the final handler.
*/
call_sync: <K extends keyof T>(options: {
args: T[K];
handler?: Handler<T[K]>;
hooks?: Hook<T[K]>[];
name: K;
}) => unknown;
/**
* Retrieve the hooks with the given name from all registered plugins, in the order they were registered.
*
* @param options - Options used to retrieve the hooks. The default is `[]`.
* @param options.hooks - List of complementary hooks from the end user. These hooks are merged with the hooks retrieved from the registered plugins.
* @param options.name - Names of the hook to retrieve.
* @param options.sort - Topological sorting of the hooks relatively to each other using the `after` and `before` properties. If `sort` is `false`, the hooks are returned in the order they were registered. The default is `true`.
* @returns - The retrieved hooks.
*/
get: <K extends keyof T>(options: {
hooks?: Handler<T[K]> | Hook<T[K]> | Hook<T[K]>[];
name: K;
sort?: boolean;
}) => HookNormalized<T, K>[];
/**
* Register a new plugin in the system.
*
* @param plugin - The plugin to register.
* @returns - The plugin system.
*
* @remarks Plugin can be provided when instantiating Plug-And-Play by passing the plugins property or they can be provided later on by calling the register function.
*
*/
register: (plugin: Plugin<T> | ((...Args: unknown[]) => Plugin<T>)) => Chain extends undefined ? this : Chain;
/**
* Check if a plugin with the given name is registered with the plugin system.
*
* @param name - The name of the plugin to check.
* @returns - True if the plugin is registered, false otherwise.
*/
registered: (name: PropertyKey) => boolean;
}
/**
* A function to initialize a plugandplay instance. Creates a plugin system with support for hooks and plugin requirements.
*
* @typeParam T - The type of the arguments and return values of the hooks. An object representing the type of every hook arguments.
* @example
*
* Loose typing:
* ```typescript
* plugandplay();
* ```
*
* Specific typing:
* ```typescript
* plugandplay<{
* "first-hook" : { bar: number; foo: string };
* "second-hook" : { baz: object }
* }>();
* ```
* @param options - The options used to initiate the library.
* @param options.args - The arguments to pass to the registered plugins.
* @param options.chain - The chain of plugins to call the hooks on.
* @param options.parent - The parent plugin system to call the hooks on.
* @param options.plugins - The initial plugins to register.
* @returns - An object representing the plugin system.
*/
declare const plugandplay: <T extends Record<string, unknown> = Record<string, unknown>, Chain = undefined>({ args, chain, parent, plugins, }?: {
args?: unknown[];
chain?: Chain;
parent?: Api<T, Chain>;
plugins?: (Plugin<T> | (<FnArgs, T_1>(...Args: FnArgs[]) => Plugin<T_1>))[];
}) => Api<T, Chain>;
export { plugandplay };
Loading