diff --git a/package-lock.json b/package-lock.json index 5e2a27e4..364f18d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,10 @@ "node": ">=6.0.0" } }, + "node_modules/@anchan828/kysely-migration": { + "resolved": "packages/kysely-migration", + "link": true + }, "node_modules/@anchan828/nest-kysely": { "resolved": "packages/kysely", "link": true @@ -15316,6 +15320,7 @@ "nest-kysely": "cli.js" }, "devDependencies": { + "@anchan828/kysely-migration": "0.6.5", "@nestjs/common": "10.4.1", "@nestjs/core": "10.4.1", "@nestjs/testing": "10.4.1", @@ -15329,6 +15334,7 @@ "rxjs": "7.8.1" }, "peerDependencies": { + "@anchan828/kysely-migration": "^0.6.5", "kysely": "^0.x" } }, @@ -15337,6 +15343,7 @@ "version": "0.6.5", "license": "MIT", "dependencies": { + "@anchan828/kysely-migration": "^0.6.5", "@anchan828/nest-kysely": "^0.6.5", "@nestjs/common": "10.4.1", "@nestjs/core": "10.4.1", @@ -15361,6 +15368,151 @@ "peerDependencies": { "kysely": "^0.x" } + }, + "packages/kysely-migration": { + "name": "@anchan828/kysely-migration", + "version": "0.6.5", + "license": "MIT", + "bin": { + "kysely-migration": "cli.js" + }, + "devDependencies": { + "@nestjs/common": "10.3.10", + "@nestjs/core": "10.3.10", + "@nestjs/testing": "10.3.10", + "@types/better-sqlite3": "7.6.11", + "@types/pg": "8.11.6", + "better-sqlite3": "11.1.2", + "kysely": "0.27.4", + "mysql2": "3.11.0", + "pg": "8.12.0", + "reflect-metadata": "0.2.2", + "rxjs": "7.8.1" + }, + "peerDependencies": { + "kysely": "^0.x" + } + }, + "packages/kysely-migration/node_modules/@nestjs/common": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.10.tgz", + "integrity": "sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.6.3", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "packages/kysely-migration/node_modules/@nestjs/core": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.10.tgz", + "integrity": "sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.6.3", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "packages/kysely-migration/node_modules/@nestjs/testing": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.3.10.tgz", + "integrity": "sha512-i3HAtVQJijxNxJq1k39aelyJlyEIBRONys7IipH/4r8W0J+M1V+y5EKDOyi4j1SdNSb/vmNyWpZ2/ewZjl3kRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "2.6.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } + } + }, + "packages/kysely-migration/node_modules/@types/pg": { + "version": "8.11.6", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.6.tgz", + "integrity": "sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "packages/kysely-migration/node_modules/better-sqlite3": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz", + "integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } } } } diff --git a/packages/kysely-example/package.json b/packages/kysely-example/package.json index 97e1a8ec..9431afc0 100644 --- a/packages/kysely-example/package.json +++ b/packages/kysely-example/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@anchan828/nest-kysely": "^0.6.5", + "@anchan828/kysely-migration": "^0.6.5", "@nestjs/common": "10.4.1", "@nestjs/core": "10.4.1", "@nestjs/platform-express": "10.4.1", @@ -61,4 +62,4 @@ "access": "public" }, "packageManager": "npm@10.8.3" -} \ No newline at end of file +} diff --git a/packages/kysely-example/src/app.module.ts b/packages/kysely-example/src/app.module.ts index 305d3986..b73f9cc2 100644 --- a/packages/kysely-example/src/app.module.ts +++ b/packages/kysely-example/src/app.module.ts @@ -1,4 +1,5 @@ -import { KyselyMigrationClassProvider, KyselyModule } from "@anchan828/nest-kysely"; +import { KyselyMigrationClassProvider } from "@anchan828/kysely-migration"; +import { KyselyModule } from "@anchan828/nest-kysely"; import { Module } from "@nestjs/common"; import { MysqlDialect } from "kysely"; import { createPool } from "mysql2"; diff --git a/packages/kysely-migration/.npmignore b/packages/kysely-migration/.npmignore new file mode 100644 index 00000000..295107c6 --- /dev/null +++ b/packages/kysely-migration/.npmignore @@ -0,0 +1,4 @@ +* +!dist/**/* +dist/**/*.tsbuildinfo +!cli.js \ No newline at end of file diff --git a/packages/kysely-migration/.prettierrc.js b/packages/kysely-migration/.prettierrc.js new file mode 100644 index 00000000..f80081cd --- /dev/null +++ b/packages/kysely-migration/.prettierrc.js @@ -0,0 +1,5 @@ +const basePrettierConfig = require("../../.prettierrc"); + +module.exports = { + ...basePrettierConfig, +}; diff --git a/packages/kysely-migration/LICENSE b/packages/kysely-migration/LICENSE new file mode 100644 index 00000000..1f1e0eae --- /dev/null +++ b/packages/kysely-migration/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 anchan828 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/kysely-migration/README.md b/packages/kysely-migration/README.md new file mode 100644 index 00000000..554f5d14 --- /dev/null +++ b/packages/kysely-migration/README.md @@ -0,0 +1,106 @@ +# @anchan828/kysely-migration + +![npm](https://img.shields.io/npm/v/@anchan828/kysely-migration.svg) +![NPM](https://img.shields.io/npm/l/@anchan828/kysely-migration.svg) + +Module for using [kysely](https://www.npmjs.com/package/kysely) with nestjs. + +## Installation + +```bash +$ npm i --save kysely @anchan828/kysely-migration +``` + +## Quick Start + +### KyselyMigrationClassProvider + +This provider can perform migration by passing the Migration class. + +```ts +import { Kysely, Migration } from "kysely"; +import { KyselyMigrationClassProvider } from "@anchan828/kysely-migration"; + +class CreateUserTable implements Migration { + public async up(db: Kysely): Promise { + await db.schema + .createTable("user") + .addColumn("id", "integer", (cb) => cb.primaryKey().autoIncrement().notNull()) + .addColumn("name", "varchar(255)", (cb) => cb.notNull()) + .execute(); + } +} + +const provider = new KyselyMigrationClassProvider([CreateUserTable]); + +await new Migrator({ db, provider }).migrateToLatest(); +``` + +### KyselyMigrationFileProvider + +This provider can perform migration by passing the migrations directory path. This provider wraps the FileMigrationProvider provided by kysely and supports SQL files. + +```shell +migrations +├── 1715003546247-CreateUserTable.ts +├── 1715003558664-CreateUserInsertTrigger.sql +├── 1715003568628-UpdateUserTable.sql +└── 1715003583015-CreateUserTableIndex.js +``` + +```ts +const provider = new KyselyMigrationFileProvider({ + fs: require("fs"), + path: require("path"), + migrationFolder: path.join(__dirname, "migrations"), +}); + +await new Migrator({ db, provider }).migrateToLatest(); +``` + +### KyselyMigrationMergeProvider + +This provider can perform migration by merging multiple providers. + +```ts +const provider = new KyselyMigrationMergeProvider({ + providers: [ + new KyselyMigrationFileProvider({ + fs: require("fs"), + path: require("path"), + migrationFolder: path.join(__dirname, "migrations"), + }), + new KyselyMigrationClassProvider([CreateUserTable]), + ], +}); + +await new Migrator({ db, provider }).migrateToLatest(); +``` + +## Repeatable Migrations + +This is a feature to support migrations that need to be regenerated multiple times, such as views/functions/triggers/etc. Unlike migrations that are executed only once, it compares the checksum of the SQL to be executed to determine the need for migration. + +```ts +import { KyselyRepeatableMigrationSqlFileProvider, RepeatableMigrator } from "@anchan828/kysely-migration"; +const provider = new KyselyRepeatableMigrationSqlFileProvider({ + sqlFiles: [resolve(__dirname, "user-view.sql")], + sqlTexts: [{ name: "test", sql: "SELECT 1;" }], +}); + +await new RepeatableMigrator({ db, provider }).migrateToLatest(); +``` + +| name | hash | timestamp | +| --------- | -------------------------------- | ------------------------ | +| user-view | 6c7e36422f79696602e19079534b4076 | 2024-05-11T17:04:20.211Z | +| test | e7d6c7d4d9b1b0b4c7f5d7b3d5e9d4d4 | 2024-05-11T17:04:20.211Z | + +### Note + +- Once the file is renamed, the migration is executed even if the contents have not changed. +- Views/Functions/Triggers created by Repeatable Migration are not automatically deleted (or update/rename) by simply deleting the corresponding SQL, so please delete them using the normal migration function. + +## License + +[MIT](LICENSE) diff --git a/packages/kysely-migration/cli.js b/packages/kysely-migration/cli.js new file mode 100755 index 00000000..d9fae776 --- /dev/null +++ b/packages/kysely-migration/cli.js @@ -0,0 +1,92 @@ +#!/usr/bin/env node + +const { relative, join } = require("node:path"); +const { writeFileSync, mkdirSync } = require("node:fs"); +const { parseArgs } = require("node:util"); +const args = process.argv.slice(2); +const parsed = parseArgs({ + args, + allowPositionals: true, + options: { + type: { + type: "string", + short: "t", + default: "ts", + multiple: false, + }, + "no-down": { + type: "boolean", + default: false, + multiple: false, + }, + }, +}); + +function errorText(text) { + return `\u001b[31m${text}\u001b[0m`; +} + +const migrationCommandName = "migration:create"; + +const usage = `Usage: nest-kysely ${migrationCommandName} [--type {ts,sql}] [--no-down] `; + +const commandName = parsed.positionals[0]; +const migrationDir = parsed.positionals[1]; +const migrationName = parsed.positionals[2]?.replace(/\s+/g, ""); + +if (commandName !== migrationCommandName) { + console.error(errorText(`Invalid command: ${parsed.positionals[0]}`)); + console.error(errorText(`Currently only ${migrationCommandName} is supported.`)); + console.info(usage); + process.exit(1); +} + +if (typeof migrationDir !== "string") { + console.log(errorText(`Migration directory is required.`)); + console.info(usage); + process.exit(1); +} + +if (typeof migrationName !== "string") { + console.log(errorText(`Migration name is required.`)); + console.info(usage); + process.exit(1); +} + +const timestamp = Date.now(); +const migrationFilePath = join(migrationDir, `${timestamp}-${migrationName}.${parsed.values.type}`); + +mkdirSync(migrationDir, { recursive: true }); + +if (parsed.values.type === "ts") { + const migrationFileContent = [ + `import { Kysely, Migration } from "kysely";`, + ``, + `export class ${migrationName}${timestamp} implements Migration {`, + ` public async up(db: Kysely): Promise {`, + ` }`, + parsed.values["no-down"] + ? undefined + : [` public async down(db: Kysely): Promise {`, ` }`].join("\n"), + `}`, + ].filter((x) => x); + + writeFileSync(migrationFilePath, migrationFileContent.join("\n")); +} +if (parsed.values.type === "js") { + const migrationFileContent = [ + `class ${migrationName}${timestamp} {`, + ` async up(db) {`, + ` }`, + parsed.values["no-down"] ? undefined : [` async down(db) {`, ` }`].join("\n"), + `}`, + ``, + `module.exports = ${migrationName}${timestamp};`, + ].filter((x) => x); + + writeFileSync(migrationFilePath, migrationFileContent.join("\n")); +} else { + writeFileSync(migrationFilePath, ""); +} + +console.info(`Created migration file: ${relative(process.cwd(), migrationFilePath)}`); diff --git a/packages/kysely-migration/jest.config.js b/packages/kysely-migration/jest.config.js new file mode 100644 index 00000000..1a4eea82 --- /dev/null +++ b/packages/kysely-migration/jest.config.js @@ -0,0 +1,4 @@ +const base = require("../../jest.config"); +module.exports = { + ...base, +}; diff --git a/packages/kysely-migration/package.json b/packages/kysely-migration/package.json new file mode 100644 index 00000000..870fd732 --- /dev/null +++ b/packages/kysely-migration/package.json @@ -0,0 +1,62 @@ +{ + "name": "@anchan828/kysely-migration", + "version": "0.6.5", + "description": "Migration helper package for Kysely", + "homepage": "https://github.com/anchan828/nest-kysely#readme", + "bugs": { + "url": "https://github.com/anchan828/nest-kysely/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/anchan828/nest-kysely.git" + }, + "license": "MIT", + "author": "anchan828 ", + "main": "dist/cjs/index.js", + "types": "dist/cjs/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.js" + }, + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.js" + } + }, + "bin": "cli.js", + "scripts": { + "build": "tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json", + "copy:license": "cp ../../LICENSE ./", + "lint": "TIMING=1 eslint '**/*.ts'", + "lint:fix": "npm run lint -- --fix", + "test": "jest --coverage --runInBand --detectOpenHandles", + "test:debug": "node --inspect-brk ../../node_modules/jest/bin/jest --runInBand --logHeapUsage", + "test:watch": "npm run test -- --watch", + "watch": "tsc --watch" + }, + "devDependencies": { + "@types/better-sqlite3": "7.6.11", + "@types/pg": "8.11.6", + "better-sqlite3": "11.1.2", + "kysely": "0.27.4", + "mysql2": "3.11.0", + "pg": "8.12.0", + "reflect-metadata": "0.2.2", + "rxjs": "7.8.1" + }, + "peerDependencies": { + "kysely": "^0.x" + }, + "volta": { + "node": "20.16.0" + }, + "publishConfig": { + "access": "public" + }, + "packageManager": "npm@10.8.2" +} diff --git a/packages/kysely-migration/src/index.ts b/packages/kysely-migration/src/index.ts new file mode 100644 index 00000000..8cfc65a9 --- /dev/null +++ b/packages/kysely-migration/src/index.ts @@ -0,0 +1,20 @@ +export { + KyselyMigrationClassProviderOptions, + KyselyMigrationFileProviderOptions, + KyselyMigrationMergeProviderOptions, + MigrationClass, +} from "./interfaces"; +export { KyselyMigrationClassProvider } from "./migration-class-provider"; +export { KyselyMigrationFileProvider } from "./migration-file-provider"; +export { KyselyMigrationMergeProvider } from "./migration-merge-provider"; +export { + KyselyRepeatableMigrationSqlFileProvider, + KyselyRepeatableMigrationSqlFileProviderOptions, + RepeatableMigration, + RepeatableMigrationInfo, + RepeatableMigrationProvider, + RepeatableMigrationResult, + RepeatableMigrationResultSet, + RepeatableMigrator, + RepeatableMigratorProps, +} from "./repeatable"; diff --git a/packages/kysely-migration/src/interfaces.ts b/packages/kysely-migration/src/interfaces.ts new file mode 100644 index 00000000..c1338421 --- /dev/null +++ b/packages/kysely-migration/src/interfaces.ts @@ -0,0 +1,30 @@ +import { FileMigrationProviderProps, Migration, MigrationProvider } from "kysely"; + +export interface MigrationClass { + readonly name: string; + new (...args: any[]): Migration; +} + +export interface KyselyMigrationClassProviderOptions { + /** + * Generates a prefix for the migration key. + */ + prefixFn?: (index: number) => string; + + /** + * If true, the number of the migration will be used as a prefix. + * For example, if the migration class name is CreateUserTable00000001, the migration name will be `00000001-CreateUserTable`. + * @default false + */ + useSuffixNumberAsPrefix?: boolean; +} + +export interface KyselyMigrationFileProviderOptions extends FileMigrationProviderProps { + fs: FileMigrationProviderProps["fs"] & { + readFile: (path: string, encoding?: BufferEncoding) => Promise; + }; +} + +export interface KyselyMigrationMergeProviderOptions { + providers: MigrationProvider[]; +} diff --git a/packages/kysely/src/migrations/migration-class-provider.spec.ts b/packages/kysely-migration/src/migration-class-provider.spec.ts similarity index 99% rename from packages/kysely/src/migrations/migration-class-provider.spec.ts rename to packages/kysely-migration/src/migration-class-provider.spec.ts index f84edbdf..8e9524a8 100644 --- a/packages/kysely/src/migrations/migration-class-provider.spec.ts +++ b/packages/kysely-migration/src/migration-class-provider.spec.ts @@ -107,6 +107,7 @@ describe("KyselyMigrationProvider", () => { }); const provider = new KyselyMigrationClassProvider(migrationClasses, { useSuffixNumberAsPrefix: true }); + await expect(provider.getMigrations()).resolves.toStrictEqual({ "0-Migration": expect.anything(), "1-Migration": expect.anything(), diff --git a/packages/kysely/src/migrations/migration-class-provider.ts b/packages/kysely-migration/src/migration-class-provider.ts similarity index 98% rename from packages/kysely/src/migrations/migration-class-provider.ts rename to packages/kysely-migration/src/migration-class-provider.ts index 2357c53e..b93d57a2 100644 --- a/packages/kysely/src/migrations/migration-class-provider.ts +++ b/packages/kysely-migration/src/migration-class-provider.ts @@ -1,5 +1,5 @@ import { Migration, MigrationProvider } from "kysely"; -import { KyselyMigrationClassProviderOptions, MigrationClass } from "../kysely.interface"; +import { KyselyMigrationClassProviderOptions, MigrationClass } from "./interfaces"; /** * Provider for generating migrations from classes. diff --git a/packages/kysely/src/migrations/migration-file-provider.spec.ts b/packages/kysely-migration/src/migration-file-provider.spec.ts similarity index 100% rename from packages/kysely/src/migrations/migration-file-provider.spec.ts rename to packages/kysely-migration/src/migration-file-provider.spec.ts diff --git a/packages/kysely/src/migrations/migration-file-provider.ts b/packages/kysely-migration/src/migration-file-provider.ts similarity index 94% rename from packages/kysely/src/migrations/migration-file-provider.ts rename to packages/kysely-migration/src/migration-file-provider.ts index d8ee87ad..0390fa06 100644 --- a/packages/kysely/src/migrations/migration-file-provider.ts +++ b/packages/kysely-migration/src/migration-file-provider.ts @@ -1,5 +1,5 @@ import { FileMigrationProvider, Migration, MigrationProvider, sql } from "kysely"; -import { KyselyMigrationFileProviderOptions } from "../kysely.interface"; +import { KyselyMigrationFileProviderOptions } from "./interfaces"; /** * Provider for generating migrations from TS/JS and SQL file. diff --git a/packages/kysely/src/migrations/migration-merge-provider.spec.ts b/packages/kysely-migration/src/migration-merge-provider.spec.ts similarity index 100% rename from packages/kysely/src/migrations/migration-merge-provider.spec.ts rename to packages/kysely-migration/src/migration-merge-provider.spec.ts diff --git a/packages/kysely/src/migrations/migration-merge-provider.ts b/packages/kysely-migration/src/migration-merge-provider.ts similarity index 89% rename from packages/kysely/src/migrations/migration-merge-provider.ts rename to packages/kysely-migration/src/migration-merge-provider.ts index fd13ac9f..4f8733a6 100644 --- a/packages/kysely/src/migrations/migration-merge-provider.ts +++ b/packages/kysely-migration/src/migration-merge-provider.ts @@ -1,5 +1,5 @@ import { Migration, MigrationProvider } from "kysely"; -import { KyselyMigrationMergeProviderOptions } from "../kysely.interface"; +import { KyselyMigrationMergeProviderOptions } from "./interfaces"; /** * Provider for merging migrations from multiple providers. diff --git a/packages/kysely/src/migrations/repeatable/index.ts b/packages/kysely-migration/src/repeatable/index.ts similarity index 100% rename from packages/kysely/src/migrations/repeatable/index.ts rename to packages/kysely-migration/src/repeatable/index.ts diff --git a/packages/kysely/src/migrations/repeatable/interface.ts b/packages/kysely-migration/src/repeatable/interface.ts similarity index 100% rename from packages/kysely/src/migrations/repeatable/interface.ts rename to packages/kysely-migration/src/repeatable/interface.ts diff --git a/packages/kysely/src/migrations/repeatable/migration-sql-file-provider.ts b/packages/kysely-migration/src/repeatable/migration-sql-file-provider.ts similarity index 100% rename from packages/kysely/src/migrations/repeatable/migration-sql-file-provider.ts rename to packages/kysely-migration/src/repeatable/migration-sql-file-provider.ts diff --git a/packages/kysely/src/migrations/repeatable/migrator.spec.ts b/packages/kysely-migration/src/repeatable/migrator.spec.ts similarity index 100% rename from packages/kysely/src/migrations/repeatable/migrator.spec.ts rename to packages/kysely-migration/src/repeatable/migrator.spec.ts diff --git a/packages/kysely/src/migrations/repeatable/migrator.ts b/packages/kysely-migration/src/repeatable/migrator.ts similarity index 100% rename from packages/kysely/src/migrations/repeatable/migrator.ts rename to packages/kysely-migration/src/repeatable/migrator.ts diff --git a/packages/kysely-migration/tsconfig.cjs.json b/packages/kysely-migration/tsconfig.cjs.json new file mode 100644 index 00000000..af9b0366 --- /dev/null +++ b/packages/kysely-migration/tsconfig.cjs.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "dist/cjs" + }, + "exclude": ["node_modules", "test", "**/*spec.ts", "src/test.utils.ts", "dist"] +} diff --git a/packages/kysely-migration/tsconfig.esm.json b/packages/kysely-migration/tsconfig.esm.json new file mode 100644 index 00000000..be049592 --- /dev/null +++ b/packages/kysely-migration/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "dist/esm" + }, + "exclude": ["node_modules", "test", "**/*spec.ts", "src/test.utils.ts", "dist"] +} diff --git a/packages/kysely-migration/tsconfig.json b/packages/kysely-migration/tsconfig.json new file mode 100644 index 00000000..970b4187 --- /dev/null +++ b/packages/kysely-migration/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "moduleResolution": "node" + }, + "exclude": ["node_modules", "dist"] +} diff --git a/packages/kysely/package.json b/packages/kysely/package.json index fefa6b2c..34acd16e 100644 --- a/packages/kysely/package.json +++ b/packages/kysely/package.json @@ -40,6 +40,7 @@ "watch": "tsc --watch" }, "devDependencies": { + "@anchan828/kysely-migration": "0.6.5", "@nestjs/common": "10.4.1", "@nestjs/core": "10.4.1", "@nestjs/testing": "10.4.1", @@ -53,7 +54,8 @@ "rxjs": "7.8.1" }, "peerDependencies": { - "kysely": "^0.x" + "kysely": "^0.x", + "@anchan828/kysely-migration": "^0.6.5" }, "volta": { "node": "20.17.0" diff --git a/packages/kysely/src/index.ts b/packages/kysely/src/index.ts index 2d82d0d1..020be894 100644 --- a/packages/kysely/src/index.ts +++ b/packages/kysely/src/index.ts @@ -1,28 +1,10 @@ export { KyselyTransactional } from "./kysely.decorator"; export { - KyselyMigrationClassProviderOptions, - KyselyMigrationFileProviderOptions, - KyselyMigrationMergeProviderOptions, KyselyMigrationOptions, KyselyModuleOptions, KyselyRepeatableMigrationOptions, KyselyTransactionalOptions, - MigrationClass, } from "./kysely.interface"; export { KyselyModule } from "./kysely.module"; export { KyselyService } from "./kysely.service"; -export { KyselyMigrationClassProvider } from "./migrations/migration-class-provider"; -export { KyselyMigrationFileProvider } from "./migrations/migration-file-provider"; -export { KyselyMigrationMergeProvider } from "./migrations/migration-merge-provider"; -export { - KyselyRepeatableMigrationSqlFileProvider, - KyselyRepeatableMigrationSqlFileProviderOptions, - RepeatableMigration, - RepeatableMigrationInfo, - RepeatableMigrationProvider, - RepeatableMigrationResult, - RepeatableMigrationResultSet, - RepeatableMigrator, - RepeatableMigratorProps, -} from "./migrations/repeatable"; export { RemoveNullPropertyPlugin } from "./plugins/remove-null-property.plugin"; diff --git a/packages/kysely/src/kysely.interface.ts b/packages/kysely/src/kysely.interface.ts index 0ba9c74d..5ca6a102 100644 --- a/packages/kysely/src/kysely.interface.ts +++ b/packages/kysely/src/kysely.interface.ts @@ -1,15 +1,5 @@ -import type { - Dialect, - FileMigrationProviderProps, - IsolationLevel, - Kysely, - KyselyConfig, - Migration, - MigrationProvider, - MigrationResultSet, - MigratorProps, -} from "kysely"; -import { RepeatableMigrationResultSet, RepeatableMigratorProps } from "./migrations/repeatable"; +import { RepeatableMigrationResultSet, RepeatableMigratorProps } from "@anchan828/kysely-migration"; +import type { Dialect, IsolationLevel, Kysely, KyselyConfig, MigrationResultSet, MigratorProps } from "kysely"; export interface KyselyMigrationOptions { migrationsRun?: boolean; @@ -62,32 +52,3 @@ export interface KyselyModuleOptions extends KyselyConfig { export interface KyselyTransactionalOptions { isolationLevel?: IsolationLevel; } - -export interface MigrationClass { - readonly name: string; - new (...args: any[]): Migration; -} - -export interface KyselyMigrationClassProviderOptions { - /** - * Generates a prefix for the migration key. - */ - prefixFn?: (index: number) => string; - - /** - * If true, the number of the migration will be used as a prefix. - * For example, if the migration class name is CreateUserTable00000001, the migration name will be `00000001-CreateUserTable`. - * @default false - */ - useSuffixNumberAsPrefix?: boolean; -} - -export interface KyselyMigrationFileProviderOptions extends FileMigrationProviderProps { - fs: FileMigrationProviderProps["fs"] & { - readFile: (path: string, encoding?: BufferEncoding) => Promise; - }; -} - -export interface KyselyMigrationMergeProviderOptions { - providers: MigrationProvider[]; -} diff --git a/packages/kysely/src/kysely.module.spec.ts b/packages/kysely/src/kysely.module.spec.ts index 97c0fcff..323f7cb2 100644 --- a/packages/kysely/src/kysely.module.spec.ts +++ b/packages/kysely/src/kysely.module.spec.ts @@ -1,3 +1,8 @@ +import { + KyselyMigrationClassProvider, + KyselyMigrationFileProvider, + KyselyRepeatableMigrationSqlFileProvider, +} from "@anchan828/kysely-migration"; import { Test } from "@nestjs/testing"; import * as SQLite from "better-sqlite3"; import { mkdtempSync, writeFileSync } from "fs"; @@ -11,9 +16,6 @@ import { resolve } from "path"; import { Pool } from "pg"; import { KyselyModule } from "./kysely.module"; import { KyselyService } from "./kysely.service"; -import { KyselyMigrationClassProvider } from "./migrations/migration-class-provider"; -import { KyselyMigrationFileProvider } from "./migrations/migration-file-provider"; -import { KyselyRepeatableMigrationSqlFileProvider } from "./migrations/repeatable"; const sqliteFilePath = resolve(tmpdir(), "kysely-sqlite-" + randomUUID() + ".db"); diff --git a/packages/kysely/src/kysely.module.ts b/packages/kysely/src/kysely.module.ts index 5e2b6d99..df8ce4db 100644 --- a/packages/kysely/src/kysely.module.ts +++ b/packages/kysely/src/kysely.module.ts @@ -1,10 +1,10 @@ +import { RepeatableMigrator } from "@anchan828/kysely-migration"; import { Global, Inject, Logger, Module, OnApplicationShutdown, OnModuleInit, Type } from "@nestjs/common"; import { Kysely, Migrator } from "kysely"; import { KYSELY } from "./kysely.constant"; import { KyselyMigrationOptions, KyselyModuleOptions, KyselyRepeatableMigrationOptions } from "./kysely.interface"; import { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } from "./kysely.module-definition"; import { KyselyService } from "./kysely.service"; -import { RepeatableMigrator } from "./migrations/repeatable"; @Global() @Module({ diff --git a/packages/kysely/src/plugins/remove-null-property.plugin.spec.ts b/packages/kysely/src/plugins/remove-null-property.plugin.spec.ts index 3a510108..456e8e86 100644 --- a/packages/kysely/src/plugins/remove-null-property.plugin.spec.ts +++ b/packages/kysely/src/plugins/remove-null-property.plugin.spec.ts @@ -1,3 +1,4 @@ +import { KyselyMigrationClassProvider } from "@anchan828/kysely-migration"; import { Test, TestingModule } from "@nestjs/testing"; import * as SQLite from "better-sqlite3"; import { Generated, Kysely, Migration, MysqlDialect, PostgresDialect, SqliteDialect } from "kysely"; @@ -5,7 +6,6 @@ import { createPool } from "mysql2"; import { Pool } from "pg"; import { KyselyModule } from "../kysely.module"; import { KyselyService } from "../kysely.service"; -import { KyselyMigrationClassProvider } from "../migrations/migration-class-provider"; import { RemoveNullPropertyPlugin } from "./remove-null-property.plugin"; describe.each([ {