diff --git a/.eslintignore b/.eslintignore
index c13a17faa..be4acda78 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -8,3 +8,4 @@ examples
**/playground
integration-tests/tests/prisma/*/client
integration-tests/tests/prisma/*/drizzle
+drizzle-kit/*
diff --git a/.github/workflows/release-feature-branch.yaml b/.github/workflows/release-feature-branch.yaml
index cce886c3a..5c2d76fb7 100644
--- a/.github/workflows/release-feature-branch.yaml
+++ b/.github/workflows/release-feature-branch.yaml
@@ -14,6 +14,7 @@ jobs:
matrix:
package:
- drizzle-orm
+ - drizzle-kit
- drizzle-zod
- drizzle-typebox
- drizzle-valibot
@@ -135,12 +136,6 @@ jobs:
cd drizzle-orm
pnpm prisma generate --schema src/prisma/schema.prisma
)
- (
- cd integration-tests
- pnpm prisma generate --schema tests/prisma/pg/schema.prisma
- pnpm prisma generate --schema tests/prisma/mysql/schema.prisma
- pnpm prisma generate --schema tests/prisma/sqlite/schema.prisma
- )
pnpm build
- name: Run tests
diff --git a/.github/workflows/release-latest.yaml b/.github/workflows/release-latest.yaml
index b801c6824..d81a0bcab 100644
--- a/.github/workflows/release-latest.yaml
+++ b/.github/workflows/release-latest.yaml
@@ -10,6 +10,7 @@ jobs:
matrix:
package:
- drizzle-orm
+ - drizzle-kit
- drizzle-zod
- drizzle-typebox
- drizzle-valibot
@@ -138,12 +139,6 @@ jobs:
cd drizzle-orm
pnpm prisma generate --schema src/prisma/schema.prisma
)
- (
- cd integration-tests
- pnpm prisma generate --schema tests/prisma/pg/schema.prisma
- pnpm prisma generate --schema tests/prisma/mysql/schema.prisma
- pnpm prisma generate --schema tests/prisma/sqlite/schema.prisma
- )
pnpm build
- name: Run tests
@@ -232,3 +227,35 @@ jobs:
} catch (e) {
core.setFailed(e.message);
}
+
+ - name: Create GitHub release for KIT package
+ uses: actions/github-script@v6
+ if: matrix.package == 'drizzle-kit' && steps.checks.outputs.has_new_release == 'true'
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ try {
+ const fs = require("fs");
+ const path = require("path");
+
+ const version = "${{ steps.checks.outputs.version }}";
+ const changelog = fs.readFileSync("${{ steps.checks.outputs.changelog_path }}", "utf8");
+
+ const release = await github.rest.repos.createRelease({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ tag_name: `drizzle-kit@${version}`,
+ name: `drizzle-kit@${version}`,
+ body: changelog,
+ });
+
+ await github.rest.repos.uploadReleaseAsset({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ release_id: release.data.id,
+ name: `${{ matrix.package }}-${version}-dist.tgz`,
+ data: fs.readFileSync(path.resolve("${{ matrix.package }}", "package.tgz")),
+ });
+ } catch (e) {
+ core.setFailed(e.message);
+ }
\ No newline at end of file
diff --git a/.github/workflows/unpublish-release-feature-branch.yaml b/.github/workflows/unpublish-release-feature-branch.yaml
index 1f0d30624..44542c24e 100644
--- a/.github/workflows/unpublish-release-feature-branch.yaml
+++ b/.github/workflows/unpublish-release-feature-branch.yaml
@@ -9,6 +9,7 @@ jobs:
matrix:
package:
- drizzle-orm
+ - drizzle-kit
- drizzle-zod
- drizzle-typebox
- drizzle-valibot
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8b289dc2e..a5f91755e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -39,25 +39,27 @@ There are several ways how you can provide a feedback
---
-- [Contributing](#contributing)
- - [Submitting bug report](#-submitting-bug-report)
- - [Submitting feature request](#-submitting-feature-request)
- - [Providing feedback](#-providing-feedback)
- - [Contribution guidelines](#-contribution-guidelines)
- - [General setup](#-general-setup)
- - [Installing node](#-installing-node)
- - [Install pnpm](#-install-pnpm)
- - [Install docker](#-install-docker)
- - [Local project setup](#-local-project-setup)
- - [Clone project](#-clone-project)
- - [Building project](#-building-project)
- - [Build project](#-build-project)
- - [Run tests](#-run-tests)
- - [Commits and PRs](#-commits-and-prs)
- - [Commit guideline](#-commit-guideline)
+- [Pre-Contribution setup](#pre-contribution)
+ - [Installing node](#-installing-node)
+ - [Install pnpm](#-install-pnpm)
+ - [Install docker](#-install-docker)
+ - [Clone project](#-clone-project)
+ - [Repository Structure](#repo-structure)
+ - [Build project](#-build-project)
+- [Contributing to `drizzle-orm`](#contributing-orm)
+ - [Project structure](#project-structure-orm)
+ - [Run tests](#run-tests-orm)
+ - [Commits and PRs](#commits-and-prs-orm)
+ - [Commit guideline](#commit-guideline-orm)
+ - [PR guideline](#pr-guideline-orm)
+- [Contributing to `drizzle-kit`](#contributing-kit)
+ - [Project structure](#project-structure-kit)
+ - [Run tests](#run-tests-kit)
+ - [Commits and PRs](#commits-and-prs-kit)
+ - [Commit guideline](#commit-guideline-kit)
- [PR guideline](#-pr-guideline)
-## General setup
+## Pre-Contribution setup
### Installing node
@@ -99,14 +101,22 @@ git clone https://github.com/drizzle-team/drizzle-orm.git
cd drizzle-orm
```
-## Building project
+### Repository Structure
```
-Project sctructure
+📂 drizzle-orm/ - orm core package with all main logic for each dialect
-📂 drizzle-orm/ - core package with all main logic for each dialect
+📂 drizzle-kit/ - kit core package with all main logic and tests for each dialect
-📂 changelogs/ - all changelogs for drizzle-orm module
+📂 drizzle-typebox/ - all the code related to drizzle+typebox extension
+
+📂 drizzle-valibot/ - all the code related to drizzle+valibot extension
+
+📂 drizzle-zod/ - all the code related to drizzle+zod extension
+
+📂 eslint-plugin-drizzle/ - all the code related to drizzle eslint plugin
+
+📂 changelogs/ - all changelogs for drizzle-orm, drizzle-kit, drizzle-typebox, drizzle-zod, drizzle-valibot modules
📂 examples/ - package with Drizzle ORM usage examples
@@ -119,7 +129,21 @@ Project sctructure
- `"pnpm i && pnpm build"` -> if you run this script from root folder - it will build whole monorepo. Running this script from specific package folder will only build current package
-### Run tests
+## Contributing to `drizzle-orm`
+
+### Project structure
+
+```
+Project structure
+
+📂 pg-core, mysql-core, sqlite-core - core packages for each dialect with all the main logic for relation and query builder
+
+📂 sql/ - package containing all expressions and SQL template implementation
+
+All other folders are for specific drivers that Drizzle ORM supports.
+```
+
+### Run tests
---
All tests for Drizzle ORM are integration tests, that are simulating real database and different queries and responses from database. Each file in `integration-tests` has a list of different scenarios for different dialect+driver. Each file is creating a docker instance with needed database and running test cases there. Right after all tests were run - docker container with database will be deleted
@@ -130,9 +154,9 @@ If you have added additional logic to core package - make sure that all tests we
- `"cd integration-tests && pnpm test"` -> will run all tests in integration test folder
-## Commits and PRs
+## Commits and PRs
-### Commit guideline
+### Commit guideline
---
@@ -160,7 +184,7 @@ In specific case, groupBy was responding with unreadable error
> **Warning**:
> All commits should be signed, before submitting PR. Please check detailed info on [how to sign commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
-### PR guideline
+### PR guideline
---
@@ -183,3 +207,91 @@ Example
- Tests on bugs, that was fixed;
To understand how test should be created and run - please check [Run tests](#-run-tests) section
+
+
+## Contributing to `drizzle-kit`
+
+### Project structure
+
+```
+📂 cli/
+ |
+ | -> 📄 schema.ts - all the commands defined using brocli
+ |
+ | -> 📂 commands - all the business logic for drizzle-kit commands
+
+📂 extensions/ - all the extension helpers for databases
+
+📂 serialaizer/ - all the necessary logic to read from the Drizzle ORM schema and convert it to a common JSON format, as well as the logic to introspect all tables, types, and other database elements and convert them to a common JSON format
+
+📄 introspect-pg.ts, introspect-mysql.ts, introspect-sqlite.ts - these files are responsible for mapping JSON snapshots to TypeScript files during introspect commands
+
+📄 snapshotsDiffer.ts - this file handles the mapping from JSON snapshot format to JSON statement objects.
+
+📄 jsonStatements.ts - this file defines JSON statement types, interfaces, and helper functions.
+
+📄 sqlgenerator.ts - this file converts JSON statements to SQL strings.
+```
+
+### Run tests
+
+---
+All tests for Drizzle Kit are integration tests, that are simulating real database and different queries and responses from database. Each file in `drizzle-kit/tests` has a list of different scenarios for different commands. Each MySQL file is creating a docker instance with needed database and running test cases there. Right after all tests were run - docker container with database will be deleted. For PostgreSQL we are using PgLite and for SQLite we are using SQLite files.
+
+If you are in the root of repo:
+
+- `"cd drizzle-kit && pnpm test"` -> will run all tests
+
+## Commits and PRs
+
+### Commit guideline
+
+---
+
+We have specific rules on how commit messages should be structured.
+
+It's important to make sure your commit messages are clear, concise, and informative to make it easier for others to understand the changes you are making
+
+Commit message pattern
+
+```
+
+
+
+```
+
+Example
+
+```
+Add groupBy error message
+
+In specific case, groupBy was responding with unreadable error
+...
+```
+
+> **Warning**:
+> All commits should be signed, before submitting PR. Please check detailed info on [how to sign commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
+
+### PR guideline
+
+---
+
+1. PR should be created with specific name pattern
+
+```
+[-kit]:
+```
+
+Example
+
+```
+[Pg-kit] Add PostGIS extension support
+```
+
+2. PR should contain detailed description with everything, that was changed
+
+3. Each PR should contain
+ - Tests on feature, that was created;
+ - Tests on bugs, that was fixed;
+
+To understand how test should be created and run - please check [Run tests](#run-tests) section
diff --git a/changelogs/drizzle-kit/0.23.2.md b/changelogs/drizzle-kit/0.23.2.md
new file mode 100644
index 000000000..c69643b8a
--- /dev/null
+++ b/changelogs/drizzle-kit/0.23.2.md
@@ -0,0 +1,2 @@
+- Fixed a bug in PostgreSQL with push and introspect where the `schemaFilter` object was passed. It was detecting enums even in schemas that were not defined in the schemaFilter.
+- Fixed the `drizzle-kit up` command to work as expected, starting from the sequences release.
diff --git a/changelogs/drizzle-kit/0.24.0.md b/changelogs/drizzle-kit/0.24.0.md
new file mode 100644
index 000000000..b766e018b
--- /dev/null
+++ b/changelogs/drizzle-kit/0.24.0.md
@@ -0,0 +1,24 @@
+## Breaking changes (for SQLite users)
+
+#### Fixed [Composite primary key order is not consistent](https://github.com/drizzle-team/drizzle-kit-mirror/issues/342) by removing `sort` in SQLite and to be consistant with the same logic in PostgreSQL and MySQL
+
+The issue that may arise for SQLite users with any driver using composite primary keys is that the order in the database may differ from the Drizzle schema.
+
+- If you are using `push`, you **MAY** be prompted to update your table with a new order of columns in the composite primary key. You will need to either change it manually in the database or push the changes, but this may lead to data loss, etc.
+
+- If you are using `generate`, you **MAY** also be prompted to update your table with a new order of columns in the composite primary key. You can either keep that migration or skip it by emptying the SQL migration file.
+
+If nothing works for you and you are blocked, please reach out to me @AndriiSherman. I will try to help you!
+
+
+## Bug fixes
+
+- [[BUG] When using double type columns, import is not inserted](https://github.com/drizzle-team/drizzle-kit-mirror/issues/403) - thanks @Karibash
+- [[BUG] A number value is specified as the default for a column of type char](https://github.com/drizzle-team/drizzle-kit-mirror/issues/404) - thanks @Karibash
+- [[BUG]: Array default in migrations are wrong](https://github.com/drizzle-team/drizzle-orm/issues/2621) - thanks @L-Mario564
+- [[FEATURE]: Simpler default array fields](https://github.com/drizzle-team/drizzle-orm/issues/2709) - thanks @L-Mario564
+- [[BUG]: drizzle-kit generate succeeds but generates invalid SQL for default([]) - Postgres](https://github.com/drizzle-team/drizzle-orm/issues/2432) - thanks @L-Mario564
+- [[BUG]: Incorrect type for array column default value](https://github.com/drizzle-team/drizzle-orm/issues/2334) - thanks @L-Mario564
+- [[BUG]: error: column is of type integer[] but default expression is of type integer](https://github.com/drizzle-team/drizzle-orm/issues/2224) - thanks @L-Mario564
+- [[BUG]: Default value in array generating wrong migration file](https://github.com/drizzle-team/drizzle-orm/issues/1003) - thanks @L-Mario564
+- [[BUG]: enum as array, not possible?](https://github.com/drizzle-team/drizzle-orm/issues/1564) - thanks @L-Mario564
\ No newline at end of file
diff --git a/changelogs/drizzle-kit/0.24.1.md b/changelogs/drizzle-kit/0.24.1.md
new file mode 100644
index 000000000..d70f6ebbe
--- /dev/null
+++ b/changelogs/drizzle-kit/0.24.1.md
@@ -0,0 +1,32 @@
+## Bug fixes
+
+> Big thanks to @L-Mario564 for his [PR](https://github.com/drizzle-team/drizzle-orm/pull/2804). It conflicted in most cases with a PR that was merged, but we incorporated some of his logic. Merging it would have caused more problems and taken more time to resolve, so we just took a few things from his PR, like removing "::" mappings in introspect and some array type default handlers
+
+### What was fixed
+
+1. The Drizzle Kit CLI was not working properly for the `introspect` command.
+2. Added the ability to use column names with special characters for all dialects.
+3. Included PostgreSQL sequences in the introspection process.
+4. Reworked array type introspection and added all test cases.
+5. Fixed all (we hope) default issues in PostgreSQL, where `::` was included in the introspected output.
+6. `preserve` casing option was broken
+
+### Tickets that were closed
+
+- [[BUG]: invalid schema generation with drizzle-kit introspect:pg](https://github.com/drizzle-team/drizzle-orm/issues/1210)
+- [[BUG][mysql introspection]: TS error when introspect column including colon](https://github.com/drizzle-team/drizzle-orm/issues/1928)
+- [[BUG]: Unhandled defaults when introspecting postgres db](https://github.com/drizzle-team/drizzle-orm/issues/1625)
+- [[BUG]: PostgreSQL Enum Naming and Schema Typing Issue](https://github.com/drizzle-team/drizzle-orm/issues/2315)
+- [[BUG]: drizzle-kit instrospect command generates syntax error on varchar column types](https://github.com/drizzle-team/drizzle-orm/issues/2714)
+- [[BUG]: Introspecting varchar[] type produces syntactically invalid schema.ts](https://github.com/drizzle-team/drizzle-orm/issues/1633)
+- [[BUG]: introspect:pg column not using generated enum name](https://github.com/drizzle-team/drizzle-orm/issues/1648)
+- [[BUG]: drizzle-kit introspect casing "preserve" config not working](https://github.com/drizzle-team/drizzle-orm/issues/2773)
+- [[BUG]: drizzle-kit introspect fails on required param that is defined](https://github.com/drizzle-team/drizzle-orm/issues/2719)
+- [[BUG]: Error when running npx drizzle-kit introspect: "Expected object, received string"](https://github.com/drizzle-team/drizzle-orm/issues/2657)
+- [[BUG]: Missing index names when running introspect command [MYSQL]](https://github.com/drizzle-team/drizzle-orm/issues/2525)
+- [[BUG]: drizzle-kit introspect TypeError: Cannot read properties of undefined (reading 'toLowerCase')](https://github.com/drizzle-team/drizzle-orm/issues/2338)
+- [[BUG]: Wrong column name when using PgEnum.array()](https://github.com/drizzle-team/drizzle-orm/issues/2100)
+- [[BUG]: Incorrect Schema Generated when introspecting extisting pg database](https://github.com/drizzle-team/drizzle-orm/issues/1985)
+- [[⚠️🐞BUG]: index() missing argument after introspection, causes tsc error that fails the build](https://github.com/drizzle-team/drizzle-orm/issues/1870)
+- [[BUG]: drizzle-kit introspect small errors](https://github.com/drizzle-team/drizzle-orm/issues/1738)
+- [[BUG]: Missing bigint import in drizzle-kit introspect](https://github.com/drizzle-team/drizzle-orm/issues/1020)
\ No newline at end of file
diff --git a/changelogs/drizzle-kit/0.24.2.md b/changelogs/drizzle-kit/0.24.2.md
new file mode 100644
index 000000000..962a29acc
--- /dev/null
+++ b/changelogs/drizzle-kit/0.24.2.md
@@ -0,0 +1,24 @@
+## New Features
+
+### 🎉 Support for `pglite` driver
+
+You can now use pglite with all drizzle-kit commands, including Drizzle Studio!
+
+```ts
+import { defineConfig } from "drizzle-kit";
+
+export default defineConfig({
+ dialect: "postgresql",
+ driver: "pglite",
+ schema: "./schema.ts",
+ dbCredentials: {
+ url: "local-pg.db",
+ },
+ verbose: true,
+ strict: true,
+});
+```
+
+## Bug fixes
+
+- mysql-kit: fix GENERATED ALWAYS AS ... NOT NULL - [#2824](https://github.com/drizzle-team/drizzle-orm/pull/2824)
\ No newline at end of file
diff --git a/changelogs/drizzle-orm/0.32.2.md b/changelogs/drizzle-orm/0.32.2.md
new file mode 100644
index 000000000..9ce68473c
--- /dev/null
+++ b/changelogs/drizzle-orm/0.32.2.md
@@ -0,0 +1,4 @@
+- Fix AWS Data API type hints bugs in RQB
+- Fix set transactions in MySQL bug - thanks @roguesherlock
+- Add forwaring dependencies within useLiveQuery, fixes [#2651](https://github.com/drizzle-team/drizzle-orm/issues/2651) - thanks @anstapol
+- Export additional types from SQLite package, like `AnySQLiteUpdate` - thanks @veloii
\ No newline at end of file
diff --git a/changelogs/drizzle-orm/0.33.0.md b/changelogs/drizzle-orm/0.33.0.md
new file mode 100644
index 000000000..0093c9d05
--- /dev/null
+++ b/changelogs/drizzle-orm/0.33.0.md
@@ -0,0 +1,64 @@
+## Breaking changes (for some of postgres.js users)
+
+#### Bugs fixed for this breaking change
+
+- [Open
+[BUG]: jsonb always inserted as a json string when using postgres-js](https://github.com/drizzle-team/drizzle-orm/issues/724)
+- [[BUG]: jsonb type on postgres implement incorrectly](https://github.com/drizzle-team/drizzle-orm/issues/1511)
+
+> As we are doing with other drivers, we've changed the behavior of PostgreSQL-JS to pass raw JSON values, the same as you see them in the database. So if you are using the PostgreSQL-JS driver and passing data to Drizzle elsewhere, please check the new behavior of the client after it is passed to Drizzle.
+
+> We will update it to ensure it does not override driver behaviors, but this will be done as a complex task for everything in Drizzle in other releases
+
+If you were using `postgres-js` with `jsonb` fields, you might have seen stringified objects in your database, while drizzle insert and select operations were working as expected.
+
+You need to convert those fields from strings to actual JSON objects. To do this, you can use the following query to update your database:
+
+**if you are using jsonb:**
+```sql
+update table_name
+set jsonb_column = (jsonb_column #>> '{}')::jsonb;
+```
+
+**if you are using json:**
+```sql
+update table_name
+set json_column = (json_column #>> '{}')::json;
+```
+
+We've tested it in several cases, and it worked well, but only if all stringified objects are arrays or objects. If you have primitives like strings, numbers, booleans, etc., you can use this query to update all the fields
+
+**if you are using jsonb:**
+```sql
+UPDATE table_name
+SET jsonb_column = CASE
+ -- Convert to JSONB if it is a valid JSON object or array
+ WHEN jsonb_column #>> '{}' LIKE '{%' OR jsonb_column #>> '{}' LIKE '[%' THEN
+ (jsonb_column #>> '{}')::jsonb
+ ELSE
+ jsonb_column
+END
+WHERE
+ jsonb_column IS NOT NULL;
+```
+
+**if you are using json:**
+```sql
+UPDATE table_name
+SET json_column = CASE
+ -- Convert to JSON if it is a valid JSON object or array
+ WHEN json_column #>> '{}' LIKE '{%' OR json_column #>> '{}' LIKE '[%' THEN
+ (json_column #>> '{}')::json
+ ELSE
+ json_column
+END
+WHERE json_column IS NOT NULL;
+```
+
+If nothing works for you and you are blocked, please reach out to me @AndriiSherman. I will try to help you!
+
+## Bug Fixes
+
+- [[BUG]: boolean mode not working with prepared statements (bettersqlite)](https://github.com/drizzle-team/drizzle-orm/issues/2568) - thanks @veloii
+- [[BUG]: isTable helper function is not working](https://github.com/drizzle-team/drizzle-orm/issues/2672) - thanks @hajek-raven
+- [[BUG]: Documentation is outdated on inArray and notInArray Methods](https://github.com/drizzle-team/drizzle-orm/issues/2690) - thanks @RemiPeruto
\ No newline at end of file
diff --git a/drizzle-kit/.gitignore b/drizzle-kit/.gitignore
new file mode 100644
index 000000000..8d2cf5a81
--- /dev/null
+++ b/drizzle-kit/.gitignore
@@ -0,0 +1,23 @@
+/*
+**/.DS_Store
+
+!src
+!tests
+!vitest.config.ts
+!README.md
+!CONTRIBUTING.md
+!schema.ts
+
+!.eslint
+!.gitignore
+!package.json
+!tsconfig.json
+!tsconfig.cli-types.json
+!pnpm-lock.yaml
+!.github
+!build.ts
+!build.dev.ts
+
+tests/test.ts
+
+!patches
diff --git a/drizzle-kit/README.md b/drizzle-kit/README.md
new file mode 100644
index 000000000..d2a4191b7
--- /dev/null
+++ b/drizzle-kit/README.md
@@ -0,0 +1,79 @@
+## Drizzle Kit
+
+DrizzleKit - is a CLI migrator tool for DrizzleORM. It is probably one and only tool that lets you completely automatically generate SQL migrations and covers ~95% of the common cases like deletions and renames by prompting user input.
+ - is a mirror repository for issues.
+
+## Documentation
+
+Check the full documenation on [the website](https://orm.drizzle.team/kit-docs/overview)
+
+### How it works
+
+`drizzle-kit` will traverse `schema folder` or `schema file`, generate schema snapshot and compare it to the previous version, if there's one.
+ Based on the difference it will generate all needed SQL migrations and if there are any `automatically unresolvable` cases like `renames` it will prompt user for input.
+
+For schema file:
+
+```typescript
+// ./src/db/schema.ts
+
+import { integer, pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
+
+const users = pgTable("users", {
+ id: serial("id").primaryKey(),
+ fullName: varchar("full_name", { length: 256 }),
+ }, (table) => ({
+ nameIdx: index("name_idx", table.fullName),
+ })
+);
+
+export const authOtp = pgTable("auth_otp", {
+ id: serial("id").primaryKey(),
+ phone: varchar("phone", { length: 256 }),
+ userId: integer("user_id").references(() => users.id),
+});
+```
+
+It will generate:
+
+```SQL
+CREATE TABLE IF NOT EXISTS auth_otp (
+ "id" SERIAL PRIMARY KEY,
+ "phone" character varying(256),
+ "user_id" INT
+);
+
+CREATE TABLE IF NOT EXISTS users (
+ "id" SERIAL PRIMARY KEY,
+ "full_name" character varying(256)
+);
+
+DO $$ BEGIN
+ ALTER TABLE auth_otp ADD CONSTRAINT auth_otp_user_id_fkey FOREIGN KEY ("user_id") REFERENCES users(id);
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+
+CREATE INDEX IF NOT EXISTS users_full_name_index ON users (full_name);
+```
+
+### Installation & configuration
+
+```shell
+npm install -D drizzle-kit
+```
+
+Running with CLI options
+
+```jsonc
+// package.json
+{
+ "scripts": {
+ "generate": "drizzle-kit generate --out migrations-folder --schema src/db/schema.ts"
+ }
+}
+```
+
+```shell
+npm run generate
+```
diff --git a/drizzle-kit/build.dev.ts b/drizzle-kit/build.dev.ts
new file mode 100644
index 000000000..58879d9c1
--- /dev/null
+++ b/drizzle-kit/build.dev.ts
@@ -0,0 +1,51 @@
+import * as esbuild from 'esbuild';
+import { cpSync } from 'node:fs';
+
+const driversPackages = [
+ // postgres drivers
+ 'pg',
+ 'postgres',
+ '@vercel/postgres',
+ '@neondatabase/serverless',
+ // mysql drivers
+ 'mysql2',
+ '@planetscale/database',
+ // sqlite drivers
+ '@libsql/client',
+ 'better-sqlite3',
+];
+
+esbuild.buildSync({
+ entryPoints: ['./src/utils.ts'],
+ bundle: true,
+ outfile: 'dist/utils.js',
+ format: 'cjs',
+ target: 'node16',
+ platform: 'node',
+ external: ['drizzle-orm', 'esbuild', ...driversPackages],
+ banner: {
+ js: `#!/usr/bin/env -S node --loader @esbuild-kit/esm-loader --no-warnings`,
+ },
+});
+
+esbuild.buildSync({
+ entryPoints: ['./src/cli/index.ts'],
+ bundle: true,
+ outfile: 'dist/index.cjs',
+ format: 'cjs',
+ target: 'node16',
+ platform: 'node',
+ external: [
+ 'commander',
+ 'json-diff',
+ 'glob',
+ 'esbuild',
+ 'drizzle-orm',
+ ...driversPackages,
+ ],
+ banner: {
+ js: `#!/usr/bin/env -S node --loader ./dist/loader.mjs --no-warnings`,
+ },
+});
+
+cpSync('./src/loader.mjs', 'dist/loader.mjs');
diff --git a/drizzle-kit/build.ts b/drizzle-kit/build.ts
new file mode 100644
index 000000000..701e9c84c
--- /dev/null
+++ b/drizzle-kit/build.ts
@@ -0,0 +1,109 @@
+import * as esbuild from 'esbuild';
+import { readFileSync, writeFileSync } from 'node:fs';
+import * as tsup from 'tsup';
+import pkg from './package.json';
+
+const driversPackages = [
+ // postgres drivers
+ 'pg',
+ 'postgres',
+ '@vercel/postgres',
+ '@neondatabase/serverless',
+ '@electric-sql/pglite',
+ // mysql drivers
+ 'mysql2',
+ '@planetscale/database',
+ // sqlite drivers
+ '@libsql/client',
+ 'better-sqlite3',
+];
+
+esbuild.buildSync({
+ entryPoints: ['./src/utils.ts'],
+ bundle: true,
+ outfile: 'dist/utils.js',
+ format: 'cjs',
+ target: 'node16',
+ platform: 'node',
+ external: [
+ 'commander',
+ 'json-diff',
+ 'glob',
+ 'esbuild',
+ 'drizzle-orm',
+ ...driversPackages,
+ ],
+ banner: {
+ js: `#!/usr/bin/env node`,
+ },
+});
+
+esbuild.buildSync({
+ entryPoints: ['./src/utils.ts'],
+ bundle: true,
+ outfile: 'dist/utils.mjs',
+ format: 'esm',
+ target: 'node16',
+ platform: 'node',
+ external: [
+ 'commander',
+ 'json-diff',
+ 'glob',
+ 'esbuild',
+ 'drizzle-orm',
+ ...driversPackages,
+ ],
+ banner: {
+ js: `#!/usr/bin/env node`,
+ },
+});
+
+esbuild.buildSync({
+ entryPoints: ['./src/cli/index.ts'],
+ bundle: true,
+ outfile: 'dist/bin.cjs',
+ format: 'cjs',
+ target: 'node16',
+ platform: 'node',
+ define: {
+ 'process.env.DRIZZLE_KIT_VERSION': `"${pkg.version}"`,
+ },
+ external: [
+ 'esbuild',
+ 'drizzle-orm',
+ ...driversPackages,
+ ],
+ banner: {
+ js: `#!/usr/bin/env node`,
+ },
+});
+
+const main = async () => {
+ await tsup.build({
+ entryPoints: ['./src/index.ts', './src/api.ts'],
+ outDir: './dist',
+ splitting: false,
+ dts: true,
+ format: ['cjs', 'esm'],
+ outExtension: (ctx) => {
+ if (ctx.format === 'cjs') {
+ return {
+ dts: '.d.ts',
+ js: '.js',
+ };
+ }
+ return {
+ dts: '.d.mts',
+ js: '.mjs',
+ };
+ },
+ });
+
+ const apiCjs = readFileSync('./dist/api.js', 'utf8').replace(/await import\(/g, 'require(');
+ writeFileSync('./dist/api.js', apiCjs);
+};
+
+main().catch((e) => {
+ console.error(e);
+ process.exit(1);
+});
diff --git a/drizzle-kit/package.json b/drizzle-kit/package.json
new file mode 100644
index 000000000..9d9e1d227
--- /dev/null
+++ b/drizzle-kit/package.json
@@ -0,0 +1,140 @@
+{
+ "name": "drizzle-kit",
+ "version": "0.24.2",
+ "homepage": "https://orm.drizzle.team",
+ "keywords": [
+ "drizzle",
+ "orm",
+ "pg",
+ "mysql",
+ "postgresql",
+ "postgres",
+ "sqlite",
+ "database",
+ "sql",
+ "typescript",
+ "ts",
+ "drizzle-kit",
+ "migrations",
+ "schema"
+ ],
+ "publishConfig": {
+ "provenance": true
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/drizzle-team/drizzle-orm.git"
+ },
+ "author": "Drizzle Team",
+ "license": "MIT",
+ "bin": {
+ "drizzle-kit": "./bin.cjs"
+ },
+ "scripts": {
+ "api": "tsx ./dev/api.ts",
+ "migrate:old": "drizzle-kit generate:mysql",
+ "cli": "tsx ./src/cli/index.ts",
+ "test": "TEST_CONFIG_PATH_PREFIX=./tests/cli/ vitest",
+ "build": "rm -rf ./dist && tsx build.ts && cp package.json dist/ && attw --pack dist",
+ "build:dev": "rm -rf ./dist && tsx build.dev.ts && tsc -p tsconfig.cli-types.json && chmod +x ./dist/index.cjs",
+ "pack": "cp package.json README.md dist/ && (cd dist && npm pack --pack-destination ..) && rm -f package.tgz && mv *.tgz package.tgz",
+ "tsc": "tsc -p tsconfig.build.json",
+ "publish": "npm publish package.tgz"
+ },
+ "dependencies": {
+ "@drizzle-team/brocli": "^0.10.1",
+ "@esbuild-kit/esm-loader": "^2.5.5",
+ "esbuild": "^0.19.7",
+ "esbuild-register": "^3.5.0"
+ },
+ "devDependencies": {
+ "@arethetypeswrong/cli": "^0.15.3",
+ "@aws-sdk/client-rds-data": "^3.556.0",
+ "@cloudflare/workers-types": "^4.20230518.0",
+ "@electric-sql/pglite": "^0.1.5",
+ "@hono/node-server": "^1.9.0",
+ "@hono/zod-validator": "^0.2.1",
+ "@libsql/client": "^0.4.2",
+ "@neondatabase/serverless": "^0.9.1",
+ "@originjs/vite-plugin-commonjs": "^1.0.3",
+ "@planetscale/database": "^1.16.0",
+ "@types/better-sqlite3": "^7.6.4",
+ "@types/dockerode": "^3.3.28",
+ "@types/glob": "^8.1.0",
+ "@types/json-diff": "^1.0.3",
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "^18.11.15",
+ "@types/pg": "^8.10.7",
+ "@types/pluralize": "^0.0.33",
+ "@types/semver": "^7.5.5",
+ "@types/uuid": "^9.0.8",
+ "@types/ws": "^8.5.10",
+ "@typescript-eslint/eslint-plugin": "^7.2.0",
+ "@typescript-eslint/parser": "^7.2.0",
+ "@vercel/postgres": "^0.8.0",
+ "ava": "^5.1.0",
+ "better-sqlite3": "^9.4.3",
+ "camelcase": "^7.0.1",
+ "chalk": "^5.2.0",
+ "commander": "^12.1.0",
+ "dockerode": "^3.3.4",
+ "dotenv": "^16.0.3",
+ "drizzle-kit": "0.21.2",
+ "drizzle-orm": "workspace:./drizzle-orm/dist",
+ "env-paths": "^3.0.0",
+ "esbuild-node-externals": "^1.9.0",
+ "eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.3",
+ "get-port": "^6.1.2",
+ "glob": "^8.1.0",
+ "hanji": "^0.0.5",
+ "hono": "^4.1.5",
+ "json-diff": "1.0.6",
+ "minimatch": "^7.4.3",
+ "mysql2": "3.3.3",
+ "node-fetch": "^3.3.2",
+ "pg": "^8.11.5",
+ "pluralize": "^8.0.0",
+ "postgres": "^3.4.4",
+ "prettier": "^2.8.1",
+ "semver": "^7.5.4",
+ "superjson": "^2.2.1",
+ "tsup": "^8.0.2",
+ "tsx": "^3.12.1",
+ "typescript": "^5.4.3",
+ "uuid": "^9.0.1",
+ "vite-tsconfig-paths": "^4.3.2",
+ "vitest": "^1.4.0",
+ "wrangler": "^3.22.1",
+ "ws": "^8.16.0",
+ "zod": "^3.20.2",
+ "zx": "^7.2.2"
+ },
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./index.d.mts",
+ "default": "./index.mjs"
+ },
+ "require": {
+ "types": "./index.d.ts",
+ "default": "./index.js"
+ },
+ "types": "./index.d.mts",
+ "default": "./index.mjs"
+ },
+ "./api": {
+ "import": {
+ "types": "./api.d.mts",
+ "default": "./api.mjs"
+ },
+ "require": {
+ "types": "./api.d.ts",
+ "default": "./api.js"
+ },
+ "types": "./api.d.mts",
+ "default": "./api.mjs"
+ }
+ }
+}
diff --git a/drizzle-kit/patches/difflib@0.2.4.patch b/drizzle-kit/patches/difflib@0.2.4.patch
new file mode 100644
index 000000000..8cd9a76b2
--- /dev/null
+++ b/drizzle-kit/patches/difflib@0.2.4.patch
@@ -0,0 +1,31 @@
+diff --git a/lib/difflib.js b/lib/difflib.js
+index 80d250e7e18bdc972df3621ee5c05ffff0e3659f..94916f33dbae0d3eea6f74e2c619c4c6f52cc125 100644
+--- a/lib/difflib.js
++++ b/lib/difflib.js
+@@ -17,7 +17,7 @@ Function restore(delta, which):
+
+ Function unifiedDiff(a, b):
+ For two lists of strings, return a delta in unified diff format.
+-
++.
+ Class SequenceMatcher:
+ A flexible class for comparing pairs of sequences of any type.
+
+@@ -75,7 +75,7 @@ Class Differ:
+
+ SequenceMatcher = (function() {
+
+- SequenceMatcher.name = 'SequenceMatcher';
++ // SequenceMatcher.name = 'SequenceMatcher';
+
+ /*
+ SequenceMatcher is a flexible class for comparing pairs of sequences of
+@@ -737,7 +737,7 @@ Class Differ:
+
+ Differ = (function() {
+
+- Differ.name = 'Differ';
++ // Differ.name = 'Differ';
+
+ /*
+ Differ is a class for comparing sequences of lines of text, and
diff --git a/drizzle-kit/pnpm-lock.yaml b/drizzle-kit/pnpm-lock.yaml
new file mode 100644
index 000000000..8f4d58f55
--- /dev/null
+++ b/drizzle-kit/pnpm-lock.yaml
@@ -0,0 +1,7603 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+patchedDependencies:
+ difflib@0.2.4:
+ hash: jq4t3ysdpnbunjeje4v7nrqn2q
+ path: patches/difflib@0.2.4.patch
+
+importers:
+
+ .:
+ dependencies:
+ '@esbuild-kit/esm-loader':
+ specifier: ^2.5.5
+ version: 2.6.5
+ esbuild:
+ specifier: ^0.19.7
+ version: 0.19.12
+ esbuild-register:
+ specifier: ^3.5.0
+ version: 3.5.0(esbuild@0.19.12)
+ devDependencies:
+ '@arethetypeswrong/cli':
+ specifier: ^0.15.3
+ version: 0.15.3
+ '@aws-sdk/client-rds-data':
+ specifier: ^3.556.0
+ version: 3.577.0
+ '@cloudflare/workers-types':
+ specifier: ^4.20230518.0
+ version: 4.20240512.0
+ '@electric-sql/pglite':
+ specifier: ^0.1.5
+ version: 0.1.5
+ '@hono/node-server':
+ specifier: ^1.9.0
+ version: 1.11.1
+ '@hono/zod-validator':
+ specifier: ^0.2.1
+ version: 0.2.1(hono@4.3.9)(zod@3.23.8)
+ '@libsql/client':
+ specifier: ^0.4.2
+ version: 0.4.3(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ '@neondatabase/serverless':
+ specifier: ^0.9.1
+ version: 0.9.3
+ '@originjs/vite-plugin-commonjs':
+ specifier: ^1.0.3
+ version: 1.0.3
+ '@planetscale/database':
+ specifier: ^1.16.0
+ version: 1.18.0
+ '@types/better-sqlite3':
+ specifier: ^7.6.4
+ version: 7.6.10
+ '@types/dockerode':
+ specifier: ^3.3.28
+ version: 3.3.29
+ '@types/glob':
+ specifier: ^8.1.0
+ version: 8.1.0
+ '@types/json-diff':
+ specifier: ^1.0.3
+ version: 1.0.3
+ '@types/minimatch':
+ specifier: ^5.1.2
+ version: 5.1.2
+ '@types/node':
+ specifier: ^18.11.15
+ version: 18.19.33
+ '@types/pg':
+ specifier: ^8.10.7
+ version: 8.11.6
+ '@types/pluralize':
+ specifier: ^0.0.33
+ version: 0.0.33
+ '@types/semver':
+ specifier: ^7.5.5
+ version: 7.5.8
+ '@types/uuid':
+ specifier: ^9.0.8
+ version: 9.0.8
+ '@types/ws':
+ specifier: ^8.5.10
+ version: 8.5.10
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^7.2.0
+ version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/parser':
+ specifier: ^7.2.0
+ version: 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ '@vercel/postgres':
+ specifier: ^0.8.0
+ version: 0.8.0
+ ava:
+ specifier: ^5.1.0
+ version: 5.3.1
+ better-sqlite3:
+ specifier: ^9.4.3
+ version: 9.6.0
+ camelcase:
+ specifier: ^7.0.1
+ version: 7.0.1
+ chalk:
+ specifier: ^5.2.0
+ version: 5.3.0
+ commander:
+ specifier: ^12.1.0
+ version: 12.1.0
+ dockerode:
+ specifier: ^3.3.4
+ version: 3.3.5
+ dotenv:
+ specifier: ^16.0.3
+ version: 16.4.5
+ drizzle-kit:
+ specifier: 0.21.2
+ version: 0.21.2
+ drizzle-orm:
+ specifier: 0.32.0-85c8008
+ version: 0.32.0-85c8008(@aws-sdk/client-rds-data@3.577.0)(@cloudflare/workers-types@4.20240512.0)(@electric-sql/pglite@0.1.5)(@libsql/client@0.4.3(bufferutil@4.0.8)(utf-8-validate@6.0.3))(@neondatabase/serverless@0.9.3)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(mysql2@2.3.3)(pg@8.11.5)(postgres@3.4.4)
+ env-paths:
+ specifier: ^3.0.0
+ version: 3.0.0
+ esbuild-node-externals:
+ specifier: ^1.9.0
+ version: 1.13.1(esbuild@0.19.12)
+ eslint:
+ specifier: ^8.57.0
+ version: 8.57.0
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.0(eslint@8.57.0)
+ eslint-plugin-prettier:
+ specifier: ^5.1.3
+ version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8)
+ get-port:
+ specifier: ^6.1.2
+ version: 6.1.2
+ glob:
+ specifier: ^8.1.0
+ version: 8.1.0
+ hanji:
+ specifier: ^0.0.5
+ version: 0.0.5
+ hono:
+ specifier: ^4.1.5
+ version: 4.3.9
+ json-diff:
+ specifier: 1.0.6
+ version: 1.0.6
+ minimatch:
+ specifier: ^7.4.3
+ version: 7.4.6
+ mysql2:
+ specifier: 2.3.3
+ version: 2.3.3
+ node-fetch:
+ specifier: ^3.3.2
+ version: 3.3.2
+ pg:
+ specifier: ^8.11.5
+ version: 8.11.5
+ pluralize:
+ specifier: ^8.0.0
+ version: 8.0.0
+ postgres:
+ specifier: ^3.4.4
+ version: 3.4.4
+ prettier:
+ specifier: ^2.8.1
+ version: 2.8.8
+ semver:
+ specifier: ^7.5.4
+ version: 7.6.2
+ superjson:
+ specifier: ^2.2.1
+ version: 2.2.1
+ tsup:
+ specifier: ^8.0.2
+ version: 8.0.2(postcss@8.4.38)(typescript@5.4.5)
+ tsx:
+ specifier: ^3.12.1
+ version: 3.14.0
+ typescript:
+ specifier: ^5.4.3
+ version: 5.4.5
+ uuid:
+ specifier: ^9.0.1
+ version: 9.0.1
+ vite-tsconfig-paths:
+ specifier: ^4.3.2
+ version: 4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@18.19.33))
+ vitest:
+ specifier: ^1.4.0
+ version: 1.6.0(@types/node@18.19.33)
+ wrangler:
+ specifier: ^3.22.1
+ version: 3.57.0(@cloudflare/workers-types@4.20240512.0)(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ ws:
+ specifier: ^8.16.0
+ version: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ zod:
+ specifier: ^3.20.2
+ version: 3.23.8
+ zx:
+ specifier: ^7.2.2
+ version: 7.2.3
+
+packages:
+
+ '@andrewbranch/untar.js@1.0.3':
+ resolution: {integrity: sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==}
+
+ '@arethetypeswrong/cli@0.15.3':
+ resolution: {integrity: sha512-sIMA9ZJBWDEg1+xt5RkAEflZuf8+PO8SdKj17x6PtETuUho+qlZJg4DgmKc3q+QwQ9zOB5VLK6jVRbFdNLdUIA==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ '@arethetypeswrong/core@0.15.1':
+ resolution: {integrity: sha512-FYp6GBAgsNz81BkfItRz8RLZO03w5+BaeiPma1uCfmxTnxbtuMrI/dbzGiOk8VghO108uFI0oJo0OkewdSHw7g==}
+ engines: {node: '>=18'}
+
+ '@aws-crypto/ie11-detection@3.0.0':
+ resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==}
+
+ '@aws-crypto/sha256-browser@3.0.0':
+ resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==}
+
+ '@aws-crypto/sha256-js@3.0.0':
+ resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==}
+
+ '@aws-crypto/supports-web-crypto@3.0.0':
+ resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==}
+
+ '@aws-crypto/util@3.0.0':
+ resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==}
+
+ '@aws-sdk/client-rds-data@3.577.0':
+ resolution: {integrity: sha512-24a27II6UkNhe2RB6ZwtQPcM3QB/DuRcKvzMmfvipgWS72Q5FEtuq3CO66IObWUel/pxi3ucE6mSvVCFnm7tBQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/client-sso-oidc@3.577.0':
+ resolution: {integrity: sha512-njmKSPDWueWWYVFpFcZ2P3fI6/pdQVDa0FgCyYZhOnJLgEHZIcBBg1AsnkVWacBuLopp9XVt2m+7hO6ugY1/1g==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/client-sso@3.577.0':
+ resolution: {integrity: sha512-BwujdXrydlk6UEyPmewm5GqG4nkQ6OVyRhS/SyZP/6UKSFv2/sf391Cmz0hN0itUTH1rR4XeLln8XCOtarkrzg==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/client-sts@3.577.0':
+ resolution: {integrity: sha512-509Kklimva1XVlhGbpTpeX3kOP6ORpm44twJxDHpa9TURbmoaxj7veWlnLCbDorxDTrbsDghvYZshvcLsojVpg==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/core@3.576.0':
+ resolution: {integrity: sha512-KDvDlbeipSTIf+ffKtTg1m419TK7s9mZSWC8bvuZ9qx6/sjQFOXIKOVqyuli6DnfxGbvRcwoRuY99OcCH1N/0w==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-env@3.577.0':
+ resolution: {integrity: sha512-Jxu255j0gToMGEiqufP8ZtKI8HW90lOLjwJ3LrdlD/NLsAY0tOQf1fWc53u28hWmmNGMxmCrL2p66IOgMDhDUw==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-http@3.577.0':
+ resolution: {integrity: sha512-n++yhCp67b9+ZRGEdY1jhamB5E/O+QsIDOPSuRmdaSGMCOd82oUEKPgIVEU1bkqxDsBxgiEWuvtfhK6sNiDS0A==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-ini@3.577.0':
+ resolution: {integrity: sha512-q7lHPtv6BjRvChUE3m0tIaEZKxPTaZ1B3lKxGYsFl3VLAu5N8yGCUKwuA1izf4ucT+LyKscVGqK6VDZx1ev3nw==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ '@aws-sdk/client-sts': ^3.577.0
+
+ '@aws-sdk/credential-provider-node@3.577.0':
+ resolution: {integrity: sha512-epZ1HOMsrXBNczc0HQpv0VMjqAEpc09DUA7Rg3gUJfn8umhML7A7bXnUyqPA+S54q397UYg1leQKdSn23OiwQQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-process@3.577.0':
+ resolution: {integrity: sha512-Gin6BWtOiXxIgITrJ3Nwc+Y2P1uVT6huYR4EcbA/DJUPWyO0n9y5UFLewPvVbLkRn15JeEqErBLUrHclkiOKtw==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-sso@3.577.0':
+ resolution: {integrity: sha512-iVm5SQvS7EgZTJsRaqUOmDQpBQPPPat42SCbWFvFQOLrl8qewq8OP94hFS5w2mP62zngeYzqhJnDel79HXbxew==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/credential-provider-web-identity@3.577.0':
+ resolution: {integrity: sha512-ZGHGNRaCtJJmszb9UTnC7izNCtRUttdPlLdMkh41KPS32vfdrBDHs1JrpbZijItRj1xKuOXsiYSXLAaHGcLh8Q==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ '@aws-sdk/client-sts': ^3.577.0
+
+ '@aws-sdk/middleware-host-header@3.577.0':
+ resolution: {integrity: sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/middleware-logger@3.577.0':
+ resolution: {integrity: sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/middleware-recursion-detection@3.577.0':
+ resolution: {integrity: sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/middleware-user-agent@3.577.0':
+ resolution: {integrity: sha512-P55HAXgwmiHHpFx5JEPvOnAbfhN7v6sWv9PBQs+z2tC7QiBcPS0cdJR6PfV7J1n4VPK52/OnrK3l9VxdQ7Ms0g==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/region-config-resolver@3.577.0':
+ resolution: {integrity: sha512-4ChCFACNwzqx/xjg3zgFcW8Ali6R9C95cFECKWT/7CUM1D0MGvkclSH2cLarmHCmJgU6onKkJroFtWp0kHhgyg==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/token-providers@3.577.0':
+ resolution: {integrity: sha512-0CkIZpcC3DNQJQ1hDjm2bdSy/Xjs7Ny5YvSsacasGOkNfk+FdkiQy6N67bZX3Zbc9KIx+Nz4bu3iDeNSNplnnQ==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ '@aws-sdk/client-sso-oidc': ^3.577.0
+
+ '@aws-sdk/types@3.577.0':
+ resolution: {integrity: sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/util-endpoints@3.577.0':
+ resolution: {integrity: sha512-FjuUz1Kdy4Zly2q/c58tpdqHd6z7iOdU/caYzoc8jwgAHBDBbIJNQLCU9hXJnPV2M8pWxQDyIZsoVwtmvErPzw==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/util-locate-window@3.568.0':
+ resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==}
+ engines: {node: '>=16.0.0'}
+
+ '@aws-sdk/util-user-agent-browser@3.577.0':
+ resolution: {integrity: sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==}
+
+ '@aws-sdk/util-user-agent-node@3.577.0':
+ resolution: {integrity: sha512-XqvtFjbSMtycZTWVwDe8DRWovuoMbA54nhUoZwVU6rW9OSD6NZWGR512BUGHFaWzW0Wg8++Dj10FrKTG2XtqfA==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ aws-crt: '>=1.0.0'
+ peerDependenciesMeta:
+ aws-crt:
+ optional: true
+
+ '@aws-sdk/util-utf8-browser@3.259.0':
+ resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==}
+
+ '@balena/dockerignore@1.0.2':
+ resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
+
+ '@cloudflare/kv-asset-handler@0.3.2':
+ resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==}
+ engines: {node: '>=16.13'}
+
+ '@cloudflare/workerd-darwin-64@1.20240512.0':
+ resolution: {integrity: sha512-VMp+CsSHFALQiBzPdQ5dDI4T1qwLu0mQ0aeKVNDosXjueN0f3zj/lf+mFil5/9jBbG3t4mG0y+6MMnalP9Lobw==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@cloudflare/workerd-darwin-arm64@1.20240512.0':
+ resolution: {integrity: sha512-lZktXGmzMrB5rJqY9+PmnNfv1HKlj/YLZwMjPfF0WVKHUFdvQbAHsi7NlKv6mW9uIvlZnS+K4sIkWc0MDXcRnA==}
+ engines: {node: '>=16'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@cloudflare/workerd-linux-64@1.20240512.0':
+ resolution: {integrity: sha512-wrHvqCZZqXz6Y3MUTn/9pQNsvaoNjbJpuA6vcXsXu8iCzJi911iVW2WUEBX+MpUWD+mBIP0oXni5tTlhkokOPw==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [linux]
+
+ '@cloudflare/workerd-linux-arm64@1.20240512.0':
+ resolution: {integrity: sha512-YPezHMySL9J9tFdzxz390eBswQ//QJNYcZolz9Dgvb3FEfdpK345cE/bsWbMOqw5ws2f82l388epoenghtYvAg==}
+ engines: {node: '>=16'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@cloudflare/workerd-windows-64@1.20240512.0':
+ resolution: {integrity: sha512-SxKapDrIYSscMR7lGIp/av0l6vokjH4xQ9ACxHgXh+OdOus9azppSmjaPyw4/ePvg7yqpkaNjf9o258IxWtvKQ==}
+ engines: {node: '>=16'}
+ cpu: [x64]
+ os: [win32]
+
+ '@cloudflare/workers-types@4.20240512.0':
+ resolution: {integrity: sha512-o2yTEWg+YK/I1t/Me+dA0oarO0aCbjibp6wSeaw52DSE9tDyKJ7S+Qdyw/XsMrKn4t8kF6f/YOba+9O4MJfW9w==}
+
+ '@colors/colors@1.5.0':
+ resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
+ engines: {node: '>=0.1.90'}
+
+ '@cspotcode/source-map-support@0.8.1':
+ resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
+ engines: {node: '>=12'}
+
+ '@electric-sql/pglite@0.1.5':
+ resolution: {integrity: sha512-eymv4ONNvoPZQTvOQIi5dbpR+J5HzEv0qQH9o/y3gvNheJV/P/NFcrbsfJZYTsDKoq7DKrTiFNexsRkJKy8x9Q==}
+
+ '@esbuild-kit/core-utils@3.3.2':
+ resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
+
+ '@esbuild-kit/esm-loader@2.6.5':
+ resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==}
+
+ '@esbuild-plugins/node-globals-polyfill@0.2.3':
+ resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==}
+ peerDependencies:
+ esbuild: '*'
+
+ '@esbuild-plugins/node-modules-polyfill@0.2.2':
+ resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==}
+ peerDependencies:
+ esbuild: '*'
+
+ '@esbuild/aix-ppc64@0.19.12':
+ resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/aix-ppc64@0.20.2':
+ resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.17.19':
+ resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm64@0.18.20':
+ resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm64@0.19.12':
+ resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm64@0.20.2':
+ resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.17.19':
+ resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-arm@0.18.20':
+ resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-arm@0.19.12':
+ resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-arm@0.20.2':
+ resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.17.19':
+ resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/android-x64@0.18.20':
+ resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/android-x64@0.19.12':
+ resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/android-x64@0.20.2':
+ resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.17.19':
+ resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-arm64@0.18.20':
+ resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-arm64@0.19.12':
+ resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-arm64@0.20.2':
+ resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.17.19':
+ resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.18.20':
+ resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.19.12':
+ resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.20.2':
+ resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.17.19':
+ resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-arm64@0.18.20':
+ resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-arm64@0.19.12':
+ resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-arm64@0.20.2':
+ resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.17.19':
+ resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.18.20':
+ resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.19.12':
+ resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.20.2':
+ resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.17.19':
+ resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm64@0.18.20':
+ resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm64@0.19.12':
+ resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm64@0.20.2':
+ resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.17.19':
+ resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.18.20':
+ resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.19.12':
+ resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.20.2':
+ resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.17.19':
+ resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.18.20':
+ resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.19.12':
+ resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.20.2':
+ resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.14.54':
+ resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.17.19':
+ resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.18.20':
+ resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.19.12':
+ resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.20.2':
+ resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.17.19':
+ resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.18.20':
+ resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.19.12':
+ resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.20.2':
+ resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.17.19':
+ resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.18.20':
+ resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.19.12':
+ resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.20.2':
+ resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.17.19':
+ resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.18.20':
+ resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.19.12':
+ resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.20.2':
+ resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.17.19':
+ resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.18.20':
+ resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.19.12':
+ resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.20.2':
+ resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.17.19':
+ resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.18.20':
+ resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.19.12':
+ resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.20.2':
+ resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-x64@0.17.19':
+ resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.18.20':
+ resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.19.12':
+ resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.20.2':
+ resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-x64@0.17.19':
+ resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.18.20':
+ resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.19.12':
+ resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.20.2':
+ resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.17.19':
+ resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/sunos-x64@0.18.20':
+ resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/sunos-x64@0.19.12':
+ resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/sunos-x64@0.20.2':
+ resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.17.19':
+ resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-arm64@0.18.20':
+ resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-arm64@0.19.12':
+ resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-arm64@0.20.2':
+ resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.17.19':
+ resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.18.20':
+ resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.19.12':
+ resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.20.2':
+ resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.17.19':
+ resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.18.20':
+ resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.19.12':
+ resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.20.2':
+ resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ '@eslint-community/eslint-utils@4.4.0':
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+ '@eslint-community/regexpp@4.10.0':
+ resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+ '@eslint/eslintrc@2.1.4':
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ '@eslint/js@8.57.0':
+ resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ '@ewoudenberg/difflib@0.1.0':
+ resolution: {integrity: sha512-OU5P5mJyD3OoWYMWY+yIgwvgNS9cFAU10f+DDuvtogcWQOoJIsQ4Hy2McSfUfhKjq8L0FuWVb4Rt7kgA+XK86A==}
+
+ '@fastify/busboy@2.1.1':
+ resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
+ engines: {node: '>=14'}
+
+ '@hono/node-server@1.11.1':
+ resolution: {integrity: sha512-GW1Iomhmm1o4Z+X57xGby8A35Cu9UZLL7pSMdqDBkD99U5cywff8F+8hLk5aBTzNubnsFAvWQ/fZjNwPsEn9lA==}
+ engines: {node: '>=18.14.1'}
+
+ '@hono/zod-validator@0.2.1':
+ resolution: {integrity: sha512-HFoxln7Q6JsE64qz2WBS28SD33UB2alp3aRKmcWnNLDzEL1BLsWfbdX6e1HIiUprHYTIXf5y7ax8eYidKUwyaA==}
+ peerDependencies:
+ hono: '>=3.9.0'
+ zod: ^3.19.1
+
+ '@humanwhocodes/config-array@0.11.14':
+ resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+ engines: {node: '>=10.10.0'}
+
+ '@humanwhocodes/module-importer@1.0.1':
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+
+ '@humanwhocodes/object-schema@2.0.3':
+ resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
+ '@jest/schemas@29.6.3':
+ resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ '@jridgewell/gen-mapping@0.3.5':
+ resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/set-array@1.2.1':
+ resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.4.15':
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
+
+ '@jridgewell/trace-mapping@0.3.9':
+ resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+
+ '@libsql/client@0.4.3':
+ resolution: {integrity: sha512-AUYKnSPqAsFBVWBvmtrb4dG3pQlvTKT92eztAest9wQU2iJkabH8WzHLDb3dKFWKql7/kiCqvBQUVpozDwhekQ==}
+
+ '@libsql/core@0.4.3':
+ resolution: {integrity: sha512-r28iYBtaLBW9RRgXPFh6cGCsVI/rwRlOzSOpAu/1PVTm6EJ3t233pUf97jETVHU0vjdr1d8VvV6fKAvJkokqCw==}
+
+ '@libsql/darwin-arm64@0.2.0':
+ resolution: {integrity: sha512-+qyT2W/n5CFH1YZWv2mxW4Fsoo4dX9Z9M/nvbQqZ7H84J8hVegvVAsIGYzcK8xAeMEcpU5yGKB1Y9NoDY4hOSQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@libsql/darwin-x64@0.2.0':
+ resolution: {integrity: sha512-hwmO2mF1n8oDHKFrUju6Jv+n9iFtTf5JUK+xlnIE3Td0ZwGC/O1R/Z/btZTd9nD+vsvakC8SJT7/Q6YlWIkhEw==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@libsql/hrana-client@0.5.6':
+ resolution: {integrity: sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==}
+
+ '@libsql/isomorphic-fetch@0.1.12':
+ resolution: {integrity: sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==}
+
+ '@libsql/isomorphic-ws@0.1.5':
+ resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==}
+
+ '@libsql/linux-arm64-gnu@0.2.0':
+ resolution: {integrity: sha512-1w2lPXIYtnBaK5t/Ej5E8x7lPiE+jP3KATI/W4yei5Z/ONJh7jQW5PJ7sYU95vTME3hWEM1FXN6kvzcpFAte7w==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@libsql/linux-arm64-musl@0.2.0':
+ resolution: {integrity: sha512-lkblBEJ7xuNiWNjP8DDq0rqoWccszfkUS7Efh5EjJ+GDWdCBVfh08mPofIZg0fZVLWQCY3j+VZCG1qZfATBizg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@libsql/linux-x64-gnu@0.2.0':
+ resolution: {integrity: sha512-+x/d289KeJydwOhhqSxKT+6MSQTCfLltzOpTzPccsvdt5fxg8CBi+gfvEJ4/XW23Sa+9bc7zodFP0i6MOlxX7w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@libsql/linux-x64-musl@0.2.0':
+ resolution: {integrity: sha512-5Xn0c5A6vKf9D1ASpgk7mef//FuY7t5Lktj/eiU4n3ryxG+6WTpqstTittJUgepVjcleLPYxIhQAYeYwTYH1IQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@libsql/win32-x64-msvc@0.2.0':
+ resolution: {integrity: sha512-rpK+trBIpRST15m3cMYg5aPaX7kvCIottxY7jZPINkKAaScvfbn9yulU/iZUM9YtuK96Y1ZmvwyVIK/Y5DzoMQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@neon-rs/load@0.0.4':
+ resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==}
+
+ '@neondatabase/serverless@0.7.2':
+ resolution: {integrity: sha512-wU3WA2uTyNO7wjPs3Mg0G01jztAxUxzd9/mskMmtPwPTjf7JKWi9AW5/puOGXLxmZ9PVgRFeBVRVYq5nBPhsCg==}
+
+ '@neondatabase/serverless@0.9.3':
+ resolution: {integrity: sha512-6ZBK8asl2Z3+ADEaELvbaVVGVlmY1oAzkxxZfpmXPKFuJhbDN+5fU3zYBamsahS/Ch1zE+CVWB3R+8QEI2LMSw==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@originjs/vite-plugin-commonjs@1.0.3':
+ resolution: {integrity: sha512-KuEXeGPptM2lyxdIEJ4R11+5ztipHoE7hy8ClZt3PYaOVQ/pyngd2alaSrPnwyFeOW1UagRBaQ752aA1dTMdOQ==}
+
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
+ '@pkgr/core@0.1.1':
+ resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+
+ '@planetscale/database@1.18.0':
+ resolution: {integrity: sha512-t2XdOfrVgcF7AW791FtdPS27NyNqcE1SpoXgk3HpziousvUMsJi4Q6NL3JyOBpsMOrvk94749o8yyonvX5quPw==}
+ engines: {node: '>=16'}
+
+ '@rollup/rollup-android-arm-eabi@4.17.2':
+ resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.17.2':
+ resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.17.2':
+ resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.17.2':
+ resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
+ resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.17.2':
+ resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.17.2':
+ resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.17.2':
+ resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
+ resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.17.2':
+ resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.17.2':
+ resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.17.2':
+ resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.17.2':
+ resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.17.2':
+ resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.17.2':
+ resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.17.2':
+ resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==}
+ cpu: [x64]
+ os: [win32]
+
+ '@sinclair/typebox@0.27.8':
+ resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
+
+ '@sindresorhus/is@4.6.0':
+ resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
+ engines: {node: '>=10'}
+
+ '@smithy/abort-controller@3.0.0':
+ resolution: {integrity: sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/config-resolver@3.0.0':
+ resolution: {integrity: sha512-2GzOfADwYLQugYkKQhIyZyQlM05K+tMKvRnc6eFfZcpJGRfKoMUMYdPlBKmqHwQFXQKBrGV6cxL9oymWgDzvFw==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/core@2.0.1':
+ resolution: {integrity: sha512-rcMkjvwxH/bER+oZUPR0yTA0ELD6m3A+d92+CFkdF6HJFCBB1bXo7P5pm21L66XwTN01B6bUhSCQ7cymWRD8zg==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/credential-provider-imds@3.0.0':
+ resolution: {integrity: sha512-lfmBiFQcA3FsDAPxNfY0L7CawcWtbyWsBOHo34nF095728JLkBX4Y9q/VPPE2r7fqMVK+drmDigqE2/SSQeVRA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/fetch-http-handler@3.0.1':
+ resolution: {integrity: sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==}
+
+ '@smithy/hash-node@3.0.0':
+ resolution: {integrity: sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/invalid-dependency@3.0.0':
+ resolution: {integrity: sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==}
+
+ '@smithy/is-array-buffer@3.0.0':
+ resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/middleware-content-length@3.0.0':
+ resolution: {integrity: sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/middleware-endpoint@3.0.0':
+ resolution: {integrity: sha512-aXOAWztw/5qAfp0NcA2OWpv6ZI/E+Dh9mByif7i91D/0iyYNUcKvskmXiowKESFkuZ7PIMd3VOR4fTibZDs2OQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/middleware-retry@3.0.1':
+ resolution: {integrity: sha512-hBhSEuL841FhJBK/19WpaGk5YWSzFk/P2UaVjANGKRv3eYNO8Y1lANWgqnuPWjOyCEWMPr58vELFDWpxvRKANw==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/middleware-serde@3.0.0':
+ resolution: {integrity: sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/middleware-stack@3.0.0':
+ resolution: {integrity: sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/node-config-provider@3.0.0':
+ resolution: {integrity: sha512-buqfaSdDh0zo62EPLf8rGDvcpKwGpO5ho4bXS2cdFhlOta7tBkWJt+O5uiaAeICfIOfPclNOndshDNSanX2X9g==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/node-http-handler@3.0.0':
+ resolution: {integrity: sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/property-provider@3.0.0':
+ resolution: {integrity: sha512-LmbPgHBswdXCrkWWuUwBm9w72S2iLWyC/5jet9/Y9cGHtzqxi+GVjfCfahkvNV4KXEwgnH8EMpcrD9RUYe0eLQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/protocol-http@4.0.0':
+ resolution: {integrity: sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/querystring-builder@3.0.0':
+ resolution: {integrity: sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/querystring-parser@3.0.0':
+ resolution: {integrity: sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/service-error-classification@3.0.0':
+ resolution: {integrity: sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/shared-ini-file-loader@3.0.0':
+ resolution: {integrity: sha512-REVw6XauXk8xE4zo5aGL7Rz4ywA8qNMUn8RtWeTRQsgAlmlvbJ7CEPBcaXU2NDC3AYBgYAXrGyWD8XrN8UGDog==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/signature-v4@3.0.0':
+ resolution: {integrity: sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/smithy-client@3.0.1':
+ resolution: {integrity: sha512-KAiFY4Y4jdHxR+4zerH/VBhaFKM8pbaVmJZ/CWJRwtM/CmwzTfXfvYwf6GoUwiHepdv+lwiOXCuOl6UBDUEINw==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/types@3.0.0':
+ resolution: {integrity: sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/url-parser@3.0.0':
+ resolution: {integrity: sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==}
+
+ '@smithy/util-base64@3.0.0':
+ resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-body-length-browser@3.0.0':
+ resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==}
+
+ '@smithy/util-body-length-node@3.0.0':
+ resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-buffer-from@3.0.0':
+ resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-config-provider@3.0.0':
+ resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-defaults-mode-browser@3.0.1':
+ resolution: {integrity: sha512-nW5kEzdJn1Bn5TF+gOPHh2rcPli8JU9vSSXLbfg7uPnfR1TMRQqs9zlYRhIb87NeSxIbpdXOI94tvXSy+fvDYg==}
+ engines: {node: '>= 10.0.0'}
+
+ '@smithy/util-defaults-mode-node@3.0.1':
+ resolution: {integrity: sha512-TFk+Qb+elLc/MOhtSp+50fstyfZ6avQbgH2d96xUBpeScu+Al9elxv+UFAjaTHe0HQe5n+wem8ZLpXvU8lwV6Q==}
+ engines: {node: '>= 10.0.0'}
+
+ '@smithy/util-endpoints@2.0.0':
+ resolution: {integrity: sha512-+exaXzEY3DNt2qtA2OtRNSDlVrE4p32j1JSsQkzA5AdP0YtJNjkYbYhJxkFmPYcjI1abuwopOZCwUmv682QkiQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-hex-encoding@3.0.0':
+ resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-middleware@3.0.0':
+ resolution: {integrity: sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-retry@3.0.0':
+ resolution: {integrity: sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-stream@3.0.1':
+ resolution: {integrity: sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-uri-escape@3.0.0':
+ resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==}
+ engines: {node: '>=16.0.0'}
+
+ '@smithy/util-utf8@3.0.0':
+ resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==}
+ engines: {node: '>=16.0.0'}
+
+ '@types/better-sqlite3@7.6.10':
+ resolution: {integrity: sha512-TZBjD+yOsyrUJGmcUj6OS3JADk3+UZcNv3NOBqGkM09bZdi28fNZw8ODqbMOLfKCu7RYCO62/ldq1iHbzxqoPw==}
+
+ '@types/docker-modem@3.0.6':
+ resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==}
+
+ '@types/dockerode@3.3.29':
+ resolution: {integrity: sha512-5PRRq/yt5OT/Jf77ltIdz4EiR9+VLnPF+HpU4xGFwUqmV24Co2HKBNW3w+slqZ1CYchbcDeqJASHDYWzZCcMiQ==}
+
+ '@types/estree@1.0.5':
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+
+ '@types/fs-extra@11.0.4':
+ resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
+
+ '@types/glob@8.1.0':
+ resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==}
+
+ '@types/json-diff@1.0.3':
+ resolution: {integrity: sha512-Qvxm8fpRMv/1zZR3sQWImeRK2mBYJji20xF51Fq9Gt//Ed18u0x6/FNLogLS1xhfUWTEmDyqveJqn95ltB6Kvw==}
+
+ '@types/jsonfile@6.1.4':
+ resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
+
+ '@types/minimatch@5.1.2':
+ resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
+
+ '@types/minimist@1.2.5':
+ resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
+
+ '@types/node-fetch@2.6.11':
+ resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
+
+ '@types/node-forge@1.3.11':
+ resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
+
+ '@types/node@18.19.33':
+ resolution: {integrity: sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==}
+
+ '@types/pg@8.11.6':
+ resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==}
+
+ '@types/pg@8.6.6':
+ resolution: {integrity: sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==}
+
+ '@types/pluralize@0.0.33':
+ resolution: {integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==}
+
+ '@types/ps-tree@1.1.6':
+ resolution: {integrity: sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==}
+
+ '@types/semver@7.5.8':
+ resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
+
+ '@types/ssh2@1.15.0':
+ resolution: {integrity: sha512-YcT8jP5F8NzWeevWvcyrrLB3zcneVjzYY9ZDSMAMboI+2zR1qYWFhwsyOFVzT7Jorn67vqxC0FRiw8YyG9P1ww==}
+
+ '@types/uuid@9.0.8':
+ resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
+
+ '@types/which@3.0.3':
+ resolution: {integrity: sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g==}
+
+ '@types/ws@8.5.10':
+ resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
+
+ '@typescript-eslint/eslint-plugin@7.10.0':
+ resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^7.0.0
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@typescript-eslint/parser@7.10.0':
+ resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@typescript-eslint/scope-manager@7.10.0':
+ resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
+ '@typescript-eslint/type-utils@7.10.0':
+ resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@typescript-eslint/types@7.10.0':
+ resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
+ '@typescript-eslint/typescript-estree@7.10.0':
+ resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@typescript-eslint/utils@7.10.0':
+ resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+
+ '@typescript-eslint/visitor-keys@7.10.0':
+ resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+
+ '@ungap/structured-clone@1.2.0':
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+
+ '@vercel/postgres@0.8.0':
+ resolution: {integrity: sha512-/QUV9ExwaNdKooRjOQqvrKNVnRvsaXeukPNI5DB1ovUTesglfR/fparw7ngo1KUWWKIVpEj2TRrA+ObRHRdaLg==}
+ engines: {node: '>=14.6'}
+
+ '@vitest/expect@1.6.0':
+ resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==}
+
+ '@vitest/runner@1.6.0':
+ resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==}
+
+ '@vitest/snapshot@1.6.0':
+ resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==}
+
+ '@vitest/spy@1.6.0':
+ resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==}
+
+ '@vitest/utils@1.6.0':
+ resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==}
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn-walk@8.3.2:
+ resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==}
+ engines: {node: '>=0.4.0'}
+
+ acorn@8.11.3:
+ resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ aggregate-error@4.0.1:
+ resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==}
+ engines: {node: '>=12'}
+
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+ ansi-escapes@6.2.1:
+ resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==}
+ engines: {node: '>=14.16'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ ansicolors@0.3.2:
+ resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ array-find-index@1.0.2:
+ resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==}
+ engines: {node: '>=0.10.0'}
+
+ array-union@2.1.0:
+ resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+ engines: {node: '>=8'}
+
+ arrgv@1.0.2:
+ resolution: {integrity: sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==}
+ engines: {node: '>=8.0.0'}
+
+ arrify@3.0.0:
+ resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==}
+ engines: {node: '>=12'}
+
+ as-table@1.0.55:
+ resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
+
+ asn1@0.2.6:
+ resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
+
+ assertion-error@1.1.0:
+ resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ ava@5.3.1:
+ resolution: {integrity: sha512-Scv9a4gMOXB6+ni4toLuhAm9KYWEjsgBglJl+kMGI5+IVDt120CCDZyB5HNU9DjmLI2t4I0GbnxGLmmRfGTJGg==}
+ engines: {node: '>=14.19 <15 || >=16.15 <17 || >=18'}
+ hasBin: true
+ peerDependencies:
+ '@ava/typescript': '*'
+ peerDependenciesMeta:
+ '@ava/typescript':
+ optional: true
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ bcrypt-pbkdf@1.0.2:
+ resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
+
+ better-sqlite3@9.6.0:
+ resolution: {integrity: sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==}
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ bindings@1.5.0:
+ resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
+ blake3-wasm@2.1.5:
+ resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
+
+ blueimp-md5@2.19.0:
+ resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
+
+ bowser@2.11.0:
+ resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==}
+
+ brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+
+ brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+
+ braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
+ bufferutil@4.0.8:
+ resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==}
+ engines: {node: '>=6.14.2'}
+
+ buildcheck@0.0.6:
+ resolution: {integrity: sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==}
+ engines: {node: '>=10.0.0'}
+
+ bundle-require@4.1.0:
+ resolution: {integrity: sha512-FeArRFM+ziGkRViKRnSTbHZc35dgmR9yNog05Kn0+ItI59pOAISGvnnIwW1WgFZQW59IxD9QpJnUPkdIPfZuXg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ peerDependencies:
+ esbuild: '>=0.17'
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ callsites@4.1.0:
+ resolution: {integrity: sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==}
+ engines: {node: '>=12.20'}
+
+ camelcase@7.0.1:
+ resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
+ engines: {node: '>=14.16'}
+
+ capnp-ts@0.7.0:
+ resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==}
+
+ cardinal@2.1.1:
+ resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==}
+ hasBin: true
+
+ cbor@8.1.0:
+ resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==}
+ engines: {node: '>=12.19'}
+
+ chai@4.4.1:
+ resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==}
+ engines: {node: '>=4'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ chalk@5.3.0:
+ resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+
+ char-regex@1.0.2:
+ resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
+ engines: {node: '>=10'}
+
+ check-error@1.0.3:
+ resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
+ chunkd@2.0.1:
+ resolution: {integrity: sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==}
+
+ ci-info@3.9.0:
+ resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+ engines: {node: '>=8'}
+
+ ci-parallel-vars@1.0.1:
+ resolution: {integrity: sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==}
+
+ clean-stack@4.2.0:
+ resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==}
+ engines: {node: '>=12'}
+
+ clean-yaml-object@0.1.0:
+ resolution: {integrity: sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==}
+ engines: {node: '>=0.10.0'}
+
+ cli-color@2.0.4:
+ resolution: {integrity: sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==}
+ engines: {node: '>=0.10'}
+
+ cli-table3@0.6.5:
+ resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
+ engines: {node: 10.* || >= 12.*}
+
+ cli-truncate@3.1.0:
+ resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ code-excerpt@4.0.0:
+ resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ colors@1.4.0:
+ resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==}
+ engines: {node: '>=0.1.90'}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@10.0.1:
+ resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+ engines: {node: '>=14'}
+
+ commander@12.1.0:
+ resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
+ engines: {node: '>=18'}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ commander@9.5.0:
+ resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
+ engines: {node: ^12.20.0 || >=14}
+
+ common-path-prefix@3.0.0:
+ resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ concordance@5.0.4:
+ resolution: {integrity: sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==}
+ engines: {node: '>=10.18.0 <11 || >=12.14.0 <13 || >=14'}
+
+ confbox@0.1.7:
+ resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
+
+ convert-to-spaces@2.0.1:
+ resolution: {integrity: sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ cookie@0.5.0:
+ resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
+ engines: {node: '>= 0.6'}
+
+ copy-anything@3.0.5:
+ resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
+ engines: {node: '>=12.13'}
+
+ cpu-features@0.0.10:
+ resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==}
+ engines: {node: '>=10.0.0'}
+
+ cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+
+ currently-unhandled@0.4.1:
+ resolution: {integrity: sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==}
+ engines: {node: '>=0.10.0'}
+
+ d@1.0.2:
+ resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
+ engines: {node: '>=0.12'}
+
+ data-uri-to-buffer@2.0.2:
+ resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
+
+ data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+
+ date-time@3.1.0:
+ resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
+ engines: {node: '>=6'}
+
+ debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ deep-eql@4.1.3:
+ resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
+ engines: {node: '>=6'}
+
+ deep-extend@0.6.0:
+ resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+ engines: {node: '>=4.0.0'}
+
+ deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ denque@2.1.0:
+ resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
+ engines: {node: '>=0.10'}
+
+ detect-libc@2.0.2:
+ resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
+ engines: {node: '>=8'}
+
+ detect-libc@2.0.3:
+ resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+ engines: {node: '>=8'}
+
+ diff-sequences@29.6.3:
+ resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ difflib@0.2.4:
+ resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==}
+
+ dir-glob@3.0.1:
+ resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+ engines: {node: '>=8'}
+
+ docker-modem@3.0.8:
+ resolution: {integrity: sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==}
+ engines: {node: '>= 8.0'}
+
+ dockerode@3.3.5:
+ resolution: {integrity: sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA==}
+ engines: {node: '>= 8.0'}
+
+ doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+
+ dotenv@16.4.5:
+ resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
+ engines: {node: '>=12'}
+
+ dreamopt@0.8.0:
+ resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==}
+ engines: {node: '>=0.4.0'}
+
+ drizzle-kit@0.21.2:
+ resolution: {integrity: sha512-U87IhZyCt/9d0ZT/Na3KFJVY31tSxtTx/n9UMcWFpW/5c2Ede39xiCG5efNV/0iimsv97UIRtDI0ldLBW5lbcg==}
+ hasBin: true
+
+ drizzle-orm@0.32.0-85c8008:
+ resolution: {integrity: sha512-gHLqGZz0eqAvSw4vq46sHRV8qLHxrbuCVlwaVZ1t4ntyH8csyCKEXTWO78cBJwYUpz7BCSzqVX+5ZYa/QM+/Gw==}
+ peerDependencies:
+ '@aws-sdk/client-rds-data': '>=3'
+ '@cloudflare/workers-types': '>=3'
+ '@electric-sql/pglite': '>=0.1.1'
+ '@libsql/client': '*'
+ '@neondatabase/serverless': '>=0.1'
+ '@op-engineering/op-sqlite': '>=2'
+ '@opentelemetry/api': ^1.4.1
+ '@planetscale/database': '>=1'
+ '@tidbcloud/serverless': '*'
+ '@types/better-sqlite3': '*'
+ '@types/pg': '*'
+ '@types/react': '>=18'
+ '@types/sql.js': '*'
+ '@vercel/postgres': '>=0.8.0'
+ '@xata.io/client': '*'
+ better-sqlite3: '>=7'
+ bun-types: '*'
+ expo-sqlite: '>=13.2.0'
+ knex: '*'
+ kysely: '*'
+ mysql2: '>=2'
+ pg: '>=8'
+ postgres: '>=3'
+ react: '>=18'
+ sql.js: '>=1'
+ sqlite3: '>=5'
+ peerDependenciesMeta:
+ '@aws-sdk/client-rds-data':
+ optional: true
+ '@cloudflare/workers-types':
+ optional: true
+ '@electric-sql/pglite':
+ optional: true
+ '@libsql/client':
+ optional: true
+ '@neondatabase/serverless':
+ optional: true
+ '@op-engineering/op-sqlite':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@tidbcloud/serverless':
+ optional: true
+ '@types/better-sqlite3':
+ optional: true
+ '@types/pg':
+ optional: true
+ '@types/react':
+ optional: true
+ '@types/sql.js':
+ optional: true
+ '@vercel/postgres':
+ optional: true
+ '@xata.io/client':
+ optional: true
+ better-sqlite3:
+ optional: true
+ bun-types:
+ optional: true
+ expo-sqlite:
+ optional: true
+ knex:
+ optional: true
+ kysely:
+ optional: true
+ mysql2:
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+ react:
+ optional: true
+ sql.js:
+ optional: true
+ sqlite3:
+ optional: true
+
+ duplexer@0.1.2:
+ resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
+
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ emittery@1.0.3:
+ resolution: {integrity: sha512-tJdCJitoy2lrC2ldJcqN4vkqJ00lT+tOWNT1hBJjO/3FDMJa5TTIiYGCKGkn/WfCyOzUMObeohbVTj00fhiLiA==}
+ engines: {node: '>=14.16'}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ emojilib@2.4.0:
+ resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
+
+ end-of-stream@1.4.4:
+ resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
+
+ env-paths@3.0.0:
+ resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ es5-ext@0.10.64:
+ resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
+ engines: {node: '>=0.10'}
+
+ es6-iterator@2.0.3:
+ resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
+
+ es6-symbol@3.1.4:
+ resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
+ engines: {node: '>=0.12'}
+
+ es6-weak-map@2.0.3:
+ resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==}
+
+ esbuild-android-64@0.14.54:
+ resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
+ esbuild-android-arm64@0.14.54:
+ resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
+ esbuild-darwin-64@0.14.54:
+ resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
+ esbuild-darwin-arm64@0.14.54:
+ resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
+ esbuild-freebsd-64@0.14.54:
+ resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
+ esbuild-freebsd-arm64@0.14.54:
+ resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ esbuild-linux-32@0.14.54:
+ resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
+ esbuild-linux-64@0.14.54:
+ resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
+ esbuild-linux-arm64@0.14.54:
+ resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
+ esbuild-linux-arm@0.14.54:
+ resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
+ esbuild-linux-mips64le@0.14.54:
+ resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
+ esbuild-linux-ppc64le@0.14.54:
+ resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
+ esbuild-linux-riscv64@0.14.54:
+ resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
+ esbuild-linux-s390x@0.14.54:
+ resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
+ esbuild-netbsd-64@0.14.54:
+ resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
+ esbuild-node-externals@1.13.1:
+ resolution: {integrity: sha512-ho4Lokc6iMB1lWbb2tWJ6otien+3Kfoaxe0fy7NUNgVuLnfmlW+GRINftTVUGtTVY/dapuwUu/CvFylYNwzkMA==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ esbuild: 0.12 - 0.21
+
+ esbuild-openbsd-64@0.14.54:
+ resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
+ esbuild-register@3.5.0:
+ resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==}
+ peerDependencies:
+ esbuild: '>=0.12 <1'
+
+ esbuild-sunos-64@0.14.54:
+ resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
+ esbuild-windows-32@0.14.54:
+ resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
+ esbuild-windows-64@0.14.54:
+ resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
+ esbuild-windows-arm64@0.14.54:
+ resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
+ esbuild@0.14.54:
+ resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ esbuild@0.17.19:
+ resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ esbuild@0.18.20:
+ resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ esbuild@0.19.12:
+ resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ esbuild@0.20.2:
+ resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ escalade@3.1.2:
+ resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@2.0.0:
+ resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+ engines: {node: '>=8'}
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
+ eslint-config-prettier@9.1.0:
+ resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+
+ eslint-plugin-prettier@5.1.3:
+ resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ '@types/eslint': '>=8.0.0'
+ eslint: '>=8.0.0'
+ eslint-config-prettier: '*'
+ prettier: '>=3.0.0'
+ peerDependenciesMeta:
+ '@types/eslint':
+ optional: true
+ eslint-config-prettier:
+ optional: true
+
+ eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ eslint@8.57.0:
+ resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+
+ esniff@2.0.1:
+ resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
+ engines: {node: '>=0.10'}
+
+ espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+
+ esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@0.6.1:
+ resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ event-emitter@0.3.5:
+ resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
+
+ event-stream@3.3.4:
+ resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==}
+
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
+ execa@8.0.1:
+ resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
+ engines: {node: '>=16.17'}
+
+ exit-hook@2.2.1:
+ resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
+ engines: {node: '>=6'}
+
+ expand-template@2.0.3:
+ resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+ engines: {node: '>=6'}
+
+ ext@1.7.0:
+ resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-diff@1.3.0:
+ resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
+
+ fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+ fast-xml-parser@4.2.5:
+ resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==}
+ hasBin: true
+
+ fastq@1.17.1:
+ resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+
+ fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+
+ fflate@0.8.2:
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
+
+ figures@5.0.0:
+ resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==}
+ engines: {node: '>=14'}
+
+ file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+
+ file-uri-to-path@1.0.0:
+ resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ find-up@6.3.0:
+ resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+
+ flatted@3.3.1:
+ resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+
+ foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+
+ form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+
+ formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+
+ from@0.1.7:
+ resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
+
+ fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
+ fs-extra@11.2.0:
+ resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
+ engines: {node: '>=14.14'}
+
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ fx@34.0.0:
+ resolution: {integrity: sha512-/fZih3/WLsrtlaj2mahjWxAmyuikmcl3D5kKPqLtFmEilLsy9wp0+/vEmfvYXXhwJc+ajtCFDCf+yttXmPMHSQ==}
+ hasBin: true
+
+ generate-function@2.3.1:
+ resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==}
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ get-func-name@2.0.2:
+ resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
+
+ get-port@6.1.2:
+ resolution: {integrity: sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ get-source@2.0.12:
+ resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
+
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
+ get-stream@8.0.1:
+ resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
+ engines: {node: '>=16'}
+
+ get-tsconfig@4.7.5:
+ resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==}
+
+ github-from-package@0.0.0:
+ resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ glob-to-regexp@0.4.1:
+ resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
+
+ glob@10.3.15:
+ resolution: {integrity: sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==}
+ engines: {node: '>=16 || 14 >=14.18'}
+ hasBin: true
+
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+
+ glob@8.1.0:
+ resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
+ engines: {node: '>=12'}
+
+ globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
+
+ globby@11.1.0:
+ resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+ engines: {node: '>=10'}
+
+ globby@13.2.2:
+ resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ globrex@0.1.2:
+ resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+
+ hanji@0.0.5:
+ resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ heap@0.2.7:
+ resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
+
+ hono@4.3.9:
+ resolution: {integrity: sha512-6c5LVE23HnIS8iBhY+XPmYJlPeeClznOi7mBNsAsJCgxo8Ciz75LTjqRUf5wv4RYq8kL+1KPLUZHCtKmbZssNg==}
+ engines: {node: '>=16.0.0'}
+
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
+ human-signals@5.0.0:
+ resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
+ engines: {node: '>=16.17.0'}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
+ ignore-by-default@2.1.0:
+ resolution: {integrity: sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==}
+ engines: {node: '>=10 <11 || >=12 <13 || >=14'}
+
+ ignore@5.3.1:
+ resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
+ engines: {node: '>= 4'}
+
+ import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
+ indent-string@5.0.0:
+ resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
+ engines: {node: '>=12'}
+
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
+ irregular-plurals@3.5.0:
+ resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==}
+ engines: {node: '>=8'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-core-module@2.13.1:
+ resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+
+ is-error@2.2.2:
+ resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-fullwidth-code-point@4.0.0:
+ resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
+ engines: {node: '>=12'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+
+ is-plain-object@5.0.0:
+ resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
+ engines: {node: '>=0.10.0'}
+
+ is-promise@2.2.2:
+ resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
+
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
+ is-property@1.0.2:
+ resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
+
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
+ is-stream@3.0.0:
+ resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ is-unicode-supported@1.3.0:
+ resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
+ engines: {node: '>=12'}
+
+ is-what@4.1.16:
+ resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
+ engines: {node: '>=12.13'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+
+ joycon@3.1.1:
+ resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
+ engines: {node: '>=10'}
+
+ js-base64@3.7.7:
+ resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
+
+ js-string-escape@1.0.1:
+ resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==}
+ engines: {node: '>= 0.8'}
+
+ js-tokens@9.0.0:
+ resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==}
+
+ js-yaml@3.14.1:
+ resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+ hasBin: true
+
+ js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-diff@0.9.0:
+ resolution: {integrity: sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==}
+ hasBin: true
+
+ json-diff@1.0.6:
+ resolution: {integrity: sha512-tcFIPRdlc35YkYdGxcamJjllUhXWv4n2rK9oJ2RsAzV4FBkuV4ojKEDgcZ+kpKxDmJKv+PFK65+1tVVOnSeEqA==}
+ hasBin: true
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+ jsonfile@6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+
+ libsql@0.2.0:
+ resolution: {integrity: sha512-ELBRqhpJx5Dap0187zKQnntZyk4EjlDHSrjIVL8t+fQ5e8IxbQTeYgZgigMjB1EvrETdkm0Y0VxBGhzPQ+t0Jg==}
+ cpu: [x64, arm64]
+ os: [darwin, linux, win32]
+
+ lilconfig@3.1.1:
+ resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==}
+ engines: {node: '>=14'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ load-json-file@7.0.1:
+ resolution: {integrity: sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ load-tsconfig@0.2.5:
+ resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ local-pkg@0.5.0:
+ resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
+ engines: {node: '>=14'}
+
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
+ locate-path@7.2.0:
+ resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+ lodash.sortby@4.7.0:
+ resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
+
+ lodash.throttle@4.1.1:
+ resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
+
+ lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
+ long@4.0.0:
+ resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
+
+ loupe@2.3.7:
+ resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
+
+ lru-cache@10.2.2:
+ resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==}
+ engines: {node: 14 || >=16.14}
+
+ lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+
+ lru-cache@7.18.3:
+ resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
+ engines: {node: '>=12'}
+
+ lru-queue@0.1.0:
+ resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==}
+
+ magic-string@0.25.9:
+ resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+
+ magic-string@0.30.10:
+ resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
+
+ map-age-cleaner@0.1.3:
+ resolution: {integrity: sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==}
+ engines: {node: '>=6'}
+
+ map-stream@0.1.0:
+ resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==}
+
+ marked-terminal@6.2.0:
+ resolution: {integrity: sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ marked: '>=1 <12'
+
+ marked@9.1.6:
+ resolution: {integrity: sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==}
+ engines: {node: '>= 16'}
+ hasBin: true
+
+ matcher@5.0.0:
+ resolution: {integrity: sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ md5-hex@3.0.1:
+ resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
+ engines: {node: '>=8'}
+
+ mem@9.0.2:
+ resolution: {integrity: sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==}
+ engines: {node: '>=12.20'}
+
+ memoizee@0.4.15:
+ resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==}
+
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ mime@3.0.0:
+ resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
+ mimic-fn@4.0.0:
+ resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
+ engines: {node: '>=12'}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
+ miniflare@3.20240512.0:
+ resolution: {integrity: sha512-X0PlKR0AROKpxFoJNmRtCMIuJxj+ngEcyTOlEokj2rAQ0TBwUhB4/1uiPvdI6ofW5NugPOD1uomAv+gLjwsLDQ==}
+ engines: {node: '>=16.13'}
+ hasBin: true
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+
+ minimatch@7.4.6:
+ resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==}
+ engines: {node: '>=10'}
+
+ minimatch@9.0.4:
+ resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ minipass@7.1.1:
+ resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
+ mlly@1.7.0:
+ resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==}
+
+ ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mustache@4.2.0:
+ resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
+ hasBin: true
+
+ mysql2@2.3.3:
+ resolution: {integrity: sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==}
+ engines: {node: '>= 8.0'}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ named-placeholders@1.1.3:
+ resolution: {integrity: sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==}
+ engines: {node: '>=12.0.0'}
+
+ nan@2.19.0:
+ resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==}
+
+ nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ napi-build-utils@1.0.2:
+ resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+ next-tick@1.1.0:
+ resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
+
+ node-abi@3.62.0:
+ resolution: {integrity: sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==}
+ engines: {node: '>=10'}
+
+ node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+
+ node-emoji@2.1.3:
+ resolution: {integrity: sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==}
+ engines: {node: '>=18'}
+
+ node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-fetch@3.3.1:
+ resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ node-forge@1.3.1:
+ resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
+ engines: {node: '>= 6.13.0'}
+
+ node-gyp-build@4.8.1:
+ resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==}
+ hasBin: true
+
+ nofilter@3.1.0:
+ resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==}
+ engines: {node: '>=12.19'}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
+ npm-run-path@5.3.0:
+ resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ obuf@1.1.2:
+ resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
+ onetime@6.0.0:
+ resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
+ engines: {node: '>=12'}
+
+ optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+
+ p-defer@1.0.0:
+ resolution: {integrity: sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==}
+ engines: {node: '>=4'}
+
+ p-event@5.0.1:
+ resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+
+ p-limit@4.0.0:
+ resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ p-limit@5.0.0:
+ resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==}
+ engines: {node: '>=18'}
+
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
+ p-locate@6.0.0:
+ resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ p-map@5.5.0:
+ resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
+ engines: {node: '>=12'}
+
+ p-timeout@5.1.0:
+ resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==}
+ engines: {node: '>=12'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ parse-ms@3.0.0:
+ resolution: {integrity: sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==}
+ engines: {node: '>=12'}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-exists@5.0.0:
+ resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
+ path-to-regexp@6.2.2:
+ resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==}
+
+ path-type@4.0.0:
+ resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+ engines: {node: '>=8'}
+
+ pathe@1.1.2:
+ resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+
+ pathval@1.1.1:
+ resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
+
+ pause-stream@0.0.11:
+ resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==}
+
+ pg-cloudflare@1.1.1:
+ resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
+
+ pg-connection-string@2.6.4:
+ resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==}
+
+ pg-int8@1.0.1:
+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
+ engines: {node: '>=4.0.0'}
+
+ pg-numeric@1.0.2:
+ resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==}
+ engines: {node: '>=4'}
+
+ pg-pool@3.6.2:
+ resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==}
+ peerDependencies:
+ pg: '>=8.0'
+
+ pg-protocol@1.6.1:
+ resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==}
+
+ pg-types@2.2.0:
+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
+ engines: {node: '>=4'}
+
+ pg-types@4.0.2:
+ resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==}
+ engines: {node: '>=10'}
+
+ pg@8.11.5:
+ resolution: {integrity: sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==}
+ engines: {node: '>= 8.0.0'}
+ peerDependencies:
+ pg-native: '>=3.0.1'
+ peerDependenciesMeta:
+ pg-native:
+ optional: true
+
+ pgpass@1.0.5:
+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
+
+ picocolors@1.0.1:
+ resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+
+ pkg-conf@4.0.0:
+ resolution: {integrity: sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ pkg-types@1.1.1:
+ resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==}
+
+ plur@5.1.0:
+ resolution: {integrity: sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ pluralize@8.0.0:
+ resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
+ engines: {node: '>=4'}
+
+ postcss-load-config@4.0.2:
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+
+ postcss@8.4.38:
+ resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ postgres-array@2.0.0:
+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
+ engines: {node: '>=4'}
+
+ postgres-array@3.0.2:
+ resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==}
+ engines: {node: '>=12'}
+
+ postgres-bytea@1.0.0:
+ resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-bytea@3.0.0:
+ resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==}
+ engines: {node: '>= 6'}
+
+ postgres-date@1.0.7:
+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-date@2.1.0:
+ resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==}
+ engines: {node: '>=12'}
+
+ postgres-interval@1.2.0:
+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
+ engines: {node: '>=0.10.0'}
+
+ postgres-interval@3.0.0:
+ resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==}
+ engines: {node: '>=12'}
+
+ postgres-range@1.1.4:
+ resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
+
+ postgres@3.4.4:
+ resolution: {integrity: sha512-IbyN+9KslkqcXa8AO9fxpk97PA4pzewvpi2B3Dwy9u4zpV32QicaEdgmF3eSQUzdRk7ttDHQejNgAEr4XoeH4A==}
+ engines: {node: '>=12'}
+
+ prebuild-install@7.1.2:
+ resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+
+ prettier-linter-helpers@1.0.0:
+ resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
+ engines: {node: '>=6.0.0'}
+
+ prettier@2.8.8:
+ resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+
+ pretty-format@29.7.0:
+ resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+
+ pretty-ms@8.0.0:
+ resolution: {integrity: sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==}
+ engines: {node: '>=14.16'}
+
+ printable-characters@1.0.42:
+ resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
+
+ ps-tree@1.2.0:
+ resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
+ engines: {node: '>= 0.10'}
+ hasBin: true
+
+ pump@3.0.0:
+ resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+
+ react-is@18.3.1:
+ resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ redeyed@2.1.1:
+ resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==}
+
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ resolve-cwd@3.0.0:
+ resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
+ engines: {node: '>=8'}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+ resolve.exports@2.0.2:
+ resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
+ engines: {node: '>=10'}
+
+ resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+
+ reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+
+ rollup-plugin-inject@3.0.2:
+ resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==}
+ deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.
+
+ rollup-plugin-node-polyfills@0.2.1:
+ resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==}
+
+ rollup-pluginutils@2.8.2:
+ resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
+
+ rollup@4.17.2:
+ resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ selfsigned@2.4.1:
+ resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
+ engines: {node: '>=10'}
+
+ semver@7.6.2:
+ resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ seq-queue@0.0.5:
+ resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==}
+
+ serialize-error@7.0.1:
+ resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
+ engines: {node: '>=10'}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ simple-concat@1.0.1:
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+ simple-get@4.0.1:
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
+ skin-tone@2.0.0:
+ resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
+ engines: {node: '>=8'}
+
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
+ slash@4.0.0:
+ resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
+ engines: {node: '>=12'}
+
+ slice-ansi@5.0.0:
+ resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
+ engines: {node: '>=12'}
+
+ source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ engines: {node: '>=0.10.0'}
+
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ source-map@0.8.0-beta.0:
+ resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
+ engines: {node: '>= 8'}
+
+ sourcemap-codec@1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ deprecated: Please use @jridgewell/sourcemap-codec instead
+
+ split-ca@1.0.1:
+ resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==}
+
+ split2@4.2.0:
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
+ engines: {node: '>= 10.x'}
+
+ split@0.3.3:
+ resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==}
+
+ sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
+ sqlstring@2.3.3:
+ resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
+ engines: {node: '>= 0.6'}
+
+ ssh2@1.15.0:
+ resolution: {integrity: sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==}
+ engines: {node: '>=10.16.0'}
+
+ stack-utils@2.0.6:
+ resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+ engines: {node: '>=10'}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ stacktracey@2.1.8:
+ resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==}
+
+ std-env@3.7.0:
+ resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
+
+ stoppable@1.1.0:
+ resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
+ engines: {node: '>=4', npm: '>=6'}
+
+ stream-combiner@0.0.4:
+ resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
+ string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
+ strip-final-newline@3.0.0:
+ resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
+ engines: {node: '>=12'}
+
+ strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+
+ strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+
+ strip-literal@2.1.0:
+ resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==}
+
+ strnum@1.0.5:
+ resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
+
+ sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ superjson@2.2.1:
+ resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==}
+ engines: {node: '>=16'}
+
+ supertap@3.0.1:
+ resolution: {integrity: sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ supports-hyperlinks@3.0.0:
+ resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==}
+ engines: {node: '>=14.18'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ synckit@0.8.8:
+ resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+
+ tar-fs@2.0.1:
+ resolution: {integrity: sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==}
+
+ tar-fs@2.1.1:
+ resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
+
+ tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+
+ temp-dir@3.0.0:
+ resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==}
+ engines: {node: '>=14.16'}
+
+ text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ through@2.3.8:
+ resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+
+ time-zone@1.0.0:
+ resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==}
+ engines: {node: '>=4'}
+
+ timers-ext@0.1.7:
+ resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==}
+
+ tinybench@2.8.0:
+ resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==}
+
+ tinypool@0.8.4:
+ resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@2.2.1:
+ resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==}
+ engines: {node: '>=14.0.0'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+ tr46@1.0.1:
+ resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
+
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
+ ts-api-utils@1.3.0:
+ resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ typescript: '>=4.2.0'
+
+ ts-expose-internals-conditionally@1.0.0-empty.0:
+ resolution: {integrity: sha512-F8m9NOF6ZhdOClDVdlM8gj3fDCav4ZIFSs/EI3ksQbAAXVSCN/Jh5OCJDDZWBuBy9psFc6jULGDlPwjMYMhJDw==}
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tsconfck@3.0.3:
+ resolution: {integrity: sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
+ tslib@2.6.2:
+ resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+
+ tsup@8.0.2:
+ resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==}
+ 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
+
+ tsx@3.14.0:
+ resolution: {integrity: sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==}
+ hasBin: true
+
+ tunnel-agent@0.6.0:
+ resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
+ tweetnacl@0.14.5:
+ resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
+
+ type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+
+ type-detect@4.0.8:
+ resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+ engines: {node: '>=4'}
+
+ type-fest@0.13.1:
+ resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
+ engines: {node: '>=10'}
+
+ type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+
+ type@2.7.2:
+ resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==}
+
+ typescript@5.3.3:
+ resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ typescript@5.4.5:
+ resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ ufo@1.5.3:
+ resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
+
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+ undici@5.28.4:
+ resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
+ engines: {node: '>=14.0'}
+
+ unicode-emoji-modifier-base@1.0.0:
+ resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
+ engines: {node: '>=4'}
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ utf-8-validate@6.0.3:
+ resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==}
+ engines: {node: '>=6.14.2'}
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ uuid@9.0.1:
+ resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
+ hasBin: true
+
+ validate-npm-package-name@5.0.1:
+ resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ vite-node@1.6.0:
+ resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+
+ vite-tsconfig-paths@4.3.2:
+ resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==}
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
+ vite@5.2.11:
+ resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
+ vitest@1.6.0:
+ resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/node': ^18.0.0 || >=20.0.0
+ '@vitest/browser': 1.6.0
+ '@vitest/ui': 1.6.0
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ web-streams-polyfill@3.3.3:
+ resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
+ engines: {node: '>= 8'}
+
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ webidl-conversions@4.0.2:
+ resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
+
+ webpod@0.0.2:
+ resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==}
+ hasBin: true
+
+ well-known-symbols@2.0.0:
+ resolution: {integrity: sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==}
+ engines: {node: '>=6'}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+ whatwg-url@7.1.0:
+ resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ which@3.0.1:
+ resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ hasBin: true
+
+ why-is-node-running@2.2.2:
+ resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+
+ wordwrap@1.0.0:
+ resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
+
+ workerd@1.20240512.0:
+ resolution: {integrity: sha512-VUBmR1PscAPHEE0OF/G2K7/H1gnr9aDWWZzdkIgWfNKkv8dKFCT75H+GJtUHjfwqz3rYCzaNZmatSXOpLGpF8A==}
+ engines: {node: '>=16'}
+ hasBin: true
+
+ wrangler@3.57.0:
+ resolution: {integrity: sha512-izK3AZtlFoTq8N0EZjLOQ7hqwsjaXCc1cbNKuhsLJjDX1jB1YZBDPhIhtXL4VVzkJAcH+0Zw2gguOePFCHNaxw==}
+ engines: {node: '>=16.17.0'}
+ hasBin: true
+ peerDependencies:
+ '@cloudflare/workers-types': ^4.20240512.0
+ peerDependenciesMeta:
+ '@cloudflare/workers-types':
+ optional: true
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ write-file-atomic@5.0.1:
+ resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ ws@8.14.2:
+ resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ ws@8.17.0:
+ resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xtend@4.0.2:
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+ engines: {node: '>=0.4'}
+
+ xxhash-wasm@1.0.2:
+ resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
+ yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
+ yaml@2.4.2:
+ resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==}
+ engines: {node: '>= 14'}
+ hasBin: true
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+ yocto-queue@1.0.0:
+ resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
+ engines: {node: '>=12.20'}
+
+ youch@3.3.3:
+ resolution: {integrity: sha512-qSFXUk3UZBLfggAW3dJKg0BMblG5biqSF8M34E06o5CSsZtH92u9Hqmj2RzGiHDi64fhe83+4tENFP2DB6t6ZA==}
+
+ zod@3.23.8:
+ resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
+
+ zx@7.2.3:
+ resolution: {integrity: sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==}
+ engines: {node: '>= 16.0.0'}
+ hasBin: true
+
+snapshots:
+
+ '@andrewbranch/untar.js@1.0.3': {}
+
+ '@arethetypeswrong/cli@0.15.3':
+ dependencies:
+ '@arethetypeswrong/core': 0.15.1
+ chalk: 4.1.2
+ cli-table3: 0.6.5
+ commander: 10.0.1
+ marked: 9.1.6
+ marked-terminal: 6.2.0(marked@9.1.6)
+ semver: 7.6.2
+
+ '@arethetypeswrong/core@0.15.1':
+ dependencies:
+ '@andrewbranch/untar.js': 1.0.3
+ fflate: 0.8.2
+ semver: 7.6.2
+ ts-expose-internals-conditionally: 1.0.0-empty.0
+ typescript: 5.3.3
+ validate-npm-package-name: 5.0.1
+
+ '@aws-crypto/ie11-detection@3.0.0':
+ dependencies:
+ tslib: 1.14.1
+
+ '@aws-crypto/sha256-browser@3.0.0':
+ dependencies:
+ '@aws-crypto/ie11-detection': 3.0.0
+ '@aws-crypto/sha256-js': 3.0.0
+ '@aws-crypto/supports-web-crypto': 3.0.0
+ '@aws-crypto/util': 3.0.0
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-locate-window': 3.568.0
+ '@aws-sdk/util-utf8-browser': 3.259.0
+ tslib: 1.14.1
+
+ '@aws-crypto/sha256-js@3.0.0':
+ dependencies:
+ '@aws-crypto/util': 3.0.0
+ '@aws-sdk/types': 3.577.0
+ tslib: 1.14.1
+
+ '@aws-crypto/supports-web-crypto@3.0.0':
+ dependencies:
+ tslib: 1.14.1
+
+ '@aws-crypto/util@3.0.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-utf8-browser': 3.259.0
+ tslib: 1.14.1
+
+ '@aws-sdk/client-rds-data@3.577.0':
+ dependencies:
+ '@aws-crypto/sha256-browser': 3.0.0
+ '@aws-crypto/sha256-js': 3.0.0
+ '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/core': 3.576.0
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/middleware-host-header': 3.577.0
+ '@aws-sdk/middleware-logger': 3.577.0
+ '@aws-sdk/middleware-recursion-detection': 3.577.0
+ '@aws-sdk/middleware-user-agent': 3.577.0
+ '@aws-sdk/region-config-resolver': 3.577.0
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-endpoints': 3.577.0
+ '@aws-sdk/util-user-agent-browser': 3.577.0
+ '@aws-sdk/util-user-agent-node': 3.577.0
+ '@smithy/config-resolver': 3.0.0
+ '@smithy/core': 2.0.1
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/hash-node': 3.0.0
+ '@smithy/invalid-dependency': 3.0.0
+ '@smithy/middleware-content-length': 3.0.0
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-retry': 3.0.1
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/middleware-stack': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ '@smithy/util-body-length-browser': 3.0.0
+ '@smithy/util-body-length-node': 3.0.0
+ '@smithy/util-defaults-mode-browser': 3.0.1
+ '@smithy/util-defaults-mode-node': 3.0.1
+ '@smithy/util-endpoints': 2.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-retry': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - aws-crt
+
+ '@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0)':
+ dependencies:
+ '@aws-crypto/sha256-browser': 3.0.0
+ '@aws-crypto/sha256-js': 3.0.0
+ '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/core': 3.576.0
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/middleware-host-header': 3.577.0
+ '@aws-sdk/middleware-logger': 3.577.0
+ '@aws-sdk/middleware-recursion-detection': 3.577.0
+ '@aws-sdk/middleware-user-agent': 3.577.0
+ '@aws-sdk/region-config-resolver': 3.577.0
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-endpoints': 3.577.0
+ '@aws-sdk/util-user-agent-browser': 3.577.0
+ '@aws-sdk/util-user-agent-node': 3.577.0
+ '@smithy/config-resolver': 3.0.0
+ '@smithy/core': 2.0.1
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/hash-node': 3.0.0
+ '@smithy/invalid-dependency': 3.0.0
+ '@smithy/middleware-content-length': 3.0.0
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-retry': 3.0.1
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/middleware-stack': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ '@smithy/util-body-length-browser': 3.0.0
+ '@smithy/util-body-length-node': 3.0.0
+ '@smithy/util-defaults-mode-browser': 3.0.1
+ '@smithy/util-defaults-mode-node': 3.0.1
+ '@smithy/util-endpoints': 2.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-retry': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - '@aws-sdk/client-sts'
+ - aws-crt
+
+ '@aws-sdk/client-sso@3.577.0':
+ dependencies:
+ '@aws-crypto/sha256-browser': 3.0.0
+ '@aws-crypto/sha256-js': 3.0.0
+ '@aws-sdk/core': 3.576.0
+ '@aws-sdk/middleware-host-header': 3.577.0
+ '@aws-sdk/middleware-logger': 3.577.0
+ '@aws-sdk/middleware-recursion-detection': 3.577.0
+ '@aws-sdk/middleware-user-agent': 3.577.0
+ '@aws-sdk/region-config-resolver': 3.577.0
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-endpoints': 3.577.0
+ '@aws-sdk/util-user-agent-browser': 3.577.0
+ '@aws-sdk/util-user-agent-node': 3.577.0
+ '@smithy/config-resolver': 3.0.0
+ '@smithy/core': 2.0.1
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/hash-node': 3.0.0
+ '@smithy/invalid-dependency': 3.0.0
+ '@smithy/middleware-content-length': 3.0.0
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-retry': 3.0.1
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/middleware-stack': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ '@smithy/util-body-length-browser': 3.0.0
+ '@smithy/util-body-length-node': 3.0.0
+ '@smithy/util-defaults-mode-browser': 3.0.1
+ '@smithy/util-defaults-mode-node': 3.0.1
+ '@smithy/util-endpoints': 2.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-retry': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - aws-crt
+
+ '@aws-sdk/client-sts@3.577.0':
+ dependencies:
+ '@aws-crypto/sha256-browser': 3.0.0
+ '@aws-crypto/sha256-js': 3.0.0
+ '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/core': 3.576.0
+ '@aws-sdk/credential-provider-node': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/middleware-host-header': 3.577.0
+ '@aws-sdk/middleware-logger': 3.577.0
+ '@aws-sdk/middleware-recursion-detection': 3.577.0
+ '@aws-sdk/middleware-user-agent': 3.577.0
+ '@aws-sdk/region-config-resolver': 3.577.0
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-endpoints': 3.577.0
+ '@aws-sdk/util-user-agent-browser': 3.577.0
+ '@aws-sdk/util-user-agent-node': 3.577.0
+ '@smithy/config-resolver': 3.0.0
+ '@smithy/core': 2.0.1
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/hash-node': 3.0.0
+ '@smithy/invalid-dependency': 3.0.0
+ '@smithy/middleware-content-length': 3.0.0
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-retry': 3.0.1
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/middleware-stack': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ '@smithy/util-body-length-browser': 3.0.0
+ '@smithy/util-body-length-node': 3.0.0
+ '@smithy/util-defaults-mode-browser': 3.0.1
+ '@smithy/util-defaults-mode-node': 3.0.1
+ '@smithy/util-endpoints': 2.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-retry': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - aws-crt
+
+ '@aws-sdk/core@3.576.0':
+ dependencies:
+ '@smithy/core': 2.0.1
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/signature-v4': 3.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ fast-xml-parser: 4.2.5
+ tslib: 2.6.2
+
+ '@aws-sdk/credential-provider-env@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/credential-provider-http@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/util-stream': 3.0.1
+ tslib: 2.6.2
+
+ '@aws-sdk/credential-provider-ini@3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)':
+ dependencies:
+ '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/credential-provider-env': 3.577.0
+ '@aws-sdk/credential-provider-process': 3.577.0
+ '@aws-sdk/credential-provider-sso': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))
+ '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/types': 3.577.0
+ '@smithy/credential-provider-imds': 3.0.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - '@aws-sdk/client-sso-oidc'
+ - aws-crt
+
+ '@aws-sdk/credential-provider-node@3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)':
+ dependencies:
+ '@aws-sdk/credential-provider-env': 3.577.0
+ '@aws-sdk/credential-provider-http': 3.577.0
+ '@aws-sdk/credential-provider-ini': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/credential-provider-process': 3.577.0
+ '@aws-sdk/credential-provider-sso': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))
+ '@aws-sdk/credential-provider-web-identity': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/types': 3.577.0
+ '@smithy/credential-provider-imds': 3.0.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - '@aws-sdk/client-sso-oidc'
+ - '@aws-sdk/client-sts'
+ - aws-crt
+
+ '@aws-sdk/credential-provider-process@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/credential-provider-sso@3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))':
+ dependencies:
+ '@aws-sdk/client-sso': 3.577.0
+ '@aws-sdk/token-providers': 3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))
+ '@aws-sdk/types': 3.577.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - '@aws-sdk/client-sso-oidc'
+ - aws-crt
+
+ '@aws-sdk/credential-provider-web-identity@3.577.0(@aws-sdk/client-sts@3.577.0)':
+ dependencies:
+ '@aws-sdk/client-sts': 3.577.0
+ '@aws-sdk/types': 3.577.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/middleware-host-header@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/middleware-logger@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/middleware-recursion-detection@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/middleware-user-agent@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@aws-sdk/util-endpoints': 3.577.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/region-config-resolver@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-config-provider': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/token-providers@3.577.0(@aws-sdk/client-sso-oidc@3.577.0(@aws-sdk/client-sts@3.577.0))':
+ dependencies:
+ '@aws-sdk/client-sso-oidc': 3.577.0(@aws-sdk/client-sts@3.577.0)
+ '@aws-sdk/types': 3.577.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/types@3.577.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/util-endpoints@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-endpoints': 2.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/util-locate-window@3.568.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@aws-sdk/util-user-agent-browser@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/types': 3.0.0
+ bowser: 2.11.0
+ tslib: 2.6.2
+
+ '@aws-sdk/util-user-agent-node@3.577.0':
+ dependencies:
+ '@aws-sdk/types': 3.577.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@aws-sdk/util-utf8-browser@3.259.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@balena/dockerignore@1.0.2': {}
+
+ '@cloudflare/kv-asset-handler@0.3.2':
+ dependencies:
+ mime: 3.0.0
+
+ '@cloudflare/workerd-darwin-64@1.20240512.0':
+ optional: true
+
+ '@cloudflare/workerd-darwin-arm64@1.20240512.0':
+ optional: true
+
+ '@cloudflare/workerd-linux-64@1.20240512.0':
+ optional: true
+
+ '@cloudflare/workerd-linux-arm64@1.20240512.0':
+ optional: true
+
+ '@cloudflare/workerd-windows-64@1.20240512.0':
+ optional: true
+
+ '@cloudflare/workers-types@4.20240512.0': {}
+
+ '@colors/colors@1.5.0':
+ optional: true
+
+ '@cspotcode/source-map-support@0.8.1':
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.9
+
+ '@electric-sql/pglite@0.1.5': {}
+
+ '@esbuild-kit/core-utils@3.3.2':
+ dependencies:
+ esbuild: 0.18.20
+ source-map-support: 0.5.21
+
+ '@esbuild-kit/esm-loader@2.6.5':
+ dependencies:
+ '@esbuild-kit/core-utils': 3.3.2
+ get-tsconfig: 4.7.5
+
+ '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)':
+ dependencies:
+ esbuild: 0.17.19
+
+ '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)':
+ dependencies:
+ esbuild: 0.17.19
+ escape-string-regexp: 4.0.0
+ rollup-plugin-node-polyfills: 0.2.1
+
+ '@esbuild/aix-ppc64@0.19.12':
+ optional: true
+
+ '@esbuild/aix-ppc64@0.20.2':
+ optional: true
+
+ '@esbuild/android-arm64@0.17.19':
+ optional: true
+
+ '@esbuild/android-arm64@0.18.20':
+ optional: true
+
+ '@esbuild/android-arm64@0.19.12':
+ optional: true
+
+ '@esbuild/android-arm64@0.20.2':
+ optional: true
+
+ '@esbuild/android-arm@0.17.19':
+ optional: true
+
+ '@esbuild/android-arm@0.18.20':
+ optional: true
+
+ '@esbuild/android-arm@0.19.12':
+ optional: true
+
+ '@esbuild/android-arm@0.20.2':
+ optional: true
+
+ '@esbuild/android-x64@0.17.19':
+ optional: true
+
+ '@esbuild/android-x64@0.18.20':
+ optional: true
+
+ '@esbuild/android-x64@0.19.12':
+ optional: true
+
+ '@esbuild/android-x64@0.20.2':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.17.19':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.18.20':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.19.12':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.20.2':
+ optional: true
+
+ '@esbuild/darwin-x64@0.17.19':
+ optional: true
+
+ '@esbuild/darwin-x64@0.18.20':
+ optional: true
+
+ '@esbuild/darwin-x64@0.19.12':
+ optional: true
+
+ '@esbuild/darwin-x64@0.20.2':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.17.19':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.18.20':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.19.12':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.20.2':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.17.19':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.18.20':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.19.12':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.20.2':
+ optional: true
+
+ '@esbuild/linux-arm64@0.17.19':
+ optional: true
+
+ '@esbuild/linux-arm64@0.18.20':
+ optional: true
+
+ '@esbuild/linux-arm64@0.19.12':
+ optional: true
+
+ '@esbuild/linux-arm64@0.20.2':
+ optional: true
+
+ '@esbuild/linux-arm@0.17.19':
+ optional: true
+
+ '@esbuild/linux-arm@0.18.20':
+ optional: true
+
+ '@esbuild/linux-arm@0.19.12':
+ optional: true
+
+ '@esbuild/linux-arm@0.20.2':
+ optional: true
+
+ '@esbuild/linux-ia32@0.17.19':
+ optional: true
+
+ '@esbuild/linux-ia32@0.18.20':
+ optional: true
+
+ '@esbuild/linux-ia32@0.19.12':
+ optional: true
+
+ '@esbuild/linux-ia32@0.20.2':
+ optional: true
+
+ '@esbuild/linux-loong64@0.14.54':
+ optional: true
+
+ '@esbuild/linux-loong64@0.17.19':
+ optional: true
+
+ '@esbuild/linux-loong64@0.18.20':
+ optional: true
+
+ '@esbuild/linux-loong64@0.19.12':
+ optional: true
+
+ '@esbuild/linux-loong64@0.20.2':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.17.19':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.18.20':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.19.12':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.20.2':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.17.19':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.18.20':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.19.12':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.20.2':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.17.19':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.18.20':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.19.12':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.20.2':
+ optional: true
+
+ '@esbuild/linux-s390x@0.17.19':
+ optional: true
+
+ '@esbuild/linux-s390x@0.18.20':
+ optional: true
+
+ '@esbuild/linux-s390x@0.19.12':
+ optional: true
+
+ '@esbuild/linux-s390x@0.20.2':
+ optional: true
+
+ '@esbuild/linux-x64@0.17.19':
+ optional: true
+
+ '@esbuild/linux-x64@0.18.20':
+ optional: true
+
+ '@esbuild/linux-x64@0.19.12':
+ optional: true
+
+ '@esbuild/linux-x64@0.20.2':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.17.19':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.18.20':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.19.12':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.20.2':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.17.19':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.18.20':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.19.12':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.20.2':
+ optional: true
+
+ '@esbuild/sunos-x64@0.17.19':
+ optional: true
+
+ '@esbuild/sunos-x64@0.18.20':
+ optional: true
+
+ '@esbuild/sunos-x64@0.19.12':
+ optional: true
+
+ '@esbuild/sunos-x64@0.20.2':
+ optional: true
+
+ '@esbuild/win32-arm64@0.17.19':
+ optional: true
+
+ '@esbuild/win32-arm64@0.18.20':
+ optional: true
+
+ '@esbuild/win32-arm64@0.19.12':
+ optional: true
+
+ '@esbuild/win32-arm64@0.20.2':
+ optional: true
+
+ '@esbuild/win32-ia32@0.17.19':
+ optional: true
+
+ '@esbuild/win32-ia32@0.18.20':
+ optional: true
+
+ '@esbuild/win32-ia32@0.19.12':
+ optional: true
+
+ '@esbuild/win32-ia32@0.20.2':
+ optional: true
+
+ '@esbuild/win32-x64@0.17.19':
+ optional: true
+
+ '@esbuild/win32-x64@0.18.20':
+ optional: true
+
+ '@esbuild/win32-x64@0.19.12':
+ optional: true
+
+ '@esbuild/win32-x64@0.20.2':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
+ dependencies:
+ eslint: 8.57.0
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.10.0': {}
+
+ '@eslint/eslintrc@2.1.4':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.1
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@8.57.0': {}
+
+ '@ewoudenberg/difflib@0.1.0':
+ dependencies:
+ heap: 0.2.7
+
+ '@fastify/busboy@2.1.1': {}
+
+ '@hono/node-server@1.11.1': {}
+
+ '@hono/zod-validator@0.2.1(hono@4.3.9)(zod@3.23.8)':
+ dependencies:
+ hono: 4.3.9
+ zod: 3.23.8
+
+ '@humanwhocodes/config-array@0.11.14':
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.3
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/object-schema@2.0.3': {}
+
+ '@isaacs/cliui@8.0.2':
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: wrap-ansi@7.0.0
+
+ '@jest/schemas@29.6.3':
+ dependencies:
+ '@sinclair/typebox': 0.27.8
+
+ '@jridgewell/gen-mapping@0.3.5':
+ dependencies:
+ '@jridgewell/set-array': 1.2.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.25
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/set-array@1.2.1': {}
+
+ '@jridgewell/sourcemap-codec@1.4.15': {}
+
+ '@jridgewell/trace-mapping@0.3.25':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ '@jridgewell/trace-mapping@0.3.9':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ '@libsql/client@0.4.3(bufferutil@4.0.8)(utf-8-validate@6.0.3)':
+ dependencies:
+ '@libsql/core': 0.4.3
+ '@libsql/hrana-client': 0.5.6(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ js-base64: 3.7.7
+ optionalDependencies:
+ libsql: 0.2.0
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - utf-8-validate
+
+ '@libsql/core@0.4.3':
+ dependencies:
+ js-base64: 3.7.7
+
+ '@libsql/darwin-arm64@0.2.0':
+ optional: true
+
+ '@libsql/darwin-x64@0.2.0':
+ optional: true
+
+ '@libsql/hrana-client@0.5.6(bufferutil@4.0.8)(utf-8-validate@6.0.3)':
+ dependencies:
+ '@libsql/isomorphic-fetch': 0.1.12
+ '@libsql/isomorphic-ws': 0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ js-base64: 3.7.7
+ node-fetch: 3.3.2
+ transitivePeerDependencies:
+ - bufferutil
+ - encoding
+ - utf-8-validate
+
+ '@libsql/isomorphic-fetch@0.1.12':
+ dependencies:
+ '@types/node-fetch': 2.6.11
+ node-fetch: 2.7.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@libsql/isomorphic-ws@0.1.5(bufferutil@4.0.8)(utf-8-validate@6.0.3)':
+ dependencies:
+ '@types/ws': 8.5.10
+ ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+
+ '@libsql/linux-arm64-gnu@0.2.0':
+ optional: true
+
+ '@libsql/linux-arm64-musl@0.2.0':
+ optional: true
+
+ '@libsql/linux-x64-gnu@0.2.0':
+ optional: true
+
+ '@libsql/linux-x64-musl@0.2.0':
+ optional: true
+
+ '@libsql/win32-x64-msvc@0.2.0':
+ optional: true
+
+ '@neon-rs/load@0.0.4':
+ optional: true
+
+ '@neondatabase/serverless@0.7.2':
+ dependencies:
+ '@types/pg': 8.6.6
+
+ '@neondatabase/serverless@0.9.3':
+ dependencies:
+ '@types/pg': 8.11.6
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.17.1
+
+ '@originjs/vite-plugin-commonjs@1.0.3':
+ dependencies:
+ esbuild: 0.14.54
+
+ '@pkgjs/parseargs@0.11.0':
+ optional: true
+
+ '@pkgr/core@0.1.1': {}
+
+ '@planetscale/database@1.18.0': {}
+
+ '@rollup/rollup-android-arm-eabi@4.17.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.17.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.17.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.17.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.17.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.17.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.17.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.17.2':
+ optional: true
+
+ '@sinclair/typebox@0.27.8': {}
+
+ '@sindresorhus/is@4.6.0': {}
+
+ '@smithy/abort-controller@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/config-resolver@3.0.0':
+ dependencies:
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-config-provider': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/core@2.0.1':
+ dependencies:
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-retry': 3.0.1
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/credential-provider-imds@3.0.0':
+ dependencies:
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/fetch-http-handler@3.0.1':
+ dependencies:
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/querystring-builder': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/hash-node@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ '@smithy/util-buffer-from': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/invalid-dependency@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/is-array-buffer@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/middleware-content-length@3.0.0':
+ dependencies:
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/middleware-endpoint@3.0.0':
+ dependencies:
+ '@smithy/middleware-serde': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/url-parser': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/middleware-retry@3.0.1':
+ dependencies:
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/service-error-classification': 3.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-retry': 3.0.0
+ tslib: 2.6.2
+ uuid: 9.0.1
+
+ '@smithy/middleware-serde@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/middleware-stack@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/node-config-provider@3.0.0':
+ dependencies:
+ '@smithy/property-provider': 3.0.0
+ '@smithy/shared-ini-file-loader': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/node-http-handler@3.0.0':
+ dependencies:
+ '@smithy/abort-controller': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/querystring-builder': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/property-provider@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/protocol-http@4.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/querystring-builder@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ '@smithy/util-uri-escape': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/querystring-parser@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/service-error-classification@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+
+ '@smithy/shared-ini-file-loader@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/signature-v4@3.0.0':
+ dependencies:
+ '@smithy/is-array-buffer': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-hex-encoding': 3.0.0
+ '@smithy/util-middleware': 3.0.0
+ '@smithy/util-uri-escape': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/smithy-client@3.0.1':
+ dependencies:
+ '@smithy/middleware-endpoint': 3.0.0
+ '@smithy/middleware-stack': 3.0.0
+ '@smithy/protocol-http': 4.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-stream': 3.0.1
+ tslib: 2.6.2
+
+ '@smithy/types@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/url-parser@3.0.0':
+ dependencies:
+ '@smithy/querystring-parser': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-base64@3.0.0':
+ dependencies:
+ '@smithy/util-buffer-from': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-body-length-browser@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/util-body-length-node@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/util-buffer-from@3.0.0':
+ dependencies:
+ '@smithy/is-array-buffer': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-config-provider@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/util-defaults-mode-browser@3.0.1':
+ dependencies:
+ '@smithy/property-provider': 3.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ bowser: 2.11.0
+ tslib: 2.6.2
+
+ '@smithy/util-defaults-mode-node@3.0.1':
+ dependencies:
+ '@smithy/config-resolver': 3.0.0
+ '@smithy/credential-provider-imds': 3.0.0
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/property-provider': 3.0.0
+ '@smithy/smithy-client': 3.0.1
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-endpoints@2.0.0':
+ dependencies:
+ '@smithy/node-config-provider': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-hex-encoding@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/util-middleware@3.0.0':
+ dependencies:
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-retry@3.0.0':
+ dependencies:
+ '@smithy/service-error-classification': 3.0.0
+ '@smithy/types': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-stream@3.0.1':
+ dependencies:
+ '@smithy/fetch-http-handler': 3.0.1
+ '@smithy/node-http-handler': 3.0.0
+ '@smithy/types': 3.0.0
+ '@smithy/util-base64': 3.0.0
+ '@smithy/util-buffer-from': 3.0.0
+ '@smithy/util-hex-encoding': 3.0.0
+ '@smithy/util-utf8': 3.0.0
+ tslib: 2.6.2
+
+ '@smithy/util-uri-escape@3.0.0':
+ dependencies:
+ tslib: 2.6.2
+
+ '@smithy/util-utf8@3.0.0':
+ dependencies:
+ '@smithy/util-buffer-from': 3.0.0
+ tslib: 2.6.2
+
+ '@types/better-sqlite3@7.6.10':
+ dependencies:
+ '@types/node': 18.19.33
+
+ '@types/docker-modem@3.0.6':
+ dependencies:
+ '@types/node': 18.19.33
+ '@types/ssh2': 1.15.0
+
+ '@types/dockerode@3.3.29':
+ dependencies:
+ '@types/docker-modem': 3.0.6
+ '@types/node': 18.19.33
+ '@types/ssh2': 1.15.0
+
+ '@types/estree@1.0.5': {}
+
+ '@types/fs-extra@11.0.4':
+ dependencies:
+ '@types/jsonfile': 6.1.4
+ '@types/node': 18.19.33
+
+ '@types/glob@8.1.0':
+ dependencies:
+ '@types/minimatch': 5.1.2
+ '@types/node': 18.19.33
+
+ '@types/json-diff@1.0.3': {}
+
+ '@types/jsonfile@6.1.4':
+ dependencies:
+ '@types/node': 18.19.33
+
+ '@types/minimatch@5.1.2': {}
+
+ '@types/minimist@1.2.5': {}
+
+ '@types/node-fetch@2.6.11':
+ dependencies:
+ '@types/node': 18.19.33
+ form-data: 4.0.0
+
+ '@types/node-forge@1.3.11':
+ dependencies:
+ '@types/node': 18.19.33
+
+ '@types/node@18.19.33':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/pg@8.11.6':
+ dependencies:
+ '@types/node': 18.19.33
+ pg-protocol: 1.6.1
+ pg-types: 4.0.2
+
+ '@types/pg@8.6.6':
+ dependencies:
+ '@types/node': 18.19.33
+ pg-protocol: 1.6.1
+ pg-types: 2.2.0
+
+ '@types/pluralize@0.0.33': {}
+
+ '@types/ps-tree@1.1.6': {}
+
+ '@types/semver@7.5.8': {}
+
+ '@types/ssh2@1.15.0':
+ dependencies:
+ '@types/node': 18.19.33
+
+ '@types/uuid@9.0.8': {}
+
+ '@types/which@3.0.3': {}
+
+ '@types/ws@8.5.10':
+ dependencies:
+ '@types/node': 18.19.33
+
+ '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)':
+ dependencies:
+ '@eslint-community/regexpp': 4.10.0
+ '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/scope-manager': 7.10.0
+ '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/visitor-keys': 7.10.0
+ eslint: 8.57.0
+ graphemer: 1.4.0
+ ignore: 5.3.1
+ natural-compare: 1.4.0
+ ts-api-utils: 1.3.0(typescript@5.4.5)
+ optionalDependencies:
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 7.10.0
+ '@typescript-eslint/types': 7.10.0
+ '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
+ '@typescript-eslint/visitor-keys': 7.10.0
+ debug: 4.3.4
+ eslint: 8.57.0
+ optionalDependencies:
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@7.10.0':
+ dependencies:
+ '@typescript-eslint/types': 7.10.0
+ '@typescript-eslint/visitor-keys': 7.10.0
+
+ '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ dependencies:
+ '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
+ '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5)
+ debug: 4.3.4
+ eslint: 8.57.0
+ ts-api-utils: 1.3.0(typescript@5.4.5)
+ optionalDependencies:
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@7.10.0': {}
+
+ '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)':
+ dependencies:
+ '@typescript-eslint/types': 7.10.0
+ '@typescript-eslint/visitor-keys': 7.10.0
+ debug: 4.3.4
+ globby: 11.1.0
+ is-glob: 4.0.3
+ minimatch: 9.0.4
+ semver: 7.6.2
+ ts-api-utils: 1.3.0(typescript@5.4.5)
+ optionalDependencies:
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@typescript-eslint/scope-manager': 7.10.0
+ '@typescript-eslint/types': 7.10.0
+ '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5)
+ eslint: 8.57.0
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ '@typescript-eslint/visitor-keys@7.10.0':
+ dependencies:
+ '@typescript-eslint/types': 7.10.0
+ eslint-visitor-keys: 3.4.3
+
+ '@ungap/structured-clone@1.2.0': {}
+
+ '@vercel/postgres@0.8.0':
+ dependencies:
+ '@neondatabase/serverless': 0.7.2
+ bufferutil: 4.0.8
+ utf-8-validate: 6.0.3
+ ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+
+ '@vitest/expect@1.6.0':
+ dependencies:
+ '@vitest/spy': 1.6.0
+ '@vitest/utils': 1.6.0
+ chai: 4.4.1
+
+ '@vitest/runner@1.6.0':
+ dependencies:
+ '@vitest/utils': 1.6.0
+ p-limit: 5.0.0
+ pathe: 1.1.2
+
+ '@vitest/snapshot@1.6.0':
+ dependencies:
+ magic-string: 0.30.10
+ pathe: 1.1.2
+ pretty-format: 29.7.0
+
+ '@vitest/spy@1.6.0':
+ dependencies:
+ tinyspy: 2.2.1
+
+ '@vitest/utils@1.6.0':
+ dependencies:
+ diff-sequences: 29.6.3
+ estree-walker: 3.0.3
+ loupe: 2.3.7
+ pretty-format: 29.7.0
+
+ acorn-jsx@5.3.2(acorn@8.11.3):
+ dependencies:
+ acorn: 8.11.3
+
+ acorn-walk@8.3.2: {}
+
+ acorn@8.11.3: {}
+
+ aggregate-error@4.0.1:
+ dependencies:
+ clean-stack: 4.2.0
+ indent-string: 5.0.0
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ansi-escapes@6.2.1: {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-regex@6.0.1: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@5.2.0: {}
+
+ ansi-styles@6.2.1: {}
+
+ ansicolors@0.3.2: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ argparse@1.0.10:
+ dependencies:
+ sprintf-js: 1.0.3
+
+ argparse@2.0.1: {}
+
+ array-find-index@1.0.2: {}
+
+ array-union@2.1.0: {}
+
+ arrgv@1.0.2: {}
+
+ arrify@3.0.0: {}
+
+ as-table@1.0.55:
+ dependencies:
+ printable-characters: 1.0.42
+
+ asn1@0.2.6:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ assertion-error@1.1.0: {}
+
+ asynckit@0.4.0: {}
+
+ ava@5.3.1:
+ dependencies:
+ acorn: 8.11.3
+ acorn-walk: 8.3.2
+ ansi-styles: 6.2.1
+ arrgv: 1.0.2
+ arrify: 3.0.0
+ callsites: 4.1.0
+ cbor: 8.1.0
+ chalk: 5.3.0
+ chokidar: 3.6.0
+ chunkd: 2.0.1
+ ci-info: 3.9.0
+ ci-parallel-vars: 1.0.1
+ clean-yaml-object: 0.1.0
+ cli-truncate: 3.1.0
+ code-excerpt: 4.0.0
+ common-path-prefix: 3.0.0
+ concordance: 5.0.4
+ currently-unhandled: 0.4.1
+ debug: 4.3.4
+ emittery: 1.0.3
+ figures: 5.0.0
+ globby: 13.2.2
+ ignore-by-default: 2.1.0
+ indent-string: 5.0.0
+ is-error: 2.2.2
+ is-plain-object: 5.0.0
+ is-promise: 4.0.0
+ matcher: 5.0.0
+ mem: 9.0.2
+ ms: 2.1.3
+ p-event: 5.0.1
+ p-map: 5.5.0
+ picomatch: 2.3.1
+ pkg-conf: 4.0.0
+ plur: 5.1.0
+ pretty-ms: 8.0.0
+ resolve-cwd: 3.0.0
+ stack-utils: 2.0.6
+ strip-ansi: 7.1.0
+ supertap: 3.0.1
+ temp-dir: 3.0.0
+ write-file-atomic: 5.0.1
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - supports-color
+
+ balanced-match@1.0.2: {}
+
+ base64-js@1.5.1: {}
+
+ bcrypt-pbkdf@1.0.2:
+ dependencies:
+ tweetnacl: 0.14.5
+
+ better-sqlite3@9.6.0:
+ dependencies:
+ bindings: 1.5.0
+ prebuild-install: 7.1.2
+
+ binary-extensions@2.3.0: {}
+
+ bindings@1.5.0:
+ dependencies:
+ file-uri-to-path: 1.0.0
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ blake3-wasm@2.1.5: {}
+
+ blueimp-md5@2.19.0: {}
+
+ bowser@2.11.0: {}
+
+ brace-expansion@1.1.11:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.1:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.2:
+ dependencies:
+ fill-range: 7.1.1
+
+ buffer-from@1.1.2: {}
+
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+
+ bufferutil@4.0.8:
+ dependencies:
+ node-gyp-build: 4.8.1
+
+ buildcheck@0.0.6:
+ optional: true
+
+ bundle-require@4.1.0(esbuild@0.19.12):
+ dependencies:
+ esbuild: 0.19.12
+ load-tsconfig: 0.2.5
+
+ cac@6.7.14: {}
+
+ callsites@3.1.0: {}
+
+ callsites@4.1.0: {}
+
+ camelcase@7.0.1: {}
+
+ capnp-ts@0.7.0:
+ dependencies:
+ debug: 4.3.4
+ tslib: 2.6.2
+ transitivePeerDependencies:
+ - supports-color
+
+ cardinal@2.1.1:
+ dependencies:
+ ansicolors: 0.3.2
+ redeyed: 2.1.1
+
+ cbor@8.1.0:
+ dependencies:
+ nofilter: 3.1.0
+
+ chai@4.4.1:
+ dependencies:
+ assertion-error: 1.1.0
+ check-error: 1.0.3
+ deep-eql: 4.1.3
+ get-func-name: 2.0.2
+ loupe: 2.3.7
+ pathval: 1.1.1
+ type-detect: 4.0.8
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ chalk@5.3.0: {}
+
+ char-regex@1.0.2: {}
+
+ check-error@1.0.3:
+ dependencies:
+ get-func-name: 2.0.2
+
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ chownr@1.1.4: {}
+
+ chunkd@2.0.1: {}
+
+ ci-info@3.9.0: {}
+
+ ci-parallel-vars@1.0.1: {}
+
+ clean-stack@4.2.0:
+ dependencies:
+ escape-string-regexp: 5.0.0
+
+ clean-yaml-object@0.1.0: {}
+
+ cli-color@2.0.4:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-iterator: 2.0.3
+ memoizee: 0.4.15
+ timers-ext: 0.1.7
+
+ cli-table3@0.6.5:
+ dependencies:
+ string-width: 4.2.3
+ optionalDependencies:
+ '@colors/colors': 1.5.0
+
+ cli-truncate@3.1.0:
+ dependencies:
+ slice-ansi: 5.0.0
+ string-width: 5.1.2
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ code-excerpt@4.0.0:
+ dependencies:
+ convert-to-spaces: 2.0.1
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
+ colors@1.4.0: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@10.0.1: {}
+
+ commander@12.1.0: {}
+
+ commander@4.1.1: {}
+
+ commander@9.5.0: {}
+
+ common-path-prefix@3.0.0: {}
+
+ concat-map@0.0.1: {}
+
+ concordance@5.0.4:
+ dependencies:
+ date-time: 3.1.0
+ esutils: 2.0.3
+ fast-diff: 1.3.0
+ js-string-escape: 1.0.1
+ lodash: 4.17.21
+ md5-hex: 3.0.1
+ semver: 7.6.2
+ well-known-symbols: 2.0.0
+
+ confbox@0.1.7: {}
+
+ convert-to-spaces@2.0.1: {}
+
+ cookie@0.5.0: {}
+
+ copy-anything@3.0.5:
+ dependencies:
+ is-what: 4.1.16
+
+ cpu-features@0.0.10:
+ dependencies:
+ buildcheck: 0.0.6
+ nan: 2.19.0
+ optional: true
+
+ cross-spawn@7.0.3:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ currently-unhandled@0.4.1:
+ dependencies:
+ array-find-index: 1.0.2
+
+ d@1.0.2:
+ dependencies:
+ es5-ext: 0.10.64
+ type: 2.7.2
+
+ data-uri-to-buffer@2.0.2: {}
+
+ data-uri-to-buffer@4.0.1: {}
+
+ date-time@3.1.0:
+ dependencies:
+ time-zone: 1.0.0
+
+ debug@4.3.4:
+ dependencies:
+ ms: 2.1.2
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+
+ deep-eql@4.1.3:
+ dependencies:
+ type-detect: 4.0.8
+
+ deep-extend@0.6.0: {}
+
+ deep-is@0.1.4: {}
+
+ delayed-stream@1.0.0: {}
+
+ denque@2.1.0: {}
+
+ detect-libc@2.0.2:
+ optional: true
+
+ detect-libc@2.0.3: {}
+
+ diff-sequences@29.6.3: {}
+
+ difflib@0.2.4(patch_hash=jq4t3ysdpnbunjeje4v7nrqn2q):
+ dependencies:
+ heap: 0.2.7
+
+ dir-glob@3.0.1:
+ dependencies:
+ path-type: 4.0.0
+
+ docker-modem@3.0.8:
+ dependencies:
+ debug: 4.3.4
+ readable-stream: 3.6.2
+ split-ca: 1.0.1
+ ssh2: 1.15.0
+ transitivePeerDependencies:
+ - supports-color
+
+ dockerode@3.3.5:
+ dependencies:
+ '@balena/dockerignore': 1.0.2
+ docker-modem: 3.0.8
+ tar-fs: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ doctrine@3.0.0:
+ dependencies:
+ esutils: 2.0.3
+
+ dotenv@16.4.5: {}
+
+ dreamopt@0.8.0:
+ dependencies:
+ wordwrap: 1.0.0
+
+ drizzle-kit@0.21.2:
+ dependencies:
+ '@esbuild-kit/esm-loader': 2.6.5
+ commander: 9.5.0
+ env-paths: 3.0.0
+ esbuild: 0.19.12
+ esbuild-register: 3.5.0(esbuild@0.19.12)
+ glob: 8.1.0
+ hanji: 0.0.5
+ json-diff: 0.9.0
+ zod: 3.23.8
+ transitivePeerDependencies:
+ - supports-color
+
+ drizzle-orm@0.32.0-85c8008(@aws-sdk/client-rds-data@3.577.0)(@cloudflare/workers-types@4.20240512.0)(@electric-sql/pglite@0.1.5)(@libsql/client@0.4.3(bufferutil@4.0.8)(utf-8-validate@6.0.3))(@neondatabase/serverless@0.9.3)(@planetscale/database@1.18.0)(@types/better-sqlite3@7.6.10)(@types/pg@8.11.6)(@vercel/postgres@0.8.0)(better-sqlite3@9.6.0)(mysql2@2.3.3)(pg@8.11.5)(postgres@3.4.4):
+ optionalDependencies:
+ '@aws-sdk/client-rds-data': 3.577.0
+ '@cloudflare/workers-types': 4.20240512.0
+ '@electric-sql/pglite': 0.1.5
+ '@libsql/client': 0.4.3(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ '@neondatabase/serverless': 0.9.3
+ '@planetscale/database': 1.18.0
+ '@types/better-sqlite3': 7.6.10
+ '@types/pg': 8.11.6
+ '@vercel/postgres': 0.8.0
+ better-sqlite3: 9.6.0
+ mysql2: 2.3.3
+ pg: 8.11.5
+ postgres: 3.4.4
+
+ duplexer@0.1.2: {}
+
+ eastasianwidth@0.2.0: {}
+
+ emittery@1.0.3: {}
+
+ emoji-regex@8.0.0: {}
+
+ emoji-regex@9.2.2: {}
+
+ emojilib@2.4.0: {}
+
+ end-of-stream@1.4.4:
+ dependencies:
+ once: 1.4.0
+
+ env-paths@3.0.0: {}
+
+ es5-ext@0.10.64:
+ dependencies:
+ es6-iterator: 2.0.3
+ es6-symbol: 3.1.4
+ esniff: 2.0.1
+ next-tick: 1.1.0
+
+ es6-iterator@2.0.3:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-symbol: 3.1.4
+
+ es6-symbol@3.1.4:
+ dependencies:
+ d: 1.0.2
+ ext: 1.7.0
+
+ es6-weak-map@2.0.3:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-iterator: 2.0.3
+ es6-symbol: 3.1.4
+
+ esbuild-android-64@0.14.54:
+ optional: true
+
+ esbuild-android-arm64@0.14.54:
+ optional: true
+
+ esbuild-darwin-64@0.14.54:
+ optional: true
+
+ esbuild-darwin-arm64@0.14.54:
+ optional: true
+
+ esbuild-freebsd-64@0.14.54:
+ optional: true
+
+ esbuild-freebsd-arm64@0.14.54:
+ optional: true
+
+ esbuild-linux-32@0.14.54:
+ optional: true
+
+ esbuild-linux-64@0.14.54:
+ optional: true
+
+ esbuild-linux-arm64@0.14.54:
+ optional: true
+
+ esbuild-linux-arm@0.14.54:
+ optional: true
+
+ esbuild-linux-mips64le@0.14.54:
+ optional: true
+
+ esbuild-linux-ppc64le@0.14.54:
+ optional: true
+
+ esbuild-linux-riscv64@0.14.54:
+ optional: true
+
+ esbuild-linux-s390x@0.14.54:
+ optional: true
+
+ esbuild-netbsd-64@0.14.54:
+ optional: true
+
+ esbuild-node-externals@1.13.1(esbuild@0.19.12):
+ dependencies:
+ esbuild: 0.19.12
+ find-up: 5.0.0
+ tslib: 2.6.2
+
+ esbuild-openbsd-64@0.14.54:
+ optional: true
+
+ esbuild-register@3.5.0(esbuild@0.19.12):
+ dependencies:
+ debug: 4.3.4
+ esbuild: 0.19.12
+ transitivePeerDependencies:
+ - supports-color
+
+ esbuild-sunos-64@0.14.54:
+ optional: true
+
+ esbuild-windows-32@0.14.54:
+ optional: true
+
+ esbuild-windows-64@0.14.54:
+ optional: true
+
+ esbuild-windows-arm64@0.14.54:
+ optional: true
+
+ esbuild@0.14.54:
+ optionalDependencies:
+ '@esbuild/linux-loong64': 0.14.54
+ esbuild-android-64: 0.14.54
+ esbuild-android-arm64: 0.14.54
+ esbuild-darwin-64: 0.14.54
+ esbuild-darwin-arm64: 0.14.54
+ esbuild-freebsd-64: 0.14.54
+ esbuild-freebsd-arm64: 0.14.54
+ esbuild-linux-32: 0.14.54
+ esbuild-linux-64: 0.14.54
+ esbuild-linux-arm: 0.14.54
+ esbuild-linux-arm64: 0.14.54
+ esbuild-linux-mips64le: 0.14.54
+ esbuild-linux-ppc64le: 0.14.54
+ esbuild-linux-riscv64: 0.14.54
+ esbuild-linux-s390x: 0.14.54
+ esbuild-netbsd-64: 0.14.54
+ esbuild-openbsd-64: 0.14.54
+ esbuild-sunos-64: 0.14.54
+ esbuild-windows-32: 0.14.54
+ esbuild-windows-64: 0.14.54
+ esbuild-windows-arm64: 0.14.54
+
+ esbuild@0.17.19:
+ optionalDependencies:
+ '@esbuild/android-arm': 0.17.19
+ '@esbuild/android-arm64': 0.17.19
+ '@esbuild/android-x64': 0.17.19
+ '@esbuild/darwin-arm64': 0.17.19
+ '@esbuild/darwin-x64': 0.17.19
+ '@esbuild/freebsd-arm64': 0.17.19
+ '@esbuild/freebsd-x64': 0.17.19
+ '@esbuild/linux-arm': 0.17.19
+ '@esbuild/linux-arm64': 0.17.19
+ '@esbuild/linux-ia32': 0.17.19
+ '@esbuild/linux-loong64': 0.17.19
+ '@esbuild/linux-mips64el': 0.17.19
+ '@esbuild/linux-ppc64': 0.17.19
+ '@esbuild/linux-riscv64': 0.17.19
+ '@esbuild/linux-s390x': 0.17.19
+ '@esbuild/linux-x64': 0.17.19
+ '@esbuild/netbsd-x64': 0.17.19
+ '@esbuild/openbsd-x64': 0.17.19
+ '@esbuild/sunos-x64': 0.17.19
+ '@esbuild/win32-arm64': 0.17.19
+ '@esbuild/win32-ia32': 0.17.19
+ '@esbuild/win32-x64': 0.17.19
+
+ esbuild@0.18.20:
+ optionalDependencies:
+ '@esbuild/android-arm': 0.18.20
+ '@esbuild/android-arm64': 0.18.20
+ '@esbuild/android-x64': 0.18.20
+ '@esbuild/darwin-arm64': 0.18.20
+ '@esbuild/darwin-x64': 0.18.20
+ '@esbuild/freebsd-arm64': 0.18.20
+ '@esbuild/freebsd-x64': 0.18.20
+ '@esbuild/linux-arm': 0.18.20
+ '@esbuild/linux-arm64': 0.18.20
+ '@esbuild/linux-ia32': 0.18.20
+ '@esbuild/linux-loong64': 0.18.20
+ '@esbuild/linux-mips64el': 0.18.20
+ '@esbuild/linux-ppc64': 0.18.20
+ '@esbuild/linux-riscv64': 0.18.20
+ '@esbuild/linux-s390x': 0.18.20
+ '@esbuild/linux-x64': 0.18.20
+ '@esbuild/netbsd-x64': 0.18.20
+ '@esbuild/openbsd-x64': 0.18.20
+ '@esbuild/sunos-x64': 0.18.20
+ '@esbuild/win32-arm64': 0.18.20
+ '@esbuild/win32-ia32': 0.18.20
+ '@esbuild/win32-x64': 0.18.20
+
+ esbuild@0.19.12:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.12
+ '@esbuild/android-arm': 0.19.12
+ '@esbuild/android-arm64': 0.19.12
+ '@esbuild/android-x64': 0.19.12
+ '@esbuild/darwin-arm64': 0.19.12
+ '@esbuild/darwin-x64': 0.19.12
+ '@esbuild/freebsd-arm64': 0.19.12
+ '@esbuild/freebsd-x64': 0.19.12
+ '@esbuild/linux-arm': 0.19.12
+ '@esbuild/linux-arm64': 0.19.12
+ '@esbuild/linux-ia32': 0.19.12
+ '@esbuild/linux-loong64': 0.19.12
+ '@esbuild/linux-mips64el': 0.19.12
+ '@esbuild/linux-ppc64': 0.19.12
+ '@esbuild/linux-riscv64': 0.19.12
+ '@esbuild/linux-s390x': 0.19.12
+ '@esbuild/linux-x64': 0.19.12
+ '@esbuild/netbsd-x64': 0.19.12
+ '@esbuild/openbsd-x64': 0.19.12
+ '@esbuild/sunos-x64': 0.19.12
+ '@esbuild/win32-arm64': 0.19.12
+ '@esbuild/win32-ia32': 0.19.12
+ '@esbuild/win32-x64': 0.19.12
+
+ esbuild@0.20.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.20.2
+ '@esbuild/android-arm': 0.20.2
+ '@esbuild/android-arm64': 0.20.2
+ '@esbuild/android-x64': 0.20.2
+ '@esbuild/darwin-arm64': 0.20.2
+ '@esbuild/darwin-x64': 0.20.2
+ '@esbuild/freebsd-arm64': 0.20.2
+ '@esbuild/freebsd-x64': 0.20.2
+ '@esbuild/linux-arm': 0.20.2
+ '@esbuild/linux-arm64': 0.20.2
+ '@esbuild/linux-ia32': 0.20.2
+ '@esbuild/linux-loong64': 0.20.2
+ '@esbuild/linux-mips64el': 0.20.2
+ '@esbuild/linux-ppc64': 0.20.2
+ '@esbuild/linux-riscv64': 0.20.2
+ '@esbuild/linux-s390x': 0.20.2
+ '@esbuild/linux-x64': 0.20.2
+ '@esbuild/netbsd-x64': 0.20.2
+ '@esbuild/openbsd-x64': 0.20.2
+ '@esbuild/sunos-x64': 0.20.2
+ '@esbuild/win32-arm64': 0.20.2
+ '@esbuild/win32-ia32': 0.20.2
+ '@esbuild/win32-x64': 0.20.2
+
+ escalade@3.1.2: {}
+
+ escape-string-regexp@2.0.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ escape-string-regexp@5.0.0: {}
+
+ eslint-config-prettier@9.1.0(eslint@8.57.0):
+ dependencies:
+ eslint: 8.57.0
+
+ eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8):
+ dependencies:
+ eslint: 8.57.0
+ prettier: 2.8.8
+ prettier-linter-helpers: 1.0.0
+ synckit: 0.8.8
+ optionalDependencies:
+ eslint-config-prettier: 9.1.0(eslint@8.57.0)
+
+ eslint-scope@7.2.2:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint@8.57.0:
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@eslint-community/regexpp': 4.10.0
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.57.0
+ '@humanwhocodes/config-array': 0.11.14
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.1
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ esniff@2.0.1:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ event-emitter: 0.3.5
+ type: 2.7.2
+
+ espree@9.6.1:
+ dependencies:
+ acorn: 8.11.3
+ acorn-jsx: 5.3.2(acorn@8.11.3)
+ eslint-visitor-keys: 3.4.3
+
+ esprima@4.0.1: {}
+
+ esquery@1.5.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@5.3.0: {}
+
+ estree-walker@0.6.1: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.5
+
+ esutils@2.0.3: {}
+
+ event-emitter@0.3.5:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+
+ event-stream@3.3.4:
+ dependencies:
+ duplexer: 0.1.2
+ from: 0.1.7
+ map-stream: 0.1.0
+ pause-stream: 0.0.11
+ split: 0.3.3
+ stream-combiner: 0.0.4
+ through: 2.3.8
+
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ execa@8.0.1:
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 8.0.1
+ human-signals: 5.0.0
+ is-stream: 3.0.0
+ merge-stream: 2.0.0
+ npm-run-path: 5.3.0
+ onetime: 6.0.0
+ signal-exit: 4.1.0
+ strip-final-newline: 3.0.0
+
+ exit-hook@2.2.1: {}
+
+ expand-template@2.0.3: {}
+
+ ext@1.7.0:
+ dependencies:
+ type: 2.7.2
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-diff@1.3.0: {}
+
+ fast-glob@3.3.2:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fast-xml-parser@4.2.5:
+ dependencies:
+ strnum: 1.0.5
+
+ fastq@1.17.1:
+ dependencies:
+ reusify: 1.0.4
+
+ fetch-blob@3.2.0:
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.3
+
+ fflate@0.8.2: {}
+
+ figures@5.0.0:
+ dependencies:
+ escape-string-regexp: 5.0.0
+ is-unicode-supported: 1.3.0
+
+ file-entry-cache@6.0.1:
+ dependencies:
+ flat-cache: 3.2.0
+
+ file-uri-to-path@1.0.0: {}
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ find-up@6.3.0:
+ dependencies:
+ locate-path: 7.2.0
+ path-exists: 5.0.0
+
+ flat-cache@3.2.0:
+ dependencies:
+ flatted: 3.3.1
+ keyv: 4.5.4
+ rimraf: 3.0.2
+
+ flatted@3.3.1: {}
+
+ foreground-child@3.1.1:
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+
+ form-data@4.0.0:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+
+ formdata-polyfill@4.0.10:
+ dependencies:
+ fetch-blob: 3.2.0
+
+ from@0.1.7: {}
+
+ fs-constants@1.0.0: {}
+
+ fs-extra@11.2.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+
+ fs.realpath@1.0.0: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ fx@34.0.0: {}
+
+ generate-function@2.3.1:
+ dependencies:
+ is-property: 1.0.2
+
+ get-caller-file@2.0.5: {}
+
+ get-func-name@2.0.2: {}
+
+ get-port@6.1.2: {}
+
+ get-source@2.0.12:
+ dependencies:
+ data-uri-to-buffer: 2.0.2
+ source-map: 0.6.1
+
+ get-stream@6.0.1: {}
+
+ get-stream@8.0.1: {}
+
+ get-tsconfig@4.7.5:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
+ github-from-package@0.0.0: {}
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-to-regexp@0.4.1: {}
+
+ glob@10.3.15:
+ dependencies:
+ foreground-child: 3.1.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.4
+ minipass: 7.1.1
+ path-scurry: 1.11.1
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ glob@8.1.0:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 5.1.6
+ once: 1.4.0
+
+ globals@13.24.0:
+ dependencies:
+ type-fest: 0.20.2
+
+ globby@11.1.0:
+ dependencies:
+ array-union: 2.1.0
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ ignore: 5.3.1
+ merge2: 1.4.1
+ slash: 3.0.0
+
+ globby@13.2.2:
+ dependencies:
+ dir-glob: 3.0.1
+ fast-glob: 3.3.2
+ ignore: 5.3.1
+ merge2: 1.4.1
+ slash: 4.0.0
+
+ globrex@0.1.2: {}
+
+ graceful-fs@4.2.11: {}
+
+ graphemer@1.4.0: {}
+
+ hanji@0.0.5:
+ dependencies:
+ lodash.throttle: 4.1.1
+ sisteransi: 1.0.5
+
+ has-flag@4.0.0: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ heap@0.2.7: {}
+
+ hono@4.3.9: {}
+
+ human-signals@2.1.0: {}
+
+ human-signals@5.0.0: {}
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ ieee754@1.2.1: {}
+
+ ignore-by-default@2.1.0: {}
+
+ ignore@5.3.1: {}
+
+ import-fresh@3.3.0:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
+ indent-string@5.0.0: {}
+
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
+ ini@1.3.8: {}
+
+ irregular-plurals@3.5.0: {}
+
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
+ is-core-module@2.13.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-error@2.2.2: {}
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-fullwidth-code-point@4.0.0: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-number@7.0.0: {}
+
+ is-path-inside@3.0.3: {}
+
+ is-plain-object@5.0.0: {}
+
+ is-promise@2.2.2: {}
+
+ is-promise@4.0.0: {}
+
+ is-property@1.0.2: {}
+
+ is-stream@2.0.1: {}
+
+ is-stream@3.0.0: {}
+
+ is-unicode-supported@1.3.0: {}
+
+ is-what@4.1.16: {}
+
+ isexe@2.0.0: {}
+
+ jackspeak@2.3.6:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ joycon@3.1.1: {}
+
+ js-base64@3.7.7: {}
+
+ js-string-escape@1.0.1: {}
+
+ js-tokens@9.0.0: {}
+
+ js-yaml@3.14.1:
+ dependencies:
+ argparse: 1.0.10
+ esprima: 4.0.1
+
+ js-yaml@4.1.0:
+ dependencies:
+ argparse: 2.0.1
+
+ json-buffer@3.0.1: {}
+
+ json-diff@0.9.0:
+ dependencies:
+ cli-color: 2.0.4
+ difflib: 0.2.4(patch_hash=jq4t3ysdpnbunjeje4v7nrqn2q)
+ dreamopt: 0.8.0
+
+ json-diff@1.0.6:
+ dependencies:
+ '@ewoudenberg/difflib': 0.1.0
+ colors: 1.4.0
+ dreamopt: 0.8.0
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ jsonfile@6.1.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
+ libsql@0.2.0:
+ dependencies:
+ '@neon-rs/load': 0.0.4
+ detect-libc: 2.0.2
+ optionalDependencies:
+ '@libsql/darwin-arm64': 0.2.0
+ '@libsql/darwin-x64': 0.2.0
+ '@libsql/linux-arm64-gnu': 0.2.0
+ '@libsql/linux-arm64-musl': 0.2.0
+ '@libsql/linux-x64-gnu': 0.2.0
+ '@libsql/linux-x64-musl': 0.2.0
+ '@libsql/win32-x64-msvc': 0.2.0
+ optional: true
+
+ lilconfig@3.1.1: {}
+
+ lines-and-columns@1.2.4: {}
+
+ load-json-file@7.0.1: {}
+
+ load-tsconfig@0.2.5: {}
+
+ local-pkg@0.5.0:
+ dependencies:
+ mlly: 1.7.0
+ pkg-types: 1.1.1
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ locate-path@7.2.0:
+ dependencies:
+ p-locate: 6.0.0
+
+ lodash.merge@4.6.2: {}
+
+ lodash.sortby@4.7.0: {}
+
+ lodash.throttle@4.1.1: {}
+
+ lodash@4.17.21: {}
+
+ long@4.0.0: {}
+
+ loupe@2.3.7:
+ dependencies:
+ get-func-name: 2.0.2
+
+ lru-cache@10.2.2: {}
+
+ lru-cache@6.0.0:
+ dependencies:
+ yallist: 4.0.0
+
+ lru-cache@7.18.3: {}
+
+ lru-queue@0.1.0:
+ dependencies:
+ es5-ext: 0.10.64
+
+ magic-string@0.25.9:
+ dependencies:
+ sourcemap-codec: 1.4.8
+
+ magic-string@0.30.10:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ map-age-cleaner@0.1.3:
+ dependencies:
+ p-defer: 1.0.0
+
+ map-stream@0.1.0: {}
+
+ marked-terminal@6.2.0(marked@9.1.6):
+ dependencies:
+ ansi-escapes: 6.2.1
+ cardinal: 2.1.1
+ chalk: 5.3.0
+ cli-table3: 0.6.5
+ marked: 9.1.6
+ node-emoji: 2.1.3
+ supports-hyperlinks: 3.0.0
+
+ marked@9.1.6: {}
+
+ matcher@5.0.0:
+ dependencies:
+ escape-string-regexp: 5.0.0
+
+ md5-hex@3.0.1:
+ dependencies:
+ blueimp-md5: 2.19.0
+
+ mem@9.0.2:
+ dependencies:
+ map-age-cleaner: 0.1.3
+ mimic-fn: 4.0.0
+
+ memoizee@0.4.15:
+ dependencies:
+ d: 1.0.2
+ es5-ext: 0.10.64
+ es6-weak-map: 2.0.3
+ event-emitter: 0.3.5
+ is-promise: 2.2.2
+ lru-queue: 0.1.0
+ next-tick: 1.1.0
+ timers-ext: 0.1.7
+
+ merge-stream@2.0.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.5:
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mime@3.0.0: {}
+
+ mimic-fn@2.1.0: {}
+
+ mimic-fn@4.0.0: {}
+
+ mimic-response@3.1.0: {}
+
+ miniflare@3.20240512.0(bufferutil@4.0.8)(utf-8-validate@6.0.3):
+ dependencies:
+ '@cspotcode/source-map-support': 0.8.1
+ acorn: 8.11.3
+ acorn-walk: 8.3.2
+ capnp-ts: 0.7.0
+ exit-hook: 2.2.1
+ glob-to-regexp: 0.4.1
+ stoppable: 1.1.0
+ undici: 5.28.4
+ workerd: 1.20240512.0
+ ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ youch: 3.3.3
+ zod: 3.23.8
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.11
+
+ minimatch@5.1.6:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ minimatch@7.4.6:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ minimatch@9.0.4:
+ dependencies:
+ brace-expansion: 2.0.1
+
+ minimist@1.2.8: {}
+
+ minipass@7.1.1: {}
+
+ mkdirp-classic@0.5.3: {}
+
+ mlly@1.7.0:
+ dependencies:
+ acorn: 8.11.3
+ pathe: 1.1.2
+ pkg-types: 1.1.1
+ ufo: 1.5.3
+
+ ms@2.1.2: {}
+
+ ms@2.1.3: {}
+
+ mustache@4.2.0: {}
+
+ mysql2@2.3.3:
+ dependencies:
+ denque: 2.1.0
+ generate-function: 2.3.1
+ iconv-lite: 0.6.3
+ long: 4.0.0
+ lru-cache: 6.0.0
+ named-placeholders: 1.1.3
+ seq-queue: 0.0.5
+ sqlstring: 2.3.3
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ named-placeholders@1.1.3:
+ dependencies:
+ lru-cache: 7.18.3
+
+ nan@2.19.0:
+ optional: true
+
+ nanoid@3.3.7: {}
+
+ napi-build-utils@1.0.2: {}
+
+ natural-compare@1.4.0: {}
+
+ next-tick@1.1.0: {}
+
+ node-abi@3.62.0:
+ dependencies:
+ semver: 7.6.2
+
+ node-domexception@1.0.0: {}
+
+ node-emoji@2.1.3:
+ dependencies:
+ '@sindresorhus/is': 4.6.0
+ char-regex: 1.0.2
+ emojilib: 2.4.0
+ skin-tone: 2.0.0
+
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-fetch@3.3.1:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
+ node-fetch@3.3.2:
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+
+ node-forge@1.3.1: {}
+
+ node-gyp-build@4.8.1: {}
+
+ nofilter@3.1.0: {}
+
+ normalize-path@3.0.0: {}
+
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
+ npm-run-path@5.3.0:
+ dependencies:
+ path-key: 4.0.0
+
+ object-assign@4.1.1: {}
+
+ obuf@1.1.2: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
+ onetime@6.0.0:
+ dependencies:
+ mimic-fn: 4.0.0
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ p-defer@1.0.0: {}
+
+ p-event@5.0.1:
+ dependencies:
+ p-timeout: 5.1.0
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-limit@4.0.0:
+ dependencies:
+ yocto-queue: 1.0.0
+
+ p-limit@5.0.0:
+ dependencies:
+ yocto-queue: 1.0.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ p-locate@6.0.0:
+ dependencies:
+ p-limit: 4.0.0
+
+ p-map@5.5.0:
+ dependencies:
+ aggregate-error: 4.0.1
+
+ p-timeout@5.1.0: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ parse-ms@3.0.0: {}
+
+ path-exists@4.0.0: {}
+
+ path-exists@5.0.0: {}
+
+ path-is-absolute@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-key@4.0.0: {}
+
+ path-parse@1.0.7: {}
+
+ path-scurry@1.11.1:
+ dependencies:
+ lru-cache: 10.2.2
+ minipass: 7.1.1
+
+ path-to-regexp@6.2.2: {}
+
+ path-type@4.0.0: {}
+
+ pathe@1.1.2: {}
+
+ pathval@1.1.1: {}
+
+ pause-stream@0.0.11:
+ dependencies:
+ through: 2.3.8
+
+ pg-cloudflare@1.1.1:
+ optional: true
+
+ pg-connection-string@2.6.4: {}
+
+ pg-int8@1.0.1: {}
+
+ pg-numeric@1.0.2: {}
+
+ pg-pool@3.6.2(pg@8.11.5):
+ dependencies:
+ pg: 8.11.5
+
+ pg-protocol@1.6.1: {}
+
+ pg-types@2.2.0:
+ dependencies:
+ pg-int8: 1.0.1
+ postgres-array: 2.0.0
+ postgres-bytea: 1.0.0
+ postgres-date: 1.0.7
+ postgres-interval: 1.2.0
+
+ pg-types@4.0.2:
+ dependencies:
+ pg-int8: 1.0.1
+ pg-numeric: 1.0.2
+ postgres-array: 3.0.2
+ postgres-bytea: 3.0.0
+ postgres-date: 2.1.0
+ postgres-interval: 3.0.0
+ postgres-range: 1.1.4
+
+ pg@8.11.5:
+ dependencies:
+ pg-connection-string: 2.6.4
+ pg-pool: 3.6.2(pg@8.11.5)
+ pg-protocol: 1.6.1
+ pg-types: 2.2.0
+ pgpass: 1.0.5
+ optionalDependencies:
+ pg-cloudflare: 1.1.1
+
+ pgpass@1.0.5:
+ dependencies:
+ split2: 4.2.0
+
+ picocolors@1.0.1: {}
+
+ picomatch@2.3.1: {}
+
+ pirates@4.0.6: {}
+
+ pkg-conf@4.0.0:
+ dependencies:
+ find-up: 6.3.0
+ load-json-file: 7.0.1
+
+ pkg-types@1.1.1:
+ dependencies:
+ confbox: 0.1.7
+ mlly: 1.7.0
+ pathe: 1.1.2
+
+ plur@5.1.0:
+ dependencies:
+ irregular-plurals: 3.5.0
+
+ pluralize@8.0.0: {}
+
+ postcss-load-config@4.0.2(postcss@8.4.38):
+ dependencies:
+ lilconfig: 3.1.1
+ yaml: 2.4.2
+ optionalDependencies:
+ postcss: 8.4.38
+
+ postcss@8.4.38:
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.1
+ source-map-js: 1.2.0
+
+ postgres-array@2.0.0: {}
+
+ postgres-array@3.0.2: {}
+
+ postgres-bytea@1.0.0: {}
+
+ postgres-bytea@3.0.0:
+ dependencies:
+ obuf: 1.1.2
+
+ postgres-date@1.0.7: {}
+
+ postgres-date@2.1.0: {}
+
+ postgres-interval@1.2.0:
+ dependencies:
+ xtend: 4.0.2
+
+ postgres-interval@3.0.0: {}
+
+ postgres-range@1.1.4: {}
+
+ postgres@3.4.4: {}
+
+ prebuild-install@7.1.2:
+ dependencies:
+ detect-libc: 2.0.3
+ expand-template: 2.0.3
+ github-from-package: 0.0.0
+ minimist: 1.2.8
+ mkdirp-classic: 0.5.3
+ napi-build-utils: 1.0.2
+ node-abi: 3.62.0
+ pump: 3.0.0
+ rc: 1.2.8
+ simple-get: 4.0.1
+ tar-fs: 2.1.1
+ tunnel-agent: 0.6.0
+
+ prelude-ls@1.2.1: {}
+
+ prettier-linter-helpers@1.0.0:
+ dependencies:
+ fast-diff: 1.3.0
+
+ prettier@2.8.8: {}
+
+ pretty-format@29.7.0:
+ dependencies:
+ '@jest/schemas': 29.6.3
+ ansi-styles: 5.2.0
+ react-is: 18.3.1
+
+ pretty-ms@8.0.0:
+ dependencies:
+ parse-ms: 3.0.0
+
+ printable-characters@1.0.42: {}
+
+ ps-tree@1.2.0:
+ dependencies:
+ event-stream: 3.3.4
+
+ pump@3.0.0:
+ dependencies:
+ end-of-stream: 1.4.4
+ once: 1.4.0
+
+ punycode@2.3.1: {}
+
+ queue-microtask@1.2.3: {}
+
+ rc@1.2.8:
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+
+ react-is@18.3.1: {}
+
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.1
+
+ redeyed@2.1.1:
+ dependencies:
+ esprima: 4.0.1
+
+ require-directory@2.1.1: {}
+
+ resolve-cwd@3.0.0:
+ dependencies:
+ resolve-from: 5.0.0
+
+ resolve-from@4.0.0: {}
+
+ resolve-from@5.0.0: {}
+
+ resolve-pkg-maps@1.0.0: {}
+
+ resolve.exports@2.0.2: {}
+
+ resolve@1.22.8:
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ reusify@1.0.4: {}
+
+ rimraf@3.0.2:
+ dependencies:
+ glob: 7.2.3
+
+ rollup-plugin-inject@3.0.2:
+ dependencies:
+ estree-walker: 0.6.1
+ magic-string: 0.25.9
+ rollup-pluginutils: 2.8.2
+
+ rollup-plugin-node-polyfills@0.2.1:
+ dependencies:
+ rollup-plugin-inject: 3.0.2
+
+ rollup-pluginutils@2.8.2:
+ dependencies:
+ estree-walker: 0.6.1
+
+ rollup@4.17.2:
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.17.2
+ '@rollup/rollup-android-arm64': 4.17.2
+ '@rollup/rollup-darwin-arm64': 4.17.2
+ '@rollup/rollup-darwin-x64': 4.17.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.17.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.17.2
+ '@rollup/rollup-linux-arm64-gnu': 4.17.2
+ '@rollup/rollup-linux-arm64-musl': 4.17.2
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.17.2
+ '@rollup/rollup-linux-s390x-gnu': 4.17.2
+ '@rollup/rollup-linux-x64-gnu': 4.17.2
+ '@rollup/rollup-linux-x64-musl': 4.17.2
+ '@rollup/rollup-win32-arm64-msvc': 4.17.2
+ '@rollup/rollup-win32-ia32-msvc': 4.17.2
+ '@rollup/rollup-win32-x64-msvc': 4.17.2
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-buffer@5.2.1: {}
+
+ safer-buffer@2.1.2: {}
+
+ selfsigned@2.4.1:
+ dependencies:
+ '@types/node-forge': 1.3.11
+ node-forge: 1.3.1
+
+ semver@7.6.2: {}
+
+ seq-queue@0.0.5: {}
+
+ serialize-error@7.0.1:
+ dependencies:
+ type-fest: 0.13.1
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ siginfo@2.0.0: {}
+
+ signal-exit@3.0.7: {}
+
+ signal-exit@4.1.0: {}
+
+ simple-concat@1.0.1: {}
+
+ simple-get@4.0.1:
+ dependencies:
+ decompress-response: 6.0.0
+ once: 1.4.0
+ simple-concat: 1.0.1
+
+ sisteransi@1.0.5: {}
+
+ skin-tone@2.0.0:
+ dependencies:
+ unicode-emoji-modifier-base: 1.0.0
+
+ slash@3.0.0: {}
+
+ slash@4.0.0: {}
+
+ slice-ansi@5.0.0:
+ dependencies:
+ ansi-styles: 6.2.1
+ is-fullwidth-code-point: 4.0.0
+
+ source-map-js@1.2.0: {}
+
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.6.1: {}
+
+ source-map@0.8.0-beta.0:
+ dependencies:
+ whatwg-url: 7.1.0
+
+ sourcemap-codec@1.4.8: {}
+
+ split-ca@1.0.1: {}
+
+ split2@4.2.0: {}
+
+ split@0.3.3:
+ dependencies:
+ through: 2.3.8
+
+ sprintf-js@1.0.3: {}
+
+ sqlstring@2.3.3: {}
+
+ ssh2@1.15.0:
+ dependencies:
+ asn1: 0.2.6
+ bcrypt-pbkdf: 1.0.2
+ optionalDependencies:
+ cpu-features: 0.0.10
+ nan: 2.19.0
+
+ stack-utils@2.0.6:
+ dependencies:
+ escape-string-regexp: 2.0.0
+
+ stackback@0.0.2: {}
+
+ stacktracey@2.1.8:
+ dependencies:
+ as-table: 1.0.55
+ get-source: 2.0.12
+
+ std-env@3.7.0: {}
+
+ stoppable@1.1.0: {}
+
+ stream-combiner@0.0.4:
+ dependencies:
+ duplexer: 0.1.2
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string-width@5.1.2:
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
+ string_decoder@1.3.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-ansi@7.1.0:
+ dependencies:
+ ansi-regex: 6.0.1
+
+ strip-final-newline@2.0.0: {}
+
+ strip-final-newline@3.0.0: {}
+
+ strip-json-comments@2.0.1: {}
+
+ strip-json-comments@3.1.1: {}
+
+ strip-literal@2.1.0:
+ dependencies:
+ js-tokens: 9.0.0
+
+ strnum@1.0.5: {}
+
+ sucrase@3.35.0:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.5
+ commander: 4.1.1
+ glob: 10.3.15
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+
+ superjson@2.2.1:
+ dependencies:
+ copy-anything: 3.0.5
+
+ supertap@3.0.1:
+ dependencies:
+ indent-string: 5.0.0
+ js-yaml: 3.14.1
+ serialize-error: 7.0.1
+ strip-ansi: 7.1.0
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-hyperlinks@3.0.0:
+ dependencies:
+ has-flag: 4.0.0
+ supports-color: 7.2.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ synckit@0.8.8:
+ dependencies:
+ '@pkgr/core': 0.1.1
+ tslib: 2.6.2
+
+ tar-fs@2.0.1:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.0
+ tar-stream: 2.2.0
+
+ tar-fs@2.1.1:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.0
+ tar-stream: 2.2.0
+
+ tar-stream@2.2.0:
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.4
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
+ temp-dir@3.0.0: {}
+
+ text-table@0.2.0: {}
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ through@2.3.8: {}
+
+ time-zone@1.0.0: {}
+
+ timers-ext@0.1.7:
+ dependencies:
+ es5-ext: 0.10.64
+ next-tick: 1.1.0
+
+ tinybench@2.8.0: {}
+
+ tinypool@0.8.4: {}
+
+ tinyspy@2.2.1: {}
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ tr46@0.0.3: {}
+
+ tr46@1.0.1:
+ dependencies:
+ punycode: 2.3.1
+
+ tree-kill@1.2.2: {}
+
+ ts-api-utils@1.3.0(typescript@5.4.5):
+ dependencies:
+ typescript: 5.4.5
+
+ ts-expose-internals-conditionally@1.0.0-empty.0: {}
+
+ ts-interface-checker@0.1.13: {}
+
+ tsconfck@3.0.3(typescript@5.4.5):
+ optionalDependencies:
+ typescript: 5.4.5
+
+ tslib@1.14.1: {}
+
+ tslib@2.6.2: {}
+
+ tsup@8.0.2(postcss@8.4.38)(typescript@5.4.5):
+ dependencies:
+ bundle-require: 4.1.0(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.17.2
+ source-map: 0.8.0-beta.0
+ sucrase: 3.35.0
+ tree-kill: 1.2.2
+ optionalDependencies:
+ postcss: 8.4.38
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+ - ts-node
+
+ tsx@3.14.0:
+ dependencies:
+ esbuild: 0.18.20
+ get-tsconfig: 4.7.5
+ source-map-support: 0.5.21
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ tunnel-agent@0.6.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ tweetnacl@0.14.5: {}
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ type-detect@4.0.8: {}
+
+ type-fest@0.13.1: {}
+
+ type-fest@0.20.2: {}
+
+ type@2.7.2: {}
+
+ typescript@5.3.3: {}
+
+ typescript@5.4.5: {}
+
+ ufo@1.5.3: {}
+
+ undici-types@5.26.5: {}
+
+ undici@5.28.4:
+ dependencies:
+ '@fastify/busboy': 2.1.1
+
+ unicode-emoji-modifier-base@1.0.0: {}
+
+ universalify@2.0.1: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ utf-8-validate@6.0.3:
+ dependencies:
+ node-gyp-build: 4.8.1
+
+ util-deprecate@1.0.2: {}
+
+ uuid@9.0.1: {}
+
+ validate-npm-package-name@5.0.1: {}
+
+ vite-node@1.6.0(@types/node@18.19.33):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.3.4
+ pathe: 1.1.2
+ picocolors: 1.0.1
+ vite: 5.2.11(@types/node@18.19.33)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ vite-tsconfig-paths@4.3.2(typescript@5.4.5)(vite@5.2.11(@types/node@18.19.33)):
+ dependencies:
+ debug: 4.3.4
+ globrex: 0.1.2
+ tsconfck: 3.0.3(typescript@5.4.5)
+ optionalDependencies:
+ vite: 5.2.11(@types/node@18.19.33)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ vite@5.2.11(@types/node@18.19.33):
+ dependencies:
+ esbuild: 0.20.2
+ postcss: 8.4.38
+ rollup: 4.17.2
+ optionalDependencies:
+ '@types/node': 18.19.33
+ fsevents: 2.3.3
+
+ vitest@1.6.0(@types/node@18.19.33):
+ dependencies:
+ '@vitest/expect': 1.6.0
+ '@vitest/runner': 1.6.0
+ '@vitest/snapshot': 1.6.0
+ '@vitest/spy': 1.6.0
+ '@vitest/utils': 1.6.0
+ acorn-walk: 8.3.2
+ chai: 4.4.1
+ debug: 4.3.4
+ execa: 8.0.1
+ local-pkg: 0.5.0
+ magic-string: 0.30.10
+ pathe: 1.1.2
+ picocolors: 1.0.1
+ std-env: 3.7.0
+ strip-literal: 2.1.0
+ tinybench: 2.8.0
+ tinypool: 0.8.4
+ vite: 5.2.11(@types/node@18.19.33)
+ vite-node: 1.6.0(@types/node@18.19.33)
+ why-is-node-running: 2.2.2
+ optionalDependencies:
+ '@types/node': 18.19.33
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ web-streams-polyfill@3.3.3: {}
+
+ webidl-conversions@3.0.1: {}
+
+ webidl-conversions@4.0.2: {}
+
+ webpod@0.0.2: {}
+
+ well-known-symbols@2.0.0: {}
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
+ whatwg-url@7.1.0:
+ dependencies:
+ lodash.sortby: 4.7.0
+ tr46: 1.0.1
+ webidl-conversions: 4.0.2
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ which@3.0.1:
+ dependencies:
+ isexe: 2.0.0
+
+ why-is-node-running@2.2.2:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ word-wrap@1.2.5: {}
+
+ wordwrap@1.0.0: {}
+
+ workerd@1.20240512.0:
+ optionalDependencies:
+ '@cloudflare/workerd-darwin-64': 1.20240512.0
+ '@cloudflare/workerd-darwin-arm64': 1.20240512.0
+ '@cloudflare/workerd-linux-64': 1.20240512.0
+ '@cloudflare/workerd-linux-arm64': 1.20240512.0
+ '@cloudflare/workerd-windows-64': 1.20240512.0
+
+ wrangler@3.57.0(@cloudflare/workers-types@4.20240512.0)(bufferutil@4.0.8)(utf-8-validate@6.0.3):
+ dependencies:
+ '@cloudflare/kv-asset-handler': 0.3.2
+ '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19)
+ '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19)
+ blake3-wasm: 2.1.5
+ chokidar: 3.6.0
+ esbuild: 0.17.19
+ miniflare: 3.20240512.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)
+ nanoid: 3.3.7
+ path-to-regexp: 6.2.2
+ resolve: 1.22.8
+ resolve.exports: 2.0.2
+ selfsigned: 2.4.1
+ source-map: 0.6.1
+ xxhash-wasm: 1.0.2
+ optionalDependencies:
+ '@cloudflare/workers-types': 4.20240512.0
+ fsevents: 2.3.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@8.1.0:
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ wrappy@1.0.2: {}
+
+ write-file-atomic@5.0.1:
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 4.1.0
+
+ ws@8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3):
+ optionalDependencies:
+ bufferutil: 4.0.8
+ utf-8-validate: 6.0.3
+
+ ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@6.0.3):
+ optionalDependencies:
+ bufferutil: 4.0.8
+ utf-8-validate: 6.0.3
+
+ xtend@4.0.2: {}
+
+ xxhash-wasm@1.0.2: {}
+
+ y18n@5.0.8: {}
+
+ yallist@4.0.0: {}
+
+ yaml@2.4.2: {}
+
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.2
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
+ yocto-queue@0.1.0: {}
+
+ yocto-queue@1.0.0: {}
+
+ youch@3.3.3:
+ dependencies:
+ cookie: 0.5.0
+ mustache: 4.2.0
+ stacktracey: 2.1.8
+
+ zod@3.23.8: {}
+
+ zx@7.2.3:
+ dependencies:
+ '@types/fs-extra': 11.0.4
+ '@types/minimist': 1.2.5
+ '@types/node': 18.19.33
+ '@types/ps-tree': 1.1.6
+ '@types/which': 3.0.3
+ chalk: 5.3.0
+ fs-extra: 11.2.0
+ fx: 34.0.0
+ globby: 13.2.2
+ minimist: 1.2.8
+ node-fetch: 3.3.1
+ ps-tree: 1.2.0
+ webpod: 0.0.2
+ which: 3.0.1
+ yaml: 2.4.2
diff --git a/drizzle-kit/schema.ts b/drizzle-kit/schema.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/drizzle-kit/src/@types/utils.ts b/drizzle-kit/src/@types/utils.ts
new file mode 100644
index 000000000..3f14151a4
--- /dev/null
+++ b/drizzle-kit/src/@types/utils.ts
@@ -0,0 +1,51 @@
+declare global {
+ interface String {
+ trimChar(char: string): string;
+ squashSpaces(): string;
+ capitalise(): string;
+ camelCase(): string;
+ concatIf(it: string, condition: boolean): string;
+ }
+
+ interface Array {
+ random(): T;
+ }
+}
+import camelcase from 'camelcase';
+
+String.prototype.trimChar = function(char: string) {
+ let start = 0;
+ let end = this.length;
+
+ while (start < end && this[start] === char) ++start;
+ while (end > start && this[end - 1] === char) --end;
+
+ // this.toString() due to ava deep equal issue with String { "value" }
+ return start > 0 || end < this.length
+ ? this.substring(start, end)
+ : this.toString();
+};
+
+String.prototype.squashSpaces = function() {
+ return this.replace(/ +/g, ' ').trim();
+};
+
+String.prototype.camelCase = function() {
+ return camelcase(String(this));
+};
+
+String.prototype.capitalise = function() {
+ return this && this.length > 0
+ ? `${this[0].toUpperCase()}${this.slice(1)}`
+ : String(this);
+};
+
+String.prototype.concatIf = function(it: string, condition: boolean) {
+ return condition ? `${this}${it}` : String(this);
+};
+
+Array.prototype.random = function() {
+ return this[~~(Math.random() * this.length)];
+};
+
+export {};
diff --git a/drizzle-kit/src/api.ts b/drizzle-kit/src/api.ts
new file mode 100644
index 000000000..3922da088
--- /dev/null
+++ b/drizzle-kit/src/api.ts
@@ -0,0 +1,460 @@
+import { randomUUID } from 'crypto';
+import { LibSQLDatabase } from 'drizzle-orm/libsql';
+import type { MySql2Database } from 'drizzle-orm/mysql2';
+import { PgDatabase } from 'drizzle-orm/pg-core';
+import { SingleStoreDriverDatabase } from 'drizzle-orm/singlestore';
+import {
+ columnsResolver,
+ enumsResolver,
+ schemasResolver,
+ sequencesResolver,
+ tablesResolver,
+} from './cli/commands/migrate';
+import { pgPushIntrospect } from './cli/commands/pgIntrospect';
+import { pgSuggestions } from './cli/commands/pgPushUtils';
+import { updateUpToV6 as upPgV6, updateUpToV7 as upPgV7 } from './cli/commands/pgUp';
+import { sqlitePushIntrospect } from './cli/commands/sqliteIntrospect';
+import { logSuggestionsAndReturn } from './cli/commands/sqlitePushUtils';
+import { originUUID } from './global';
+import { fillPgSnapshot } from './migrationPreparator';
+import { MySqlSchema as MySQLSchemaKit, mysqlSchema, squashMysqlScheme } from './serializer/mysqlSchema';
+import { generateMySqlSnapshot } from './serializer/mysqlSerializer';
+import { prepareFromExports } from './serializer/pgImports';
+import { PgSchema as PgSchemaKit, pgSchema, squashPgScheme } from './serializer/pgSchema';
+import { generatePgSnapshot } from './serializer/pgSerializer';
+import {
+ SingleStoreSchema as SingleStoreSchemaKit,
+ singlestoreSchema,
+ squashSingleStoreScheme,
+} from './serializer/singlestoreSchema';
+import { generateSingleStoreSnapshot } from './serializer/singlestoreSerializer';
+import { SQLiteSchema as SQLiteSchemaKit, sqliteSchema, squashSqliteScheme } from './serializer/sqliteSchema';
+import { generateSqliteSnapshot } from './serializer/sqliteSerializer';
+import type { DB, SQLiteDB } from './utils';
+export type DrizzleSnapshotJSON = PgSchemaKit;
+export type DrizzleSQLiteSnapshotJSON = SQLiteSchemaKit;
+export type DrizzleMySQLSnapshotJSON = MySQLSchemaKit;
+export type DrizzleSingleStoreSnapshotJSON = SingleStoreSchemaKit;
+
+export const generateDrizzleJson = (
+ imports: Record,
+ prevId?: string,
+ schemaFilters?: string[],
+): PgSchemaKit => {
+ const prepared = prepareFromExports(imports);
+
+ const id = randomUUID();
+
+ const snapshot = generatePgSnapshot(
+ prepared.tables,
+ prepared.enums,
+ prepared.schemas,
+ prepared.sequences,
+ schemaFilters,
+ );
+
+ return fillPgSnapshot({
+ serialized: snapshot,
+ id,
+ idPrev: prevId ?? originUUID,
+ });
+};
+
+export const generateMigration = async (
+ prev: DrizzleSnapshotJSON,
+ cur: DrizzleSnapshotJSON,
+) => {
+ const { applyPgSnapshotsDiff } = await import('./snapshotsDiffer');
+
+ const validatedPrev = pgSchema.parse(prev);
+ const validatedCur = pgSchema.parse(cur);
+
+ const squashedPrev = squashPgScheme(validatedPrev);
+ const squashedCur = squashPgScheme(validatedCur);
+
+ const { sqlStatements, _meta } = await applyPgSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ schemasResolver,
+ enumsResolver,
+ sequencesResolver,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ return sqlStatements;
+};
+
+export const pushSchema = async (
+ imports: Record,
+ drizzleInstance: PgDatabase,
+ schemaFilters?: string[],
+) => {
+ const { applyPgSnapshotsDiff } = await import('./snapshotsDiffer');
+ const { sql } = await import('drizzle-orm');
+
+ const db: DB = {
+ query: async (query: string, params?: any[]) => {
+ const res = await drizzleInstance.execute(sql.raw(query));
+ return res.rows;
+ },
+ };
+
+ const cur = generateDrizzleJson(imports);
+ const { schema: prev } = await pgPushIntrospect(
+ db,
+ [],
+ schemaFilters ?? ['public'],
+ );
+
+ const validatedPrev = pgSchema.parse(prev);
+ const validatedCur = pgSchema.parse(cur);
+
+ const squashedPrev = squashPgScheme(validatedPrev, 'push');
+ const squashedCur = squashPgScheme(validatedCur, 'push');
+
+ const { statements } = await applyPgSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ schemasResolver,
+ enumsResolver,
+ sequencesResolver,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ const { shouldAskForApprove, statementsToExecute, infoToPrint } = await pgSuggestions(db, statements);
+
+ return {
+ hasDataLoss: shouldAskForApprove,
+ warnings: infoToPrint,
+ statementsToExecute,
+ apply: async () => {
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+ },
+ };
+};
+
+// SQLite
+
+export const generateSQLiteDrizzleJson = async (
+ imports: Record,
+ prevId?: string,
+): Promise => {
+ const { prepareFromExports } = await import('./serializer/sqliteImports');
+
+ const prepared = prepareFromExports(imports);
+
+ const id = randomUUID();
+
+ const snapshot = generateSqliteSnapshot(prepared.tables);
+
+ return {
+ ...snapshot,
+ id,
+ prevId: prevId ?? originUUID,
+ };
+};
+
+export const generateSQLiteMigration = async (
+ prev: DrizzleSQLiteSnapshotJSON,
+ cur: DrizzleSQLiteSnapshotJSON,
+) => {
+ const { applySqliteSnapshotsDiff } = await import('./snapshotsDiffer');
+
+ const validatedPrev = sqliteSchema.parse(prev);
+ const validatedCur = sqliteSchema.parse(cur);
+
+ const squashedPrev = squashSqliteScheme(validatedPrev);
+ const squashedCur = squashSqliteScheme(validatedCur);
+
+ const { sqlStatements } = await applySqliteSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ return sqlStatements;
+};
+
+export const pushSQLiteSchema = async (
+ imports: Record,
+ drizzleInstance: LibSQLDatabase,
+) => {
+ const { applySqliteSnapshotsDiff } = await import('./snapshotsDiffer');
+ const { sql } = await import('drizzle-orm');
+
+ const db: SQLiteDB = {
+ query: async (query: string, params?: any[]) => {
+ const res = drizzleInstance.all(sql.raw(query));
+ return res;
+ },
+ run: async (query: string) => {
+ return Promise.resolve(drizzleInstance.run(sql.raw(query))).then(
+ () => {},
+ );
+ },
+ };
+
+ const cur = await generateSQLiteDrizzleJson(imports);
+ const { schema: prev } = await sqlitePushIntrospect(db, []);
+
+ const validatedPrev = sqliteSchema.parse(prev);
+ const validatedCur = sqliteSchema.parse(cur);
+
+ const squashedPrev = squashSqliteScheme(validatedPrev, 'push');
+ const squashedCur = squashSqliteScheme(validatedCur, 'push');
+
+ const { statements, _meta } = await applySqliteSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ const { shouldAskForApprove, statementsToExecute, infoToPrint } = await logSuggestionsAndReturn(
+ db,
+ statements,
+ squashedPrev,
+ squashedCur,
+ _meta!,
+ );
+
+ return {
+ hasDataLoss: shouldAskForApprove,
+ warnings: infoToPrint,
+ statementsToExecute,
+ apply: async () => {
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+ },
+ };
+};
+
+// MySQL
+
+export const generateMySQLDrizzleJson = async (
+ imports: Record,
+ prevId?: string,
+): Promise => {
+ const { prepareFromExports } = await import('./serializer/mysqlImports');
+
+ const prepared = prepareFromExports(imports);
+
+ const id = randomUUID();
+
+ const snapshot = generateMySqlSnapshot(prepared.tables);
+
+ return {
+ ...snapshot,
+ id,
+ prevId: prevId ?? originUUID,
+ };
+};
+
+export const generateMySQLMigration = async (
+ prev: DrizzleMySQLSnapshotJSON,
+ cur: DrizzleMySQLSnapshotJSON,
+) => {
+ const { applyMysqlSnapshotsDiff } = await import('./snapshotsDiffer');
+
+ const validatedPrev = mysqlSchema.parse(prev);
+ const validatedCur = mysqlSchema.parse(cur);
+
+ const squashedPrev = squashMysqlScheme(validatedPrev);
+ const squashedCur = squashMysqlScheme(validatedCur);
+
+ const { sqlStatements } = await applyMysqlSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ return sqlStatements;
+};
+
+export const pushMySQLSchema = async (
+ imports: Record,
+ drizzleInstance: MySql2Database,
+ databaseName: string,
+) => {
+ const { applyMysqlSnapshotsDiff } = await import('./snapshotsDiffer');
+ const { logSuggestionsAndReturn } = await import(
+ './cli/commands/mysqlPushUtils'
+ );
+ const { mysqlPushIntrospect } = await import(
+ './cli/commands/mysqlIntrospect'
+ );
+ const { sql } = await import('drizzle-orm');
+
+ const db: DB = {
+ query: async (query: string, params?: any[]) => {
+ const res = await drizzleInstance.execute(sql.raw(query));
+ return res[0] as unknown as any[];
+ },
+ };
+ const cur = await generateMySQLDrizzleJson(imports);
+ const { schema: prev } = await mysqlPushIntrospect(db, databaseName, []);
+
+ const validatedPrev = mysqlSchema.parse(prev);
+ const validatedCur = mysqlSchema.parse(cur);
+
+ const squashedPrev = squashMysqlScheme(validatedPrev);
+ const squashedCur = squashMysqlScheme(validatedCur);
+
+ const { statements } = await applyMysqlSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ const { shouldAskForApprove, statementsToExecute, infoToPrint } = await logSuggestionsAndReturn(
+ db,
+ statements,
+ validatedCur,
+ );
+
+ return {
+ hasDataLoss: shouldAskForApprove,
+ warnings: infoToPrint,
+ statementsToExecute,
+ apply: async () => {
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+ },
+ };
+};
+
+// SingleStore
+
+export const generateSingleStoreDrizzleJson = async (
+ imports: Record,
+ prevId?: string,
+): Promise => {
+ const { prepareFromExports } = await import('./serializer/singlestoreImports');
+
+ const prepared = prepareFromExports(imports);
+
+ const id = randomUUID();
+
+ const snapshot = generateSingleStoreSnapshot(prepared.tables);
+
+ return {
+ ...snapshot,
+ id,
+ prevId: prevId ?? originUUID,
+ };
+};
+
+export const generateSingleStoreMigration = async (
+ prev: DrizzleSingleStoreSnapshotJSON,
+ cur: DrizzleSingleStoreSnapshotJSON,
+) => {
+ const { applySingleStoreSnapshotsDiff } = await import('./snapshotsDiffer');
+
+ const validatedPrev = singlestoreSchema.parse(prev);
+ const validatedCur = singlestoreSchema.parse(cur);
+
+ const squashedPrev = squashSingleStoreScheme(validatedPrev);
+ const squashedCur = squashSingleStoreScheme(validatedCur);
+
+ const { sqlStatements } = await applySingleStoreSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ return sqlStatements;
+};
+
+export const pushSingleStoreSchema = async (
+ imports: Record,
+ drizzleInstance: SingleStoreDriverDatabase,
+ databaseName: string,
+) => {
+ const { applySingleStoreSnapshotsDiff } = await import('./snapshotsDiffer');
+ const { logSuggestionsAndReturn } = await import(
+ './cli/commands/singlestorePushUtils'
+ );
+ const { singlestorePushIntrospect } = await import(
+ './cli/commands/singlestoreIntrospect'
+ );
+ const { sql } = await import('drizzle-orm');
+
+ const db: DB = {
+ query: async (query: string, params?: any[]) => {
+ const res = await drizzleInstance.execute(sql.raw(query));
+ return res[0] as unknown as any[];
+ },
+ };
+ const cur = await generateSingleStoreDrizzleJson(imports);
+ const { schema: prev } = await singlestorePushIntrospect(db, databaseName, []);
+
+ const validatedPrev = singlestoreSchema.parse(prev);
+ const validatedCur = singlestoreSchema.parse(cur);
+
+ const squashedPrev = squashSingleStoreScheme(validatedPrev);
+ const squashedCur = squashSingleStoreScheme(validatedCur);
+
+ const { statements } = await applySingleStoreSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ const { shouldAskForApprove, statementsToExecute, infoToPrint } = await logSuggestionsAndReturn(
+ db,
+ statements,
+ validatedCur,
+ );
+
+ return {
+ hasDataLoss: shouldAskForApprove,
+ warnings: infoToPrint,
+ statementsToExecute,
+ apply: async () => {
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+ },
+ };
+};
+
+export const upPgSnapshot = (snapshot: Record) => {
+ if (snapshot.version === '5') {
+ return upPgV7(upPgV6(snapshot));
+ }
+ if (snapshot.version === '6') {
+ return upPgV7(snapshot);
+ }
+ return snapshot;
+};
diff --git a/drizzle-kit/src/cli/commands/_es5.ts b/drizzle-kit/src/cli/commands/_es5.ts
new file mode 100644
index 000000000..51838ffe5
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/_es5.ts
@@ -0,0 +1,2 @@
+const _ = '';
+export default _;
diff --git a/drizzle-kit/src/cli/commands/check.ts b/drizzle-kit/src/cli/commands/check.ts
new file mode 100644
index 000000000..092057372
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/check.ts
@@ -0,0 +1,52 @@
+import { Dialect } from '../../schemaValidator';
+import { prepareOutFolder, validateWithReport } from '../../utils';
+
+export const checkHandler = (out: string, dialect: Dialect) => {
+ const { snapshots } = prepareOutFolder(out, dialect);
+ const report = validateWithReport(snapshots, dialect);
+
+ if (report.nonLatest.length > 0) {
+ console.log(
+ report.nonLatest
+ .map((it) => {
+ return `${it} is not of the latest version, please run "drizzle-kit up"`;
+ })
+ .join('\n'),
+ );
+ process.exit(1);
+ }
+
+ if (report.malformed.length) {
+ const message = report.malformed
+ .map((it) => {
+ return `${it} data is malformed`;
+ })
+ .join('\n');
+ console.log(message);
+ }
+
+ const collisionEntries = Object.entries(report.idsMap).filter(
+ (it) => it[1].snapshots.length > 1,
+ );
+
+ const message = collisionEntries
+ .map((it) => {
+ const data = it[1];
+ return `[${
+ data.snapshots.join(
+ ', ',
+ )
+ }] are pointing to a parent snapshot: ${data.parent}/snapshot.json which is a collision.`;
+ })
+ .join('\n');
+
+ if (message) {
+ console.log(message);
+ }
+
+ const abort = report.malformed.length!! || collisionEntries.length > 0;
+
+ if (abort) {
+ process.exit(1);
+ }
+};
diff --git a/drizzle-kit/src/cli/commands/drop.ts b/drizzle-kit/src/cli/commands/drop.ts
new file mode 100644
index 000000000..183e9459d
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/drop.ts
@@ -0,0 +1,60 @@
+import chalk from 'chalk';
+import { readFileSync, rmSync, writeFileSync } from 'fs';
+import fs from 'fs';
+import { render } from 'hanji';
+import { join } from 'path';
+import { Journal } from '../../utils';
+import { DropMigrationView } from '../views';
+import { embeddedMigrations } from './migrate';
+
+export const dropMigration = async ({
+ out,
+ bundle,
+}: {
+ out: string;
+ bundle: boolean;
+}) => {
+ const metaFilePath = join(out, 'meta', '_journal.json');
+ const journal = JSON.parse(readFileSync(metaFilePath, 'utf-8')) as Journal;
+
+ if (journal.entries.length === 0) {
+ console.log(
+ `[${chalk.blue('i')}] no migration entries found in ${metaFilePath}`,
+ );
+ return;
+ }
+
+ const result = await render(new DropMigrationView(journal.entries));
+ if (result.status === 'aborted') return;
+
+ delete journal.entries[journal.entries.indexOf(result.data!)];
+
+ const resultJournal: Journal = {
+ ...journal,
+ entries: journal.entries.filter(Boolean),
+ };
+ const sqlFilePath = join(out, `${result.data.tag}.sql`);
+ const snapshotFilePath = join(
+ out,
+ 'meta',
+ `${result.data.tag.split('_')[0]}_snapshot.json`,
+ );
+ rmSync(sqlFilePath);
+ rmSync(snapshotFilePath);
+ writeFileSync(metaFilePath, JSON.stringify(resultJournal, null, 2));
+
+ if (bundle) {
+ fs.writeFileSync(
+ join(out, `migrations.js`),
+ embeddedMigrations(resultJournal),
+ );
+ }
+
+ console.log(
+ `[${chalk.green('✓')}] ${
+ chalk.bold(
+ result.data.tag,
+ )
+ } migration successfully dropped`,
+ );
+};
diff --git a/drizzle-kit/src/cli/commands/introspect.ts b/drizzle-kit/src/cli/commands/introspect.ts
new file mode 100644
index 000000000..3558bf83c
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/introspect.ts
@@ -0,0 +1,633 @@
+import chalk from 'chalk';
+import { writeFileSync } from 'fs';
+import { render, renderWithTask } from 'hanji';
+import { Minimatch } from 'minimatch';
+import { join } from 'path';
+import { plural, singular } from 'pluralize';
+import { drySingleStore, SingleStoreSchema, squashSingleStoreScheme } from 'src/serializer/singlestoreSchema';
+import { assertUnreachable, originUUID } from '../../global';
+import { schemaToTypeScript as mysqlSchemaToTypeScript } from '../../introspect-mysql';
+import { paramNameFor, schemaToTypeScript as postgresSchemaToTypeScript } from '../../introspect-pg';
+import { schemaToTypeScript as singlestoreSchemaToTypeScript } from '../../introspect-singlestore';
+import { schemaToTypeScript as sqliteSchemaToTypeScript } from '../../introspect-sqlite';
+import { dryMySql, MySqlSchema, squashMysqlScheme } from '../../serializer/mysqlSchema';
+import { fromDatabase as fromMysqlDatabase } from '../../serializer/mysqlSerializer';
+import { dryPg, type PgSchema, squashPgScheme } from '../../serializer/pgSchema';
+import { fromDatabase as fromPostgresDatabase } from '../../serializer/pgSerializer';
+import { fromDatabase as fromSingleStoreDatabase } from '../../serializer/singlestoreSerializer';
+import { drySQLite, type SQLiteSchema, squashSqliteScheme } from '../../serializer/sqliteSchema';
+import { fromDatabase as fromSqliteDatabase } from '../../serializer/sqliteSerializer';
+import {
+ applyMysqlSnapshotsDiff,
+ applyPgSnapshotsDiff,
+ applySingleStoreSnapshotsDiff,
+ applySqliteSnapshotsDiff,
+} from '../../snapshotsDiffer';
+import { prepareOutFolder } from '../../utils';
+import type { Casing, Prefix } from '../validations/common';
+import type { MysqlCredentials } from '../validations/mysql';
+import type { PostgresCredentials } from '../validations/postgres';
+import { SingleStoreCredentials } from '../validations/singlestore';
+import type { SqliteCredentials } from '../validations/sqlite';
+import { IntrospectProgress } from '../views';
+import {
+ columnsResolver,
+ enumsResolver,
+ schemasResolver,
+ sequencesResolver,
+ tablesResolver,
+ writeResult,
+} from './migrate';
+
+export const introspectPostgres = async (
+ casing: Casing,
+ out: string,
+ breakpoints: boolean,
+ credentials: PostgresCredentials,
+ tablesFilter: string[],
+ schemasFilter: string[],
+ prefix: Prefix,
+) => {
+ const { preparePostgresDB } = await import('../connections');
+ const db = await preparePostgresDB(credentials);
+
+ const matchers = tablesFilter.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new IntrospectProgress(true);
+ const res = await renderWithTask(
+ progress,
+ fromPostgresDatabase(db, filter, schemasFilter, (stage, count, status) => {
+ progress.update(stage, count, status);
+ }),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as PgSchema;
+ const ts = postgresSchemaToTypeScript(schema, casing);
+ const relationsTs = relationsToTypeScript(schema, casing);
+ const { internal, ...schemaWithoutInternals } = schema;
+
+ const schemaFile = join(out, 'schema.ts');
+ writeFileSync(schemaFile, ts.file);
+ const relationsFile = join(out, 'relations.ts');
+ writeFileSync(relationsFile, relationsTs.file);
+ console.log();
+
+ const { snapshots, journal } = prepareOutFolder(out, 'postgresql');
+
+ if (snapshots.length === 0) {
+ const { sqlStatements, _meta } = await applyPgSnapshotsDiff(
+ squashPgScheme(dryPg),
+ squashPgScheme(schema),
+ schemasResolver,
+ enumsResolver,
+ sequencesResolver,
+ tablesResolver,
+ columnsResolver,
+ dryPg,
+ schema,
+ );
+
+ writeResult({
+ cur: schema,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder: out,
+ breakpoints,
+ type: 'introspect',
+ prefixMode: prefix,
+ });
+ } else {
+ render(
+ `[${
+ chalk.blue(
+ 'i',
+ )
+ }] No SQL generated, you already have migrations in project`,
+ );
+ }
+
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You schema file is ready ➜ ${chalk.bold.underline.blue(schemaFile)} 🚀`,
+ );
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You relations file is ready ➜ ${
+ chalk.bold.underline.blue(
+ relationsFile,
+ )
+ } 🚀`,
+ );
+ process.exit(0);
+};
+
+export const introspectMysql = async (
+ casing: Casing,
+ out: string,
+ breakpoints: boolean,
+ credentials: MysqlCredentials,
+ tablesFilter: string[],
+ prefix: Prefix,
+) => {
+ const { connectToMySQL } = await import('../connections');
+ const { db, database } = await connectToMySQL(credentials);
+
+ const matchers = tablesFilter.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new IntrospectProgress();
+ const res = await renderWithTask(
+ progress,
+ fromMysqlDatabase(db, database, filter, (stage, count, status) => {
+ progress.update(stage, count, status);
+ }),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as MySqlSchema;
+ const ts = mysqlSchemaToTypeScript(schema, casing);
+ const relationsTs = relationsToTypeScript(schema, casing);
+
+ const schemaFile = join(out, 'schema.ts');
+ writeFileSync(schemaFile, ts.file);
+ const relationsFile = join(out, 'relations.ts');
+ writeFileSync(relationsFile, relationsTs.file);
+ console.log();
+
+ const { snapshots, journal } = prepareOutFolder(out, 'mysql');
+
+ if (snapshots.length === 0) {
+ const { sqlStatements, _meta } = await applyMysqlSnapshotsDiff(
+ squashMysqlScheme(dryMySql),
+ squashMysqlScheme(schema),
+ tablesResolver,
+ columnsResolver,
+ dryMySql,
+ schema,
+ );
+
+ writeResult({
+ cur: schema,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder: out,
+ breakpoints,
+ type: 'introspect',
+ prefixMode: prefix,
+ });
+ } else {
+ render(
+ `[${
+ chalk.blue(
+ 'i',
+ )
+ }] No SQL generated, you already have migrations in project`,
+ );
+ }
+
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You schema file is ready ➜ ${chalk.bold.underline.blue(schemaFile)} 🚀`,
+ );
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You relations file is ready ➜ ${
+ chalk.bold.underline.blue(
+ relationsFile,
+ )
+ } 🚀`,
+ );
+ process.exit(0);
+};
+
+export const introspectSingleStore = async (
+ casing: Casing,
+ out: string,
+ breakpoints: boolean,
+ credentials: SingleStoreCredentials,
+ tablesFilter: string[],
+ prefix: Prefix,
+) => {
+ const { connectToSingleStore } = await import('../connections');
+ const { db, database } = await connectToSingleStore(credentials);
+
+ const matchers = tablesFilter.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new IntrospectProgress();
+ const res = await renderWithTask(
+ progress,
+ fromSingleStoreDatabase(db, database, filter, (stage, count, status) => {
+ progress.update(stage, count, status);
+ }),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as SingleStoreSchema;
+ const ts = singlestoreSchemaToTypeScript(schema, casing);
+ const { internal, ...schemaWithoutInternals } = schema;
+
+ const schemaFile = join(out, 'schema.ts');
+ writeFileSync(schemaFile, ts.file);
+ console.log();
+
+ const { snapshots, journal } = prepareOutFolder(out, 'postgresql');
+
+ if (snapshots.length === 0) {
+ const { sqlStatements, _meta } = await applySingleStoreSnapshotsDiff(
+ squashSingleStoreScheme(drySingleStore),
+ squashSingleStoreScheme(schema),
+ tablesResolver,
+ columnsResolver,
+ drySingleStore,
+ schema,
+ );
+
+ writeResult({
+ cur: schema,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder: out,
+ breakpoints,
+ type: 'introspect',
+ prefixMode: prefix,
+ });
+ } else {
+ render(
+ `[${
+ chalk.blue(
+ 'i',
+ )
+ }] No SQL generated, you already have migrations in project`,
+ );
+ }
+
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You schema file is ready ➜ ${chalk.bold.underline.blue(schemaFile)} 🚀`,
+ );
+ process.exit(0);
+};
+
+export const introspectSqlite = async (
+ casing: Casing,
+ out: string,
+ breakpoints: boolean,
+ credentials: SqliteCredentials,
+ tablesFilter: string[],
+ prefix: Prefix,
+) => {
+ const { connectToSQLite } = await import('../connections');
+ const db = await connectToSQLite(credentials);
+
+ const matchers = tablesFilter.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new IntrospectProgress();
+ const res = await renderWithTask(
+ progress,
+ fromSqliteDatabase(db, filter, (stage, count, status) => {
+ progress.update(stage, count, status);
+ }),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as SQLiteSchema;
+ const ts = sqliteSchemaToTypeScript(schema, casing);
+ const relationsTs = relationsToTypeScript(schema, casing);
+
+ // check orm and orm-pg api version
+
+ const schemaFile = join(out, 'schema.ts');
+ writeFileSync(schemaFile, ts.file);
+ const relationsFile = join(out, 'relations.ts');
+ writeFileSync(relationsFile, relationsTs.file);
+ console.log();
+
+ const { snapshots, journal } = prepareOutFolder(out, 'sqlite');
+
+ if (snapshots.length === 0) {
+ const { sqlStatements, _meta } = await applySqliteSnapshotsDiff(
+ squashSqliteScheme(drySQLite),
+ squashSqliteScheme(schema),
+ tablesResolver,
+ columnsResolver,
+ drySQLite,
+ schema,
+ );
+
+ writeResult({
+ cur: schema,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder: out,
+ breakpoints,
+ type: 'introspect',
+ prefixMode: prefix,
+ });
+ } else {
+ render(
+ `[${
+ chalk.blue(
+ 'i',
+ )
+ }] No SQL generated, you already have migrations in project`,
+ );
+ }
+
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You schema file is ready ➜ ${chalk.bold.underline.blue(schemaFile)} 🚀`,
+ );
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] You relations file is ready ➜ ${
+ chalk.bold.underline.blue(
+ relationsFile,
+ )
+ } 🚀`,
+ );
+ process.exit(0);
+};
+
+const withCasing = (value: string, casing: Casing) => {
+ if (casing === 'preserve') {
+ return value;
+ }
+ if (casing === 'camel') {
+ return value.camelCase();
+ }
+
+ assertUnreachable(casing);
+};
+
+export const relationsToTypeScript = (
+ schema: {
+ tables: Record<
+ string,
+ {
+ schema?: string;
+ foreignKeys: Record<
+ string,
+ {
+ name: string;
+ tableFrom: string;
+ columnsFrom: string[];
+ tableTo: string;
+ schemaTo?: string;
+ columnsTo: string[];
+ onUpdate?: string | undefined;
+ onDelete?: string | undefined;
+ }
+ >;
+ }
+ >;
+ },
+ casing: Casing,
+) => {
+ const imports: string[] = [];
+ const tableRelations: Record<
+ string,
+ {
+ name: string;
+ type: 'one' | 'many';
+ tableFrom: string;
+ schemaFrom?: string;
+ columnFrom: string;
+ tableTo: string;
+ schemaTo?: string;
+ columnTo: string;
+ relationName?: string;
+ }[]
+ > = {};
+
+ Object.values(schema.tables).forEach((table) => {
+ Object.values(table.foreignKeys).forEach((fk) => {
+ const tableNameFrom = paramNameFor(fk.tableFrom, table.schema);
+ const tableNameTo = paramNameFor(fk.tableTo, fk.schemaTo);
+ const tableFrom = withCasing(tableNameFrom, casing);
+ const tableTo = withCasing(tableNameTo, casing);
+ const columnFrom = withCasing(fk.columnsFrom[0], casing);
+ const columnTo = withCasing(fk.columnsTo[0], casing);
+
+ imports.push(tableTo, tableFrom);
+
+ // const keyFrom = `${schemaFrom}.${tableFrom}`;
+ const keyFrom = tableFrom;
+
+ if (!tableRelations[keyFrom]) {
+ tableRelations[keyFrom] = [];
+ }
+
+ tableRelations[keyFrom].push({
+ name: singular(tableTo),
+ type: 'one',
+ tableFrom,
+ columnFrom,
+ tableTo,
+ columnTo,
+ });
+
+ // const keyTo = `${schemaTo}.${tableTo}`;
+ const keyTo = tableTo;
+
+ if (!tableRelations[keyTo]) {
+ tableRelations[keyTo] = [];
+ }
+
+ tableRelations[keyTo].push({
+ name: plural(tableFrom),
+ type: 'many',
+ tableFrom: tableTo,
+ columnFrom: columnTo,
+ tableTo: tableFrom,
+ columnTo: columnFrom,
+ });
+ });
+ });
+
+ const uniqueImports = [...new Set(imports)];
+
+ const importsTs = `import { relations } from "drizzle-orm/relations";\nimport { ${
+ uniqueImports.join(
+ ', ',
+ )
+ } } from "./schema";\n\n`;
+
+ const relationStatements = Object.entries(tableRelations).map(
+ ([table, relations]) => {
+ const hasOne = relations.some((it) => it.type === 'one');
+ const hasMany = relations.some((it) => it.type === 'many');
+
+ // * change relation names if they are duplicated or if there are multiple relations between two tables
+ const preparedRelations = relations.map(
+ (relation, relationIndex, originArray) => {
+ let name = relation.name;
+ let relationName;
+ const hasMultipleRelations = originArray.some(
+ (it, originIndex) => relationIndex !== originIndex && it.tableTo === relation.tableTo,
+ );
+ if (hasMultipleRelations) {
+ relationName = relation.type === 'one'
+ ? `${relation.tableFrom}_${relation.columnFrom}_${relation.tableTo}_${relation.columnTo}`
+ : `${relation.tableTo}_${relation.columnTo}_${relation.tableFrom}_${relation.columnFrom}`;
+ }
+ const hasDuplicatedRelation = originArray.some(
+ (it, originIndex) => relationIndex !== originIndex && it.name === relation.name,
+ );
+ if (hasDuplicatedRelation) {
+ name = `${relation.name}_${relation.type === 'one' ? relation.columnFrom : relation.columnTo}`;
+ }
+ return {
+ ...relation,
+ name,
+ relationName,
+ };
+ },
+ );
+
+ const fields = preparedRelations.map((relation) => {
+ if (relation.type === 'one') {
+ return `\t${relation.name}: one(${relation.tableTo}, {\n\t\tfields: [${relation.tableFrom}.${relation.columnFrom}],\n\t\treferences: [${relation.tableTo}.${relation.columnTo}]${
+ relation.relationName
+ ? `,\n\t\trelationName: "${relation.relationName}"`
+ : ''
+ }\n\t}),`;
+ } else {
+ return `\t${relation.name}: many(${relation.tableTo}${
+ relation.relationName
+ ? `, {\n\t\trelationName: "${relation.relationName}"\n\t}`
+ : ''
+ }),`;
+ }
+ });
+
+ return `export const ${table}Relations = relations(${table}, ({${hasOne ? 'one' : ''}${
+ hasOne && hasMany ? ', ' : ''
+ }${hasMany ? 'many' : ''}}) => ({\n${fields.join('\n')}\n}));`;
+ },
+ );
+
+ return {
+ file: importsTs + relationStatements.join('\n\n'),
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/migrate.ts b/drizzle-kit/src/cli/commands/migrate.ts
new file mode 100644
index 000000000..726c8ed4b
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/migrate.ts
@@ -0,0 +1,999 @@
+import fs from 'fs';
+import {
+ prepareMySqlDbPushSnapshot,
+ prepareMySqlMigrationSnapshot,
+ preparePgDbPushSnapshot,
+ preparePgMigrationSnapshot,
+ prepareSingleStoreDbPushSnapshot,
+ prepareSingleStoreMigrationSnapshot,
+ prepareSQLiteDbPushSnapshot,
+ prepareSqliteMigrationSnapshot,
+} from '../../migrationPreparator';
+
+import chalk from 'chalk';
+import { render } from 'hanji';
+import path, { join } from 'path';
+import { SingleStoreSchema, singlestoreSchema, squashSingleStoreScheme } from 'src/serializer/singlestoreSchema';
+import { TypeOf } from 'zod';
+import type { CommonSchema } from '../../schemaValidator';
+import { MySqlSchema, mysqlSchema, squashMysqlScheme } from '../../serializer/mysqlSchema';
+import { PgSchema, pgSchema, squashPgScheme } from '../../serializer/pgSchema';
+import { SQLiteSchema, sqliteSchema, squashSqliteScheme } from '../../serializer/sqliteSchema';
+import {
+ applyMysqlSnapshotsDiff,
+ applyPgSnapshotsDiff,
+ applySingleStoreSnapshotsDiff,
+ applySqliteSnapshotsDiff,
+ Column,
+ ColumnsResolverInput,
+ ColumnsResolverOutput,
+ Enum,
+ ResolverInput,
+ ResolverOutput,
+ ResolverOutputWithMoved,
+ Sequence,
+ Table,
+} from '../../snapshotsDiffer';
+import { assertV1OutFolder, Journal, prepareMigrationFolder } from '../../utils';
+import { prepareMigrationMetadata } from '../../utils/words';
+import { Prefix } from '../validations/common';
+import { withStyle } from '../validations/outputs';
+import {
+ isRenamePromptItem,
+ RenamePropmtItem,
+ ResolveColumnSelect,
+ ResolveSchemasSelect,
+ ResolveSelect,
+ schema,
+} from '../views';
+import { GenerateConfig } from './utils';
+
+export type Named = {
+ name: string;
+};
+
+export type NamedWithSchema = {
+ name: string;
+ schema: string;
+};
+
+export const schemasResolver = async (
+ input: ResolverInput,
+): Promise> => {
+ try {
+ const { created, deleted, renamed } = await promptSchemasConflict(
+ input.created,
+ input.deleted,
+ );
+
+ return { created: created, deleted: deleted, renamed: renamed };
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+};
+
+export const tablesResolver = async (
+ input: ResolverInput,
+): Promise> => {
+ try {
+ const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
+ input.created,
+ input.deleted,
+ 'table',
+ );
+
+ return {
+ created: created,
+ deleted: deleted,
+ moved: moved,
+ renamed: renamed,
+ };
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+};
+
+export const sequencesResolver = async (
+ input: ResolverInput,
+): Promise> => {
+ try {
+ const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
+ input.created,
+ input.deleted,
+ 'sequence',
+ );
+
+ return {
+ created: created,
+ deleted: deleted,
+ moved: moved,
+ renamed: renamed,
+ };
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+};
+
+export const enumsResolver = async (
+ input: ResolverInput,
+): Promise> => {
+ try {
+ const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
+ input.created,
+ input.deleted,
+ 'enum',
+ );
+
+ return {
+ created: created,
+ deleted: deleted,
+ moved: moved,
+ renamed: renamed,
+ };
+ } catch (e) {
+ console.error(e);
+ throw e;
+ }
+};
+
+export const columnsResolver = async (
+ input: ColumnsResolverInput,
+): Promise> => {
+ const result = await promptColumnsConflicts(
+ input.tableName,
+ input.created,
+ input.deleted,
+ );
+ return {
+ tableName: input.tableName,
+ schema: input.schema,
+ created: result.created,
+ deleted: result.deleted,
+ renamed: result.renamed,
+ };
+};
+
+export const prepareAndMigratePg = async (config: GenerateConfig) => {
+ const outFolder = config.out;
+ const schemaPath = config.schema;
+
+ try {
+ assertV1OutFolder(outFolder);
+
+ const { snapshots, journal } = prepareMigrationFolder(
+ outFolder,
+ 'postgresql',
+ );
+
+ const { prev, cur, custom } = await preparePgMigrationSnapshot(
+ snapshots,
+ schemaPath,
+ );
+
+ const validatedPrev = pgSchema.parse(prev);
+ const validatedCur = pgSchema.parse(cur);
+
+ if (config.custom) {
+ writeResult({
+ cur: custom,
+ sqlStatements: [],
+ journal,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ type: 'custom',
+ prefixMode: config.prefix,
+ });
+ return;
+ }
+
+ const squashedPrev = squashPgScheme(validatedPrev);
+ const squashedCur = squashPgScheme(validatedCur);
+
+ const { sqlStatements, _meta } = await applyPgSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ schemasResolver,
+ enumsResolver,
+ sequencesResolver,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ writeResult({
+ cur,
+ sqlStatements,
+ journal,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ prefixMode: config.prefix,
+ });
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+export const preparePgPush = async (
+ schemaPath: string | string[],
+ snapshot: PgSchema,
+ schemaFilter: string[],
+) => {
+ const { prev, cur } = await preparePgDbPushSnapshot(
+ snapshot,
+ schemaPath,
+ schemaFilter,
+ );
+
+ const validatedPrev = pgSchema.parse(prev);
+ const validatedCur = pgSchema.parse(cur);
+
+ const squashedPrev = squashPgScheme(validatedPrev, 'push');
+ const squashedCur = squashPgScheme(validatedCur, 'push');
+
+ const { sqlStatements, statements, _meta } = await applyPgSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ schemasResolver,
+ enumsResolver,
+ sequencesResolver,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ return { sqlStatements, statements, squashedPrev, squashedCur };
+};
+
+// Not needed for now
+function mysqlSchemaSuggestions(
+ curSchema: TypeOf,
+ prevSchema: TypeOf,
+) {
+ const suggestions: string[] = [];
+ const usedSuggestions: string[] = [];
+ const suggestionTypes = {
+ serial: withStyle.errorWarning(
+ `We deprecated the use of 'serial' for MySQL starting from version 0.20.0. In MySQL, 'serial' is simply an alias for 'bigint unsigned not null auto_increment unique,' which creates all constraints and indexes for you. This may make the process less explicit for both users and drizzle-kit push commands`,
+ ),
+ };
+
+ for (const table of Object.values(curSchema.tables)) {
+ for (const column of Object.values(table.columns)) {
+ if (column.type === 'serial') {
+ if (!usedSuggestions.includes('serial')) {
+ suggestions.push(suggestionTypes['serial']);
+ }
+
+ const uniqueForSerial = Object.values(
+ prevSchema.tables[table.name].uniqueConstraints,
+ ).find((it) => it.columns[0] === column.name);
+
+ suggestions.push(
+ `\n`
+ + withStyle.suggestion(
+ `We are suggesting to change ${
+ chalk.blue(
+ column.name,
+ )
+ } column in ${
+ chalk.blueBright(
+ table.name,
+ )
+ } table from serial to bigint unsigned\n\n${
+ chalk.blueBright(
+ `bigint("${column.name}", { mode: "number", unsigned: true }).notNull().autoincrement().unique(${
+ uniqueForSerial?.name ? `"${uniqueForSerial?.name}"` : ''
+ })`,
+ )
+ }`,
+ ),
+ );
+ }
+ }
+ }
+
+ return suggestions;
+}
+
+// Intersect with prepareAnMigrate
+export const prepareMySQLPush = async (
+ schemaPath: string | string[],
+ snapshot: MySqlSchema,
+) => {
+ try {
+ const { prev, cur } = await prepareMySqlDbPushSnapshot(
+ snapshot,
+ schemaPath,
+ );
+
+ const validatedPrev = mysqlSchema.parse(prev);
+ const validatedCur = mysqlSchema.parse(cur);
+
+ const squashedPrev = squashMysqlScheme(validatedPrev);
+ const squashedCur = squashMysqlScheme(validatedCur);
+
+ const { sqlStatements, statements } = await applyMysqlSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ return { sqlStatements, statements, validatedCur, validatedPrev };
+ } catch (e) {
+ console.error(e);
+ process.exit(1);
+ }
+};
+
+export const prepareAndMigrateMysql = async (config: GenerateConfig) => {
+ const outFolder = config.out;
+ const schemaPath = config.schema;
+
+ try {
+ // TODO: remove
+ assertV1OutFolder(outFolder);
+
+ const { snapshots, journal } = prepareMigrationFolder(outFolder, 'mysql');
+ const { prev, cur, custom } = await prepareMySqlMigrationSnapshot(
+ snapshots,
+ schemaPath,
+ );
+
+ const validatedPrev = mysqlSchema.parse(prev);
+ const validatedCur = mysqlSchema.parse(cur);
+
+ if (config.custom) {
+ writeResult({
+ cur: custom,
+ sqlStatements: [],
+ journal,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ type: 'custom',
+ prefixMode: config.prefix,
+ });
+ return;
+ }
+
+ const squashedPrev = squashMysqlScheme(validatedPrev);
+ const squashedCur = squashMysqlScheme(validatedCur);
+
+ const { sqlStatements, statements, _meta } = await applyMysqlSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ writeResult({
+ cur,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ prefixMode: config.prefix,
+ });
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+// Not needed for now
+function singleStoreSchemaSuggestions(
+ curSchema: TypeOf,
+ prevSchema: TypeOf,
+) {
+ const suggestions: string[] = [];
+ const usedSuggestions: string[] = [];
+ const suggestionTypes = {
+ // TODO: Check if SingleStore has serial type
+ serial: withStyle.errorWarning(
+ `We deprecated the use of 'serial' for SingleStore starting from version 0.20.0. In SingleStore, 'serial' is simply an alias for 'bigint unsigned not null auto_increment unique,' which creates all constraints and indexes for you. This may make the process less explicit for both users and drizzle-kit push commands`,
+ ),
+ };
+
+ for (const table of Object.values(curSchema.tables)) {
+ for (const column of Object.values(table.columns)) {
+ if (column.type === 'serial') {
+ if (!usedSuggestions.includes('serial')) {
+ suggestions.push(suggestionTypes['serial']);
+ }
+
+ const uniqueForSerial = Object.values(
+ prevSchema.tables[table.name].uniqueConstraints,
+ ).find((it) => it.columns[0] === column.name);
+
+ suggestions.push(
+ `\n`
+ + withStyle.suggestion(
+ `We are suggesting to change ${
+ chalk.blue(
+ column.name,
+ )
+ } column in ${
+ chalk.blueBright(
+ table.name,
+ )
+ } table from serial to bigint unsigned\n\n${
+ chalk.blueBright(
+ `bigint("${column.name}", { mode: "number", unsigned: true }).notNull().autoincrement().unique(${
+ uniqueForSerial?.name ? `"${uniqueForSerial?.name}"` : ''
+ })`,
+ )
+ }`,
+ ),
+ );
+ }
+ }
+ }
+
+ return suggestions;
+}
+
+// Intersect with prepareAnMigrate
+export const prepareSingleStorePush = async (
+ schemaPath: string | string[],
+ snapshot: SingleStoreSchema,
+) => {
+ try {
+ const { prev, cur } = await prepareSingleStoreDbPushSnapshot(
+ snapshot,
+ schemaPath,
+ );
+
+ const validatedPrev = singlestoreSchema.parse(prev);
+ const validatedCur = singlestoreSchema.parse(cur);
+
+ const squashedPrev = squashSingleStoreScheme(validatedPrev);
+ const squashedCur = squashSingleStoreScheme(validatedCur);
+
+ const { sqlStatements, statements } = await applySingleStoreSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ return { sqlStatements, statements, validatedCur, validatedPrev };
+ } catch (e) {
+ console.error(e);
+ process.exit(1);
+ }
+};
+
+export const prepareAndMigrateSingleStore = async (config: GenerateConfig) => {
+ const outFolder = config.out;
+ const schemaPath = config.schema;
+
+ try {
+ // TODO: remove
+ assertV1OutFolder(outFolder);
+
+ const { snapshots, journal } = prepareMigrationFolder(outFolder, 'singlestore');
+ const { prev, cur, custom } = await prepareSingleStoreMigrationSnapshot(
+ snapshots,
+ schemaPath,
+ );
+
+ const validatedPrev = singlestoreSchema.parse(prev);
+ const validatedCur = singlestoreSchema.parse(cur);
+
+ if (config.custom) {
+ writeResult({
+ cur: custom,
+ sqlStatements: [],
+ journal,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ type: 'custom',
+ prefixMode: config.prefix,
+ });
+ return;
+ }
+
+ const squashedPrev = squashSingleStoreScheme(validatedPrev);
+ const squashedCur = squashSingleStoreScheme(validatedCur);
+
+ const { sqlStatements, statements, _meta } = await applySingleStoreSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ writeResult({
+ cur,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ prefixMode: config.prefix,
+ });
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+export const prepareAndMigrateSqlite = async (config: GenerateConfig) => {
+ const outFolder = config.out;
+ const schemaPath = config.schema;
+
+ try {
+ assertV1OutFolder(outFolder);
+
+ const { snapshots, journal } = prepareMigrationFolder(outFolder, 'sqlite');
+ const { prev, cur, custom } = await prepareSqliteMigrationSnapshot(
+ snapshots,
+ schemaPath,
+ );
+
+ const validatedPrev = sqliteSchema.parse(prev);
+ const validatedCur = sqliteSchema.parse(cur);
+
+ if (config.custom) {
+ writeResult({
+ cur: custom,
+ sqlStatements: [],
+ journal,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ bundle: config.bundle,
+ type: 'custom',
+ prefixMode: config.prefix,
+ });
+ return;
+ }
+
+ const squashedPrev = squashSqliteScheme(validatedPrev);
+ const squashedCur = squashSqliteScheme(validatedCur);
+
+ const { sqlStatements, _meta } = await applySqliteSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ );
+
+ writeResult({
+ cur,
+ sqlStatements,
+ journal,
+ _meta,
+ outFolder,
+ name: config.name,
+ breakpoints: config.breakpoints,
+ bundle: config.bundle,
+ prefixMode: config.prefix,
+ });
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+export const prepareSQLitePush = async (
+ schemaPath: string | string[],
+ snapshot: SQLiteSchema,
+) => {
+ const { prev, cur } = await prepareSQLiteDbPushSnapshot(snapshot, schemaPath);
+
+ const validatedPrev = sqliteSchema.parse(prev);
+ const validatedCur = sqliteSchema.parse(cur);
+
+ const squashedPrev = squashSqliteScheme(validatedPrev, 'push');
+ const squashedCur = squashSqliteScheme(validatedCur, 'push');
+
+ const { sqlStatements, statements, _meta } = await applySqliteSnapshotsDiff(
+ squashedPrev,
+ squashedCur,
+ tablesResolver,
+ columnsResolver,
+ validatedPrev,
+ validatedCur,
+ 'push',
+ );
+
+ return {
+ sqlStatements,
+ statements,
+ squashedPrev,
+ squashedCur,
+ meta: _meta,
+ };
+};
+
+const freeeeeeze = (obj: any) => {
+ Object.freeze(obj);
+ for (let key in obj) {
+ if (obj.hasOwnProperty(key) && typeof obj[key] === 'object') {
+ freeeeeeze(obj[key]);
+ }
+ }
+};
+
+export const promptColumnsConflicts = async (
+ tableName: string,
+ newColumns: T[],
+ missingColumns: T[],
+) => {
+ if (newColumns.length === 0 || missingColumns.length === 0) {
+ return { created: newColumns, renamed: [], deleted: missingColumns };
+ }
+ const result: { created: T[]; renamed: { from: T; to: T }[]; deleted: T[] } = {
+ created: [],
+ renamed: [],
+ deleted: [],
+ };
+
+ let index = 0;
+ let leftMissing = [...missingColumns];
+
+ do {
+ const created = newColumns[index];
+
+ const renames: RenamePropmtItem[] = leftMissing.map((it) => {
+ return { from: it, to: created };
+ });
+
+ const promptData: (RenamePropmtItem | T)[] = [created, ...renames];
+
+ const { status, data } = await render(
+ new ResolveColumnSelect(tableName, created, promptData),
+ );
+ if (status === 'aborted') {
+ console.error('ERROR');
+ process.exit(1);
+ }
+
+ if (isRenamePromptItem(data)) {
+ console.log(
+ `${chalk.yellow('~')} ${data.from.name} › ${data.to.name} ${
+ chalk.gray(
+ 'column will be renamed',
+ )
+ }`,
+ );
+ result.renamed.push(data);
+ // this will make [item1, undefined, item2]
+ delete leftMissing[leftMissing.indexOf(data.from)];
+ // this will make [item1, item2]
+ leftMissing = leftMissing.filter(Boolean);
+ } else {
+ console.log(
+ `${chalk.green('+')} ${data.name} ${
+ chalk.gray(
+ 'column will be created',
+ )
+ }`,
+ );
+ result.created.push(created);
+ }
+ index += 1;
+ } while (index < newColumns.length);
+ console.log(
+ chalk.gray(`--- all columns conflicts in ${tableName} table resolved ---\n`),
+ );
+
+ result.deleted.push(...leftMissing);
+ return result;
+};
+
+export const promptNamedWithSchemasConflict = async (
+ newItems: T[],
+ missingItems: T[],
+ entity: 'table' | 'enum' | 'sequence',
+): Promise<{
+ created: T[];
+ renamed: { from: T; to: T }[];
+ moved: { name: string; schemaFrom: string; schemaTo: string }[];
+ deleted: T[];
+}> => {
+ if (missingItems.length === 0 || newItems.length === 0) {
+ return {
+ created: newItems,
+ renamed: [],
+ moved: [],
+ deleted: missingItems,
+ };
+ }
+
+ const result: {
+ created: T[];
+ renamed: { from: T; to: T }[];
+ moved: { name: string; schemaFrom: string; schemaTo: string }[];
+ deleted: T[];
+ } = { created: [], renamed: [], moved: [], deleted: [] };
+ let index = 0;
+ let leftMissing = [...missingItems];
+ do {
+ const created = newItems[index];
+ const renames: RenamePropmtItem[] = leftMissing.map((it) => {
+ return { from: it, to: created };
+ });
+
+ const promptData: (RenamePropmtItem | T)[] = [created, ...renames];
+
+ const { status, data } = await render(
+ new ResolveSelect(created, promptData, entity),
+ );
+ if (status === 'aborted') {
+ console.error('ERROR');
+ process.exit(1);
+ }
+
+ if (isRenamePromptItem(data)) {
+ const schemaFromPrefix = !data.from.schema || data.from.schema === 'public'
+ ? ''
+ : `${data.from.schema}.`;
+ const schemaToPrefix = !data.to.schema || data.to.schema === 'public'
+ ? ''
+ : `${data.to.schema}.`;
+
+ console.log(
+ `${chalk.yellow('~')} ${schemaFromPrefix}${data.from.name} › ${schemaToPrefix}${data.to.name} ${
+ chalk.gray(
+ `${entity} will be renamed/moved`,
+ )
+ }`,
+ );
+
+ if (data.from.name !== data.to.name) {
+ result.renamed.push(data);
+ }
+
+ if (data.from.schema !== data.to.schema) {
+ result.moved.push({
+ name: data.from.name,
+ schemaFrom: data.from.schema || 'public',
+ schemaTo: data.to.schema || 'public',
+ });
+ }
+
+ delete leftMissing[leftMissing.indexOf(data.from)];
+ leftMissing = leftMissing.filter(Boolean);
+ } else {
+ console.log(
+ `${chalk.green('+')} ${data.name} ${
+ chalk.gray(
+ `${entity} will be created`,
+ )
+ }`,
+ );
+ result.created.push(created);
+ }
+ index += 1;
+ } while (index < newItems.length);
+ console.log(chalk.gray(`--- all ${entity} conflicts resolved ---\n`));
+ result.deleted.push(...leftMissing);
+ return result;
+};
+
+export const promptSchemasConflict = async (
+ newSchemas: T[],
+ missingSchemas: T[],
+): Promise<{ created: T[]; renamed: { from: T; to: T }[]; deleted: T[] }> => {
+ if (missingSchemas.length === 0 || newSchemas.length === 0) {
+ return { created: newSchemas, renamed: [], deleted: missingSchemas };
+ }
+
+ const result: { created: T[]; renamed: { from: T; to: T }[]; deleted: T[] } = {
+ created: [],
+ renamed: [],
+ deleted: [],
+ };
+ let index = 0;
+ let leftMissing = [...missingSchemas];
+ do {
+ const created = newSchemas[index];
+ const renames: RenamePropmtItem[] = leftMissing.map((it) => {
+ return { from: it, to: created };
+ });
+
+ const promptData: (RenamePropmtItem | T)[] = [created, ...renames];
+
+ const { status, data } = await render(
+ new ResolveSchemasSelect(created, promptData),
+ );
+ if (status === 'aborted') {
+ console.error('ERROR');
+ process.exit(1);
+ }
+
+ if (isRenamePromptItem(data)) {
+ console.log(
+ `${chalk.yellow('~')} ${data.from.name} › ${data.to.name} ${
+ chalk.gray(
+ 'schema will be renamed',
+ )
+ }`,
+ );
+ result.renamed.push(data);
+ delete leftMissing[leftMissing.indexOf(data.from)];
+ leftMissing = leftMissing.filter(Boolean);
+ } else {
+ console.log(
+ `${chalk.green('+')} ${data.name} ${
+ chalk.gray(
+ 'schema will be created',
+ )
+ }`,
+ );
+ result.created.push(created);
+ }
+ index += 1;
+ } while (index < newSchemas.length);
+ console.log(chalk.gray('--- all schemas conflicts resolved ---\n'));
+ result.deleted.push(...leftMissing);
+ return result;
+};
+
+export const BREAKPOINT = '--> statement-breakpoint\n';
+
+export const writeResult = ({
+ cur,
+ sqlStatements,
+ journal,
+ _meta = {
+ columns: {},
+ schemas: {},
+ tables: {},
+ },
+ outFolder,
+ breakpoints,
+ name,
+ bundle = false,
+ type = 'none',
+ prefixMode,
+}: {
+ cur: CommonSchema;
+ sqlStatements: string[];
+ journal: Journal;
+ _meta?: any;
+ outFolder: string;
+ breakpoints: boolean;
+ prefixMode: Prefix;
+ name?: string;
+ bundle?: boolean;
+ type?: 'introspect' | 'custom' | 'none';
+}) => {
+ if (type === 'none') {
+ console.log(schema(cur));
+
+ if (sqlStatements.length === 0) {
+ console.log('No schema changes, nothing to migrate 😴');
+ return;
+ }
+ }
+
+ // append entry to _migrations.json
+ // append entry to _journal.json->entries
+ // dialect in _journal.json
+ // append sql file to out folder
+ // append snapshot file to meta folder
+ const lastEntryInJournal = journal.entries[journal.entries.length - 1];
+ const idx = typeof lastEntryInJournal === 'undefined' ? 0 : lastEntryInJournal.idx + 1;
+
+ const { prefix, tag } = prepareMigrationMetadata(idx, prefixMode, name);
+
+ const toSave = JSON.parse(JSON.stringify(cur));
+ toSave['_meta'] = _meta;
+
+ // todo: save results to a new migration folder
+ const metaFolderPath = join(outFolder, 'meta');
+ const metaJournal = join(metaFolderPath, '_journal.json');
+
+ fs.writeFileSync(
+ join(metaFolderPath, `${prefix}_snapshot.json`),
+ JSON.stringify(toSave, null, 2),
+ );
+
+ const sqlDelimiter = breakpoints ? BREAKPOINT : '\n';
+ let sql = sqlStatements.join(sqlDelimiter);
+
+ if (type === 'introspect') {
+ sql =
+ `-- Current sql file was generated after introspecting the database\n-- If you want to run this migration please uncomment this code before executing migrations\n/*\n${sql}\n*/`;
+ }
+
+ if (type === 'custom') {
+ console.log('Prepared empty file for your custom SQL migration!');
+ sql = '-- Custom SQL migration file, put you code below! --';
+ }
+
+ journal.entries.push({
+ idx,
+ version: cur.version,
+ when: +new Date(),
+ tag,
+ breakpoints: breakpoints,
+ });
+
+ fs.writeFileSync(metaJournal, JSON.stringify(journal, null, 2));
+
+ fs.writeFileSync(`${outFolder}/${tag}.sql`, sql);
+
+ // js file with .sql imports for React Native / Expo
+ if (bundle) {
+ const js = embeddedMigrations(journal);
+ fs.writeFileSync(`${outFolder}/migrations.js`, js);
+ }
+
+ render(
+ `[${
+ chalk.green(
+ '✓',
+ )
+ }] Your SQL migration file ➜ ${
+ chalk.bold.underline.blue(
+ path.join(`${outFolder}/${tag}.sql`),
+ )
+ } 🚀`,
+ );
+};
+
+export const embeddedMigrations = (journal: Journal) => {
+ let content =
+ '// This file is required for Expo/React Native SQLite migrations - https://orm.drizzle.team/quick-sqlite/expo\n\n';
+ content += "import journal from './meta/_journal.json';\n";
+ journal.entries.forEach((entry) => {
+ content += `import m${entry.idx.toString().padStart(4, '0')} from './${entry.tag}.sql';\n`;
+ });
+
+ content += `
+ export default {
+ journal,
+ migrations: {
+ ${
+ journal.entries
+ .map((it) => `m${it.idx.toString().padStart(4, '0')}`)
+ .join(',\n')
+ }
+ }
+ }
+ `;
+ return content;
+};
+
+export const prepareSnapshotFolderName = () => {
+ const now = new Date();
+ return `${now.getFullYear()}${two(now.getUTCMonth() + 1)}${
+ two(
+ now.getUTCDate(),
+ )
+ }${two(now.getUTCHours())}${two(now.getUTCMinutes())}${
+ two(
+ now.getUTCSeconds(),
+ )
+ }`;
+};
+
+const two = (input: number): string => {
+ return input.toString().padStart(2, '0');
+};
diff --git a/drizzle-kit/src/cli/commands/mysqlIntrospect.ts b/drizzle-kit/src/cli/commands/mysqlIntrospect.ts
new file mode 100644
index 000000000..f0132be64
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/mysqlIntrospect.ts
@@ -0,0 +1,53 @@
+import { renderWithTask } from 'hanji';
+import { Minimatch } from 'minimatch';
+import { originUUID } from '../../global';
+import type { MySqlSchema } from '../../serializer/mysqlSchema';
+import { fromDatabase } from '../../serializer/mysqlSerializer';
+import type { DB } from '../../utils';
+import { ProgressView } from '../views';
+
+export const mysqlPushIntrospect = async (
+ db: DB,
+ databaseName: string,
+ filters: string[],
+) => {
+ const matchers = filters.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new ProgressView(
+ 'Pulling schema from database...',
+ 'Pulling schema from database...',
+ );
+ const res = await renderWithTask(
+ progress,
+ fromDatabase(db, databaseName, filter),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as MySqlSchema;
+ const { internal, ...schemaWithoutInternals } = schema;
+ return { schema: schemaWithoutInternals };
+};
diff --git a/drizzle-kit/src/cli/commands/mysqlPushUtils.ts b/drizzle-kit/src/cli/commands/mysqlPushUtils.ts
new file mode 100644
index 000000000..db1134e63
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/mysqlPushUtils.ts
@@ -0,0 +1,352 @@
+import chalk from 'chalk';
+import { render } from 'hanji';
+import { TypeOf } from 'zod';
+import { JsonAlterColumnTypeStatement, JsonStatement } from '../../jsonStatements';
+import { mysqlSchema, MySqlSquasher } from '../../serializer/mysqlSchema';
+import type { DB } from '../../utils';
+import { Select } from '../selector-ui';
+import { withStyle } from '../validations/outputs';
+
+export const filterStatements = (
+ statements: JsonStatement[],
+ currentSchema: TypeOf,
+ prevSchema: TypeOf,
+) => {
+ return statements.filter((statement) => {
+ if (statement.type === 'alter_table_alter_column_set_type') {
+ // Don't need to handle it on migrations step and introspection
+ // but for both it should be skipped
+ if (
+ statement.oldDataType.startsWith('tinyint')
+ && statement.newDataType.startsWith('boolean')
+ ) {
+ return false;
+ }
+
+ if (
+ statement.oldDataType.startsWith('bigint unsigned')
+ && statement.newDataType.startsWith('serial')
+ ) {
+ return false;
+ }
+
+ if (
+ statement.oldDataType.startsWith('serial')
+ && statement.newDataType.startsWith('bigint unsigned')
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'alter_table_alter_column_set_default') {
+ if (
+ statement.newDefaultValue === false
+ && statement.oldDefaultValue === 0
+ && statement.newDataType === 'boolean'
+ ) {
+ return false;
+ }
+ if (
+ statement.newDefaultValue === true
+ && statement.oldDefaultValue === 1
+ && statement.newDataType === 'boolean'
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'delete_unique_constraint') {
+ const unsquashed = MySqlSquasher.unsquashUnique(statement.data);
+ // only if constraint was removed from a serial column, than treat it as removed
+ // const serialStatement = statements.find(
+ // (it) => it.type === "alter_table_alter_column_set_type"
+ // ) as JsonAlterColumnTypeStatement;
+ // if (
+ // serialStatement?.oldDataType.startsWith("bigint unsigned") &&
+ // serialStatement?.newDataType.startsWith("serial") &&
+ // serialStatement.columnName ===
+ // MySqlSquasher.unsquashUnique(statement.data).columns[0]
+ // ) {
+ // return false;
+ // }
+ // Check if uniqueindex was only on this column, that is serial
+
+ // if now serial and was not serial and was unique index
+ if (
+ unsquashed.columns.length === 1
+ && currentSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .type === 'serial'
+ && prevSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .type === 'serial'
+ && currentSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .name === unsquashed.columns[0]
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_notnull') {
+ // only if constraint was removed from a serial column, than treat it as removed
+ const serialStatement = statements.find(
+ (it) => it.type === 'alter_table_alter_column_set_type',
+ ) as JsonAlterColumnTypeStatement;
+ if (
+ serialStatement?.oldDataType.startsWith('bigint unsigned')
+ && serialStatement?.newDataType.startsWith('serial')
+ && serialStatement.columnName === statement.columnName
+ && serialStatement.tableName === statement.tableName
+ ) {
+ return false;
+ }
+ if (statement.newDataType === 'serial' && !statement.columnNotNull) {
+ return false;
+ }
+ if (statement.columnAutoIncrement) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+};
+
+export const logSuggestionsAndReturn = async (
+ db: DB,
+ statements: JsonStatement[],
+ json2: TypeOf,
+) => {
+ let shouldAskForApprove = false;
+ const statementsToExecute: string[] = [];
+ const infoToPrint: string[] = [];
+
+ const tablesToRemove: string[] = [];
+ const columnsToRemove: string[] = [];
+ const schemasToRemove: string[] = [];
+ const tablesToTruncate: string[] = [];
+
+ for (const statement of statements) {
+ if (statement.type === 'drop_table') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table with ${count} items`,
+ );
+ tablesToRemove.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_drop_column') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column in ${statement.tableName} table with ${count} items`,
+ );
+ columnsToRemove.push(`${statement.tableName}_${statement.columnName}`);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'drop_schema') {
+ const res = await db.query(
+ `select count(*) as count from information_schema.tables where table_schema = \`${statement.name}\`;`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.name,
+ )
+ } schema with ${count} tables`,
+ );
+ schemasToRemove.push(statement.name);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_set_type') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column type from ${
+ chalk.underline(
+ statement.oldDataType,
+ )
+ } to ${chalk.underline(statement.newDataType)} with ${count} items`,
+ );
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_default') {
+ if (statement.columnNotNull) {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to remove default value from ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } not-null column with ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ // shouldAskForApprove = true;
+ } else if (statement.type === 'alter_table_alter_column_set_notnull') {
+ if (typeof statement.columnDefault === 'undefined') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to set not-null constraint to ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column without default, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_pk') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ // if drop pk and json2 has autoincrement in table -> exit process with error
+ if (
+ Object.values(json2.tables[statement.tableName].columns).filter(
+ (column) => column.autoincrement,
+ ).length > 0
+ ) {
+ console.log(
+ `${
+ withStyle.errorWarning(
+ `You have removed the primary key from a ${statement.tableName} table without removing the auto-increment property from this table. As the database error states: 'there can be only one auto column, and it must be defined as a key. Make sure to remove autoincrement from ${statement.tableName} table`,
+ )
+ }`,
+ );
+ process.exit(1);
+ }
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } primary key. This statements may fail and you table may left without primary key`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'delete_composite_pk') {
+ // if drop pk and json2 has autoincrement in table -> exit process with error
+ if (
+ Object.values(json2.tables[statement.tableName].columns).filter(
+ (column) => column.autoincrement,
+ ).length > 0
+ ) {
+ console.log(
+ `${
+ withStyle.errorWarning(
+ `You have removed the primary key from a ${statement.tableName} table without removing the auto-increment property from this table. As the database error states: 'there can be only one auto column, and it must be defined as a key. Make sure to remove autoincrement from ${statement.tableName} table`,
+ )
+ }`,
+ );
+ process.exit(1);
+ }
+ } else if (statement.type === 'alter_table_add_column') {
+ if (
+ statement.column.notNull
+ && typeof statement.column.default === 'undefined'
+ ) {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to add not-null ${
+ chalk.underline(
+ statement.column.name,
+ )
+ } column without default value, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ } else if (statement.type === 'create_unique_constraint') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ const unsquashedUnique = MySqlSquasher.unsquashUnique(statement.data);
+ console.log(
+ `· You're about to add ${
+ chalk.underline(
+ unsquashedUnique.name,
+ )
+ } unique constraint to the table, which contains ${count} items. If this statement fails, you will receive an error from the database. Do you want to truncate ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table?\n`,
+ );
+ const { status, data } = await render(
+ new Select([
+ 'No, add the constraint without truncating the table',
+ `Yes, truncate the table`,
+ ]),
+ );
+ if (data?.index === 1) {
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+ shouldAskForApprove = true;
+ }
+ }
+ }
+ }
+
+ return {
+ statementsToExecute,
+ shouldAskForApprove,
+ infoToPrint,
+ columnsToRemove: [...new Set(columnsToRemove)],
+ schemasToRemove: [...new Set(schemasToRemove)],
+ tablesToTruncate: [...new Set(tablesToTruncate)],
+ tablesToRemove: [...new Set(tablesToRemove)],
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/mysqlUp.ts b/drizzle-kit/src/cli/commands/mysqlUp.ts
new file mode 100644
index 000000000..6c7d2ebe5
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/mysqlUp.ts
@@ -0,0 +1,101 @@
+import chalk from 'chalk';
+import fs, { writeFileSync } from 'fs';
+import path from 'path';
+import { Column, MySqlSchema, MySqlSchemaV4, MySqlSchemaV5, mysqlSchemaV5, Table } from '../../serializer/mysqlSchema';
+import { prepareOutFolder, validateWithReport } from '../../utils';
+
+export const upMysqlHandler = (out: string) => {};
+
+export const upMySqlHandlerV4toV5 = (obj: MySqlSchemaV4): MySqlSchemaV5 => {
+ const mappedTables: Record = {};
+
+ for (const [key, table] of Object.entries(obj.tables)) {
+ const mappedColumns: Record = {};
+ for (const [ckey, column] of Object.entries(table.columns)) {
+ let newDefault: any = column.default;
+ let newType: string = column.type;
+ let newAutoIncrement: boolean | undefined = column.autoincrement;
+
+ if (column.type.toLowerCase().startsWith('datetime')) {
+ if (typeof column.default !== 'undefined') {
+ if (column.default.startsWith("'") && column.default.endsWith("'")) {
+ newDefault = `'${
+ column.default
+ .substring(1, column.default.length - 1)
+ .replace('T', ' ')
+ .slice(0, 23)
+ }'`;
+ } else {
+ newDefault = column.default.replace('T', ' ').slice(0, 23);
+ }
+ }
+
+ newType = column.type.toLowerCase().replace('datetime (', 'datetime(');
+ } else if (column.type.toLowerCase() === 'date') {
+ if (typeof column.default !== 'undefined') {
+ if (column.default.startsWith("'") && column.default.endsWith("'")) {
+ newDefault = `'${
+ column.default
+ .substring(1, column.default.length - 1)
+ .split('T')[0]
+ }'`;
+ } else {
+ newDefault = column.default.split('T')[0];
+ }
+ }
+ newType = column.type.toLowerCase().replace('date (', 'date(');
+ } else if (column.type.toLowerCase().startsWith('timestamp')) {
+ if (typeof column.default !== 'undefined') {
+ if (column.default.startsWith("'") && column.default.endsWith("'")) {
+ newDefault = `'${
+ column.default
+ .substring(1, column.default.length - 1)
+ .replace('T', ' ')
+ .slice(0, 23)
+ }'`;
+ } else {
+ newDefault = column.default.replace('T', ' ').slice(0, 23);
+ }
+ }
+ newType = column.type
+ .toLowerCase()
+ .replace('timestamp (', 'timestamp(');
+ } else if (column.type.toLowerCase().startsWith('time')) {
+ newType = column.type.toLowerCase().replace('time (', 'time(');
+ } else if (column.type.toLowerCase().startsWith('decimal')) {
+ newType = column.type.toLowerCase().replace(', ', ',');
+ } else if (column.type.toLowerCase().startsWith('enum')) {
+ newType = column.type.toLowerCase();
+ } else if (column.type.toLowerCase().startsWith('serial')) {
+ newAutoIncrement = true;
+ }
+ mappedColumns[ckey] = {
+ ...column,
+ default: newDefault,
+ type: newType,
+ autoincrement: newAutoIncrement,
+ };
+ }
+
+ mappedTables[key] = {
+ ...table,
+ columns: mappedColumns,
+ compositePrimaryKeys: {},
+ uniqueConstraints: {},
+ };
+ }
+
+ return {
+ version: '5',
+ dialect: obj.dialect,
+ id: obj.id,
+ prevId: obj.prevId,
+ tables: mappedTables,
+ schemas: obj.schemas,
+ _meta: {
+ schemas: {} as Record,
+ tables: {} as Record,
+ columns: {} as Record,
+ },
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/pgIntrospect.ts b/drizzle-kit/src/cli/commands/pgIntrospect.ts
new file mode 100644
index 000000000..dbd3ba238
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/pgIntrospect.ts
@@ -0,0 +1,52 @@
+import { renderWithTask } from 'hanji';
+import { Minimatch } from 'minimatch';
+import { originUUID } from '../../global';
+import type { PgSchema } from '../../serializer/pgSchema';
+import { fromDatabase } from '../../serializer/pgSerializer';
+import type { DB } from '../../utils';
+import { ProgressView } from '../views';
+
+export const pgPushIntrospect = async (
+ db: DB,
+ filters: string[],
+ schemaFilters: string[],
+) => {
+ const matchers = filters.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+ const progress = new ProgressView(
+ 'Pulling schema from database...',
+ 'Pulling schema from database...',
+ );
+ const res = await renderWithTask(
+ progress,
+ fromDatabase(db, filter, schemaFilters),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as PgSchema;
+ const { internal, ...schemaWithoutInternals } = schema;
+ return { schema: schemaWithoutInternals };
+};
diff --git a/drizzle-kit/src/cli/commands/pgPushUtils.ts b/drizzle-kit/src/cli/commands/pgPushUtils.ts
new file mode 100644
index 000000000..eee0dc954
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/pgPushUtils.ts
@@ -0,0 +1,348 @@
+import chalk from 'chalk';
+import { render } from 'hanji';
+import type { JsonStatement } from '../../jsonStatements';
+import { PgSquasher } from '../../serializer/pgSchema';
+import { fromJson } from '../../sqlgenerator';
+import type { DB } from '../../utils';
+import { Select } from '../selector-ui';
+
+// export const filterStatements = (statements: JsonStatement[]) => {
+// return statements.filter((statement) => {
+// if (statement.type === "alter_table_alter_column_set_type") {
+// // Don't need to handle it on migrations step and introspection
+// // but for both it should be skipped
+// if (
+// statement.oldDataType.startsWith("tinyint") &&
+// statement.newDataType.startsWith("boolean")
+// ) {
+// return false;
+// }
+// } else if (statement.type === "alter_table_alter_column_set_default") {
+// if (
+// statement.newDefaultValue === false &&
+// statement.oldDefaultValue === 0 &&
+// statement.newDataType === "boolean"
+// ) {
+// return false;
+// }
+// if (
+// statement.newDefaultValue === true &&
+// statement.oldDefaultValue === 1 &&
+// statement.newDataType === "boolean"
+// ) {
+// return false;
+// }
+// }
+// return true;
+// });
+// };
+
+function concatSchemaAndTableName(schema: string | undefined, table: string) {
+ return schema ? `"${schema}"."${table}"` : `"${table}"`;
+}
+
+function tableNameWithSchemaFrom(
+ schema: string | undefined,
+ tableName: string,
+ renamedSchemas: Record,
+ renamedTables: Record,
+) {
+ const newSchemaName = schema
+ ? renamedSchemas[schema]
+ ? renamedSchemas[schema]
+ : schema
+ : undefined;
+
+ const newTableName = renamedTables[
+ concatSchemaAndTableName(newSchemaName, tableName)
+ ]
+ ? renamedTables[concatSchemaAndTableName(newSchemaName, tableName)]
+ : tableName;
+
+ return concatSchemaAndTableName(newSchemaName, newTableName);
+}
+
+export const pgSuggestions = async (db: DB, statements: JsonStatement[]) => {
+ let shouldAskForApprove = false;
+ const statementsToExecute: string[] = [];
+ const infoToPrint: string[] = [];
+
+ const tablesToRemove: string[] = [];
+ const columnsToRemove: string[] = [];
+ const schemasToRemove: string[] = [];
+ const tablesToTruncate: string[] = [];
+
+ let renamedSchemas: Record = {};
+ let renamedTables: Record = {};
+
+ for (const statement of statements) {
+ if (statement.type === 'rename_schema') {
+ renamedSchemas[statement.to] = statement.from;
+ } else if (statement.type === 'rename_table') {
+ renamedTables[
+ concatSchemaAndTableName(statement.toSchema, statement.tableNameTo)
+ ] = statement.tableNameFrom;
+ } else if (statement.type === 'drop_table') {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table with ${count} items`,
+ );
+ // statementsToExecute.push(
+ // `truncate table ${tableNameWithSchemaFrom(statement)} cascade;`
+ // );
+ tablesToRemove.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_drop_column') {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column in ${statement.tableName} table with ${count} items`,
+ );
+ columnsToRemove.push(`${statement.tableName}_${statement.columnName}`);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'drop_schema') {
+ const res = await db.query(
+ `select count(*) as count from information_schema.tables where table_schema = '${statement.name}';`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.name,
+ )
+ } schema with ${count} tables`,
+ );
+ schemasToRemove.push(statement.name);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_set_type') {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column type from ${
+ chalk.underline(
+ statement.oldDataType,
+ )
+ } to ${chalk.underline(statement.newDataType)} with ${count} items`,
+ );
+ statementsToExecute.push(
+ `truncate table ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ } cascade;`,
+ );
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_pk') {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } primary key. This statements may fail and you table may left without primary key`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+
+ const tableNameWithSchema = tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ );
+
+ const pkNameResponse = await db.query(
+ `SELECT constraint_name FROM information_schema.table_constraints
+ WHERE table_schema = '${
+ typeof statement.schema === 'undefined' || statement.schema === ''
+ ? 'public'
+ : statement.schema
+ }'
+ AND table_name = '${statement.tableName}'
+ AND constraint_type = 'PRIMARY KEY';`,
+ );
+
+ statementsToExecute.push(
+ `ALTER TABLE ${tableNameWithSchema} DROP CONSTRAINT "${pkNameResponse[0].constraint_name}"`,
+ );
+ // we will generate statement for drop pk here and not after all if-else statements
+ continue;
+ } else if (statement.type === 'alter_table_add_column') {
+ if (
+ statement.column.notNull
+ && typeof statement.column.default === 'undefined'
+ ) {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to add not-null ${
+ chalk.underline(
+ statement.column.name,
+ )
+ } column without default value, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(
+ `truncate table ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ } cascade;`,
+ );
+
+ shouldAskForApprove = true;
+ }
+ }
+ } else if (statement.type === 'create_unique_constraint') {
+ const res = await db.query(
+ `select count(*) as count from ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ }`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ const unsquashedUnique = PgSquasher.unsquashUnique(statement.data);
+ console.log(
+ `· You're about to add ${
+ chalk.underline(
+ unsquashedUnique.name,
+ )
+ } unique constraint to the table, which contains ${count} items. If this statement fails, you will receive an error from the database. Do you want to truncate ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table?\n`,
+ );
+ const { status, data } = await render(
+ new Select([
+ 'No, add the constraint without truncating the table',
+ `Yes, truncate the table`,
+ ]),
+ );
+ if (data?.index === 1) {
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(
+ `truncate table ${
+ tableNameWithSchemaFrom(
+ statement.schema,
+ statement.tableName,
+ renamedSchemas,
+ renamedTables,
+ )
+ } cascade;`,
+ );
+ shouldAskForApprove = true;
+ }
+ }
+ }
+ const stmnt = fromJson([statement], 'postgresql');
+ if (typeof stmnt !== 'undefined') {
+ if (statement.type === 'drop_table') {
+ statementsToExecute.push(
+ `DROP TABLE ${
+ concatSchemaAndTableName(
+ statement.schema,
+ statement.tableName,
+ )
+ } CASCADE;`,
+ );
+ } else {
+ statementsToExecute.push(...stmnt);
+ }
+ }
+ }
+
+ return {
+ statementsToExecute,
+ shouldAskForApprove,
+ infoToPrint,
+ columnsToRemove: [...new Set(columnsToRemove)],
+ schemasToRemove: [...new Set(schemasToRemove)],
+ tablesToTruncate: [...new Set(tablesToTruncate)],
+ tablesToRemove: [...new Set(tablesToRemove)],
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/pgUp.ts b/drizzle-kit/src/cli/commands/pgUp.ts
new file mode 100644
index 000000000..f3faaeb62
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/pgUp.ts
@@ -0,0 +1,176 @@
+import chalk from 'chalk';
+import { writeFileSync } from 'fs';
+import {
+ Column,
+ Index,
+ PgSchema,
+ PgSchemaV4,
+ PgSchemaV5,
+ pgSchemaV5,
+ PgSchemaV6,
+ pgSchemaV6,
+ Table,
+ TableV5,
+} from '../../serializer/pgSchema';
+import { prepareOutFolder, validateWithReport } from '../../utils';
+
+export const upPgHandler = (out: string) => {
+ const { snapshots } = prepareOutFolder(out, 'postgresql');
+ const report = validateWithReport(snapshots, 'postgresql');
+
+ report.nonLatest
+ .map((it) => ({
+ path: it,
+ raw: report.rawMap[it]!! as Record,
+ }))
+ .forEach((it) => {
+ const path = it.path;
+
+ let resultV6 = it.raw;
+ if (it.raw.version === '5') {
+ resultV6 = updateUpToV6(it.raw);
+ }
+
+ const result = updateUpToV7(resultV6);
+
+ console.log(`[${chalk.green('✓')}] ${path}`);
+
+ writeFileSync(path, JSON.stringify(result, null, 2));
+ });
+
+ console.log("Everything's fine 🐶🔥");
+};
+
+export const updateUpToV6 = (json: Record): PgSchemaV6 => {
+ const schema = pgSchemaV5.parse(json);
+ const tables = Object.fromEntries(
+ Object.entries(schema.tables).map((it) => {
+ const table = it[1];
+ const schema = table.schema || 'public';
+ return [`${schema}.${table.name}`, table];
+ }),
+ );
+ const enums = Object.fromEntries(
+ Object.entries(schema.enums).map((it) => {
+ const en = it[1];
+ return [
+ `public.${en.name}`,
+ {
+ name: en.name,
+ schema: 'public',
+ values: Object.values(en.values),
+ },
+ ];
+ }),
+ );
+ return {
+ ...schema,
+ version: '6',
+ dialect: 'postgresql',
+ tables: tables,
+ enums,
+ };
+};
+
+// Changed index format stored in snapshot for PostgreSQL in 0.22.0
+export const updateUpToV7 = (json: Record): PgSchema => {
+ const schema = pgSchemaV6.parse(json);
+ const tables = Object.fromEntries(
+ Object.entries(schema.tables).map((it) => {
+ const table = it[1];
+ const mappedIndexes = Object.fromEntries(
+ Object.entries(table.indexes).map((idx) => {
+ const { columns, ...rest } = idx[1];
+ const mappedColumns = columns.map((it) => {
+ return {
+ expression: it,
+ isExpression: false,
+ asc: true,
+ nulls: 'last',
+ opClass: undefined,
+ };
+ });
+ return [idx[0], { columns: mappedColumns, with: {}, ...rest }];
+ }),
+ );
+ return [it[0], { ...table, indexes: mappedIndexes }];
+ }),
+ );
+
+ return {
+ ...schema,
+ version: '7',
+ dialect: 'postgresql',
+ sequences: {},
+ tables: tables,
+ };
+};
+
+// major migration with of folder structure, etc...
+export const upPgHandlerV4toV5 = (obj: PgSchemaV4): PgSchemaV5 => {
+ const mappedTables: Record = {};
+
+ for (const [key, table] of Object.entries(obj.tables)) {
+ const mappedColumns: Record = {};
+ for (const [ckey, column] of Object.entries(table.columns)) {
+ let newDefault: any = column.default;
+ let newType: string = column.type;
+ if (column.type.toLowerCase() === 'date') {
+ if (typeof column.default !== 'undefined') {
+ if (column.default.startsWith("'") && column.default.endsWith("'")) {
+ newDefault = `'${
+ column.default
+ .substring(1, column.default.length - 1)
+ .split('T')[0]
+ }'`;
+ } else {
+ newDefault = column.default.split('T')[0];
+ }
+ }
+ } else if (column.type.toLowerCase().startsWith('timestamp')) {
+ if (typeof column.default !== 'undefined') {
+ if (column.default.startsWith("'") && column.default.endsWith("'")) {
+ newDefault = `'${
+ column.default
+ .substring(1, column.default.length - 1)
+ .replace('T', ' ')
+ .slice(0, 23)
+ }'`;
+ } else {
+ newDefault = column.default.replace('T', ' ').slice(0, 23);
+ }
+ }
+ newType = column.type
+ .toLowerCase()
+ .replace('timestamp (', 'timestamp(');
+ } else if (column.type.toLowerCase().startsWith('time')) {
+ newType = column.type.toLowerCase().replace('time (', 'time(');
+ } else if (column.type.toLowerCase().startsWith('interval')) {
+ newType = column.type.toLowerCase().replace(' (', '(');
+ }
+ mappedColumns[ckey] = { ...column, default: newDefault, type: newType };
+ }
+
+ mappedTables[key] = {
+ ...table,
+ columns: mappedColumns,
+ compositePrimaryKeys: {},
+ uniqueConstraints: {},
+ };
+ }
+
+ return {
+ version: '5',
+ dialect: obj.dialect,
+ id: obj.id,
+ prevId: obj.prevId,
+ tables: mappedTables,
+ enums: obj.enums,
+ schemas: obj.schemas,
+ _meta: {
+ schemas: {} as Record,
+ tables: {} as Record,
+ columns: {} as Record,
+ },
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/push.ts b/drizzle-kit/src/cli/commands/push.ts
new file mode 100644
index 000000000..f1b6f7739
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/push.ts
@@ -0,0 +1,527 @@
+import chalk from 'chalk';
+import { render } from 'hanji';
+import { fromJson } from '../../sqlgenerator';
+import { Select } from '../selector-ui';
+import type { MysqlCredentials } from '../validations/mysql';
+import { withStyle } from '../validations/outputs';
+import type { PostgresCredentials } from '../validations/postgres';
+import { SingleStoreCredentials } from '../validations/singlestore';
+import type { SqliteCredentials } from '../validations/sqlite';
+import {
+ filterStatements as mySqlFilterStatements,
+ logSuggestionsAndReturn as mySqlLogSuggestionsAndReturn,
+} from './mysqlPushUtils';
+import { pgSuggestions } from './pgPushUtils';
+import {
+ filterStatements as singleStoreFilterStatements,
+ logSuggestionsAndReturn as singleStoreLogSuggestionsAndReturn,
+} from './singlestorePushUtils';
+import { logSuggestionsAndReturn as sqliteSuggestions } from './sqlitePushUtils';
+
+export const mysqlPush = async (
+ schemaPath: string | string[],
+ credentials: MysqlCredentials,
+ tablesFilter: string[],
+ strict: boolean,
+ verbose: boolean,
+ force: boolean,
+) => {
+ const { connectToMySQL } = await import('../connections');
+ const { mysqlPushIntrospect } = await import('./mysqlIntrospect');
+
+ const { db, database } = await connectToMySQL(credentials);
+
+ const { schema } = await mysqlPushIntrospect(db, database, tablesFilter);
+ const { prepareMySQLPush } = await import('./migrate');
+
+ const statements = await prepareMySQLPush(schemaPath, schema);
+
+ const filteredStatements = mySqlFilterStatements(
+ statements.statements ?? [],
+ statements.validatedCur,
+ statements.validatedPrev,
+ );
+
+ try {
+ if (filteredStatements.length === 0) {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ } else {
+ const {
+ shouldAskForApprove,
+ statementsToExecute,
+ columnsToRemove,
+ tablesToRemove,
+ tablesToTruncate,
+ infoToPrint,
+ schemasToRemove,
+ } = await mySqlLogSuggestionsAndReturn(
+ db,
+ filteredStatements,
+ statements.validatedCur,
+ );
+
+ const filteredSqlStatements = fromJson(filteredStatements, 'mysql');
+
+ const uniqueSqlStatementsToExecute: string[] = [];
+ statementsToExecute.forEach((ss) => {
+ if (!uniqueSqlStatementsToExecute.includes(ss)) {
+ uniqueSqlStatementsToExecute.push(ss);
+ }
+ });
+ const uniqueFilteredSqlStatements: string[] = [];
+ filteredSqlStatements.forEach((ss) => {
+ if (!uniqueFilteredSqlStatements.includes(ss)) {
+ uniqueFilteredSqlStatements.push(ss);
+ }
+ });
+
+ if (verbose) {
+ console.log();
+ console.log(
+ withStyle.warning('You are about to execute current statements:'),
+ );
+ console.log();
+ console.log(
+ [...uniqueSqlStatementsToExecute, ...uniqueFilteredSqlStatements]
+ .map((s) => chalk.blue(s))
+ .join('\n'),
+ );
+ console.log();
+ }
+
+ if (!force && strict) {
+ if (!shouldAskForApprove) {
+ const { status, data } = await render(
+ new Select(['No, abort', `Yes, I want to execute all statements`]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+ }
+
+ if (!force && shouldAskForApprove) {
+ console.log(withStyle.warning('Found data-loss statements:'));
+ console.log(infoToPrint.join('\n'));
+ console.log();
+ console.log(
+ chalk.red.bold(
+ 'THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED\n',
+ ),
+ );
+
+ console.log(chalk.white('Do you still want to push changes?'));
+
+ const { status, data } = await render(
+ new Select([
+ 'No, abort',
+ `Yes, I want to${
+ tablesToRemove.length > 0
+ ? ` remove ${tablesToRemove.length} ${tablesToRemove.length > 1 ? 'tables' : 'table'},`
+ : ' '
+ }${
+ columnsToRemove.length > 0
+ ? ` remove ${columnsToRemove.length} ${columnsToRemove.length > 1 ? 'columns' : 'column'},`
+ : ' '
+ }${
+ tablesToTruncate.length > 0
+ ? ` truncate ${tablesToTruncate.length} ${tablesToTruncate.length > 1 ? 'tables' : 'table'}`
+ : ''
+ }`
+ .replace(/(^,)|(,$)/g, '')
+ .replace(/ +(?= )/g, ''),
+ ]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+
+ for (const dStmnt of uniqueSqlStatementsToExecute) {
+ await db.query(dStmnt);
+ }
+
+ for (const statement of uniqueFilteredSqlStatements) {
+ await db.query(statement);
+ }
+ if (filteredStatements.length > 0) {
+ render(`[${chalk.green('✓')}] Changes applied`);
+ } else {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ }
+ }
+ } catch (e) {
+ console.log(e);
+ }
+};
+
+export const singlestorePush = async (
+ schemaPath: string | string[],
+ credentials: SingleStoreCredentials,
+ tablesFilter: string[],
+ strict: boolean,
+ verbose: boolean,
+ force: boolean,
+) => {
+ const { connectToSingleStore } = await import('../connections');
+ const { singlestorePushIntrospect } = await import('./singlestoreIntrospect');
+
+ const { db, database } = await connectToSingleStore(credentials);
+
+ const { schema } = await singlestorePushIntrospect(db, database, tablesFilter);
+ const { prepareSingleStorePush } = await import('./migrate');
+
+ const statements = await prepareSingleStorePush(schemaPath, schema);
+
+ const filteredStatements = singleStoreFilterStatements(
+ statements.statements ?? [],
+ statements.validatedCur,
+ statements.validatedPrev,
+ );
+
+ try {
+ if (filteredStatements.length === 0) {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ } else {
+ const {
+ shouldAskForApprove,
+ statementsToExecute,
+ columnsToRemove,
+ tablesToRemove,
+ tablesToTruncate,
+ infoToPrint,
+ schemasToRemove,
+ } = await singleStoreLogSuggestionsAndReturn(
+ db,
+ filteredStatements,
+ statements.validatedCur,
+ );
+
+ const filteredSqlStatements = fromJson(filteredStatements, 'singlestore');
+
+ const uniqueSqlStatementsToExecute: string[] = [];
+ statementsToExecute.forEach((ss) => {
+ if (!uniqueSqlStatementsToExecute.includes(ss)) {
+ uniqueSqlStatementsToExecute.push(ss);
+ }
+ });
+ const uniqueFilteredSqlStatements: string[] = [];
+ filteredSqlStatements.forEach((ss) => {
+ if (!uniqueFilteredSqlStatements.includes(ss)) {
+ uniqueFilteredSqlStatements.push(ss);
+ }
+ });
+
+ if (verbose) {
+ console.log();
+ // console.log(chalk.gray('Verbose logs:'));
+ console.log(
+ withStyle.warning('You are about to execute current statements:'),
+ );
+ console.log();
+ console.log(
+ [...uniqueSqlStatementsToExecute, ...uniqueFilteredSqlStatements]
+ .map((s) => chalk.blue(s))
+ .join('\n'),
+ );
+ console.log();
+ }
+
+ if (!force && strict) {
+ if (!shouldAskForApprove) {
+ const { status, data } = await render(
+ new Select(['No, abort', `Yes, I want to execute all statements`]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+ }
+
+ if (!force && shouldAskForApprove) {
+ console.log(withStyle.warning('Found data-loss statements:'));
+ console.log(infoToPrint.join('\n'));
+ console.log();
+ console.log(
+ chalk.red.bold(
+ 'THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED\n',
+ ),
+ );
+
+ console.log(chalk.white('Do you still want to push changes?'));
+
+ const { status, data } = await render(
+ new Select([
+ 'No, abort',
+ `Yes, I want to${
+ tablesToRemove.length > 0
+ ? ` remove ${tablesToRemove.length} ${tablesToRemove.length > 1 ? 'tables' : 'table'},`
+ : ' '
+ }${
+ columnsToRemove.length > 0
+ ? ` remove ${columnsToRemove.length} ${columnsToRemove.length > 1 ? 'columns' : 'column'},`
+ : ' '
+ }${
+ tablesToTruncate.length > 0
+ ? ` truncate ${tablesToTruncate.length} ${tablesToTruncate.length > 1 ? 'tables' : 'table'}`
+ : ''
+ }`
+ .replace(/(^,)|(,$)/g, '')
+ .replace(/ +(?= )/g, ''),
+ ]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+
+ for (const dStmnt of uniqueSqlStatementsToExecute) {
+ await db.query(dStmnt);
+ }
+
+ for (const statement of uniqueFilteredSqlStatements) {
+ await db.query(statement);
+ }
+ if (filteredStatements.length > 0) {
+ render(`[${chalk.green('✓')}] Changes applied`);
+ } else {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ }
+ }
+ } catch (e) {
+ console.log(e);
+ }
+};
+
+export const pgPush = async (
+ schemaPath: string | string[],
+ verbose: boolean,
+ strict: boolean,
+ credentials: PostgresCredentials,
+ tablesFilter: string[],
+ schemasFilter: string[],
+ force: boolean,
+) => {
+ const { preparePostgresDB } = await import('../connections');
+ const { pgPushIntrospect } = await import('./pgIntrospect');
+
+ const db = await preparePostgresDB(credentials);
+ const { schema } = await pgPushIntrospect(db, tablesFilter, schemasFilter);
+
+ const { preparePgPush } = await import('./migrate');
+
+ const statements = await preparePgPush(schemaPath, schema, schemasFilter);
+
+ try {
+ if (statements.sqlStatements.length === 0) {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ } else {
+ // const filteredStatements = filterStatements(statements.statements);
+ const {
+ shouldAskForApprove,
+ statementsToExecute,
+ columnsToRemove,
+ tablesToRemove,
+ tablesToTruncate,
+ infoToPrint,
+ schemasToRemove,
+ } = await pgSuggestions(db, statements.statements);
+
+ if (verbose) {
+ console.log();
+ // console.log(chalk.gray('Verbose logs:'));
+ console.log(
+ withStyle.warning('You are about to execute current statements:'),
+ );
+ console.log();
+ console.log(statementsToExecute.map((s) => chalk.blue(s)).join('\n'));
+ console.log();
+ }
+
+ if (!force && strict) {
+ if (!shouldAskForApprove) {
+ const { status, data } = await render(
+ new Select(['No, abort', `Yes, I want to execute all statements`]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+ }
+
+ if (!force && shouldAskForApprove) {
+ console.log(withStyle.warning('Found data-loss statements:'));
+ console.log(infoToPrint.join('\n'));
+ console.log();
+ console.log(
+ chalk.red.bold(
+ 'THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED\n',
+ ),
+ );
+
+ console.log(chalk.white('Do you still want to push changes?'));
+
+ const { status, data } = await render(
+ new Select([
+ 'No, abort',
+ `Yes, I want to${
+ tablesToRemove.length > 0
+ ? ` remove ${tablesToRemove.length} ${tablesToRemove.length > 1 ? 'tables' : 'table'},`
+ : ' '
+ }${
+ columnsToRemove.length > 0
+ ? ` remove ${columnsToRemove.length} ${columnsToRemove.length > 1 ? 'columns' : 'column'},`
+ : ' '
+ }${
+ tablesToTruncate.length > 0
+ ? ` truncate ${tablesToTruncate.length} ${tablesToTruncate.length > 1 ? 'tables' : 'table'}`
+ : ''
+ }`
+ .replace(/(^,)|(,$)/g, '')
+ .replace(/ +(?= )/g, ''),
+ ]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+
+ if (statements.statements.length > 0) {
+ render(`[${chalk.green('✓')}] Changes applied`);
+ } else {
+ render(`[${chalk.blue('i')}] No changes detected`);
+ }
+ }
+ } catch (e) {
+ console.error(e);
+ }
+};
+
+export const sqlitePush = async (
+ schemaPath: string | string[],
+ verbose: boolean,
+ strict: boolean,
+ credentials: SqliteCredentials,
+ tablesFilter: string[],
+ force: boolean,
+) => {
+ const { connectToSQLite } = await import('../connections');
+ const { sqlitePushIntrospect } = await import('./sqliteIntrospect');
+
+ const db = await connectToSQLite(credentials);
+ const { schema } = await sqlitePushIntrospect(db, tablesFilter);
+ const { prepareSQLitePush } = await import('./migrate');
+
+ const statements = await prepareSQLitePush(schemaPath, schema);
+
+ if (statements.sqlStatements.length === 0) {
+ render(`\n[${chalk.blue('i')}] No changes detected`);
+ } else {
+ const {
+ shouldAskForApprove,
+ statementsToExecute,
+ columnsToRemove,
+ tablesToRemove,
+ tablesToTruncate,
+ infoToPrint,
+ } = await sqliteSuggestions(
+ db,
+ statements.statements,
+ statements.squashedCur,
+ statements.squashedPrev,
+ statements.meta!,
+ );
+
+ if (verbose && statementsToExecute.length > 0) {
+ console.log();
+ console.log(
+ withStyle.warning('You are about to execute current statements:'),
+ );
+ console.log();
+ console.log(statementsToExecute.map((s) => chalk.blue(s)).join('\n'));
+ console.log();
+ }
+
+ if (!force && strict) {
+ if (!shouldAskForApprove) {
+ const { status, data } = await render(
+ new Select(['No, abort', `Yes, I want to execute all statements`]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+ }
+
+ if (!force && shouldAskForApprove) {
+ console.log(withStyle.warning('Found data-loss statements:'));
+ console.log(infoToPrint.join('\n'));
+ console.log();
+ console.log(
+ chalk.red.bold(
+ 'THIS ACTION WILL CAUSE DATA LOSS AND CANNOT BE REVERTED\n',
+ ),
+ );
+
+ console.log(chalk.white('Do you still want to push changes?'));
+
+ const { status, data } = await render(
+ new Select([
+ 'No, abort',
+ `Yes, I want to${
+ tablesToRemove.length > 0
+ ? ` remove ${tablesToRemove.length} ${tablesToRemove.length > 1 ? 'tables' : 'table'},`
+ : ' '
+ }${
+ columnsToRemove.length > 0
+ ? ` remove ${columnsToRemove.length} ${columnsToRemove.length > 1 ? 'columns' : 'column'},`
+ : ' '
+ }${
+ tablesToTruncate.length > 0
+ ? ` truncate ${tablesToTruncate.length} ${tablesToTruncate.length > 1 ? 'tables' : 'table'}`
+ : ''
+ }`
+ .trimEnd()
+ .replace(/(^,)|(,$)/g, '')
+ .replace(/ +(?= )/g, ''),
+ ]),
+ );
+ if (data?.index === 0) {
+ render(`[${chalk.red('x')}] All changes were aborted`);
+ process.exit(0);
+ }
+ }
+
+ if (statementsToExecute.length === 0) {
+ render(`\n[${chalk.blue('i')}] No changes detected`);
+ } else {
+ if (!('driver' in credentials)) {
+ await db.query('begin');
+ try {
+ for (const dStmnt of statementsToExecute) {
+ await db.query(dStmnt);
+ }
+ await db.query('commit');
+ } catch (e) {
+ console.error(e);
+ await db.query('rollback');
+ process.exit(1);
+ }
+ } else if (credentials.driver === 'turso') {
+ await db.batch!(statementsToExecute.map((it) => ({ query: it })));
+ }
+ render(`[${chalk.green('✓')}] Changes applied`);
+ }
+ }
+};
diff --git a/drizzle-kit/src/cli/commands/singlestoreIntrospect.ts b/drizzle-kit/src/cli/commands/singlestoreIntrospect.ts
new file mode 100644
index 000000000..27d8c59c5
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/singlestoreIntrospect.ts
@@ -0,0 +1,53 @@
+import { renderWithTask } from 'hanji';
+import { Minimatch } from 'minimatch';
+import { originUUID } from '../../global';
+import type { SingleStoreSchema } from '../../serializer/singlestoreSchema';
+import { fromDatabase } from '../../serializer/singlestoreSerializer';
+import type { DB } from '../../utils';
+import { ProgressView } from '../views';
+
+export const singlestorePushIntrospect = async (
+ db: DB,
+ databaseName: string,
+ filters: string[],
+) => {
+ const matchers = filters.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new ProgressView(
+ 'Pulling schema from database...',
+ 'Pulling schema from database...',
+ );
+ const res = await renderWithTask(
+ progress,
+ fromDatabase(db, databaseName, filter),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as SingleStoreSchema;
+ const { internal, ...schemaWithoutInternals } = schema;
+ return { schema: schemaWithoutInternals };
+};
diff --git a/drizzle-kit/src/cli/commands/singlestorePushUtils.ts b/drizzle-kit/src/cli/commands/singlestorePushUtils.ts
new file mode 100644
index 000000000..80fad9b2d
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/singlestorePushUtils.ts
@@ -0,0 +1,352 @@
+import chalk from 'chalk';
+import { render } from 'hanji';
+import { TypeOf } from 'zod';
+import { JsonAlterColumnTypeStatement, JsonStatement } from '../../jsonStatements';
+import { singlestoreSchema, SingleStoreSquasher } from '../../serializer/singlestoreSchema';
+import type { DB } from '../../utils';
+import { Select } from '../selector-ui';
+import { withStyle } from '../validations/outputs';
+
+export const filterStatements = (
+ statements: JsonStatement[],
+ currentSchema: TypeOf,
+ prevSchema: TypeOf,
+) => {
+ return statements.filter((statement) => {
+ if (statement.type === 'alter_table_alter_column_set_type') {
+ // Don't need to handle it on migrations step and introspection
+ // but for both it should be skipped
+ if (
+ statement.oldDataType.startsWith('tinyint')
+ && statement.newDataType.startsWith('boolean')
+ ) {
+ return false;
+ }
+
+ if (
+ statement.oldDataType.startsWith('bigint unsigned')
+ && statement.newDataType.startsWith('serial')
+ ) {
+ return false;
+ }
+
+ if (
+ statement.oldDataType.startsWith('serial')
+ && statement.newDataType.startsWith('bigint unsigned')
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'alter_table_alter_column_set_default') {
+ if (
+ statement.newDefaultValue === false
+ && statement.oldDefaultValue === 0
+ && statement.newDataType === 'boolean'
+ ) {
+ return false;
+ }
+ if (
+ statement.newDefaultValue === true
+ && statement.oldDefaultValue === 1
+ && statement.newDataType === 'boolean'
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'delete_unique_constraint') {
+ const unsquashed = SingleStoreSquasher.unsquashUnique(statement.data);
+ // only if constraint was removed from a serial column, than treat it as removed
+ // const serialStatement = statements.find(
+ // (it) => it.type === "alter_table_alter_column_set_type"
+ // ) as JsonAlterColumnTypeStatement;
+ // if (
+ // serialStatement?.oldDataType.startsWith("bigint unsigned") &&
+ // serialStatement?.newDataType.startsWith("serial") &&
+ // serialStatement.columnName ===
+ // SingleStoreSquasher.unsquashUnique(statement.data).columns[0]
+ // ) {
+ // return false;
+ // }
+ // Check if uniqueindex was only on this column, that is serial
+
+ // if now serial and was not serial and was unique index
+ if (
+ unsquashed.columns.length === 1
+ && currentSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .type === 'serial'
+ && prevSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .type === 'serial'
+ && currentSchema.tables[statement.tableName].columns[unsquashed.columns[0]]
+ .name === unsquashed.columns[0]
+ ) {
+ return false;
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_notnull') {
+ // only if constraint was removed from a serial column, than treat it as removed
+ const serialStatement = statements.find(
+ (it) => it.type === 'alter_table_alter_column_set_type',
+ ) as JsonAlterColumnTypeStatement;
+ if (
+ serialStatement?.oldDataType.startsWith('bigint unsigned')
+ && serialStatement?.newDataType.startsWith('serial')
+ && serialStatement.columnName === statement.columnName
+ && serialStatement.tableName === statement.tableName
+ ) {
+ return false;
+ }
+ if (statement.newDataType === 'serial' && !statement.columnNotNull) {
+ return false;
+ }
+ if (statement.columnAutoIncrement) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+};
+
+export const logSuggestionsAndReturn = async (
+ db: DB,
+ statements: JsonStatement[],
+ json2: TypeOf,
+) => {
+ let shouldAskForApprove = false;
+ const statementsToExecute: string[] = [];
+ const infoToPrint: string[] = [];
+
+ const tablesToRemove: string[] = [];
+ const columnsToRemove: string[] = [];
+ const schemasToRemove: string[] = [];
+ const tablesToTruncate: string[] = [];
+
+ for (const statement of statements) {
+ if (statement.type === 'drop_table') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table with ${count} items`,
+ );
+ tablesToRemove.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_drop_column') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column in ${statement.tableName} table with ${count} items`,
+ );
+ columnsToRemove.push(`${statement.tableName}_${statement.columnName}`);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'drop_schema') {
+ const res = await db.query(
+ `select count(*) as count from information_schema.tables where table_schema = \`${statement.name}\`;`,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.name,
+ )
+ } schema with ${count} tables`,
+ );
+ schemasToRemove.push(statement.name);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_set_type') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column type from ${
+ chalk.underline(
+ statement.oldDataType,
+ )
+ } to ${chalk.underline(statement.newDataType)} with ${count} items`,
+ );
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_default') {
+ if (statement.columnNotNull) {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to remove default value from ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } not-null column with ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ // shouldAskForApprove = true;
+ } else if (statement.type === 'alter_table_alter_column_set_notnull') {
+ if (typeof statement.columnDefault === 'undefined') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to set not-null constraint to ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column without default, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ } else if (statement.type === 'alter_table_alter_column_drop_pk') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+
+ // if drop pk and json2 has autoincrement in table -> exit process with error
+ if (
+ Object.values(json2.tables[statement.tableName].columns).filter(
+ (column) => column.autoincrement,
+ ).length > 0
+ ) {
+ console.log(
+ `${
+ withStyle.errorWarning(
+ `You have removed the primary key from a ${statement.tableName} table without removing the auto-increment property from this table. As the database error states: 'there can be only one auto column, and it must be defined as a key. Make sure to remove autoincrement from ${statement.tableName} table`,
+ )
+ }`,
+ );
+ process.exit(1);
+ }
+
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to change ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } primary key. This statements may fail and you table may left without primary key`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ } else if (statement.type === 'delete_composite_pk') {
+ // if drop pk and json2 has autoincrement in table -> exit process with error
+ if (
+ Object.values(json2.tables[statement.tableName].columns).filter(
+ (column) => column.autoincrement,
+ ).length > 0
+ ) {
+ console.log(
+ `${
+ withStyle.errorWarning(
+ `You have removed the primary key from a ${statement.tableName} table without removing the auto-increment property from this table. As the database error states: 'there can be only one auto column, and it must be defined as a key. Make sure to remove autoincrement from ${statement.tableName} table`,
+ )
+ }`,
+ );
+ process.exit(1);
+ }
+ } else if (statement.type === 'alter_table_add_column') {
+ if (
+ statement.column.notNull
+ && typeof statement.column.default === 'undefined'
+ ) {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to add not-null ${
+ chalk.underline(
+ statement.column.name,
+ )
+ } column without default value, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ } else if (statement.type === 'create_unique_constraint') {
+ const res = await db.query(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ const unsquashedUnique = SingleStoreSquasher.unsquashUnique(statement.data);
+ console.log(
+ `· You're about to add ${
+ chalk.underline(
+ unsquashedUnique.name,
+ )
+ } unique constraint to the table, which contains ${count} items. If this statement fails, you will receive an error from the database. Do you want to truncate ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table?\n`,
+ );
+ const { status, data } = await render(
+ new Select([
+ 'No, add the constraint without truncating the table',
+ `Yes, truncate the table`,
+ ]),
+ );
+ if (data?.index === 1) {
+ tablesToTruncate.push(statement.tableName);
+ statementsToExecute.push(`truncate table ${statement.tableName};`);
+ shouldAskForApprove = true;
+ }
+ }
+ }
+ }
+
+ return {
+ statementsToExecute,
+ shouldAskForApprove,
+ infoToPrint,
+ columnsToRemove: [...new Set(columnsToRemove)],
+ schemasToRemove: [...new Set(schemasToRemove)],
+ tablesToTruncate: [...new Set(tablesToTruncate)],
+ tablesToRemove: [...new Set(tablesToRemove)],
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/singlestoreUp.ts b/drizzle-kit/src/cli/commands/singlestoreUp.ts
new file mode 100644
index 000000000..dc5004ed0
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/singlestoreUp.ts
@@ -0,0 +1 @@
+export const upSinglestoreHandler = (out: string) => {};
diff --git a/drizzle-kit/src/cli/commands/sqliteIntrospect.ts b/drizzle-kit/src/cli/commands/sqliteIntrospect.ts
new file mode 100644
index 000000000..1c62498f5
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/sqliteIntrospect.ts
@@ -0,0 +1,96 @@
+import { renderWithTask } from 'hanji';
+import { Minimatch } from 'minimatch';
+import { originUUID } from '../../global';
+import { schemaToTypeScript } from '../../introspect-sqlite';
+import type { SQLiteSchema } from '../../serializer/sqliteSchema';
+import { fromDatabase } from '../../serializer/sqliteSerializer';
+import type { SQLiteDB } from '../../utils';
+import { Casing } from '../validations/common';
+import type { SqliteCredentials } from '../validations/sqlite';
+import { IntrospectProgress, ProgressView } from '../views';
+
+export const sqliteIntrospect = async (
+ credentials: SqliteCredentials,
+ filters: string[],
+ casing: Casing,
+) => {
+ const { connectToSQLite } = await import('../connections');
+ const db = await connectToSQLite(credentials);
+
+ const matchers = filters.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new IntrospectProgress();
+ const res = await renderWithTask(
+ progress,
+ fromDatabase(db, filter, (stage, count, status) => {
+ progress.update(stage, count, status);
+ }),
+ );
+
+ const schema = { id: originUUID, prevId: '', ...res } as SQLiteSchema;
+ const ts = schemaToTypeScript(schema, casing);
+ return { schema, ts };
+};
+
+export const sqlitePushIntrospect = async (db: SQLiteDB, filters: string[]) => {
+ const matchers = filters.map((it) => {
+ return new Minimatch(it);
+ });
+
+ const filter = (tableName: string) => {
+ if (matchers.length === 0) return true;
+
+ let flags: boolean[] = [];
+
+ for (let matcher of matchers) {
+ if (matcher.negate) {
+ if (!matcher.match(tableName)) {
+ flags.push(false);
+ }
+ }
+
+ if (matcher.match(tableName)) {
+ flags.push(true);
+ }
+ }
+
+ if (flags.length > 0) {
+ return flags.every(Boolean);
+ }
+ return false;
+ };
+
+ const progress = new ProgressView(
+ 'Pulling schema from database...',
+ 'Pulling schema from database...',
+ );
+ const res = await renderWithTask(progress, fromDatabase(db, filter));
+
+ const schema = { id: originUUID, prevId: '', ...res } as SQLiteSchema;
+ return { schema };
+};
diff --git a/drizzle-kit/src/cli/commands/sqlitePushUtils.ts b/drizzle-kit/src/cli/commands/sqlitePushUtils.ts
new file mode 100644
index 000000000..d11a4ce62
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/sqlitePushUtils.ts
@@ -0,0 +1,393 @@
+import chalk from 'chalk';
+
+import { SQLiteSchemaInternal, SQLiteSchemaSquashed, SQLiteSquasher } from '../../serializer/sqliteSchema';
+import {
+ CreateSqliteIndexConvertor,
+ fromJson,
+ SQLiteCreateTableConvertor,
+ SQLiteDropTableConvertor,
+ SqliteRenameTableConvertor,
+} from '../../sqlgenerator';
+
+import type { JsonStatement } from '../../jsonStatements';
+import type { SQLiteDB } from '../../utils';
+
+export const _moveDataStatements = (
+ tableName: string,
+ json: SQLiteSchemaSquashed,
+ dataLoss: boolean = false,
+) => {
+ const statements: string[] = [];
+
+ // rename table to __old_${tablename}
+ statements.push(
+ new SqliteRenameTableConvertor().convert({
+ type: 'rename_table',
+ tableNameFrom: tableName,
+ tableNameTo: `__old_push_${tableName}`,
+ fromSchema: '',
+ toSchema: '',
+ }),
+ );
+
+ // create table statement from a new json2 with proper name
+ const tableColumns = Object.values(json.tables[tableName].columns);
+ const referenceData = Object.values(json.tables[tableName].foreignKeys);
+ const compositePKs = Object.values(
+ json.tables[tableName].compositePrimaryKeys,
+ ).map((it) => SQLiteSquasher.unsquashPK(it));
+
+ const fks = referenceData.map((it) => SQLiteSquasher.unsquashPushFK(it));
+
+ statements.push(
+ new SQLiteCreateTableConvertor().convert({
+ type: 'sqlite_create_table',
+ tableName: tableName,
+ columns: tableColumns,
+ referenceData: fks,
+ compositePKs,
+ }),
+ );
+
+ // move data
+ if (!dataLoss) {
+ statements.push(
+ `INSERT INTO "${tableName}" SELECT * FROM "__old_push_${tableName}";`,
+ );
+ }
+ // drop table with name __old_${tablename}
+ statements.push(
+ new SQLiteDropTableConvertor().convert({
+ type: 'drop_table',
+ tableName: `__old_push_${tableName}`,
+ schema: '',
+ }),
+ );
+
+ for (const idx of Object.values(json.tables[tableName].indexes)) {
+ statements.push(
+ new CreateSqliteIndexConvertor().convert({
+ type: 'create_index',
+ tableName: tableName,
+ schema: '',
+ data: idx,
+ }),
+ );
+ }
+
+ return statements;
+};
+
+export const getOldTableName = (
+ tableName: string,
+ meta: SQLiteSchemaInternal['_meta'],
+) => {
+ for (const key of Object.keys(meta.tables)) {
+ const value = meta.tables[key];
+ if (`"${tableName}"` === value) {
+ return key.substring(1, key.length - 1);
+ }
+ }
+ return tableName;
+};
+
+export const getNewTableName = (
+ tableName: string,
+ meta: SQLiteSchemaInternal['_meta'],
+) => {
+ if (typeof meta.tables[`"${tableName}"`] !== 'undefined') {
+ return meta.tables[`"${tableName}"`].substring(
+ 1,
+ meta.tables[`"${tableName}"`].length - 1,
+ );
+ }
+ return tableName;
+};
+
+export const logSuggestionsAndReturn = async (
+ connection: SQLiteDB,
+ statements: JsonStatement[],
+ json1: SQLiteSchemaSquashed,
+ json2: SQLiteSchemaSquashed,
+ meta: SQLiteSchemaInternal['_meta'],
+) => {
+ let shouldAskForApprove = false;
+ const statementsToExecute: string[] = [];
+ const infoToPrint: string[] = [];
+
+ const tablesToRemove: string[] = [];
+ const columnsToRemove: string[] = [];
+ const schemasToRemove: string[] = [];
+ const tablesToTruncate: string[] = [];
+
+ const tablesContext: Record = {};
+
+ for (const statement of statements) {
+ if (statement.type === 'drop_table') {
+ const res = await connection.query<{ count: string }>(
+ `select count(*) as count from \`${statement.tableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.tableName,
+ )
+ } table with ${count} items`,
+ );
+ tablesToRemove.push(statement.tableName);
+ shouldAskForApprove = true;
+ }
+ const stmnt = fromJson([statement], 'sqlite')[0];
+ statementsToExecute.push(stmnt);
+ } else if (statement.type === 'alter_table_drop_column') {
+ const newTableName = getOldTableName(statement.tableName, meta);
+
+ const columnIsPartOfPk = Object.values(
+ json1.tables[newTableName].compositePrimaryKeys,
+ ).find((c) => SQLiteSquasher.unsquashPK(c).includes(statement.columnName));
+
+ const columnIsPartOfIndex = Object.values(
+ json1.tables[newTableName].indexes,
+ ).find((c) => SQLiteSquasher.unsquashIdx(c).columns.includes(statement.columnName));
+
+ const columnIsPk = json1.tables[newTableName].columns[statement.columnName].primaryKey;
+
+ const columnIsPartOfFk = Object.values(
+ json1.tables[newTableName].foreignKeys,
+ ).find((t) =>
+ SQLiteSquasher.unsquashPushFK(t).columnsFrom.includes(
+ statement.columnName,
+ )
+ );
+
+ const res = await connection.query<{ count: string }>(
+ `select count(*) as count from \`${newTableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to delete ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column in ${newTableName} table with ${count} items`,
+ );
+ columnsToRemove.push(`${newTableName}_${statement.columnName}`);
+ shouldAskForApprove = true;
+ }
+
+ if (
+ columnIsPk
+ || columnIsPartOfPk
+ || columnIsPartOfIndex
+ || columnIsPartOfFk
+ ) {
+ tablesContext[newTableName] = [
+ ..._moveDataStatements(statement.tableName, json2, true),
+ ];
+ // check table that have fk to this table
+
+ const tablesReferncingCurrent: string[] = [];
+
+ for (const table of Object.values(json1.tables)) {
+ const tablesRefs = Object.values(json1.tables[table.name].foreignKeys)
+ .filter(
+ (t) => SQLiteSquasher.unsquashPushFK(t).tableTo === newTableName,
+ )
+ .map((t) => SQLiteSquasher.unsquashPushFK(t).tableFrom);
+
+ tablesReferncingCurrent.push(...tablesRefs);
+ }
+
+ const uniqueTableRefs = [...new Set(tablesReferncingCurrent)];
+
+ for (const table of uniqueTableRefs) {
+ if (typeof tablesContext[table] === 'undefined') {
+ tablesContext[table] = [..._moveDataStatements(table, json2)];
+ }
+ }
+ } else {
+ if (typeof tablesContext[newTableName] === 'undefined') {
+ const stmnt = fromJson([statement], 'sqlite')[0];
+ statementsToExecute.push(stmnt);
+ }
+ }
+ } else if (statement.type === 'sqlite_alter_table_add_column') {
+ const newTableName = getOldTableName(statement.tableName, meta);
+ if (statement.column.notNull && !statement.column.default) {
+ const res = await connection.query<{ count: string }>(
+ `select count(*) as count from \`${newTableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to add not-null ${
+ chalk.underline(
+ statement.column.name,
+ )
+ } column without default value, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(newTableName);
+ statementsToExecute.push(`delete from ${newTableName};`);
+
+ shouldAskForApprove = true;
+ }
+ }
+ if (statement.column.primaryKey) {
+ tablesContext[newTableName] = [
+ ..._moveDataStatements(statement.tableName, json2, true),
+ ];
+ const tablesReferncingCurrent: string[] = [];
+
+ for (const table of Object.values(json1.tables)) {
+ const tablesRefs = Object.values(json1.tables[table.name].foreignKeys)
+ .filter(
+ (t) => SQLiteSquasher.unsquashPushFK(t).tableTo === newTableName,
+ )
+ .map((t) => SQLiteSquasher.unsquashPushFK(t).tableFrom);
+
+ tablesReferncingCurrent.push(...tablesRefs);
+ }
+
+ const uniqueTableRefs = [...new Set(tablesReferncingCurrent)];
+
+ for (const table of uniqueTableRefs) {
+ if (typeof tablesContext[table] === 'undefined') {
+ tablesContext[table] = [..._moveDataStatements(table, json2)];
+ }
+ }
+ } else {
+ if (typeof tablesContext[newTableName] === 'undefined') {
+ const stmnt = fromJson([statement], 'sqlite')[0];
+ statementsToExecute.push(stmnt);
+ }
+ }
+ } else if (
+ statement.type === 'alter_table_alter_column_set_type'
+ || statement.type === 'alter_table_alter_column_set_default'
+ || statement.type === 'alter_table_alter_column_drop_default'
+ || statement.type === 'alter_table_alter_column_set_notnull'
+ || statement.type === 'alter_table_alter_column_drop_notnull'
+ || statement.type === 'alter_table_alter_column_drop_autoincrement'
+ || statement.type === 'alter_table_alter_column_set_autoincrement'
+ || statement.type === 'alter_table_alter_column_drop_pk'
+ || statement.type === 'alter_table_alter_column_set_pk'
+ ) {
+ if (
+ !(
+ statement.type === 'alter_table_alter_column_set_notnull'
+ && statement.columnPk
+ )
+ ) {
+ const newTableName = getOldTableName(statement.tableName, meta);
+ if (
+ statement.type === 'alter_table_alter_column_set_notnull'
+ && typeof statement.columnDefault === 'undefined'
+ ) {
+ const res = await connection.query<{ count: string }>(
+ `select count(*) as count from \`${newTableName}\``,
+ );
+ const count = Number(res[0].count);
+ if (count > 0) {
+ infoToPrint.push(
+ `· You're about to add not-null constraint to ${
+ chalk.underline(
+ statement.columnName,
+ )
+ } column without default value, which contains ${count} items`,
+ );
+
+ tablesToTruncate.push(newTableName);
+ shouldAskForApprove = true;
+ }
+ tablesContext[newTableName] = _moveDataStatements(
+ statement.tableName,
+ json1,
+ true,
+ );
+ } else {
+ if (typeof tablesContext[newTableName] === 'undefined') {
+ tablesContext[newTableName] = _moveDataStatements(
+ statement.tableName,
+ json1,
+ );
+ }
+ }
+
+ const tablesReferncingCurrent: string[] = [];
+
+ for (const table of Object.values(json1.tables)) {
+ const tablesRefs = Object.values(json1.tables[table.name].foreignKeys)
+ .filter(
+ (t) => SQLiteSquasher.unsquashPushFK(t).tableTo === newTableName,
+ )
+ .map((t) => {
+ return getNewTableName(
+ SQLiteSquasher.unsquashPushFK(t).tableFrom,
+ meta,
+ );
+ });
+
+ tablesReferncingCurrent.push(...tablesRefs);
+ }
+
+ const uniqueTableRefs = [...new Set(tablesReferncingCurrent)];
+
+ for (const table of uniqueTableRefs) {
+ if (typeof tablesContext[table] === 'undefined') {
+ tablesContext[table] = [..._moveDataStatements(table, json1)];
+ }
+ }
+ }
+ } else if (
+ statement.type === 'create_reference'
+ || statement.type === 'delete_reference'
+ || statement.type === 'alter_reference'
+ ) {
+ const fk = SQLiteSquasher.unsquashPushFK(statement.data);
+
+ if (typeof tablesContext[statement.tableName] === 'undefined') {
+ tablesContext[statement.tableName] = _moveDataStatements(
+ statement.tableName,
+ json2,
+ );
+ }
+ } else if (
+ statement.type === 'create_composite_pk'
+ || statement.type === 'alter_composite_pk'
+ || statement.type === 'delete_composite_pk'
+ || statement.type === 'create_unique_constraint'
+ || statement.type === 'delete_unique_constraint'
+ ) {
+ const newTableName = getOldTableName(statement.tableName, meta);
+ if (typeof tablesContext[newTableName] === 'undefined') {
+ tablesContext[newTableName] = _moveDataStatements(
+ statement.tableName,
+ json2,
+ );
+ }
+ } else {
+ const stmnt = fromJson([statement], 'sqlite');
+ if (typeof stmnt !== 'undefined') {
+ statementsToExecute.push(...stmnt);
+ }
+ }
+ }
+
+ for (const context of Object.values(tablesContext)) {
+ statementsToExecute.push(...context);
+ }
+
+ return {
+ statementsToExecute,
+ shouldAskForApprove,
+ infoToPrint,
+ columnsToRemove: [...new Set(columnsToRemove)],
+ schemasToRemove: [...new Set(schemasToRemove)],
+ tablesToTruncate: [...new Set(tablesToTruncate)],
+ tablesToRemove: [...new Set(tablesToRemove)],
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/sqliteUp.ts b/drizzle-kit/src/cli/commands/sqliteUp.ts
new file mode 100644
index 000000000..b76b9e2cd
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/sqliteUp.ts
@@ -0,0 +1,51 @@
+import chalk from 'chalk';
+import { writeFileSync } from 'fs';
+import { mapEntries } from 'src/global';
+import { SQLiteSchema, sqliteSchemaV5 } from 'src/serializer/sqliteSchema';
+import { prepareOutFolder, validateWithReport } from 'src/utils';
+
+export const upSqliteHandler = (out: string) => {
+ const { snapshots } = prepareOutFolder(out, 'sqlite');
+ const report = validateWithReport(snapshots, 'sqlite');
+
+ report.nonLatest
+ .map((it) => ({
+ path: it,
+ raw: report.rawMap[it]!! as Record,
+ }))
+ .forEach((it) => {
+ const path = it.path;
+ const result = updateUpToV6(it.raw);
+
+ console.log(`[${chalk.green('✓')}] ${path}`);
+
+ writeFileSync(path, JSON.stringify(result, null, 2));
+ });
+
+ console.log("Everything's fine 🐶🔥");
+};
+
+const updateUpToV6 = (json: Record): SQLiteSchema => {
+ const schema = sqliteSchemaV5.parse(json);
+
+ const tables = mapEntries(schema.tables, (tableKey, table) => {
+ const columns = mapEntries(table.columns, (key, value) => {
+ if (
+ value.default
+ && (typeof value.default === 'object' || Array.isArray(value.default))
+ ) {
+ value.default = `'${JSON.stringify(value.default)}'`;
+ }
+ return [key, value];
+ });
+ table.columns = columns;
+ return [tableKey, table];
+ });
+
+ return {
+ ...schema,
+ version: '6',
+ dialect: 'sqlite',
+ tables: tables,
+ };
+};
diff --git a/drizzle-kit/src/cli/commands/utils.ts b/drizzle-kit/src/cli/commands/utils.ts
new file mode 100644
index 000000000..e8a8f2b95
--- /dev/null
+++ b/drizzle-kit/src/cli/commands/utils.ts
@@ -0,0 +1,729 @@
+import chalk from 'chalk';
+import { existsSync } from 'fs';
+import { render } from 'hanji';
+import { join, resolve } from 'path';
+import { object, string } from 'zod';
+import { assertUnreachable } from '../../global';
+import { type Dialect, dialect } from '../../schemaValidator';
+import { prepareFilenames } from '../../serializer';
+import { pullParams, pushParams } from '../validations/cli';
+import {
+ Casing,
+ CliConfig,
+ configCommonSchema,
+ configMigrations,
+ Driver,
+ Prefix,
+ wrapParam,
+} from '../validations/common';
+import {
+ MysqlCredentials,
+ mysqlCredentials,
+ printConfigConnectionIssues as printIssuesMysql,
+} from '../validations/mysql';
+import { outputs } from '../validations/outputs';
+import {
+ PostgresCredentials,
+ postgresCredentials,
+ printConfigConnectionIssues as printIssuesPg,
+} from '../validations/postgres';
+import {
+ printConfigConnectionIssues as printIssuesSingleStore,
+ SingleStoreCredentials,
+ singlestoreCredentials,
+} from '../validations/singlestore';
+import {
+ printConfigConnectionIssues as printIssuesSqlite,
+ SqliteCredentials,
+ sqliteCredentials,
+} from '../validations/sqlite';
+import { studioCliParams, studioConfig } from '../validations/studio';
+import { error } from '../views';
+
+// NextJs default config is target: es5, which esbuild-register can't consume
+const assertES5 = async (unregister: () => void) => {
+ try {
+ require('./_es5.ts');
+ } catch (e: any) {
+ if ('errors' in e && Array.isArray(e.errors) && e.errors.length > 0) {
+ const es5Error = (e.errors as any[]).filter((it) => it.text?.includes(`("es5") is not supported yet`)).length > 0;
+ if (es5Error) {
+ console.log(
+ error(
+ `Please change compilerOptions.target from 'es5' to 'es6' or above in your tsconfig.json`,
+ ),
+ );
+ process.exit(1);
+ }
+ }
+ console.error(e);
+ process.exit(1);
+ }
+};
+
+export const safeRegister = async () => {
+ const { register } = await import('esbuild-register/dist/node');
+ let res: { unregister: () => void };
+ try {
+ res = register({
+ format: 'cjs',
+ loader: 'ts',
+ });
+ } catch {
+ // tsx fallback
+ res = {
+ unregister: () => {},
+ };
+ }
+
+ // has to be outside try catch to be able to run with tsx
+ await assertES5(res.unregister);
+ return res;
+};
+
+export const prepareCheckParams = async (
+ options: {
+ config?: string;
+ dialect?: Dialect;
+ out?: string;
+ },
+ from: 'cli' | 'config',
+): Promise<{ out: string; dialect: Dialect }> => {
+ const config = from === 'config'
+ ? await drizzleConfigFromFile(options.config as string | undefined)
+ : options;
+
+ if (!config.out || !config.dialect) {
+ let text = `Please provide required params for AWS Data API driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('database', config.out));
+ console.log(wrapParam('secretArn', config.dialect));
+ process.exit(1);
+ }
+ return { out: config.out, dialect: config.dialect };
+};
+
+export const prepareDropParams = async (
+ options: {
+ config?: string;
+ out?: string;
+ driver?: Driver;
+ },
+ from: 'cli' | 'config',
+): Promise<{ out: string; bundle: boolean }> => {
+ const config = from === 'config'
+ ? await drizzleConfigFromFile(options.config as string | undefined)
+ : options;
+
+ return { out: config.out || 'drizzle', bundle: config.driver === 'expo' };
+};
+
+export type GenerateConfig = {
+ dialect: Dialect;
+ schema: string | string[];
+ out: string;
+ breakpoints: boolean;
+ name?: string;
+ prefix: Prefix;
+ custom: boolean;
+ bundle: boolean;
+};
+
+export const prepareGenerateConfig = async (
+ options: {
+ config?: string;
+ schema?: string;
+ out?: string;
+ breakpoints?: boolean;
+ custom?: boolean;
+ name?: string;
+ dialect?: Dialect;
+ driver?: Driver;
+ prefix?: Prefix;
+ },
+ from: 'config' | 'cli',
+): Promise => {
+ const config = from === 'config' ? await drizzleConfigFromFile(options.config) : options;
+
+ const { schema, out, breakpoints, dialect, driver } = config;
+
+ if (!schema || !dialect) {
+ console.log(error('Please provide required params:'));
+ console.log(wrapParam('schema', schema));
+ console.log(wrapParam('dialect', dialect));
+ console.log(wrapParam('out', out, true));
+ process.exit(1);
+ }
+
+ const fileNames = prepareFilenames(schema);
+ if (fileNames.length === 0) {
+ render(`[${chalk.blue('i')}] No schema file in ${schema} was found`);
+ process.exit(0);
+ }
+
+ const prefix = ('migrations' in config ? config.migrations?.prefix : options.prefix)
+ || 'index';
+
+ return {
+ dialect: dialect,
+ name: options.name,
+ custom: options.custom || false,
+ prefix,
+ breakpoints: breakpoints || true,
+ schema: schema,
+ out: out || 'drizzle',
+ bundle: driver === 'expo',
+ };
+};
+
+export const flattenDatabaseCredentials = (config: any) => {
+ if ('dbCredentials' in config) {
+ const { dbCredentials, ...rest } = config;
+ return {
+ ...rest,
+ ...dbCredentials,
+ };
+ }
+ return config;
+};
+
+const flattenPull = (config: any) => {
+ if ('dbCredentials' in config) {
+ const { dbCredentials, introspect, ...rest } = config;
+ return {
+ ...rest,
+ ...dbCredentials,
+ casing: introspect?.casing,
+ };
+ }
+ return config;
+};
+
+export const preparePushConfig = async (
+ options: Record,
+ from: 'cli' | 'config',
+): Promise<
+ (
+ | {
+ dialect: 'mysql';
+ credentials: MysqlCredentials;
+ }
+ | {
+ dialect: 'postgresql';
+ credentials: PostgresCredentials;
+ }
+ | {
+ dialect: 'sqlite';
+ credentials: SqliteCredentials;
+ }
+ | {
+ dialect: 'singlestore';
+ credentials: SingleStoreCredentials;
+ }
+ ) & {
+ schemaPath: string | string[];
+ verbose: boolean;
+ strict: boolean;
+ force: boolean;
+ tablesFilter: string[];
+ schemasFilter: string[];
+ }
+> => {
+ const raw = flattenDatabaseCredentials(
+ from === 'config'
+ ? await drizzleConfigFromFile(options.config as string | undefined)
+ : options,
+ );
+
+ raw.verbose ||= options.verbose; // if provided in cli to debug
+ raw.strict ||= options.strict; // if provided in cli only
+
+ const parsed = pushParams.safeParse(raw);
+
+ if (parsed.error) {
+ console.log(error('Please provide required params:'));
+ console.log(wrapParam('dialect', raw.dialect));
+ console.log(wrapParam('schema', raw.schema));
+ process.exit(1);
+ }
+
+ const config = parsed.data;
+
+ const schemaFiles = prepareFilenames(config.schema);
+ if (schemaFiles.length === 0) {
+ render(`[${chalk.blue('i')}] No schema file in ${config.schema} was found`);
+ process.exit(0);
+ }
+
+ const tablesFilterConfig = config.tablesFilter;
+ const tablesFilter = tablesFilterConfig
+ ? typeof tablesFilterConfig === 'string'
+ ? [tablesFilterConfig]
+ : tablesFilterConfig
+ : [];
+
+ const schemasFilterConfig = config.schemaFilter;
+
+ const schemasFilter = schemasFilterConfig
+ ? typeof schemasFilterConfig === 'string'
+ ? [schemasFilterConfig]
+ : schemasFilterConfig
+ : [];
+
+ if (config.extensionsFilters) {
+ if (
+ config.extensionsFilters.includes('postgis')
+ && config.dialect === 'postgresql'
+ ) {
+ tablesFilter.push(
+ ...['!geography_columns', '!geometry_columns', '!spatial_ref_sys'],
+ );
+ }
+ }
+
+ if (config.dialect === 'postgresql') {
+ const parsed = postgresCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesPg(config);
+ process.exit(1);
+ }
+
+ return {
+ dialect: 'postgresql',
+ schemaPath: config.schema,
+ strict: config.strict ?? false,
+ verbose: config.verbose ?? false,
+ force: (options.force as boolean) ?? false,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ };
+ }
+
+ if (config.dialect === 'mysql') {
+ const parsed = mysqlCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesMysql(config);
+ process.exit(1);
+ }
+ return {
+ dialect: 'mysql',
+ schemaPath: config.schema,
+ strict: config.strict ?? false,
+ verbose: config.verbose ?? false,
+ force: (options.force as boolean) ?? false,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ };
+ }
+
+ if (config.dialect === 'singlestore') {
+ const parsed = singlestoreCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesSingleStore(config);
+ process.exit(1);
+ }
+
+ return {
+ dialect: 'singlestore',
+ schemaPath: config.schema,
+ strict: config.strict ?? false,
+ verbose: config.verbose ?? false,
+ force: (options.force as boolean) ?? false,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ };
+ }
+
+ if (config.dialect === 'sqlite') {
+ const parsed = sqliteCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesSqlite(config, 'pull');
+ process.exit(1);
+ }
+ return {
+ dialect: 'sqlite',
+ schemaPath: config.schema,
+ strict: config.strict ?? false,
+ verbose: config.verbose ?? false,
+ force: (options.force as boolean) ?? false,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ };
+ }
+
+ assertUnreachable(config.dialect);
+};
+
+export const preparePullConfig = async (
+ options: Record,
+ from: 'cli' | 'config',
+): Promise<
+ (
+ | {
+ dialect: 'mysql';
+ credentials: MysqlCredentials;
+ }
+ | {
+ dialect: 'postgresql';
+ credentials: PostgresCredentials;
+ }
+ | {
+ dialect: 'sqlite';
+ credentials: SqliteCredentials;
+ }
+ | {
+ dialect: 'singlestore';
+ credentials: SingleStoreCredentials;
+ }
+ ) & {
+ out: string;
+ breakpoints: boolean;
+ casing: Casing;
+ tablesFilter: string[];
+ schemasFilter: string[];
+ prefix: Prefix;
+ }
+> => {
+ const raw = flattenPull(
+ from === 'config'
+ ? await drizzleConfigFromFile(options.config as string | undefined)
+ : options,
+ );
+ const parsed = pullParams.safeParse(raw);
+
+ if (parsed.error) {
+ console.log(error('Please provide required params:'));
+ console.log(wrapParam('dialect', raw.dialect));
+ process.exit(1);
+ }
+
+ const config = parsed.data;
+ const dialect = config.dialect;
+
+ const tablesFilterConfig = config.tablesFilter;
+ const tablesFilter = tablesFilterConfig
+ ? typeof tablesFilterConfig === 'string'
+ ? [tablesFilterConfig]
+ : tablesFilterConfig
+ : [];
+
+ if (config.extensionsFilters) {
+ if (
+ config.extensionsFilters.includes('postgis')
+ && dialect === 'postgresql'
+ ) {
+ tablesFilter.push(
+ ...['!geography_columns', '!geometry_columns', '!spatial_ref_sys'],
+ );
+ }
+ }
+
+ const schemasFilterConfig = config.schemaFilter; // TODO: consistent naming
+ const schemasFilter = schemasFilterConfig
+ ? typeof schemasFilterConfig === 'string'
+ ? [schemasFilterConfig]
+ : schemasFilterConfig
+ : [];
+
+ if (dialect === 'postgresql') {
+ const parsed = postgresCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesPg(config);
+ process.exit(1);
+ }
+
+ return {
+ dialect: 'postgresql',
+ out: config.out,
+ breakpoints: config.breakpoints,
+ casing: config.casing,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ prefix: config.migrations?.prefix || 'index',
+ };
+ }
+
+ if (dialect === 'mysql') {
+ const parsed = mysqlCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesMysql(config);
+ process.exit(1);
+ }
+ return {
+ dialect: 'mysql',
+ out: config.out,
+ breakpoints: config.breakpoints,
+ casing: config.casing,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ prefix: config.migrations?.prefix || 'index',
+ };
+ }
+
+ if (dialect === 'singlestore') {
+ const parsed = singlestoreCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesSingleStore(config);
+ process.exit(1);
+ }
+
+ return {
+ dialect: 'singlestore',
+ out: config.out,
+ breakpoints: config.breakpoints,
+ casing: config.casing,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ prefix: config.migrations?.prefix || 'index',
+ };
+ }
+
+ if (dialect === 'sqlite') {
+ const parsed = sqliteCredentials.safeParse(config);
+ if (!parsed.success) {
+ printIssuesSqlite(config, 'pull');
+ process.exit(1);
+ }
+ return {
+ dialect: 'sqlite',
+ out: config.out,
+ breakpoints: config.breakpoints,
+ casing: config.casing,
+ credentials: parsed.data,
+ tablesFilter,
+ schemasFilter,
+ prefix: config.migrations?.prefix || 'index',
+ };
+ }
+
+ assertUnreachable(dialect);
+};
+
+export const prepareStudioConfig = async (options: Record) => {
+ const params = studioCliParams.parse(options);
+ const config = await drizzleConfigFromFile(params.config);
+ const result = studioConfig.safeParse(config);
+ if (!result.success) {
+ if (!('dialect' in config)) {
+ console.log(outputs.studio.noDialect());
+ }
+ process.exit(1);
+ }
+
+ if (!('dbCredentials' in config)) {
+ console.log(outputs.studio.noCredentials());
+ process.exit(1);
+ }
+ const { host, port } = params;
+ const { dialect, schema } = result.data;
+ const flattened = flattenDatabaseCredentials(config);
+
+ if (dialect === 'postgresql') {
+ const parsed = postgresCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesPg(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ schema,
+ host,
+ port,
+ credentials,
+ };
+ }
+
+ if (dialect === 'mysql') {
+ const parsed = mysqlCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesMysql(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ schema,
+ host,
+ port,
+ credentials,
+ };
+ }
+
+ if (dialect === 'singlestore') {
+ const parsed = singlestoreCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesSingleStore(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ schema,
+ host,
+ port,
+ credentials,
+ };
+ }
+
+ if (dialect === 'sqlite') {
+ const parsed = sqliteCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesSqlite(flattened as Record, 'studio');
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ schema,
+ host,
+ port,
+ credentials,
+ };
+ }
+
+ assertUnreachable(dialect);
+};
+
+export const migrateConfig = object({
+ dialect,
+ out: string().optional().default('drizzle'),
+ migrations: configMigrations,
+});
+
+export const prepareMigrateConfig = async (configPath: string | undefined) => {
+ const config = await drizzleConfigFromFile(configPath);
+ const parsed = migrateConfig.safeParse(config);
+ if (parsed.error) {
+ console.log(error('Please provide required params:'));
+ console.log(wrapParam('dialect', config.dialect));
+ process.exit(1);
+ }
+
+ const { dialect, out } = parsed.data;
+ const { schema, table } = parsed.data.migrations || {};
+ const flattened = flattenDatabaseCredentials(config);
+
+ if (dialect === 'postgresql') {
+ const parsed = postgresCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesPg(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ out,
+ credentials,
+ schema,
+ table,
+ };
+ }
+
+ if (dialect === 'mysql') {
+ const parsed = mysqlCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesMysql(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ out,
+ credentials,
+ schema,
+ table,
+ };
+ }
+
+ if (dialect === 'singlestore') {
+ const parsed = singlestoreCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesSingleStore(flattened as Record);
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ out,
+ credentials,
+ schema,
+ table,
+ };
+ }
+
+ if (dialect === 'sqlite') {
+ const parsed = sqliteCredentials.safeParse(flattened);
+ if (!parsed.success) {
+ printIssuesSqlite(flattened as Record, 'migrate');
+ process.exit(1);
+ }
+ const credentials = parsed.data;
+ return {
+ dialect,
+ out,
+ credentials,
+ schema,
+ table,
+ };
+ }
+
+ assertUnreachable(dialect);
+};
+
+export const drizzleConfigFromFile = async (
+ configPath?: string,
+): Promise => {
+ const prefix = process.env.TEST_CONFIG_PATH_PREFIX || '';
+
+ const defaultTsConfigExists = existsSync(resolve(join(prefix, 'drizzle.config.ts')));
+ const defaultJsConfigExists = existsSync(resolve(join(prefix, 'drizzle.config.js')));
+ const defaultJsonConfigExists = existsSync(
+ join(resolve('drizzle.config.json')),
+ );
+
+ const defaultConfigPath = defaultTsConfigExists
+ ? 'drizzle.config.ts'
+ : defaultJsConfigExists
+ ? 'drizzle.config.js'
+ : 'drizzle.config.json';
+
+ if (!configPath) {
+ console.log(
+ chalk.gray(
+ `No config path provided, using default '${defaultConfigPath}'`,
+ ),
+ );
+ }
+
+ const path: string = resolve(join(prefix, configPath ?? defaultConfigPath));
+
+ if (!existsSync(path)) {
+ console.log(`${path} file does not exist`);
+ process.exit(1);
+ }
+
+ console.log(chalk.grey(`Reading config file '${path}'`));
+ const { unregister } = await safeRegister();
+ const required = require(`${path}`);
+ const content = required.default ?? required;
+ unregister();
+
+ // --- get response and then check by each dialect independently
+ const res = configCommonSchema.safeParse(content);
+ if (!res.success) {
+ if (!('dialect' in content)) {
+ console.log(error("Please specify 'dialect' param in config file"));
+ }
+ process.exit(1);
+ }
+
+ return res.data;
+};
diff --git a/drizzle-kit/src/cli/connections.ts b/drizzle-kit/src/cli/connections.ts
new file mode 100644
index 000000000..3357bf146
--- /dev/null
+++ b/drizzle-kit/src/cli/connections.ts
@@ -0,0 +1,795 @@
+import type { AwsDataApiPgQueryResult, AwsDataApiSessionOptions } from 'drizzle-orm/aws-data-api/pg';
+import type { MigrationConfig } from 'drizzle-orm/migrator';
+import type { PreparedQueryConfig } from 'drizzle-orm/pg-core';
+import fetch from 'node-fetch';
+import ws from 'ws';
+import { assertUnreachable } from '../global';
+import type { ProxyParams } from '../serializer/studio';
+import { type DB, normalisePGliteUrl, normaliseSQLiteUrl, type Proxy, type SQLiteDB, type SqliteProxy } from '../utils';
+import { assertPackages, checkPackage } from './utils';
+import type { MysqlCredentials } from './validations/mysql';
+import { withStyle } from './validations/outputs';
+import type { PostgresCredentials } from './validations/postgres';
+import { SingleStoreCredentials } from './validations/singlestore';
+import type { SqliteCredentials } from './validations/sqlite';
+
+export const preparePostgresDB = async (
+ credentials: PostgresCredentials,
+): Promise<
+ DB & {
+ proxy: Proxy;
+ migrate: (config: string | MigrationConfig) => Promise;
+ }
+> => {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'aws-data-api') {
+ assertPackages('@aws-sdk/client-rds-data');
+ const { RDSDataClient, ExecuteStatementCommand, TypeHint } = await import(
+ '@aws-sdk/client-rds-data'
+ );
+ const { AwsDataApiSession, drizzle } = await import(
+ 'drizzle-orm/aws-data-api/pg'
+ );
+ const { migrate } = await import('drizzle-orm/aws-data-api/pg/migrator');
+ const { PgDialect } = await import('drizzle-orm/pg-core');
+
+ const config: AwsDataApiSessionOptions = {
+ database: credentials.database,
+ resourceArn: credentials.resourceArn,
+ secretArn: credentials.secretArn,
+ };
+ const rdsClient = new RDSDataClient();
+ const session = new AwsDataApiSession(
+ rdsClient,
+ new PgDialect(),
+ undefined,
+ config,
+ undefined,
+ );
+
+ const db = drizzle(rdsClient, config);
+ const migrateFn = async (config: string | MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params: any[]) => {
+ const prepared = session.prepareQuery(
+ { sql, params: params ?? [] },
+ undefined,
+ undefined,
+ false,
+ );
+ const result = await prepared.all();
+ return result as any[];
+ };
+ const proxy = async (params: ProxyParams) => {
+ const prepared = session.prepareQuery<
+ PreparedQueryConfig & {
+ execute: AwsDataApiPgQueryResult;
+ values: AwsDataApiPgQueryResult;
+ }
+ >(
+ {
+ sql: params.sql,
+ params: params.params ?? [],
+ typings: params.typings,
+ },
+ undefined,
+ undefined,
+ params.mode === 'array',
+ );
+ if (params.mode === 'array') {
+ const result = await prepared.values();
+ return result.rows;
+ }
+ const result = await prepared.execute();
+ return result.rows;
+ };
+
+ return {
+ query,
+ proxy,
+ migrate: migrateFn,
+ };
+ }
+
+ if (driver === 'pglite') {
+ assertPackages('@electric-sql/pglite');
+ const { PGlite } = await import('@electric-sql/pglite');
+ const { drizzle } = await import('drizzle-orm/pglite');
+ const { migrate } = await import('drizzle-orm/pglite/migrator');
+
+ const pglite = new PGlite(normalisePGliteUrl(credentials.url));
+ await pglite.waitReady;
+ const drzl = drizzle(pglite);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(drzl, config);
+ };
+
+ const query = async (sql: string, params: any[] = []) => {
+ const result = await pglite.query(sql, params);
+ return result.rows as T[];
+ };
+
+ const proxy = async (params: ProxyParams) => {
+ const preparedParams = preparePGliteParams(params.params);
+ if (
+ params.method === 'values'
+ || params.method === 'get'
+ || params.method === 'all'
+ ) {
+ const result = await pglite.query(params.sql, preparedParams, {
+ rowMode: params.mode,
+ });
+ return result.rows;
+ }
+
+ const result = await pglite.query(params.sql, preparedParams);
+ return result.rows;
+ };
+
+ return { query, proxy, migrate: migrateFn };
+ }
+
+ assertUnreachable(driver);
+ }
+
+ if (await checkPackage('pg')) {
+ console.log(withStyle.info(`Using 'pg' driver for database querying`));
+ const pg = await import('pg');
+ const { drizzle } = await import('drizzle-orm/node-postgres');
+ const { migrate } = await import('drizzle-orm/node-postgres/migrator');
+
+ const ssl = 'ssl' in credentials
+ ? credentials.ssl === 'prefer'
+ || credentials.ssl === 'require'
+ || credentials.ssl === 'allow'
+ ? { rejectUnauthorized: false }
+ : credentials.ssl === 'verify-full'
+ ? {}
+ : credentials.ssl
+ : {};
+
+ const client = 'url' in credentials
+ ? new pg.default.Pool({ connectionString: credentials.url, max: 1 })
+ : new pg.default.Pool({ ...credentials, ssl, max: 1 });
+
+ const db = drizzle(client);
+ const migrateFn = async (config: string | MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params?: any[]) => {
+ const result = await client.query(sql, params ?? []);
+ return result.rows;
+ };
+
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = await client.query({
+ text: params.sql,
+ values: params.params,
+ ...(params.mode === 'array' && { rowMode: 'array' }),
+ });
+ return result.rows;
+ };
+
+ return { query, proxy, migrate: migrateFn };
+ }
+
+ if (await checkPackage('postgres')) {
+ console.log(
+ withStyle.info(`Using 'postgres' driver for database querying`),
+ );
+ const postgres = await import('postgres');
+
+ const { drizzle } = await import('drizzle-orm/postgres-js');
+ const { migrate } = await import('drizzle-orm/postgres-js/migrator');
+
+ const client = 'url' in credentials
+ ? postgres.default(credentials.url, { max: 1 })
+ : postgres.default({ ...credentials, max: 1 });
+
+ const db = drizzle(client);
+ const migrateFn = async (config: string | MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params?: any[]) => {
+ const result = await client.unsafe(sql, params ?? []);
+ return result as any[];
+ };
+
+ const proxy = async (params: ProxyParams) => {
+ if (params.mode === 'object') {
+ return await client.unsafe(params.sql, params.params);
+ }
+ return await client.unsafe(params.sql, params.params).values();
+ };
+
+ return { query, proxy, migrate: migrateFn };
+ }
+
+ if (await checkPackage('@vercel/postgres')) {
+ console.log(
+ withStyle.info(`Using '@vercel/postgres' driver for database querying`),
+ );
+ console.log(
+ withStyle.fullWarning(
+ "'@vercel/postgres' can only connect to remote Neon/Vercel Postgres/Supabase instances through a websocket",
+ ),
+ );
+ const { VercelPool } = await import('@vercel/postgres');
+ const { drizzle } = await import('drizzle-orm/vercel-postgres');
+ const { migrate } = await import('drizzle-orm/vercel-postgres/migrator');
+ const ssl = 'ssl' in credentials
+ ? credentials.ssl === 'prefer'
+ || credentials.ssl === 'require'
+ || credentials.ssl === 'allow'
+ ? { rejectUnauthorized: false }
+ : credentials.ssl === 'verify-full'
+ ? {}
+ : credentials.ssl
+ : {};
+
+ const client = 'url' in credentials
+ ? new VercelPool({ connectionString: credentials.url })
+ : new VercelPool({ ...credentials, ssl });
+
+ await client.connect();
+
+ const db = drizzle(client);
+ const migrateFn = async (config: string | MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params?: any[]) => {
+ const result = await client.query(sql, params ?? []);
+ return result.rows;
+ };
+
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = await client.query({
+ text: params.sql,
+ values: params.params,
+ ...(params.mode === 'array' && { rowMode: 'array' }),
+ });
+ return result.rows;
+ };
+
+ return { query, proxy, migrate: migrateFn };
+ }
+
+ if (await checkPackage('@neondatabase/serverless')) {
+ console.log(
+ withStyle.info(
+ `Using '@neondatabase/serverless' driver for database querying`,
+ ),
+ );
+ console.log(
+ withStyle.fullWarning(
+ "'@neondatabase/serverless' can only connect to remote Neon/Vercel Postgres/Supabase instances through a websocket",
+ ),
+ );
+ const { Pool, neonConfig } = await import('@neondatabase/serverless');
+ const { drizzle } = await import('drizzle-orm/neon-serverless');
+ const { migrate } = await import('drizzle-orm/neon-serverless/migrator');
+
+ const ssl = 'ssl' in credentials
+ ? credentials.ssl === 'prefer'
+ || credentials.ssl === 'require'
+ || credentials.ssl === 'allow'
+ ? { rejectUnauthorized: false }
+ : credentials.ssl === 'verify-full'
+ ? {}
+ : credentials.ssl
+ : {};
+
+ const client = 'url' in credentials
+ ? new Pool({ connectionString: credentials.url, max: 1 })
+ : new Pool({ ...credentials, max: 1, ssl });
+ neonConfig.webSocketConstructor = ws;
+
+ const db = drizzle(client);
+ const migrateFn = async (config: string | MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params?: any[]) => {
+ const result = await client.query(sql, params ?? []);
+ return result.rows;
+ };
+
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = await client.query({
+ text: params.sql,
+ values: params.params,
+ ...(params.mode === 'array' && { rowMode: 'array' }),
+ });
+ return result.rows;
+ };
+
+ return { query, proxy, migrate: migrateFn };
+ }
+
+ console.error(
+ "To connect to Postgres database - please install either of 'pg', 'postgres', '@neondatabase/serverless' or '@vercel/postgres' drivers",
+ );
+ process.exit(1);
+};
+
+const parseMysqlCredentials = (credentials: MysqlCredentials) => {
+ if ('url' in credentials) {
+ const url = credentials.url;
+
+ const connectionUrl = new URL(url);
+ const pathname = connectionUrl.pathname;
+
+ const database = pathname.split('/')[pathname.split('/').length - 1];
+ if (!database) {
+ console.error(
+ 'You should specify a database name in connection string (mysql://USER:PASSWORD@HOST:PORT/DATABASE)',
+ );
+ process.exit(1);
+ }
+ return { database, url };
+ } else {
+ return {
+ database: credentials.database,
+ credentials,
+ };
+ }
+};
+
+export const connectToMySQL = async (
+ it: MysqlCredentials,
+): Promise<{
+ db: DB;
+ proxy: Proxy;
+ database: string;
+ migrate: (config: MigrationConfig) => Promise;
+}> => {
+ const result = parseMysqlCredentials(it);
+
+ if (await checkPackage('mysql2')) {
+ const { createConnection } = await import('mysql2/promise');
+ const { drizzle } = await import('drizzle-orm/mysql2');
+ const { migrate } = await import('drizzle-orm/mysql2/migrator');
+
+ const connection = result.url
+ ? await createConnection(result.url)
+ : await createConnection(result.credentials!); // needed for some reason!
+
+ const db = drizzle(connection);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ await connection.connect();
+ const query: DB['query'] = async (
+ sql: string,
+ params?: any[],
+ ): Promise => {
+ const res = await connection.execute(sql, params);
+ return res[0] as any;
+ };
+
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = await connection.query({
+ sql: params.sql,
+ values: params.params,
+ rowsAsArray: params.mode === 'array',
+ });
+ return result[0] as any[];
+ };
+
+ return {
+ db: { query },
+ proxy,
+ database: result.database,
+ migrate: migrateFn,
+ };
+ }
+
+ if (await checkPackage('@planetscale/database')) {
+ const { connect } = await import('@planetscale/database');
+ const { drizzle } = await import('drizzle-orm/planetscale-serverless');
+ const { migrate } = await import(
+ 'drizzle-orm/planetscale-serverless/migrator'
+ );
+
+ const connection = connect(result);
+
+ const db = drizzle(connection);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ const query = async (sql: string, params?: any[]): Promise => {
+ const res = await connection.execute(sql, params);
+ return res.rows as T[];
+ };
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = params.mode === 'object'
+ ? await connection.execute(params.sql, params.params)
+ : await connection.execute(params.sql, params.params, {
+ as: 'array',
+ });
+ return result.rows;
+ };
+
+ return {
+ db: { query },
+ proxy,
+ database: result.database,
+ migrate: migrateFn,
+ };
+ }
+
+ console.error(
+ "To connect to MySQL database - please install either of 'mysql2' or '@planetscale/database' drivers",
+ );
+ process.exit(1);
+};
+
+const prepareSqliteParams = (params: any[], driver?: string) => {
+ return params.map((param) => {
+ if (
+ param
+ && typeof param === 'object'
+ && 'type' in param
+ && 'value' in param
+ && param.type === 'binary'
+ ) {
+ const value = typeof param.value === 'object'
+ ? JSON.stringify(param.value)
+ : (param.value as string);
+
+ if (driver === 'd1-http') {
+ return value;
+ }
+
+ return Buffer.from(value);
+ }
+ return param;
+ });
+};
+
+const preparePGliteParams = (params: any[]) => {
+ return params.map((param) => {
+ if (
+ param
+ && typeof param === 'object'
+ && 'type' in param
+ && 'value' in param
+ && param.type === 'binary'
+ ) {
+ const value = typeof param.value === 'object'
+ ? JSON.stringify(param.value)
+ : (param.value as string);
+
+ return value;
+ }
+ return param;
+ });
+};
+
+export const connectToSQLite = async (
+ credentials: SqliteCredentials,
+): Promise<
+ & SQLiteDB
+ & SqliteProxy
+ & { migrate: (config: MigrationConfig) => Promise }
+> => {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'turso') {
+ assertPackages('@libsql/client');
+ const { createClient } = await import('@libsql/client');
+ const { drizzle } = await import('drizzle-orm/libsql');
+ const { migrate } = await import('drizzle-orm/libsql/migrator');
+
+ const client = createClient({
+ url: credentials.url,
+ authToken: credentials.authToken,
+ });
+
+ const drzl = drizzle(client);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(drzl, config);
+ };
+
+ const db: SQLiteDB = {
+ query: async (sql: string, params?: any[]) => {
+ const res = await client.execute({ sql, args: params || [] });
+ return res.rows as T[];
+ },
+ run: async (query: string) => {
+ await client.execute(query);
+ },
+ batch: async (
+ queries: { query: string; values?: any[] | undefined }[],
+ ) => {
+ await client.batch(
+ queries.map((it) => ({ sql: it.query, args: it.values ?? [] })),
+ );
+ },
+ };
+ const proxy: SqliteProxy = {
+ proxy: async (params: ProxyParams) => {
+ const preparedParams = prepareSqliteParams(params.params);
+ const result = await client.execute({
+ sql: params.sql,
+ args: preparedParams,
+ });
+
+ if (params.mode === 'array') {
+ return result.rows.map((row) => Object.values(row));
+ } else {
+ return result.rows;
+ }
+ },
+ };
+
+ return { ...db, ...proxy, migrate: migrateFn };
+ } else if (driver === 'd1-http') {
+ const { drizzle } = await import('drizzle-orm/sqlite-proxy');
+ const { migrate } = await import('drizzle-orm/sqlite-proxy/migrator');
+
+ const remoteCallback: Parameters[0] = async (
+ sql,
+ params,
+ method,
+ ) => {
+ const res = await fetch(
+ `https://api.cloudflare.com/client/v4/accounts/${credentials.accountId}/d1/database/${credentials.databaseId}/${
+ method === 'values' ? 'raw' : 'query'
+ }`,
+ {
+ method: 'POST',
+ body: JSON.stringify({ sql, params }),
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${credentials.token}`,
+ },
+ },
+ );
+
+ const data = (await res.json()) as
+ | {
+ success: true;
+ result: {
+ results:
+ | any[]
+ | {
+ columns: string[];
+ rows: any[][];
+ };
+ }[];
+ }
+ | {
+ success: false;
+ errors: { code: number; message: string }[];
+ };
+
+ if (!data.success) {
+ throw new Error(
+ data.errors.map((it) => `${it.code}: ${it.message}`).join('\n'),
+ );
+ }
+
+ const result = data.result[0].results;
+ const rows = Array.isArray(result) ? result : result.rows;
+
+ return {
+ rows,
+ };
+ };
+
+ const drzl = drizzle(remoteCallback);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(
+ drzl,
+ async (queries) => {
+ for (const query of queries) {
+ await remoteCallback(query, [], 'run');
+ }
+ },
+ config,
+ );
+ };
+
+ const db: SQLiteDB = {
+ query: async (sql: string, params?: any[]) => {
+ const res = await remoteCallback(sql, params || [], 'all');
+ return res.rows as T[];
+ },
+ run: async (query: string) => {
+ await remoteCallback(query, [], 'run');
+ },
+ };
+ const proxy: SqliteProxy = {
+ proxy: async (params: ProxyParams) => {
+ const preparedParams = prepareSqliteParams(params.params, 'd1-http');
+ const result = await remoteCallback(
+ params.sql,
+ preparedParams,
+ params.mode === 'array' ? 'values' : 'all',
+ );
+
+ return result.rows;
+ },
+ };
+ return { ...db, ...proxy, migrate: migrateFn };
+ } else {
+ assertUnreachable(driver);
+ }
+ }
+
+ if (await checkPackage('@libsql/client')) {
+ const { createClient } = await import('@libsql/client');
+ const { drizzle } = await import('drizzle-orm/libsql');
+ const { migrate } = await import('drizzle-orm/libsql/migrator');
+
+ const client = createClient({
+ url: normaliseSQLiteUrl(credentials.url, 'libsql'),
+ });
+ const drzl = drizzle(client);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(drzl, config);
+ };
+
+ const db: SQLiteDB = {
+ query: async (sql: string, params?: any[]) => {
+ const res = await client.execute({ sql, args: params || [] });
+ return res.rows as T[];
+ },
+ run: async (query: string) => {
+ await client.execute(query);
+ },
+ };
+
+ const proxy: SqliteProxy = {
+ proxy: async (params: ProxyParams) => {
+ const preparedParams = prepareSqliteParams(params.params);
+ const result = await client.execute({
+ sql: params.sql,
+ args: preparedParams,
+ });
+
+ if (params.mode === 'array') {
+ return result.rows.map((row) => Object.values(row));
+ } else {
+ return result.rows;
+ }
+ },
+ };
+
+ return { ...db, ...proxy, migrate: migrateFn };
+ }
+
+ if (await checkPackage('better-sqlite3')) {
+ const { default: Database } = await import('better-sqlite3');
+ const { drizzle } = await import('drizzle-orm/better-sqlite3');
+ const { migrate } = await import('drizzle-orm/better-sqlite3/migrator');
+
+ const sqlite = new Database(
+ normaliseSQLiteUrl(credentials.url, 'better-sqlite'),
+ );
+ const drzl = drizzle(sqlite);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(drzl, config);
+ };
+
+ const db: SQLiteDB = {
+ query: async (sql: string, params: any[] = []) => {
+ return sqlite.prepare(sql).bind(params).all() as T[];
+ },
+ run: async (query: string) => {
+ sqlite.prepare(query).run();
+ },
+ };
+
+ const proxy: SqliteProxy = {
+ proxy: async (params: ProxyParams) => {
+ const preparedParams = prepareSqliteParams(params.params);
+ if (
+ params.method === 'values'
+ || params.method === 'get'
+ || params.method === 'all'
+ ) {
+ return sqlite
+ .prepare(params.sql)
+ .raw(params.mode === 'array')
+ .all(preparedParams);
+ }
+
+ return sqlite.prepare(params.sql).run(preparedParams);
+ },
+ };
+ return { ...db, ...proxy, migrate: migrateFn };
+ }
+ console.log(
+ "Please install either 'better-sqlite3' or '@libsql/client' for Drizzle Kit to connect to SQLite databases",
+ );
+ process.exit(1);
+};
+
+const parseSingleStoreCredentials = (credentials: SingleStoreCredentials) => {
+ if ('url' in credentials) {
+ const url = credentials.url;
+
+ const connectionUrl = new URL(url);
+ const pathname = connectionUrl.pathname;
+
+ const database = pathname.split('/')[pathname.split('/').length - 1];
+ if (!database) {
+ console.error(
+ 'You should specify a database name in connection string (singlestore://USER:PASSWORD@HOST:PORT/DATABASE)',
+ );
+ process.exit(1);
+ }
+ return { database, url };
+ } else {
+ return {
+ database: credentials.database,
+ credentials,
+ };
+ }
+};
+
+export const connectToSingleStore = async (
+ it: SingleStoreCredentials,
+): Promise<{
+ db: DB;
+ proxy: Proxy;
+ database: string;
+ migrate: (config: MigrationConfig) => Promise;
+}> => {
+ const result = parseSingleStoreCredentials(it);
+
+ if (await checkPackage('singlestore')) {
+ const { createConnection } = await import('mysql2/promise');
+ const { drizzle } = await import('drizzle-orm/singlestore');
+ const { migrate } = await import('drizzle-orm/singlestore/migrator');
+
+ const connection = result.url
+ ? await createConnection(result.url)
+ : await createConnection(result.credentials!); // needed for some reason!
+
+ const db = drizzle(connection);
+ const migrateFn = async (config: MigrationConfig) => {
+ return migrate(db, config);
+ };
+
+ await connection.connect();
+ const query: DB['query'] = async (
+ sql: string,
+ params?: any[],
+ ): Promise => {
+ const res = await connection.execute(sql, params);
+ return res[0] as any;
+ };
+
+ const proxy: Proxy = async (params: ProxyParams) => {
+ const result = await connection.query({
+ sql: params.sql,
+ values: params.params,
+ rowsAsArray: params.mode === 'array',
+ });
+ return result[0] as any[];
+ };
+
+ return {
+ db: { query },
+ proxy,
+ database: result.database,
+ migrate: migrateFn,
+ };
+ }
+
+ console.error(
+ "To connect to SingleStore database - please install 'mysql2' drivers",
+ );
+ process.exit(1);
+};
diff --git a/drizzle-kit/src/cli/index.ts b/drizzle-kit/src/cli/index.ts
new file mode 100644
index 000000000..86bffdf3d
--- /dev/null
+++ b/drizzle-kit/src/cli/index.ts
@@ -0,0 +1,48 @@
+import { command, run } from '@drizzle-team/brocli';
+import chalk from 'chalk';
+import { check, drop, generate, migrate, pull, push, studio, up } from './schema';
+import { ormCoreVersions } from './utils';
+
+const version = async () => {
+ const { npmVersion } = await ormCoreVersions();
+ const ormVersion = npmVersion ? `drizzle-orm: v${npmVersion}` : '';
+ const envVersion = process.env.DRIZZLE_KIT_VERSION;
+ const kitVersion = envVersion ? `v${envVersion}` : '--';
+ const versions = `drizzle-kit: ${kitVersion}\n${ormVersion}`;
+ console.log(chalk.gray(versions), '\n');
+};
+
+const legacyCommand = (name: string, newName: string) => {
+ return command({
+ name,
+ hidden: true,
+ handler: () => {
+ console.log(
+ `This command is deprecated, please use updated '${newName}' command (see https://orm.drizzle.team/kit-docs/upgrade-21#how-to-migrate-to-0210)`,
+ );
+ },
+ });
+};
+
+const legacy = [
+ legacyCommand('generate:pg', 'generate'),
+ legacyCommand('generate:mysql', 'generate'),
+ legacyCommand('generate:sqlite', 'generate'),
+ legacyCommand('push:pg', 'push'),
+ legacyCommand('push:mysql', 'push'),
+ legacyCommand('push:sqlite', 'push'),
+ legacyCommand('introspect:pg', 'introspect'),
+ legacyCommand('introspect:mysql', 'introspect'),
+ legacyCommand('introspect:sqlite', 'introspect'),
+ legacyCommand('up:pg', 'up'),
+ legacyCommand('up:mysql', 'up'),
+ legacyCommand('up:sqlite', 'up'),
+ legacyCommand('check:pg', 'check'),
+ legacyCommand('check:mysql', 'check'),
+ legacyCommand('check:sqlite', 'check'),
+];
+
+run([generate, migrate, pull, push, studio, up, check, drop, ...legacy], {
+ name: 'drizzle-kit',
+ version: version,
+});
diff --git a/drizzle-kit/src/cli/schema.ts b/drizzle-kit/src/cli/schema.ts
new file mode 100644
index 000000000..b2a6dbb3a
--- /dev/null
+++ b/drizzle-kit/src/cli/schema.ts
@@ -0,0 +1,689 @@
+import chalk from 'chalk';
+import { checkHandler } from './commands/check';
+import { assertOrmCoreVersion, assertPackages, assertStudioNodeVersion, ormVersionGt } from './utils';
+import '../@types/utils';
+import { assertUnreachable } from '../global';
+import { type Setup } from '../serializer/studio';
+import { assertV1OutFolder } from '../utils';
+import { dropMigration } from './commands/drop';
+import { upMysqlHandler } from './commands/mysqlUp';
+import { upPgHandler } from './commands/pgUp';
+import { upSqliteHandler } from './commands/sqliteUp';
+import {
+ prepareCheckParams,
+ prepareDropParams,
+ prepareGenerateConfig,
+ prepareMigrateConfig,
+ preparePullConfig,
+ preparePushConfig,
+ prepareStudioConfig,
+} from './commands/utils';
+import { assertCollisions, drivers, prefixes } from './validations/common';
+import { withStyle } from './validations/outputs';
+import 'dotenv/config';
+import { boolean, command, number, string } from '@drizzle-team/brocli';
+import { mkdirSync } from 'fs';
+import { renderWithTask } from 'hanji';
+import { dialects } from 'src/schemaValidator';
+import { assertUnreachable } from '../global';
+import { drizzleForSingleStore, prepareSingleStoreSchema, type Setup } from '../serializer/studio';
+import { certs } from '../utils/certs';
+import { upSinglestoreHandler } from './commands/singlestoreUp';
+import { grey, MigrateProgress } from './views';
+
+const optionDialect = string('dialect')
+ .enum(...dialects)
+ .desc(`Database dialect: 'postgresql', 'mysql', 'sqlite' or 'singlestore'`);
+const optionOut = string().desc("Output folder, 'drizzle' by default");
+const optionConfig = string().desc('Path to drizzle config file');
+const optionBreakpoints = boolean().desc(
+ `Prepare SQL statements with breakpoints`,
+);
+
+const optionDriver = string()
+ .enum(...drivers)
+ .desc('Database driver');
+
+export const generate = command({
+ name: 'generate',
+ options: {
+ config: optionConfig,
+ dialect: optionDialect,
+ driver: optionDriver,
+ schema: string().desc('Path to a schema file or folder'),
+ out: optionOut,
+ name: string().desc('Migration file name'),
+ breakpoints: optionBreakpoints,
+ custom: boolean()
+ .desc('Prepare empty migration file for custom SQL')
+ .default(false),
+ prefix: string()
+ .enum(...prefixes)
+ .default('index'),
+ },
+ transform: async (opts) => {
+ const from = assertCollisions(
+ 'generate',
+ opts,
+ ['prefix', 'name', 'custom'],
+ ['driver', 'breakpoints', 'schema', 'out', 'dialect'],
+ );
+ return prepareGenerateConfig(opts, from);
+ },
+ handler: async (opts) => {
+ await assertOrmCoreVersion();
+ await assertPackages('drizzle-orm');
+
+ // const parsed = cliConfigGenerate.parse(opts);
+
+ const {
+ prepareAndMigratePg,
+ prepareAndMigrateMysql,
+ prepareAndMigrateSqlite,
+ prepareAndMigrateSingleStore,
+ } = await import('./commands/migrate');
+
+ const dialect = opts.dialect;
+ if (dialect === 'postgresql') {
+ await prepareAndMigratePg(opts);
+ } else if (dialect === 'mysql') {
+ await prepareAndMigrateMysql(opts);
+ } else if (dialect === 'sqlite') {
+ await prepareAndMigrateSqlite(opts);
+ } else if (dialect === 'singlestore') {
+ await prepareAndMigrateSqlite(opts);
+ } else {
+ assertUnreachable(dialect);
+ }
+ },
+});
+
+export const migrate = command({
+ name: 'migrate',
+ options: {
+ config: optionConfig,
+ },
+ transform: async (opts) => {
+ return await prepareMigrateConfig(opts.config);
+ },
+ handler: async (opts) => {
+ await assertOrmCoreVersion();
+ await assertPackages('drizzle-orm');
+
+ const { dialect, schema, table, out, credentials } = opts;
+ try {
+ if (dialect === 'postgresql') {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'aws-data-api') {
+ if (!(await ormVersionGt('0.30.10'))) {
+ console.log(
+ "To use 'aws-data-api' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else if (driver === 'pglite') {
+ if (!(await ormVersionGt('0.30.6'))) {
+ console.log(
+ "To use 'pglite' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else {
+ assertUnreachable(driver);
+ }
+ }
+ const { preparePostgresDB } = await import('./connections');
+ const { migrate } = await preparePostgresDB(credentials);
+ await renderWithTask(
+ new MigrateProgress(),
+ migrate({
+ migrationsFolder: out,
+ migrationsTable: table,
+ migrationsSchema: schema,
+ }),
+ );
+ } else if (dialect === 'mysql') {
+ const { connectToMySQL } = await import('./connections');
+ const { migrate } = await connectToMySQL(credentials);
+ await renderWithTask(
+ new MigrateProgress(),
+ migrate({
+ migrationsFolder: out,
+ migrationsTable: table,
+ migrationsSchema: schema,
+ }),
+ );
+ } else if (dialect === 'singlestore') {
+ const { connectToSingleStore } = await import('./connections');
+ const { migrate } = await connectToSingleStore(credentials);
+ await renderWithTask(
+ new MigrateProgress(),
+ migrate({
+ migrationsFolder: out,
+ migrationsTable: table,
+ migrationsSchema: schema,
+ }),
+ );
+ } else if (dialect === 'sqlite') {
+ const { connectToSQLite } = await import('./connections');
+ const { migrate } = await connectToSQLite(credentials);
+ await renderWithTask(
+ new MigrateProgress(),
+ migrate({
+ migrationsFolder: opts.out,
+ migrationsTable: table,
+ migrationsSchema: schema,
+ }),
+ );
+ } else {
+ assertUnreachable(dialect);
+ }
+ } catch (e) {
+ console.error(e);
+ process.exit(1);
+ }
+
+ process.exit(0);
+ },
+});
+
+const optionsFilters = {
+ tablesFilter: string().desc('Table name filters'),
+ schemaFilters: string().desc('Schema name filters'),
+ extensionsFilters: string().desc(
+ '`Database extensions internal database filters',
+ ),
+} as const;
+
+const optionsDatabaseCredentials = {
+ url: string().desc('Database connection URL'),
+ host: string().desc('Database host'),
+ port: string().desc('Database port'),
+ user: string().desc('Database user'),
+ password: string().desc('Database password'),
+ database: string().desc('Database name'),
+ ssl: string().desc('ssl mode'),
+ // Turso
+ authToken: string('auth-token').desc('Database auth token [Turso]'),
+ // specific cases
+ driver: optionDriver,
+} as const;
+
+export const push = command({
+ name: 'push',
+ options: {
+ config: optionConfig,
+ dialect: optionDialect,
+ schema: string().desc('Path to a schema file or folder'),
+ ...optionsFilters,
+ ...optionsDatabaseCredentials,
+ verbose: boolean()
+ .desc('Print all statements for each push')
+ .default(false),
+ strict: boolean().desc('Always ask for confirmation').default(false),
+ force: boolean()
+ .desc(
+ 'Auto-approve all data loss statements. Note: Data loss statements may truncate your tables and data',
+ )
+ .default(false),
+ },
+ transform: async (opts) => {
+ const from = assertCollisions(
+ 'push',
+ opts,
+ ['force', 'verbose', 'strict'],
+ [
+ 'schema',
+ 'dialect',
+ 'driver',
+ 'url',
+ 'host',
+ 'port',
+ 'user',
+ 'password',
+ 'database',
+ 'ssl',
+ 'authToken',
+ 'schemaFilters',
+ 'extensionsFilters',
+ 'tablesFilter',
+ ],
+ );
+
+ return preparePushConfig(opts, from);
+ },
+ handler: async (config) => {
+ await assertPackages('drizzle-orm');
+ await assertOrmCoreVersion();
+
+ const {
+ dialect,
+ schemaPath,
+ strict,
+ verbose,
+ credentials,
+ tablesFilter,
+ schemasFilter,
+ force,
+ } = config;
+
+ try {
+ if (dialect === 'mysql') {
+ const { mysqlPush } = await import('./commands/push');
+ await mysqlPush(
+ schemaPath,
+ credentials,
+ tablesFilter,
+ strict,
+ verbose,
+ force,
+ );
+ } else if (dialect === 'postgresql') {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'aws-data-api') {
+ if (!(await ormVersionGt('0.30.10'))) {
+ console.log(
+ "To use 'aws-data-api' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else if (driver === 'pglite') {
+ if (!(await ormVersionGt('0.30.6'))) {
+ console.log(
+ "To use 'pglite' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else {
+ assertUnreachable(driver);
+ }
+ }
+
+ const { pgPush } = await import('./commands/push');
+ await pgPush(
+ schemaPath,
+ verbose,
+ strict,
+ credentials,
+ tablesFilter,
+ schemasFilter,
+ force,
+ );
+ } else if (dialect === 'sqlite') {
+ const { sqlitePush } = await import('./commands/push');
+ await sqlitePush(
+ schemaPath,
+ verbose,
+ strict,
+ credentials,
+ tablesFilter,
+ force,
+ );
+ } else if (dialect === 'singlestore') {
+ const { singlestorePush } = await import('./commands/push');
+ await singlestorePush(
+ schemaPath,
+ credentials,
+ tablesFilter,
+ strict,
+ verbose,
+ force,
+ );
+ } else {
+ assertUnreachable(dialect);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ process.exit(0);
+ },
+});
+
+export const check = command({
+ name: 'check',
+ options: {
+ config: optionConfig,
+ dialect: optionDialect,
+ out: optionOut,
+ },
+ transform: async (opts) => {
+ const from = assertCollisions('check', opts, [], ['dialect', 'out']);
+ return prepareCheckParams(opts, from);
+ },
+ handler: async (config) => {
+ await assertOrmCoreVersion();
+
+ const { out, dialect } = config;
+ checkHandler(out, dialect);
+ console.log("Everything's fine 🐶🔥");
+ },
+});
+
+export const up = command({
+ name: 'up',
+ options: {
+ config: optionConfig,
+ dialect: optionDialect,
+ out: optionOut,
+ },
+ transform: async (opts) => {
+ const from = assertCollisions('check', opts, [], ['dialect', 'out']);
+ return prepareCheckParams(opts, from);
+ },
+ handler: async (config) => {
+ await assertOrmCoreVersion();
+
+ const { out, dialect } = config;
+ await assertPackages('drizzle-orm');
+
+ if (dialect === 'postgresql') {
+ upPgHandler(out);
+ }
+
+ if (dialect === 'mysql') {
+ upMysqlHandler(out);
+ }
+
+ if (dialect === 'sqlite') {
+ upSqliteHandler(out);
+ }
+
+ if (dialect === 'singlestore') {
+ upSinglestoreHandler(out);
+ }
+ },
+});
+
+export const pull = command({
+ name: 'introspect',
+ aliases: ['pull'],
+ options: {
+ config: optionConfig,
+ dialect: optionDialect,
+ out: optionOut,
+ breakpoints: optionBreakpoints,
+ casing: string('introspect-casing').enum('camel', 'preserve'),
+ ...optionsFilters,
+ ...optionsDatabaseCredentials,
+ },
+ transform: async (opts) => {
+ const from = assertCollisions(
+ 'introspect',
+ opts,
+ [],
+ [
+ 'dialect',
+ 'driver',
+ 'out',
+ 'url',
+ 'host',
+ 'port',
+ 'user',
+ 'password',
+ 'database',
+ 'ssl',
+ 'authToken',
+ 'casing',
+ 'breakpoints',
+ 'tablesFilter',
+ 'schemaFilters',
+ 'extensionsFilters',
+ ],
+ );
+ return preparePullConfig(opts, from);
+ },
+ handler: async (config) => {
+ await assertPackages('drizzle-orm');
+ await assertOrmCoreVersion();
+
+ const {
+ dialect,
+ credentials,
+ out,
+ casing,
+ breakpoints,
+ tablesFilter,
+ schemasFilter,
+ prefix,
+ } = config;
+ mkdirSync(out, { recursive: true });
+
+ console.log(
+ grey(
+ `Pulling from [${
+ schemasFilter
+ .map((it) => `'${it}'`)
+ .join(', ')
+ }] list of schemas`,
+ ),
+ );
+ console.log();
+
+ try {
+ if (dialect === 'postgresql') {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'aws-data-api') {
+ if (!(await ormVersionGt('0.30.10'))) {
+ console.log(
+ "To use 'aws-data-api' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else if (driver === 'pglite') {
+ if (!(await ormVersionGt('0.30.6'))) {
+ console.log(
+ "To use 'pglite' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else {
+ assertUnreachable(driver);
+ }
+ }
+
+ const { introspectPostgres } = await import('./commands/introspect');
+ await introspectPostgres(
+ casing,
+ out,
+ breakpoints,
+ credentials,
+ tablesFilter,
+ schemasFilter,
+ prefix,
+ );
+ } else if (dialect === 'mysql') {
+ const { introspectMysql } = await import('./commands/introspect');
+ await introspectMysql(
+ casing,
+ out,
+ breakpoints,
+ credentials,
+ tablesFilter,
+ prefix,
+ );
+ } else if (dialect === 'sqlite') {
+ const { introspectSqlite } = await import('./commands/introspect');
+ await introspectSqlite(
+ casing,
+ out,
+ breakpoints,
+ credentials,
+ tablesFilter,
+ prefix,
+ );
+ } else if (dialect === 'singlestore') {
+ const { introspectSingleStore } = await import('./commands/introspect');
+ await introspectSingleStore(
+ casing,
+ out,
+ breakpoints,
+ credentials,
+ tablesFilter,
+ prefix,
+ );
+ } else {
+ assertUnreachable(dialect);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ process.exit(0);
+ },
+});
+
+export const drop = command({
+ name: 'drop',
+ options: {
+ config: optionConfig,
+ out: optionOut,
+ driver: optionDriver,
+ },
+ transform: async (opts) => {
+ const from = assertCollisions('check', opts, [], ['driver', 'out']);
+ return prepareDropParams(opts, from);
+ },
+ handler: async (config) => {
+ await assertOrmCoreVersion();
+
+ assertV1OutFolder(config.out);
+ await dropMigration(config);
+ },
+});
+
+export const studio = command({
+ name: 'studio',
+ options: {
+ config: optionConfig,
+ port: number().desc('Custom port for drizzle studio [default=4983]'),
+ host: string().desc('Custom host for drizzle studio [default=0.0.0.0]'),
+ verbose: boolean()
+ .default(false)
+ .desc('Print all stataments that are executed by Studio'),
+ },
+ handler: async (opts) => {
+ await assertOrmCoreVersion();
+ await assertPackages('drizzle-orm');
+
+ assertStudioNodeVersion();
+
+ const {
+ dialect,
+ schema: schemaPath,
+ port,
+ host,
+ credentials,
+ } = await prepareStudioConfig(opts);
+
+ const {
+ drizzleForPostgres,
+ preparePgSchema,
+ prepareMySqlSchema,
+ drizzleForMySQL,
+ prepareSQLiteSchema,
+ drizzleForSQLite,
+ prepareSingleStoreSchema,
+ drizzleForSingleStore,
+ } = await import('../serializer/studio');
+
+ let setup: Setup;
+ try {
+ if (dialect === 'postgresql') {
+ if ('driver' in credentials) {
+ const { driver } = credentials;
+ if (driver === 'aws-data-api') {
+ if (!(await ormVersionGt('0.30.10'))) {
+ console.log(
+ "To use 'aws-data-api' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else if (driver === 'pglite') {
+ if (!(await ormVersionGt('0.30.6'))) {
+ console.log(
+ "To use 'pglite' driver - please update drizzle-orm to the latest version",
+ );
+ process.exit(1);
+ }
+ } else {
+ assertUnreachable(driver);
+ }
+ }
+
+ const { schema, relations, files } = schemaPath
+ ? await preparePgSchema(schemaPath)
+ : { schema: {}, relations: {}, files: [] };
+ setup = await drizzleForPostgres(credentials, schema, relations, files);
+ } else if (dialect === 'mysql') {
+ const { schema, relations, files } = schemaPath
+ ? await prepareMySqlSchema(schemaPath)
+ : { schema: {}, relations: {}, files: [] };
+ setup = await drizzleForMySQL(credentials, schema, relations, files);
+ } else if (dialect === 'sqlite') {
+ const { schema, relations, files } = schemaPath
+ ? await prepareSQLiteSchema(schemaPath)
+ : { schema: {}, relations: {}, files: [] };
+ setup = await drizzleForSQLite(credentials, schema, relations, files);
+ } else if (dialect === 'singlestore') {
+ const { schema, relations, files } = schemaPath
+ ? await prepareSingleStoreSchema(schemaPath)
+ : { schema: {}, relations: {}, files: [] };
+ setup = await drizzleForSingleStore(credentials, schema, relations, files);
+ } else {
+ assertUnreachable(dialect);
+ }
+
+ const { prepareServer } = await import('../serializer/studio');
+
+ const server = await prepareServer(setup);
+
+ console.log();
+ console.log(
+ withStyle.fullWarning(
+ 'Drizzle Studio is currently in Beta. If you find anything that is not working as expected or should be improved, feel free to create an issue on GitHub: https://github.com/drizzle-team/drizzle-kit-mirror/issues/new or write to us on Discord: https://discord.gg/WcRKz2FFxN',
+ ),
+ );
+
+ const { key, cert } = (await certs()) || {};
+ server.start({
+ host,
+ port,
+ key,
+ cert,
+ cb: (err, address) => {
+ if (err) {
+ console.error(err);
+ } else {
+ const queryParams: { port?: number; host?: string } = {};
+ if (port !== 4983) {
+ queryParams.port = port;
+ }
+
+ if (host !== '127.0.0.1') {
+ queryParams.host = host;
+ }
+
+ const queryString = Object.keys(queryParams)
+ .map((key: keyof { port?: number; host?: string }) => {
+ return `${key}=${queryParams[key]}`;
+ })
+ .join('&');
+
+ console.log(
+ `\nDrizzle Studio is up and running on ${
+ chalk.blue(
+ `https://local.drizzle.studio${queryString ? `?${queryString}` : ''}`,
+ )
+ }`,
+ );
+ }
+ },
+ });
+ } catch (e) {
+ console.error(e);
+ process.exit(0);
+ }
+ },
+});
diff --git a/drizzle-kit/src/cli/selector-ui.ts b/drizzle-kit/src/cli/selector-ui.ts
new file mode 100644
index 000000000..f384831d0
--- /dev/null
+++ b/drizzle-kit/src/cli/selector-ui.ts
@@ -0,0 +1,38 @@
+import chalk from 'chalk';
+import { Prompt, SelectState } from 'hanji';
+
+export class Select extends Prompt<{ index: number; value: string }> {
+ private readonly data: SelectState<{ label: string; value: string }>;
+
+ constructor(items: string[]) {
+ super();
+ this.on('attach', (terminal) => terminal.toggleCursor('hide'));
+ this.on('detach', (terminal) => terminal.toggleCursor('show'));
+
+ this.data = new SelectState(
+ items.map((it) => ({ label: it, value: `${it}-value` })),
+ );
+ this.data.bind(this);
+ }
+
+ render(status: 'idle' | 'submitted' | 'aborted'): string {
+ if (status === 'submitted' || status === 'aborted') return '';
+
+ let text = ``;
+ this.data.items.forEach((it, idx) => {
+ text += idx === this.data.selectedIdx
+ ? `${chalk.green('❯ ' + it.label)}`
+ : ` ${it.label}`;
+ text += idx != this.data.items.length - 1 ? '\n' : '';
+ });
+
+ return text;
+ }
+
+ result() {
+ return {
+ index: this.data.selectedIdx,
+ value: this.data.items[this.data.selectedIdx]!.value!,
+ };
+ }
+}
diff --git a/drizzle-kit/src/cli/utils.ts b/drizzle-kit/src/cli/utils.ts
new file mode 100644
index 000000000..f7e7a2ae9
--- /dev/null
+++ b/drizzle-kit/src/cli/utils.ts
@@ -0,0 +1,112 @@
+import semver from 'semver';
+import { err, warning } from './views';
+
+export const assertExists = (it?: any) => {
+ if (!it) throw new Error();
+};
+
+export const ormVersionGt = async (version: string) => {
+ const { npmVersion } = await import('drizzle-orm/version');
+ if (!semver.gte(npmVersion, version)) {
+ return false;
+ }
+ return true;
+};
+
+export const assertStudioNodeVersion = () => {
+ if (semver.gte(process.version, '18.0.0')) return;
+
+ err('Drizzle Studio requires NodeJS v18 or above');
+ process.exit(1);
+};
+
+export const checkPackage = async (it: string) => {
+ try {
+ await import(it);
+ return true;
+ } catch (e) {
+ return false;
+ }
+};
+
+export const assertPackages = async (...pkgs: string[]) => {
+ try {
+ for (let i = 0; i < pkgs.length; i++) {
+ const it = pkgs[i];
+ await import(it);
+ }
+ } catch (e) {
+ err(
+ `please install required packages: ${
+ pkgs
+ .map((it) => `'${it}'`)
+ .join(' ')
+ }`,
+ );
+ process.exit(1);
+ }
+};
+
+// ex: either pg or postgres are needed
+export const assertEitherPackage = async (
+ ...pkgs: string[]
+): Promise => {
+ const availables = [] as string[];
+ for (let i = 0; i < pkgs.length; i++) {
+ try {
+ const it = pkgs[i];
+ await import(it);
+ availables.push(it);
+ } catch (e) {}
+ }
+
+ if (availables.length > 0) {
+ return availables;
+ }
+
+ err(
+ `Please install one of those packages are needed: ${
+ pkgs
+ .map((it) => `'${it}'`)
+ .join(' or ')
+ }`,
+ );
+ process.exit(1);
+};
+
+const requiredApiVersion = 7;
+export const assertOrmCoreVersion = async () => {
+ try {
+ const { compatibilityVersion } = await import('drizzle-orm/version');
+
+ await import('drizzle-orm/relations');
+
+ if (compatibilityVersion && compatibilityVersion === requiredApiVersion) {
+ return;
+ }
+
+ if (!compatibilityVersion || compatibilityVersion < requiredApiVersion) {
+ console.log(
+ 'This version of drizzle-kit requires newer version of drizzle-orm\nPlease update drizzle-orm package to the latest version 👍',
+ );
+ } else {
+ console.log(
+ 'This version of drizzle-kit is outdated\nPlease update drizzle-kit package to the latest version 👍',
+ );
+ }
+ } catch (e) {
+ console.log('Please install latest version of drizzle-orm');
+ }
+ process.exit(1);
+};
+
+export const ormCoreVersions = async () => {
+ try {
+ const { compatibilityVersion, npmVersion } = await import(
+ 'drizzle-orm/version'
+ );
+ return { compatibilityVersion, npmVersion };
+ } catch (e) {
+ return {};
+ }
+};
diff --git a/drizzle-kit/src/cli/validations/cli.ts b/drizzle-kit/src/cli/validations/cli.ts
new file mode 100644
index 000000000..c4bbbe530
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/cli.ts
@@ -0,0 +1,62 @@
+import { boolean, intersection, literal, object, string, TypeOf, union } from 'zod';
+import { dialect } from '../../schemaValidator';
+import { casing, prefix } from './common';
+
+export const cliConfigGenerate = object({
+ dialect: dialect.optional(),
+ schema: union([string(), string().array()]).optional(),
+ out: string().optional().default('./drizzle'),
+ config: string().optional(),
+ name: string().optional(),
+ prefix: prefix.optional(),
+ breakpoints: boolean().optional().default(true),
+ custom: boolean().optional().default(false),
+}).strict();
+
+export type CliConfigGenerate = TypeOf;
+
+export const pushParams = object({
+ dialect: dialect,
+ schema: union([string(), string().array()]),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()])
+ .optional()
+ .default(['public']),
+ extensionsFilters: literal('postgis').array().optional(),
+ verbose: boolean().optional(),
+ strict: boolean().optional(),
+}).passthrough();
+
+export type PushParams = TypeOf;
+
+export const pullParams = object({
+ config: string().optional(),
+ dialect: dialect,
+ out: string().optional().default('drizzle'),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()])
+ .optional()
+ .default(['public']),
+ extensionsFilters: literal('postgis').array().optional(),
+ casing,
+ breakpoints: boolean().optional().default(true),
+ migrations: object({
+ prefix: prefix.optional().default('index'),
+ }).optional(),
+}).passthrough();
+
+export type PullParams = TypeOf;
+
+export const configCheck = object({
+ dialect: dialect.optional(),
+ out: string().optional(),
+});
+
+export const cliConfigCheck = intersection(
+ object({
+ config: string().optional(),
+ }),
+ configCheck,
+);
+
+export type CliCheckConfig = TypeOf;
diff --git a/drizzle-kit/src/cli/validations/common.ts b/drizzle-kit/src/cli/validations/common.ts
new file mode 100644
index 000000000..a7307f4d6
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/common.ts
@@ -0,0 +1,186 @@
+import chalk from 'chalk';
+import { UnionToIntersection } from 'hono/utils/types';
+import { any, boolean, enum as enum_, literal, object, string, TypeOf, union } from 'zod';
+import { dialect } from '../../schemaValidator';
+import { outputs } from './outputs';
+
+export type Commands =
+ | 'introspect'
+ | 'generate'
+ | 'check'
+ | 'up'
+ | 'drop'
+ | 'push';
+
+type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never;
+type IsUnion = [T] extends [UnionToIntersection] ? false : true;
+type LastTupleElement = TArr extends [
+ ...start: infer _,
+ end: infer Last,
+] ? Last
+ : never;
+
+export type UniqueArrayOfUnion = Exclude<
+ TUnion,
+ TArray[number]
+> extends never ? [TUnion]
+ : [...TArray, Exclude];
+
+export const assertCollisions = <
+ T extends Record,
+ TKeys extends (keyof T)[],
+ TRemainingKeys extends Exclude[],
+ Exhaustive extends TRemainingKeys,
+ UNIQ extends UniqueArrayOfUnion,
+>(
+ command: Commands,
+ options: T,
+ whitelist: Exclude,
+ remainingKeys: UniqueArrayOfUnion,
+): IsUnion> extends false ? 'cli' | 'config' : TKeys => {
+ const { config, ...rest } = options;
+
+ let atLeastOneParam = false;
+ for (const key of Object.keys(rest)) {
+ if (whitelist.includes(key)) continue;
+
+ atLeastOneParam = atLeastOneParam || rest[key] !== undefined;
+ }
+
+ if (!config && atLeastOneParam) {
+ return 'cli' as any;
+ }
+
+ if (!atLeastOneParam) {
+ return 'config' as any;
+ }
+
+ // if config and cli - return error - write a reason
+ console.log(outputs.common.ambiguousParams(command));
+ process.exit(1);
+};
+
+export const sqliteDriversLiterals = [
+ literal('turso'),
+ literal('d1-http'),
+ literal('expo'),
+] as const;
+
+export const postgresqlDriversLiterals = [
+ literal('aws-data-api'),
+ literal('pglite'),
+] as const;
+
+export const prefixes = [
+ 'index',
+ 'timestamp',
+ 'supabase',
+ 'unix',
+ 'none',
+] as const;
+export const prefix = enum_(prefixes);
+export type Prefix = (typeof prefixes)[number];
+
+{
+ const _: Prefix = '' as TypeOf;
+}
+
+export const sqliteDriver = union(sqliteDriversLiterals);
+export const postgresDriver = union(postgresqlDriversLiterals);
+export const driver = union([sqliteDriver, postgresDriver]);
+
+export const configMigrations = object({
+ table: string().optional(),
+ schema: string().optional(),
+ prefix: prefix.optional().default('index'),
+}).optional();
+
+export const configCommonSchema = object({
+ dialect: dialect,
+ schema: union([string(), string().array()]).optional(),
+ out: string().optional(),
+ breakpoints: boolean().optional().default(true),
+ verbose: boolean().optional().default(false),
+ driver: driver.optional(),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()]).default(['public']),
+ migrations: configMigrations,
+ dbCredentials: any().optional(),
+}).passthrough();
+
+export const casing = union([literal('camel'), literal('preserve')]).default(
+ 'camel',
+);
+
+export const introspectParams = object({
+ schema: union([string(), string().array()]).optional(),
+ out: string().optional().default('./drizzle'),
+ breakpoints: boolean().default(true),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()]).default(['public']),
+ introspect: object({
+ casing,
+ }).default({ casing: 'camel' }),
+});
+
+export type IntrospectParams = TypeOf;
+export type Casing = TypeOf;
+
+export const configIntrospectCliSchema = object({
+ schema: union([string(), string().array()]).optional(),
+ out: string().optional().default('./drizzle'),
+ breakpoints: boolean().default(true),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()]).default(['public']),
+ introspectCasing: union([literal('camel'), literal('preserve')]).default(
+ 'camel',
+ ),
+});
+
+export const configGenerateSchema = object({
+ schema: union([string(), string().array()]),
+ out: string().optional().default('./drizzle'),
+ breakpoints: boolean().default(true),
+});
+
+export type GenerateSchema = TypeOf;
+
+export const configPushSchema = object({
+ dialect: dialect,
+ schema: union([string(), string().array()]),
+ tablesFilter: union([string(), string().array()]).optional(),
+ schemaFilter: union([string(), string().array()]).default(['public']),
+ verbose: boolean().default(false),
+ strict: boolean().default(false),
+ out: string().optional(),
+});
+
+export type CliConfig = TypeOf;
+export const drivers = ['turso', 'd1-http', 'expo', 'aws-data-api', 'pglite'] as const;
+export type Driver = (typeof drivers)[number];
+const _: Driver = '' as TypeOf;
+
+export const wrapParam = (
+ name: string,
+ param: any | undefined,
+ optional: boolean = false,
+ type?: 'url' | 'secret',
+) => {
+ const check = `[${chalk.green('✓')}]`;
+ const cross = `[${chalk.red('x')}]`;
+ if (typeof param === 'string') {
+ if (param.length === 0) {
+ return ` ${cross} ${name}: ''`;
+ }
+ if (type === 'secret') {
+ return ` ${check} ${name}: '*****'`;
+ } else if (type === 'url') {
+ return ` ${check} ${name}: '${param.replace(/(?<=:\/\/[^:\n]*:)([^@]*)/, '****')}'`;
+ }
+ return ` ${check} ${name}: '${param}'`;
+ }
+ if (optional) {
+ return chalk.gray(` ${name}?: `);
+ }
+ return ` ${cross} ${name}: ${chalk.gray('undefined')}`;
+};
diff --git a/drizzle-kit/src/cli/validations/mysql.ts b/drizzle-kit/src/cli/validations/mysql.ts
new file mode 100644
index 000000000..1841dbdd6
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/mysql.ts
@@ -0,0 +1,61 @@
+import { boolean, coerce, object, string, TypeOf, union } from 'zod';
+import { error } from '../views';
+import { wrapParam } from './common';
+import { outputs } from './outputs';
+
+export const mysqlCredentials = union([
+ object({
+ host: string().min(1),
+ port: coerce.number().min(1).optional(),
+ user: string().min(1).optional(),
+ password: string().min(1).optional(),
+ database: string().min(1),
+ ssl: union([
+ string(),
+ object({
+ pfx: string().optional(),
+ key: string().optional(),
+ passphrase: string().optional(),
+ cert: string().optional(),
+ ca: union([string(), string().array()]).optional(),
+ crl: union([string(), string().array()]).optional(),
+ ciphers: string().optional(),
+ rejectUnauthorized: boolean().optional(),
+ }),
+ ]).optional(),
+ }),
+ object({
+ url: string().min(1),
+ }),
+]);
+
+export type MysqlCredentials = TypeOf;
+
+export const printCliConnectionIssues = (options: any) => {
+ const { uri, host, database } = options || {};
+
+ if (!uri && (!host || !database)) {
+ console.log(outputs.mysql.connection.required());
+ }
+};
+
+export const printConfigConnectionIssues = (
+ options: Record,
+) => {
+ if ('url' in options) {
+ let text = `Please provide required params for MySQL driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('url', options.url, false, 'url'));
+ process.exit(1);
+ }
+
+ let text = `Please provide required params for MySQL driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('host', options.host));
+ console.log(wrapParam('port', options.port, true));
+ console.log(wrapParam('user', options.user, true));
+ console.log(wrapParam('password', options.password, true, 'secret'));
+ console.log(wrapParam('database', options.database));
+ console.log(wrapParam('ssl', options.ssl, true));
+ process.exit(1);
+};
diff --git a/drizzle-kit/src/cli/validations/outputs.ts b/drizzle-kit/src/cli/validations/outputs.ts
new file mode 100644
index 000000000..ad0423b97
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/outputs.ts
@@ -0,0 +1,91 @@
+import chalk from 'chalk';
+import { sqliteDriversLiterals } from './common';
+
+export const withStyle = {
+ error: (str: string) => `${chalk.red(`${chalk.white.bgRed(' Invalid input ')} ${str}`)}`,
+ warning: (str: string) => `${chalk.white.bgGray(' Warning ')} ${str}`,
+ errorWarning: (str: string) => `${chalk.red(`${chalk.white.bgRed(' Warning ')} ${str}`)}`,
+ fullWarning: (str: string) => `${chalk.black.bgYellow(' Warning ')} ${chalk.bold(str)}`,
+ suggestion: (str: string) => `${chalk.white.bgGray(' Suggestion ')} ${str}`,
+ info: (str: string) => `${chalk.grey(str)}`,
+};
+
+export const outputs = {
+ studio: {
+ drivers: (param: string) =>
+ withStyle.error(
+ `"${param}" is not a valid driver. Available drivers: "pg", "mysql2", "better-sqlite", "libsql", "turso". You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
+ ),
+ noCredentials: () =>
+ withStyle.error(
+ `Please specify a 'dbCredentials' param in config. It will help drizzle to know how to query you database. You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
+ ),
+ noDriver: () =>
+ withStyle.error(
+ `Please specify a 'driver' param in config. It will help drizzle to know how to query you database. You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
+ ),
+ noDialect: () =>
+ withStyle.error(
+ `Please specify 'dialect' param in config, either of 'pg', 'mysql', 'sqlite' or singlestore`,
+ ),
+ },
+ common: {
+ ambiguousParams: (command: string) =>
+ withStyle.error(
+ `You can't use both --config and other cli options for ${command} command`,
+ ),
+ schema: (command: string) => withStyle.error(`"--schema" is a required field for ${command} command`),
+ },
+ postgres: {
+ connection: {
+ required: () =>
+ withStyle.error(
+ `Either "url" or "host", "database" are required for database connection`,
+ ),
+ awsDataApi: () =>
+ withStyle.error(
+ "You need to provide 'database', 'secretArn' and 'resourceArn' for Drizzle Kit to connect to AWS Data API",
+ ),
+ },
+ },
+ mysql: {
+ connection: {
+ driver: () => withStyle.error(`Only "mysql2" is available options for "--driver"`),
+ required: () =>
+ withStyle.error(
+ `Either "url" or "host", "database" are required for database connection`,
+ ),
+ },
+ },
+ sqlite: {
+ connection: {
+ driver: () => {
+ const listOfDrivers = sqliteDriversLiterals
+ .map((it) => `'${it.value}'`)
+ .join(', ');
+ return withStyle.error(
+ `Either ${listOfDrivers} are available options for 'driver' param`,
+ );
+ },
+ url: (driver: string) =>
+ withStyle.error(
+ `"url" is a required option for driver "${driver}". You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
+ ),
+ authToken: (driver: string) =>
+ withStyle.error(
+ `"authToken" is a required option for driver "${driver}". You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
+ ),
+ },
+ introspect: {},
+ push: {},
+ },
+ singlestore: {
+ connection: {
+ driver: () => withStyle.error(`Only "mysql2" is available options for "--driver"`),
+ required: () =>
+ withStyle.error(
+ `Either "url" or "host", "database" are required for database connection`,
+ ),
+ },
+ },
+};
diff --git a/drizzle-kit/src/cli/validations/postgres.ts b/drizzle-kit/src/cli/validations/postgres.ts
new file mode 100644
index 000000000..658760c61
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/postgres.ts
@@ -0,0 +1,83 @@
+import { boolean, coerce, literal, object, string, TypeOf, undefined, union } from 'zod';
+import { error } from '../views';
+import { wrapParam } from './common';
+
+export const postgresCredentials = union([
+ object({
+ driver: undefined(),
+ host: string().min(1),
+ port: coerce.number().min(1).optional(),
+ user: string().min(1).optional(),
+ password: string().min(1).optional(),
+ database: string().min(1),
+ ssl: union([
+ literal('require'),
+ literal('allow'),
+ literal('prefer'),
+ literal('verify-full'),
+ boolean(),
+ object({}).passthrough(),
+ ]).optional(),
+ }).transform((o) => {
+ delete o.driver;
+ return o as Omit;
+ }),
+ object({
+ driver: undefined(),
+ url: string().min(1),
+ }).transform<{ url: string }>((o) => {
+ delete o.driver;
+ return o;
+ }),
+ object({
+ driver: literal('aws-data-api'),
+ database: string().min(1),
+ secretArn: string().min(1),
+ resourceArn: string().min(1),
+ }),
+ object({
+ driver: literal('pglite'),
+ url: string().min(1),
+ }),
+]);
+
+export type PostgresCredentials = TypeOf;
+
+export const printConfigConnectionIssues = (
+ options: Record,
+) => {
+ if (options.driver === 'aws-data-api') {
+ let text = `Please provide required params for AWS Data API driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('database', options.database));
+ console.log(wrapParam('secretArn', options.secretArn, false, 'secret'));
+ console.log(wrapParam('resourceArn', options.resourceArn, false, 'secret'));
+ process.exit(1);
+ }
+
+ if ('url' in options) {
+ let text = `Please provide required params for Postgres driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('url', options.url, false, 'url'));
+ process.exit(1);
+ }
+
+ if ('host' in options || 'database' in options) {
+ let text = `Please provide required params for Postgres driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('host', options.host));
+ console.log(wrapParam('port', options.port, true));
+ console.log(wrapParam('user', options.user, true));
+ console.log(wrapParam('password', options.password, true, 'secret'));
+ console.log(wrapParam('database', options.database));
+ console.log(wrapParam('ssl', options.ssl, true));
+ process.exit(1);
+ }
+
+ console.log(
+ error(
+ `Either connection "url" or "host", "database" are required for PostgreSQL database connection`,
+ ),
+ );
+ process.exit(1);
+};
diff --git a/drizzle-kit/src/cli/validations/singlestore.ts b/drizzle-kit/src/cli/validations/singlestore.ts
new file mode 100644
index 000000000..ebe0cc5f0
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/singlestore.ts
@@ -0,0 +1,61 @@
+import { boolean, coerce, object, string, TypeOf, union } from 'zod';
+import { error } from '../views';
+import { wrapParam } from './common';
+import { outputs } from './outputs';
+
+export const singlestoreCredentials = union([
+ object({
+ host: string().min(1),
+ port: coerce.number().min(1).optional(),
+ user: string().min(1).optional(),
+ password: string().min(1).optional(),
+ database: string().min(1),
+ ssl: union([
+ string(),
+ object({
+ pfx: string().optional(),
+ key: string().optional(),
+ passphrase: string().optional(),
+ cert: string().optional(),
+ ca: union([string(), string().array()]).optional(),
+ crl: union([string(), string().array()]).optional(),
+ ciphers: string().optional(),
+ rejectUnauthorized: boolean().optional(),
+ }),
+ ]).optional(),
+ }),
+ object({
+ url: string().min(1),
+ }),
+]);
+
+export type SingleStoreCredentials = TypeOf;
+
+export const printCliConnectionIssues = (options: any) => {
+ const { uri, host, database } = options || {};
+
+ if (!uri && (!host || !database)) {
+ console.log(outputs.singlestore.connection.required());
+ }
+};
+
+export const printConfigConnectionIssues = (
+ options: Record,
+) => {
+ if ('url' in options) {
+ let text = `Please provide required params for SingleStore driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('url', options.url, false, 'url'));
+ process.exit(1);
+ }
+
+ let text = `Please provide required params for SingleStore driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('host', options.host));
+ console.log(wrapParam('port', options.port, true));
+ console.log(wrapParam('user', options.user, true));
+ console.log(wrapParam('password', options.password, true, 'secret'));
+ console.log(wrapParam('database', options.database));
+ console.log(wrapParam('ssl', options.ssl, true));
+ process.exit(1);
+};
diff --git a/drizzle-kit/src/cli/validations/sqlite.ts b/drizzle-kit/src/cli/validations/sqlite.ts
new file mode 100644
index 000000000..b6ad062d5
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/sqlite.ts
@@ -0,0 +1,94 @@
+import { softAssertUnreachable } from 'src/global';
+import { literal, object, string, TypeOf, undefined, union } from 'zod';
+import { error } from '../views';
+import { sqliteDriver, wrapParam } from './common';
+
+export const sqliteCredentials = union([
+ object({
+ driver: literal('turso'),
+ url: string().min(1),
+ authToken: string().min(1).optional(),
+ }),
+ object({
+ driver: literal('d1-http'),
+ accountId: string().min(1),
+ databaseId: string().min(1),
+ token: string().min(1),
+ }),
+ object({
+ driver: undefined(),
+ url: string().min(1),
+ }).transform<{ url: string }>((o) => {
+ delete o.driver;
+ return o;
+ }),
+]);
+
+export type SqliteCredentials =
+ | {
+ driver: 'turso';
+ url: string;
+ authToken: string;
+ }
+ | {
+ driver: 'd1-http';
+ accountId: string;
+ databaseId: string;
+ token: string;
+ }
+ | {
+ url: string;
+ };
+
+const _: SqliteCredentials = {} as TypeOf;
+
+export const printConfigConnectionIssues = (
+ options: Record,
+ command: 'generate' | 'migrate' | 'push' | 'pull' | 'studio',
+) => {
+ const parsedDriver = sqliteDriver.safeParse(options.driver);
+ const driver = parsedDriver.success ? parsedDriver.data : ('' as never);
+
+ if (driver === 'expo') {
+ if (command === 'migrate') {
+ console.log(
+ error(
+ `You can't use 'migrate' command with Expo SQLite, please follow migration instructions in our docs - https://orm.drizzle.team/docs/get-started-sqlite#expo-sqlite`,
+ ),
+ );
+ } else if (command === 'studio') {
+ console.log(
+ error(
+ `You can't use 'studio' command with Expo SQLite, please use Expo Plugin https://www.npmjs.com/package/expo-drizzle-studio-plugin`,
+ ),
+ );
+ } else if (command === 'pull') {
+ console.log(error("You can't use 'pull' command with Expo SQLite"));
+ } else if (command === 'push') {
+ console.log(error("You can't use 'push' command with Expo SQLite"));
+ } else {
+ console.log(error('Unexpected error with expo driver 🤔'));
+ }
+ process.exit(1);
+ } else if (driver === 'd1-http') {
+ let text = `Please provide required params for D1 HTTP driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('accountId', options.accountId));
+ console.log(wrapParam('databaseId', options.databaseId));
+ console.log(wrapParam('token', options.token, false, 'secret'));
+ process.exit(1);
+ } else if (driver === 'turso') {
+ let text = `Please provide required params for Turso driver:\n`;
+ console.log(error(text));
+ console.log(wrapParam('url', options.url));
+ console.log(wrapParam('authToken', options.authToken, false, 'secret'));
+ return;
+ } else {
+ softAssertUnreachable(driver);
+ }
+
+ let text = `Please provide required params:\n`;
+ console.log(error(text));
+ console.log(wrapParam('url', options.url));
+ process.exit(1);
+};
diff --git a/drizzle-kit/src/cli/validations/studio.ts b/drizzle-kit/src/cli/validations/studio.ts
new file mode 100644
index 000000000..cbbb3ac25
--- /dev/null
+++ b/drizzle-kit/src/cli/validations/studio.ts
@@ -0,0 +1,24 @@
+import { coerce, intersection, object, string, TypeOf, union } from 'zod';
+import { dialect } from '../../schemaValidator';
+import { mysqlCredentials } from './mysql';
+import { postgresCredentials } from './postgres';
+import { sqliteCredentials } from './sqlite';
+
+export const credentials = intersection(
+ postgresCredentials,
+ mysqlCredentials,
+ sqliteCredentials,
+);
+
+export type Credentials = TypeOf;
+
+export const studioCliParams = object({
+ port: coerce.number().optional().default(4983),
+ host: string().optional().default('127.0.0.1'),
+ config: string().optional(),
+});
+
+export const studioConfig = object({
+ dialect,
+ schema: union([string(), string().array()]).optional(),
+});
diff --git a/drizzle-kit/src/cli/views.ts b/drizzle-kit/src/cli/views.ts
new file mode 100644
index 000000000..56e0331df
--- /dev/null
+++ b/drizzle-kit/src/cli/views.ts
@@ -0,0 +1,558 @@
+import chalk from 'chalk';
+import { Prompt, render, SelectState, TaskView } from 'hanji';
+import type { CommonSchema } from '../schemaValidator';
+import { objectValues } from '../utils';
+import type { Named, NamedWithSchema } from './commands/migrate';
+
+export const warning = (msg: string) => {
+ render(`[${chalk.yellow('Warning')}] ${msg}`);
+};
+export const err = (msg: string) => {
+ render(`${chalk.bold.red('Error')} ${msg}`);
+};
+
+export const info = (msg: string, greyMsg: string = ''): string => {
+ return `${chalk.blue.bold('Info:')} ${msg} ${greyMsg ? chalk.grey(greyMsg) : ''}`.trim();
+};
+export const grey = (msg: string): string => {
+ return chalk.grey(msg);
+};
+
+export const error = (error: string, greyMsg: string = ''): string => {
+ return `${chalk.bgRed.bold(' Error ')} ${error} ${greyMsg ? chalk.grey(greyMsg) : ''}`.trim();
+};
+
+export const schema = (schema: CommonSchema): string => {
+ type TableEntry = (typeof schema)['tables'][keyof (typeof schema)['tables']];
+ const tables = Object.values(schema.tables) as unknown as TableEntry[];
+
+ let msg = chalk.bold(`${tables.length} tables\n`);
+
+ msg += tables
+ .map((t) => {
+ const columnsCount = Object.values(t.columns).length;
+ const indexesCount = Object.values(t.indexes).length;
+ const foreignKeys = Object.values(t.foreignKeys).length;
+ return `${chalk.bold.blue(t.name)} ${
+ chalk.gray(
+ `${columnsCount} columns ${indexesCount} indexes ${foreignKeys} fks`,
+ )
+ }`;
+ })
+ .join('\n');
+
+ msg += '\n';
+
+ const enums = objectValues(
+ 'enums' in schema
+ ? 'values' in schema['enums']
+ ? schema['enums']
+ : {}
+ : {},
+ );
+
+ if (enums.length > 0) {
+ msg += '\n';
+ msg += chalk.bold(`${enums.length} enums\n`);
+
+ msg += enums
+ .map((it) => {
+ return `${chalk.bold.blue(it.name)} ${
+ chalk.gray(
+ `[${Object.values(it.values).join(', ')}]`,
+ )
+ }`;
+ })
+ .join('\n');
+ msg += '\n';
+ }
+ return msg;
+};
+
+export interface RenamePropmtItem {
+ from: T;
+ to: T;
+}
+
+export const isRenamePromptItem = (
+ item: RenamePropmtItem | T,
+): item is RenamePropmtItem => {
+ return 'from' in item && 'to' in item;
+};
+
+export class ResolveColumnSelect extends Prompt<
+ RenamePropmtItem | T
+> {
+ private readonly data: SelectState | T>;
+
+ constructor(
+ private readonly tableName: string,
+ private readonly base: Named,
+ data: (RenamePropmtItem | T)[],
+ ) {
+ super();
+ this.on('attach', (terminal) => terminal.toggleCursor('hide'));
+ this.data = new SelectState(data);
+ this.data.bind(this);
+ }
+
+ render(status: 'idle' | 'submitted' | 'aborted'): string {
+ if (status === 'submitted' || status === 'aborted') {
+ return '\n';
+ }
+
+ let text = `\nIs ${
+ chalk.bold.blue(
+ this.base.name,
+ )
+ } column in ${
+ chalk.bold.blue(
+ this.tableName,
+ )
+ } table created or renamed from another column?\n`;
+
+ const isSelectedRenamed = isRenamePromptItem(
+ this.data.items[this.data.selectedIdx],
+ );
+
+ const selectedPrefix = isSelectedRenamed
+ ? chalk.yellow('❯ ')
+ : chalk.green('❯ ');
+
+ const labelLength: number = this.data.items
+ .filter((it) => isRenamePromptItem(it))
+ .map((it: RenamePropmtItem) => {
+ return this.base.name.length + 3 + it['from'].name.length;
+ })
+ .reduce((a, b) => {
+ if (a > b) {
+ return a;
+ }
+ return b;
+ }, 0);
+
+ this.data.items.forEach((it, idx) => {
+ const isSelected = idx === this.data.selectedIdx;
+ const isRenamed = isRenamePromptItem(it);
+ const title = isRenamed
+ ? `${it.from.name} › ${it.to.name}`.padEnd(labelLength, ' ')
+ : it.name.padEnd(labelLength, ' ');
+ const label = isRenamed
+ ? `${chalk.yellow('~')} ${title} ${chalk.gray('rename column')}`
+ : `${chalk.green('+')} ${title} ${chalk.gray('create column')}`;
+
+ text += isSelected ? `${selectedPrefix}${label}` : ` ${label}`;
+ text += idx != this.data.items.length - 1 ? '\n' : '';
+ });
+ return text;
+ }
+
+ result(): RenamePropmtItem | T {
+ return this.data.items[this.data.selectedIdx]!;
+ }
+}
+
+export const tableKey = (it: NamedWithSchema) => {
+ return it.schema === 'public' || !it.schema
+ ? it.name
+ : `${it.schema}.${it.name}`;
+};
+
+export class ResolveSelect extends Prompt<
+ RenamePropmtItem | T
+> {
+ private readonly state: SelectState | T>;
+
+ constructor(
+ private readonly base: T,
+ data: (RenamePropmtItem | T)[],
+ private readonly entityType: 'table' | 'enum' | 'sequence',
+ ) {
+ super();
+ this.on('attach', (terminal) => terminal.toggleCursor('hide'));
+ this.state = new SelectState(data);
+ this.state.bind(this);
+ this.base = base;
+ }
+
+ render(status: 'idle' | 'submitted' | 'aborted'): string {
+ if (status === 'submitted' || status === 'aborted') {
+ return '';
+ }
+ const key = tableKey(this.base);
+
+ let text = `\nIs ${chalk.bold.blue(key)} ${this.entityType} created or renamed from another ${this.entityType}?\n`;
+
+ const isSelectedRenamed = isRenamePromptItem(
+ this.state.items[this.state.selectedIdx],
+ );
+
+ const selectedPrefix = isSelectedRenamed
+ ? chalk.yellow('❯ ')
+ : chalk.green('❯ ');
+
+ const labelLength: number = this.state.items
+ .filter((it) => isRenamePromptItem(it))
+ .map((_) => {
+ const it = _ as RenamePropmtItem;
+ const keyFrom = tableKey(it.from);
+ return key.length + 3 + keyFrom.length;
+ })
+ .reduce((a, b) => {
+ if (a > b) {
+ return a;
+ }
+ return b;
+ }, 0);
+
+ const entityType = this.entityType;
+ this.state.items.forEach((it, idx) => {
+ const isSelected = idx === this.state.selectedIdx;
+ const isRenamed = isRenamePromptItem(it);
+
+ const title = isRenamed
+ ? `${tableKey(it.from)} › ${tableKey(it.to)}`.padEnd(labelLength, ' ')
+ : tableKey(it).padEnd(labelLength, ' ');
+
+ const label = isRenamed
+ ? `${chalk.yellow('~')} ${title} ${chalk.gray(`rename ${entityType}`)}`
+ : `${chalk.green('+')} ${title} ${chalk.gray(`create ${entityType}`)}`;
+
+ text += isSelected ? `${selectedPrefix}${label}` : ` ${label}`;
+ text += idx != this.state.items.length - 1 ? '\n' : '';
+ });
+ return text;
+ }
+
+ result(): RenamePropmtItem | T {
+ return this.state.items[this.state.selectedIdx]!;
+ }
+}
+
+export class ResolveSchemasSelect extends Prompt<
+ RenamePropmtItem | T
+> {
+ private readonly state: SelectState | T>;
+
+ constructor(private readonly base: Named, data: (RenamePropmtItem | T)[]) {
+ super();
+ this.on('attach', (terminal) => terminal.toggleCursor('hide'));
+ this.state = new SelectState(data);
+ this.state.bind(this);
+ this.base = base;
+ }
+
+ render(status: 'idle' | 'submitted' | 'aborted'): string {
+ if (status === 'submitted' || status === 'aborted') {
+ return '';
+ }
+
+ let text = `\nIs ${
+ chalk.bold.blue(
+ this.base.name,
+ )
+ } schema created or renamed from another schema?\n`;
+ const isSelectedRenamed = isRenamePromptItem(
+ this.state.items[this.state.selectedIdx],
+ );
+ const selectedPrefix = isSelectedRenamed
+ ? chalk.yellow('❯ ')
+ : chalk.green('❯ ');
+
+ const labelLength: number = this.state.items
+ .filter((it) => isRenamePromptItem(it))
+ .map((it: RenamePropmtItem) => {
+ return this.base.name.length + 3 + it['from'].name.length;
+ })
+ .reduce((a, b) => {
+ if (a > b) {
+ return a;
+ }
+ return b;
+ }, 0);
+
+ this.state.items.forEach((it, idx) => {
+ const isSelected = idx === this.state.selectedIdx;
+ const isRenamed = isRenamePromptItem(it);
+ const title = isRenamed
+ ? `${it.from.name} › ${it.to.name}`.padEnd(labelLength, ' ')
+ : it.name.padEnd(labelLength, ' ');
+ const label = isRenamed
+ ? `${chalk.yellow('~')} ${title} ${chalk.gray('rename schema')}`
+ : `${chalk.green('+')} ${title} ${chalk.gray('create schema')}`;
+
+ text += isSelected ? `${selectedPrefix}${label}` : ` ${label}`;
+ text += idx != this.state.items.length - 1 ? '\n' : '';
+ });
+ return text;
+ }
+
+ result(): RenamePropmtItem | T {
+ return this.state.items[this.state.selectedIdx]!;
+ }
+}
+
+class Spinner {
+ private offset: number = 0;
+ private readonly iterator: () => void;
+
+ constructor(private readonly frames: string[]) {
+ this.iterator = () => {
+ this.offset += 1;
+ this.offset %= frames.length - 1;
+ };
+ }
+
+ public tick = () => {
+ this.iterator();
+ };
+
+ public value = () => {
+ return this.frames[this.offset];
+ };
+}
+
+const frames = function(values: string[]): () => string {
+ let index = 0;
+ const iterator = () => {
+ const frame = values[index];
+ index += 1;
+ index %= values.length;
+ return frame!;
+ };
+ return iterator;
+};
+
+type ValueOf = T[keyof T];
+export type IntrospectStatus = 'fetching' | 'done';
+export type IntrospectStage =
+ | 'tables'
+ | 'columns'
+ | 'enums'
+ | 'indexes'
+ | 'fks';
+type IntrospectState = {
+ [key in IntrospectStage]: {
+ count: number;
+ name: string;
+ status: IntrospectStatus;
+ };
+};
+
+export class IntrospectProgress extends TaskView {
+ private readonly spinner: Spinner = new Spinner('⣷⣯⣟⡿⢿⣻⣽⣾'.split(''));
+ private timeout: NodeJS.Timeout | undefined;
+
+ private state: IntrospectState = {
+ tables: {
+ count: 0,
+ name: 'tables',
+ status: 'fetching',
+ },
+ columns: {
+ count: 0,
+ name: 'columns',
+ status: 'fetching',
+ },
+ enums: {
+ count: 0,
+ name: 'enums',
+ status: 'fetching',
+ },
+ indexes: {
+ count: 0,
+ name: 'indexes',
+ status: 'fetching',
+ },
+ fks: {
+ count: 0,
+ name: 'foreign keys',
+ status: 'fetching',
+ },
+ };
+
+ constructor(private readonly hasEnums: boolean = false) {
+ super();
+ this.timeout = setInterval(() => {
+ this.spinner.tick();
+ this.requestLayout();
+ }, 128);
+
+ this.on('detach', () => clearInterval(this.timeout));
+ }
+
+ public update(
+ stage: IntrospectStage,
+ count: number,
+ status: IntrospectStatus,
+ ) {
+ this.state[stage].count = count;
+ this.state[stage].status = status;
+ this.requestLayout();
+ }
+
+ private formatCount = (count: number) => {
+ const width: number = Math.max.apply(
+ null,
+ Object.values(this.state).map((it) => it.count.toFixed(0).length),
+ );
+
+ return count.toFixed(0).padEnd(width, ' ');
+ };
+
+ private statusText = (spinner: string, stage: ValueOf) => {
+ const { name, count } = stage;
+ const isDone = stage.status === 'done';
+
+ const prefix = isDone ? `[${chalk.green('✓')}]` : `[${spinner}]`;
+
+ const formattedCount = this.formatCount(count);
+ const suffix = isDone
+ ? `${formattedCount} ${name} fetched`
+ : `${formattedCount} ${name} fetching`;
+
+ return `${prefix} ${suffix}\n`;
+ };
+
+ render(): string {
+ let info = '';
+ const spin = this.spinner.value();
+ info += this.statusText(spin, this.state.tables);
+ info += this.statusText(spin, this.state.columns);
+ info += this.hasEnums ? this.statusText(spin, this.state.enums) : '';
+ info += this.statusText(spin, this.state.indexes);
+ info += this.statusText(spin, this.state.fks);
+ return info;
+ }
+}
+
+export class MigrateProgress extends TaskView {
+ private readonly spinner: Spinner = new Spinner('⣷⣯⣟⡿⢿⣻⣽⣾'.split(''));
+ private timeout: NodeJS.Timeout | undefined;
+
+ constructor() {
+ super();
+ this.timeout = setInterval(() => {
+ this.spinner.tick();
+ this.requestLayout();
+ }, 128);
+
+ this.on('detach', () => clearInterval(this.timeout));
+ }
+
+ render(status: 'pending' | 'done'): string {
+ if (status === 'pending') {
+ const spin = this.spinner.value();
+ return `[${spin}] applying migrations...`;
+ }
+ return `[${chalk.green('✓')}] migrations applied successfully!`;
+ }
+}
+
+export class ProgressView extends TaskView {
+ private readonly spinner: Spinner = new Spinner('⣷⣯⣟⡿⢿⣻⣽⣾'.split(''));
+ private timeout: NodeJS.Timeout | undefined;
+
+ constructor(
+ private readonly progressText: string,
+ private readonly successText: string,
+ ) {
+ super();
+ this.timeout = setInterval(() => {
+ this.spinner.tick();
+ this.requestLayout();
+ }, 128);
+
+ this.on('detach', () => clearInterval(this.timeout));
+ }
+
+ render(status: 'pending' | 'done'): string {
+ if (status === 'pending') {
+ const spin = this.spinner.value();
+ return `[${spin}] ${this.progressText}\n`;
+ }
+ return `[${chalk.green('✓')}] ${this.successText}\n`;
+ }
+}
+
+export class DropMigrationView extends Prompt {
+ private readonly data: SelectState;
+
+ constructor(data: T[]) {
+ super();
+ this.on('attach', (terminal) => terminal.toggleCursor('hide'));
+ this.data = new SelectState(data);
+ this.data.selectedIdx = data.length - 1;
+ this.data.bind(this);
+ }
+
+ render(status: 'idle' | 'submitted' | 'aborted'): string {
+ if (status === 'submitted' || status === 'aborted') {
+ return '\n';
+ }
+
+ let text = chalk.bold('Please select migration to drop:\n');
+ const selectedPrefix = chalk.yellow('❯ ');
+
+ const data = trimmedRange(this.data.items, this.data.selectedIdx, 9);
+ const labelLength: number = data.trimmed
+ .map((it) => it.tag.length)
+ .reduce((a, b) => {
+ if (a > b) {
+ return a;
+ }
+ return b;
+ }, 0);
+
+ text += data.startTrimmed ? ' ...\n' : '';
+
+ data.trimmed.forEach((it, idx) => {
+ const isSelected = idx === this.data.selectedIdx - data.offset;
+ let title = it.tag.padEnd(labelLength, ' ');
+ title = isSelected ? chalk.yellow(title) : title;
+
+ text += isSelected ? `${selectedPrefix}${title}` : ` ${title}`;
+ text += idx != this.data.items.length - 1 ? '\n' : '';
+ });
+
+ text += data.endTrimmed ? ' ...\n' : '';
+ return text;
+ }
+
+ result(): T {
+ return this.data.items[this.data.selectedIdx]!;
+ }
+}
+
+export const trimmedRange = (
+ arr: T[],
+ index: number,
+ limitLines: number,
+): {
+ trimmed: T[];
+ offset: number;
+ startTrimmed: boolean;
+ endTrimmed: boolean;
+} => {
+ const limit = limitLines - 2;
+ const sideLimit = Math.round(limit / 2);
+
+ const endTrimmed = arr.length - sideLimit > index;
+ const startTrimmed = index > sideLimit - 1;
+
+ const paddingStart = Math.max(index + sideLimit - arr.length, 0);
+ const paddingEnd = Math.min(index - sideLimit + 1, 0);
+
+ const d1 = endTrimmed ? 1 : 0;
+ const d2 = startTrimmed ? 0 : 1;
+
+ const start = Math.max(0, index - sideLimit + d1 - paddingStart);
+ const end = Math.min(arr.length, index + sideLimit + d2 - paddingEnd);
+
+ return {
+ trimmed: arr.slice(start, end),
+ offset: start,
+ startTrimmed,
+ endTrimmed,
+ };
+};
diff --git a/drizzle-kit/src/extensions/vector.ts b/drizzle-kit/src/extensions/vector.ts
new file mode 100644
index 000000000..e8b4f87ef
--- /dev/null
+++ b/drizzle-kit/src/extensions/vector.ts
@@ -0,0 +1,10 @@
+export const vectorOps = [
+ 'vector_l2_ops',
+ 'vector_ip_ops',
+ 'vector_cosine_ops',
+ 'vector_l1_ops',
+ 'bit_hamming_ops',
+ 'bit_jaccard_ops',
+ 'halfvec_l2_ops',
+ 'sparsevec_l2_ops',
+];
diff --git a/drizzle-kit/src/global.ts b/drizzle-kit/src/global.ts
new file mode 100644
index 000000000..4cea3d15e
--- /dev/null
+++ b/drizzle-kit/src/global.ts
@@ -0,0 +1,61 @@
+export const originUUID = '00000000-0000-0000-0000-000000000000';
+export const snapshotVersion = '7';
+
+export function assertUnreachable(x: never | undefined): never {
+ throw new Error("Didn't expect to get here");
+}
+
+// don't fail in runtime, types only
+export function softAssertUnreachable(x: never) {
+ return null as never;
+}
+
+export const mapValues = (
+ obj: Record,
+ map: (input: IN) => OUT,
+): Record => {
+ const result = Object.keys(obj).reduce(function(result, key) {
+ result[key] = map(obj[key]);
+ return result;
+ }, {} as Record);
+ return result;
+};
+
+export const mapKeys = (
+ obj: Record,
+ map: (key: string, value: T) => string,
+): Record => {
+ const result = Object.fromEntries(
+ Object.entries(obj).map(([key, val]) => {
+ const newKey = map(key, val);
+ return [newKey, val];
+ }),
+ );
+ return result;
+};
+
+export const mapEntries = (
+ obj: Record,
+ map: (key: string, value: T) => [string, T],
+): Record => {
+ const result = Object.fromEntries(
+ Object.entries(obj).map(([key, val]) => {
+ const [newKey, newVal] = map(key, val);
+ return [newKey, newVal];
+ }),
+ );
+ return result;
+};
+
+export const customMapEntries = (
+ obj: Record,
+ map: (key: string, value: T) => [string, TReturn],
+): Record => {
+ const result = Object.fromEntries(
+ Object.entries(obj).map(([key, val]) => {
+ const [newKey, newVal] = map(key, val);
+ return [newKey, newVal];
+ }),
+ );
+ return result;
+};
diff --git a/drizzle-kit/src/index.ts b/drizzle-kit/src/index.ts
new file mode 100644
index 000000000..9fab4bcb8
--- /dev/null
+++ b/drizzle-kit/src/index.ts
@@ -0,0 +1,319 @@
+import { ConnectionOptions } from 'tls';
+import type { Driver, Prefix } from './cli/validations/common';
+import type { Dialect } from './schemaValidator';
+
+// import {SslOptions} from 'mysql2'
+type SslOptions = {
+ pfx?: string;
+ key?: string;
+ passphrase?: string;
+ cert?: string;
+ ca?: string | string[];
+ crl?: string | string[];
+ ciphers?: string;
+ rejectUnauthorized?: boolean;
+};
+
+type Verify = U;
+
+/**
+ * **You are currently using version 0.21.0+ of drizzle-kit. If you have just upgraded to this version, please make sure to read the changelog to understand what changes have been made and what
+ * adjustments may be necessary for you. See https://orm.drizzle.team/kit-docs/upgrade-21#how-to-migrate-to-0210**
+ *
+ * **Config** usage:
+ *
+ * `dialect` - mandatory and is responsible for explicitly providing a databse dialect you are using for all the commands
+ * *Possible values*: `postgresql`, `mysql`, `sqlite`, `singlestore
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#dialect
+ *
+ * ---
+ * `schema` - param lets you define where your schema file/files live.
+ * You can have as many separate schema files as you want and define paths to them using glob or array of globs syntax.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#schema
+ *
+ * ---
+ * `out` - allows you to define the folder for your migrations and a folder, where drizzle will introspect the schema and relations
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#out
+ *
+ * ---
+ * `driver` - optional param that is responsible for explicitly providing a driver to use when accessing a database
+ * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso`, `pglite`
+ * If you don't use AWS Data API, D1, Turso or Expo - ypu don't need this driver. You can check a driver strategy choice here: https://orm.drizzle.team/kit-docs/upgrade-21
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#driver
+ *
+ * ---
+ *
+ * `dbCredentials` - an object to define your connection to the database. For more info please check the docs
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#dbcredentials
+ *
+ * ---
+ *
+ * `migrations` - param let’s use specify custom table and schema(PostgreSQL only) for migrations.
+ * By default, all information about executed migrations will be stored in the database inside
+ * the `__drizzle_migrations` table, and for PostgreSQL, inside the drizzle schema.
+ * However, you can configure where to store those records.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#migrations
+ *
+ * ---
+ *
+ * `breakpoints` - param lets you enable/disable SQL statement breakpoints in generated migrations.
+ * It’s optional and true by default, it’s necessary to properly apply migrations on databases,
+ * that do not support multiple DDL alternation statements in one transaction(MySQL, SQLite, SingleStore) and
+ * Drizzle ORM has to apply them sequentially one by one.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#breakpoints
+ *
+ * ---
+ *
+ * `tablesFilters` - param lets you filter tables with glob syntax for db push command.
+ * It’s useful when you have only one database avaialable for several separate projects with separate sql schemas.
+ *
+ * How to define multi-project tables with Drizzle ORM — see https://orm.drizzle.team/docs/goodies#multi-project-schema
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#tablesfilters
+ *
+ * ---
+ *
+ * `schemaFilter` - parameter allows you to define which schema in PostgreSQL should be used for either introspect or push commands.
+ * This parameter accepts a single schema as a string or an array of schemas as strings.
+ * No glob pattern is supported here. By default, drizzle will use the public schema for both commands,
+ * but you can add any schema you need.
+ *
+ * For example, having schemaFilter: ["my_schema"] will only look for tables in both the database and
+ * drizzle schema that are a part of the my_schema schema.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#schemafilter
+ *
+ * ---
+ *
+ * `verbose` - command is used for drizzle-kit push commands and prints all statements that will be executed.
+ *
+ * > Note: This command will only print the statements that should be executed.
+ * To approve them before applying, please refer to the `strict` command.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#verbose
+ *
+ * ---
+ *
+ * `strict` - command is used for drizzle-kit push commands and will always ask for your confirmation,
+ * either to execute all statements needed to sync your schema with the database or not.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#strict
+ */
+export type Config =
+ & {
+ dialect: Dialect;
+ out?: string;
+ breakpoints?: boolean;
+ tablesFilter?: string | string[];
+ extensionsFilters?: 'postgis'[];
+ schemaFilter?: string | string[];
+ schema?: string | string[];
+ verbose?: boolean;
+ strict?: boolean;
+ migrations?: {
+ table?: string;
+ schema?: string;
+ prefix?: Prefix;
+ };
+ introspect?: {
+ casing: 'camel' | 'preserve';
+ };
+ }
+ & (
+ | {
+ dialect: Verify;
+ driver: Verify;
+ dbCredentials: {
+ url: string;
+ authToken?: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ dbCredentials: {
+ url: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ dbCredentials:
+ | ({
+ host: string;
+ port?: number;
+ user?: string;
+ password?: string;
+ database: string;
+ ssl?:
+ | boolean
+ | 'require'
+ | 'allow'
+ | 'prefer'
+ | 'verify-full'
+ | ConnectionOptions;
+ } & {})
+ | {
+ url: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ driver: Verify;
+ dbCredentials: {
+ database: string;
+ secretArn: string;
+ resourceArn: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ driver: Verify;
+ dbCredentials: {
+ url: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ dbCredentials:
+ | {
+ host: string;
+ port?: number;
+ user?: string;
+ password?: string;
+ database: string;
+ ssl?: string | SslOptions;
+ }
+ | {
+ url: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ driver: Verify;
+ dbCredentials: {
+ accountId: string;
+ databaseId: string;
+ token: string;
+ };
+ }
+ | {
+ dialect: Verify;
+ driver: Verify;
+ }
+ | {}
+ | {
+ dialect: Verify;
+ dbCredentials:
+ | {
+ host: string;
+ port?: number;
+ user?: string;
+ password?: string;
+ database: string;
+ ssl?: string | SslOptions;
+ }
+ | {
+ url: string;
+ };
+ }
+ );
+
+/**
+ * **You are currently using version 0.21.0+ of drizzle-kit. If you have just upgraded to this version, please make sure to read the changelog to understand what changes have been made and what
+ * adjustments may be necessary for you. See https://orm.drizzle.team/kit-docs/upgrade-21#how-to-migrate-to-0210**
+ *
+ * **Config** usage:
+ *
+ * `dialect` - mandatory and is responsible for explicitly providing a databse dialect you are using for all the commands
+ * *Possible values*: `postgresql`, `mysql`, `sqlite`, `singlestore`
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#dialect
+ *
+ * ---
+ * `schema` - param lets you define where your schema file/files live.
+ * You can have as many separate schema files as you want and define paths to them using glob or array of globs syntax.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#schema
+ *
+ * ---
+ * `out` - allows you to define the folder for your migrations and a folder, where drizzle will introspect the schema and relations
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#out
+ *
+ * ---
+ * `driver` - optional param that is responsible for explicitly providing a driver to use when accessing a database
+ * *Possible values*: `aws-data-api`, `d1-http`, `expo`, `turso`, `pglite`
+ * If you don't use AWS Data API, D1, Turso or Expo - ypu don't need this driver. You can check a driver strategy choice here: https://orm.drizzle.team/kit-docs/upgrade-21
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#driver
+ *
+ * ---
+ *
+ * `dbCredentials` - an object to define your connection to the database. For more info please check the docs
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#dbcredentials
+ *
+ * ---
+ *
+ * `migrations` - param let’s use specify custom table and schema(PostgreSQL only) for migrations.
+ * By default, all information about executed migrations will be stored in the database inside
+ * the `__drizzle_migrations` table, and for PostgreSQL, inside the drizzle schema.
+ * However, you can configure where to store those records.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#migrations
+ *
+ * ---
+ *
+ * `breakpoints` - param lets you enable/disable SQL statement breakpoints in generated migrations.
+ * It’s optional and true by default, it’s necessary to properly apply migrations on databases,
+ * that do not support multiple DDL alternation statements in one transaction(MySQL, SQLite, SingleStore) and
+ * Drizzle ORM has to apply them sequentially one by one.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#breakpoints
+ *
+ * ---
+ *
+ * `tablesFilters` - param lets you filter tables with glob syntax for db push command.
+ * It’s useful when you have only one database avaialable for several separate projects with separate sql schemas.
+ *
+ * How to define multi-project tables with Drizzle ORM — see https://orm.drizzle.team/docs/goodies#multi-project-schema
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#tablesfilters
+ *
+ * ---
+ *
+ * `schemaFilter` - parameter allows you to define which schema in PostgreSQL should be used for either introspect or push commands.
+ * This parameter accepts a single schema as a string or an array of schemas as strings.
+ * No glob pattern is supported here. By default, drizzle will use the public schema for both commands,
+ * but you can add any schema you need.
+ *
+ * For example, having schemaFilter: ["my_schema"] will only look for tables in both the database and
+ * drizzle schema that are a part of the my_schema schema.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#schemafilter
+ *
+ * ---
+ *
+ * `verbose` - command is used for drizzle-kit push commands and prints all statements that will be executed.
+ *
+ * > Note: This command will only print the statements that should be executed.
+ * To approve them before applying, please refer to the `strict` command.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#verbose
+ *
+ * ---
+ *
+ * `strict` - command is used for drizzle-kit push commands and will always ask for your confirmation,
+ * either to execute all statements needed to sync your schema with the database or not.
+ *
+ * See https://orm.drizzle.team/kit-docs/config-reference#strict
+ */
+export function defineConfig(config: Config) {
+ return config;
+}
diff --git a/drizzle-kit/src/introspect-mysql.ts b/drizzle-kit/src/introspect-mysql.ts
new file mode 100644
index 000000000..f206935a3
--- /dev/null
+++ b/drizzle-kit/src/introspect-mysql.ts
@@ -0,0 +1,879 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+import './@types/utils';
+import type { Casing } from './cli/validations/common';
+import {
+ Column,
+ ForeignKey,
+ Index,
+ MySqlSchema,
+ MySqlSchemaInternal,
+ PrimaryKey,
+ UniqueConstraint,
+} from './serializer/mysqlSchema';
+import { indexName } from './serializer/mysqlSerializer';
+
+// time precision to fsp
+// {mode: "string"} for timestamp by default
+
+const mysqlImportsList = new Set([
+ 'mysqlTable',
+ 'mysqlEnum',
+ 'bigint',
+ 'binary',
+ 'boolean',
+ 'char',
+ 'date',
+ 'datetime',
+ 'decimal',
+ 'double',
+ 'float',
+ 'int',
+ 'json',
+ 'mediumint',
+ 'real',
+ 'serial',
+ 'smallint',
+ 'text',
+ 'tinytext',
+ 'mediumtext',
+ 'longtext',
+ 'time',
+ 'timestamp',
+ 'tinyint',
+ 'varbinary',
+ 'varchar',
+ 'year',
+ 'enum',
+]);
+
+const objToStatement = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `"${it}": "${json[it]}"`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const objToStatement2 = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
+ statement += ' }';
+ return statement;
+};
+
+const timeConfig = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const binaryConfig = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const importsPatch = {
+ 'double precision': 'doublePrecision',
+ 'timestamp without time zone': 'timestamp',
+} as Record;
+
+const relations = new Set();
+
+const escapeColumnKey = (value: string) => {
+ if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) {
+ return `"${value}"`;
+ }
+ return value;
+};
+
+const prepareCasing = (casing?: Casing) => (value: string) => {
+ if (casing === 'preserve') {
+ return escapeColumnKey(value);
+ }
+ if (casing === 'camel') {
+ return escapeColumnKey(value.camelCase());
+ }
+
+ return escapeColumnKey(value);
+};
+
+export const schemaToTypeScript = (
+ schema: MySqlSchemaInternal,
+ casing: Casing,
+) => {
+ const withCasing = prepareCasing(casing);
+ // collectFKs
+ Object.values(schema.tables).forEach((table) => {
+ Object.values(table.foreignKeys).forEach((fk) => {
+ const relation = `${fk.tableFrom}-${fk.tableTo}`;
+ relations.add(relation);
+ });
+ });
+
+ const imports = Object.values(schema.tables).reduce(
+ (res, it) => {
+ const idxImports = Object.values(it.indexes).map((idx) => idx.isUnique ? 'uniqueIndex' : 'index');
+ const fkImpots = Object.values(it.foreignKeys).map((it) => 'foreignKey');
+ const pkImports = Object.values(it.compositePrimaryKeys).map(
+ (it) => 'primaryKey',
+ );
+ const uniqueImports = Object.values(it.uniqueConstraints).map(
+ (it) => 'unique',
+ );
+
+ res.mysql.push(...idxImports);
+ res.mysql.push(...fkImpots);
+ res.mysql.push(...pkImports);
+ res.mysql.push(...uniqueImports);
+
+ const columnImports = Object.values(it.columns)
+ .map((col) => {
+ let patched = importsPatch[col.type] ?? col.type;
+ patched = patched.startsWith('varchar(') ? 'varchar' : patched;
+ patched = patched.startsWith('char(') ? 'char' : patched;
+ patched = patched.startsWith('binary(') ? 'binary' : patched;
+ patched = patched.startsWith('decimal(') ? 'decimal' : patched;
+ patched = patched.startsWith('smallint(') ? 'smallint' : patched;
+ patched = patched.startsWith('enum(') ? 'mysqlEnum' : patched;
+ patched = patched.startsWith('datetime(') ? 'datetime' : patched;
+ patched = patched.startsWith('varbinary(') ? 'varbinary' : patched;
+ patched = patched.startsWith('int(') ? 'int' : patched;
+ patched = patched.startsWith('double(') ? 'double' : patched;
+ return patched;
+ })
+ .filter((type) => {
+ return mysqlImportsList.has(type);
+ });
+
+ res.mysql.push(...columnImports);
+ return res;
+ },
+ { mysql: [] as string[] },
+ );
+
+ const tableStatements = Object.values(schema.tables).map((table) => {
+ const func = 'mysqlTable';
+ let statement = '';
+ if (imports.mysql.includes(withCasing(table.name))) {
+ statement = `// Table name is in conflict with ${
+ withCasing(
+ table.name,
+ )
+ } import.\n// Please change to any other name, that is not in imports list\n`;
+ }
+ statement += `export const ${withCasing(table.name)} = ${func}("${table.name}", {\n`;
+ statement += createTableColumns(
+ Object.values(table.columns),
+ Object.values(table.foreignKeys),
+ withCasing,
+ table.name,
+ schema,
+ );
+ statement += '}';
+
+ // more than 2 fields or self reference or cyclic
+ const filteredFKs = Object.values(table.foreignKeys).filter((it) => {
+ return it.columnsFrom.length > 1 || isSelf(it);
+ });
+
+ if (
+ Object.keys(table.indexes).length > 0
+ || filteredFKs.length > 0
+ || Object.keys(table.compositePrimaryKeys).length > 0
+ || Object.keys(table.uniqueConstraints).length > 0
+ ) {
+ statement += ',\n';
+ statement += '(table) => {\n';
+ statement += '\treturn {\n';
+ statement += createTableIndexes(
+ table.name,
+ Object.values(table.indexes),
+ withCasing,
+ );
+ statement += createTableFKs(Object.values(filteredFKs), withCasing);
+ statement += createTablePKs(
+ Object.values(table.compositePrimaryKeys),
+ withCasing,
+ );
+ statement += createTableUniques(
+ Object.values(table.uniqueConstraints),
+ withCasing,
+ );
+ statement += '\t}\n';
+ statement += '}';
+ }
+
+ statement += ');';
+ return statement;
+ });
+
+ const uniqueMySqlImports = [
+ 'mysqlTable',
+ 'mysqlSchema',
+ 'AnyMySqlColumn',
+ ...new Set(imports.mysql),
+ ];
+ const importsTs = `import { ${
+ uniqueMySqlImports.join(
+ ', ',
+ )
+ } } from "drizzle-orm/mysql-core"\nimport { sql } from "drizzle-orm"\n\n`;
+
+ let decalrations = '';
+ decalrations += tableStatements.join('\n\n');
+
+ const file = importsTs + decalrations;
+
+ const schemaEntry = `
+ {
+ ${
+ Object.values(schema.tables)
+ .map((it) => withCasing(it.name))
+ .join(',')
+ }
+ }
+ `;
+
+ return {
+ file, // backward compatible, print to file
+ imports: importsTs,
+ decalrations,
+ schemaEntry,
+ };
+};
+
+const isCyclic = (fk: ForeignKey) => {
+ const key = `${fk.tableFrom}-${fk.tableTo}`;
+ const reverse = `${fk.tableTo}-${fk.tableFrom}`;
+ return relations.has(key) && relations.has(reverse);
+};
+
+const isSelf = (fk: ForeignKey) => {
+ return fk.tableFrom === fk.tableTo;
+};
+
+const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => {
+ if (isExpression) {
+ return `sql\`${defaultValue}\``;
+ }
+
+ return defaultValue;
+};
+
+const mapColumnDefaultForJson = (defaultValue: any) => {
+ if (
+ typeof defaultValue === 'string'
+ && defaultValue.startsWith("('")
+ && defaultValue.endsWith("')")
+ ) {
+ return defaultValue.substring(2, defaultValue.length - 2);
+ }
+
+ return defaultValue;
+};
+
+const column = (
+ type: string,
+ name: string,
+ casing: (value: string) => string,
+ defaultValue?: any,
+ autoincrement?: boolean,
+ onUpdate?: boolean,
+ isExpression?: boolean,
+) => {
+ let lowered = type;
+ if (!type.startsWith('enum(')) {
+ lowered = type.toLowerCase();
+ }
+
+ if (lowered === 'serial') {
+ return `${casing(name)}: serial("${name}")`;
+ }
+
+ if (lowered.startsWith('int')) {
+ const isUnsigned = lowered.startsWith('int unsigned');
+ let out = `${casing(name)}: int("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('tinyint')) {
+ const isUnsigned = lowered.startsWith('tinyint unsigned');
+ // let out = `${name.camelCase()}: tinyint("${name}")`;
+ let out: string = `${casing(name)}: tinyint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('smallint')) {
+ const isUnsigned = lowered.startsWith('smallint unsigned');
+ let out = `${casing(name)}: smallint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('mediumint')) {
+ const isUnsigned = lowered.startsWith('mediumint unsigned');
+ let out = `${casing(name)}: mediumint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('bigint')) {
+ const isUnsigned = lowered.startsWith('bigint unsigned');
+ let out = `${casing(name)}: bigint("${name}", { mode: "number"${isUnsigned ? ', unsigned: true' : ''} })`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'boolean') {
+ let out = `${casing(name)}: boolean("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('double')) {
+ let params:
+ | { precision: string | undefined; scale: string | undefined }
+ | undefined;
+
+ if (lowered.length > 6) {
+ const [precision, scale] = lowered
+ .slice(7, lowered.length - 1)
+ .split(',');
+ params = { precision, scale };
+ }
+
+ let out = params
+ ? `${casing(name)}: double("${name}", ${timeConfig(params)})`
+ : `${casing(name)}: double("${name}")`;
+
+ // let out = `${name.camelCase()}: double("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'float') {
+ let out = `${casing(name)}: float("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'real') {
+ let out = `${casing(name)}: real("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('timestamp')) {
+ const keyLength = 'timestamp'.length + 1;
+ let fsp = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ fsp = fsp ? fsp : null;
+
+ const params = timeConfig({ fsp, mode: "'string'" });
+
+ let out = params
+ ? `${casing(name)}: timestamp("${name}", ${params})`
+ : `${casing(name)}: timestamp("${name}")`;
+
+ // mysql has only CURRENT_TIMESTAMP, as I found from docs. But will leave now() for just a case
+ defaultValue = defaultValue === 'now()' || defaultValue === '(CURRENT_TIMESTAMP)'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+
+ let onUpdateNow = onUpdate ? '.onUpdateNow()' : '';
+ out += onUpdateNow;
+
+ return out;
+ }
+
+ if (lowered.startsWith('time')) {
+ const keyLength = 'time'.length + 1;
+ let fsp = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ fsp = fsp ? fsp : null;
+
+ const params = timeConfig({ fsp });
+
+ let out = params
+ ? `${casing(name)}: time("${name}", ${params})`
+ : `${casing(name)}: time("${name}")`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered === 'date') {
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t${
+ casing(
+ name,
+ )
+ }: date("${name}", { mode: 'string' })`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ if (lowered === 'text') {
+ let out = `${casing(name)}: text("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ if (lowered === 'tinytext') {
+ let out = `${casing(name)}: tinytext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ if (lowered === 'mediumtext') {
+ let out = `${casing(name)}: mediumtext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ if (lowered === 'longtext') {
+ let out = `${casing(name)}: longtext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'year') {
+ let out = `${casing(name)}: year("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql json can't have default value. Will leave it in case smth ;)
+ if (lowered === 'json') {
+ let out = `${casing(name)}: json("${name}")`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefaultForJson(defaultValue)})`
+ : '';
+
+ return out;
+ }
+
+ if (lowered.startsWith('varchar')) {
+ let out: string = `${
+ casing(
+ name,
+ )
+ }: varchar("${name}", { length: ${
+ lowered.substring(
+ 'varchar'.length + 1,
+ lowered.length - 1,
+ )
+ } })`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('char')) {
+ let out: string = `${
+ casing(
+ name,
+ )
+ }: char("${name}", { length: ${
+ lowered.substring(
+ 'char'.length + 1,
+ lowered.length - 1,
+ )
+ } })`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('datetime')) {
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t`;
+
+ const fsp = lowered.startsWith('datetime(')
+ ? lowered.substring('datetime'.length + 1, lowered.length - 1)
+ : undefined;
+
+ out = fsp
+ ? `${
+ casing(
+ name,
+ )
+ }: datetime("${name}", { mode: 'string', fsp: ${
+ lowered.substring(
+ 'datetime'.length + 1,
+ lowered.length - 1,
+ )
+ } })`
+ : `${casing(name)}: datetime("${name}", { mode: 'string'})`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('decimal')) {
+ let params:
+ | { precision: string | undefined; scale: string | undefined }
+ | undefined;
+
+ if (lowered.length > 7) {
+ const [precision, scale] = lowered
+ .slice(8, lowered.length - 1)
+ .split(',');
+ params = { precision, scale };
+ }
+
+ let out = params
+ ? `${casing(name)}: decimal("${name}", ${timeConfig(params)})`
+ : `${casing(name)}: decimal("${name}")`;
+
+ defaultValue = typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('binary')) {
+ const keyLength = 'binary'.length + 1;
+ let length = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ length = length ? length : null;
+
+ const params = binaryConfig({ length });
+
+ let out = params
+ ? `${casing(name)}: binary("${name}", ${params})`
+ : `${casing(name)}: binary("${name}")`;
+
+ defaultValue = defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('enum')) {
+ const values = lowered.substring('enum'.length + 1, lowered.length - 1);
+ let out = `${casing(name)}: mysqlEnum("${name}", [${values}])`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('varbinary')) {
+ const keyLength = 'varbinary'.length + 1;
+ let length = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ length = length ? length : null;
+
+ const params = binaryConfig({ length });
+
+ let out = params
+ ? `${casing(name)}: varbinary("${name}", ${params})`
+ : `${casing(name)}: varbinary("${name}")`;
+
+ defaultValue = defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ console.log('uknown', type);
+ return `// Warning: Can't parse ${type} from database\n\t// ${type}Type: ${type}("${name}")`;
+};
+
+const createTableColumns = (
+ columns: Column[],
+ fks: ForeignKey[],
+ casing: (val: string) => string,
+ tableName: string,
+ schema: MySqlSchemaInternal,
+): string => {
+ let statement = '';
+
+ // no self refs and no cyclic
+ const oneColumnsFKs = Object.values(fks)
+ .filter((it) => {
+ return !isSelf(it);
+ })
+ .filter((it) => it.columnsFrom.length === 1);
+
+ const fkByColumnName = oneColumnsFKs.reduce((res, it) => {
+ const arr = res[it.columnsFrom[0]] || [];
+ arr.push(it);
+ res[it.columnsFrom[0]] = arr;
+ return res;
+ }, {} as Record);
+
+ columns.forEach((it) => {
+ statement += '\t';
+ statement += column(
+ it.type,
+ it.name,
+ casing,
+ it.default,
+ it.autoincrement,
+ it.onUpdate,
+ schema.internal?.tables![tableName]?.columns[it.name]
+ ?.isDefaultAnExpression ?? false,
+ );
+ statement += it.primaryKey ? '.primaryKey()' : '';
+ statement += it.notNull ? '.notNull()' : '';
+
+ statement += it.generated
+ ? `.generatedAlwaysAs(sql\`${
+ it.generated.as.replace(
+ /`/g,
+ '\\`',
+ )
+ }\`, { mode: "${it.generated.type}" })`
+ : '';
+
+ const fks = fkByColumnName[it.name];
+ if (fks) {
+ const fksStatement = fks
+ .map((it) => {
+ const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null;
+ const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null;
+ const params = { onDelete, onUpdate };
+
+ const typeSuffix = isCyclic(it) ? ': AnyMySqlColumn' : '';
+
+ const paramsStr = objToStatement2(params);
+ if (paramsStr) {
+ return `.references(()${typeSuffix} => ${
+ casing(
+ it.tableTo,
+ )
+ }.${casing(it.columnsTo[0])}, ${paramsStr} )`;
+ }
+ return `.references(()${typeSuffix} => ${casing(it.tableTo)}.${
+ casing(
+ it.columnsTo[0],
+ )
+ })`;
+ })
+ .join('');
+ statement += fksStatement;
+ }
+
+ statement += ',\n';
+ });
+
+ return statement;
+};
+
+const createTableIndexes = (
+ tableName: string,
+ idxs: Index[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ idxs.forEach((it) => {
+ let idxKey = it.name.startsWith(tableName) && it.name !== tableName
+ ? it.name.slice(tableName.length + 1)
+ : it.name;
+ idxKey = idxKey.endsWith('_index')
+ ? idxKey.slice(0, -'_index'.length) + '_idx'
+ : idxKey;
+
+ idxKey = casing(idxKey);
+
+ const indexGeneratedName = indexName(tableName, it.columns);
+ const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
+
+ statement += `\t\t${idxKey}: `;
+ statement += it.isUnique ? 'uniqueIndex(' : 'index(';
+ statement += `${escapedIndexName})`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${casing(it)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTableUniques = (
+ unqs: UniqueConstraint[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ unqs.forEach((it) => {
+ const idxKey = casing(it.name);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'unique(';
+ statement += `"${it.name}")`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${casing(it)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTablePKs = (
+ pks: PrimaryKey[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ pks.forEach((it) => {
+ let idxKey = casing(it.name);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'primaryKey({ columns: [';
+ statement += `${
+ it.columns
+ .map((c) => {
+ return `table.${casing(c)}`;
+ })
+ .join(', ')
+ }]${it.name ? `, name: "${it.name}"` : ''}}`;
+ statement += '),';
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTableFKs = (
+ fks: ForeignKey[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ fks.forEach((it) => {
+ const isSelf = it.tableTo === it.tableFrom;
+ const tableTo = isSelf ? 'table' : `${casing(it.tableTo)}`;
+ statement += `\t\t${casing(it.name)}: foreignKey({\n`;
+ statement += `\t\t\tcolumns: [${
+ it.columnsFrom
+ .map((i) => `table.${casing(i)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tforeignColumns: [${
+ it.columnsTo
+ .map((i) => `${tableTo}.${casing(i)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tname: "${it.name}"\n`;
+ statement += `\t\t})`;
+
+ statement += it.onUpdate && it.onUpdate !== 'no action'
+ ? `.onUpdate("${it.onUpdate}")`
+ : '';
+
+ statement += it.onDelete && it.onDelete !== 'no action'
+ ? `.onDelete("${it.onDelete}")`
+ : '';
+
+ statement += `,\n`;
+ });
+
+ return statement;
+};
diff --git a/drizzle-kit/src/introspect-pg.ts b/drizzle-kit/src/introspect-pg.ts
new file mode 100644
index 000000000..b7a52b735
--- /dev/null
+++ b/drizzle-kit/src/introspect-pg.ts
@@ -0,0 +1,1314 @@
+import { getTableName, is } from 'drizzle-orm';
+import { AnyPgTable } from 'drizzle-orm/pg-core';
+import {
+ createTableRelationsHelpers,
+ extractTablesRelationalConfig,
+ Many,
+ One,
+ Relation,
+ Relations,
+} from 'drizzle-orm/relations';
+import { plural, singular } from 'pluralize';
+import './@types/utils';
+import { Casing } from './cli/validations/common';
+import { vectorOps } from './extensions/vector';
+import { assertUnreachable } from './global';
+import {
+ Column,
+ ForeignKey,
+ Index,
+ PgKitInternals,
+ PgSchemaInternal,
+ PrimaryKey,
+ UniqueConstraint,
+} from './serializer/pgSchema';
+import { indexName } from './serializer/pgSerializer';
+
+const pgImportsList = new Set([
+ 'pgTable',
+ 'pgEnum',
+ 'smallint',
+ 'integer',
+ 'bigint',
+ 'boolean',
+ 'text',
+ 'varchar',
+ 'char',
+ 'serial',
+ 'smallserial',
+ 'bigserial',
+ 'decimal',
+ 'numeric',
+ 'real',
+ 'json',
+ 'jsonb',
+ 'time',
+ 'timestamp',
+ 'date',
+ 'interval',
+ 'cidr',
+ 'inet',
+ 'macaddr',
+ 'macaddr8',
+ 'bigint',
+ 'doublePrecision',
+ 'uuid',
+ 'vector',
+ 'point',
+ 'line',
+ 'geometry',
+]);
+
+const objToStatement2 = (json: { [s: string]: unknown }) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
+ statement += ' }';
+ return statement;
+};
+
+const timeConfig = (json: { [s: string]: unknown }) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const possibleIntervals = [
+ 'year',
+ 'month',
+ 'day',
+ 'hour',
+ 'minute',
+ 'second',
+ 'year to month',
+ 'day to hour',
+ 'day to minute',
+ 'day to second',
+ 'hour to minute',
+ 'hour to second',
+ 'minute to second',
+];
+
+const intervalStrToObj = (str: string) => {
+ if (str.startsWith('interval(')) {
+ return {
+ precision: Number(str.substring('interval('.length, str.length - 1)),
+ };
+ }
+ const splitted = str.split(' ');
+ if (splitted.length === 1) {
+ return {};
+ }
+ const rest = splitted.slice(1, splitted.length).join(' ');
+ if (possibleIntervals.includes(rest)) {
+ return { fields: `"${rest}"` };
+ }
+
+ for (const s of possibleIntervals) {
+ if (rest.startsWith(`${s}(`)) {
+ return {
+ fields: `"${s}"`,
+ precision: Number(rest.substring(s.length + 1, rest.length - 1)),
+ };
+ }
+ }
+ return {};
+};
+
+const intervalConfig = (str: string) => {
+ const json = intervalStrToObj(str);
+ // json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys
+ .map((it: keyof typeof json) => `${it}: ${json[it]}`)
+ .join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => {
+ if (isExpression) {
+ return `sql\`${defaultValue}\``;
+ }
+
+ return defaultValue;
+};
+
+const importsPatch = {
+ 'double precision': 'doublePrecision',
+ 'timestamp without time zone': 'timestamp',
+ 'timestamp with time zone': 'timestamp',
+ 'time without time zone': 'time',
+ 'time with time zone': 'time',
+} as Record;
+
+const relations = new Set();
+
+const escapeColumnKey = (value: string) => {
+ if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) {
+ return `"${value}"`;
+ }
+ return value;
+};
+
+const withCasing = (value: string, casing: Casing) => {
+ if (casing === 'preserve') {
+ return escapeColumnKey(value);
+ }
+ if (casing === 'camel') {
+ return escapeColumnKey(value.camelCase());
+ }
+
+ assertUnreachable(casing);
+};
+
+export const relationsToTypeScriptForStudio = (
+ schema: Record>>,
+ relations: Record>>>,
+) => {
+ const relationalSchema: Record = {
+ ...Object.fromEntries(
+ Object.entries(schema)
+ .map(([key, val]) => {
+ // have unique keys across schemas
+ const mappedTableEntries = Object.entries(val).map((tableEntry) => {
+ return [`__${key}__.${tableEntry[0]}`, tableEntry[1]];
+ });
+
+ return mappedTableEntries;
+ })
+ .flat(),
+ ),
+ ...relations,
+ };
+
+ const relationsConfig = extractTablesRelationalConfig(
+ relationalSchema,
+ createTableRelationsHelpers,
+ );
+
+ let result = '';
+
+ function findColumnKey(table: AnyPgTable, columnName: string) {
+ for (const tableEntry of Object.entries(table)) {
+ const key = tableEntry[0];
+ const value = tableEntry[1];
+
+ if (value.name === columnName) {
+ return key;
+ }
+ }
+ }
+
+ Object.values(relationsConfig.tables).forEach((table) => {
+ const tableName = table.tsName.split('.')[1];
+ const relations = table.relations;
+ let hasRelations = false;
+ let relationsObjAsStr = '';
+ let hasOne = false;
+ let hasMany = false;
+
+ Object.values(relations).forEach((relation) => {
+ hasRelations = true;
+
+ if (is(relation, Many)) {
+ hasMany = true;
+ relationsObjAsStr += `\t\t${relation.fieldName}: many(${
+ relationsConfig.tableNamesMap[relation.referencedTableName].split(
+ '.',
+ )[1]
+ }${
+ typeof relation.relationName !== 'undefined'
+ ? `, { relationName: "${relation.relationName}"}`
+ : ''
+ }),`;
+ }
+
+ if (is(relation, One)) {
+ hasOne = true;
+ relationsObjAsStr += `\t\t${relation.fieldName}: one(${
+ relationsConfig.tableNamesMap[relation.referencedTableName].split(
+ '.',
+ )[1]
+ }, { fields: [${
+ relation.config?.fields.map(
+ (c) =>
+ `${
+ relationsConfig.tableNamesMap[
+ getTableName(relation.sourceTable)
+ ].split('.')[1]
+ }.${findColumnKey(relation.sourceTable, c.name)}`,
+ )
+ }], references: [${
+ relation.config?.references.map(
+ (c) =>
+ `${
+ relationsConfig.tableNamesMap[
+ getTableName(relation.referencedTable)
+ ].split('.')[1]
+ }.${findColumnKey(relation.referencedTable, c.name)}`,
+ )
+ }]${
+ typeof relation.relationName !== 'undefined'
+ ? `, relationName: "${relation.relationName}"`
+ : ''
+ }}),`;
+ }
+ });
+
+ if (hasRelations) {
+ result += `export const ${tableName}Relation = relations(${tableName}, ({${hasOne ? 'one' : ''}${
+ hasOne && hasMany ? ', ' : ''
+ }${hasMany ? 'many' : ''}}) => ({
+ ${relationsObjAsStr}
+ }));\n`;
+ }
+ });
+
+ return result;
+};
+
+function generateIdentityParams(identity: Column['identity']) {
+ let paramsObj = `{ name: "${identity!.name}"`;
+ if (identity?.startWith) {
+ paramsObj += `, startWith: ${identity.startWith}`;
+ }
+ if (identity?.increment) {
+ paramsObj += `, increment: ${identity.increment}`;
+ }
+ if (identity?.minValue) {
+ paramsObj += `, minValue: ${identity.minValue}`;
+ }
+ if (identity?.maxValue) {
+ paramsObj += `, maxValue: ${identity.maxValue}`;
+ }
+ if (identity?.cache) {
+ paramsObj += `, cache: ${identity.cache}`;
+ }
+ if (identity?.cycle) {
+ paramsObj += `, cycle: true`;
+ }
+ paramsObj += ' }';
+ if (identity?.type === 'always') {
+ return `.generatedAlwaysAsIdentity(${paramsObj})`;
+ }
+ return `.generatedByDefaultAsIdentity(${paramsObj})`;
+}
+
+export const paramNameFor = (name: string, schema?: string) => {
+ const schemaSuffix = schema && schema !== 'public' ? `In${schema.capitalise()}` : '';
+ return `${name}${schemaSuffix}`;
+};
+
+export const schemaToTypeScript = (
+ schema: PgSchemaInternal,
+ casing: Casing,
+) => {
+ // collectFKs
+ Object.values(schema.tables).forEach((table) => {
+ Object.values(table.foreignKeys).forEach((fk) => {
+ const relation = `${fk.tableFrom}-${fk.tableTo}`;
+ relations.add(relation);
+ });
+ });
+
+ const schemas = Object.fromEntries(
+ Object.entries(schema.schemas).map((it) => {
+ return [it[0], withCasing(it[1], casing)];
+ }),
+ );
+
+ const enumTypes = Object.values(schema.enums).reduce(
+ (acc, cur) => {
+ acc.add(`${cur.schema}.${cur.name}`);
+ return acc;
+ },
+ new Set(),
+ );
+
+ const imports = Object.values(schema.tables).reduce(
+ (res, it) => {
+ const idxImports = Object.values(it.indexes).map((idx) => idx.isUnique ? 'uniqueIndex' : 'index');
+ const fkImpots = Object.values(it.foreignKeys).map((it) => 'foreignKey');
+ if (
+ Object.values(it.foreignKeys).some((it) => isCyclic(it) && !isSelf(it))
+ ) {
+ res.pg.push('type AnyPgColumn');
+ }
+ const pkImports = Object.values(it.compositePrimaryKeys).map(
+ (it) => 'primaryKey',
+ );
+ const uniqueImports = Object.values(it.uniqueConstraints).map(
+ (it) => 'unique',
+ );
+
+ if (it.schema && it.schema !== 'public' && it.schema !== '') {
+ res.pg.push('pgSchema');
+ }
+
+ res.pg.push(...idxImports);
+ res.pg.push(...fkImpots);
+ res.pg.push(...pkImports);
+ res.pg.push(...uniqueImports);
+
+ const columnImports = Object.values(it.columns)
+ .map((col) => {
+ let patched: string = (importsPatch[col.type] || col.type).replace('[]', '');
+ patched = patched === 'double precision' ? 'doublePrecision' : patched;
+ patched = patched.startsWith('varchar(') ? 'varchar' : patched;
+ patched = patched.startsWith('char(') ? 'char' : patched;
+ patched = patched.startsWith('numeric(') ? 'numeric' : patched;
+ patched = patched.startsWith('time(') ? 'time' : patched;
+ patched = patched.startsWith('timestamp(') ? 'timestamp' : patched;
+ patched = patched.startsWith('vector(') ? 'vector' : patched;
+ patched = patched.startsWith('geometry(') ? 'geometry' : patched;
+ return patched;
+ })
+ .filter((type) => {
+ return pgImportsList.has(type);
+ });
+
+ res.pg.push(...columnImports);
+ return res;
+ },
+ { pg: [] as string[] },
+ );
+
+ Object.values(schema.sequences).forEach((it) => {
+ if (it.schema && it.schema !== 'public' && it.schema !== '') {
+ imports.pg.push('pgSchema');
+ } else if (it.schema === 'public') {
+ imports.pg.push('pgSequence');
+ }
+ });
+
+ Object.values(schema.enums).forEach((it) => {
+ if (it.schema && it.schema !== 'public' && it.schema !== '') {
+ imports.pg.push('pgSchema');
+ } else if (it.schema === 'public') {
+ imports.pg.push('pgEnum');
+ }
+ });
+
+ const enumStatements = Object.values(schema.enums)
+ .map((it) => {
+ const enumSchema = schemas[it.schema];
+ // const func = schema || schema === "public" ? "pgTable" : schema;
+ const paramName = paramNameFor(it.name, enumSchema);
+
+ const func = enumSchema ? `${enumSchema}.enum` : 'pgEnum';
+
+ const values = Object.values(it.values)
+ .map((it) => `'${it}'`)
+ .join(', ');
+ return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}", [${values}])\n`;
+ })
+ .join('')
+ .concat('\n');
+
+ const sequencesStatements = Object.values(schema.sequences)
+ .map((it) => {
+ const seqSchema = schemas[it.schema];
+ const paramName = paramNameFor(it.name, seqSchema);
+
+ const func = seqSchema ? `${seqSchema}.sequence` : 'pgSequence';
+
+ let params = '';
+
+ if (it.startWith) {
+ params += `, startWith: "${it.startWith}"`;
+ }
+ if (it.increment) {
+ params += `, increment: "${it.increment}"`;
+ }
+ if (it.minValue) {
+ params += `, minValue: "${it.minValue}"`;
+ }
+ if (it.maxValue) {
+ params += `, maxValue: "${it.maxValue}"`;
+ }
+ if (it.cache) {
+ params += `, cache: "${it.cache}"`;
+ }
+ if (it.cycle) {
+ params += `, cycle: true`;
+ } else {
+ params += `, cycle: false`;
+ }
+
+ return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}"${
+ params ? `, { ${params.trimChar(',')} }` : ''
+ })\n`;
+ })
+ .join('')
+ .concat('\n');
+
+ const schemaStatements = Object.entries(schemas)
+ // .filter((it) => it[0] !== "public")
+ .map((it) => {
+ return `export const ${it[1]} = pgSchema("${it[0]}");\n`;
+ })
+ .join('');
+
+ const tableStatements = Object.values(schema.tables).map((table) => {
+ const tableSchema = schemas[table.schema];
+ const paramName = paramNameFor(table.name, tableSchema);
+
+ const func = tableSchema ? `${tableSchema}.table` : 'pgTable';
+ let statement = `export const ${withCasing(paramName, casing)} = ${func}("${table.name}", {\n`;
+ statement += createTableColumns(
+ table.name,
+ Object.values(table.columns),
+ Object.values(table.foreignKeys),
+ enumTypes,
+ schemas,
+ casing,
+ schema.internal,
+ );
+ statement += '}';
+
+ // more than 2 fields or self reference or cyclic
+ // Andrii: I switched this one off until we will get custom names in .references()
+ // const filteredFKs = Object.values(table.foreignKeys).filter((it) => {
+ // return it.columnsFrom.length > 1 || isSelf(it);
+ // });
+
+ if (
+ Object.keys(table.indexes).length > 0
+ || Object.values(table.foreignKeys).length > 0
+ || Object.keys(table.compositePrimaryKeys).length > 0
+ || Object.keys(table.uniqueConstraints).length > 0
+ ) {
+ statement += ',\n';
+ statement += '(table) => {\n';
+ statement += '\treturn {\n';
+ statement += createTableIndexes(
+ table.name,
+ Object.values(table.indexes),
+ casing,
+ );
+ statement += createTableFKs(Object.values(table.foreignKeys), schemas, casing);
+ statement += createTablePKs(
+ Object.values(table.compositePrimaryKeys),
+ casing,
+ );
+ statement += createTableUniques(
+ Object.values(table.uniqueConstraints),
+ casing,
+ );
+ statement += '\t}\n';
+ statement += '}';
+ }
+
+ statement += ');';
+ return statement;
+ });
+
+ const uniquePgImports = ['pgTable', ...new Set(imports.pg)];
+
+ const importsTs = `import { ${
+ uniquePgImports.join(
+ ', ',
+ )
+ } } from "drizzle-orm/pg-core"
+ import { sql } from "drizzle-orm"\n\n`;
+
+ let decalrations = schemaStatements;
+ decalrations += enumStatements;
+ decalrations += sequencesStatements;
+ decalrations += '\n';
+ decalrations += tableStatements.join('\n\n');
+
+ const file = importsTs + decalrations;
+
+ // for drizzle studio query runner
+ const schemaEntry = `
+ {
+ ${
+ Object.values(schema.tables)
+ .map((it) => withCasing(it.name, casing))
+ .join(',\n')
+ }
+ }
+ `;
+
+ return { file, imports: importsTs, decalrations, schemaEntry };
+};
+
+const isCyclic = (fk: ForeignKey) => {
+ const key = `${fk.tableFrom}-${fk.tableTo}`;
+ const reverse = `${fk.tableTo}-${fk.tableFrom}`;
+ return relations.has(key) && relations.has(reverse);
+};
+
+const isSelf = (fk: ForeignKey) => {
+ return fk.tableFrom === fk.tableTo;
+};
+
+const buildArrayDefault = (defaultValue: string, typeName: string): string => {
+ if (typeof defaultValue === 'string' && !(defaultValue.startsWith('{') || defaultValue.startsWith("'{"))) {
+ return `sql\`${defaultValue}\``;
+ }
+ defaultValue = defaultValue.substring(2, defaultValue.length - 2);
+ return `[${
+ defaultValue
+ .split(/\s*,\s*/g)
+ .map((value) => {
+ // if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(typeName)) {
+ // return value;
+ // } else if (typeName === 'interval') {
+ // return value.replaceAll('"', "'");
+ // } else if (typeName === 'boolean') {
+ // return value === 't' ? 'true' : 'false';
+ if (typeName === 'json' || typeName === 'jsonb') {
+ return value
+ .substring(1, value.length - 1)
+ .replaceAll('\\', '');
+ }
+ return value;
+ // }
+ })
+ .join(', ')
+ }]`;
+};
+
+const mapDefault = (
+ tableName: string,
+ type: string,
+ name: string,
+ enumTypes: Set,
+ typeSchema: string,
+ defaultValue?: any,
+ internals?: PgKitInternals,
+) => {
+ const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false;
+ const isArray = internals?.tables[tableName]?.columns[name]?.isArray ?? false;
+ const lowered = type.toLowerCase().replace('[]', '');
+
+ if (isArray) {
+ return typeof defaultValue !== 'undefined' ? `.default(${buildArrayDefault(defaultValue, lowered)})` : '';
+ }
+
+ if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('integer')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('smallint')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('bigint')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('boolean')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('double precision')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('real')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('uuid')) {
+ return defaultValue === 'gen_random_uuid()'
+ ? '.defaultRandom()'
+ : defaultValue
+ ? `.default(sql\`${defaultValue}\`)`
+ : '';
+ }
+
+ if (lowered.startsWith('numeric')) {
+ defaultValue = defaultValue
+ ? defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`)
+ ? defaultValue.substring(1, defaultValue.length - 1)
+ : defaultValue
+ : undefined;
+ return defaultValue ? `.default('${mapColumnDefault(defaultValue, isExpression)}')` : '';
+ }
+
+ if (lowered.startsWith('timestamp')) {
+ return defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue === 'CURRENT_TIMESTAMP'
+ ? '.default(sql\`CURRENT_TIMESTAMP\`)'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ }
+
+ if (lowered.startsWith('time')) {
+ return defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ }
+
+ if (lowered.startsWith('interval')) {
+ return defaultValue ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered === 'date') {
+ return defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue === 'CURRENT_DATE'
+ ? `.default(sql\`${defaultValue}\`)`
+ : defaultValue
+ ? `.default(${defaultValue})`
+ : '';
+ }
+
+ if (lowered.startsWith('text')) {
+ return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
+ }
+
+ if (lowered.startsWith('jsonb')) {
+ const def = typeof defaultValue !== 'undefined'
+ ? defaultValue.replace(/::(.*?)(?,
+ typeSchema: string,
+ casing: Casing,
+ defaultValue?: any,
+ internals?: PgKitInternals,
+) => {
+ const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false;
+ const lowered = type.toLowerCase().replace('[]', '');
+
+ if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) {
+ let out = `${withCasing(name, casing)}: ${
+ withCasing(
+ paramNameFor(type.replace('[]', ''), typeSchema),
+ casing,
+ )
+ }("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('serial')) {
+ return `${withCasing(name, casing)}: serial("${name}")`;
+ }
+
+ if (lowered.startsWith('smallserial')) {
+ return `${withCasing(name, casing)}: smallserial("${name}")`;
+ }
+
+ if (lowered.startsWith('bigserial')) {
+ return `${
+ withCasing(
+ name,
+ casing,
+ )
+ }: bigserial("${name}", { mode: "bigint" })`;
+ }
+
+ if (lowered.startsWith('integer')) {
+ let out = `${withCasing(name, casing)}: integer("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('smallint')) {
+ let out = `${withCasing(name, casing)}: smallint("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('bigint')) {
+ let out = `// You can use { mode: "bigint" } if numbers are exceeding js number limitations\n\t`;
+ out += `${withCasing(name, casing)}: bigint("${name}", { mode: "number" })`;
+ return out;
+ }
+
+ if (lowered.startsWith('boolean')) {
+ let out = `${withCasing(name, casing)}: boolean("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('double precision')) {
+ let out = `${withCasing(name, casing)}: doublePrecision("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('real')) {
+ let out = `${withCasing(name, casing)}: real("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('uuid')) {
+ let out = `${withCasing(name, casing)}: uuid("${name}")`;
+
+ return out;
+ }
+
+ if (lowered.startsWith('numeric')) {
+ let params:
+ | { precision: string | undefined; scale: string | undefined }
+ | undefined;
+
+ if (lowered.length > 7) {
+ const [precision, scale] = lowered
+ .slice(8, lowered.length - 1)
+ .split(',');
+ params = { precision, scale };
+ }
+
+ let out = params
+ ? `${withCasing(name, casing)}: numeric("${name}", ${timeConfig(params)})`
+ : `${withCasing(name, casing)}: numeric("${name}")`;
+
+ return out;
+ }
+
+ if (lowered.startsWith('timestamp')) {
+ const withTimezone = lowered.includes('with time zone');
+ // const split = lowered.split(" ");
+ let precision = lowered.startsWith('timestamp(')
+ ? Number(
+ lowered
+ .split(' ')[0]
+ .substring('timestamp('.length, lowered.split(' ')[0].length - 1),
+ )
+ : null;
+ precision = precision ? precision : null;
+
+ const params = timeConfig({
+ precision,
+ withTimezone,
+ mode: "'string'",
+ });
+
+ let out = params
+ ? `${withCasing(name, casing)}: timestamp("${name}", ${params})`
+ : `${withCasing(name, casing)}: timestamp("${name}")`;
+
+ return out;
+ }
+
+ if (lowered.startsWith('time')) {
+ const withTimezone = lowered.includes('with time zone');
+
+ let precision = lowered.startsWith('time(')
+ ? Number(
+ lowered
+ .split(' ')[0]
+ .substring('time('.length, lowered.split(' ')[0].length - 1),
+ )
+ : null;
+ precision = precision ? precision : null;
+
+ const params = timeConfig({ precision, withTimezone });
+
+ let out = params
+ ? `${withCasing(name, casing)}: time("${name}", ${params})`
+ : `${withCasing(name, casing)}: time("${name}")`;
+
+ return out;
+ }
+
+ if (lowered.startsWith('interval')) {
+ // const withTimezone = lowered.includes("with time zone");
+ // const split = lowered.split(" ");
+ // let precision = split.length >= 2 ? Number(split[1].substring(1, 2)) : null;
+ // precision = precision ? precision : null;
+
+ const params = intervalConfig(lowered);
+
+ let out = params
+ ? `${withCasing(name, casing)}: interval("${name}", ${params})`
+ : `${withCasing(name, casing)}: interval("${name}")`;
+
+ return out;
+ }
+
+ if (lowered === 'date') {
+ let out = `${withCasing(name, casing)}: date("${name}")`;
+
+ return out;
+ }
+
+ if (lowered.startsWith('text')) {
+ let out = `${withCasing(name, casing)}: text("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('jsonb')) {
+ let out = `${withCasing(name, casing)}: jsonb("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('json')) {
+ let out = `${withCasing(name, casing)}: json("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('inet')) {
+ let out = `${withCasing(name, casing)}: inet("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('cidr')) {
+ let out = `${withCasing(name, casing)}: cidr("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('macaddr8')) {
+ let out = `${withCasing(name, casing)}: macaddr8("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('macaddr')) {
+ let out = `${withCasing(name, casing)}: macaddr("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('varchar')) {
+ let out: string;
+ if (lowered.length !== 7) {
+ out = `${
+ withCasing(
+ name,
+ casing,
+ )
+ }: varchar("${name}", { length: ${
+ lowered.substring(
+ 8,
+ lowered.length - 1,
+ )
+ } })`;
+ } else {
+ out = `${withCasing(name, casing)}: varchar("${name}")`;
+ }
+
+ return out;
+ }
+
+ if (lowered.startsWith('point')) {
+ let out: string = `${withCasing(name, casing)}: point("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('line')) {
+ let out: string = `${withCasing(name, casing)}: point("${name}")`;
+ return out;
+ }
+
+ if (lowered.startsWith('geometry')) {
+ let out: string = '';
+
+ let isGeoUnknown = false;
+
+ if (lowered.length !== 8) {
+ const geometryOptions = lowered.slice(9, -1).split(',');
+ if (geometryOptions.length === 1 && geometryOptions[0] !== '') {
+ out = `${withCasing(name, casing)}: geometry("${name}", { type: "${geometryOptions[0]}" })`;
+ } else if (geometryOptions.length === 2) {
+ out = `${withCasing(name, casing)}: geometry("${name}", { type: "${geometryOptions[0]}", srid: ${
+ geometryOptions[1]
+ } })`;
+ } else {
+ isGeoUnknown = true;
+ }
+ } else {
+ out = `${withCasing(name, casing)}: geometry("${name}")`;
+ }
+
+ if (isGeoUnknown) {
+ let unknown =
+ `// TODO: failed to parse geometry type because found more than 2 options inside geometry function '${type}'\n// Introspect is currently supporting only type and srid options\n`;
+ unknown += `\t${withCasing(name, casing)}: unknown("${name}")`;
+ return unknown;
+ }
+ return out;
+ }
+
+ if (lowered.startsWith('vector')) {
+ let out: string;
+ if (lowered.length !== 6) {
+ out = `${
+ withCasing(
+ name,
+ casing,
+ )
+ }: vector("${name}", { dimensions: ${
+ lowered.substring(
+ 7,
+ lowered.length - 1,
+ )
+ } })`;
+ } else {
+ out = `${withCasing(name, casing)}: vector("${name}")`;
+ }
+
+ return out;
+ }
+
+ if (lowered.startsWith('char')) {
+ let out: string;
+ if (lowered.length !== 4) {
+ out = `${
+ withCasing(
+ name,
+ casing,
+ )
+ }: char("${name}", { length: ${
+ lowered.substring(
+ 5,
+ lowered.length - 1,
+ )
+ } })`;
+ } else {
+ out = `${withCasing(name, casing)}: char("${name}")`;
+ }
+
+ return out;
+ }
+
+ let unknown = `// TODO: failed to parse database type '${type}'\n`;
+ unknown += `\t${withCasing(name, casing)}: unknown("${name}")`;
+ return unknown;
+};
+
+const dimensionsInArray = (size?: number): string => {
+ let res = '';
+ if (typeof size === 'undefined') return res;
+ for (let i = 0; i < size; i++) {
+ res += '.array()';
+ }
+ return res;
+};
+
+const createTableColumns = (
+ tableName: string,
+ columns: Column[],
+ fks: ForeignKey[],
+ enumTypes: Set,
+ schemas: Record,
+ casing: Casing,
+ internals: PgKitInternals,
+): string => {
+ let statement = '';
+
+ // no self refs and no cyclic
+ const oneColumnsFKs = Object.values(fks)
+ .filter((it) => {
+ return !isSelf(it);
+ })
+ .filter((it) => it.columnsFrom.length === 1);
+
+ const fkByColumnName = oneColumnsFKs.reduce((res, it) => {
+ const arr = res[it.columnsFrom[0]] || [];
+ arr.push(it);
+ res[it.columnsFrom[0]] = arr;
+ return res;
+ }, {} as Record);
+
+ columns.forEach((it) => {
+ const columnStatement = column(
+ tableName,
+ it.type,
+ it.name,
+ enumTypes,
+ it.typeSchema ?? 'public',
+ casing,
+ it.default,
+ internals,
+ );
+ statement += '\t';
+ statement += columnStatement;
+ // Provide just this in column function
+ if (internals?.tables[tableName]?.columns[it.name]?.isArray) {
+ statement += dimensionsInArray(
+ internals?.tables[tableName]?.columns[it.name]?.dimensions,
+ );
+ }
+ statement += mapDefault(
+ tableName,
+ it.type,
+ it.name,
+ enumTypes,
+ it.typeSchema ?? 'public',
+ it.default,
+ internals,
+ );
+ statement += it.primaryKey ? '.primaryKey()' : '';
+ statement += it.notNull && !it.identity ? '.notNull()' : '';
+
+ statement += it.identity ? generateIdentityParams(it.identity) : '';
+
+ statement += it.generated
+ ? `.generatedAlwaysAs(sql\`${it.generated.as}\`)`
+ : '';
+
+ // const fks = fkByColumnName[it.name];
+ // Andrii: I switched it off until we will get a custom naem setting in references
+ // if (fks) {
+ // const fksStatement = fks
+ // .map((it) => {
+ // const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null;
+ // const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null;
+ // const params = { onDelete, onUpdate };
+
+ // const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : '';
+
+ // const paramsStr = objToStatement2(params);
+ // const tableSchema = schemas[it.schemaTo || ''];
+ // const paramName = paramNameFor(it.tableTo, tableSchema);
+ // if (paramsStr) {
+ // return `.references(()${typeSuffix} => ${
+ // withCasing(
+ // paramName,
+ // casing,
+ // )
+ // }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`;
+ // }
+ // return `.references(()${typeSuffix} => ${
+ // withCasing(
+ // paramName,
+ // casing,
+ // )
+ // }.${withCasing(it.columnsTo[0], casing)})`;
+ // })
+ // .join('');
+ // statement += fksStatement;
+ // }
+
+ statement += ',\n';
+ });
+
+ return statement;
+};
+
+const createTableIndexes = (
+ tableName: string,
+ idxs: Index[],
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ idxs.forEach((it) => {
+ // we have issue when index is called as table called
+ let idxKey = it.name.startsWith(tableName) && it.name !== tableName
+ ? it.name.slice(tableName.length + 1)
+ : it.name;
+ idxKey = idxKey.endsWith('_index')
+ ? idxKey.slice(0, -'_index'.length) + '_idx'
+ : idxKey;
+
+ idxKey = withCasing(idxKey, casing);
+
+ const indexGeneratedName = indexName(
+ tableName,
+ it.columns.map((it) => it.expression),
+ );
+ const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
+
+ statement += `\t\t${idxKey}: `;
+ statement += it.isUnique ? 'uniqueIndex(' : 'index(';
+ statement += `${escapedIndexName})`;
+ statement += `${it.concurrently ? `.concurrently()` : ''}`;
+
+ statement += `.using("${it.method}", ${
+ it.columns
+ .map((it) => {
+ if (it.isExpression) {
+ return `sql\`${it.expression}\``;
+ } else {
+ return `table.${withCasing(it.expression, casing)}${it.asc ? '.asc()' : '.desc()'}${
+ it.nulls === 'first' ? '.nullsFirst()' : '.nullsLast()'
+ }${
+ it.opclass && vectorOps.includes(it.opclass)
+ ? `.op("${it.opclass}")`
+ : ''
+ }`;
+ }
+ })
+ .join(', ')
+ })`;
+ statement += it.where ? `.where(sql\`${it.where}\`)` : '';
+
+ function reverseLogic(mappedWith: Record): string {
+ let reversedString = '{';
+ for (const key in mappedWith) {
+ if (mappedWith.hasOwnProperty(key)) {
+ reversedString += `${key}: "${mappedWith[key]}",`;
+ }
+ }
+ reversedString = reversedString.length > 1
+ ? reversedString.slice(0, reversedString.length - 1)
+ : reversedString;
+ return `${reversedString}}`;
+ }
+
+ statement += it.with && Object.keys(it.with).length > 0
+ ? `.with(${reverseLogic(it.with)})`
+ : '';
+ statement += `,\n`;
+ });
+
+ return statement;
+};
+
+const createTablePKs = (pks: PrimaryKey[], casing: Casing): string => {
+ let statement = '';
+
+ pks.forEach((it) => {
+ let idxKey = withCasing(it.name, casing);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'primaryKey({ columns: [';
+ statement += `${
+ it.columns
+ .map((c) => {
+ return `table.${withCasing(c, casing)}`;
+ })
+ .join(', ')
+ }]${it.name ? `, name: "${it.name}"` : ''}}`;
+ statement += ')';
+ statement += `,\n`;
+ });
+
+ return statement;
+};
+
+const createTableUniques = (
+ unqs: UniqueConstraint[],
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ unqs.forEach((it) => {
+ const idxKey = withCasing(it.name, casing);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'unique(';
+ statement += `"${it.name}")`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${withCasing(it, casing)}`)
+ .join(', ')
+ })`;
+ statement += it.nullsNotDistinct ? `.nullsNotDistinct()` : '';
+ statement += `,\n`;
+ });
+
+ return statement;
+};
+
+const createTableFKs = (
+ fks: ForeignKey[],
+ schemas: Record,
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ fks.forEach((it) => {
+ const tableSchema = schemas[it.schemaTo || ''];
+ const paramName = paramNameFor(it.tableTo, tableSchema);
+
+ const isSelf = it.tableTo === it.tableFrom;
+ const tableTo = isSelf ? 'table' : `${withCasing(paramName, casing)}`;
+ statement += `\t\t${withCasing(it.name, casing)}: foreignKey({\n`;
+ statement += `\t\t\tcolumns: [${
+ it.columnsFrom
+ .map((i) => `table.${withCasing(i, casing)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tforeignColumns: [${
+ it.columnsTo
+ .map((i) => `${tableTo}.${withCasing(i, casing)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tname: "${it.name}"\n`;
+ statement += `\t\t})`;
+
+ statement += it.onUpdate && it.onUpdate !== 'no action'
+ ? `.onUpdate("${it.onUpdate}")`
+ : '';
+
+ statement += it.onDelete && it.onDelete !== 'no action'
+ ? `.onDelete("${it.onDelete}")`
+ : '';
+
+ statement += `,\n`;
+ });
+
+ return statement;
+};
diff --git a/drizzle-kit/src/introspect-singlestore.ts b/drizzle-kit/src/introspect-singlestore.ts
new file mode 100644
index 000000000..8aa6e3dd7
--- /dev/null
+++ b/drizzle-kit/src/introspect-singlestore.ts
@@ -0,0 +1,780 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+import './@types/utils';
+import type { Casing } from './cli/validations/common';
+import { Column, Index, PrimaryKey, SingleStoreSchemaInternal, UniqueConstraint } from './serializer/singlestoreSchema';
+import { indexName } from './serializer/singlestoreSerializer';
+
+// time precision to fsp
+// {mode: "string"} for timestamp by default
+
+const singlestoreImportsList = new Set([
+ 'singlestoreTable',
+ 'singlestoreEnum',
+ 'bigint',
+ 'binary',
+ 'boolean',
+ 'char',
+ 'date',
+ 'datetime',
+ 'decimal',
+ 'double',
+ 'float',
+ 'int',
+ 'json',
+ // TODO: add new type BSON
+ // TODO: add new type Blob
+ // TODO: add new type UUID
+ // TODO: add new type GUID
+ // TODO: add new type Vector
+ // TODO: add new type GeoPoint
+ 'mediumint',
+ 'real',
+ 'serial',
+ 'smallint',
+ 'text',
+ 'tinytext',
+ 'mediumtext',
+ 'longtext',
+ 'time',
+ 'timestamp',
+ 'tinyint',
+ 'varbinary',
+ 'varchar',
+ 'year',
+ 'enum',
+]);
+
+const objToStatement = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `"${it}": "${json[it]}"`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const objToStatement2 = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
+ statement += ' }';
+ return statement;
+};
+
+const timeConfig = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const binaryConfig = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
+ statement += ' }';
+ return statement;
+};
+
+const importsPatch = {
+ 'double precision': 'doublePrecision',
+ 'timestamp without time zone': 'timestamp',
+} as Record;
+
+const relations = new Set();
+
+const prepareCasing = (casing?: Casing) => (value: string) => {
+ if (typeof casing === 'undefined') {
+ return value;
+ }
+ if (casing === 'camel') {
+ return value.camelCase();
+ }
+
+ return value;
+};
+
+export const schemaToTypeScript = (
+ schema: SingleStoreSchemaInternal,
+ casing: Casing,
+) => {
+ const withCasing = prepareCasing(casing);
+
+ const imports = Object.values(schema.tables).reduce(
+ (res, it) => {
+ const idxImports = Object.values(it.indexes).map((idx) => idx.isUnique ? 'uniqueIndex' : 'index');
+ const pkImports = Object.values(it.compositePrimaryKeys).map(
+ (it) => 'primaryKey',
+ );
+ const uniqueImports = Object.values(it.uniqueConstraints).map(
+ (it) => 'unique',
+ );
+
+ res.singlestore.push(...idxImports);
+ res.singlestore.push(...pkImports);
+ res.singlestore.push(...uniqueImports);
+
+ const columnImports = Object.values(it.columns)
+ .map((col) => {
+ let patched = importsPatch[col.type] ?? col.type;
+ patched = patched.startsWith('varchar(') ? 'varchar' : patched;
+ patched = patched.startsWith('char(') ? 'char' : patched;
+ patched = patched.startsWith('binary(') ? 'binary' : patched;
+ patched = patched.startsWith('decimal(') ? 'decimal' : patched;
+ patched = patched.startsWith('smallint(') ? 'smallint' : patched;
+ patched = patched.startsWith('enum(') ? 'singlestoreEnum' : patched;
+ patched = patched.startsWith('datetime(') ? 'datetime' : patched;
+ patched = patched.startsWith('varbinary(') ? 'varbinary' : patched;
+ patched = patched.startsWith('int(') ? 'int' : patched;
+ return patched;
+ })
+ .filter((type) => {
+ return singlestoreImportsList.has(type);
+ });
+
+ res.singlestore.push(...columnImports);
+ return res;
+ },
+ { singlestore: [] as string[] },
+ );
+
+ const tableStatements = Object.values(schema.tables).map((table) => {
+ const func = 'singlestoreTable';
+ let statement = '';
+ if (imports.singlestore.includes(withCasing(table.name))) {
+ statement = `// Table name is in conflict with ${
+ withCasing(
+ table.name,
+ )
+ } import.\n// Please change to any other name, that is not in imports list\n`;
+ }
+ statement += `export const ${withCasing(table.name)} = ${func}("${table.name}", {\n`;
+ statement += createTableColumns(
+ Object.values(table.columns),
+ withCasing,
+ table.name,
+ schema,
+ );
+ statement += '}';
+
+ if (
+ Object.keys(table.indexes).length > 0
+ || Object.keys(table.compositePrimaryKeys).length > 0
+ || Object.keys(table.uniqueConstraints).length > 0
+ ) {
+ statement += ',\n';
+ statement += '(table) => {\n';
+ statement += '\treturn {\n';
+ statement += createTableIndexes(
+ table.name,
+ Object.values(table.indexes),
+ withCasing,
+ );
+ statement += createTablePKs(
+ Object.values(table.compositePrimaryKeys),
+ withCasing,
+ );
+ statement += createTableUniques(
+ Object.values(table.uniqueConstraints),
+ withCasing,
+ );
+ statement += '\t}\n';
+ statement += '}';
+ }
+
+ statement += ');';
+ return statement;
+ });
+
+ const uniqueSingleStoreImports = [
+ 'singlestoreTable',
+ 'singlestoreSchema',
+ 'AnySingleStoreColumn',
+ ...new Set(imports.singlestore),
+ ];
+ const importsTs = `import { ${
+ uniqueSingleStoreImports.join(
+ ', ',
+ )
+ } } from "drizzle-orm/singlestore-core"\nimport { sql } from "drizzle-orm"\n\n`;
+
+ let decalrations = '';
+ decalrations += tableStatements.join('\n\n');
+
+ const file = importsTs + decalrations;
+
+ const schemaEntry = `
+ {
+ ${
+ Object.values(schema.tables)
+ .map((it) => withCasing(it.name))
+ .join(',')
+ }
+ }
+ `;
+
+ return {
+ file, // backward compatible, print to file
+ imports: importsTs,
+ decalrations,
+ schemaEntry,
+ };
+};
+
+const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => {
+ if (isExpression) {
+ return `sql\`${defaultValue}\``;
+ }
+
+ return defaultValue;
+};
+
+const mapColumnDefaultForJson = (defaultValue: any) => {
+ if (
+ typeof defaultValue === 'string'
+ && defaultValue.startsWith("('")
+ && defaultValue.endsWith("')")
+ ) {
+ return defaultValue.substring(2, defaultValue.length - 2);
+ }
+
+ return defaultValue;
+};
+
+const column = (
+ type: string,
+ name: string,
+ casing: (value: string) => string,
+ defaultValue?: any,
+ autoincrement?: boolean,
+ onUpdate?: boolean,
+ isExpression?: boolean,
+) => {
+ let lowered = type;
+ if (!type.startsWith('enum(')) {
+ lowered = type.toLowerCase();
+ }
+
+ if (lowered === 'serial') {
+ return `${casing(name)}: serial("${name}")`;
+ }
+
+ if (lowered.startsWith('int')) {
+ const isUnsigned = lowered.startsWith('int unsigned');
+ let out = `${casing(name)}: int("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('tinyint')) {
+ const isUnsigned = lowered.startsWith('tinyint unsigned');
+ // let out = `${name.camelCase()}: tinyint("${name}")`;
+ let out: string = `${casing(name)}: tinyint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('smallint')) {
+ const isUnsigned = lowered.startsWith('smallint unsigned');
+ let out = `${casing(name)}: smallint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('mediumint')) {
+ const isUnsigned = lowered.startsWith('mediumint unsigned');
+ let out = `${casing(name)}: mediumint("${name}"${isUnsigned ? ', { unsigned: true }' : ''})`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('bigint')) {
+ const isUnsigned = lowered.startsWith('bigint unsigned');
+ let out = `${casing(name)}: bigint("${name}", { mode: "number"${isUnsigned ? ', unsigned: true' : ''} })`;
+ out += autoincrement ? `.autoincrement()` : '';
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'boolean') {
+ let out = `${casing(name)}: boolean("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('double')) {
+ let params:
+ | { precision: string | undefined; scale: string | undefined }
+ | undefined;
+
+ if (lowered.length > 6) {
+ const [precision, scale] = lowered
+ .slice(7, lowered.length - 1)
+ .split(',');
+ params = { precision, scale };
+ }
+
+ let out = params
+ ? `${casing(name)}: double("${name}", ${timeConfig(params)})`
+ : `${casing(name)}: double("${name}")`;
+
+ // let out = `${name.camelCase()}: double("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'float') {
+ let out = `${casing(name)}: float("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'real') {
+ let out = `${casing(name)}: real("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('timestamp')) {
+ const keyLength = 'timestamp'.length + 1;
+ let fsp = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ fsp = fsp ? fsp : null;
+
+ const params = timeConfig({ fsp, mode: "'string'" });
+
+ let out = params
+ ? `${casing(name)}: timestamp("${name}", ${params})`
+ : `${casing(name)}: timestamp("${name}")`;
+
+ // TODO: check if SingleStore has defaultNow() or now()
+ defaultValue = defaultValue === 'now()' || defaultValue === '(CURRENT_TIMESTAMP)'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+
+ // TODO: check if SingleStore has onUpdateNow()
+ let onUpdateNow = onUpdate ? '.onUpdateNow()' : '';
+ out += onUpdateNow;
+
+ return out;
+ }
+
+ if (lowered.startsWith('time')) {
+ const keyLength = 'time'.length + 1;
+ let fsp = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ fsp = fsp ? fsp : null;
+
+ const params = timeConfig({ fsp });
+
+ let out = params
+ ? `${casing(name)}: time("${name}", ${params})`
+ : `${casing(name)}: time("${name}")`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered === 'date') {
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t${
+ casing(
+ name,
+ )
+ }: date("${name}", { mode: 'string' })`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ // TODO: check if SingleStore has text can't have default value
+ if (lowered === 'text') {
+ let out = `${casing(name)}: text("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ // TODO: check if SingleStore has tinytext can't have default value
+ if (lowered === 'tinytext') {
+ let out = `${casing(name)}: tinytext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ // TODO: check if SingleStore has mediumtext can't have default value
+ if (lowered === 'mediumtext') {
+ let out = `${casing(name)}: mediumtext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql text can't have default value. Will leave it in case smth ;)
+ // TODO: check if SingleStore has longtext can't have default value
+ if (lowered === 'longtext') {
+ let out = `${casing(name)}: longtext("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'year') {
+ let out = `${casing(name)}: year("${name}")`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ // in mysql json can't have default value. Will leave it in case smth ;)
+ // TODO: check if SingleStore has json can't have default value
+ if (lowered === 'json') {
+ let out = `${casing(name)}: json("${name}")`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefaultForJson(defaultValue)})`
+ : '';
+
+ return out;
+ }
+
+ // TODO: add new type BSON
+
+ // TODO: add new type Blob
+
+ // TODO: add new type UUID
+
+ // TODO: add new type GUID
+
+ // TODO: add new type Vector
+
+ // TODO: add new type GeoPoint
+
+ if (lowered.startsWith('varchar')) {
+ let out: string = `${
+ casing(
+ name,
+ )
+ }: varchar("${name}", { length: ${
+ lowered.substring(
+ 'varchar'.length + 1,
+ lowered.length - 1,
+ )
+ } })`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('char')) {
+ let out: string = `${
+ casing(
+ name,
+ )
+ }: char("${name}", { length: ${
+ lowered.substring(
+ 'char'.length + 1,
+ lowered.length - 1,
+ )
+ } })`;
+
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('datetime')) {
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t`;
+
+ const fsp = lowered.startsWith('datetime(')
+ ? lowered.substring('datetime'.length + 1, lowered.length - 1)
+ : undefined;
+
+ out = fsp
+ ? `${
+ casing(
+ name,
+ )
+ }: datetime("${name}", { mode: 'string', fsp: ${
+ lowered.substring(
+ 'datetime'.length + 1,
+ lowered.length - 1,
+ )
+ } })`
+ : `${casing(name)}: datetime("${name}", { mode: 'string'})`;
+
+ defaultValue = defaultValue === 'now()'
+ ? '.defaultNow()'
+ : defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('decimal')) {
+ let params:
+ | { precision: string | undefined; scale: string | undefined }
+ | undefined;
+
+ if (lowered.length > 7) {
+ const [precision, scale] = lowered
+ .slice(8, lowered.length - 1)
+ .split(',');
+ params = { precision, scale };
+ }
+
+ let out = params
+ ? `${casing(name)}: decimal("${name}", ${timeConfig(params)})`
+ : `${casing(name)}: decimal("${name}")`;
+
+ defaultValue = typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('binary')) {
+ const keyLength = 'binary'.length + 1;
+ let length = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ length = length ? length : null;
+
+ const params = binaryConfig({ length });
+
+ let out = params
+ ? `${casing(name)}: binary("${name}", ${params})`
+ : `${casing(name)}: binary("${name}")`;
+
+ defaultValue = defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ if (lowered.startsWith('enum')) {
+ const values = lowered.substring('enum'.length + 1, lowered.length - 1);
+ let out = `${casing(name)}: singlestoreEnum("${name}", [${values}])`;
+ out += defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+ return out;
+ }
+
+ if (lowered.startsWith('varbinary')) {
+ const keyLength = 'varbinary'.length + 1;
+ let length = lowered.length > keyLength
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
+ : null;
+ length = length ? length : null;
+
+ const params = binaryConfig({ length });
+
+ let out = params
+ ? `${casing(name)}: varbinary("${name}", ${params})`
+ : `${casing(name)}: varbinary("${name}")`;
+
+ defaultValue = defaultValue
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
+ : '';
+
+ out += defaultValue;
+ return out;
+ }
+
+ console.log('uknown', type);
+ return `// Warning: Can't parse ${type} from database\n\t// ${type}Type: ${type}("${name}")`;
+};
+
+const createTableColumns = (
+ columns: Column[],
+ casing: (val: string) => string,
+ tableName: string,
+ schema: SingleStoreSchemaInternal,
+): string => {
+ let statement = '';
+
+ columns.forEach((it) => {
+ statement += '\t';
+ statement += column(
+ it.type,
+ it.name,
+ casing,
+ it.default,
+ it.autoincrement,
+ it.onUpdate,
+ schema.internal?.tables![tableName]?.columns[it.name]
+ ?.isDefaultAnExpression ?? false,
+ );
+ statement += it.primaryKey ? '.primaryKey()' : '';
+ statement += it.notNull ? '.notNull()' : '';
+
+ statement += it.generated
+ ? `.generatedAlwaysAs(sql\`${
+ it.generated.as.replace(
+ /`/g,
+ '\\`',
+ )
+ }\`, { mode: "${it.generated.type}" })`
+ : '';
+
+ statement += ',\n';
+ });
+
+ return statement;
+};
+
+const createTableIndexes = (
+ tableName: string,
+ idxs: Index[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ idxs.forEach((it) => {
+ let idxKey = it.name.startsWith(tableName) && it.name !== tableName
+ ? it.name.slice(tableName.length + 1)
+ : it.name;
+ idxKey = idxKey.endsWith('_index')
+ ? idxKey.slice(0, -'_index'.length) + '_idx'
+ : idxKey;
+
+ idxKey = casing(idxKey);
+
+ const indexGeneratedName = indexName(tableName, it.columns);
+ const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
+
+ statement += `\t\t${idxKey}: `;
+ statement += it.isUnique ? 'uniqueIndex(' : 'index(';
+ statement += `${escapedIndexName})`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${casing(it)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTableUniques = (
+ unqs: UniqueConstraint[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ unqs.forEach((it) => {
+ const idxKey = casing(it.name);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'unique(';
+ statement += `"${it.name}")`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${casing(it)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTablePKs = (
+ pks: PrimaryKey[],
+ casing: (value: string) => string,
+): string => {
+ let statement = '';
+
+ pks.forEach((it) => {
+ let idxKey = casing(it.name);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'primaryKey({ columns: [';
+ statement += `${
+ it.columns
+ .map((c) => {
+ return `table.${casing(c)}`;
+ })
+ .join(', ')
+ }]${it.name ? `, name: "${it.name}"` : ''}}`;
+ statement += '),';
+ statement += `\n`;
+ });
+
+ return statement;
+};
diff --git a/drizzle-kit/src/introspect-sqlite.ts b/drizzle-kit/src/introspect-sqlite.ts
new file mode 100644
index 000000000..b4a729f4c
--- /dev/null
+++ b/drizzle-kit/src/introspect-sqlite.ts
@@ -0,0 +1,457 @@
+/* eslint-disable @typescript-eslint/no-unsafe-argument */
+import './@types/utils';
+import type { Casing } from './cli/validations/common';
+import type {
+ Column,
+ ForeignKey,
+ Index,
+ PrimaryKey,
+ SQLiteSchema,
+ SQLiteSchemaInternal,
+ UniqueConstraint,
+} from './serializer/sqliteSchema';
+
+const sqliteImportsList = new Set([
+ 'sqliteTable',
+ 'integer',
+ 'real',
+ 'text',
+ 'numeric',
+ 'blob',
+]);
+
+export const indexName = (tableName: string, columns: string[]) => {
+ return `${tableName}_${columns.join('_')}_index`;
+};
+
+const objToStatement2 = (json: any) => {
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
+
+ const keys = Object.keys(json);
+ if (keys.length === 0) return;
+
+ let statement = '{ ';
+ statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
+ statement += ' }';
+ return statement;
+};
+
+const relations = new Set();
+
+const escapeColumnKey = (value: string) => {
+ if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) {
+ return `"${value}"`;
+ }
+ return value;
+};
+
+const withCasing = (value: string, casing?: Casing) => {
+ if (casing === 'preserve') {
+ return escapeColumnKey(value);
+ }
+ if (casing === 'camel') {
+ return escapeColumnKey(value.camelCase());
+ }
+
+ return value;
+};
+
+export const schemaToTypeScript = (
+ schema: SQLiteSchemaInternal,
+ casing: Casing,
+) => {
+ // collectFKs
+ Object.values(schema.tables).forEach((table) => {
+ Object.values(table.foreignKeys).forEach((fk) => {
+ const relation = `${fk.tableFrom}-${fk.tableTo}`;
+ relations.add(relation);
+ });
+ });
+
+ const imports = Object.values(schema.tables).reduce(
+ (res, it) => {
+ const idxImports = Object.values(it.indexes).map((idx) => idx.isUnique ? 'uniqueIndex' : 'index');
+ const fkImpots = Object.values(it.foreignKeys).map((it) => 'foreignKey');
+ const pkImports = Object.values(it.compositePrimaryKeys).map(
+ (it) => 'primaryKey',
+ );
+ const uniqueImports = Object.values(it.uniqueConstraints).map(
+ (it) => 'unique',
+ );
+
+ res.sqlite.push(...idxImports);
+ res.sqlite.push(...fkImpots);
+ res.sqlite.push(...pkImports);
+ res.sqlite.push(...uniqueImports);
+
+ const columnImports = Object.values(it.columns)
+ .map((col) => {
+ return col.type;
+ })
+ .filter((type) => {
+ return sqliteImportsList.has(type);
+ });
+
+ res.sqlite.push(...columnImports);
+ return res;
+ },
+ { sqlite: [] as string[] },
+ );
+
+ const tableStatements = Object.values(schema.tables).map((table) => {
+ const func = 'sqliteTable';
+ let statement = '';
+ if (imports.sqlite.includes(withCasing(table.name, casing))) {
+ statement = `// Table name is in conflict with ${
+ withCasing(
+ table.name,
+ casing,
+ )
+ } import.\n// Please change to any other name, that is not in imports list\n`;
+ }
+ statement += `export const ${withCasing(table.name, casing)} = ${func}("${table.name}", {\n`;
+ statement += createTableColumns(
+ Object.values(table.columns),
+ Object.values(table.foreignKeys),
+ casing,
+ );
+ statement += '}';
+
+ // more than 2 fields or self reference or cyclic
+ const filteredFKs = Object.values(table.foreignKeys).filter((it) => {
+ return it.columnsFrom.length > 1 || isSelf(it);
+ });
+
+ if (
+ Object.keys(table.indexes).length > 0
+ || filteredFKs.length > 0
+ || Object.keys(table.compositePrimaryKeys).length > 0
+ || Object.keys(table.uniqueConstraints).length > 0
+ ) {
+ statement += ',\n';
+ statement += '(table) => {\n';
+ statement += '\treturn {\n';
+ statement += createTableIndexes(
+ table.name,
+ Object.values(table.indexes),
+ casing,
+ );
+ statement += createTableFKs(Object.values(filteredFKs), casing);
+ statement += createTablePKs(
+ Object.values(table.compositePrimaryKeys),
+ casing,
+ );
+ statement += createTableUniques(
+ Object.values(table.uniqueConstraints),
+ casing,
+ );
+ statement += '\t}\n';
+ statement += '}';
+ }
+
+ statement += ');';
+ return statement;
+ });
+
+ const uniqueSqliteImports = [
+ 'sqliteTable',
+ 'AnySQLiteColumn',
+ ...new Set(imports.sqlite),
+ ];
+
+ const importsTs = `import { ${
+ uniqueSqliteImports.join(
+ ', ',
+ )
+ } } from "drizzle-orm/sqlite-core"
+ import { sql } from "drizzle-orm"\n\n`;
+
+ const decalrations = tableStatements.join('\n\n');
+
+ const file = importsTs + decalrations;
+
+ // for drizzle studio query runner
+ const schemaEntry = `
+ {
+ ${
+ Object.values(schema.tables)
+ .map((it) => withCasing(it.name, casing))
+ .join(',')
+ }
+ }
+ `;
+
+ return { file, imports: importsTs, decalrations, schemaEntry };
+};
+
+const isCyclic = (fk: ForeignKey) => {
+ const key = `${fk.tableFrom}-${fk.tableTo}`;
+ const reverse = `${fk.tableTo}-${fk.tableFrom}`;
+ return relations.has(key) && relations.has(reverse);
+};
+
+const isSelf = (fk: ForeignKey) => {
+ return fk.tableFrom === fk.tableTo;
+};
+
+const mapColumnDefault = (defaultValue: any) => {
+ if (
+ typeof defaultValue === 'string'
+ && defaultValue.startsWith('(')
+ && defaultValue.endsWith(')')
+ ) {
+ return `sql\`${defaultValue}\``;
+ }
+ // If default value is NULL as string it will come back from db as "'NULL'" and not just "NULL"
+ if (defaultValue === 'NULL') {
+ return `sql\`NULL\``;
+ }
+
+ if (
+ typeof defaultValue === 'string'
+ && defaultValue.startsWith("'")
+ && defaultValue.endsWith("'")
+ ) {
+ return defaultValue.substring(1, defaultValue.length - 1);
+ }
+
+ return defaultValue;
+};
+
+const column = (
+ type: string,
+ name: string,
+ defaultValue?: any,
+ autoincrement?: boolean,
+ casing?: Casing,
+) => {
+ let lowered = type;
+
+ if (lowered === 'integer') {
+ let out = `${withCasing(name, casing)}: integer("${name}")`;
+ // out += autoincrement ? `.autoincrement()` : "";
+ out += typeof defaultValue !== 'undefined'
+ ? `.default(${mapColumnDefault(defaultValue)})`
+ : '';
+ return out;
+ }
+
+ if (lowered === 'real') {
+ let out = `${withCasing(name, casing)}: real("${name}")`;
+ out += defaultValue ? `.default(${mapColumnDefault(defaultValue)})` : '';
+ return out;
+ }
+
+ if (lowered.startsWith('text')) {
+ const match = lowered.match(/\d+/);
+ let out: string;
+
+ if (match) {
+ out = `${withCasing(name, casing)}: text("${name}", { length: ${match[0]} })`;
+ } else {
+ out = `${withCasing(name, casing)}: text("${name}")`;
+ }
+
+ out += defaultValue ? `.default("${mapColumnDefault(defaultValue)}")` : '';
+ return out;
+ }
+
+ if (lowered === 'blob') {
+ let out = `${withCasing(name, casing)}: blob("${name}")`;
+ out += defaultValue ? `.default(${mapColumnDefault(defaultValue)})` : '';
+ return out;
+ }
+
+ if (lowered === 'numeric') {
+ let out = `${withCasing(name, casing)}: numeric("${name}")`;
+ out += defaultValue ? `.default(${mapColumnDefault(defaultValue)})` : '';
+ return out;
+ }
+
+ // console.log("uknown", type);
+ return `// Warning: Can't parse ${type} from database\n\t// ${type}Type: ${type}("${name}")`;
+};
+
+const createTableColumns = (
+ columns: Column[],
+ fks: ForeignKey[],
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ // no self refs and no cyclic
+ const oneColumnsFKs = Object.values(fks)
+ .filter((it) => {
+ return !isSelf(it);
+ })
+ .filter((it) => it.columnsFrom.length === 1);
+
+ const fkByColumnName = oneColumnsFKs.reduce((res, it) => {
+ const arr = res[it.columnsFrom[0]] || [];
+ arr.push(it);
+ res[it.columnsFrom[0]] = arr;
+ return res;
+ }, {} as Record);
+
+ columns.forEach((it) => {
+ statement += '\t';
+ statement += column(it.type, it.name, it.default, it.autoincrement, casing);
+ statement += it.primaryKey
+ ? `.primaryKey(${it.autoincrement ? '{ autoIncrement: true }' : ''})`
+ : '';
+ statement += it.notNull ? '.notNull()' : '';
+
+ statement += it.generated
+ ? `.generatedAlwaysAs(sql\`${
+ it.generated.as
+ .replace(/`/g, '\\`')
+ .slice(1, -1)
+ }\`, { mode: "${it.generated.type}" })`
+ : '';
+
+ const fks = fkByColumnName[it.name];
+ if (fks) {
+ const fksStatement = fks
+ .map((it) => {
+ const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null;
+ const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null;
+ const params = { onDelete, onUpdate };
+
+ const typeSuffix = isCyclic(it) ? ': AnySQLiteColumn' : '';
+
+ const paramsStr = objToStatement2(params);
+ if (paramsStr) {
+ return `.references(()${typeSuffix} => ${
+ withCasing(
+ it.tableTo,
+ casing,
+ )
+ }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`;
+ }
+ return `.references(()${typeSuffix} => ${
+ withCasing(
+ it.tableTo,
+ casing,
+ )
+ }.${withCasing(it.columnsTo[0], casing)})`;
+ })
+ .join('');
+ statement += fksStatement;
+ }
+
+ statement += ',\n';
+ });
+
+ return statement;
+};
+
+const createTableIndexes = (
+ tableName: string,
+ idxs: Index[],
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ idxs.forEach((it) => {
+ let idxKey = it.name.startsWith(tableName) && it.name !== tableName
+ ? it.name.slice(tableName.length + 1)
+ : it.name;
+ idxKey = idxKey.endsWith('_index')
+ ? idxKey.slice(0, -'_index'.length) + '_idx'
+ : idxKey;
+
+ idxKey = withCasing(idxKey, casing);
+
+ const indexGeneratedName = indexName(tableName, it.columns);
+ const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
+
+ statement += `\t\t${idxKey}: `;
+ statement += it.isUnique ? 'uniqueIndex(' : 'index(';
+ statement += `${escapedIndexName})`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${withCasing(it, casing)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTableUniques = (
+ unqs: UniqueConstraint[],
+ casing: Casing,
+): string => {
+ let statement = '';
+
+ unqs.forEach((it) => {
+ const idxKey = withCasing(it.name, casing);
+
+ statement += `\t\t${idxKey}: `;
+ statement += 'unique(';
+ statement += `"${it.name}")`;
+ statement += `.on(${
+ it.columns
+ .map((it) => `table.${withCasing(it, casing)}`)
+ .join(', ')
+ }),`;
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTablePKs = (pks: PrimaryKey[], casing: Casing): string => {
+ let statement = '';
+
+ pks.forEach((it, i) => {
+ statement += `\t\tpk${i}: `;
+ statement += 'primaryKey({ columns: [';
+ statement += `${
+ it.columns
+ .map((c) => {
+ return `table.${withCasing(c, casing)}`;
+ })
+ .join(', ')
+ }]${it.name ? `, name: "${it.name}"` : ''}}`;
+ statement += ')';
+ statement += `\n`;
+ });
+
+ return statement;
+};
+
+const createTableFKs = (fks: ForeignKey[], casing: Casing): string => {
+ let statement = '';
+
+ fks.forEach((it) => {
+ const isSelf = it.tableTo === it.tableFrom;
+ const tableTo = isSelf ? 'table' : `${withCasing(it.tableTo, casing)}`;
+ statement += `\t\t${withCasing(it.name, casing)}: foreignKey(() => ({\n`;
+ statement += `\t\t\tcolumns: [${
+ it.columnsFrom
+ .map((i) => `table.${withCasing(i, casing)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tforeignColumns: [${
+ it.columnsTo
+ .map((i) => `${tableTo}.${withCasing(i, casing)}`)
+ .join(', ')
+ }],\n`;
+ statement += `\t\t\tname: "${it.name}"\n`;
+ statement += `\t\t}))`;
+
+ statement += it.onUpdate && it.onUpdate !== 'no action'
+ ? `.onUpdate("${it.onUpdate}")`
+ : '';
+
+ statement += it.onDelete && it.onDelete !== 'no action'
+ ? `.onDelete("${it.onDelete}")`
+ : '';
+
+ statement += `,\n`;
+ });
+
+ return statement;
+};
diff --git a/drizzle-kit/src/jsonDiffer.js b/drizzle-kit/src/jsonDiffer.js
new file mode 100644
index 000000000..113d7e0a4
--- /dev/null
+++ b/drizzle-kit/src/jsonDiffer.js
@@ -0,0 +1,638 @@
+'use-strict';
+import { diff } from 'json-diff';
+
+export function diffForRenamedTables(pairs) {
+ // raname table1 to name of table2, so we can apply diffs
+ const renamed = pairs.map((it) => {
+ const from = it.from;
+ const to = it.to;
+ const newFrom = { ...from, name: to.name };
+ return [newFrom, to];
+ });
+
+ // find any alternations made to a renamed table
+ const altered = renamed.map((pair) => {
+ return diffForRenamedTable(pair[0], pair[1]);
+ });
+
+ return altered;
+}
+
+function diffForRenamedTable(t1, t2) {
+ t1.name = t2.name;
+ const diffed = diff(t1, t2) || {};
+ diffed.name = t2.name;
+
+ return findAlternationsInTable(diffed, t2.schema);
+}
+
+export function diffForRenamedColumn(t1, t2) {
+ const renamed = { ...t1, name: t2.name };
+ const diffed = diff(renamed, t2) || {};
+ diffed.name = t2.name;
+
+ return alternationsInColumn(diffed);
+}
+
+const update1to2 = (json) => {
+ Object.entries(json).forEach(([key, val]) => {
+ if ('object' !== typeof val) return;
+
+ if (val.hasOwnProperty('references')) {
+ const ref = val['references'];
+ const fkName = ref['foreignKeyName'];
+ const table = ref['table'];
+ const column = ref['column'];
+ const onDelete = ref['onDelete'];
+ const onUpdate = ref['onUpdate'];
+ const newRef = `${fkName};${table};${column};${onDelete ?? ''};${onUpdate ?? ''}`;
+ val['references'] = newRef;
+ } else {
+ update1to2(val);
+ }
+ });
+};
+
+const mapArraysDiff = (source, diff) => {
+ const sequence = [];
+ let sourceIndex = 0;
+ for (let i = 0; i < diff.length; i++) {
+ const it = diff[i];
+ if (it.length === 1) {
+ sequence.push({ type: 'same', value: source[sourceIndex] });
+ sourceIndex += 1;
+ } else {
+ if (it[0] === '-') {
+ sequence.push({ type: 'removed', value: it[1] });
+ } else {
+ sequence.push({ type: 'added', value: it[1], before: '' });
+ }
+ }
+ }
+ const result = sequence.reverse().reduce(
+ (acc, it) => {
+ if (it.type === 'same') {
+ acc.prev = it.value;
+ }
+
+ if (it.type === 'added' && acc.prev) {
+ it.before = acc.prev;
+ }
+ acc.result.push(it);
+ return acc;
+ },
+ { result: [] },
+ );
+
+ return result.result.reverse();
+};
+
+export function diffSchemasOrTables(left, right) {
+ left = JSON.parse(JSON.stringify(left));
+ right = JSON.parse(JSON.stringify(right));
+
+ const result = Object.entries(diff(left, right) ?? {});
+
+ const added = result
+ .filter((it) => it[0].endsWith('__added'))
+ .map((it) => it[1]);
+ const deleted = result
+ .filter((it) => it[0].endsWith('__deleted'))
+ .map((it) => it[1]);
+
+ return { added, deleted };
+}
+
+export function diffColumns(left, right) {
+ left = JSON.parse(JSON.stringify(left));
+ right = JSON.parse(JSON.stringify(right));
+ const result = diff(left, right) ?? {};
+
+ const alteredTables = Object.fromEntries(
+ Object.entries(result)
+ .filter((it) => {
+ return !(it[0].includes('__added') || it[0].includes('__deleted'));
+ })
+ .map((tableEntry) => {
+ // const entry = { name: it, ...result[it] }
+ const deletedColumns = Object.entries(tableEntry[1].columns ?? {})
+ .filter((it) => {
+ return it[0].endsWith('__deleted');
+ })
+ .map((it) => {
+ return it[1];
+ });
+
+ const addedColumns = Object.entries(tableEntry[1].columns ?? {})
+ .filter((it) => {
+ return it[0].endsWith('__added');
+ })
+ .map((it) => {
+ return it[1];
+ });
+
+ tableEntry[1].columns = {
+ added: addedColumns,
+ deleted: deletedColumns,
+ };
+ const table = left[tableEntry[0]];
+ return [
+ tableEntry[0],
+ { name: table.name, schema: table.schema, ...tableEntry[1] },
+ ];
+ }),
+ );
+
+ return alteredTables;
+}
+
+export function applyJsonDiff(json1, json2) {
+ json1 = JSON.parse(JSON.stringify(json1));
+ json2 = JSON.parse(JSON.stringify(json2));
+
+ // deep copy, needed because of the bug in diff library
+ const rawDiff = diff(json1, json2);
+
+ const difference = JSON.parse(JSON.stringify(rawDiff || {}));
+ difference.schemas = difference.schemas || {};
+ difference.tables = difference.tables || {};
+ difference.enums = difference.enums || {};
+ difference.sequences = difference.sequences || {};
+
+ // remove added/deleted schemas
+ const schemaKeys = Object.keys(difference.schemas);
+ for (let key of schemaKeys) {
+ if (key.endsWith('__added') || key.endsWith('__deleted')) {
+ delete difference.schemas[key];
+ continue;
+ }
+ }
+
+ // remove added/deleted tables
+ const tableKeys = Object.keys(difference.tables);
+ for (let key of tableKeys) {
+ if (key.endsWith('__added') || key.endsWith('__deleted')) {
+ delete difference.tables[key];
+ continue;
+ }
+
+ // supply table name and schema for altered tables
+ const table = json1.tables[key];
+ difference.tables[key] = {
+ name: table.name,
+ schema: table.schema,
+ ...difference.tables[key],
+ };
+ }
+
+ for (let [tableKey, tableValue] of Object.entries(difference.tables)) {
+ const table = difference.tables[tableKey];
+ const columns = tableValue.columns || {};
+ const columnKeys = Object.keys(columns);
+ for (let key of columnKeys) {
+ if (key.endsWith('__added') || key.endsWith('__deleted')) {
+ delete table.columns[key];
+ continue;
+ }
+ }
+
+ if (Object.keys(columns).length === 0) {
+ delete table['columns'];
+ }
+
+ if (
+ 'name' in table
+ && 'schema' in table
+ && Object.keys(table).length === 2
+ ) {
+ delete difference.tables[tableKey];
+ }
+ }
+
+ const enumsEntries = Object.entries(difference.enums);
+ const alteredEnums = enumsEntries
+ .filter((it) => !(it[0].includes('__added') || it[0].includes('__deleted')))
+ .map((it) => {
+ const enumEntry = json1.enums[it[0]];
+ const { name, schema, values } = enumEntry;
+
+ const sequence = mapArraysDiff(values, it[1].values);
+ const addedValues = sequence
+ .filter((it) => it.type === 'added')
+ .map((it) => {
+ return {
+ before: it.before,
+ value: it.value,
+ };
+ });
+ const deletedValues = sequence
+ .filter((it) => it.type === 'removed')
+ .map((it) => it.value);
+
+ return { name, schema, addedValues, deletedValues };
+ });
+
+ const sequencesEntries = Object.entries(difference.sequences);
+ const alteredSequences = sequencesEntries
+ .filter((it) => !(it[0].includes('__added') || it[0].includes('__deleted')) && 'values' in it[1])
+ .map((it) => {
+ return json2.sequences[it[0]];
+ });
+
+ const alteredTablesWithColumns = Object.values(difference.tables).map(
+ (table) => {
+ return findAlternationsInTable(table);
+ },
+ );
+
+ return {
+ alteredTablesWithColumns,
+ alteredEnums,
+ alteredSequences,
+ };
+}
+
+const findAlternationsInTable = (table) => {
+ // map each table to have altered, deleted or renamed columns
+
+ // in case no columns were altered, but indexes were
+ const columns = table.columns ?? {};
+
+ const altered = Object.keys(columns)
+ .filter((it) => !(it.includes('__deleted') || it.includes('__added')))
+ .map((it) => {
+ return { name: it, ...columns[it] };
+ });
+
+ const deletedIndexes = Object.fromEntries(
+ Object.entries(table.indexes__deleted || {})
+ .concat(
+ Object.entries(table.indexes || {}).filter((it) => it[0].includes('__deleted')),
+ )
+ .map((entry) => [entry[0].replace('__deleted', ''), entry[1]]),
+ );
+
+ const addedIndexes = Object.fromEntries(
+ Object.entries(table.indexes__added || {})
+ .concat(
+ Object.entries(table.indexes || {}).filter((it) => it[0].includes('__added')),
+ )
+ .map((entry) => [entry[0].replace('__added', ''), entry[1]]),
+ );
+
+ const alteredIndexes = Object.fromEntries(
+ Object.entries(table.indexes || {}).filter((it) => {
+ return !it[0].endsWith('__deleted') && !it[0].endsWith('__added');
+ }),
+ );
+
+ const deletedForeignKeys = Object.fromEntries(
+ Object.entries(table.foreignKeys__deleted || {})
+ .concat(
+ Object.entries(table.foreignKeys || {}).filter((it) => it[0].includes('__deleted')),
+ )
+ .map((entry) => [entry[0].replace('__deleted', ''), entry[1]]),
+ );
+
+ const addedForeignKeys = Object.fromEntries(
+ Object.entries(table.foreignKeys__added || {})
+ .concat(
+ Object.entries(table.foreignKeys || {}).filter((it) => it[0].includes('__added')),
+ )
+ .map((entry) => [entry[0].replace('__added', ''), entry[1]]),
+ );
+
+ const alteredForeignKeys = Object.fromEntries(
+ Object.entries(table.foreignKeys || {})
+ .filter(
+ (it) => !it[0].endsWith('__added') && !it[0].endsWith('__deleted'),
+ )
+ .map((entry) => [entry[0], entry[1]]),
+ );
+
+ const addedCompositePKs = Object.fromEntries(
+ Object.entries(table.compositePrimaryKeys || {}).filter((it) => {
+ return it[0].endsWith('__added');
+ }),
+ );
+
+ const deletedCompositePKs = Object.fromEntries(
+ Object.entries(table.compositePrimaryKeys || {}).filter((it) => {
+ return it[0].endsWith('__deleted');
+ }),
+ );
+
+ const alteredCompositePKs = Object.fromEntries(
+ Object.entries(table.compositePrimaryKeys || {}).filter((it) => {
+ return !it[0].endsWith('__deleted') && !it[0].endsWith('__added');
+ }),
+ );
+
+ const addedUniqueConstraints = Object.fromEntries(
+ Object.entries(table.uniqueConstraints || {}).filter((it) => {
+ return it[0].endsWith('__added');
+ }),
+ );
+
+ const deletedUniqueConstraints = Object.fromEntries(
+ Object.entries(table.uniqueConstraints || {}).filter((it) => {
+ return it[0].endsWith('__deleted');
+ }),
+ );
+
+ const alteredUniqueConstraints = Object.fromEntries(
+ Object.entries(table.uniqueConstraints || {}).filter((it) => {
+ return !it[0].endsWith('__deleted') && !it[0].endsWith('__added');
+ }),
+ );
+
+ const mappedAltered = altered.map((it) => alternationsInColumn(it)).filter(Boolean);
+
+ return {
+ name: table.name,
+ schema: table.schema || '',
+ altered: mappedAltered,
+ addedIndexes,
+ deletedIndexes,
+ alteredIndexes,
+ addedForeignKeys,
+ deletedForeignKeys,
+ alteredForeignKeys,
+ addedCompositePKs,
+ deletedCompositePKs,
+ alteredCompositePKs,
+ addedUniqueConstraints,
+ deletedUniqueConstraints,
+ alteredUniqueConstraints,
+ };
+};
+
+const alternationsInColumn = (column) => {
+ const altered = [column];
+ const result = altered
+ .filter((it) => {
+ if ('type' in it && it.type.__old.replace(' (', '(') === it.type.__new.replace(' (', '(')) {
+ return false;
+ }
+ return true;
+ })
+ .map((it) => {
+ if (typeof it.name !== 'string' && '__old' in it.name) {
+ // rename
+ return {
+ ...it,
+ name: { type: 'changed', old: it.name.__old, new: it.name.__new },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('type' in it) {
+ // type change
+ return {
+ ...it,
+ type: { type: 'changed', old: it.type.__old, new: it.type.__new },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('default' in it) {
+ return {
+ ...it,
+ default: {
+ type: 'changed',
+ old: it.default.__old,
+ new: it.default.__new,
+ },
+ };
+ }
+ if ('default__added' in it) {
+ const { default__added, ...others } = it;
+ return {
+ ...others,
+ default: { type: 'added', value: it.default__added },
+ };
+ }
+ if ('default__deleted' in it) {
+ const { default__deleted, ...others } = it;
+ return {
+ ...others,
+ default: { type: 'deleted', value: it.default__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('generated' in it) {
+ if ('as' in it.generated && 'type' in it.generated) {
+ return {
+ ...it,
+ generated: {
+ type: 'changed',
+ old: { as: it.generated.as.__old, type: it.generated.type.__old },
+ new: { as: it.generated.as.__new, type: it.generated.type.__new },
+ },
+ };
+ } else if ('as' in it.generated) {
+ return {
+ ...it,
+ generated: {
+ type: 'changed',
+ old: { as: it.generated.as.__old },
+ new: { as: it.generated.as.__new },
+ },
+ };
+ } else {
+ return {
+ ...it,
+ generated: {
+ type: 'changed',
+ old: { as: it.generated.type.__old },
+ new: { as: it.generated.type.__new },
+ },
+ };
+ }
+ }
+ if ('generated__added' in it) {
+ const { generated__added, ...others } = it;
+ return {
+ ...others,
+ generated: { type: 'added', value: it.generated__added },
+ };
+ }
+ if ('generated__deleted' in it) {
+ const { generated__deleted, ...others } = it;
+ return {
+ ...others,
+ generated: { type: 'deleted', value: it.generated__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('identity' in it) {
+ return {
+ ...it,
+ identity: {
+ type: 'changed',
+ old: it.identity.__old,
+ new: it.identity.__new,
+ },
+ };
+ }
+ if ('identity__added' in it) {
+ const { identity__added, ...others } = it;
+ return {
+ ...others,
+ identity: { type: 'added', value: it.identity__added },
+ };
+ }
+ if ('identity__deleted' in it) {
+ const { identity__deleted, ...others } = it;
+ return {
+ ...others,
+ identity: { type: 'deleted', value: it.identity__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('notNull' in it) {
+ return {
+ ...it,
+ notNull: {
+ type: 'changed',
+ old: it.notNull.__old,
+ new: it.notNull.__new,
+ },
+ };
+ }
+ if ('notNull__added' in it) {
+ const { notNull__added, ...others } = it;
+ return {
+ ...others,
+ notNull: { type: 'added', value: it.notNull__added },
+ };
+ }
+ if ('notNull__deleted' in it) {
+ const { notNull__deleted, ...others } = it;
+ return {
+ ...others,
+ notNull: { type: 'deleted', value: it.notNull__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('primaryKey' in it) {
+ return {
+ ...it,
+ primaryKey: {
+ type: 'changed',
+ old: it.primaryKey.__old,
+ new: it.primaryKey.__new,
+ },
+ };
+ }
+ if ('primaryKey__added' in it) {
+ const { notNull__added, ...others } = it;
+ return {
+ ...others,
+ primaryKey: { type: 'added', value: it.primaryKey__added },
+ };
+ }
+ if ('primaryKey__deleted' in it) {
+ const { notNull__deleted, ...others } = it;
+ return {
+ ...others,
+ primaryKey: { type: 'deleted', value: it.primaryKey__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('typeSchema' in it) {
+ return {
+ ...it,
+ typeSchema: {
+ type: 'changed',
+ old: it.typeSchema.__old,
+ new: it.typeSchema.__new,
+ },
+ };
+ }
+ if ('typeSchema__added' in it) {
+ const { typeSchema__added, ...others } = it;
+ return {
+ ...others,
+ typeSchema: { type: 'added', value: it.typeSchema__added },
+ };
+ }
+ if ('typeSchema__deleted' in it) {
+ const { typeSchema__deleted, ...others } = it;
+ return {
+ ...others,
+ typeSchema: { type: 'deleted', value: it.typeSchema__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('onUpdate' in it) {
+ return {
+ ...it,
+ onUpdate: {
+ type: 'changed',
+ old: it.onUpdate.__old,
+ new: it.onUpdate.__new,
+ },
+ };
+ }
+ if ('onUpdate__added' in it) {
+ const { onUpdate__added, ...others } = it;
+ return {
+ ...others,
+ onUpdate: { type: 'added', value: it.onUpdate__added },
+ };
+ }
+ if ('onUpdate__deleted' in it) {
+ const { onUpdate__deleted, ...others } = it;
+ return {
+ ...others,
+ onUpdate: { type: 'deleted', value: it.onUpdate__deleted },
+ };
+ }
+ return it;
+ })
+ .map((it) => {
+ if ('autoincrement' in it) {
+ return {
+ ...it,
+ autoincrement: {
+ type: 'changed',
+ old: it.autoincrement.__old,
+ new: it.autoincrement.__new,
+ },
+ };
+ }
+ if ('autoincrement__added' in it) {
+ const { autoincrement__added, ...others } = it;
+ return {
+ ...others,
+ autoincrement: { type: 'added', value: it.autoincrement__added },
+ };
+ }
+ if ('autoincrement__deleted' in it) {
+ const { autoincrement__deleted, ...others } = it;
+ return {
+ ...others,
+ autoincrement: { type: 'deleted', value: it.autoincrement__deleted },
+ };
+ }
+ return it;
+ })
+ .filter(Boolean);
+
+ return result[0];
+};
diff --git a/drizzle-kit/src/jsonStatements.ts b/drizzle-kit/src/jsonStatements.ts
new file mode 100644
index 000000000..090b0cdde
--- /dev/null
+++ b/drizzle-kit/src/jsonStatements.ts
@@ -0,0 +1,2686 @@
+import chalk from 'chalk';
+import { warning } from './cli/views';
+import { CommonSquashedSchema } from './schemaValidator';
+import { MySqlKitInternals, MySqlSchema, MySqlSquasher } from './serializer/mysqlSchema';
+import { Index, PgSchema, PgSquasher } from './serializer/pgSchema';
+import { SingleStoreKitInternals, SingleStoreSchema, SingleStoreSquasher } from './serializer/singlestoreSchema';
+import { SQLiteKitInternals, SQLiteSquasher } from './serializer/sqliteSchema';
+import { AlteredColumn, Column, Sequence, Table } from './snapshotsDiffer';
+
+export interface JsonSqliteCreateTableStatement {
+ type: 'sqlite_create_table';
+ tableName: string;
+ columns: Column[];
+ referenceData: {
+ name: string;
+ tableFrom: string;
+ columnsFrom: string[];
+ tableTo: string;
+ columnsTo: string[];
+ onUpdate?: string | undefined;
+ onDelete?: string | undefined;
+ }[];
+ compositePKs: string[][];
+ uniqueConstraints?: string[];
+}
+
+export interface JsonCreateTableStatement {
+ type: 'create_table';
+ tableName: string;
+ schema: string;
+ columns: Column[];
+ compositePKs: string[];
+ compositePkName?: string;
+ uniqueConstraints?: string[];
+ internals?: MySqlKitInternals | SingleStoreKitInternals;
+}
+
+export interface JsonDropTableStatement {
+ type: 'drop_table';
+ tableName: string;
+ schema: string;
+}
+
+export interface JsonRenameTableStatement {
+ type: 'rename_table';
+ fromSchema: string;
+ toSchema: string;
+ tableNameFrom: string;
+ tableNameTo: string;
+}
+
+export interface JsonCreateEnumStatement {
+ type: 'create_type_enum';
+ name: string;
+ schema: string;
+ values: string[];
+}
+
+export interface JsonDropEnumStatement {
+ type: 'drop_type_enum';
+ name: string;
+ schema: string;
+}
+
+export interface JsonMoveEnumStatement {
+ type: 'move_type_enum';
+ name: string;
+ schemaFrom: string;
+ schemaTo: string;
+}
+
+export interface JsonRenameEnumStatement {
+ type: 'rename_type_enum';
+ nameFrom: string;
+ nameTo: string;
+ schema: string;
+}
+
+export interface JsonAddValueToEnumStatement {
+ type: 'alter_type_add_value';
+ name: string;
+ schema: string;
+ value: string;
+ before: string;
+}
+
+export interface JsonCreateSequenceStatement {
+ type: 'create_sequence';
+ name: string;
+ schema: string;
+ values: {
+ increment?: string | undefined;
+ minValue?: string | undefined;
+ maxValue?: string | undefined;
+ startWith?: string | undefined;
+ cache?: string | undefined;
+ cycle?: boolean | undefined;
+ };
+}
+
+export interface JsonDropSequenceStatement {
+ type: 'drop_sequence';
+ name: string;
+ schema: string;
+}
+
+export interface JsonMoveSequenceStatement {
+ type: 'move_sequence';
+ name: string;
+ schemaFrom: string;
+ schemaTo: string;
+}
+
+export interface JsonRenameSequenceStatement {
+ type: 'rename_sequence';
+ nameFrom: string;
+ nameTo: string;
+ schema: string;
+}
+
+export interface JsonAlterSequenceStatement {
+ type: 'alter_sequence';
+ name: string;
+ schema: string;
+ values: {
+ increment?: string | undefined;
+ minValue?: string | undefined;
+ maxValue?: string | undefined;
+ startWith?: string | undefined;
+ cache?: string | undefined;
+ cycle?: boolean | undefined;
+ };
+}
+
+export interface JsonDropColumnStatement {
+ type: 'alter_table_drop_column';
+ tableName: string;
+ columnName: string;
+ schema: string;
+}
+
+export interface JsonAddColumnStatement {
+ type: 'alter_table_add_column';
+ tableName: string;
+ column: Column;
+ schema: string;
+}
+
+export interface JsonSqliteAddColumnStatement {
+ type: 'sqlite_alter_table_add_column';
+ tableName: string;
+ column: Column;
+ referenceData?: string;
+}
+
+export interface JsonCreateIndexStatement {
+ type: 'create_index';
+ tableName: string;
+ data: string;
+ schema: string;
+ internal?: MySqlKitInternals | SQLiteKitInternals | SingleStoreKitInternals;
+}
+
+export interface JsonPgCreateIndexStatement {
+ type: 'create_index_pg';
+ tableName: string;
+ data: Index;
+ schema: string;
+}
+
+export interface JsonReferenceStatement {
+ type: 'create_reference' | 'alter_reference' | 'delete_reference';
+ data: string;
+ schema: string;
+ tableName: string;
+ // fromTable: string;
+ // fromColumns: string[];
+ // toTable: string;
+ // toColumns: string[];
+ // foreignKeyName: string;
+ // onDelete?: string;
+ // onUpdate?: string;
+}
+
+export interface JsonCreateUniqueConstraint {
+ type: 'create_unique_constraint';
+ tableName: string;
+ data: string;
+ schema?: string;
+ constraintName?: string;
+}
+
+export interface JsonDeleteUniqueConstraint {
+ type: 'delete_unique_constraint';
+ tableName: string;
+ data: string;
+ schema?: string;
+ constraintName?: string;
+}
+
+export interface JsonAlterUniqueConstraint {
+ type: 'alter_unique_constraint';
+ tableName: string;
+ old: string;
+ new: string;
+ schema?: string;
+ oldConstraintName?: string;
+ newConstraintName?: string;
+}
+
+export interface JsonCreateCompositePK {
+ type: 'create_composite_pk';
+ tableName: string;
+ data: string;
+ schema?: string;
+ constraintName?: string;
+}
+
+export interface JsonDeleteCompositePK {
+ type: 'delete_composite_pk';
+ tableName: string;
+ data: string;
+ schema?: string;
+ constraintName?: string;
+}
+
+export interface JsonAlterCompositePK {
+ type: 'alter_composite_pk';
+ tableName: string;
+ old: string;
+ new: string;
+ schema?: string;
+ oldConstraintName?: string;
+ newConstraintName?: string;
+}
+
+export interface JsonAlterTableSetSchema {
+ type: 'alter_table_set_schema';
+ tableName: string;
+ schemaFrom: string;
+ schemaTo: string;
+}
+
+export interface JsonAlterTableRemoveFromSchema {
+ type: 'alter_table_remove_from_schema';
+ tableName: string;
+ schema: string;
+}
+
+export interface JsonAlterTableSetNewSchema {
+ type: 'alter_table_set_new_schema';
+ tableName: string;
+ from: string;
+ to: string;
+}
+
+export interface JsonCreateReferenceStatement extends JsonReferenceStatement {
+ type: 'create_reference';
+}
+
+export interface JsonAlterReferenceStatement extends JsonReferenceStatement {
+ type: 'alter_reference';
+ oldFkey: string;
+}
+
+export interface JsonDeleteReferenceStatement extends JsonReferenceStatement {
+ type: 'delete_reference';
+}
+
+export interface JsonDropIndexStatement {
+ type: 'drop_index';
+ tableName: string;
+ data: string;
+ schema: string;
+}
+
+export interface JsonRenameColumnStatement {
+ type: 'alter_table_rename_column';
+ tableName: string;
+ oldColumnName: string;
+ newColumnName: string;
+ schema: string;
+}
+
+export interface JsonAlterColumnTypeStatement {
+ type: 'alter_table_alter_column_set_type';
+ tableName: string;
+ columnName: string;
+ newDataType: string;
+ oldDataType: string;
+ schema: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+ columnGenerated?: { as: string; type: 'stored' | 'virtual' };
+}
+
+export interface JsonAlterColumnSetPrimaryKeyStatement {
+ type: 'alter_table_alter_column_set_pk';
+ tableName: string;
+ schema: string;
+ columnName: string;
+}
+
+export interface JsonAlterColumnDropPrimaryKeyStatement {
+ type: 'alter_table_alter_column_drop_pk';
+ tableName: string;
+ columnName: string;
+ schema: string;
+}
+
+export interface JsonAlterColumnSetDefaultStatement {
+ type: 'alter_table_alter_column_set_default';
+ tableName: string;
+ columnName: string;
+ newDefaultValue: any;
+ oldDefaultValue?: any;
+ schema: string;
+ newDataType: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnDropDefaultStatement {
+ type: 'alter_table_alter_column_drop_default';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnSetNotNullStatement {
+ type: 'alter_table_alter_column_set_notnull';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnDropNotNullStatement {
+ type: 'alter_table_alter_column_drop_notnull';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnSetGeneratedStatement {
+ type: 'alter_table_alter_column_set_generated';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+ columnGenerated?: { as: string; type: 'stored' | 'virtual' };
+}
+export interface JsonAlterColumnSetIdentityStatement {
+ type: 'alter_table_alter_column_set_identity';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ identity: string;
+}
+
+export interface JsonAlterColumnDropIdentityStatement {
+ type: 'alter_table_alter_column_drop_identity';
+ tableName: string;
+ columnName: string;
+ schema: string;
+}
+
+export interface JsonAlterColumnAlterIdentityStatement {
+ type: 'alter_table_alter_column_change_identity';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ identity: string;
+ oldIdentity: string;
+}
+
+export interface JsonAlterColumnDropGeneratedStatement {
+ type: 'alter_table_alter_column_drop_generated';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+ columnGenerated?: { as: string; type: 'stored' | 'virtual' };
+ oldColumn?: Column;
+}
+
+export interface JsonAlterColumnAlterGeneratedStatement {
+ type: 'alter_table_alter_column_alter_generated';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+ columnGenerated?: { as: string; type: 'stored' | 'virtual' };
+}
+
+export interface JsonAlterColumnSetOnUpdateStatement {
+ type: 'alter_table_alter_column_set_on_update';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnDropOnUpdateStatement {
+ type: 'alter_table_alter_column_drop_on_update';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnSetAutoincrementStatement {
+ type: 'alter_table_alter_column_set_autoincrement';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonAlterColumnDropAutoincrementStatement {
+ type: 'alter_table_alter_column_drop_autoincrement';
+ tableName: string;
+ columnName: string;
+ schema: string;
+ newDataType: string;
+ columnDefault: string;
+ columnOnUpdate: boolean;
+ columnNotNull: boolean;
+ columnAutoIncrement: boolean;
+ columnPk: boolean;
+}
+
+export interface JsonCreateSchema {
+ type: 'create_schema';
+ name: string;
+}
+
+export interface JsonDropSchema {
+ type: 'drop_schema';
+ name: string;
+}
+
+export interface JsonRenameSchema {
+ type: 'rename_schema';
+ from: string;
+ to: string;
+}
+
+export type JsonAlterColumnStatement =
+ | JsonRenameColumnStatement
+ | JsonAlterColumnTypeStatement
+ | JsonAlterColumnSetDefaultStatement
+ | JsonAlterColumnDropDefaultStatement
+ | JsonAlterColumnSetNotNullStatement
+ | JsonAlterColumnDropNotNullStatement
+ | JsonAlterColumnDropOnUpdateStatement
+ | JsonAlterColumnSetOnUpdateStatement
+ | JsonAlterColumnDropAutoincrementStatement
+ | JsonAlterColumnSetAutoincrementStatement
+ | JsonAlterColumnSetPrimaryKeyStatement
+ | JsonAlterColumnDropPrimaryKeyStatement
+ | JsonAlterColumnSetGeneratedStatement
+ | JsonAlterColumnDropGeneratedStatement
+ | JsonAlterColumnAlterGeneratedStatement
+ | JsonAlterColumnSetIdentityStatement
+ | JsonAlterColumnAlterIdentityStatement
+ | JsonAlterColumnDropIdentityStatement;
+
+export type JsonStatement =
+ | JsonAlterColumnStatement
+ | JsonCreateTableStatement
+ | JsonDropTableStatement
+ | JsonRenameTableStatement
+ | JsonCreateEnumStatement
+ | JsonDropEnumStatement
+ | JsonMoveEnumStatement
+ | JsonRenameEnumStatement
+ | JsonAddValueToEnumStatement
+ | JsonDropColumnStatement
+ | JsonAddColumnStatement
+ | JsonCreateIndexStatement
+ | JsonCreateReferenceStatement
+ | JsonAlterReferenceStatement
+ | JsonDeleteReferenceStatement
+ | JsonDropIndexStatement
+ | JsonReferenceStatement
+ | JsonSqliteCreateTableStatement
+ | JsonSqliteAddColumnStatement
+ | JsonCreateCompositePK
+ | JsonDeleteCompositePK
+ | JsonAlterCompositePK
+ | JsonCreateUniqueConstraint
+ | JsonDeleteUniqueConstraint
+ | JsonAlterUniqueConstraint
+ | JsonCreateSchema
+ | JsonDropSchema
+ | JsonRenameSchema
+ | JsonAlterTableSetSchema
+ | JsonAlterTableRemoveFromSchema
+ | JsonAlterTableSetNewSchema
+ | JsonPgCreateIndexStatement
+ | JsonAlterSequenceStatement
+ | JsonDropSequenceStatement
+ | JsonCreateSequenceStatement
+ | JsonMoveSequenceStatement
+ | JsonRenameSequenceStatement;
+
+export const preparePgCreateTableJson = (
+ table: Table,
+ // TODO: remove?
+ json2: PgSchema,
+): JsonCreateTableStatement => {
+ const { name, schema, columns, compositePrimaryKeys, uniqueConstraints } = table;
+ const tableKey = `${schema || 'public'}.${name}`;
+
+ // TODO: @AndriiSherman. We need this, will add test cases
+ const compositePkName = Object.values(compositePrimaryKeys).length > 0
+ ? json2.tables[tableKey].compositePrimaryKeys[
+ `${PgSquasher.unsquashPK(Object.values(compositePrimaryKeys)[0]).name}`
+ ].name
+ : '';
+
+ return {
+ type: 'create_table',
+ tableName: name,
+ schema,
+ columns: Object.values(columns),
+ compositePKs: Object.values(compositePrimaryKeys),
+ compositePkName: compositePkName,
+ uniqueConstraints: Object.values(uniqueConstraints),
+ };
+};
+
+export const prepareMySqlCreateTableJson = (
+ table: Table,
+ // TODO: remove?
+ json2: MySqlSchema,
+ // we need it to know if some of the indexes(and in future other parts) are expressions or columns
+ // didn't change mysqlserialaizer, because it will break snapshots and diffs and it's hard to detect
+ // if previously it was an expression or column
+ internals: MySqlKitInternals,
+): JsonCreateTableStatement => {
+ const { name, schema, columns, compositePrimaryKeys, uniqueConstraints } = table;
+
+ return {
+ type: 'create_table',
+ tableName: name,
+ schema,
+ columns: Object.values(columns),
+ compositePKs: Object.values(compositePrimaryKeys),
+ compositePkName: Object.values(compositePrimaryKeys).length > 0
+ ? json2.tables[name].compositePrimaryKeys[
+ MySqlSquasher.unsquashPK(Object.values(compositePrimaryKeys)[0])
+ .name
+ ].name
+ : '',
+ uniqueConstraints: Object.values(uniqueConstraints),
+ internals,
+ };
+};
+
+export const prepareSingleStoreCreateTableJson = (
+ table: Table,
+ // TODO: remove?
+ json2: SingleStoreSchema,
+ // we need it to know if some of the indexes(and in future other parts) are expressions or columns
+ // didn't change singlestoreserialaizer, because it will break snapshots and diffs and it's hard to detect
+ // if previously it was an expression or column
+ internals: SingleStoreKitInternals,
+): JsonCreateTableStatement => {
+ const { name, schema, columns, compositePrimaryKeys, uniqueConstraints } = table;
+
+ return {
+ type: 'create_table',
+ tableName: name,
+ schema,
+ columns: Object.values(columns),
+ compositePKs: Object.values(compositePrimaryKeys),
+ compositePkName: Object.values(compositePrimaryKeys).length > 0
+ ? json2.tables[name].compositePrimaryKeys[
+ SingleStoreSquasher.unsquashPK(Object.values(compositePrimaryKeys)[0])
+ .name
+ ].name
+ : '',
+ uniqueConstraints: Object.values(uniqueConstraints),
+ internals,
+ };
+};
+
+export const prepareSQLiteCreateTable = (
+ table: Table,
+ action?: 'push' | undefined,
+): JsonSqliteCreateTableStatement => {
+ const { name, columns, uniqueConstraints } = table;
+
+ const references: string[] = Object.values(table.foreignKeys);
+
+ const composites: string[][] = Object.values(table.compositePrimaryKeys).map(
+ (it) => SQLiteSquasher.unsquashPK(it),
+ );
+
+ const fks = references.map((it) =>
+ action === 'push'
+ ? SQLiteSquasher.unsquashPushFK(it)
+ : SQLiteSquasher.unsquashFK(it)
+ );
+
+ return {
+ type: 'sqlite_create_table',
+ tableName: name,
+ columns: Object.values(columns),
+ referenceData: fks,
+ compositePKs: composites,
+ uniqueConstraints: Object.values(uniqueConstraints),
+ };
+};
+
+export const prepareDropTableJson = (table: Table): JsonDropTableStatement => {
+ return {
+ type: 'drop_table',
+ tableName: table.name,
+ schema: table.schema,
+ };
+};
+
+export const prepareRenameTableJson = (
+ tableFrom: Table,
+ tableTo: Table,
+): JsonRenameTableStatement => {
+ return {
+ type: 'rename_table',
+ fromSchema: tableTo.schema,
+ toSchema: tableTo.schema,
+ tableNameFrom: tableFrom.name,
+ tableNameTo: tableTo.name,
+ };
+};
+
+export const prepareCreateEnumJson = (
+ name: string,
+ schema: string,
+ values: string[],
+): JsonCreateEnumStatement => {
+ return {
+ type: 'create_type_enum',
+ name: name,
+ schema: schema,
+ values,
+ };
+};
+
+// https://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/
+export const prepareAddValuesToEnumJson = (
+ name: string,
+ schema: string,
+ values: { value: string; before: string }[],
+): JsonAddValueToEnumStatement[] => {
+ return values.map((it) => {
+ return {
+ type: 'alter_type_add_value',
+ name: name,
+ schema: schema,
+ value: it.value,
+ before: it.before,
+ };
+ });
+};
+
+export const prepareDropEnumJson = (
+ name: string,
+ schema: string,
+): JsonDropEnumStatement => {
+ return {
+ type: 'drop_type_enum',
+ name: name,
+ schema: schema,
+ };
+};
+
+export const prepareMoveEnumJson = (
+ name: string,
+ schemaFrom: string,
+ schemaTo: string,
+): JsonMoveEnumStatement => {
+ return {
+ type: 'move_type_enum',
+ name: name,
+ schemaFrom,
+ schemaTo,
+ };
+};
+
+export const prepareRenameEnumJson = (
+ nameFrom: string,
+ nameTo: string,
+ schema: string,
+): JsonRenameEnumStatement => {
+ return {
+ type: 'rename_type_enum',
+ nameFrom,
+ nameTo,
+ schema,
+ };
+};
+
+////////////
+
+export const prepareCreateSequenceJson = (
+ seq: Sequence,
+): JsonCreateSequenceStatement => {
+ const values = PgSquasher.unsquashSequence(seq.values);
+ return {
+ type: 'create_sequence',
+ name: seq.name,
+ schema: seq.schema,
+ values,
+ };
+};
+
+export const prepareAlterSequenceJson = (
+ seq: Sequence,
+): JsonAlterSequenceStatement[] => {
+ const values = PgSquasher.unsquashSequence(seq.values);
+ return [
+ {
+ type: 'alter_sequence',
+ schema: seq.schema,
+ name: seq.name,
+ values,
+ },
+ ];
+};
+
+export const prepareDropSequenceJson = (
+ name: string,
+ schema: string,
+): JsonDropSequenceStatement => {
+ return {
+ type: 'drop_sequence',
+ name: name,
+ schema: schema,
+ };
+};
+
+export const prepareMoveSequenceJson = (
+ name: string,
+ schemaFrom: string,
+ schemaTo: string,
+): JsonMoveSequenceStatement => {
+ return {
+ type: 'move_sequence',
+ name: name,
+ schemaFrom,
+ schemaTo,
+ };
+};
+
+export const prepareRenameSequenceJson = (
+ nameFrom: string,
+ nameTo: string,
+ schema: string,
+): JsonRenameSequenceStatement => {
+ return {
+ type: 'rename_sequence',
+ nameFrom,
+ nameTo,
+ schema,
+ };
+};
+
+////////////
+
+export const prepareCreateSchemasJson = (
+ values: string[],
+): JsonCreateSchema[] => {
+ return values.map((it) => {
+ return {
+ type: 'create_schema',
+ name: it,
+ } as JsonCreateSchema;
+ });
+};
+
+export const prepareRenameSchemasJson = (
+ values: { from: string; to: string }[],
+): JsonRenameSchema[] => {
+ return values.map((it) => {
+ return {
+ type: 'rename_schema',
+ from: it.from,
+ to: it.to,
+ } as JsonRenameSchema;
+ });
+};
+
+export const prepareDeleteSchemasJson = (
+ values: string[],
+): JsonDropSchema[] => {
+ return values.map((it) => {
+ return {
+ type: 'drop_schema',
+ name: it,
+ } as JsonDropSchema;
+ });
+};
+
+export const prepareRenameColumns = (
+ tableName: string,
+ // TODO: split for pg and mysql+sqlite and singlestore without schema
+ schema: string,
+ pairs: { from: Column; to: Column }[],
+): JsonRenameColumnStatement[] => {
+ return pairs.map((it) => {
+ return {
+ type: 'alter_table_rename_column',
+ tableName: tableName,
+ oldColumnName: it.from.name,
+ newColumnName: it.to.name,
+ schema,
+ };
+ });
+};
+
+export const _prepareDropColumns = (
+ taleName: string,
+ schema: string,
+ columns: Column[],
+): JsonDropColumnStatement[] => {
+ return columns.map((it) => {
+ return {
+ type: 'alter_table_drop_column',
+ tableName: taleName,
+ columnName: it.name,
+ schema,
+ };
+ });
+};
+
+export const _prepareAddColumns = (
+ tableName: string,
+ schema: string,
+ columns: Column[],
+): JsonAddColumnStatement[] => {
+ return columns.map((it) => {
+ return {
+ type: 'alter_table_add_column',
+ tableName: tableName,
+ column: it,
+ schema,
+ };
+ });
+};
+
+export const _prepareSqliteAddColumns = (
+ tableName: string,
+ columns: Column[],
+ referenceData: string[],
+): JsonSqliteAddColumnStatement[] => {
+ const unsquashed = referenceData.map((addedFkValue) => SQLiteSquasher.unsquashFK(addedFkValue));
+
+ return columns
+ .map((it) => {
+ const columnsWithReference = unsquashed.find((t) => t.columnsFrom.includes(it.name));
+
+ if (it.generated?.type === 'stored') {
+ warning(
+ `As SQLite docs mention: "It is not possible to ALTER TABLE ADD COLUMN a STORED column. One can add a VIRTUAL column, however", source: "https://www.sqlite.org/gencol.html"`,
+ );
+ return undefined;
+ }
+
+ return {
+ type: 'sqlite_alter_table_add_column',
+ tableName: tableName,
+ column: it,
+ referenceData: columnsWithReference
+ ? SQLiteSquasher.squashFK(columnsWithReference)
+ : undefined,
+ };
+ })
+ .filter(Boolean) as JsonSqliteAddColumnStatement[];
+};
+
+export const prepareAlterColumnsMysql = (
+ tableName: string,
+ schema: string,
+ columns: AlteredColumn[],
+ // TODO: remove?
+ json1: CommonSquashedSchema,
+ json2: CommonSquashedSchema,
+ action?: 'push' | undefined,
+): JsonAlterColumnStatement[] => {
+ let statements: JsonAlterColumnStatement[] = [];
+ let dropPkStatements: JsonAlterColumnDropPrimaryKeyStatement[] = [];
+ let setPkStatements: JsonAlterColumnSetPrimaryKeyStatement[] = [];
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ const table = json2.tables[tableName];
+ const snapshotColumn = table.columns[columnName];
+
+ const columnType = snapshotColumn.type;
+ const columnDefault = snapshotColumn.default;
+ const columnOnUpdate = 'onUpdate' in snapshotColumn ? snapshotColumn.onUpdate : undefined;
+ const columnNotNull = table.columns[columnName].notNull;
+
+ const columnAutoIncrement = 'autoincrement' in snapshotColumn
+ ? snapshotColumn.autoincrement ?? false
+ : false;
+
+ const columnPk = table.columns[columnName].primaryKey;
+
+ if (column.autoincrement?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_autoincrement',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.autoincrement?.type === 'changed') {
+ const type = column.autoincrement.new
+ ? 'alter_table_alter_column_set_autoincrement'
+ : 'alter_table_alter_column_drop_autoincrement';
+
+ statements.push({
+ type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.autoincrement?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_autoincrement',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ // I used any, because those fields are available only for mysql dialect
+ // For other dialects it will become undefined, that is fine for json statements
+ const columnType = json2.tables[tableName].columns[columnName].type;
+ const columnDefault = json2.tables[tableName].columns[columnName].default;
+ const columnGenerated = json2.tables[tableName].columns[columnName].generated;
+ const columnOnUpdate = (json2.tables[tableName].columns[columnName] as any)
+ .onUpdate;
+ const columnNotNull = json2.tables[tableName].columns[columnName].notNull;
+ const columnAutoIncrement = (
+ json2.tables[tableName].columns[columnName] as any
+ ).autoincrement;
+ const columnPk = (json2.tables[tableName].columns[columnName] as any)
+ .primaryKey;
+
+ const compositePk = json2.tables[tableName].compositePrimaryKeys[
+ `${tableName}_${columnName}`
+ ];
+
+ if (typeof column.name !== 'string') {
+ statements.push({
+ type: 'alter_table_rename_column',
+ tableName,
+ oldColumnName: column.name.old,
+ newColumnName: column.name.new,
+ schema,
+ });
+ }
+
+ if (column.type?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_type',
+ tableName,
+ columnName,
+ newDataType: column.type.new,
+ oldDataType: column.type.old,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'deleted'
+ || (column.primaryKey?.type === 'changed'
+ && !column.primaryKey.new
+ && typeof compositePk === 'undefined')
+ ) {
+ dropPkStatements.push({
+ ////
+ type: 'alter_table_alter_column_drop_pk',
+ tableName,
+ columnName,
+ schema,
+ });
+ }
+
+ if (column.default?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.value,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.new,
+ oldDefaultValue: column.default.old,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_default',
+ tableName,
+ columnName,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'changed') {
+ const type = column.notNull.new
+ ? 'alter_table_alter_column_set_notnull'
+ : 'alter_table_alter_column_drop_notnull';
+ statements.push({
+ type: type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.generated?.type === 'added') {
+ if (columnGenerated?.type === 'virtual') {
+ warning(
+ `You are trying to add virtual generated constraint to ${
+ chalk.blue(
+ columnName,
+ )
+ } column. As MySQL docs mention: "Nongenerated columns can be altered to stored but not virtual generated columns". We will drop an existing column and add it with a virtual generated statement. This means that the data previously stored in this column will be wiped, and new data will be generated on each read for this column\n`,
+ );
+ }
+ statements.push({
+ type: 'alter_table_alter_column_set_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'changed' && action !== 'push') {
+ statements.push({
+ type: 'alter_table_alter_column_alter_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'deleted') {
+ if (columnGenerated?.type === 'virtual') {
+ warning(
+ `You are trying to remove virtual generated constraint from ${
+ chalk.blue(
+ columnName,
+ )
+ } column. As MySQL docs mention: "Stored but not virtual generated columns can be altered to nongenerated columns. The stored generated values become the values of the nongenerated column". We will drop an existing column and add it without a virtual generated statement. This means that this column will have no data after migration\n`,
+ );
+ }
+ statements.push({
+ type: 'alter_table_alter_column_drop_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ oldColumn: json1.tables[tableName].columns[columnName],
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'added'
+ || (column.primaryKey?.type === 'changed' && column.primaryKey.new)
+ ) {
+ const wasAutoincrement = statements.filter(
+ (it) => it.type === 'alter_table_alter_column_set_autoincrement',
+ );
+ if (wasAutoincrement.length === 0) {
+ setPkStatements.push({
+ type: 'alter_table_alter_column_set_pk',
+ tableName,
+ schema,
+ columnName,
+ });
+ }
+ }
+
+ if (column.onUpdate?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.onUpdate?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ return [...dropPkStatements, ...setPkStatements, ...statements];
+};
+
+export const prepareAlterColumnsSingleStore = (
+ tableName: string,
+ schema: string,
+ columns: AlteredColumn[],
+ // TODO: remove?
+ json1: CommonSquashedSchema,
+ json2: CommonSquashedSchema,
+ action?: 'push' | undefined,
+): JsonAlterColumnStatement[] => {
+ let statements: JsonAlterColumnStatement[] = [];
+ let dropPkStatements: JsonAlterColumnDropPrimaryKeyStatement[] = [];
+ let setPkStatements: JsonAlterColumnSetPrimaryKeyStatement[] = [];
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ const table = json2.tables[tableName];
+ const snapshotColumn = table.columns[columnName];
+
+ const columnType = snapshotColumn.type;
+ const columnDefault = snapshotColumn.default;
+ const columnOnUpdate = 'onUpdate' in snapshotColumn ? snapshotColumn.onUpdate : undefined;
+ const columnNotNull = table.columns[columnName].notNull;
+
+ const columnAutoIncrement = 'autoincrement' in snapshotColumn
+ ? snapshotColumn.autoincrement ?? false
+ : false;
+
+ const columnPk = table.columns[columnName].primaryKey;
+
+ if (column.autoincrement?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_autoincrement',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.autoincrement?.type === 'changed') {
+ const type = column.autoincrement.new
+ ? 'alter_table_alter_column_set_autoincrement'
+ : 'alter_table_alter_column_drop_autoincrement';
+
+ statements.push({
+ type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.autoincrement?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_autoincrement',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ // I used any, because those fields are available only for mysql and singlestore dialect
+ // For other dialects it will become undefined, that is fine for json statements
+ const columnType = json2.tables[tableName].columns[columnName].type;
+ const columnDefault = json2.tables[tableName].columns[columnName].default;
+ const columnGenerated = json2.tables[tableName].columns[columnName].generated;
+ const columnOnUpdate = (json2.tables[tableName].columns[columnName] as any)
+ .onUpdate;
+ const columnNotNull = json2.tables[tableName].columns[columnName].notNull;
+ const columnAutoIncrement = (
+ json2.tables[tableName].columns[columnName] as any
+ ).autoincrement;
+ const columnPk = (json2.tables[tableName].columns[columnName] as any)
+ .primaryKey;
+
+ const compositePk = json2.tables[tableName].compositePrimaryKeys[
+ `${tableName}_${columnName}`
+ ];
+
+ if (typeof column.name !== 'string') {
+ statements.push({
+ type: 'alter_table_rename_column',
+ tableName,
+ oldColumnName: column.name.old,
+ newColumnName: column.name.new,
+ schema,
+ });
+ }
+
+ if (column.type?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_type',
+ tableName,
+ columnName,
+ newDataType: column.type.new,
+ oldDataType: column.type.old,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'deleted'
+ || (column.primaryKey?.type === 'changed'
+ && !column.primaryKey.new
+ && typeof compositePk === 'undefined')
+ ) {
+ dropPkStatements.push({
+ ////
+ type: 'alter_table_alter_column_drop_pk',
+ tableName,
+ columnName,
+ schema,
+ });
+ }
+
+ if (column.default?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.value,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.new,
+ oldDefaultValue: column.default.old,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_default',
+ tableName,
+ columnName,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'changed') {
+ const type = column.notNull.new
+ ? 'alter_table_alter_column_set_notnull'
+ : 'alter_table_alter_column_drop_notnull';
+ statements.push({
+ type: type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.generated?.type === 'added') {
+ if (columnGenerated?.type === 'virtual') {
+ // TODO: Change warning message according to SingleStore docs
+ warning(
+ `You are trying to add virtual generated constraint to ${
+ chalk.blue(
+ columnName,
+ )
+ } column. As MySQL docs mention: "Nongenerated columns can be altered to stored but not virtual generated columns". We will drop an existing column and add it with a virtual generated statement. This means that the data previously stored in this column will be wiped, and new data will be generated on each read for this column\n`,
+ );
+ }
+ statements.push({
+ type: 'alter_table_alter_column_set_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'changed' && action !== 'push') {
+ statements.push({
+ type: 'alter_table_alter_column_alter_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'deleted') {
+ if (columnGenerated?.type === 'virtual') {
+ // TODO: Change warning message according to SingleStore docs
+ warning(
+ `You are trying to remove virtual generated constraint from ${
+ chalk.blue(
+ columnName,
+ )
+ } column. As MySQL docs mention: "Stored but not virtual generated columns can be altered to nongenerated columns. The stored generated values become the values of the nongenerated column". We will drop an existing column and add it without a virtual generated statement. This means that this column will have no data after migration\n`,
+ );
+ }
+ statements.push({
+ type: 'alter_table_alter_column_drop_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ oldColumn: json1.tables[tableName].columns[columnName],
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'added'
+ || (column.primaryKey?.type === 'changed' && column.primaryKey.new)
+ ) {
+ const wasAutoincrement = statements.filter(
+ (it) => it.type === 'alter_table_alter_column_set_autoincrement',
+ );
+ if (wasAutoincrement.length === 0) {
+ setPkStatements.push({
+ type: 'alter_table_alter_column_set_pk',
+ tableName,
+ schema,
+ columnName,
+ });
+ }
+ }
+
+ if (column.onUpdate?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.onUpdate?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ return [...dropPkStatements, ...setPkStatements, ...statements];
+};
+
+export const preparePgAlterColumns = (
+ _tableName: string,
+ schema: string,
+ columns: AlteredColumn[],
+ // TODO: remove?
+ json2: CommonSquashedSchema,
+ action?: 'push' | undefined,
+): JsonAlterColumnStatement[] => {
+ const tableKey = `${schema || 'public'}.${_tableName}`;
+ let statements: JsonAlterColumnStatement[] = [];
+ let dropPkStatements: JsonAlterColumnDropPrimaryKeyStatement[] = [];
+ let setPkStatements: JsonAlterColumnSetPrimaryKeyStatement[] = [];
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ const tableName = json2.tables[tableKey].name;
+
+ // I used any, because those fields are available only for mysql dialect
+ // For other dialects it will become undefined, that is fine for json statements
+ const columnType = json2.tables[tableKey].columns[columnName].type;
+ const columnDefault = json2.tables[tableKey].columns[columnName].default;
+ const columnGenerated = json2.tables[tableKey].columns[columnName].generated;
+ const columnOnUpdate = (json2.tables[tableKey].columns[columnName] as any)
+ .onUpdate;
+ const columnNotNull = json2.tables[tableKey].columns[columnName].notNull;
+ const columnAutoIncrement = (
+ json2.tables[tableKey].columns[columnName] as any
+ ).autoincrement;
+ const columnPk = (json2.tables[tableKey].columns[columnName] as any)
+ .primaryKey;
+
+ const compositePk = json2.tables[tableKey].compositePrimaryKeys[`${tableName}_${columnName}`];
+
+ if (typeof column.name !== 'string') {
+ statements.push({
+ type: 'alter_table_rename_column',
+ tableName,
+ oldColumnName: column.name.old,
+ newColumnName: column.name.new,
+ schema,
+ });
+ }
+
+ if (column.type?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_type',
+ tableName,
+ columnName,
+ newDataType: column.type.new,
+ oldDataType: column.type.old,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'deleted'
+ || (column.primaryKey?.type === 'changed'
+ && !column.primaryKey.new
+ && typeof compositePk === 'undefined')
+ ) {
+ dropPkStatements.push({
+ ////
+ type: 'alter_table_alter_column_drop_pk',
+ tableName,
+ columnName,
+ schema,
+ });
+ }
+
+ if (column.default?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.value,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.new,
+ oldDefaultValue: column.default.old,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_default',
+ tableName,
+ columnName,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'changed') {
+ const type = column.notNull.new
+ ? 'alter_table_alter_column_set_notnull'
+ : 'alter_table_alter_column_drop_notnull';
+ statements.push({
+ type: type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.identity?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_identity',
+ tableName,
+ columnName,
+ schema,
+ identity: column.identity.value,
+ });
+ }
+
+ if (column.identity?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_change_identity',
+ tableName,
+ columnName,
+ schema,
+ identity: column.identity.new,
+ oldIdentity: column.identity.old,
+ });
+ }
+
+ if (column.identity?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_identity',
+ tableName,
+ columnName,
+ schema,
+ });
+ }
+
+ if (column.generated?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'changed' && action !== 'push') {
+ statements.push({
+ type: 'alter_table_alter_column_alter_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (column.generated?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'added'
+ || (column.primaryKey?.type === 'changed' && column.primaryKey.new)
+ ) {
+ const wasAutoincrement = statements.filter(
+ (it) => it.type === 'alter_table_alter_column_set_autoincrement',
+ );
+ if (wasAutoincrement.length === 0) {
+ setPkStatements.push({
+ type: 'alter_table_alter_column_set_pk',
+ tableName,
+ schema,
+ columnName,
+ });
+ }
+ }
+
+ // if (column.primaryKey?.type === "added") {
+ // statements.push({
+ // type: "alter_table_alter_column_set_primarykey",
+ // tableName,
+ // columnName,
+ // schema,
+ // newDataType: columnType,
+ // columnDefault,
+ // columnOnUpdate,
+ // columnNotNull,
+ // columnAutoIncrement,
+ // });
+ // }
+
+ // if (column.primaryKey?.type === "changed") {
+ // const type = column.primaryKey.new
+ // ? "alter_table_alter_column_set_primarykey"
+ // : "alter_table_alter_column_drop_primarykey";
+
+ // statements.push({
+ // type,
+ // tableName,
+ // columnName,
+ // schema,
+ // newDataType: columnType,
+ // columnDefault,
+ // columnOnUpdate,
+ // columnNotNull,
+ // columnAutoIncrement,
+ // });
+ // }
+
+ // if (column.primaryKey?.type === "deleted") {
+ // statements.push({
+ // type: "alter_table_alter_column_drop_primarykey",
+ // tableName,
+ // columnName,
+ // schema,
+ // newDataType: columnType,
+ // columnDefault,
+ // columnOnUpdate,
+ // columnNotNull,
+ // columnAutoIncrement,
+ // });
+ // }
+
+ if (column.onUpdate?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.onUpdate?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ return [...dropPkStatements, ...setPkStatements, ...statements];
+};
+
+export const prepareSqliteAlterColumns = (
+ tableName: string,
+ schema: string,
+ columns: AlteredColumn[],
+ // TODO: remove?
+ json2: CommonSquashedSchema,
+): JsonAlterColumnStatement[] => {
+ let statements: JsonAlterColumnStatement[] = [];
+ let dropPkStatements: JsonAlterColumnDropPrimaryKeyStatement[] = [];
+ let setPkStatements: JsonAlterColumnSetPrimaryKeyStatement[] = [];
+
+ for (const column of columns) {
+ const columnName = typeof column.name !== 'string' ? column.name.new : column.name;
+
+ // I used any, because those fields are available only for mysql dialect
+ // For other dialects it will become undefined, that is fine for json statements
+ const columnType = json2.tables[tableName].columns[columnName].type;
+ const columnDefault = json2.tables[tableName].columns[columnName].default;
+ const columnOnUpdate = (json2.tables[tableName].columns[columnName] as any)
+ .onUpdate;
+ const columnNotNull = json2.tables[tableName].columns[columnName].notNull;
+ const columnAutoIncrement = (
+ json2.tables[tableName].columns[columnName] as any
+ ).autoincrement;
+ const columnPk = (json2.tables[tableName].columns[columnName] as any)
+ .primaryKey;
+
+ const columnGenerated = json2.tables[tableName].columns[columnName].generated;
+
+ const compositePk = json2.tables[tableName].compositePrimaryKeys[
+ `${tableName}_${columnName}`
+ ];
+
+ if (typeof column.name !== 'string') {
+ statements.push({
+ type: 'alter_table_rename_column',
+ tableName,
+ oldColumnName: column.name.old,
+ newColumnName: column.name.new,
+ schema,
+ });
+ }
+
+ if (column.type?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_type',
+ tableName,
+ columnName,
+ newDataType: column.type.new,
+ oldDataType: column.type.old,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'deleted'
+ || (column.primaryKey?.type === 'changed'
+ && !column.primaryKey.new
+ && typeof compositePk === 'undefined')
+ ) {
+ dropPkStatements.push({
+ ////
+ type: 'alter_table_alter_column_drop_pk',
+ tableName,
+ columnName,
+ schema,
+ });
+ }
+
+ if (column.default?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.value,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'changed') {
+ statements.push({
+ type: 'alter_table_alter_column_set_default',
+ tableName,
+ columnName,
+ newDefaultValue: column.default.new,
+ oldDefaultValue: column.default.old,
+ schema,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.default?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_default',
+ tableName,
+ columnName,
+ schema,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ newDataType: columnType,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'changed') {
+ const type = column.notNull.new
+ ? 'alter_table_alter_column_set_notnull'
+ : 'alter_table_alter_column_drop_notnull';
+ statements.push({
+ type: type,
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.notNull?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_notnull',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.generated?.type === 'added') {
+ if (columnGenerated?.type === 'virtual') {
+ statements.push({
+ type: 'alter_table_alter_column_set_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ } else {
+ warning(
+ `As SQLite docs mention: "It is not possible to ALTER TABLE ADD COLUMN a STORED column. One can add a VIRTUAL column, however", source: "https://www.sqlite.org/gencol.html"`,
+ );
+ }
+ }
+
+ if (column.generated?.type === 'changed') {
+ if (columnGenerated?.type === 'virtual') {
+ statements.push({
+ type: 'alter_table_alter_column_alter_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ } else {
+ warning(
+ `As SQLite docs mention: "It is not possible to ALTER TABLE ADD COLUMN a STORED column. One can add a VIRTUAL column, however", source: "https://www.sqlite.org/gencol.html"`,
+ );
+ }
+ }
+
+ if (column.generated?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_generated',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ columnGenerated,
+ });
+ }
+
+ if (
+ column.primaryKey?.type === 'added'
+ || (column.primaryKey?.type === 'changed' && column.primaryKey.new)
+ ) {
+ const wasAutoincrement = statements.filter(
+ (it) => it.type === 'alter_table_alter_column_set_autoincrement',
+ );
+ if (wasAutoincrement.length === 0) {
+ setPkStatements.push({
+ type: 'alter_table_alter_column_set_pk',
+ tableName,
+ schema,
+ columnName,
+ });
+ }
+ }
+
+ if (column.onUpdate?.type === 'added') {
+ statements.push({
+ type: 'alter_table_alter_column_set_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+
+ if (column.onUpdate?.type === 'deleted') {
+ statements.push({
+ type: 'alter_table_alter_column_drop_on_update',
+ tableName,
+ columnName,
+ schema,
+ newDataType: columnType,
+ columnDefault,
+ columnOnUpdate,
+ columnNotNull,
+ columnAutoIncrement,
+ columnPk,
+ });
+ }
+ }
+
+ return [...dropPkStatements, ...setPkStatements, ...statements];
+};
+
+export const preparePgCreateIndexesJson = (
+ tableName: string,
+ schema: string,
+ indexes: Record,
+ fullSchema: PgSchema,
+ action?: 'push' | undefined,
+): JsonPgCreateIndexStatement[] => {
+ if (action === 'push') {
+ return Object.values(indexes).map((indexData) => {
+ const unsquashedIndex = PgSquasher.unsquashIdxPush(indexData);
+ const data = fullSchema.tables[`${schema === '' ? 'public' : schema}.${tableName}`]
+ .indexes[unsquashedIndex.name];
+ return {
+ type: 'create_index_pg',
+ tableName,
+ data,
+ schema,
+ };
+ });
+ }
+ return Object.values(indexes).map((indexData) => {
+ return {
+ type: 'create_index_pg',
+ tableName,
+ data: PgSquasher.unsquashIdx(indexData),
+ schema,
+ };
+ });
+};
+
+export const prepareCreateIndexesJson = (
+ tableName: string,
+ schema: string,
+ indexes: Record,
+ internal?: MySqlKitInternals | SQLiteKitInternals,
+): JsonCreateIndexStatement[] => {
+ return Object.values(indexes).map((indexData) => {
+ return {
+ type: 'create_index',
+ tableName,
+ data: indexData,
+ schema,
+ internal,
+ };
+ });
+};
+
+export const prepareCreateReferencesJson = (
+ tableName: string,
+ schema: string,
+ foreignKeys: Record,
+): JsonCreateReferenceStatement[] => {
+ return Object.values(foreignKeys).map((fkData) => {
+ return {
+ type: 'create_reference',
+ tableName,
+ data: fkData,
+ schema,
+ };
+ });
+};
+
+export const prepareDropReferencesJson = (
+ tableName: string,
+ schema: string,
+ foreignKeys: Record,
+): JsonDeleteReferenceStatement[] => {
+ return Object.values(foreignKeys).map((fkData) => {
+ return {
+ type: 'delete_reference',
+ tableName,
+ data: fkData,
+ schema,
+ };
+ });
+};
+
+// alter should create 2 statements. It's important to make only 1 sql per statement(for breakpoints)
+export const prepareAlterReferencesJson = (
+ tableName: string,
+ schema: string,
+ foreignKeys: Record,
+): JsonReferenceStatement[] => {
+ const stmts: JsonReferenceStatement[] = [];
+ Object.values(foreignKeys).map((val) => {
+ stmts.push({
+ type: 'delete_reference',
+ tableName,
+ schema,
+ data: val.__old,
+ });
+
+ stmts.push({
+ type: 'create_reference',
+ tableName,
+ schema,
+ data: val.__new,
+ });
+ });
+ return stmts;
+};
+
+export const prepareDropIndexesJson = (
+ tableName: string,
+ schema: string,
+ indexes: Record,
+): JsonDropIndexStatement[] => {
+ return Object.values(indexes).map((indexData) => {
+ return {
+ type: 'drop_index',
+ tableName,
+ data: indexData,
+ schema,
+ };
+ });
+};
+
+export const prepareAddCompositePrimaryKeySqlite = (
+ tableName: string,
+ pks: Record,
+): JsonCreateCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'create_composite_pk',
+ tableName,
+ data: it,
+ } as JsonCreateCompositePK;
+ });
+};
+
+export const prepareDeleteCompositePrimaryKeySqlite = (
+ tableName: string,
+ pks: Record,
+): JsonDeleteCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'delete_composite_pk',
+ tableName,
+ data: it,
+ } as JsonDeleteCompositePK;
+ });
+};
+
+export const prepareAlterCompositePrimaryKeySqlite = (
+ tableName: string,
+ pks: Record,
+): JsonAlterCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'alter_composite_pk',
+ tableName,
+ old: it.__old,
+ new: it.__new,
+ } as JsonAlterCompositePK;
+ });
+};
+
+export const prepareAddCompositePrimaryKeyPg = (
+ tableName: string,
+ schema: string,
+ pks: Record,
+ // TODO: remove?
+ json2: PgSchema,
+): JsonCreateCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ const unsquashed = PgSquasher.unsquashPK(it);
+ return {
+ type: 'create_composite_pk',
+ tableName,
+ data: it,
+ schema,
+ constraintName: json2.tables[`${schema || 'public'}.${tableName}`].compositePrimaryKeys[
+ unsquashed.name
+ ].name,
+ } as JsonCreateCompositePK;
+ });
+};
+
+export const prepareDeleteCompositePrimaryKeyPg = (
+ tableName: string,
+ schema: string,
+ pks: Record,
+ // TODO: remove?
+ json1: PgSchema,
+): JsonDeleteCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'delete_composite_pk',
+ tableName,
+ data: it,
+ schema,
+ constraintName: json1.tables[`${schema || 'public'}.${tableName}`].compositePrimaryKeys[
+ PgSquasher.unsquashPK(it).name
+ ].name,
+ } as JsonDeleteCompositePK;
+ });
+};
+
+export const prepareAlterCompositePrimaryKeyPg = (
+ tableName: string,
+ schema: string,
+ pks: Record,
+ // TODO: remove?
+ json1: PgSchema,
+ json2: PgSchema,
+): JsonAlterCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'alter_composite_pk',
+ tableName,
+ old: it.__old,
+ new: it.__new,
+ schema,
+ oldConstraintName: json1.tables[`${schema || 'public'}.${tableName}`].compositePrimaryKeys[
+ PgSquasher.unsquashPK(it.__old).name
+ ].name,
+ newConstraintName: json2.tables[`${schema || 'public'}.${tableName}`].compositePrimaryKeys[
+ PgSquasher.unsquashPK(it.__new).name
+ ].name,
+ } as JsonAlterCompositePK;
+ });
+};
+
+export const prepareAddUniqueConstraintPg = (
+ tableName: string,
+ schema: string,
+ unqs: Record,
+): JsonCreateUniqueConstraint[] => {
+ return Object.values(unqs).map((it) => {
+ return {
+ type: 'create_unique_constraint',
+ tableName,
+ data: it,
+ schema,
+ } as JsonCreateUniqueConstraint;
+ });
+};
+
+export const prepareDeleteUniqueConstraintPg = (
+ tableName: string,
+ schema: string,
+ unqs: Record,
+): JsonDeleteUniqueConstraint[] => {
+ return Object.values(unqs).map((it) => {
+ return {
+ type: 'delete_unique_constraint',
+ tableName,
+ data: it,
+ schema,
+ } as JsonDeleteUniqueConstraint;
+ });
+};
+
+// add create table changes
+// add handler to make drop and add and not alter(looking at __old and __new)
+// add serializer for mysql and sqlite + types
+// add introspect serializer for pg+sqlite+mysql
+// add introspect actual code
+// add push sqlite handler
+// add push mysql warning if data exists and may have unique conflict
+// add release notes
+// add docs changes
+
+export const prepareAlterUniqueConstraintPg = (
+ tableName: string,
+ schema: string,
+ unqs: Record,
+): JsonAlterUniqueConstraint[] => {
+ return Object.values(unqs).map((it) => {
+ return {
+ type: 'alter_unique_constraint',
+ tableName,
+ old: it.__old,
+ new: it.__new,
+ schema,
+ } as JsonAlterUniqueConstraint;
+ });
+};
+
+export const prepareAddCompositePrimaryKeyMySql = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: MySqlSchema,
+ json2: MySqlSchema,
+): JsonCreateCompositePK[] => {
+ const res: JsonCreateCompositePK[] = [];
+ for (const it of Object.values(pks)) {
+ const unsquashed = MySqlSquasher.unsquashPK(it);
+
+ if (
+ unsquashed.columns.length === 1
+ && json1.tables[tableName]?.columns[unsquashed.columns[0]]?.primaryKey
+ ) {
+ continue;
+ }
+
+ res.push({
+ type: 'create_composite_pk',
+ tableName,
+ data: it,
+ constraintName: json2.tables[tableName].compositePrimaryKeys[unsquashed.name].name,
+ } as JsonCreateCompositePK);
+ }
+ return res;
+};
+
+export const prepareDeleteCompositePrimaryKeyMySql = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: MySqlSchema,
+): JsonDeleteCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'delete_composite_pk',
+ tableName,
+ data: it,
+ constraintName: json1.tables[tableName].compositePrimaryKeys[
+ MySqlSquasher.unsquashPK(it).name
+ ].name,
+ } as JsonDeleteCompositePK;
+ });
+};
+
+export const prepareAlterCompositePrimaryKeyMySql = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: MySqlSchema,
+ json2: MySqlSchema,
+): JsonAlterCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'alter_composite_pk',
+ tableName,
+ old: it.__old,
+ new: it.__new,
+ oldConstraintName: json1.tables[tableName].compositePrimaryKeys[
+ MySqlSquasher.unsquashPK(it.__old).name
+ ].name,
+ newConstraintName: json2.tables[tableName].compositePrimaryKeys[
+ MySqlSquasher.unsquashPK(it.__new).name
+ ].name,
+ } as JsonAlterCompositePK;
+ });
+};
+
+export const prepareAddCompositePrimaryKeySingleStore = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: SingleStoreSchema,
+ json2: SingleStoreSchema,
+): JsonCreateCompositePK[] => {
+ const res: JsonCreateCompositePK[] = [];
+ for (const it of Object.values(pks)) {
+ const unsquashed = SingleStoreSquasher.unsquashPK(it);
+
+ if (
+ unsquashed.columns.length === 1
+ && json1.tables[tableName]?.columns[unsquashed.columns[0]]?.primaryKey
+ ) {
+ continue;
+ }
+
+ res.push({
+ type: 'create_composite_pk',
+ tableName,
+ data: it,
+ constraintName: json2.tables[tableName].compositePrimaryKeys[unsquashed.name].name,
+ } as JsonCreateCompositePK);
+ }
+ return res;
+};
+
+export const prepareDeleteCompositePrimaryKeySingleStore = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: SingleStoreSchema,
+): JsonDeleteCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'delete_composite_pk',
+ tableName,
+ data: it,
+ constraintName: json1.tables[tableName].compositePrimaryKeys[
+ SingleStoreSquasher.unsquashPK(it).name
+ ].name,
+ } as JsonDeleteCompositePK;
+ });
+};
+
+export const prepareAlterCompositePrimaryKeySingleStore = (
+ tableName: string,
+ pks: Record,
+ // TODO: remove?
+ json1: SingleStoreSchema,
+ json2: SingleStoreSchema,
+): JsonAlterCompositePK[] => {
+ return Object.values(pks).map((it) => {
+ return {
+ type: 'alter_composite_pk',
+ tableName,
+ old: it.__old,
+ new: it.__new,
+ oldConstraintName: json1.tables[tableName].compositePrimaryKeys[
+ SingleStoreSquasher.unsquashPK(it.__old).name
+ ].name,
+ newConstraintName: json2.tables[tableName].compositePrimaryKeys[
+ SingleStoreSquasher.unsquashPK(it.__new).name
+ ].name,
+ } as JsonAlterCompositePK;
+ });
+};
diff --git a/drizzle-kit/src/loader.mjs b/drizzle-kit/src/loader.mjs
new file mode 100644
index 000000000..488f5712c
--- /dev/null
+++ b/drizzle-kit/src/loader.mjs
@@ -0,0 +1,57 @@
+import esbuild from 'esbuild';
+import { readFileSync } from 'fs';
+import * as path from 'path';
+
+const parse = (it) => {
+ if (!it) return { drizzle: false };
+
+ if (it.endsWith('__drizzle__')) {
+ const offset = it.startsWith('file://') ? 'file://'.length : 0;
+ const clean = it.slice(offset, -'__drizzle__'.length);
+ return { drizzle: true, clean, original: it };
+ }
+ return { drizzle: false, clean: it };
+};
+
+export function resolve(specifier, context, nextResolve) {
+ const { drizzle, clean } = parse(specifier);
+ if (drizzle && !clean.endsWith('.ts') && !clean.endsWith('.mts')) {
+ return nextResolve(clean);
+ }
+
+ if (drizzle) {
+ return {
+ shortCircuit: true,
+ url: `file://${specifier}`,
+ };
+ }
+
+ const parsedParent = parse(context.parentURL);
+ const parentURL = parsedParent.drizzle
+ ? new URL(`file://${path.resolve(parsedParent.clean)}`)
+ : context.parentURL;
+
+ // Let Node.js handle all other specifiers.
+ return nextResolve(specifier, { ...context, parentURL });
+}
+
+export async function load(url, context, defaultLoad) {
+ const { drizzle, clean } = parse(url);
+ if (drizzle) {
+ const file = readFileSync(clean, 'utf-8');
+ if (clean.endsWith('.ts') || clean.endsWith('.mts')) {
+ const source = esbuild.transformSync(file, {
+ loader: 'ts',
+ format: 'esm',
+ });
+ return {
+ format: 'module',
+ shortCircuit: true,
+ source: source.code,
+ };
+ }
+ }
+
+ // let Node.js handle all other URLs
+ return defaultLoad(url, context, defaultLoad);
+}
diff --git a/drizzle-kit/src/migrationPreparator.ts b/drizzle-kit/src/migrationPreparator.ts
new file mode 100644
index 000000000..4e5664290
--- /dev/null
+++ b/drizzle-kit/src/migrationPreparator.ts
@@ -0,0 +1,208 @@
+import { randomUUID } from 'crypto';
+import fs from 'fs';
+import { serializeMySql, serializePg, serializeSingleStore, serializeSQLite } from './serializer';
+import { dryMySql, MySqlSchema, mysqlSchema } from './serializer/mysqlSchema';
+import { dryPg, PgSchema, pgSchema, PgSchemaInternal } from './serializer/pgSchema';
+import { drySingleStore, SingleStoreSchema, singlestoreSchema } from './serializer/singlestoreSchema';
+import { drySQLite, SQLiteSchema, sqliteSchema } from './serializer/sqliteSchema';
+
+export const prepareMySqlDbPushSnapshot = async (
+ prev: MySqlSchema,
+ schemaPath: string | string[],
+): Promise<{ prev: MySqlSchema; cur: MySqlSchema }> => {
+ const serialized = await serializeMySql(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prev.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: MySqlSchema = { version, dialect, id, prevId: idPrev, ...rest };
+
+ return { prev, cur: result };
+};
+
+export const prepareSingleStoreDbPushSnapshot = async (
+ prev: SingleStoreSchema,
+ schemaPath: string | string[],
+): Promise<{ prev: SingleStoreSchema; cur: SingleStoreSchema }> => {
+ const serialized = await serializeSingleStore(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prev.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: SingleStoreSchema = { version, dialect, id, prevId: idPrev, ...rest };
+
+ return { prev, cur: result };
+};
+
+export const prepareSQLiteDbPushSnapshot = async (
+ prev: SQLiteSchema,
+ schemaPath: string | string[],
+): Promise<{ prev: SQLiteSchema; cur: SQLiteSchema }> => {
+ const serialized = await serializeSQLite(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prev.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: SQLiteSchema = {
+ version,
+ dialect,
+ id,
+ prevId: idPrev,
+ ...rest,
+ };
+
+ return { prev, cur: result };
+};
+
+export const preparePgDbPushSnapshot = async (
+ prev: PgSchema,
+ schemaPath: string | string[],
+ schemaFilter: string[] = ['public'],
+): Promise<{ prev: PgSchema; cur: PgSchema }> => {
+ const serialized = await serializePg(schemaPath, schemaFilter);
+
+ const id = randomUUID();
+ const idPrev = prev.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: PgSchema = { version, dialect, id, prevId: idPrev, ...rest };
+
+ return { prev, cur: result };
+};
+
+export const prepareMySqlMigrationSnapshot = async (
+ migrationFolders: string[],
+ schemaPath: string | string[],
+): Promise<{ prev: MySqlSchema; cur: MySqlSchema; custom: MySqlSchema }> => {
+ const prevSnapshot = mysqlSchema.parse(
+ preparePrevSnapshot(migrationFolders, dryMySql),
+ );
+ const serialized = await serializeMySql(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prevSnapshot.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: MySqlSchema = { version, dialect, id, prevId: idPrev, ...rest };
+
+ const { id: _ignoredId, prevId: _ignoredPrevId, ...prevRest } = prevSnapshot;
+
+ // that's for custom migrations, when we need new IDs, but old snapshot
+ const custom: MySqlSchema = {
+ id,
+ prevId: idPrev,
+ ...prevRest,
+ };
+
+ return { prev: prevSnapshot, cur: result, custom };
+};
+
+export const prepareSingleStoreMigrationSnapshot = async (
+ migrationFolders: string[],
+ schemaPath: string | string[],
+): Promise<{ prev: SingleStoreSchema; cur: SingleStoreSchema; custom: SingleStoreSchema }> => {
+ const prevSnapshot = singlestoreSchema.parse(
+ preparePrevSnapshot(migrationFolders, drySingleStore),
+ );
+ const serialized = await serializeSingleStore(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prevSnapshot.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: SingleStoreSchema = { version, dialect, id, prevId: idPrev, ...rest };
+
+ const { id: _ignoredId, prevId: _ignoredPrevId, ...prevRest } = prevSnapshot;
+
+ // that's for custom migrations, when we need new IDs, but old snapshot
+ const custom: SingleStoreSchema = {
+ id,
+ prevId: idPrev,
+ ...prevRest,
+ };
+
+ return { prev: prevSnapshot, cur: result, custom };
+};
+
+export const prepareSqliteMigrationSnapshot = async (
+ snapshots: string[],
+ schemaPath: string | string[],
+): Promise<{ prev: SQLiteSchema; cur: SQLiteSchema; custom: SQLiteSchema }> => {
+ const prevSnapshot = sqliteSchema.parse(
+ preparePrevSnapshot(snapshots, drySQLite),
+ );
+ const serialized = await serializeSQLite(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prevSnapshot.id;
+
+ const { version, dialect, ...rest } = serialized;
+ const result: SQLiteSchema = {
+ version,
+ dialect,
+ id,
+ prevId: idPrev,
+ ...rest,
+ };
+
+ const { id: _ignoredId, prevId: _ignoredPrevId, ...prevRest } = prevSnapshot;
+
+ // that's for custom migrations, when we need new IDs, but old snapshot
+ const custom: SQLiteSchema = {
+ id,
+ prevId: idPrev,
+ ...prevRest,
+ };
+
+ return { prev: prevSnapshot, cur: result, custom };
+};
+
+export const fillPgSnapshot = ({
+ serialized,
+ id,
+ idPrev,
+}: {
+ serialized: PgSchemaInternal;
+ id: string;
+ idPrev: string;
+}): PgSchema => {
+ // const id = randomUUID();
+ return { id, prevId: idPrev, ...serialized };
+};
+
+export const preparePgMigrationSnapshot = async (
+ snapshots: string[],
+ schemaPath: string | string[],
+): Promise<{ prev: PgSchema; cur: PgSchema; custom: PgSchema }> => {
+ const prevSnapshot = pgSchema.parse(preparePrevSnapshot(snapshots, dryPg));
+ const serialized = await serializePg(schemaPath);
+
+ const id = randomUUID();
+ const idPrev = prevSnapshot.id;
+
+ // const { version, dialect, ...rest } = serialized;
+
+ const result: PgSchema = { id, prevId: idPrev, ...serialized };
+
+ const { id: _ignoredId, prevId: _ignoredPrevId, ...prevRest } = prevSnapshot;
+
+ // that's for custom migrations, when we need new IDs, but old snapshot
+ const custom: PgSchema = fillPgSnapshot({ serialized: prevRest, id, idPrev });
+
+ return { prev: prevSnapshot, cur: result, custom };
+};
+
+const preparePrevSnapshot = (snapshots: string[], defaultPrev: any) => {
+ let prevSnapshot: any;
+
+ if (snapshots.length === 0) {
+ prevSnapshot = defaultPrev;
+ } else {
+ const lastSnapshot = snapshots[snapshots.length - 1];
+ prevSnapshot = JSON.parse(fs.readFileSync(lastSnapshot).toString());
+ }
+ return prevSnapshot;
+};
diff --git a/drizzle-kit/src/schemaValidator.ts b/drizzle-kit/src/schemaValidator.ts
new file mode 100644
index 000000000..712252f37
--- /dev/null
+++ b/drizzle-kit/src/schemaValidator.ts
@@ -0,0 +1,23 @@
+import { enum as enumType, TypeOf, union } from 'zod';
+import { mysqlSchema, mysqlSchemaSquashed } from './serializer/mysqlSchema';
+import { pgSchema, pgSchemaSquashed } from './serializer/pgSchema';
+import { singlestoreSchema, singlestoreSchemaSquashed } from './serializer/singlestoreSchema';
+import { sqliteSchema, SQLiteSchemaSquashed } from './serializer/sqliteSchema';
+
+export const dialects = ['postgresql', 'mysql', 'sqlite', 'singlestore'] as const;
+export const dialect = enumType(dialects);
+
+export type Dialect = (typeof dialects)[number];
+const _: Dialect = '' as TypeOf;
+
+const commonSquashedSchema = union([
+ pgSchemaSquashed,
+ mysqlSchemaSquashed,
+ SQLiteSchemaSquashed,
+ singlestoreSchemaSquashed,
+]);
+
+const commonSchema = union([pgSchema, mysqlSchema, sqliteSchema, singlestoreSchema]);
+
+export type CommonSquashedSchema = TypeOf;
+export type CommonSchema = TypeOf;
diff --git a/drizzle-kit/src/serializer/index.ts b/drizzle-kit/src/serializer/index.ts
new file mode 100644
index 000000000..6eb55c6f6
--- /dev/null
+++ b/drizzle-kit/src/serializer/index.ts
@@ -0,0 +1,154 @@
+import chalk from 'chalk';
+import type { SQL } from 'drizzle-orm';
+import fs from 'fs';
+import * as glob from 'glob';
+import Path from 'path';
+import { error } from '../cli/views';
+import type { MySqlSchemaInternal } from './mysqlSchema';
+import type { PgSchemaInternal } from './pgSchema';
+import { SingleStoreSchemaInternal } from './singlestoreSchema';
+import type { SQLiteSchemaInternal } from './sqliteSchema';
+
+export const sqlToStr = (sql: SQL) => {
+ return sql.toQuery({
+ escapeName: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ escapeParam: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ escapeString: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ }).sql;
+};
+
+export const sqlToStrGenerated = (sql: SQL) => {
+ return sql.toQuery({
+ escapeName: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ escapeParam: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ escapeString: () => {
+ throw new Error("we don't support params for `sql` default values");
+ },
+ }).sql;
+};
+
+export const serializeMySql = async (
+ path: string | string[],
+): Promise => {
+ const filenames = prepareFilenames(path);
+
+ console.log(chalk.gray(`Reading schema files:\n${filenames.join('\n')}\n`));
+
+ const { prepareFromMySqlImports } = await import('./mysqlImports');
+ const { generateMySqlSnapshot } = await import('./mysqlSerializer');
+
+ const { tables } = await prepareFromMySqlImports(filenames);
+
+ return generateMySqlSnapshot(tables);
+};
+
+export const serializePg = async (
+ path: string | string[],
+ schemaFilter?: string[],
+): Promise => {
+ const filenames = prepareFilenames(path);
+
+ const { prepareFromPgImports } = await import('./pgImports');
+ const { generatePgSnapshot } = await import('./pgSerializer');
+
+ const { tables, enums, schemas, sequences } = await prepareFromPgImports(
+ filenames,
+ );
+
+ return generatePgSnapshot(tables, enums, schemas, sequences, schemaFilter);
+};
+
+export const serializeSQLite = async (
+ path: string | string[],
+): Promise => {
+ const filenames = prepareFilenames(path);
+
+ const { prepareFromSqliteImports } = await import('./sqliteImports');
+ const { generateSqliteSnapshot } = await import('./sqliteSerializer');
+ const { tables } = await prepareFromSqliteImports(filenames);
+ return generateSqliteSnapshot(tables);
+};
+
+export const serializeSingleStore = async (
+ path: string | string[],
+): Promise => {
+ const filenames = prepareFilenames(path);
+
+ console.log(chalk.gray(`Reading schema files:\n${filenames.join('\n')}\n`));
+
+ const { prepareFromSingleStoreImports } = await import('./singlestoreImports');
+ const { generateSingleStoreSnapshot } = await import('./singlestoreSerializer');
+
+ const { tables } = await prepareFromSingleStoreImports(filenames);
+
+ return generateSingleStoreSnapshot(tables);
+};
+
+export const prepareFilenames = (path: string | string[]) => {
+ if (typeof path === 'string') {
+ path = [path];
+ }
+ const prefix = process.env.TEST_CONFIG_PATH_PREFIX || '';
+
+ const result = path.reduce((result, cur) => {
+ const globbed = glob.sync(`${prefix}${cur}`);
+
+ globbed.forEach((it) => {
+ const fileName = fs.lstatSync(it).isDirectory() ? null : Path.resolve(it);
+
+ const filenames = fileName
+ ? [fileName!]
+ : fs.readdirSync(it).map((file) => Path.join(Path.resolve(it), file));
+
+ filenames
+ .filter((file) => !fs.lstatSync(file).isDirectory())
+ .forEach((file) => result.add(file));
+ });
+
+ return result;
+ }, new Set());
+ const res = [...result];
+
+ // TODO: properly handle and test
+ const errors = res.filter((it) => {
+ return !(
+ it.endsWith('.ts')
+ || it.endsWith('.js')
+ || it.endsWith('.cjs')
+ || it.endsWith('.mjs')
+ || it.endsWith('.mts')
+ || it.endsWith('.cts')
+ );
+ });
+
+ // when schema: "./schema" and not "./schema.ts"
+ if (res.length === 0) {
+ console.log(
+ error(
+ `No schema files found for path config [${
+ path
+ .map((it) => `'${it}'`)
+ .join(', ')
+ }]`,
+ ),
+ );
+ console.log(
+ error(
+ `If path represents a file - please make sure to use .ts or other extension in the path`,
+ ),
+ );
+ process.exit(1);
+ }
+
+ return res;
+};
diff --git a/drizzle-kit/src/serializer/mysqlImports.ts b/drizzle-kit/src/serializer/mysqlImports.ts
new file mode 100644
index 000000000..d9899026b
--- /dev/null
+++ b/drizzle-kit/src/serializer/mysqlImports.ts
@@ -0,0 +1,31 @@
+import { is } from 'drizzle-orm';
+import { AnyMySqlTable, MySqlTable } from 'drizzle-orm/mysql-core';
+import { safeRegister } from '../cli/commands/utils';
+
+export const prepareFromExports = (exports: Record) => {
+ const tables: AnyMySqlTable[] = [];
+
+ const i0values = Object.values(exports);
+ i0values.forEach((t) => {
+ if (is(t, MySqlTable)) {
+ tables.push(t);
+ }
+ });
+
+ return { tables };
+};
+
+export const prepareFromMySqlImports = async (imports: string[]) => {
+ const tables: AnyMySqlTable[] = [];
+
+ const { unregister } = await safeRegister();
+ for (let i = 0; i < imports.length; i++) {
+ const it = imports[i];
+ const i0: Record = require(`${it}`);
+ const prepared = prepareFromExports(i0);
+
+ tables.push(...prepared.tables);
+ }
+ unregister();
+ return { tables: Array.from(new Set(tables)) };
+};
diff --git a/drizzle-kit/src/serializer/mysqlSchema.ts b/drizzle-kit/src/serializer/mysqlSchema.ts
new file mode 100644
index 000000000..5bc62ab2f
--- /dev/null
+++ b/drizzle-kit/src/serializer/mysqlSchema.ts
@@ -0,0 +1,348 @@
+import { any, boolean, enum as enumType, literal, object, record, string, TypeOf, union } from 'zod';
+import { mapValues, originUUID, snapshotVersion } from '../global';
+
+// ------- V3 --------
+const index = object({
+ name: string(),
+ columns: string().array(),
+ isUnique: boolean(),
+ using: enumType(['btree', 'hash']).optional(),
+ algorithm: enumType(['default', 'inplace', 'copy']).optional(),
+ lock: enumType(['default', 'none', 'shared', 'exclusive']).optional(),
+}).strict();
+
+const fk = object({
+ name: string(),
+ tableFrom: string(),
+ columnsFrom: string().array(),
+ tableTo: string(),
+ columnsTo: string().array(),
+ onUpdate: string().optional(),
+ onDelete: string().optional(),
+}).strict();
+
+const column = object({
+ name: string(),
+ type: string(),
+ primaryKey: boolean(),
+ notNull: boolean(),
+ autoincrement: boolean().optional(),
+ default: any().optional(),
+ onUpdate: any().optional(),
+ generated: object({
+ type: enumType(['stored', 'virtual']),
+ as: string(),
+ }).optional(),
+}).strict();
+
+const tableV3 = object({
+ name: string(),
+ columns: record(string(), column),
+ indexes: record(string(), index),
+ foreignKeys: record(string(), fk),
+}).strict();
+
+const compositePK = object({
+ name: string(),
+ columns: string().array(),
+}).strict();
+
+const uniqueConstraint = object({
+ name: string(),
+ columns: string().array(),
+}).strict();
+
+const tableV4 = object({
+ name: string(),
+ schema: string().optional(),
+ columns: record(string(), column),
+ indexes: record(string(), index),
+ foreignKeys: record(string(), fk),
+}).strict();
+
+const table = object({
+ name: string(),
+ columns: record(string(), column),
+ indexes: record(string(), index),
+ foreignKeys: record(string(), fk),
+ compositePrimaryKeys: record(string(), compositePK),
+ uniqueConstraints: record(string(), uniqueConstraint).default({}),
+}).strict();
+
+export const kitInternals = object({
+ tables: record(
+ string(),
+ object({
+ columns: record(
+ string(),
+ object({ isDefaultAnExpression: boolean().optional() }).optional(),
+ ),
+ }).optional(),
+ ).optional(),
+ indexes: record(
+ string(),
+ object({
+ columns: record(
+ string(),
+ object({ isExpression: boolean().optional() }).optional(),
+ ),
+ }).optional(),
+ ).optional(),
+}).optional();
+
+// use main dialect
+const dialect = literal('mysql');
+
+const schemaHash = object({
+ id: string(),
+ prevId: string(),
+});
+
+export const schemaInternalV3 = object({
+ version: literal('3'),
+ dialect: dialect,
+ tables: record(string(), tableV3),
+}).strict();
+
+export const schemaInternalV4 = object({
+ version: literal('4'),
+ dialect: dialect,
+ tables: record(string(), tableV4),
+ schemas: record(string(), string()),
+}).strict();
+
+export const schemaInternalV5 = object({
+ version: literal('5'),
+ dialect: dialect,
+ tables: record(string(), table),
+ schemas: record(string(), string()),
+ _meta: object({
+ schemas: record(string(), string()),
+ tables: record(string(), string()),
+ columns: record(string(), string()),
+ }),
+ internal: kitInternals,
+}).strict();
+
+export const schemaInternal = object({
+ version: literal('5'),
+ dialect: dialect,
+ tables: record(string(), table),
+ _meta: object({
+ tables: record(string(), string()),
+ columns: record(string(), string()),
+ }),
+ internal: kitInternals,
+}).strict();
+
+export const schemaV3 = schemaInternalV3.merge(schemaHash);
+export const schemaV4 = schemaInternalV4.merge(schemaHash);
+export const schemaV5 = schemaInternalV5.merge(schemaHash);
+export const schema = schemaInternal.merge(schemaHash);
+
+const tableSquashedV4 = object({
+ name: string(),
+ schema: string().optional(),
+ columns: record(string(), column),
+ indexes: record(string(), string()),
+ foreignKeys: record(string(), string()),
+}).strict();
+
+const tableSquashed = object({
+ name: string(),
+ columns: record(string(), column),
+ indexes: record(string(), string()),
+ foreignKeys: record(string(), string()),
+ compositePrimaryKeys: record(string(), string()),
+ uniqueConstraints: record(string(), string()).default({}),
+}).strict();
+
+export const schemaSquashed = object({
+ version: literal('5'),
+ dialect: dialect,
+ tables: record(string(), tableSquashed),
+}).strict();
+
+export const schemaSquashedV4 = object({
+ version: literal('4'),
+ dialect: dialect,
+ tables: record(string(), tableSquashedV4),
+ schemas: record(string(), string()),
+}).strict();
+
+export type Dialect = TypeOf;
+export type Column = TypeOf;
+export type Table = TypeOf;
+export type TableV4 = TypeOf;
+export type MySqlSchema = TypeOf;
+export type MySqlSchemaV3 = TypeOf;
+export type MySqlSchemaV4 = TypeOf