UNPKG

@smartmonkeysinc/node-red-contrib-postgres-migrations

Version:

A Node-RED node to run PostgreSQL migrations from a msg.migrations array using Knex.

125 lines (94 loc) 5.75 kB
# `node-red-contrib-postgres-migrations` A Node-RED node to execute PostgreSQL database migrations directly from a JavaScript array. ## Overview This Node-RED custom node provides a flexible way to manage PostgreSQL database schemas within your Node-RED flows. Instead of relying on external migration files, it allows you to define your database migrations as an array of JavaScript objects containing raw SQL `up` scripts. It handles: - Connecting to your PostgreSQL database. - Creating a dedicated `_nodered_migrations` table to track executed migrations. - Applying new, unapplied migrations in order. - Reporting on success or failure. ## Features - **In-Memory Migrations:** Define your migrations directly within Node-RED `Function` nodes or other data sources as a JavaScript array. - **Raw SQL Support:** Execute arbitrary raw SQL commands for schema changes (`CREATE TABLE`, `ALTER TABLE`, `CREATE INDEX`, etc.). - **Automatic Tracking:** Automatically tracks applied migrations in your database using a `_nodered_migrations` table. - **Configurable Connection:** Easily configure PostgreSQL connection details (host, port, user, password, database) via the node's properties. - **Error Handling:** Provides clear error feedback in Node-RED's debug sidebar and status. ## Usage Once installed, the "Postgres Migrations" node will appear in the "storage" category of your Node-RED palette. ### 1. Configure the Node Drag the "Postgres Migrations" node onto your flow. Double-click it to open its properties panel: - **Name (optional):** A friendly name for the node in your flow. - **Host:** The hostname or IP address of your PostgreSQL server (e.g., `localhost`, `192.168.1.100`). - **Port:** The port number for your PostgreSQL server (default: `5432`). - **User:** The username to connect to the database. - **Password:** The password for the specified user. - **Database:** The name of the database to connect to. ### 2. Prepare `msg.migrations` The node expects an input message with a `msg.migrations` property. This property must be an **array of migration objects**. Each migration object needs: - `name` (string): A unique identifier for the migration. It's highly recommended to use a timestamp-based format (e.g., `YYYYMMDDHHmmss_description`) to ensure correct ordering. - `up` (string): The raw SQL string to apply this migration. #### Example `msg.migrations` array (e.g., from a Function node): ```javascript msg.migrations = [ { name: "20250709100000_create_devices_table", up: ` CREATE TABLE devices ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, location TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); `, }, { name: "20250709100100_create_readings_table", up: ` CREATE TABLE readings ( id BIGSERIAL PRIMARY KEY, device_id UUID NOT NULL REFERENCES devices(id) ON DELETE CASCADE, value NUMERIC NOT NULL, recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_readings_device_time ON readings (device_id, recorded_at DESC); `, }, { name: "20250709100200_alter_devices_add_firmware", up: "ALTER TABLE devices ADD COLUMN firmware_version VARCHAR(50);", }, ]; return msg; ``` ## Node Inputs <dl class="message-properties"> <dt>msg.migrations <span class="property-type">array</span></dt> <dd>An array of migration objects, each with <code>name</code> and <code>up</code> string properties containing raw SQL.</dd> </dl> ## Node Outputs <dl class="message-properties"> <dt>msg.payload <span class="property-type">object</span></dt> <dd> On successful completion, the <code>msg.payload</code> will contain an object with a summary of the migration run: <ul> <li><code>summary</code> (string): A human-readable summary of applied and skipped migrations.</li> <li><code>applied</code> (array): An array of names of migrations that were successfully applied during this run.</li> <li><code>skipped</code> (number): The count of migrations that were already applied and thus skipped.</li> </ul> </dd> </dl> ## How it Works 1. **Connection:** Upon receiving a message, the node establishes a temporary connection to the PostgreSQL database using the provided configuration. 2. **Migration Tracking Table:** It checks for the existence of a table named `_nodered_migrations`. If it doesn't exist, it creates it with `name`, `batch`, and `migration_time` columns. This table stores the names of all migrations that have been successfully run. 3. **Identify Pending Migrations:** It queries `_nodered_migrations` to get a list of already applied migrations. It then compares this list with the `msg.migrations` array to identify which migrations are pending. 4. **Execute Migrations:** For each pending migration in the `msg.migrations` array (ordered by their appearance in the array), it executes the `up` SQL script using `knex.raw()`. 5. **Record Migration:** After successful execution of an `up` script, the migration's `name` is inserted into the `_nodered_migrations` table, along with a `batch` number and timestamp. 6. **Cleanup:** The database connection is closed after processing all migrations or on error. 7. **Status and Output:** The node's status indicates progress and final outcome. A success message with details is sent to `msg.payload` on completion. Errors are caught and sent to Node-RED's error handling. ## Dependencies This node relies on: - `knex` - `pg` (PostgreSQL driver) These dependencies are automatically installed when you install the Node-RED package. ## License This project is licensed under the MIT License. See the `LICENSE` file for details.