import { Log } from '@spinajs/log-common'; import { IColumnDescriptor, IDriverOptions, IPoolOptions, ISupportedFeature, IsolationLevel, ITransactionContext, ITransactionOptions } from './interfaces.js'; import { SyncService, IContainer, Container } from '@spinajs/di'; import { UpdateQueryBuilder, SelectQueryBuilder, IndexQueryBuilder, DeleteQueryBuilder, InsertQueryBuilder, SchemaQueryBuilder, TruncateTableQueryBuilder, Builder } from './builders.js'; import { AsyncLocalStorage } from 'async_hooks'; import { ConnectionState, IConnectionResilienceOptions } from './resilience.js'; import { IPoolMetrics } from './metrics.js'; import './hydrators.js'; import './dehydrators.js'; /** * Body of a transaction. Whatever it resolves with becomes the result of `transaction()`. */ export type TransactionCallback = (driver: OrmDriver) => Promise; export declare abstract class OrmDriver extends SyncService { /** * Connection options */ Options: T; Container: IContainer; protected RootContainer: Container; protected Log: Log; /** * Ambient transaction context. * * Statements executed inside a `transaction()` callback must run on that transaction's * connection. This lives on the abstract driver — rather than being a MySQL implementation * detail, as it used to be — so the guarantee is part of the contract and every driver * inherits it. */ protected TransactionStorage: AsyncLocalStorage; /** * Isolation levels this driver honours. Empty by default: a driver that declares nothing * rejects every explicitly requested isolation level rather than quietly ignoring it. */ readonly SupportedIsolationLevels: IsolationLevel[]; /** * JSON-schema shapes for SQL types this driver hands back as something other than what * @spinajs/orm's shared map assumes, keyed by the same `IColumnDescriptor.Type` string. * Applied only to the RESPONSE schema - what a client may send is unaffected. * * Empty by default, because "how does this type arrive in JS" is a driver fact and only * the driver knows it: mysql2 returns DECIMAL as a string ( decimalNumbers off, so values * above 2^53 keep the precision DECIMAL exists for ), while tedious and sqlite return * numbers. Encoding any one of those answers in the shared map makes the generated * documentation lie for every other driver. */ readonly ResponseSchemaTypes: Readonly>; /** * The transaction currently in scope on this async execution path, or `undefined` outside * a transaction. */ get CurrentTransaction(): ITransactionContext | undefined; constructor(options: T); /** * Executes query on database * * @param stmt - query string or query objects that is executed in database * @param params - binding parameters * @param context - query context to optimize queries sent to DB */ abstract execute(builder: Builder): Promise; /** * Checks if database is avaible * @returns false if cannot reach database */ abstract ping(): Promise; /** * Connects to database * @throws OrmException if can't connec to to database */ abstract connect(): Promise; /** * Disconnects from database */ abstract disconnect(): Promise; /** * Get list of supported features for this connection */ abstract supportedFeatures(): ISupportedFeature; abstract tableInfo(name: string, schema?: string): Promise; resolve(): void; /** * Effective pool settings: `Pool.*` when given, then the deprecated `PoolLimit` for `Max`, * then the defaults. Resolved in one place so every driver agrees on what "unset" means. */ protected resolvedPoolOptions(): Required; private _state; /** * Current connection lifecycle state. */ get State(): ConnectionState; /** * Records a state transition and logs it. Repeat transitions to the same state are ignored. */ protected setState(state: ConnectionState): void; /** * Effective resilience settings with defaults applied. */ protected resolvedResilienceOptions(): Required; /** * True when the error means the transport died rather than the statement being wrong. * Drivers override to add dialect-specific codes. */ protected isRetryableError(err: unknown): boolean; /** * Runs `operation`, and on a retryable transport failure reconnects and retries with bounded * exponential backoff. Query errors propagate on the first attempt untouched. */ protected withReconnect(operation: () => Promise): Promise; private _healthCheckTimer; /** * Starts the periodic health probe. Replaces the single startup `ping()` — a connection that * was healthy at boot tells you nothing about a pool holding sockets to a database that has * since restarted. No-op when `Resilience.HealthCheckInterval` is 0. Idempotent. */ startHealthCheck(): void; /** * Stops the periodic health probe. Idempotent. */ stopHealthCheck(): void; /** * One health probe. A failed probe degrades the driver and attempts a single reconnect; it * never throws, because it runs on a timer with no caller to receive the error. */ protected runHealthCheck(): Promise; /** * Point-in-time pool state. The base implementation reports an empty pool; drivers that own a * real pool override it. Must never throw — it runs on the health-check timer. */ poolMetrics(): IPoolMetrics; /** * Pushes the current pool state and connection state to the shared `Metrics` registry from * `@spinajs/telemetry-common`. Nothing has to be wired for this to work — `Metrics` owns a * private registry and `@spinajs/telemetry`'s `/metrics` endpoint renders that same singleton. */ publishPoolMetrics(): void; /** * Records one pool-acquire wait, in SECONDS ( prometheus convention ). Drivers that own a real * pool call this from the acquire callback; keeping the prom-client objects behind this method * is what stops every driver from needing to know about `@spinajs/telemetry-common`. Never * throws, for the same reason `publishPoolMetrics` never throws. */ observeAcquireSeconds(seconds: number): void; /** * Creates select query builder associated with this connection. * This can be used to execute raw queries to db without orm model layer */ select(): SelectQueryBuilder; /** * Creates delete query builder associated with this connection. * This can be used to execute raw queries to db without orm model layer */ del(): DeleteQueryBuilder; /** * Creates insert query builder associated with this connection. * This can be used to execute raw queries to db without orm model layer */ insert(): InsertQueryBuilder; /** * Truncates given table */ truncate(table: string): TruncateTableQueryBuilder; /** * Creates update query builder associated with this connection. * This can be used to execute raw queries to db without orm model layer */ update(): UpdateQueryBuilder; /** * Creates schema query builder associated with this connection. * This can be use to modify database structure */ schema(): SchemaQueryBuilder; /** * Creates index query builder associated with this connection. * This can be use to create table indexes */ index(): IndexQueryBuilder; /** * Opens a transaction and returns its per-transaction context. Drivers that pool connections * acquire one here and put it on the context; drivers with a single shared handle return a * context without a connection. */ protected abstract _begin(options?: ITransactionOptions): Promise; /** * Commits the transaction described by `ctx`. */ protected abstract _commit(ctx: ITransactionContext): Promise; /** * Rolls the transaction described by `ctx` back. */ protected abstract _rollback(ctx: ITransactionContext): Promise; /** * Takes a named savepoint inside the transaction described by `ctx`. */ protected abstract _savepoint(ctx: ITransactionContext, name: string): Promise; /** * Releases a named savepoint — the nested block succeeded and its changes fold into the * enclosing transaction. */ protected abstract _releaseSavepoint(ctx: ITransactionContext, name: string): Promise; /** * Discards everything done since a named savepoint, leaving the enclosing transaction intact. */ protected abstract _rollbackToSavepoint(ctx: ITransactionContext, name: string): Promise; /** * Releases whatever `_begin` acquired. Called exactly once per transaction, on every exit * path. A no-op for drivers that acquire nothing. */ protected abstract _dispose(ctx: ITransactionContext): Promise; /** * Runs `cb` inside a transaction and owns its whole lifecycle: commits when the callback * resolves, rolls back when it throws, and releases the connection exactly once either way. * Resolves with whatever the callback returned. * * Statements issued inside the callback run on this transaction's connection automatically — * the context is carried through `AsyncLocalStorage`, so nothing has to be threaded through * by hand. * * Calling it again while a transaction is already in scope on this async path does **not** * open a second, independent transaction: it takes a savepoint, so a failing nested block * rolls back only its own work. * * @param cb - the transaction body * @param options - optional isolation level, validated against {@link SupportedIsolationLevels} */ transaction(cb: TransactionCallback, options?: ITransactionOptions): Promise; } //# sourceMappingURL=driver.d.ts.map