import type { LocaleConfig } from "./i18n"; /** Supported database driver identifiers. */ export type DatabaseDriver = "mysql" | "pgsql" | "postgres" | "sqlite"; /** SQL dialect for generated migrations. */ export type SQLDialect = "mysql" | "postgresql" | "sqlite"; /** Migration type identifier. */ export type MigrationType = "laravel" | "sql"; /** Per-migration output configuration. */ export interface MigrationConfig { /** Migration output type. */ type: MigrationType; /** Output directory for migration files. */ path: string; /** Path for exported schemas JSON (laravel only). */ schemasPath?: string; /** SQL dialect for generated migrations (sql only). */ dialect?: SQLDialect; /** Use deterministic timestamps (year-2000 base + sort-order offset) for packages. Issue #60. */ stableTimestamps?: boolean; } /** Per-connection database and migration configuration. */ export interface ConnectionConfig { driver: DatabaseDriver; migrations?: MigrationConfig[]; } /** TypeScript codegen configuration. */ export interface CodegenTypeScriptConfig { /** Enable TypeScript codegen. Defaults to false. */ enable: boolean; /** Output directory for generated TypeScript model files (legacy alias for `output`). */ modelsPath?: string; /** Output directory for generated TypeScript model files. Preferred over `modelsPath`; symmetrical with the top-level `input` field used by consumer-mode configs. */ output?: string; } /** Laravel codegen path configuration for a target (model, request, etc.). */ export interface CodegenLaravelPathConfig { /** Disable generation for layers that support it (currently `service`). */ enable?: boolean; /** Output directory path for the BASE (auto-generated, regenerated) class. */ path?: string; /** PHP namespace for the BASE class. Defaults to namespace derived from path. */ namespace?: string; /** * Output directory path for the USER-EDITABLE stub. Defaults to `path` * (legacy: editable stub shares the dir with base). Set to e.g. * `app/Models` to put stubs at the canonical Laravel location while * keeping bases isolated under `app/Omnify/`. Issue #96, v5.4+. */ userEditablePath?: string; /** * PHP namespace for the USER-EDITABLE stub. Defaults to `namespace`. * When set, the editable stub uses this namespace and `extends` the * base via the base's full FQN. Issue #96, v5.4+. */ userEditableNamespace?: string; /** * `true` collapses the legacy two-tier shape (base under `Base/` / * `OmnifyBase/` subfolder with `*Base*` suffix) into a single flat * directory: base lives at `path` with class name = `` for * models or `` for service / resource / etc. The * editable stub then `extends \{namespace}\` directly — one * less indirection. Recommended when `path` already isolates * generated code (e.g. `app/Omnify/Models/`). Issue #96, v5.4+. */ flatBase?: boolean; /** * Issue #98 v5.8.5: when `true`, the user-editable layer's path + * namespace mirrors the schema's group folder (e.g. * `app/Models/Auth/User.php`, namespace `App\Models\Auth`). Default * `false` — Laravel-canonical FLAT layout (`app/Models/User.php`, * namespace `App\Models`); group is encoded only in the base layer * and the `use ... as Base` import inside the editable stub. Per * layer (model / service / request / resource / policy / controller). */ userEditableGroupByFolder?: boolean; } /** Nested set package configuration. */ export interface CodegenNestedSetConfig { /** PHP namespace for the nested set package. Defaults to "Aimeos\Nestedset". */ namespace?: string; } /** Laravel PHP codegen configuration. */ export interface CodegenLaravelConfig { /** Enable Laravel codegen. Defaults to false. */ enable: boolean; /** * Filesystem prefix applied to all generated paths. Use this for monorepo * setups where the Laravel project lives in a subdirectory, e.g. `backend` * makes everything write under `backend/app/...`, `backend/config/...`, etc. */ rootPath?: string; /** Directory layout: "legacy" (default) or "modular". */ structure?: "legacy" | "modular"; /** * High-level layout convention (issue #98, v5.7+). * - "legacy" (default): editable stubs share the dir with the base * (matches v5.x behavior — no migration needed). * - "canonical": splits bases under `app/Omnify//` and * editable stubs at canonical Laravel paths * (`app/Models/`, `app/Http/Requests/`, ...). One-line shortcut * for the canonical opt-in instead of the verbose 6-layer block. * Per-layer `userEditablePath` / `userEditableNamespace` * overrides win. v6.0 plan: flip default to "canonical". */ layout?: "legacy" | "canonical"; /** Model output configuration. */ model?: CodegenLaravelPathConfig; /** Request output configuration. */ request?: CodegenLaravelPathConfig; /** Resource output configuration. */ resource?: CodegenLaravelPathConfig; /** Factory output configuration. */ factory?: CodegenLaravelPathConfig; /** Provider output configuration. */ provider?: CodegenLaravelPathConfig; /** Policy output configuration (default: app/Policies/Omnify). */ policy?: CodegenLaravelPathConfig; /** Controller output configuration (default: app/Http/Controllers). */ controller?: CodegenLaravelPathConfig; /** Service output configuration (default: app/Services). */ service?: CodegenLaravelPathConfig; /** Route file output configuration (default: routes/api/omnify). */ route?: CodegenLaravelPathConfig; /** Path for the omnify-schemas.php config file (default: config/omnify-schemas.php). */ config?: CodegenLaravelPathConfig; /** Nested set package configuration. Only applies to schemas with nestedSet: true. */ nestedset?: CodegenNestedSetConfig; } /** Migration emission style for the Go target. Issue #103. */ export type GoMigrationStyle = "inline" | "numbered_files"; /** Go database / SQL dialect for the Go migrations generator. */ export type GoDatabase = "sqlite" | "mysql" | "mariadb" | "postgres"; /** Output path + package name for one Go codegen sub-target. */ export interface CodegenGoPathConfig { outputPath?: string; packageName?: string; } /** Schema include / exclude filter for a Go target. */ export interface CodegenGoSchemaFilter { include?: string[]; exclude?: string[]; } /** * Bun ORM (uptrace/bun) tag emission. When `enable: true`, generated * structs gain `bun:"..."` struct tags + an embedded `bun.BaseModel`. * Issue #103. */ export interface CodegenGoBunConfig { /** Turn Bun tag emission on. Default false → plain structs (json + db tags). */ enable?: boolean; /** * Table alias on `bun.BaseModel`. Empty → omnify derives one from the * schema name (e.g. ProjectDoc → "pd"). Set to "-" to suppress alias. */ alias?: string; /** Import path for `bun.BaseModel`. Defaults to "github.com/uptrace/bun". */ baseModelImport?: string; /** Tag fragment used on soft-delete columns. Default ",soft_delete,nullzero". */ softDeleteTag?: string; } /** Go (uptrace/bun-friendly) codegen target. Issue omnify-jp/omnify-go#65 + #103. */ export interface CodegenGoTarget { /** Target identifier for partial-regen flags. */ name?: string; /** Enable this target. Defaults to false. */ enable?: boolean; /** Root path for generated Go files (e.g. "./backend"). */ rootPath?: string; /** SQL dialect for the migrations generator. Default "sqlite". */ database?: GoDatabase; /** Go module path (e.g. "github.com/org/app"). Reads go.mod when empty. */ modulePath?: string; /** Plain-struct output (`{Model}Base` + json/db tags). */ domain?: CodegenGoPathConfig; /** Enums package output. */ enums?: CodegenGoPathConfig; /** Migrations output (style depends on `migrationStyle` + `database`). */ migrations?: CodegenGoPathConfig; /** sqlc query files output. */ sqlc?: CodegenGoPathConfig; /** * Trivial CRUD repository generator (Phase 2 of issue #103). * Emits `_repo.go` per object schema with Get / Insert / * Update / Delete / List backed by Bun, plus a shared `errors.go` * (`ErrNotFound` sentinel). Skipped for `kind: enum` / `kind: pivot` * / partial schemas. Uses Bun's `OmitZero()` on Update to avoid * clobbering DDL-default columns when caller leaves them at zero. */ repo?: CodegenGoPathConfig; /** Schema include / exclude filter for this target. */ schemas?: CodegenGoSchemaFilter; /** Bun ORM tag emission (default off; opt in via `bun.enable: true`). */ bun?: CodegenGoBunConfig; /** * Migration emission style. * "inline" — generated//migrations.go with `Migrations []string` slice * "numbered_files" — migrations/NNNN_*.up.sql + .down.sql (golang-migrate compatible) * Defaults: sqlite → "numbered_files"; mysql/mariadb/postgres → "inline". */ migrationStyle?: GoMigrationStyle; /** Emit `json:"..."` struct tags. Default true. */ jsonTags?: boolean; /** Append `,omitempty` to json tags for nullable / pointer fields. Default true. */ omitemptyForNullable?: boolean; /** * Auto-generate `_translations` sidecar tables + Go structs * (Bun has-many relation when `bun.enable: true`) for properties * marked `translatable: true`. Default true when any translatable * field is present. */ emitTranslations?: boolean; } /** Code generation configuration (connection-independent). */ export interface CodegenConfig { typescript?: CodegenTypeScriptConfig; laravel?: CodegenLaravelConfig; /** Go target — plain structs + migrations + optional Bun tags. */ go?: CodegenGoTarget | CodegenGoTarget[]; } /** * Audit configuration. Two related features in one block: * * - The `created_by_id` / `updated_by_id` / `deleted_by_id` columns * auto-populated from `auth()->user()` (createdBy / updatedBy / * deletedBy toggles). * - The `audits` history table that records every model lifecycle * event into a single polymorphic table for compliance / debugging * (issue #94 — log / logExclude / logRetention / logQueue). * * Per-schema overrides live under `options.audit:` in each schema YAML. */ export interface AuditConfig { /** * Schema name of the actor / user model (typically `User`). Required * when `log: true` because the audits row records the polymorphic * `(user_type, user_id)` of the writer. The referenced schema MUST * have `options.authenticatable: true`. */ model?: string; /** Global default for the `created_by_id` audit column. */ createdBy?: boolean; /** Global default for the `updated_by_id` audit column. */ updatedBy?: boolean; /** Global default for the `deleted_by_id` audit column. */ deletedBy?: boolean; /** * Toggle the audits-history table feature globally. Per-schema * `options.audit.log` overrides. Records created / updated / deleted * / restored events into a single polymorphic `audits` table. */ log?: boolean; /** * Additional sensitive columns scrubbed from `old_values` / * `new_values` BEFORE the audit row is built. Built-in defaults * (`password`, `remember_token`, `api_token`, `two_factor_secret`, * `two_factor_recovery_codes`) are always merged in — your list ADDS * to them, never replaces. */ logExclude?: string[]; /** * Prunable retention period (`90d` / `12w` / `6m` / `1y`). Empty * string keeps audits forever (no scheduled prune). Format is * validated; bad input fails generation. */ logRetention?: string; /** * Laravel queue connection name for the WriteAuditLog job. Empty * string forces synchronous dispatch — only acceptable in dev / * low-traffic apps. Production should use a queue backed by a real * driver (redis, sqs, etc.). */ logQueue?: string; } /** * Plan/debug workflow backend selection. Default 'local' writes * `plans/plan-NNN/` and `debugs/debug-NNN/` folders in the repo — * matches the historical omnify-plan / omnify-debug skill output * byte-for-byte. Future backends (GitHub issues, internal wiki, * Notion, ...) plug in via `internal/workflow.Backend` without * changes to skills, status command, or MCP tools. * * Long-form `.md` content (DESIGN/TESTS/NOTES, SYMPTOMS/INVESTIGATION/FIX) * always lives in the repository regardless of backend; only metadata * + task checklist routes through the chosen backend. This keeps git * as the source of truth for design content (atomic with code commits, * no size limits) while letting team coordination move to whichever * tool fits. */ export interface WorkflowConfig { /** * Backend kind. Open enum: `local` is built-in; future values are * accepted by newer omnify versions, ignored (with warning) by * older binaries — your config doesn't crash old CLIs. */ backend?: 'local' | (string & {}); /** LocalBackend overrides — only consulted when backend is 'local' or omitted. */ local?: { /** Directory holding `plan-NNN/` subdirectories. Default 'plans'. */ plansDir?: string; /** Directory holding `debug-NNN/` subdirectories. Default 'debugs'. */ debugsDir?: string; }; } /** External schema package configuration. */ export interface PackageConfig { /** Path to package root (short form: auto-discovers omnify.yaml inside). */ path?: string; /** Package identifier. Defaults to directory basename (short form) or required (long form). */ name?: string; /** Path to schemas directory (long form only). */ schemasDir?: string; /** Path to package lock file (long form only). */ lockFile?: string; /** Codegen overrides for this package. */ codegen?: CodegenConfig; /** * Schemas-only package mode (issue #94). When true, the package * ships ONLY YAML schemas — no `omnify.yaml`, no `lock.json`, no * `database/migrations/` tree. The host project owns migrations, * lock state, and codegen for this package's schemas; the * `s.Package` tag is still set so consumer-side codegen lands * classes in the right per-package namespace. * * - Requires `path` or explicit `schemasDir`. * - Forbids `lockFile` (host's lock is the single source of truth). * - `kind: extend` overlays in the host merge into the base CREATE * on first generate; later additions emit ALTER as usual. */ inline?: boolean; } /** Main Omnify configuration (omnify.yaml). */ export interface OmnifyConfig { /** * Consumer-mode shortcut: path/URL/npm-spec for an upstream `schemas.json`. * When set, omnify-ts skips the connections+migrations indirection and * uses this value directly. Accepts a local path (relative to this file), * an http(s) URL (cached + pinned via `.omnify/input.lock.json`), or a * scoped npm package specifier (e.g. `@famgia/dxs-product-schemas/schemas.json`). * Frontend / consumer projects should use this; backend projects use * `schemasDir` + `connections` instead. */ input?: string; /** Directory containing schema YAML files. */ schemasDir?: string; /** External schema packages to consume. */ packages?: PackageConfig[]; /** Path to the lock file for tracking migration state. */ lockFilePath?: string; /** Database connection configurations. */ connections?: Record; /** Default connection name. */ default?: string; /** Locale settings for multi-language support. */ locale?: LocaleConfig; /** Built-in compound type packs to enable (e.g. "japan"). */ compoundTypes?: string[]; /** Code generation configuration (connection-independent). */ codegen?: CodegenConfig; /** Audit columns + audit-log history table feature (issue #94). */ audit?: AuditConfig; /** Plan/debug workflow backend (default 'local'). */ workflow?: WorkflowConfig; /** Package mode: stable deterministic timestamps for all Laravel migrations. Issue #60. */ package?: boolean; /** Enable verbose output during generation. */ verbose?: boolean; }