import type { FromSchema, JSONSchema } from "json-schema-to-ts";
import type { JsonPointer } from "./json-pointer.js";
export type LixForeignKeyScopeColumn = "version_id" | "file_id";
/**
 * Foreign key constraint definition
 */
export type LixForeignKey = {
    /**
     * Local JSON-schema property names that participate in the FK.
     * Must have at least one property.
     */
    properties: readonly JsonPointer[] | JsonPointer[];
    /**
     * Where they point to.
     */
    references: {
        /**
         * The x-lix-key of the referenced schema
         */
        schemaKey: string;
        /**
         * Remote property names (must have same length as local properties)
         */
        properties: readonly JsonPointer[] | JsonPointer[];
        /**
         * Optional version of the referenced schema
         */
        schemaVersion?: string;
    };
    /**
     * Validation mode for this foreign key.
     * - "immediate" (default): validate referenced existence on insert/update; restrict deletion when referenced.
     * - "materialized": skip insert/update existence checks (reference is derived/materialized later);
     *   still restrict deletion when referenced.
     */
    mode?: "immediate" | "materialized";
    /**
     * Implicit columns that scope the foreign key relationship.
     * When omitted, defaults to ["version_id", "file_id"] for state-backed schemas.
     * Provide an empty array to disable implicit scoping entirely.
     */
    scope?: readonly LixForeignKeyScopeColumn[] | LixForeignKeyScopeColumn[];
};
export declare const LixSchemaDefinition: {
    readonly $schema: "http://json-schema.org/draft-07/schema#";
    readonly title: "Lix Change Schema";
    readonly description: "A JSON schema document that also includes custom x-key and x-version properties for identification and versioning.";
    readonly allOf: readonly [{
        readonly $ref: "http://json-schema.org/draft-07/schema#";
    }, {
        readonly type: "object";
        readonly properties: {
            readonly "x-lix-unique": {
                readonly type: "array";
                readonly items: {
                    readonly type: "array";
                    readonly minItems: 1;
                    readonly uniqueItems: true;
                    readonly items: {
                        readonly type: "string";
                        readonly format: "json-pointer";
                        readonly description: "JSON Pointer referencing a property";
                    };
                };
            };
            readonly additionalProperties: {
                readonly type: "boolean";
                readonly const: false;
                readonly description: "Objects describing Lix schemas must not allow arbitrary additional properties; set this explicitly to false.";
            };
            readonly "x-lix-primary-key": {
                readonly type: "array";
                readonly minItems: 1;
                readonly uniqueItems: true;
                readonly items: {
                    readonly type: "string";
                    readonly format: "json-pointer";
                    readonly description: "JSON Pointer referencing a property that participates in the primary key.";
                };
            };
            readonly "x-lix-foreign-keys": {
                readonly type: "array";
                readonly items: {
                    readonly type: "object";
                    readonly required: readonly ["properties", "references"];
                    readonly properties: {
                        readonly properties: {
                            readonly type: "array";
                            readonly minItems: 1;
                            readonly items: {
                                readonly type: "string";
                                readonly format: "json-pointer";
                                readonly description: "JSON Pointer referencing the local field.";
                            };
                            readonly uniqueItems: true;
                            readonly description: "Local JSON-schema property names that participate in the FK";
                        };
                        readonly references: {
                            readonly type: "object";
                            readonly required: readonly ["schemaKey", "properties"];
                            readonly properties: {
                                readonly schemaKey: {
                                    readonly type: "string";
                                    readonly description: "The x-lix-key of the referenced schema";
                                };
                                readonly properties: {
                                    readonly type: "array";
                                    readonly minItems: 1;
                                    readonly items: {
                                        readonly type: "string";
                                        readonly format: "json-pointer";
                                        readonly description: "JSON Pointer referencing the remote field.";
                                    };
                                    readonly uniqueItems: true;
                                    readonly description: "Remote property names (same length as local properties)";
                                };
                                readonly schemaVersion: {
                                    readonly type: "string";
                                    readonly pattern: "^\\d+\\.\\d+$";
                                    readonly description: "Optional version of the referenced schema";
                                };
                            };
                        };
                        readonly mode: {
                            readonly type: "string";
                            readonly enum: readonly ["immediate", "materialized"];
                            readonly description: "Validation mode: immediate (default) or materialized (defer insert/update existence checks)";
                        };
                        readonly scope: {
                            readonly type: "array";
                            readonly items: {
                                readonly type: "string";
                                readonly enum: readonly ["version_id", "file_id"];
                            };
                            readonly uniqueItems: true;
                            readonly description: "Implicit columns (version_id and/or file_id) used to scope the foreign key relationship";
                        };
                    };
                };
            };
            readonly "x-lix-key": {
                readonly type: "string";
                readonly pattern: "^[a-z][a-z0-9_]*$";
                readonly description: "The schema identifier. Must be snake_case (lowercase, underscores) to safely embed in SQL identifiers.";
                readonly examples: readonly ["csv_plugin_cell"];
            };
            readonly "x-lix-immutable": {
                readonly type: "boolean";
                readonly description: "When true, entities for this schema cannot be updated after creation.";
            };
            readonly "x-lix-override-lixcols": {
                readonly type: "object";
                readonly description: "Default metadata column values (such as lixcol_file_id). Does not affect JSON property defaults.";
                readonly additionalProperties: {
                    readonly type: "string";
                    readonly format: "cel";
                };
            };
            readonly "x-lix-entity-views": {
                readonly type: "array";
                readonly description: "Restricts which SQL entity views (state/state_by_version/state_history) are generated. When omitted, all views are created.";
                readonly items: {
                    readonly type: "string";
                    readonly enum: readonly ["state", "state_by_version", "state_history"];
                };
                readonly uniqueItems: true;
            };
            readonly "x-lix-version": {
                readonly type: "string";
                readonly description: "The version of the schema. Use the major version to signal breaking changes. Use the minor version to signal non-breaking changes.";
                readonly pattern: "^\\d+\\.\\d+$";
                readonly examples: readonly ["1.0"];
            };
            readonly properties: {
                readonly type: "object";
                readonly additionalProperties: {
                    readonly allOf: readonly [{
                        readonly $ref: "http://json-schema.org/draft-07/schema#";
                    }, {
                        readonly type: "object";
                        readonly properties: {
                            readonly "x-lix-default": {
                                readonly type: "string";
                                readonly format: "cel";
                                readonly description: "CEL expression evaluated to produce the default value when the property is omitted.";
                            };
                        };
                    }];
                };
            };
        };
        readonly required: readonly ["x-lix-key", "x-lix-version", "additionalProperties"];
    }];
};
/**
 * Extended property schema that includes Lix-specific extensions
 */
type LixPropertySchema = JSONSchema & {
    "x-lix-default"?: string;
};
/**
 * LixSchema
 *
 * A superset of JSON Schema (draft-07) that includes Lix-specific metadata
 * and supports custom extensions.
 *
 * Custom extensions may be added with any x-* prefix.
 */
export type LixSchemaDefinition = JSONSchema & {
    /**
     * The key of the schema.
     *
     * The key is used to identify the schema. You must use a
     * unique key for each schema.
     *
     * @example
     *   "csv_plugin_cell"
     */
    "x-lix-key": string;
    /**
     * Marks the schema as immutable. Immutable entities may be inserted but cannot be updated.
     */
    "x-lix-immutable"?: boolean;
    /**
     * The version of the schema.
     *
     * Use the major version to signal breaking changes.
     * Use the minor version to signal non-breaking changes.
     *
     * @example
     *   "1.0"
     */
    "x-lix-version": string;
    /**
     * Override metadata column values applied by entity-view rewrites (e.g. `lixcol_file_id`).
     * Does not provide defaults for JSON properties inside `properties`. Each entry is a CEL
     * expression evaluated in the same context as property defaults.
     *
     * @example
     *   {
     *     "x-lix-override-lixcols": {
     *       "lixcol_file_id": "\"lix\"",
     *       "lixcol_untracked": "0"
     *     }
     *   }
     */
    "x-lix-override-lixcols"?: Record<string, string>;
    /**
     * Restricts which entity views are generated. When omitted, all default
     * variants (state, state_by_version, state_history) are emitted.
     *
     * @example
     *   {
     *     "x-lix-entity-views": ["state"] // only generate the base view
     *   }
     */
    "x-lix-entity-views"?: ("state" | "state_by_version" | "state_history")[] | readonly ("state" | "state_by_version" | "state_history")[];
    "x-lix-primary-key"?: JsonPointer[] | readonly JsonPointer[];
    /**
     * Properties that must be unique per version.
     *
     * Not to be confused by `x-version` which is used for versioning the schema.
     *
     *
     * @example
     *   {
     *     "x-lix-unique": [
     *       // the id must be unique
     *       ["/id"],
     *       // the name and age must be unique as well
     *       ["/name", "/age"],
     *     ],
     *     properties: {
     *       id: { type: "string" },
     *       name: { type: "string" },
     *       age: { type: "number" },
     *     },
     *   }
     */
    "x-lix-unique"?: JsonPointer[][] | readonly (readonly JsonPointer[])[];
    /**
     * Foreign key constraints referencing other schemas.
     *
     * @example
     *   [
     *     {
     *       "properties": ["/author_id"],
     *       "references": {
     *         "schemaKey": "user_profile",
     *         "properties": ["/id"]
     *       }
     *     },
     *     {
     *       "properties": ["/entity_id", "/schema_key", "/file_id"],
     *       "references": {
     *         "schemaKey": "state",
     *         "properties": ["/entity_id", "/schema_key", "/file_id"]
     *       }
     *     }
     *   ]
     */
    "x-lix-foreign-keys"?: LixForeignKey[] | readonly LixForeignKey[];
    type: "object";
    /**
     * Has to be false to know the schema beforehand.
     */
    additionalProperties: false;
    properties?: {
        [key: string]: LixPropertySchema;
    };
};
/**
 * Marker type for database columns that are auto-generated.
 *
 * This type brands values as "generated" to enable special handling in insert/update
 * operations. Generated fields become optional in inserts since the database
 * provides default values.
 *
 * The type accepts T values directly for developer convenience while preserving
 * the generated marker for type transformations.
 *
 * @example
 * ```typescript
 * type Account = {
 *   id: LixGenerated<string>;  // Auto-generated UUID
 *   name: string;              // User-provided
 *   created_at: LixGenerated<string>;  // Auto-generated timestamp
 * };
 *
 * // In inserts, generated fields are optional
 * const newAccount: LixInsertable<Account> = {
 *   name: "John"  // id and created_at are optional
 * };
 * ```
 */
export type LixGenerated<T> = T & {
    readonly __lixGenerated?: true;
};
/**
 * Check if a type has the LixGenerated brand
 */
type IsLixGenerated<T> = T extends {
    readonly __lixGenerated?: true;
} ? true : false;
/**
 * Extract the base type from LixGenerated<T>
 * Since LixGenerated<T> = T & { brand }, we need to extract T
 */
type ExtractFromGenerated<T> = T extends LixGenerated<infer U> ? U : T;
/**
 * Extract the select type from LixGenerated or return the type as-is
 */
type SelectType<T> = ExtractFromGenerated<T>;
/**
 * Extract the insert type from LixGenerated or return the type as-is
 */
type InsertType<T> = IsLixGenerated<T> extends true ? ExtractFromGenerated<T> | undefined : T;
/**
 * Extract the update type from LixGenerated or return the type as-is
 */
type UpdateType<T> = ExtractFromGenerated<T>;
/**
 * Evaluates to K if T can be null or undefined
 */
type IfNullable<T, K> = undefined extends T ? K : null extends T ? K : never;
/**
 * Evaluates to K if T can't be null or undefined
 */
type IfNotNullable<T, K> = undefined extends T ? never : null extends T ? never : T extends never ? never : K;
/**
 * Keys whose InsertType can be null or undefined (optional in inserts)
 */
type NullableInsertKeys<T> = {
    [K in keyof T]: IfNullable<InsertType<T[K]>, K>;
}[keyof T];
/**
 * Keys whose InsertType can't be null or undefined (required in inserts)
 */
type NonNullableInsertKeys<T> = {
    [K in keyof T]: IfNotNullable<InsertType<T[K]>, K>;
}[keyof T];
/**
 * Transform a type for insert operations.
 *
 * This type makes LixGenerated fields optional while keeping other required
 * fields mandatory. Use this when defining types for creating new entities.
 *
 * The database will automatically populate generated fields (like IDs,
 * timestamps) if not provided.
 *
 * @example
 * ```typescript
 * type Account = {
 *   id: LixGenerated<string>;
 *   name: string;
 *   email: string;
 *   created_at: LixGenerated<string>;
 * };
 *
 * type NewAccount = LixInsertable<Account>;
 * // Result: { name: string; email: string; id?: string; created_at?: string; }
 *
 * const account: NewAccount = {
 *   name: "John",
 *   email: "john@example.com"
 *   // id and created_at are optional
 * };
 * ```
 */
export type LixInsertable<T> = {
    [K in NonNullableInsertKeys<T>]: InsertType<T[K]>;
} & {
    [K in NullableInsertKeys<T>]?: InsertType<T[K]>;
};
/**
 * Transform a type for update operations.
 *
 * This type makes all fields optional, allowing partial updates where you
 * only specify the fields you want to change. LixGenerated markers are
 * removed since you're providing explicit values.
 *
 * The database preserves existing values for any fields not included
 * in the update.
 *
 * @example
 * ```typescript
 * type Account = {
 *   id: LixGenerated<string>;
 *   name: string;
 *   email: string;
 *   updated_at: LixGenerated<string>;
 * };
 *
 * type AccountUpdate = LixUpdateable<Account>;
 * // Result: { id?: string; name?: string; email?: string; updated_at?: string; }
 *
 * // Update only the email
 * const updates: AccountUpdate = {
 *   email: "newemail@example.com"
 *   // Other fields remain unchanged
 * };
 * ```
 */
export type LixUpdateable<T> = {
    [K in keyof T]?: UpdateType<T[K]>;
};
/**
 * Transform a type for select/query operations.
 *
 * This type unwraps all LixGenerated markers, giving you the actual engine
 * types that will be returned from database queries. All fields are required
 * and have their base types.
 *
 * Use this type when defining the shape of data returned from queries or
 * when passing entity data to UI components.
 *
 * @example
 * ```typescript
 * type Account = {
 *   id: LixGenerated<string>;
 *   name: string;
 *   email: string;
 *   created_at: LixGenerated<string>;
 * };
 *
 * type AccountData = LixSelectable<Account>;
 * // Result: { id: string; name: string; email: string; created_at: string; }
 *
 * // Query results have this shape
 * const accounts: AccountData[] = await db
 *   .selectFrom("account")
 *   .selectAll()
 *   .execute();
 *
 * console.log(accounts[0].id);  // string (not LixGenerated<string>)
 * ```
 */
export type LixSelectable<T> = {
    [K in keyof T]: SelectType<T[K]>;
};
type IsNever<T> = [T] extends [never] ? true : false;
type IsAny<T> = 0 extends 1 & T ? true : false;
/**
 * Transform object types with no properties from unknown to Record<string, any>
 */
type TransformEmptyObject<T> = IsAny<T> extends true ? any : IsNever<T> extends true ? never : T extends object ? keyof T extends never ? Record<string, any> : T : T;
/**
 * Check if a schema property is an empty object type (no properties defined)
 */
type IsEmptyObjectSchema<P> = P extends {
    type: "object";
} ? P extends {
    properties: any;
} ? false : true : false;
/**
 * Get the nullable part of a type based on schema
 */
type GetNullablePart<P> = P extends {
    nullable: true;
} ? null : never;
/**
 * Internal type that applies LixGenerated markers to properties that provide defaults.
 */
type PropertyHasDefault<P> = P extends {
    "x-lix-default": any;
} ? true : P extends {
    default: any;
} ? true : false;
type ApplyLixGenerated<TSchema extends LixSchemaDefinition> = TSchema extends {
    properties: infer Props;
} ? {
    [K in keyof FromSchema<TSchema>]: K extends keyof Props ? PropertyHasDefault<Props[K]> extends true ? LixGenerated<TransformEmptyObject<FromSchema<TSchema>[K]>> : IsEmptyObjectSchema<Props[K]> extends true ? Record<string, any> | GetNullablePart<Props[K]> : TransformEmptyObject<FromSchema<TSchema>[K]> : TransformEmptyObject<FromSchema<TSchema>[K]>;
} : never;
/**
 * Convert a LixSchemaDefinition to a TypeScript type.
 *
 * This type transformation:
 * 1. Converts JSON Schema properties to TypeScript types
 * 2. Wraps properties that declare defaults (`default` or `x-lix-default`) in LixGenerated markers
 * 3. Transforms `type: "object"` without properties to `Record<string, any>`
 *
 * The resulting type can be used with LixInsertable, LixUpdateable, and
 * LixSelectable for database operations.
 *
 * @example
 * ```typescript
 * const AccountSchema = {
 *   "x-lix-key": "account",
 *   "x-lix-version": "1.0",
 *   "x-lix-primary-key": ["/id"],
 *   type: "object",
 *   properties: {
 *     id: { type: "string", default: "auto-generated" },
 *     name: { type: "string" },
 *     email: { type: "string" },
 *     metadata: { type: "object" },  // Becomes Record<string, any>
 *     created_at: { type: "string", "x-lix-default": "lix_now()" }
 *   },
 *   required: ["id", "name", "email"],
 *   additionalProperties: false
 * } as const satisfies LixSchemaDefinition;
 *
 * type Account = FromLixSchemaDefinition<typeof AccountSchema>;
 * // Result: {
 * //   id: LixGenerated<string>;
 * //   name: string;
 * //   email: string;
 * //   metadata: Record<string, any> | undefined;
 * //   created_at: LixGenerated<string> | undefined;
 * // }
 * ```
 */
export type FromLixSchemaDefinition<T extends LixSchemaDefinition> = ApplyLixGenerated<T>;
export {};
//# sourceMappingURL=definition.d.ts.map