/** * The version-1 schema, and what a file must satisfy to be read as one. * * A workflow run is one SQLite database, and every question about whether that * file is *this* run's is answered here before a single row is trusted. * * Three answers are kept apart because a host acts on them differently. A file * that belongs to another program is a **format** failure: nothing here will * ever read it. A schema version this build does not implement is a **version** * failure: a later build might read it, and this one must not touch it. A file * that claims to be a version-1 workflow database and is not shaped like one is * **damage** — the header says the tables are there, so their absence or their * wrong shape is the file disagreeing with itself. * * Recognizing it is not the same as reading its table names. The stored * definition of every table is compared with the definition this build creates, * so a column that is gone, a constraint that was dropped, and a table nobody * declared are all caught before a row reaches a parser that assumes they hold. * * Nothing in this module writes to a database it did not just create. An * incompatible or damaged file is described and left exactly as it was found: a * host that silently replaced it would be claiming to continue a run whose * history it had just deleted. */ import type { DatabaseSync } from "node:sqlite"; import type { Database as CloudflareDatabase } from "../../vendor/cloudflare-computer-dofs/generated/storage"; /** * The bytes `XMD1` as a 32-bit integer, written into the SQLite header. * * A database carries what wrote it, so a file that is perfectly valid SQLite * and belongs to something else is refused on sight rather than through the * confusing shape of its missing tables. */ export declare const APPLICATION_ID = 1481458737; /** * The version a Git-definition run is written at, and reads back as. * * Still the value it always was. A version-2 database is a different inventory * rather than a later amendment of this one, so redefining this constant to * mean "latest" would silently move every version-1 assertion that names it. */ export declare const SCHEMA_VERSION = 1; /** The version a source-bundle run is written at, and reads back as. */ export declare const SOURCE_BUNDLE_SCHEMA_VERSION = 2; /** Every live schema version this build recognizes. */ export type WorkflowSchemaVersion = 1 | 2; export declare const EXPECTED_SCHEMA: readonly Readonly<{ name: string; type: "index" | "table"; sql: string; }>[]; /** The same declarations, for the source-bundle inventory. */ export declare const SOURCE_BUNDLE_EXPECTED_SCHEMA: readonly Readonly<{ name: string; type: "index" | "table"; sql: string; }>[]; /** * Objects a version-1 file must hold, including the pinned Cloudflare * structure. * * The optional ones are absent from this list and only from this list: they are * created with every new database, compared against their declaration wherever * they are found, and simply not demanded of a file written before they * existed. */ export declare const REQUIRED_OBJECTS: readonly string[]; /** Tables a version-1 file must hold. */ export declare const REQUIRED_TABLES: readonly string[]; /** Every object version 1 declares, required or not. */ export declare const DECLARED_OBJECTS: readonly string[]; /** * The exact declaration of one optional table, for the transaction that first * needs it. * * There is one spelling of this table and it is the one above. A caller creates * it from this rather than writing its own, because a second copy of a CREATE * statement is a second shape that verification would then call damage. */ export declare function declaredObjectSql(name: string): string; /** Version 1 in full. */ export declare const SCHEMA_SQL: string; /** Version 2 in full. */ export declare const SOURCE_BUNDLE_SCHEMA_SQL: string; /** * Write one live schema into a database that holds nothing. * * Called inside the caller's transaction, so the application id, the version * and the tables appear together or not at all — a half-initialized file would * be indistinguishable from one this build must refuse. * * The version comes from the candidate definition that is about to be written, * never from what a file already claims: this initializes an empty database and * nothing here ever upgrades one. */ export declare function initializeSchema(database: DatabaseSync, dofs: CloudflareDatabase, initializeRun: () => void, version?: WorkflowSchemaVersion): void; /** * The version a recognized database declares. * * Read from the pragma rather than inferred from the descriptor a row holds: * the pragma is what structural recognition just held the whole inventory to, * and a row parsed under a version its own file does not declare would be read * with columns that file does not have. */ export declare function liveSchemaVersion(database: DatabaseSync, path: string): WorkflowSchemaVersion; /** * Whether a database holds nothing at all, and may therefore be initialized. * * Pristine means all three: no application id, no schema version, and not one * object anybody created. A file carrying a version but no tables, or tables * belonging to something else, is not empty — it is a file this build has no * business writing into, whatever its header happens to say. */ export declare function isUninitialized(database: DatabaseSync, path: string): boolean; /** * Refuse anything that is not a workflow-run database this build recognizes. * * Structure only. Whether the rows describe the run that was asked for is a * separate question, asked after this one succeeds. * * The application id is read first, and only then the version — and the version * selects one of exactly two immutable inventories. Nothing here repairs, * migrates or reinterprets: a file whose objects are a mixture of the two, or * that carries an extra one, disagrees with the version it declares and is left * as it was found. */ export declare function verifySchema(database: DatabaseSync, path: string, dofs: CloudflareDatabase): void; /** * The same recognition, answering which version it recognized. * * A reader that has to parse a row differently per version asks this, so the * version a record is read under is the one structural recognition just proved * rather than one read again afterwards. */ export declare function verifyRecognizedSchema(database: DatabaseSync, path: string, dofs: CloudflareDatabase): WorkflowSchemaVersion; /** * Ask SQLite whether it can still read its own file. * * A page-level failure surfaces here rather than as an unreadable row much * later, which is what keeps damage distinguishable from a record this build * cannot parse. */ export declare function checkIntegrity(database: DatabaseSync, path: string): void; /** * A crashed run, read through a connection that cannot recover it. * * Provider-private and deliberately not a `WorkflowStorageError`: it is not an * outcome any caller receives, it is the one condition read-only inspection * answers by recovering a private copy instead. Whatever inspection produces * after that — a snapshot, a recognition refusal, or a recovery failure — is * what the caller sees, so this never leaves the Deno provider. */ export declare class WorkflowReadonlyRollbackError extends Error { name: string; readonly path: string; constructor(path: string); } /** * The typed refusal a SQLite failure describes, or the failure unchanged. * * Keyed on the code SQLite reports rather than on the words in its message, so * a storage failure of our own passes through as itself instead of being * re-read as damage because of what it happens to say. */ export declare function translateSqliteError(error: unknown, path: string): unknown; export declare function isSqliteForeignKeyConstraint(error: unknown): boolean;