diff --git a/src/kysely.ts b/src/kysely.ts index e4059eec4..036ffdc26 100644 --- a/src/kysely.ts +++ b/src/kysely.ts @@ -42,6 +42,9 @@ import { provideControlledConnection, } from './util/provide-controlled-connection.js' +// @ts-ignore +Symbol.asyncDispose ??= Symbol('Symbol.asyncDispose') + /** * The main Kysely class. * @@ -87,7 +90,7 @@ import { */ export class Kysely extends QueryCreator - implements QueryExecutorProvider + implements QueryExecutorProvider, AsyncDisposable { readonly #props: KyselyProps @@ -515,6 +518,10 @@ export class Kysely return this.getExecutor().executeQuery(compiledQuery, queryId) } + + async [Symbol.asyncDispose]() { + await this.destroy() + } } export class Transaction extends Kysely { diff --git a/test/node/src/async-dispose.test.ts b/test/node/src/async-dispose.test.ts new file mode 100644 index 000000000..72440ba46 --- /dev/null +++ b/test/node/src/async-dispose.test.ts @@ -0,0 +1,65 @@ +import { + CompiledQuery, + DatabaseConnection, + DummyDriver, + Kysely, + PostgresAdapter, + PostgresIntrospector, + PostgresQueryCompiler, + QueryResult, + RootOperationNode, + sql, +} from '../../..' +import { expect } from './test-setup' + +describe('async dispose', function () { + it('should call destroy ', async () => { + const steps: string[] = [] + + { + await using db = new Kysely({ + dialect: { + createAdapter: () => new PostgresAdapter(), + createDriver: () => + new (class extends DummyDriver { + async acquireConnection() { + return new (class implements DatabaseConnection { + async executeQuery(): Promise> { + steps.push('executed') + return { rows: [] } + } + streamQuery(): AsyncIterableIterator> { + throw new Error('Method not implemented.') + } + })() + } + async destroy(): Promise { + steps.push('destroyed') + } + })(), + createIntrospector: (db) => new PostgresIntrospector(db), + createQueryCompiler: () => + new (class extends PostgresQueryCompiler { + compileQuery(node: RootOperationNode): CompiledQuery { + const compiled = super.compileQuery(node) + steps.push('compiled') + return compiled + } + })(), + }, + }) + + await sql`select 1`.execute(db) + } + + steps.push('after runScope') + + expect(steps).to.length.to.be.greaterThan(1) + expect(steps).to.deep.equal([ + 'compiled', + 'executed', + 'destroyed', + 'after runScope', + ]) + }) +}) diff --git a/test/node/tsconfig.json b/test/node/tsconfig.json index 83e6196bb..1ed9e5376 100644 --- a/test/node/tsconfig.json +++ b/test/node/tsconfig.json @@ -2,6 +2,8 @@ "extends": "../../tsconfig-base.json", "include": ["src/**/*"], "compilerOptions": { + "target": "ES2022", + "lib": ["ESNext"], "module": "CommonJS", "outDir": "dist", "skipLibCheck": true