{"version":3,"file":"session.cjs","names":["entityKind","NoopCache","DrizzleQueryError","sql","SingleStoreDatabase","TransactionRollbackError"],"sources":["../../src/singlestore-core/session.ts"],"sourcesContent":["import type * as V1 from '~/_relations.ts';\nimport { type Cache, NoopCache, strategyFor } from '~/cache/core/cache.ts';\nimport type { WithCacheConfig } from '~/cache/core/types.ts';\nimport { entityKind, is } from '~/entity.ts';\nimport { DrizzleQueryError, TransactionRollbackError } from '~/errors.ts';\nimport type { Logger } from '~/logger.ts';\nimport type { AnyRelations, EmptyRelations } from '~/relations.ts';\nimport type { PreparedQuery } from '~/session.ts';\nimport { fillPlaceholders, type Query, type SQL, sql } from '~/sql/sql.ts';\nimport { assertUnreachable, type Assume, type Equal } from '~/utils.ts';\nimport { SingleStoreDatabase } from './db.ts';\nimport type { SingleStoreDialect } from './dialect.ts';\n\nexport interface SingleStoreQueryResultHKT {\n\treadonly $brand: 'SingleStoreQueryResultHKT';\n\treadonly row: unknown;\n\treadonly type: unknown;\n}\n\nexport interface AnySingleStoreQueryResultHKT extends SingleStoreQueryResultHKT {\n\treadonly type: any;\n}\n\nexport type SingleStoreQueryResultKind<TKind extends SingleStoreQueryResultHKT, TRow> = (TKind & {\n\treadonly row: TRow;\n})['type'];\n\nexport interface SingleStorePreparedQueryConfig {\n\texecute: unknown;\n\titerator: unknown;\n}\n\nexport interface SingleStorePreparedQueryHKT {\n\treadonly $brand: 'SingleStorePreparedQueryHKT';\n\treadonly config: unknown;\n\treadonly type: unknown;\n}\n\nexport type AnySingleStoreMapper = (\n\tresponse: Record<string, unknown>[] | unknown[][] | { insertId: number; affectedRows: number },\n) => any;\n\nexport type PreparedQueryKind<\n\tTKind extends SingleStorePreparedQueryHKT,\n\tTConfig extends SingleStorePreparedQueryConfig,\n\tTAssume extends boolean = false,\n> = Equal<TAssume, true> extends true\n\t? Assume<(TKind & { readonly config: TConfig })['type'], SingleStoreBasePreparedQuery<TConfig>>\n\t: (TKind & { readonly config: TConfig })['type'];\n\nexport abstract class SingleStoreBasePreparedQuery<T extends SingleStorePreparedQueryConfig> implements PreparedQuery {\n\tstatic readonly [entityKind]: string = 'SingleStoreBasePreparedQuery';\n\n\tconstructor(\n\t\tprotected query: Query,\n\t) {}\n\n\tgetQuery(): Query {\n\t\treturn this.query;\n\t}\n\n\tabstract execute(placeholderValues?: Record<string, unknown>): Promise<T['execute']>;\n\n\tabstract iterator(placeholderValues?: Record<string, unknown>): AsyncGenerator<T['iterator']>;\n}\n\nexport class SingleStorePreparedQuery<T extends SingleStorePreparedQueryConfig>\n\textends SingleStoreBasePreparedQuery<T>\n{\n\tstatic override readonly [entityKind]: string = 'SingleStorePreparedQuery';\n\n\t/** @internal */\n\treadonly mapper: {\n\t\t(rows: any[]): any;\n\t\tbody?: string;\n\t} | undefined;\n\n\tprivate fastPath: boolean;\n\n\tconstructor(\n\t\tprotected executor: (params?: unknown[]) => Promise<any>,\n\t\tprotected _iterator: ((params?: unknown[]) => AsyncGenerator<any>) | undefined,\n\t\tquery: Query,\n\t\tmapper: AnySingleStoreMapper | undefined,\n\t\treadonly mode: 'arrays' | 'objects' | 'raw',\n\t\tprotected logger: Logger,\n\t\t// cache instance\n\t\tprivate cache: Cache | undefined,\n\t\t// per query related metadata\n\t\tprivate queryMetadata: {\n\t\t\ttype: 'select' | 'update' | 'delete' | 'insert';\n\t\t\ttables: string[];\n\t\t} | undefined,\n\t\t// config that was passed through $withCache\n\t\tprivate cacheConfig?: WithCacheConfig | undefined,\n\t) {\n\t\tsuper(query);\n\t\tthis.mapper = mapper;\n\t\t// it means that no $withCache options were passed and it should be just enabled\n\t\tif (cache && cache.strategy() === 'all' && cacheConfig === undefined) {\n\t\t\tthis.cacheConfig = { enabled: true, autoInvalidate: true };\n\t\t}\n\t\tif (!this.cacheConfig?.enabled) {\n\t\t\tthis.cacheConfig = undefined;\n\t\t}\n\n\t\tthis.fastPath = cacheConfig === undefined\n\t\t\t&& (cache === undefined || is(cache, NoopCache));\n\t}\n\n\t/** @internal */\n\tprotected async queryWithCache<T>(\n\t\tqueryString: string,\n\t\tparams: any[],\n\t\tquery: () => Promise<T>,\n\t): Promise<T> {\n\t\tconst cacheStrat = this.cache !== undefined && !is(this.cache, NoopCache)\n\t\t\t? await strategyFor(queryString, params, this.queryMetadata, this.cacheConfig)\n\t\t\t: { type: 'skip' as const };\n\n\t\tif (cacheStrat.type === 'skip') {\n\t\t\treturn query().catch((e) => {\n\t\t\t\tthrow new DrizzleQueryError(queryString, params, e as Error);\n\t\t\t});\n\t\t}\n\n\t\tconst cache = this.cache!;\n\n\t\t// For mutate queries, we should query the database, wait for a response, and then perform invalidation\n\t\tif (cacheStrat.type === 'invalidate') {\n\t\t\treturn Promise.all([\n\t\t\t\tquery(),\n\t\t\t\tcache.onMutate({ tables: cacheStrat.tables }),\n\t\t\t]).then((res) => res[0]).catch((e) => {\n\t\t\t\tthrow new DrizzleQueryError(queryString, params, e as Error);\n\t\t\t});\n\t\t}\n\n\t\tif (cacheStrat.type === 'try') {\n\t\t\tconst { tables, key, isTag, autoInvalidate, config } = cacheStrat;\n\t\t\tconst fromCache = await cache.get(\n\t\t\t\tkey,\n\t\t\t\ttables,\n\t\t\t\tisTag,\n\t\t\t\tautoInvalidate,\n\t\t\t);\n\n\t\t\tif (fromCache === undefined) {\n\t\t\t\tconst result = await query().catch((e) => {\n\t\t\t\t\tthrow new DrizzleQueryError(queryString, params, e as Error);\n\t\t\t\t});\n\t\t\t\t// put actual key\n\t\t\t\tawait cache.put(\n\t\t\t\t\tkey,\n\t\t\t\t\tresult,\n\t\t\t\t\t// make sure we send tables that were used in a query only if user wants to invalidate it on each write\n\t\t\t\t\tautoInvalidate ? tables : [],\n\t\t\t\t\tisTag,\n\t\t\t\t\tconfig,\n\t\t\t\t);\n\t\t\t\t// put flag if we should invalidate or not\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\treturn fromCache as unknown as T;\n\t\t}\n\n\t\tassertUnreachable(cacheStrat);\n\t}\n\n\toverride async execute(placeholderValues: Record<string, unknown> = {}): Promise<T['execute']> {\n\t\tconst { query, logger, executor, mapper, fastPath } = this;\n\t\tconst { sql } = query;\n\t\tconst params = query.params.length === 0\n\t\t\t? query.params\n\t\t\t: fillPlaceholders(query.params, placeholderValues);\n\t\tlogger.logQuery(sql, params);\n\n\t\tconst res = fastPath\n\t\t\t? executor(params).catch((e) => {\n\t\t\t\tthrow new DrizzleQueryError(sql, params, e as Error);\n\t\t\t})\n\t\t\t: this.queryWithCache(sql, params, () => executor(params));\n\t\tif (!mapper) return res;\n\n\t\treturn res.then((rows) => mapper(rows));\n\t}\n\n\toverride async *iterator(placeholderValues: Record<string, unknown> = {}): AsyncGenerator<T['iterator']> {\n\t\tconst { query, logger, executor, _iterator, mapper, fastPath } = this;\n\t\tconst { sql } = query;\n\t\tconst params = query.params.length === 0\n\t\t\t? query.params\n\t\t\t: fillPlaceholders(query.params, placeholderValues);\n\t\tlogger.logQuery(sql, params);\n\n\t\tif (_iterator) {\n\t\t\ttry {\n\t\t\t\tif (mapper) {\n\t\t\t\t\tfor await (const row of _iterator(params)) {\n\t\t\t\t\t\tconst mapped = mapper([row]);\n\t\t\t\t\t\tyield Array.isArray(mapped) ? mapped[0] : mapped;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor await (const row of _iterator(params)) {\n\t\t\t\t\tyield row as Awaited<T['iterator']>;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new DrizzleQueryError(sql, params, e as Error);\n\t\t\t}\n\t\t}\n\n\t\t// Fallback for compatibility between drivers\n\t\tconst rows = await (fastPath\n\t\t\t? executor(params).catch((e) => {\n\t\t\t\tthrow new DrizzleQueryError(sql, params, e as Error);\n\t\t\t})\n\t\t\t: this.queryWithCache(sql, params, () => executor(params)));\n\n\t\tif (mapper) {\n\t\t\tfor (const row of rows) {\n\t\t\t\tconst mapped = mapper([row]);\n\t\t\t\tyield Array.isArray(mapped) ? mapped[0] : mapped;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const row of rows) {\n\t\t\tyield row;\n\t\t}\n\t}\n}\n\nexport interface SingleStoreTransactionConfig {\n\twithConsistentSnapshot?: boolean;\n\taccessMode?: 'read only' | 'read write';\n\tisolationLevel: 'read committed'; // SingleStore only supports read committed isolation level (https://docs.singlestore.com/db/v8.7/introduction/faqs/durability/)\n}\n\nexport abstract class SingleStoreSession<\n\tTQueryResult extends SingleStoreQueryResultHKT = SingleStoreQueryResultHKT,\n\tTPreparedQueryHKT extends PreparedQueryHKTBase = PreparedQueryHKTBase,\n\tTFullSchema extends Record<string, unknown> = Record<string, never>,\n\tTRelations extends AnyRelations = EmptyRelations,\n\tTSchema extends V1.TablesRelationalConfig = Record<string, never>,\n> {\n\tstatic readonly [entityKind]: string = 'SingleStoreSession';\n\n\tconstructor(protected dialect: SingleStoreDialect) {}\n\n\tabstract prepareQuery<\n\t\tT extends SingleStorePreparedQueryConfig,\n\t\tTPreparedQueryHKT extends SingleStorePreparedQueryHKT,\n\t>(\n\t\tquery: Query,\n\t\tmode: 'arrays' | 'objects' | 'raw',\n\t\tmapper?: (rows: any) => any,\n\t\tqueryMetadata?: {\n\t\t\ttype: 'select' | 'update' | 'delete' | 'insert';\n\t\t\ttables: string[];\n\t\t},\n\t\tcacheConfig?: WithCacheConfig,\n\t): PreparedQueryKind<TPreparedQueryHKT, T>;\n\n\texecute<T>(query: SQL): Promise<T> {\n\t\treturn this.prepareQuery<SingleStorePreparedQueryConfig & { execute: T }, PreparedQueryHKTBase>(\n\t\t\tthis.dialect.sqlToQuery(query),\n\t\t\t'raw',\n\t\t).execute();\n\t}\n\n\tarrays<T = unknown>(query: SQL): Promise<T[]> {\n\t\treturn this.prepareQuery<SingleStorePreparedQueryConfig & { execute: T[] }, PreparedQueryHKTBase>(\n\t\t\tthis.dialect.sqlToQuery(query),\n\t\t\t'arrays',\n\t\t).execute();\n\t}\n\n\tobjects<T = unknown>(query: SQL): Promise<T[]> {\n\t\treturn this.prepareQuery<SingleStorePreparedQueryConfig & { execute: T[] }, PreparedQueryHKTBase>(\n\t\t\tthis.dialect.sqlToQuery(query),\n\t\t\t'objects',\n\t\t).execute();\n\t}\n\n\tasync count(sql: SQL): Promise<number> {\n\t\tconst res = await this.execute<[[{ count: string }]]>(sql);\n\n\t\treturn Number(\n\t\t\tres[0][0]['count'],\n\t\t);\n\t}\n\n\tabstract transaction<T>(\n\t\ttransaction: (\n\t\t\ttx: SingleStoreTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TSchema>,\n\t\t) => Promise<T>,\n\t\tconfig?: SingleStoreTransactionConfig,\n\t): Promise<T>;\n\n\tprotected getSetTransactionSQL(config: SingleStoreTransactionConfig): SQL | undefined {\n\t\tconst parts: string[] = [];\n\n\t\tif (config.isolationLevel) {\n\t\t\tparts.push(`isolation level ${config.isolationLevel}`);\n\t\t}\n\n\t\treturn parts.length ? sql`set transaction ${sql.raw(parts.join(' '))}` : undefined;\n\t}\n\n\tprotected getStartTransactionSQL(config: SingleStoreTransactionConfig): SQL | undefined {\n\t\tconst parts: string[] = [];\n\n\t\tif (config.withConsistentSnapshot) {\n\t\t\tparts.push('with consistent snapshot');\n\t\t}\n\n\t\tif (config.accessMode) {\n\t\t\tparts.push(config.accessMode);\n\t\t}\n\n\t\treturn parts.length ? sql`start transaction ${sql.raw(parts.join(', '))}` : undefined;\n\t}\n}\n\nexport abstract class SingleStoreTransaction<\n\tTQueryResult extends SingleStoreQueryResultHKT,\n\tTPreparedQueryHKT extends PreparedQueryHKTBase,\n\tTFullSchema extends Record<string, unknown> = Record<string, never>,\n\tTRelations extends AnyRelations = EmptyRelations,\n\tTSchema extends V1.TablesRelationalConfig = Record<string, never>,\n> extends SingleStoreDatabase<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TSchema> {\n\tstatic override readonly [entityKind]: string = 'SingleStoreTransaction';\n\n\tconstructor(\n\t\tdialect: SingleStoreDialect,\n\t\tsession: SingleStoreSession,\n\t\tprotected relations: TRelations,\n\t\tprotected schema: V1.RelationalSchemaConfig<TSchema> | undefined,\n\t\tprotected readonly nestedIndex: number,\n\t) {\n\t\tsuper(dialect, session, relations, schema);\n\t}\n\n\trollback(): never {\n\t\tthrow new TransactionRollbackError();\n\t}\n\n\t/** Nested transactions (aka savepoints) only work with InnoDB engine. */\n\tabstract override transaction<T>(\n\t\ttransaction: (\n\t\t\ttx: SingleStoreTransaction<TQueryResult, TPreparedQueryHKT, TFullSchema, TRelations, TSchema>,\n\t\t) => Promise<T>,\n\t): Promise<T>;\n}\n\nexport interface PreparedQueryHKTBase extends SingleStorePreparedQueryHKT {\n\ttype: SingleStoreBasePreparedQuery<Assume<this['config'], SingleStorePreparedQueryConfig>>;\n}\n"],"mappings":"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"}