libsql-migrate
Advanced tools
| import { setConfigPath } from "./getConfig.js"; | ||
| export default function handleOptions(command) { | ||
| const options = command.opts(); | ||
| if (options.config) { | ||
| setConfigPath(options.config); | ||
| } | ||
| } |
+1
-1
| The MIT License (MIT) | ||
| Copyright © 2024 Travis Horn | ||
| Copyright © 2025 Travis Horn | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of |
+4
-1
| { | ||
| "name": "libsql-migrate", | ||
| "version": "1.1.4", | ||
| "version": "1.2.0", | ||
| "description": "Database migration and seed management for libsql with configurable options.", | ||
@@ -29,2 +29,5 @@ "bin": { | ||
| "author": "Travis Horn <travis@travishorn.com> (https://travishorn.com/)", | ||
| "contributors": [ | ||
| "mkrenzke <krenzke@unipoin.com>" | ||
| ], | ||
| "repository": { | ||
@@ -31,0 +34,0 @@ "type": "git", |
+107
-1
@@ -73,2 +73,18 @@ # libsql Migrate | ||
| ### Options | ||
| #### Custom Config Path (`-c`, `--config`) | ||
| `libsql-migrate` uses a configuration file named `libsqlrc.js` by default, which should export the necessary database connection and migration settings. | ||
| You can specify a custom path to your configuration file using the `--config` (or short `-c`) option. This is useful if the config file is located outside the project root or when you want to manage multiple environments. | ||
| **Example:** | ||
| ```bash | ||
| libsql-migrate up --config ../configs/libsqlrc.js | ||
| ``` | ||
| This tells `libsql-migrate` to load configuration from the specified file instead of looking for `libsqlrc.js` in the current working directory. If used with command `init` it will write the default config file to the given location. | ||
| ### Make a new migration | ||
@@ -129,2 +145,92 @@ | ||
| --- | ||
| ## Hooks | ||
| You can define optional lifecycle hooks to run custom logic before, after, or when an error occurs during a migration. These hooks are defined in the `libsqlrc.js` file. | ||
| ### Available Hooks and Parameters | ||
| | Hook Name | Called When | | ||
| | ----------------------------------------- | -------------------------------------------------------------------- | | ||
| | `beforeMigration(action, name)` | Before each migration is executed | | ||
| | `afterMigration(action, name, result)` | After each migration is successfully executed | | ||
| | `afterMigrations(action, names, results)` | **Only** called after all migrations when using the `latest` command | | ||
| | `onError(action, name, error)` | When a migration fails | | ||
| ### Hook Parameters | ||
| #### `action` (`"up"` \| `"down"`) | ||
| Indicates the direction of the migration: | ||
| - `"up"`: applying a migration | ||
| - `"down"`: rolling back a migration | ||
| #### `name` (string) | ||
| The full name of the migration file, including the timestamp prefix. | ||
| This is the name that has been generated using the `make` command, for example: | ||
| ``` | ||
| 20240327102435_add-users-table | ||
| ``` | ||
| #### `result` (any | undefined) | ||
| The result of the executed migration. This is the value returned by the migration function, if any. | ||
| If the function does not return a value, `result` will be `undefined`. | ||
| #### `names` (string[]) | ||
| An array of all processed migration names (only used in `afterMigrations`). | ||
| #### `results` (any[] | undefined[]) | ||
| An array of results returned by each migration (only used in `afterMigrations`). | ||
| If a migration does not return a value, the corresponding entry will be `undefined`. | ||
| #### `error` (Error) | ||
| The error object thrown during a failed migration. | ||
| ### Example | ||
| ```js | ||
| // libsqlrc.js | ||
| export default { | ||
| development: { | ||
| connection: { | ||
| url: "file:local.db", | ||
| }, | ||
| migrations: { | ||
| directory: "my_migrations_directory", | ||
| }, | ||
| hooks: { | ||
| beforeMigration: (action, name) => { | ||
| console.log(`[${action}] Starting migration: ${name}`); | ||
| }, | ||
| afterMigration: (action, name, result) => { | ||
| console.log(`[${action}] Finished migration: ${name}`, result); | ||
| }, | ||
| afterMigrations: (action, names, results) => { | ||
| console.log(`[${action}] All migrations completed via "latest":`); | ||
| names.forEach((name, i) => { | ||
| console.log(` - ${name}`, results[i]); | ||
| }); | ||
| }, | ||
| onError: (action, name, error) => { | ||
| console.error(`[${action}] Migration failed: ${name}`, error); | ||
| }, | ||
| }, | ||
| }, | ||
| // ... | ||
| }; | ||
| ``` | ||
| > **Note:** All hooks are optional. If a hook is not defined, it will be skipped silently. | ||
| --- | ||
| ### Run the next migration | ||
@@ -301,3 +407,3 @@ | ||
| Copyright © 2024 Travis Horn | ||
| Copyright © 2025 Travis Horn | ||
@@ -304,0 +410,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of |
+18
-1
@@ -22,4 +22,21 @@ import { createClient } from "@libsql/client"; | ||
| const latest = migrations.completed[migrations.completed.length - 1]; | ||
| await latest.down(client); | ||
| if (typeof config.hooks?.beforeMigration === "function") { | ||
| await config.hooks.beforeMigration("down", latest.name); | ||
| } | ||
| let result; | ||
| try { | ||
| result = await latest.down(client); | ||
| } catch (err) { | ||
| if (typeof config.hooks?.onError === "function") { | ||
| config.hooks.onError("down", latest.name, err); | ||
| } | ||
| throw err; | ||
| } | ||
| if (typeof config.hooks?.afterMigration === "function") { | ||
| await config.hooks.afterMigration("down", latest.name, result); | ||
| } | ||
| await client.execute({ | ||
@@ -26,0 +43,0 @@ sql: ` |
+5
-2
| #! /usr/bin/env node | ||
| import { program } from "commander"; | ||
| import { getVersion } from "../lib/index.js"; | ||
| import { getVersion, handleOptions } from "../lib/index.js"; | ||
| import down from "./down.js"; | ||
@@ -58,2 +58,5 @@ import init from "./init.js"; | ||
| program.parse(); | ||
| program | ||
| .option("-c --config <path>", "path to config-file", "./libsqlrc.js") | ||
| .hook("preAction", handleOptions) | ||
| .parse(); |
+2
-1
| import { writeFileIfNotExists, logger } from "../lib/index.js"; | ||
| import { getConfigPath } from "../lib/getConfig.js"; | ||
@@ -44,5 +45,5 @@ const configTemplate = `/** | ||
| export default async function init() { | ||
| const filePath = "libsqlrc.js"; | ||
| const filePath = getConfigPath(); | ||
| await writeFileIfNotExists(filePath, configTemplate, "utf-8"); | ||
| logger.info(`Template configuration file written to ${filePath}.`); | ||
| } |
+26
-6
@@ -24,4 +24,23 @@ import { createClient } from "@libsql/client"; | ||
| const results = []; | ||
| for (const migration of migrations.pending) { | ||
| await migration.up(client); | ||
| if (typeof config.hooks?.beforeMigration === "function") { | ||
| await config.hooks.beforeMigration("up", migration.name); | ||
| } | ||
| let result; | ||
| try { | ||
| result = await migration.up(client); | ||
| results.push(result); | ||
| } catch (err) { | ||
| if (typeof config.hooks?.onError === "function") { | ||
| config.hooks.onError("up", migration.name, err); | ||
| } | ||
| throw err; | ||
| } | ||
| if (typeof config.hooks?.afterMigration === "function") { | ||
| await config.hooks.afterMigration("up", migration.name, result); | ||
| } | ||
| await client.execute({ | ||
@@ -44,10 +63,11 @@ sql: ` | ||
| const names = migrations.pending | ||
| .map((migration) => migration.name) | ||
| .join(", "); | ||
| const names = migrations.pending.map((migration) => migration.name); | ||
| const plural = migrations.pending.length !== 1; | ||
| if (typeof config.hooks?.afterMigrations === "function") { | ||
| await config.hooks.afterMigrations("up", names, results); | ||
| } | ||
| logger.info( | ||
| `Ran ${migrations.pending.length} migration${plural ? "s" : ""}: ${names}.`, | ||
| `Ran ${migrations.pending.length} migration${plural ? "s" : ""}: ${names.join(", ")}.`, | ||
| ); | ||
@@ -54,0 +74,0 @@ } else { |
+18
-1
@@ -24,4 +24,21 @@ import { createClient } from "@libsql/client"; | ||
| : null; | ||
| await next.up(client); | ||
| if (typeof config.hooks?.beforeMigration === "function") { | ||
| await config.hooks.beforeMigration("up", next.name); | ||
| } | ||
| let result; | ||
| try { | ||
| result = await next.up(client); | ||
| } catch (err) { | ||
| if (typeof config.hooks?.onError === "function") { | ||
| config.hooks.onError("up", next.name, err); | ||
| } | ||
| throw err; | ||
| } | ||
| if (typeof config.hooks?.afterMigration === "function") { | ||
| await config.hooks.afterMigration("up", next.name, result); | ||
| } | ||
| await client.execute({ | ||
@@ -28,0 +45,0 @@ sql: ` |
+13
-3
| import { join } from "node:path"; | ||
| import { merge } from "lodash-es"; | ||
| let configPath = join(process.cwd(), "libsqlrc.js"); | ||
| const defaultConfig = { | ||
@@ -9,2 +11,10 @@ migrations: { directory: "./migrations" }, | ||
| export function setConfigPath(path) { | ||
| configPath = join(process.cwd(), path); | ||
| } | ||
| export function getConfigPath() { | ||
| return configPath; | ||
| } | ||
| /** | ||
@@ -22,7 +32,7 @@ * Retrieves the configuration settings based on the current environment. Reads | ||
| const environment = process.env.NODE_ENV ?? "development"; | ||
| const definedConfig = ( | ||
| await import(join("file:///", process.cwd(), "libsqlrc.js")) | ||
| ).default[environment]; | ||
| const definedConfig = (await import(join("file:///", configPath))).default[ | ||
| environment | ||
| ]; | ||
| return merge(defaultConfig, definedConfig); | ||
| } |
+1
-0
@@ -8,1 +8,2 @@ export { default as getConfig } from "./getConfig.js"; | ||
| export { default as writeFileIfNotExists } from "./writeFileIfNotExists.js"; | ||
| export { default as handleOptions } from "./handleOptions.js"; |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
35680
19.7%21
5%699
10.08%423
33.44%