@hembrow-innovations/odm-plugin-js
v0.0.2
Published
node.js plugin library for odm
Downloads
3
Readme
Node.js gRPC Plugin Server for ODM CLI
This package provides a robust and easy-to-use framework for creating gRPC-based plugins for the ODM CLI using Node.js and TypeScript. It abstracts away the complexities of gRPC communication, allowing you to focus on the core logic of your plugin.
Features
- Simplified Plugin Development: Define your plugin logic by implementing a single
PluginExecuterinterface. - Automatic gRPC Server Management: The
PluginServerclass handles gRPC server setup, binding, and graceful shutdown. - Protobuf
AnyType Handling: TheProtobufHelperclass simplifies the packing and unpacking of various data types to and from thegoogle.protobuf.Anymessage, which is used for dynamic arguments and options. - Example Implementation: Includes an
ExamplePluginto demonstrate how to implement thePluginExecuterinterface and process requests. - Graceful Shutdown: The
PluginMainclass sets up listeners forSIGTERMandSIGINTsignals to ensure a clean shutdown of the server.
Installation
Assuming you have a Node.js project, you can add this package as a dependency.
npm install @grpc/grpc-js @grpc/proto-loader google-protobufYou will also need to have your gRPC proto definition file (odm-plugin.proto in this example) available in your project.
Usage
1. Define Your Plugin Logic
Your plugin's core logic should be encapsulated in a class that implements the PluginExecuter interface. The execute method is where you will handle the incoming request and return the appropriate response.
// my-plugin.ts
import {
PluginExecuter,
ExecutionRequestBody,
ExecutionResponse,
ProtobufHelper,
} from "@hembrow-innovations/odm-plugin-js";
export class MyCustomPlugin implements PluginExecuter {
async execute(request: ExecutionRequestBody): Promise<ExecutionResponse> {
// Unpack args and options using the helper
const myArg = ProtobufHelper.unpackAny(request.args.my_argument_key);
const myOption = ProtobufHelper.unpackAny(request.options.my_option_key);
console.log(`Received input: ${request.input}`);
console.log(`My custom argument value: ${myArg}`);
console.log(`My custom option value: ${myOption}`);
// Your custom logic here
const resultString = `The result of my plugin is based on input: "${request.input}"`;
return {
result: resultString,
};
}
}2. Create the Main Entry Point
Create a main file to instantiate your plugin and start the server. This file will be the entry point for the ODM CLI to execute your plugin.
// main.ts
import { PluginMain } from "./plugin-framework"; // Adjust the path as needed
import { MyCustomPlugin } from "./my-plugin";
// Create an instance of your plugin
const myPlugin = new MyCustomPlugin();
// Create the main server manager with your plugin
const pluginMain = new PluginMain(myPlugin);
// Start the server
pluginMain.start().catch((error) => {
console.error("Failed to start the plugin server:", error);
process.exit(1);
});3. Build and Run
Compile your TypeScript code and then run the compiled JavaScript file.
# Example tsconfig.json
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true
}
}tsc
node dist/main.jsWhen the PluginMain starts, it will log the port it is listening on to stdout in the format PLUGIN_PORT=<port_number>. The ODM CLI uses this information to establish a connection with your plugin.
API Reference
PluginExecuter
This is the core interface your plugin must implement.
execute(request: ExecutionRequestBody): Promise<ExecutionResponse>:request: An object containinginput(string),args(map of string toAny), andoptions(map of string toAny).returns: A promise that resolves to anExecutionResponseobject with aresultstring.
PluginServer
Manages the gRPC server lifecycle. You typically won't interact with this class directly, as PluginMain handles it for you.
constructor(executer: PluginExecuter): Creates a server instance bound to your plugin's logic.start(port: number = 0): Promise<number>: Binds the server to a port and starts it. Returns the assigned port.stop(): void: Shuts down the server.
ProtobufHelper
A utility class for working with google.protobuf.Any.
static packAny(value: any, typeUrl?: string): Any: Packs a JavaScript value into a protobufAnymessage.static unpackAny(any: Any): any: Unpacks a protobufAnymessage back into a JavaScript value.
PluginMain
The entry point for your plugin.
constructor(executer: PluginExecuter): Creates aPluginMaininstance with your plugin's implementation.start(): Promise<void>: Starts the gRPC server, logs the port, and sets up signal handlers for graceful shutdown.
