import type { Generated, Insertable, Selectable, Updateable } from "kysely"; import type { SqliteWasmDatabase } from "sqlite-wasm-kysely"; import { Declaration, Pattern, VariableReference, } from "../json-schema/pattern.js"; export function applySchema(args: { sqlite: SqliteWasmDatabase }) { const foreignKeyActivated: any = args.sqlite.exec("PRAGMA foreign_keys", { returnValue: "resultRows", }); if ( // first row that is returned // first column of the first row // is equal to 0, then foreign keys are disabled foreignKeyActivated[0][0] === 0 ) { args.sqlite.exec("PRAGMA foreign_keys = ON", { returnValue: "resultRows", }); } args.sqlite.exec(` CREATE TABLE IF NOT EXISTS bundle ( id TEXT PRIMARY KEY DEFAULT (human_id()), declarations BLOB NOT NULL DEFAULT (jsonb('[]')) ) strict; CREATE TABLE IF NOT EXISTS message ( id TEXT PRIMARY KEY DEFAULT (uuid_v7()), bundle_id TEXT NOT NULL, locale TEXT NOT NULL, selectors BLOB NOT NULL DEFAULT (jsonb('[]')), FOREIGN KEY (bundle_id) REFERENCES bundle(id) ON DELETE CASCADE ) strict; CREATE TABLE IF NOT EXISTS variant ( id TEXT PRIMARY KEY DEFAULT (uuid_v7()), message_id TEXT NOT NULL, matches BLOB NOT NULL DEFAULT (jsonb('[]')), pattern BLOB NOT NULL DEFAULT (jsonb('[]')), FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE ) strict; CREATE INDEX IF NOT EXISTS idx_message_bundle_id ON message (bundle_id); CREATE INDEX IF NOT EXISTS idx_variant_message_id ON variant (message_id); `); } export type InlangDatabaseSchema = { bundle: BundleTable; message: MessageTable; variant: VariantTable; }; type BundleTable = { id: Generated; declarations: Generated>; }; type MessageTable = { id: Generated; bundleId: string; locale: string; selectors: Generated>; }; type VariantTable = { id: Generated; messageId: string; matches: Generated>; pattern: Generated; }; /** * A match is a variable reference that is either a literal or a catch-all. * * https://github.com/opral/inlang/issues/205 * * @example * match = { type: "match", name: "gender", value: { type: "literal", value: "male" }} */ export type Match = LiteralMatch | CatchAllMatch; export type LiteralMatch = { type: "literal-match"; key: VariableReference["name"]; value: string; }; export type CatchAllMatch = { type: "catchall-match"; key: VariableReference["name"]; }; export type Bundle = Selectable; export type NewBundle = Insertable; export type BundleUpdate = Updateable; export type Message = Selectable; export type NewMessage = Insertable; export type MessageUpdate = Updateable; export type Variant = Selectable; export type NewVariant = Insertable; export type VariantUpdate = Updateable; export type MessageNested = Message & { variants: Variant[]; }; export type NewMessageNested = NewMessage & { variants: NewVariant[]; }; export type MessageNestedUpdate = Updateable & { variants: VariantUpdate[]; }; export type BundleNested = Bundle & { messages: MessageNested[]; }; export type NewBundleNested = NewBundle & { messages: NewMessageNested[]; }; export type BundleNestedUpdate = BundleUpdate & { messages: MessageNestedUpdate[]; };