diff --git a/packages/migrator/new.md b/packages/migrator/new.md
deleted file mode 100644
index 11280fe2..00000000
--- a/packages/migrator/new.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# @pgkit/migrator
-
-A migration tool for postgres, using [pgkit](https://npmjs.com/package/@pgkit/client)
-
-Features:
-
-- SQL-first - write migrations using plain-old SQL. Just write `create table ...` statements.
-- Flexible - migrations can also be written in javascript or typescript for more dynamic use-cases.
-- DDL generation - read and write from a definitions file, making it easy to see what your whole schema looks like.
-- Smart `create` - tinker with your database manually, then automatically create a migration file based on the drift.
-- `goto`: Automatic "down" migrations. Uses [migra](https://npmjs.com/package/@pgkit/migra) to go "back" to a specific migration.
-- `rebase` migrations - rewrite and squash migrations past a certain point to consolidate working changes into one.
-- `check` migrations to see if your database state matches what it should be based on the list of migrations
-- `repair` to update the database to match the state described by your migrations
-- `baseline` - mark an existing database as up-to-date, making it easy to introduce this tool to existing projects, and avoids worry about version updates.
-- Ready for distributed systems - database-level advisory locking makes it safe for multiple servers to run migrations at the same time
-- Footgun-protection - any destructive changes require explicit confirmation
-- Transaction support - apply all your migrations if they succeed, or none of them if any fail
-
-## Installation
-
-```
-npm install @pgkit/migrator
-```
-
-## Usage
-
-You can run it out of the box as a CLI:
-
-```
-npx @pgkit/migrator --help
-```
-
-```
-Commands:
- sql Query the database. Not strictly related to migrations, but can be used for debugging. Use with caution!
- up Apply pending migrations
- baseline Baseline the database at the specified migration. This forcibly edits the migrations table to mark all migrations up to this point as executed. Useful for introducing the migrator to an existing database.
- rebase Rebase the migrations from the specified migration. This deletes all migration files after this point, and replaces them with a squashed migration based on the calculated diff required to reach the current database state.
- definitions.filepath Get the path to the definitions file
- definitions.updateDb Update the database from the definitions file
- definitions.updateFile Update the definitions file from the database
- list List migrations, along with their status, file path and content
- unlock Release the advisory lock for this migrator on the database. This is useful if the migrator is stuck due to a previous crash
- latest Get the latest migration
- create Create a new migration file
- check Verify that your database is in an expected state, matching your migrations
- repair If your migrations are not in a valid state, this will calculate the diff required to move your database to a valid state, and apply it
- goto Go "back" to a specific migration. This will calculate the diff required to get to the target migration, then apply it
- wipe Wipe the database - remove all tables, views etc.
- ddl Sync the database with the definitions file
-
-Flags:
- --full-errors Throw unedited raw errors rather than summarising to make more human-readable.
- -h, --help Show help
-```
-
-## Configuration
-
-Right now, the built-in CLI is configured via environment variables.
-
-
-
-
-Environment Variable |
-Description |
-Default Value |
-
-
-
-
-PGKIT_CONNECTION_STRING |
-postgresql client connection string |
-postgresql://postgres:postgres@localhost:5432/postgres |
-
-
-PGKIT_MIGRATIONS_PATH |
-Path to folder containing migraitons scripts |
-${cwd}/migrations |
-
-
-PGKIT_MIGRATIONS_TABLE_NAME |
-Name for table to store migration history in |
-migrations |
-
-
-
-
-In future, a `pgkit.config.ts` file will (probably) be supported.
diff --git a/packages/migrator/package.json b/packages/migrator/package.json
index e155aba0..5c53c8db 100644
--- a/packages/migrator/package.json
+++ b/packages/migrator/package.json
@@ -22,11 +22,12 @@
"test": "vitest run"
},
"devDependencies": {
+ "@rebundled/execa": "8.0.2-next.2",
"@types/lodash": "^4.14.202",
"@types/node": "^20.11.10",
"dedent": "^1.5.1",
"eslint": "^8.57.0",
- "eslint-plugin-mmkal": "0.5.0",
+ "eslint-plugin-mmkal": "0.7.0",
"execa": "^8.0.1",
"fs-syncer": "^0.4.0",
"js-yaml": "^4.1.0",
@@ -46,8 +47,9 @@
"@trpc/server": "^10.45.2",
"cleye": "^1.3.2",
"picocolors": "^1.0.1",
+ "strip-ansi": "6.0.0",
"tasuku": "^2.0.1",
- "trpc-cli": "^0.1.4",
+ "trpc-cli": "^0.2.2",
"umzug": "^3.7.0",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.0",
diff --git a/packages/migrator/readme.md b/packages/migrator/readme.md
index 61fb31ce..3f8f7f18 100644
--- a/packages/migrator/readme.md
+++ b/packages/migrator/readme.md
@@ -1,6 +1,6 @@
# @pgkit/migrator
->Note: @pgkit/migrator is being re-written. See [the new docs](./new.md).
+>Note: @pgkit/migrator is being re-written. Docs are _mostly_ updated.
A cli migration tool for postgres, using [pgkit](https://npmjs.com/package/@pgkit/client).
@@ -18,359 +18,339 @@ This isn't technically a cli - it's a cli _helper_. Most node migration librarie
Contents
-
+
- [Motivation](#motivation)
+- [Installation](#installation)
- [Usage](#usage)
- - [JavaScript and TypeScript migrations](#javascript-and-typescript-migrations)
- - [Running migrations](#running-migrations)
- - [More commands](#more-commands)
- - [Controlling migrations](#controlling-migrations)
-- [Commands](#commands)
- - [up](#up)
- - [down](#down)
- - [pending](#pending)
- - [executed](#executed)
- - [create](#create)
- - [repair](#repair)
- - [Examples](#examples)
- - [Running programatically](#running-programatically)
+ - [Commands](#commands)
+ - [Command: up](#command-up)
+ - [Command: create](#command-create)
+ - [Command: list](#command-list)
+ - [Command: latest](#command-latest)
+ - [Command: check](#command-check)
+ - [Command: repair](#command-repair)
+ - [Command: goto](#command-goto)
+ - [Command: baseline](#command-baseline)
+ - [Command: rebase](#command-rebase)
+ - [Command: definitions.filepath](#command-definitionsfilepath)
+ - [Command: definitions.updateDb](#command-definitionsupdatedb)
+ - [Command: definitions.updateFile](#command-definitionsupdatefile)
+ - [Command: unlock](#command-unlock)
+ - [Command: wipe](#command-wipe)
+ - [Command: sql](#command-sql)
- [Configuration](#configuration)
-- [Implementation](#implementation)
+# @pgkit/migrator
+
+A migration tool for postgres, using [pgkit](https://npmjs.com/package/@pgkit/client)
+
+Features:
+
+- SQL-first - write migrations using plain-old SQL. Just write `create table ...` statements.
+- Flexible - migrations can also be written in javascript or typescript for more dynamic use-cases.
+- DDL generation - read and write from a definitions file, making it easy to see what your whole schema looks like.
+- Smart `create` - tinker with your database manually, then automatically create a migration file based on the drift.
+- `goto`: Automatic "down" migrations. Uses [migra](https://npmjs.com/package/@pgkit/migra) to go "back" to a specific migration.
+- `rebase` migrations - rewrite and squash migrations past a certain point to consolidate working changes into one.
+- `check` migrations to see if your database state matches what it should be based on the list of migrations
+- `repair` to update the database to match the state described by your migrations
+- `baseline` - mark an existing database as up-to-date, making it easy to introduce this tool to existing projects, and avoids worry about version updates.
+- Ready for distributed systems - database-level advisory locking makes it safe for multiple servers to run migrations at the same time
+- Footgun-protection - any destructive changes require explicit confirmation
+- Transaction support - apply all your migrations if they succeed, or none of them if any fail
+
+## Installation
+
+```
+npm install @pgkit/migrator
+```
## Usage
-```bash
-npm install --save-dev @pgkit/migrator
+You can run it out of the box as a CLI:
+
+```
+npx @pgkit/migrator --help
```
-Then in a file called `migrate.js`:
-```javascript
-const {Migrator} = require('@pgkit/migrator')
-const {createClient} = require('@pgkit/client')
+
+### Commands
-// in an existing project, this may be setup in another module
-const client = createClient(process.env.POSTGRES_CONNECTION_STRING) // e.g. 'postgresql://postgres:postgres@localhost:5433/postgres'
+- [`up`](#command-up) - Apply pending migrations
+- [`create`](#command-create) - Create a new migration file
+- [`list`](#command-list) - List migrations, along with their status, file path and content
+- [`latest`](#command-latest) - Get the latest migration
+- [`check`](#command-check) - Verify that your database is in an expected state, matching your migrations
+- [`repair`](#command-repair) - If your migrations are not in a valid state, this will calculate the diff required to move your database to a valid state, and apply it
+- [`goto`](#command-goto) - Go "back" to a specific migration. This will calculate the diff required to get to the target migration, then apply it
+- [`baseline`](#command-baseline) - Baseline the database at the specified migration. This forcibly edits the migrations table to mark all migrations up to this point as executed. Useful for introducing the migrator to an existing database.
+- [`rebase`](#command-rebase) - Rebase the migrations from the specified migration. This deletes all migration files after this point, and replaces them with a squashed migration based on the calculated diff required to reach the current database state.
+- [`definitions.filepath`](#command-definitions.filepath) - Get the path to the definitions file
+- [`definitions.updateDb`](#command-definitions.updateDb) - Update the database from the definitions file
+- [`definitions.updateFile`](#command-definitions.updateFile) - Update the definitions file from the database
+- [`unlock`](#command-unlock) - Release the advisory lock for this migrator on the database. This is useful if the migrator is stuck due to a previous crash
+- [`wipe`](#command-wipe) - Wipe the database - remove all tables, views etc.
+- [`sql`](#command-sql) - Query the database. Not strictly related to migrations, but can be used for debugging. Use with caution!
-const migrator = new Migrator({
- migrationsPath: __dirname + '/migrations',
- migrationTableName: 'migration',
- client,
- logger: Migrator.prettyLogger,
-})
+---
-migrator.runAsCLI()
-```
+### Command: up
-By calling `runAsCLI()`, `migrate.js` has now become a runnable cli script via `node migrate.js` or just `node migrate`:
+Apply pending migrations
-```bash
-node migrate create --name users.sql
-```
-This generates placeholder migration sql scripts in the directory specified by `migrationsPath` called something like `2019-06-17T03-27.users.sql` and `down/2019-06-17T03-27.users.sql`.
+#### Usage
-You can now edit the generated sql files to `create table users(name text)` for the 'up' migration and `drop table users` for the 'down' migration.
+- `up [flags...]`
-### JavaScript and TypeScript migrations
-
-These are expected to be modules with a required `up` export and an optional `down` export. Each of these functions will have an object passed to them with a client instance, and a `sql` tag function. You can see a [javascript](./test/generated/run/migrations/03.three.js) and a [typescript](./test/generated/run/migrations/04.four.ts) example in the tests.
-
-Note: if writing migrations in typescript, you will likely want to use a tool like [ts-node](https://npmjs.com/package/ts-node) to enable loading typescript modules. You can either add `require('ts-node/register/transpile-only')` at the top of your `migrate.js` file, or run `node -r ts-node/register/transpile-only migrate ...` instead of `node migrate ...`.
+#### Flags
-(Using `ts-node/register/transpile-only` performs faster than `ts-node/register`, and is safe to use if type-checking is performed separately).
+- `--step ` - Apply this many migrations; Exclusive minimum: 0
+- `--to ` - Only apply migrations up to this one
+- `-h, --help` - Show help
-**Recommendation**: where possible, it's better to use SQL migrations than JavaScript or TypeScript. They're more portable and less likely to have side-effects beyond the DB.
+---
-### Running migrations
+### Command: create
-To run all "up" migrations:
+Create a new migration file
-```bash
-node migrate up
-```
+#### Usage
-The `users` table will now have been created.
+- `create [flags...]`
-To revert the last migration:
+#### Flags
-```bash
-node migrate down
-```
+- `--content ` - SQL content of the migration. If not specified, content will be generated based on the calculated diff between the existing migrations and the current database state.
+- `--name ` - Name of the migration file. If not specified, a name will be generated based on the content of the migraiton
+- `-h, --help` - Show help
-The `users` table will now have been dropped again.
+---
-### More commands
+### Command: list
-To print the list of migrations that have already been applied:
+List migrations, along with their status, file path and content
-```bash
-node migrate executed
-```
+#### Usage
-To print the list of migrations that are due to be applied:
+- `list [flags...]`
-```bash
-node migrate pending
-```
+#### Flags
-### Controlling migrations
+- `--output ` - Result properties to return; Enum: name,path,content,object (default: "object")
+- `--query ` - Search query - migrations with names containing this string will be returned
+- `--result ` - Which result(s) to return; Enum: first,last,one,maybeOne,all (default: "all")
+- `--status ` - Filter by status; Enum: pending,executed
+- `-h, --help` - Show help
-By default, `node migrate down` reverts only the most recent migration.
+---
-It is also possible to migrate up or down "to" a specific migration. For example, if you have run migrations `one.sql`, `two.sql`, `three.sql` and `four.sql`, you can revert `three.sql` and `four.sql` by running `node migrate down --to three.sql`. Note that the range is *inclusive*. To revert all migrations in one go, run `node migrate down --to 0`. Note also that the migration names will usually contain a timestamp prefix, and can be listed with `node migrate pending` or `node migrate executed`.
+### Command: latest
-Conversely, `node migrate up` runs all `up` migrations by default. To run only up to a certain migaton, run `node migrate up --to two.sql`. This will run migrations `one.sql` and `two.sql` - again, the range is *inclusive* of the name.
+Get the latest migration
-See [commands](#commands) for more options, and [examples](#examples) to see how you can use the CLI.
+#### Usage
-
-
-## Commands
+- `latest [flags...]`
-```
-usage: node migrate [-h] ...
+#### Flags
-@pgkit/migrator - PostgreSQL migration tool
+- `--skip-check` - Skip checking that migrations are in a valid state
+- `-h, --help` - Show help
-Positional arguments:
-
- up Applies pending migrations
- down Revert migrations
- pending Lists pending migrations
- executed Lists executed migrations
- create Create a migration file
- repair Repair hashes in the migration table
+---
-Optional arguments:
- -h, --help Show this help message and exit.
+### Command: check
-For detailed help about a specific command, use: node migrate -h
-```
+Verify that your database is in an expected state, matching your migrations
-### up
+#### Usage
-```
-usage: node migrate up [-h] [--to NAME] [--step COUNT] [--name MIGRATION]
- [--rerun {THROW,SKIP,ALLOW}]
-
-
-Performs all migrations. See --help for more options
-
-Optional arguments:
- -h, --help Show this help message and exit.
- --to NAME All migrations up to and including this one should be
- applied.
- --step COUNT Run this many migrations. If not specified, all will
- be applied.
- --name MIGRATION Explicity declare migration name(s) to be applied.
- --rerun {THROW,SKIP,ALLOW}
- Specify what action should be taken when a migration
- that has already been applied is passed to --name.
- The default value is "THROW".
-```
+- `check [flags...]`
-### down
+#### Flags
-```
-usage: node migrate down [-h] [--to NAME] [--step COUNT] [--name MIGRATION]
- [--rerun {THROW,SKIP,ALLOW}]
-
-
-Undoes previously-applied migrations. By default, undoes the most recent
-migration only. Use --help for more options. Useful in development to start
-from a clean slate. Use with care in production!
-
-Optional arguments:
- -h, --help Show this help message and exit.
- --to NAME All migrations up to and including this one should be
- reverted. Pass "0" to revert all.
- --step COUNT Run this many migrations. If not specified, one will
- be reverted.
- --name MIGRATION Explicity declare migration name(s) to be reverted.
- --rerun {THROW,SKIP,ALLOW}
- Specify what action should be taken when a migration
- that has already been reverted is passed to --name.
- The default value is "THROW".
-```
+- `-h, --help` - Show help
-### pending
+---
-```
-usage: node migrate pending [-h] [--json]
+### Command: repair
-Prints migrations returned by `umzug.pending()`. By default, prints migration
-names one per line.
+If your migrations are not in a valid state, this will calculate the diff required to move your database to a valid state, and apply it
-Optional arguments:
- -h, --help Show this help message and exit.
- --json Print pending migrations in a json format including names and
- paths. This allows piping output to tools like jq. Without this
- flag, the migration names will be printed one per line.
-```
+#### Usage
-### executed
+- `repair [flags...]`
-```
-usage: node migrate executed [-h] [--json]
+#### Flags
-Prints migrations returned by `umzug.executed()`. By default, prints
-migration names one per line.
+- `-h, --help` - Show help
-Optional arguments:
- -h, --help Show this help message and exit.
- --json Print executed migrations in a json format including names and
- paths. This allows piping output to tools like jq. Without this
- flag, the migration names will be printed one per line.
-```
+---
-### create
+### Command: goto
-```
-usage: node migrate create [-h] --name NAME [--prefix {TIMESTAMP,DATE,NONE}]
- [--folder PATH] [--allow-extension EXTENSION]
- [--skip-verify] [--allow-confusing-ordering]
-
-
-Generates a placeholder migration file using a timestamp as a prefix. By
-default, mimics the last existing migration, or guesses where to generate the
-file if no migration exists yet.
-
-Optional arguments:
- -h, --help Show this help message and exit.
- --name NAME The name of the migration file. e.g. my-migration.js,
- my-migration.ts or my-migration.sql. Note - a prefix
- will be added to this name, usually based on a
- timestamp. See --prefix
- --prefix {TIMESTAMP,DATE,NONE}
- The prefix format for generated files. TIMESTAMP uses
- a second-resolution timestamp, DATE uses a
- day-resolution timestamp, and NONE removes the prefix
- completely. The default value is "TIMESTAMP".
- --folder PATH Path on the filesystem where the file should be
- created. The new migration will be created as a
- sibling of the last existing one if this is omitted.
- --allow-extension EXTENSION
- Allowable extension for created files. By default .js,
- .ts and .sql files can be created. To create txt
- file migrations, for example, you could use '--name
- my-migration.txt --allow-extension .txt' This
- parameter may alternatively be specified via the
- UMZUG_ALLOW_EXTENSION environment variable.
- --skip-verify By default, the generated file will be checked after
- creation to make sure it is detected as a pending
- migration. This catches problems like creation in the
- wrong folder, or invalid naming conventions. This
- flag bypasses that verification step.
- --allow-confusing-ordering
- By default, an error will be thrown if you try to
- create a migration that will run before a migration
- that already exists. This catches errors which can
- cause problems if you change file naming conventions.
- If you use a custom ordering system, you can disable
- this behavior, but it's strongly recommended that you
- don't! If you're unsure, just ignore this option.
-```
+Go "back" to a specific migration. This will calculate the diff required to get to the target migration, then apply it
-### repair
+#### Usage
-```
-usage: node migrate repair [-h] [-d]
+- `goto [flags...]`
-If, for any reason, the hashes are incorrectly stored in the database, you
-can recompute them using this command. Note that due to a bug in
-@pgkit/migrator v0.8.X-v0.9-X the hashes were incorrectly calculated, so
-this command is recommended after upgrading to v0.10.
+#### Flags
-Optional arguments:
- -h, --help Show this help message and exit.
- -d, --dry-run No changes are actually made
-```
-
+- `--name ` - Name of the migration to go to. Use "list" to see available migrations.
+- `-h, --help` - Show help
-### Examples
+---
-Assuming `migrate.js` is a script setup something like:
+### Command: baseline
-```js
-const {Migrator} = require('@pgkit/migrator')
+Baseline the database at the specified migration. This forcibly edits the migrations table to mark all migrations up to this point as executed. Useful for introducing the migrator to an existing database.
-const migrator = new Migrator(/* ... */)
-migrator.runAsCLI()
-```
+#### Usage
-Here are some ways you could use it:
+- `baseline [flags...]`
-```bash
-ndoe migrate --help # shows help
+#### Flags
-node migrate up # runs all pending migrations
+- `--purge-disk` - Delete files subsequent to the specified migration (optional)
+- `--to ` - Name of the migration to baseline to. Use `list` to see available migrations.
+- `-h, --help` - Show help
-node migrate down # reverts the last-run migration
+---
-node migrate down --to 0 # reverts all migrations
-node migrate up --to some-specific-migration.sql # runs all migrations up to and including some-specific-migration.sql
-node migrate down --to some-other-migration.sql # reverts all migrations down to and including some-other-migration.sql
+### Command: rebase
-node migrate up --step 2 # runs the next two migrations
-node migrate down --step 2 # reverts the two most recent migrations
+Rebase the migrations from the specified migration. This deletes all migration files after this point, and replaces them with a squashed migration based on the calculated diff required to reach the current database state.
-node migrate up --name m1.sql --name m2.sql # runs only m1.sql and m2.sql. Throws if they aren't pending.
-node migrate up --name m1.sql --name m2.sql --rerun ALLOW # runs m1.sql and m2.sql, even if they've already been executed
-node migrate up --name m1.sql --name m2.sql --rerun SKIP # runs m1.sql and m2.sql, if they haven't already been executed. Skips if they have.
+#### Usage
-node migrate down --name m1.sql --name m2.sql # reverts only m1.sql and m2.sql. Throws if they haven't been executed.
-node migrate down --name m1.sql --name m2.sql --rerun ALLOW # runs m1.sql and m2.sql, even if they haven't been executed yet.
-node migrate down --name m1.sql --name m2.sql --rerun SKIP # runs m1.sql and m2.sql, if they have already been executed. Skips if they haven't.
+- `rebase [flags...]`
-node migrate up --help # shows help for `up`
-node migrate down --help # shows help for `down`
+#### Flags
-node migrate create --name some-migration.sql # creates a new migration, prefixed with timestamp, in the migrations folder
+- `--from ` - Name of the migration to rebase from. This migration will remain, all subsequent ones will be replaced with a squashed migration. Use `list` to see available migrations.
+- `-h, --help` - Show help
-node migrate pending # lists pending migrations
-node migrate executed # lists executed migrations
+---
-node migrate repair --dry-run # logs which migrations are in need of a repair
-node migrate repair # repairs them
-```
+### Command: definitions.filepath
-### Running programatically
+Get the path to the definitions file
-To run migrations programmatically, you can import the `migrator` object from another file. For example, in a lambda handler:
+#### Usage
-```javascript
-module.exports.handler = () => require('./migrate').up()
-```
+- `definitions.filepath [flags...]`
-Or, you could write a script which seeds data in test environments:
+#### Flags
-```javascript
-import {migrator, client} from './migrate'
-import {sql} from '@pgkit/client'
+- `-h, --help` - Show help
-export const seed = async () => {
- const migrations = await migrator.up()
- if (migrations.some(m => m.file.endsWith('.users.sql'))) {
- await client.query(sql`insert into users(name) values('foo')`)
- }
-}
-```
+---
-## Configuration
+### Command: definitions.updateDb
+
+Update the database from the definitions file
+
+#### Usage
+
+- `definitions.updateDb [flags...]`
+
+#### Flags
+
+- `-h, --help` - Show help
+
+---
+
+### Command: definitions.updateFile
+
+Update the definitions file from the database
+
+#### Usage
+
+- `definitions.updateFile [flags...]`
+
+#### Flags
+
+- `-h, --help` - Show help
+
+---
+
+### Command: unlock
+
+Release the advisory lock for this migrator on the database. This is useful if the migrator is stuck due to a previous crash
-parameters for the `Migrator` constructor:
+#### Usage
-| property | description | default value |
-|--------|------------|-------------|
-| `client` | database pool instance, created by `createPool` or `createClient`. | N/A |
-| `migrationsPath` | path pointing to directory on filesystem where migration files will live. | N/A |
-| `migrationTableName` | the name for the table migrations information will be stored in. You can change this to avoid a clash with existing tables, or to conform with your team's naming standards. Set to an array to change the schema e.g. `['public', 'dbmigrations']` | N/A |
-| `logger` | how information about the migrations will be logged. You can set to `console` to log raw objects to console, `undefined` to prevent logs appearing at all, use `Migrator.prettyLogger` or supply a custom logger. | `undefined` |
+- `unlock [flags...]`
-`Migrator.prettyLogger` logs all messages to console. Known events are prettified to strings, unknown events or unexpected message properties in known events are logged as objects.
+#### Flags
-## Implementation
+- `-h, --help` - Show help
+
+---
+
+### Command: wipe
+
+Wipe the database - remove all tables, views etc.
+
+#### Usage
+
+- `wipe [flags...]`
+
+#### Flags
+
+- `-h, --help` - Show help
+
+---
+
+### Command: sql
+
+Query the database. Not strictly related to migrations, but can be used for debugging. Use with caution!
+
+#### Usage
+
+- `sql [flags...]`
+
+#### Flags
+
+- `--doublequote ` - Character to use in place of " - use to avoid having to do bash quote-escaping (optional)
+- `--method ` - Enum: any,many,one,maybeOne,query,anyFirst,oneFirst,maybeOneFirst (optional) (default: "any")
+- `--query `
+- `--singlequote ` - Character to use in place of ' - use to avoid having to do bash quote-escaping (optional)
+- `-h, --help` - Show help
+
+
+## Configuration
-Under the hood, the library thinly wraps [umzug](https://npmjs.com/package/umzug) with a custom pgkit-based storage implementation.
+Right now, the built-in CLI is configured via environment variables.
+
+
+
+
+Environment Variable |
+Description |
+Default Value |
+
+
+
+
+PGKIT_CONNECTION_STRING |
+postgresql client connection string |
+postgresql://postgres:postgres@localhost:5432/postgres |
+
+
+PGKIT_MIGRATIONS_PATH |
+Path to folder containing migraitons scripts |
+${cwd}/migrations |
+
+
+PGKIT_MIGRATIONS_TABLE_NAME |
+Name for table to store migration history in |
+migrations |
+
+
+
+
+In future, a `pgkit.config.ts` file will (probably) be supported.
diff --git a/packages/migrator/scripts/codegen.ts b/packages/migrator/scripts/codegen.ts
new file mode 100644
index 00000000..87c68892
--- /dev/null
+++ b/packages/migrator/scripts/codegen.ts
@@ -0,0 +1,101 @@
+import {execaSync} from '@rebundled/execa'
+import {CodegenPreset} from 'eslint-plugin-mmkal'
+import stripAnsi from 'strip-ansi'
+
+export const help: import('eslint-plugin-mmkal').CodegenPreset<{command?: string}> = ({options}) => {
+ const {stdout} = execaSync('./node_modules/.bin/tsx', ['src/bin', options.command!, '--help'].filter(Boolean), {
+ all: true as never,
+ })
+ const stripped = stripAnsi(stdout)
+ return [
+ `### \`${options.command || `@pgkit/migrator`}\``,
+ '',
+ '```yaml',
+ JSON.stringify(parseCLIHelp(stripped), null, 2), //
+ '```',
+ ].join('\n')
+}
+
+export const cliToMarkdown: CodegenPreset<{cli: string}> = ({options: {cli}}) => {
+ const {stdout: root} = execaSync('./node_modules/.bin/tsx', [cli, '--help'])
+
+ const rootParsed = parseCLIHelp(root)
+ delete rootParsed.sections.Flags // rm default flags
+ rootParsed.sections.Commands!.rows.forEach(row => {
+ row.link = `#command-${row.name}`
+ })
+
+ const commands = rootParsed.sections.Commands!.rows.map(cmd => {
+ const {stdout} = execaSync('./node_modules/.bin/tsx', ['src/bin', cmd.name, '--help'])
+ const parsed = parseCLIHelp(stdout)
+ const first = Object.values(parsed.sections)[0]!
+ first.title = `Command: ${first.title}`
+ parsed.sections.Flags!.rows.sort((a, b) => {
+ const scores = [a, b].map(r => (r.name.includes('--help') ? 1 : 0))
+ return scores[0]! - scores[1]!
+ })
+ return parsed
+ })
+
+ // if (Math.random()) return JSON.stringify({rootParsed}, null, 2) + '\n\n' + parsedHelpToMarkdown(rootParsed)
+
+ return [
+ parsedHelpToMarkdown(rootParsed), //
+ ...commands.map(parsedHelpToMarkdown),
+ ].join('\n\n---\n\n')
+}
+
+function parsedHelpToMarkdown(parsed: ReturnType) {
+ const sections = Object.values(parsed.sections)
+ const blocks = sections.map((section, i) => {
+ const headerLevel = i === 0 ? '###' : '####'
+ return [
+ `${headerLevel} ${section.title}`,
+ section.description,
+ section.rows
+ .map(row => {
+ let ref = `\`${row.name}\``
+ if (row.link) ref = `[${ref}](${row.link})`
+ return [`- ${ref}`, row.value].filter(Boolean).join(' - ')
+ })
+ .join('\n'),
+ ]
+ .filter(Boolean)
+ .join('\n\n')
+ })
+
+ return blocks.join('\n\n')
+}
+
+function parseCLIHelp(text: string) {
+ text = stripAnsi(text)
+ // split by lines looking like `Section:\n`, using a lookahead to include the section name in the result
+ const rawSections = text.split(/(?=\b\w+:$)/m)
+ const sections = rawSections.map((section, i) => {
+ const [head = '', ...content] = section.split(':\n').filter(Boolean)
+ const [title, ...description] = head.split('\n')
+ const body = content.join(':\n').trim()
+
+ const rows = body
+ .split('\n')
+ .map(line => line.trim())
+ .filter(Boolean)
+ .flatMap(line => {
+ const [name, value] = line.split(/ +/)
+ if (!name) return []
+ return [{name, link: '', value}]
+ })
+
+ return {
+ title: title || `Section ${i + 1}`,
+ description: description.join('\n').trim(),
+ body,
+ rows,
+ }
+ })
+
+ return {
+ raw: text,
+ sections: Object.fromEntries(sections.map(s => [s.title, s] as const)),
+ }
+}
diff --git a/packages/migrator/src/router.ts b/packages/migrator/src/router.ts
index 9a9c1b45..629dcf41 100644
--- a/packages/migrator/src/router.ts
+++ b/packages/migrator/src/router.ts
@@ -74,34 +74,6 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
- let query = input.query
- if (input.singlequote) query = query.replaceAll(input.singlequote, `'`)
- if (input.doublequote) query = query.replaceAll(input.doublequote, `"`)
-
- return ctx.migrator.client[input.method](sql.raw(query))
- }),
up: trpc.procedure
.meta({description: 'Apply pending migrations'})
.input(
@@ -116,59 +88,27 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
return ctx.migrator.up(input)
}),
- baseline: trpc.procedure
- .meta({
- description:
- 'Baseline the database at the specified migration. This forcibly edits the migrations table to mark all migrations up to this point as executed. Useful for introducing the migrator to an existing database.',
- })
- .input(
- z.object({
- to: z.string().describe('Name of the migration to baseline to. Use `list` to see available migrations.'),
- purgeDisk: z.boolean().default(false).describe('Delete files subsequent to the specified migration'),
- }),
- )
- .mutation(async ({input, ctx}) => {
- return ctx.migrator.baseline({...input, to: input.to})
- }),
- rebase: trpc.procedure
- .meta({
- description:
- 'Rebase the migrations from the specified migration. This deletes all migration files after this point, and replaces them with a squashed migration based on the calculated diff required to reach the current database state.',
- })
+ create: trpc.procedure
+ .meta({description: 'Create a new migration file'})
.input(
z.object({
- from: z
+ content: z
.string()
+ .optional()
.describe(
- 'Name of the migration to rebase from. This migration will remain, all subsequent ones will be replaced with a squashed migration. Use `list` to see available migrations.',
+ 'SQL content of the migration. If not specified, content will be generated based on the calculated diff between the existing migrations and the current database state.',
+ ),
+ name: z
+ .string()
+ .optional()
+ .describe(
+ 'Name of the migration file. If not specified, a name will be generated based on the content of the migraiton',
),
}),
)
.mutation(async ({input, ctx}) => {
- return ctx.migrator.rebase({...input, confirm: ctx.confirm})
+ return ctx.migrator.create(input)
}),
- definitions: trpc.router({
- filepath: trpc.procedure
- .meta({
- description: 'Get the path to the definitions file',
- })
- .query(async ({ctx}) => {
- return {
- path: ctx.migrator.definitionsFile,
- content: await readFile(ctx.migrator.definitionsFile, 'utf8'),
- }
- }),
- updateDb: trpc.procedure
- .meta({description: 'Update the database from the definitions file'})
- .mutation(async ({ctx}) => {
- return ctx.migrator.updateDBFromDDL({confirm: ctx.confirm})
- }),
- updateFile: trpc.procedure
- .meta({description: 'Update the definitions file from the database'})
- .mutation(async ({ctx}) => {
- return ctx.migrator.updateDDLFromDB()
- }),
- }),
list: trpc.procedure
.meta({
description: 'List migrations, along with their status, file path and content',
@@ -218,14 +158,6 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
- return ctx.migrator.unlock({confirm: ctx.confirm})
- }),
latest: trpc.procedure
.meta({
description: 'Get the latest migration',
@@ -238,27 +170,6 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
return ctx.migrator.latest(input)
}),
- create: trpc.procedure
- .meta({description: 'Create a new migration file'})
- .input(
- z.object({
- content: z
- .string()
- .optional()
- .describe(
- 'SQL content of the migration. If not specified, content will be generated based on the calculated diff between the existing migrations and the current database state.',
- ),
- name: z
- .string()
- .optional()
- .describe(
- 'Name of the migration file. If not specified, a name will be generated based on the content of the migraiton',
- ),
- }),
- )
- .mutation(async ({input, ctx}) => {
- return ctx.migrator.create(input)
- }),
check: trpc.procedure
.meta({description: 'Verify that your database is in an expected state, matching your migrations'})
.mutation(async ({ctx}) => {
@@ -285,6 +196,67 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
return ctx.migrator.goto({name: input.name, confirm: ctx.confirm})
}),
+ baseline: trpc.procedure
+ .meta({
+ description:
+ 'Baseline the database at the specified migration. This forcibly edits the migrations table to mark all migrations up to this point as executed. Useful for introducing the migrator to an existing database.',
+ })
+ .input(
+ z.object({
+ to: z.string().describe('Name of the migration to baseline to. Use `list` to see available migrations.'),
+ purgeDisk: z.boolean().default(false).describe('Delete files subsequent to the specified migration'),
+ }),
+ )
+ .mutation(async ({input, ctx}) => {
+ return ctx.migrator.baseline({...input, to: input.to})
+ }),
+ rebase: trpc.procedure
+ .meta({
+ description:
+ 'Rebase the migrations from the specified migration. This deletes all migration files after this point, and replaces them with a squashed migration based on the calculated diff required to reach the current database state.',
+ })
+ .input(
+ z.object({
+ from: z
+ .string()
+ .describe(
+ 'Name of the migration to rebase from. This migration will remain, all subsequent ones will be replaced with a squashed migration. Use `list` to see available migrations.',
+ ),
+ }),
+ )
+ .mutation(async ({input, ctx}) => {
+ return ctx.migrator.rebase({...input, confirm: ctx.confirm})
+ }),
+ definitions: trpc.router({
+ filepath: trpc.procedure
+ .meta({
+ description: 'Get the path to the definitions file',
+ })
+ .query(async ({ctx}) => {
+ return {
+ path: ctx.migrator.definitionsFile,
+ content: await readFile(ctx.migrator.definitionsFile, 'utf8'),
+ }
+ }),
+ updateDb: trpc.procedure
+ .meta({description: 'Update the database from the definitions file'})
+ .mutation(async ({ctx}) => {
+ return ctx.migrator.updateDBFromDDL({confirm: ctx.confirm})
+ }),
+ updateFile: trpc.procedure
+ .meta({description: 'Update the definitions file from the database'})
+ .mutation(async ({ctx}) => {
+ return ctx.migrator.updateDDLFromDB()
+ }),
+ }),
+ unlock: trpc.procedure
+ .meta({
+ description:
+ 'Release the advisory lock for this migrator on the database. This is useful if the migrator is stuck due to a previous crash',
+ })
+ .mutation(async ({ctx}) => {
+ return ctx.migrator.unlock({confirm: ctx.confirm})
+ }),
wipe: trpc.procedure
.meta({
description: 'Wipe the database - remove all tables, views etc.',
@@ -292,6 +264,34 @@ export const createMigratorRouter = (procedure: TRPCProcedureLike {
return ctx.migrator.wipe({confirm: ctx.confirm})
}),
+ sql: trpc.procedure
+ .meta({
+ description:
+ 'Query the database. Not strictly related to migrations, but can be used for debugging. Use with caution!',
+ })
+ .input(
+ z.object({
+ query: z.string(),
+ singlequote: z
+ .string()
+ .describe("Character to use in place of ' - use to avoid having to do bash quote-escaping")
+ .optional(),
+ doublequote: z
+ .string()
+ .describe('Character to use in place of " - use to avoid having to do bash quote-escaping')
+ .optional(),
+ method: z
+ .enum(['any', 'many', 'one', 'maybeOne', 'query', 'anyFirst', 'oneFirst', 'maybeOneFirst'])
+ .default('any'),
+ }),
+ )
+ .mutation(async ({input, ctx}) => {
+ let query = input.query
+ if (input.singlequote) query = query.replaceAll(input.singlequote, `'`)
+ if (input.doublequote) query = query.replaceAll(input.doublequote, `"`)
+
+ return ctx.migrator.client[input.method](sql.raw(query))
+ }),
})
return router
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dfc187e1..817a0049 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -434,7 +434,7 @@ importers:
version: 15.2.0
tsup:
specifier: ^8.0.1
- version: 8.0.1(typescript@5.3.3)
+ version: 8.0.1(ts-node@10.9.2)(typescript@5.3.3)
tsx:
specifier: ^4.7.1
version: 4.7.1
@@ -465,12 +465,15 @@ importers:
picocolors:
specifier: ^1.0.1
version: 1.0.1
+ strip-ansi:
+ specifier: 6.0.0
+ version: 6.0.0
tasuku:
specifier: ^2.0.1
version: 2.0.1
trpc-cli:
- specifier: ^0.1.4
- version: 0.1.4(@trpc/server@10.45.2)(zod@3.23.8)
+ specifier: ^0.2.2
+ version: 0.2.2(@trpc/server@10.45.2)(zod@3.23.8)
umzug:
specifier: ^3.7.0
version: 3.7.0
@@ -484,6 +487,9 @@ importers:
specifier: ^3.3.0
version: 3.3.0(zod@3.23.8)
devDependencies:
+ '@rebundled/execa':
+ specifier: 8.0.2-next.2
+ version: 8.0.2-next.2
'@types/lodash':
specifier: ^4.14.202
version: 4.14.202
@@ -497,8 +503,8 @@ importers:
specifier: ^8.57.0
version: 8.57.0
eslint-plugin-mmkal:
- specifier: 0.5.0
- version: 0.5.0(eslint@8.57.0)(typescript@5.3.3)(vitest@1.2.2)
+ specifier: 0.7.0
+ version: 0.7.0(eslint@8.57.0)(typescript@5.3.3)(vitest@1.2.2)
execa:
specifier: ^8.0.1
version: 8.0.1
@@ -1671,6 +1677,12 @@ packages:
dev: true
optional: true
+ /@next/eslint-plugin-next@14.2.3:
+ resolution: {integrity: sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==}
+ dependencies:
+ glob: 10.3.10
+ dev: true
+
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@@ -2920,6 +2932,20 @@ packages:
signal-exit: 4.1.0
strip-final-newline: 4.0.0
+ /@rebundled/execa@8.0.2-next.2:
+ resolution: {integrity: sha512-S3rd39mObqtVaXqShfiSiYf4F1pUjSXyONfk+VRvsrQt2i1pFTZZIEm7yGyplzPcWefY8/dA/XSivCMVkMGMHQ==}
+ engines: {node: '>=18'}
+ dependencies:
+ '@sindresorhus/merge-streams': 2.2.0
+ cross-spawn: 7.0.3
+ get-stream: 8.0.1
+ human-signals: 6.0.0
+ is-stream: 3.0.0
+ npm-run-path: 5.2.0
+ signal-exit: 4.1.0
+ strip-final-newline: 4.0.0
+ dev: true
+
/@rollup/rollup-android-arm-eabi@4.9.6:
resolution: {integrity: sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==}
cpu: [arm]
@@ -3678,34 +3704,6 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/eslint-plugin@7.3.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3):
- resolution: {integrity: sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==}
- engines: {node: ^18.18.0 || >=20.0.0}
- peerDependencies:
- '@typescript-eslint/parser': ^7.0.0
- eslint: ^8.56.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
- dependencies:
- '@eslint-community/regexpp': 4.10.0
- '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3)
- '@typescript-eslint/scope-manager': 7.3.1
- '@typescript-eslint/type-utils': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
- '@typescript-eslint/utils': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
- '@typescript-eslint/visitor-keys': 7.3.1
- debug: 4.3.4
- eslint: 8.57.0
- graphemer: 1.4.0
- ignore: 5.3.1
- natural-compare: 1.4.0
- semver: 7.6.0
- ts-api-utils: 1.3.0(typescript@5.3.3)
- typescript: 5.3.3
- transitivePeerDependencies:
- - supports-color
-
/@typescript-eslint/eslint-plugin@7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3):
resolution: {integrity: sha512-STEDMVQGww5lhCuNXVSQfbfuNII5E08QWkvAw5Qwf+bj2WT+JkG1uc+5/vXA3AOYMDHVOSpL+9rcbEUiHIm2dw==}
engines: {node: ^18.18.0 || >=20.0.0}
@@ -3785,6 +3783,7 @@ packages:
typescript: 5.3.3
transitivePeerDependencies:
- supports-color
+ dev: true
/@typescript-eslint/parser@7.3.1(eslint@8.57.0)(typescript@5.3.3):
resolution: {integrity: sha512-Rq49+pq7viTRCH48XAbTA+wdLRrB/3sRq4Lpk0oGDm0VmnjBrAOVXH/Laalmwsv2VpekiEfVFwJYVk6/e8uvQw==}
@@ -3840,6 +3839,7 @@ packages:
dependencies:
'@typescript-eslint/types': 7.1.0
'@typescript-eslint/visitor-keys': 7.1.0
+ dev: true
/@typescript-eslint/scope-manager@7.3.1:
resolution: {integrity: sha512-fVS6fPxldsKY2nFvyT7IP78UO1/I2huG+AYu5AMjCT9wtl6JFiDnsv4uad4jQ0GTFzcUV5HShVeN96/17bTBag==}
@@ -3925,6 +3925,7 @@ packages:
/@typescript-eslint/types@7.1.0:
resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==}
engines: {node: ^16.0.0 || >=18.0.0}
+ dev: true
/@typescript-eslint/types@7.3.1:
resolution: {integrity: sha512-2tUf3uWggBDl4S4183nivWQ2HqceOZh1U4hhu4p1tPiIJoRRXrab7Y+Y0p+dozYwZVvLPRI6r5wKe9kToF9FIw==}
@@ -4032,6 +4033,7 @@ packages:
typescript: 5.3.3
transitivePeerDependencies:
- supports-color
+ dev: true
/@typescript-eslint/typescript-estree@7.3.1(typescript@5.3.3):
resolution: {integrity: sha512-tLpuqM46LVkduWP7JO7yVoWshpJuJzxDOPYIVWUUZbW+4dBpgGeUdl/fQkhuV0A8eGnphYw3pp8d2EnvPOfxmQ==}
@@ -4199,6 +4201,7 @@ packages:
dependencies:
'@typescript-eslint/types': 7.1.0
eslint-visitor-keys: 3.4.3
+ dev: true
/@typescript-eslint/visitor-keys@7.3.1:
resolution: {integrity: sha512-9RMXwQF8knsZvfv9tdi+4D/j7dMG28X/wMJ8Jj6eOHyHWwDW4ngQJcqEczSsqIKKjFiLFr40Mnr7a5ulDD3vmw==}
@@ -5994,7 +5997,7 @@ packages:
eslint: '>=8.0.0'
typescript: '>=4.7'
dependencies:
- '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3)
+ '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
'@typescript-eslint/parser': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
eslint: 8.57.0
typescript: 5.3.3
@@ -6059,7 +6062,7 @@ packages:
'@types/glob': 7.1.3
'@types/js-yaml': 3.12.5
'@types/lodash': 4.14.202
- '@types/node': 20.11.21
+ '@types/node': 20.12.12
dedent: 1.5.1
eslint-plugin-markdown: 4.0.1(eslint@8.57.0)
expect: 29.7.0
@@ -6143,7 +6146,7 @@ packages:
jest:
optional: true
dependencies:
- '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3)
+ '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
'@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.3.3)
eslint: 8.57.0
transitivePeerDependencies:
@@ -6195,7 +6198,51 @@ packages:
'@rushstack/eslint-plugin-packlets': 0.8.1(eslint@8.57.0)(typescript@5.3.3)
'@rushstack/eslint-plugin-security': 0.7.1(eslint@8.57.0)(typescript@5.3.3)
'@types/eslint': 8.56.6
- '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3)
+ '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
+ '@typescript-eslint/parser': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
+ eslint-config-prettier: 9.1.0(eslint@8.57.0)
+ eslint-config-xo: 0.43.1(eslint@8.57.0)
+ eslint-config-xo-react: 0.27.0(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.34.1)(eslint@8.57.0)
+ eslint-config-xo-typescript: 1.0.1(@typescript-eslint/eslint-plugin@7.3.1)(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
+ eslint-plugin-codegen: 0.28.0(eslint@8.57.0)
+ eslint-plugin-functional: 6.1.1(eslint@8.57.0)(typescript@5.3.3)
+ eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)
+ eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
+ eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
+ eslint-plugin-markdown: 4.0.1(eslint@8.57.0)
+ eslint-plugin-prettier: 5.1.3(@types/eslint@8.56.6)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5)
+ eslint-plugin-promise: 6.1.1(eslint@8.57.0)
+ eslint-plugin-react: 7.34.1(eslint@8.57.0)
+ eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0)
+ eslint-plugin-unicorn: 49.0.0(eslint@8.57.0)
+ eslint-plugin-vitest: 0.3.26(@typescript-eslint/eslint-plugin@7.3.1)(eslint@8.57.0)(typescript@5.3.3)(vitest@1.2.2)
+ eslint-plugin-wrapper: 0.1.0-1
+ globals: 14.0.0
+ lodash: 4.17.21
+ prettier: 3.2.5
+ typescript-eslint: 7.3.1(eslint@8.57.0)(typescript@5.3.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - eslint
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - jest
+ - supports-color
+ - typescript
+ - vitest
+
+ /eslint-plugin-mmkal@0.7.0(eslint@8.57.0)(typescript@5.3.3)(vitest@1.2.2):
+ resolution: {integrity: sha512-1AO+XgJU0Lzwyklx8fnWt3Tb49404lEC/z9kODnwp7PewaWaCtjqQsnuxB7AxrDBelwLd3A/hKcFtub2syHHtg==}
+ engines: {node: '>=18'}
+ dependencies:
+ '@eslint/js': 8.57.0
+ '@next/eslint-plugin-next': 14.2.3
+ '@rushstack/eslint-config': 3.6.5(eslint@8.57.0)(typescript@5.3.3)
+ '@rushstack/eslint-plugin': 0.13.1(eslint@8.57.0)(typescript@5.3.3)
+ '@rushstack/eslint-plugin-packlets': 0.8.1(eslint@8.57.0)(typescript@5.3.3)
+ '@rushstack/eslint-plugin-security': 0.7.1(eslint@8.57.0)(typescript@5.3.3)
+ '@types/eslint': 8.56.6
+ '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
'@typescript-eslint/parser': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
eslint-config-prettier: 9.1.0(eslint@8.57.0)
eslint-config-xo: 0.43.1(eslint@8.57.0)
@@ -6227,6 +6274,7 @@ packages:
- supports-color
- typescript
- vitest
+ dev: true
/eslint-plugin-prettier@5.1.3(@types/eslint@8.56.6)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5):
resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
@@ -6367,7 +6415,7 @@ packages:
vitest:
optional: true
dependencies:
- '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.1.0)(eslint@8.57.0)(typescript@5.3.3)
+ '@typescript-eslint/eslint-plugin': 7.3.1(@typescript-eslint/parser@7.3.1)(eslint@8.57.0)(typescript@5.3.3)
'@typescript-eslint/utils': 7.3.1(eslint@8.57.0)(typescript@5.3.3)
eslint: 8.57.0
vitest: 1.2.2(@types/node@20.11.17)
@@ -10751,6 +10799,12 @@ packages:
ansi-regex: 4.1.1
dev: true
+ /strip-ansi@6.0.0:
+ resolution: {integrity: sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -11055,8 +11109,8 @@ packages:
hasBin: true
dev: true
- /trpc-cli@0.1.4(@trpc/server@10.45.2)(zod@3.23.8):
- resolution: {integrity: sha512-GFCdsx+A+72rsPIM4MBAYWDxeKghhb/lK1WjsAIDiD8fwrrfZtHWybujGbie5DUCW/cGWed1qSojfsIRGIeXUg==}
+ /trpc-cli@0.2.1(@trpc/server@10.45.2)(zod@3.23.8):
+ resolution: {integrity: sha512-HJzmLbdbj2CcdP7XCj+TAWvVNSbnhiLIaRUI67v4qmpHJoXgHisseih4Kap6WvC/CVYvuAieB0TNV0etEIf44Q==}
engines: {node: '>=18'}
peerDependencies:
'@trpc/server': '>=10'
@@ -11070,8 +11124,8 @@ packages:
zod-validation-error: 3.3.0(zod@3.23.8)
dev: false
- /trpc-cli@0.2.1(@trpc/server@10.45.2)(zod@3.23.8):
- resolution: {integrity: sha512-HJzmLbdbj2CcdP7XCj+TAWvVNSbnhiLIaRUI67v4qmpHJoXgHisseih4Kap6WvC/CVYvuAieB0TNV0etEIf44Q==}
+ /trpc-cli@0.2.2(@trpc/server@10.45.2)(zod@3.23.8):
+ resolution: {integrity: sha512-+NypGyxu3reFxq+CSPQVbcqrqIKQCdFc6arlTMbF2OfUhYwUGpeWf+uU3KsanVPb85EgI9sGiXtmuhkbxyuZmg==}
engines: {node: '>=18'}
peerDependencies:
'@trpc/server': '>=10'
@@ -11277,45 +11331,6 @@ packages:
- ts-node
dev: true
- /tsup@8.0.1(typescript@5.3.3):
- resolution: {integrity: sha512-hvW7gUSG96j53ZTSlT4j/KL0q1Q2l6TqGBFc6/mu/L46IoNWqLLUzLRLP1R8Q7xrJTmkDxxDoojV5uCVs1sVOg==}
- engines: {node: '>=18'}
- hasBin: true
- peerDependencies:
- '@microsoft/api-extractor': ^7.36.0
- '@swc/core': ^1
- postcss: ^8.4.12
- typescript: '>=4.5.0'
- peerDependenciesMeta:
- '@microsoft/api-extractor':
- optional: true
- '@swc/core':
- optional: true
- postcss:
- optional: true
- typescript:
- optional: true
- dependencies:
- bundle-require: 4.0.2(esbuild@0.19.12)
- cac: 6.7.14
- chokidar: 3.6.0
- debug: 4.3.4
- esbuild: 0.19.12
- execa: 5.1.1
- globby: 11.1.0
- joycon: 3.1.1
- postcss-load-config: 4.0.2(postcss@8.4.38)
- resolve-from: 5.0.0
- rollup: 4.9.6
- source-map: 0.8.0-beta.0
- sucrase: 3.35.0
- tree-kill: 1.2.2
- typescript: 5.3.3
- transitivePeerDependencies:
- - supports-color
- - ts-node
- dev: true
-
/tsutils@3.21.0(typescript@5.3.3):
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
@@ -12402,7 +12417,7 @@ packages:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
- strip-ansi: 6.0.1
+ strip-ansi: 6.0.0
/wrap-ansi@8.1.0:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}