Skip to content

Configuration

Arkorm loads config from arkormx.config.cjs, arkormx.config.js, or arkormx.config.ts in your project root.

Adapter configuration is the primary runtime path. Prisma is optional and only needed when you want compatibility mode, CLI flows, or Prisma-backed transactions on the supported 2.x compatibility path.

defineConfig

ts
import { defineConfig } from 'arkormx';
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';
import { createKyselyAdapter } from 'arkormx';

export default defineConfig({
  adapter: createKyselyAdapter(
    new Kysely<Record<string, never>>({
      dialect: new PostgresDialect({
        pool: new Pool({
          connectionString: process.env.DATABASE_URL,
        }),
      }),
    }),
  ),
});

Full configuration shape

ts
import { createKyselyAdapter, defineConfig, URLDriver } from 'arkormx';
import { Kysely, PostgresDialect } from 'kysely';
import { Pool } from 'pg';

const db = new Kysely<Record<string, never>>({
  dialect: new PostgresDialect({
    pool: new Pool({
      connectionString: process.env.DATABASE_URL,
    }),
  }),
});

class AppURLDriver extends URLDriver {}

export default defineConfig({
  adapter: createKyselyAdapter(db),
  naming: {
    case: 'snake',
  },
  features: {
    persistedColumnMappings: true,
    persistedEnums: true,
  },
  debug: (event) => {
    console.debug(event);
  },
  pagination: {
    urlDriver: (options) => new AppURLDriver(options),
  },
  paths: {
    stubs: './stubs',
    models: './src/models',
    factories: './database/factories',
    seeders: './database/seeders',
    migrations: './database/migrations',
    buildOutput: './dist',
  },
  outputExt: 'ts',
});

If you still need Prisma compatibility, add it alongside the adapter instead of replacing the adapter-first setup:

ts
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default defineConfig({
  client: () => prisma,
  adapter: createKyselyAdapter(db),
});

Config reference

KeyDescription
client (optional)Runtime client instance or resolver function for compatibility mode, CLI flows, and transaction fallback when no adapter transaction path is available.
prisma (optional, deprecated alias)Prisma client instance or resolver function kept for 2.x compatibility with older config.
adapterOptional global adapter applied automatically to models that do not define their own adapter.
naming.caseCasing strategy for inferred database identifiers ('snake' default, also supports 'camel', 'kebab', and 'studly').
features.persistedColumnMappingsEnable or disable persisted non-Prisma column mapping metadata written to .arkormx/column-mappings.json during adapter-backed migrations. Defaults to true.
features.persistedEnumsEnable or disable persisted non-Prisma enum metadata used by adapter-backed models:sync. Defaults to true.
bootOptional low-level synchronous hook for advanced runtime binding work.
debugSet to true for default query logging or provide a callback that receives structured query events.
pagination.urlDriverCustom URL driver factory for paginator links.
pagination.resolveCurrentPageRuntime hook used when paginate() or simplePaginate() is called without an explicit page argument.
paths.modelsGenerated model directory.
paths.factoriesGenerated factory directory.
paths.seedersGenerated seeder directory.
paths.migrationsGenerated migration directory.
paths.buildOutputBuild output root used to map runtime files in production.
outputExtPreferred generated extension ('ts' by default, falls back to 'js' when TypeScript is unavailable).

naming.modelTableCase is deprecated. It remains available as a compatibility alias for naming.case during the 2.x transition.

For event phases, query inspection, and structured exceptions, see Observability and Errors.

Additive runtime paths

The paths config points Arkorm at your application's primary model, factory, seeder, and migration directories. Packages and plugins can add their own directories without replacing those configured paths:

ts
import {
  loadFactoriesFrom,
  loadMigrationsFrom,
  loadModelsFrom,
  loadSeedersFrom,
  registerPaths,
} from 'arkormx';

loadMigrationsFrom('./packages/audit/database/migrations');
loadSeedersFrom('./packages/audit/database/seeders');
loadModelsFrom('./packages/audit/src/models');
loadFactoriesFrom('./packages/audit/database/factories');

registerPaths({
  migrations: ['./packages/billing/database/migrations'],
  seeders: './packages/billing/database/seeders',
});

The same focused path helpers are also available on the Arkorm class:

ts
import { Arkorm } from 'arkormx';

Arkorm.loadMigrationsFrom('./packages/audit/database/migrations');
Arkorm.loadSeedersFrom('./packages/audit/database/seeders');
Arkorm.loadModelsFrom('./packages/audit/src/models');
Arkorm.loadFactoriesFrom('./packages/audit/database/factories');

These helpers augment runtime discovery only. They do not mutate defineConfig({ paths: ... }), and generated files still use the configured primary paths.

Explicit runtime registration

You can also register concrete classes directly. This is useful for plugins, test harnesses, or bundled packages where the files may not live in a normal discovery directory:

ts
import {
  registerFactories,
  registerMigrations,
  registerModels,
  registerSeeders,
} from 'arkormx';
import { CreateAuditTablesMigration } from './database/migrations/CreateAuditTablesMigration';
import { AuditSeeder } from './database/seeders/AuditSeeder';
import { AuditLog } from './src/models/AuditLog';
import { AuditLogFactory } from './database/factories/AuditLogFactory';

registerMigrations(CreateAuditTablesMigration);
registerSeeders(AuditSeeder);
registerModels(AuditLog);
registerFactories(AuditLogFactory);

Or use the Arkorm class when you are already bootstrapping extensions through an Arkorm instance:

ts
import { Arkorm } from 'arkormx';

const arkorm = new Arkorm();

arkorm.registerMigrations(CreateAuditTablesMigration);
arkorm.registerSeeders(AuditSeeder);
arkorm.registerModels(AuditLog);
arkorm.registerFactories(AuditLogFactory);

The migration and seeder CLI commands include explicitly registered classes alongside discovered files. Explicit registrations can run even when no migration or seeder directory exists.

Runtime configuration

For frameworks that bootstrap Prisma elsewhere, use runtime configuration:

ts
import { configureArkormRuntime } from 'arkormx';

configureArkormRuntime(() => prisma, {
  outputExt: 'js',
});

Runtime configuration does not replace defineConfig({ adapter }). Prefer the top-level adapter field so Arkorm can apply one adapter automatically across your model layer, and use the lower-level binding APIs only for advanced cases such as transaction-scoped adapter overrides.

ts
import { createKyselyAdapter, defineConfig } from 'arkormx';

export default defineConfig({
  client: () => prisma,
  adapter: createKyselyAdapter(db),
});

Runtime configuration also enables transaction scopes through Model.transaction(...), because Arkorm can resolve the active runtime client and switch compatibility-adapter queries onto the transaction client automatically.

If you do not use compatibility-client features, you can omit client entirely and configure only adapter.