kysely-ctl

repository·main·Indexed 43 days ago

https://github.com/kysely-org/kysely-ctl

The official command-line interface for Kysely version 0.21.0. It provides tools for managing database migrations and seeds, executing raw SQL queries in single or interactive mode, and initializing project configurations via `defineConfig`.

Tokens
9.6K
Snippets
43
Records
51
Agent score
55%

What's inside kysely-ctl

  1. Install kysely-ctl

    main

    Prerequisites

    kysely-ctl requires kysely >= 0.18.1 to be installed in your project.

    System-wide installation

    Install globally to use the kysely command anywhere in your terminal.

    Node.js:

    npm i -g kysely-ctl
    # or
    pnpm add -g kysely-ctl

    Bun:

    bun add -g kysely-ctl

    Deno:

    deno install -g -f npm:kysely-ctl@latest

    Project-scoped installation

    Install as a dev dependency to make kysely available within your project's package.json.

    Node.js:

    npm i -D kysely-ctl
    # or
    yarn add -D kysely-ctl
    # or
    pnpm add -D kysely-ctl

    Bun:

    bun add -D kysely-ctl

    Deno:

    deno add -D npm:kysely-ctl
    npm i -D kysely-ctl
  2. Use the kysely CLI

    main

    The kysely command-line tool provides a suite of commands for managing Kysely projects, including initialization, migrations, seeding, and raw SQL execution.

    Available command groups include:

    • Initialization: init
    • Migrations: migrate (and legacy migration commands like up, down, rollback, make, list, latest)
    • Seeding: seed (and legacy seed commands like make, run)
    • SQL: sql
    # Example usage (actual subcommands depend on your project setup)
    kysely migrate up
    kysely seed run
    kysely sql
  3. Implement Kysely migration files

    main

    When creating a new migration file, you must export an up function to apply the changes and optionally export a down function to revert them.

    Both functions receive a db instance of type Kysely<any>. Using any for the database type is recommended to ensure migrations remain 'frozen in time' and are not broken by subsequent changes to your main database interface. Alternatively, you can use a specific 'snapshot' version of your database interface.

    • up(db): Mandatory. Contains the logic to apply the migration.
    • down(db): Optional. Contains the logic to undo the changes made by up. You can safely delete this function if you do not need rollback capabilities.
    /**
     * @param {import('kysely').Kysely<any>} db
     * @returns {Promise<void>}
     */
    export async function up(db) {
    	// up migration code goes here...
    }
    
    /**
     * @param {import('kysely').Kysely<any>} db
     * @returns {Promise<void>}
     */
    export async function down(db) {
    	// down migration code goes here...
    }
  4. Configure kysely-ctl with defineConfig

    main

    A kysely.config.ts file is required in your project root or a .config folder. You can create one by running kysely init.

    Use defineConfig to specify how the CLI interacts with your database, migrations, and seeds. You can either provide a dialect and dialectConfig or pass an existing Kysely instance directly.

    Key Configuration Options:

    • destroyOnExit (boolean): Whether the Kysely instance should be destroyed when a command finishes. Defaults to true.
    • dialect: A Kysely dialect instance or the name of a driver library (e.g., 'pg').
    • dialectConfig: Options passed to the driver library if dialect is a string.
    • kysely: An existing Kysely instance to reuse.
    • migrations: Configuration for migrations (folder, provider, migrator, etc.).
    • seeds: Configuration for seeds (folder, provider, seeder, etc.).
    • plugins: A list of Kysely plugins.
    import { defineConfig } from "kysely-ctl";
    
    export default defineConfig({
      destroyOnExit, // optional. default is `true`.
      dialect, // a `Kysely` dialect instance OR the name of an underlying driver library (e.g. `'pg'`).
      dialectConfig, // optional.
      migrations: {
        allowJS, // optional. default is `false`.
        getMigrationPrefix, // optional. default is `() => ${Date.now()}_`.
        migrationFolder, // optional. default is "migrations" next to config.
        migrator, // optional.
        provider, // optional. default is `kysely-ctl`'s `TSFileMigrationProvider`.
      },
      plugins, // optional. default is `[]`.
      seeds: {
        allowJS, // optional. default is `false`.
        getSeedPrefix, // optional. default is `() => ${Date.now()}_`.
        provider, // optional. default is `kysely-ctl`'s `FileSeedProvider`.
        seeder, // optional.
        seedFolder, // optional. default is "seeds" next to config.
      }
    });
  5. Reuse an existing Kysely instance in configuration

    main

    Instead of defining a dialect and configuration from scratch, you can import and pass a pre-configured Kysely instance to defineConfig using the kysely key.

    import { defineConfig } from "kysely-ctl";
    import { kysely } from 'path/to/kysely/instance';
    
    export default defineConfig({
      destroyOnExit, // optional. default is `true`.
      // ...
      kysely,
      // ...
    });
  6. Use Knex-style timestamp prefixes for migrations

    main

    To use Knex's timestamp prefixes for migration files instead of the default timestamp, use the getKnexTimestampPrefix helper in your migrations configuration.

    import { defineConfig, getKnexTimestampPrefix } from "kysely-ctl";
    
    export default defineConfig({
      // ...
      migrations: {
        // ...
        getMigrationPrefix: getKnexTimestampPrefix,
        // ...
      },
      // ...
    });
  7. Configure tsdown for building kysely-ctl

    main

    The tsdown.config.mts file defines the build configuration for the project using tsdown. It specifies entry points, output formats, and automated checks for module compatibility.

    Key configuration areas include:

    • Entry points: Defines the source files to be bundled (./src/index.mts and ./src/bin.mts).
    • Formats: Set to ['esm'] to ensure the output is ECMAScript Modules.
    • Exports: Configures the bin export for the kysely command, while excluding the bin key from the public package exports.
    • Automated Checks: Enables attw (Are The Types Wrong?) with an esm-only profile and publint to ensure package quality and compatibility.
    • Asset Management: Copies template files from ./src/templates to the dist directory.
    import { defineConfig } from 'tsdown'
    
    export default defineConfig({
    	attw: {
    		enabled: true,
    		level: 'error',
    		profile: 'esm-only',
    	},
    	clean: true,
    	copy: {
    		from: ['./src/templates'],
    		to: 'dist',
    	},
    	dts: true,
    	entry: ['./src/index.mts', './src/bin.mts'],
    	exports: {
    		bin: {
    			kysely: './src/bin.mts',
    		},
    		enabled: 'local-only',
    		exclude: ['bin'],
    	},
    	format: ['esm'],
    	publint: {
    		enabled: true,
    	},
    	shims: true,
    	tsconfig: './tsconfig.prod.json',
    })
  8. Configure seeds

    main

    Seeds can be configured in two ways: Seederless (folder-based) or Seederful (custom logic).

    Seederless Seeds

    Used for standard folder-based seeding.

    • seedFolder: The directory containing seed files.
    • allowJS: Whether to allow .js seed files.
    • provider: A custom SeedProvider to handle seed storage/retrieval.

    Seederful Seeds

    Used when you want to provide your own Seeder instance.

    • seeder: A factory function that receives the Kysely instance and returns a Seeder.

    Note: If you provide a seeder, you cannot provide seedFolder or provider directly in the same config block.

    // Seederless example
    const seedsConfig = {
      seedFolder: './src/seeds',
      allowJS: true
    };
    
    // Seederful example
    const seedsConfig = {
      seeder: (db) => new MyCustomSeeder(db)
    };
  9. Configure migrations

    main

    Migrations can be configured in two ways: Migratorless (folder-based) or Migratorful (custom logic).

    Migratorless Migrations

    Used when you want kysely-ctl to manage migrations from a specific folder.

    • migrationFolder: The directory containing migration files.
    • allowJS: Whether to allow .js migration files in addition to .ts.
    • provider: A custom MigrationProvider to handle how migrations are stored/retrieved.

    Migratorful Migrations

    Used when you want to provide your own Migrator instance.

    • migrator: A factory function that receives the Kysely instance and returns a Migrator.
    • getMigrationPrefix: A function to determine the migration file prefix.

    Note: If you provide a migrator, you cannot provide migrationFolder or provider directly in the same config block.

    // Migratorless example
    const migrationsConfig = {
      migrationFolder: './src/migrations',
      allowJS: true
    };
    
    // Migratorful example
    const migrationsConfig = {
      migrator: (db) => new Migrator({ /* ... */ })
    };
  10. Configure TSFileMigrationProviderProps

    main

    When instantiating TSFileMigrationProvider, you must provide a configuration object conforming to TSFileMigrationProviderProps.

    KeyTypeDescription
    migrationFolderstringRequired. The path to the directory containing your migration files.
    allowJSbooleanOptional. If true, the provider will also attempt to load .js files. If false (default), it will ignore everything except .ts files.
    ...GetJitiArgsobjectAdditional arguments passed to the underlying jiti loader for TypeScript file processing (inherited from GetJitiArgs).
    interface TSFileMigrationProviderProps extends GetJitiArgs {
      allowJS?: boolean
      migrationFolder: string
    }
  11. Configure kysely-ctl via KyselyCTLConfig

    main

    The KyselyCTLConfig object is the primary way to configure kysely-ctl. It supports three main modes of operation: defining a dialect and its configuration, providing a custom Kysely instance, or using a resolvable dialect string.

    Configuration Modes

    1. Dialect Mode: Specify a dialect (e.g., 'pg', 'mysql2', 'better-sqlite3') and its corresponding dialectConfig. This is the recommended way for most users.
    2. Kysely Instance Mode: Provide an existing kysely instance directly. In this mode, dialect and dialectConfig must not be provided.
    3. Resolvable Dialect Mode: Use supported dialect strings that map to specific configuration shapes.

    Supported Dialects and Config Types

    DialectConfig Type
    pgPostgresDialectConfig
    mysql2MysqlDialectConfig
    tediousMssqlDialectConfig
    better-sqlite3SqliteDialectConfig
    pglitePGliteDialectConfig
    postgresPostgresJSDialectConfig
    bunPostgresJSDialectConfig
    @neondatabase/serverlessNeonDialectConfig
    @prisma/ppgPPGDialectConfig

    Global Options

    • destroyOnExit: Boolean indicating if the connection should be destroyed on exit.
    • plugins: An array of KyselyPlugin instances (can be provided as a factory function).
    • migrations: Configuration for migrations (see Migrations Configuration).
    • seeds: Configuration for seeds (see Seeds Configuration).
    // Example: Using a dialect
    const config: KyselyCTLConfig = {
      dialect: 'pg',
      dialectConfig: {
        connectionString: 'postgres://user:pass@localhost:5432/db'
      }
    };
    
    // Example: Using an existing Kysely instance
    const configWithInstance: KyselyCTLConfig = {
      kysely: myExistingKyselyInstance
    };
  12. Enable JavaScript extensions in configuration

    main

    By default, kysely-ctl may restrict file extensions to TypeScript. If you attempt to use a JavaScript extension (like js, mjs, or cjs) and encounter an error, you must enable JavaScript support in your configuration.

    To allow JavaScript files for migrations or seeds, set the allowJS property to true within the corresponding context in your kysely-ctl configuration object.

    Contexts available:

    • migrations
    • seeds
    {
      "migrations": {
        "allowJS": true
      },
      "seeds": {
        "allowJS": true
      }
    }