From ba5715980db70edca822c465f5aaa1f7e3e974ff Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Thu, 30 May 2024 14:00:04 +0300 Subject: [PATCH 01/13] Docs now reflect `tedious` support in `Bun` (#1018) --- site/docs/getting-started/shared.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/docs/getting-started/shared.tsx b/site/docs/getting-started/shared.tsx index ba24dcddd..3f458363d 100644 --- a/site/docs/getting-started/shared.tsx +++ b/site/docs/getting-started/shared.tsx @@ -12,7 +12,7 @@ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'deno' | 'bun' const PACKAGE_MANAGER_UNSUPPORTED_DIALECTS: Record = { - bun: ['sqlite', 'mssql'], + bun: ['sqlite'], deno: ['sqlite', 'mssql'], npm: [], pnpm: [], From 896dcd396cd8b0aa43e5de76a509a07001759c78 Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Sat, 1 Jun 2024 14:11:47 +0300 Subject: [PATCH 02/13] ci: bump bun, test mssql in bun. (#1022) --- .github/workflows/test.yml | 2 +- package-lock.json | 10 +++++----- package.json | 4 ++-- test/bun/bun.lockb | Bin 9840 -> 67954 bytes test/bun/bun.test.ts | 37 +++++++++++++++++++++++++++++++++++++ test/bun/package.json | 10 ++++++++-- 6 files changed, 53 insertions(+), 10 deletions(-) mode change 100644 => 100755 test/bun/bun.lockb diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e97a7b0b8..08aaa1981 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: node-version: [18.x, 20.x, 22.x] - bun-version: [1.0.23] + bun-version: [1.1.x] deno-version: [1.42.x] steps: diff --git a/package-lock.json b/package-lock.json index 311dc1a0e..0e41d5d9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "prettier": "^3.1.1", "sinon": "^17.0.1", "tarn": "^3.0.2", - "tedious": "^16.4.0", + "tedious": "^17.0.0", "tsd": "^0.30.3", "typescript": "^5.4.2" }, @@ -4831,9 +4831,9 @@ } }, "node_modules/tedious": { - "version": "16.7.1", - "resolved": "https://registry.npmjs.org/tedious/-/tedious-16.7.1.tgz", - "integrity": "sha512-NmedZS0NJiTv3CoYnf1FtjxIDUgVYzEmavrc8q2WHRb+lP4deI9BpQfmNnBZZaWusDbP5FVFZCcvzb3xOlNVlQ==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-17.0.0.tgz", + "integrity": "sha512-tXsl/kvDAFpnXU+ooEOQyrXdJFD0/OWvPq9i1bDhbOvoFGcrZURiXyUxbI8gJPsG6o2K5fs3HX6zRTSxuCUC5g==", "dev": true, "dependencies": { "@azure/identity": "^3.4.1", @@ -4849,7 +4849,7 @@ "sprintf-js": "^1.1.2" }, "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/tedious/node_modules/bl": { diff --git a/package.json b/package.json index a6ae37c86..a854a1977 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "test:node:run": "mocha --timeout 15000 test/node/dist/**/*.test.js", "test:browser:build": "rm -rf test/browser/bundle.js && esbuild test/browser/main.ts --bundle --outfile=test/browser/bundle.js", "test:browser": "npm run build && npm run test:browser:build && node test/browser/test.js", - "test:bun": "npm run build && cd test/bun && bun install && bun run test", + "test:bun": "npm run build && bun link && cd test/bun && bun install && bun run test", "test:cloudflare-workers": "npm run build && cd test/cloudflare-workers && npm ci && npm test", "test:deno": "npm run build && deno run --allow-env --allow-read --allow-net test/deno/local.test.ts && deno run --allow-env --allow-read --allow-net test/deno/cdn.test.ts", "test:typings": "tsd test/typings", @@ -94,7 +94,7 @@ "prettier": "^3.1.1", "sinon": "^17.0.1", "tarn": "^3.0.2", - "tedious": "^16.4.0", + "tedious": "^17.0.0", "tsd": "^0.30.3", "typescript": "^5.4.2" } diff --git a/test/bun/bun.lockb b/test/bun/bun.lockb old mode 100644 new mode 100755 index e716655b7eaafe04a5d8c73f60c2c337f269fb8f..19a9da9e20171f832dcaa282ba47cc33ef5787b2 GIT binary patch literal 67954 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 F{|`a~AcOz_ delta 2996 zcmc&$Yitx%6uvXvfzGzuC+%$8E$?Tg%XVp5uw*R-l-A{y0I7kHR9R}F-EP?}Pzv2* zkO%}*dW1FxK_j8Hic}(k5R9S_ARy8Q_6Jrl2tN!25qU&tJm>BmWQc!AOufnE%y+(X z?m6e)nS0Oe2GcE1y**@ZZ9I0i>E#W>A1rOY7CL{q_QLiP$BxF@F5Ymh?Ko+^a(M*f zV_;aYNFnhJkua zjH$?X3HdF`1jI*BdWfJGl4TV>o^u;wGvcOxj76i|jhGU&W6>0NiPu+IVZh};keWL-A9(pn>_e|W$3}Ay!UUx*XF^=Qt9FKKhMX!#ISG-Qd9=i zrK%Ex!c4ca1<8DvIWkv0hi};!NP=xvmnvcXgiJ7ZluOA$G!bTw%2k{3t&m%xUi}>r z7K>KfEG}i3Oml5b$W^@fHVrH>x#~ysh88l!$GDUmh$g_yxLkQy1ehIewKxJ5NJl`t z!=*MNniDp5xRmRN^7$lVa4qunNz~|~0l`A(Z zQ0R24zX&=K>4}lJ(hl@g;6kiR_Vj}@(QbK9KQLR|@>LY$-RdM!h9J$xUIB>e2~ONqHl{2l9&X23tXSbwTwNBr1=I2zb9mf zt4Klri%l3jDakQi=>JU;um5u-2@ewXPfJo83l7KUm6Ky1RLoO*T<{_ejg|jr6~nq0 zio$!@8{3PsO7MZtga42{PXnbQ?@1~G=2j5ZgVaGIrGVro>g_2Sc>M;i{_q*6-1!JiR20OoAZpiC4XRccye#kyr)EvlU_`(`#X@C(yn2!9GE(s{BuLb! z(=~WAXz)se3!GZ~q6Rrt1}X{GSCLoDOB(!Yq%_D{Nz_+JJ(^8tYS(~?+t<@FDjcH4B|%RAM#qmMR>j!Vh@JY`?%ngIvCw;z94UN$c| z?av9$ErVJ%?yPxb^`-T*J0EP=6P((7t>#{WZFJ#Y+q$3RJL!2ei5Tj+cldEhpA0L} zwP6{mKf8bT)5<>7iC;@3)rWyaL=nI51Bc_+hyLH?r_1M`@hq#*COVXED>Uq#HIxox z`o2=cY&wnHMK9 zg(hqflMPSB$%cmLf5AqA$BjdYZ4z}j{Cp-ix{W9hUd^l(2L;52g9o5MbeZVEDR&By ziVsz$;ggIHoxya2Q3^@;PzF>$Q7X@wvD$Q~ZOcg2n-_~`@YSm0ml9=ZvBU1nu{#*t zZOfJ?<9XU{wH2Tz-X3*DV>50XE&n4ROIdaY+A!?8;MI1gyo|w)c8^VO@>;)mID5bQ zxkn~xah4rT8G8fIwswzPE`g`RYSVkVf*)+^qMD1fvQ#T3+$2F=hgIGo!MhzxZF&6f7qEK-gWtNc!Fez3V6U{%WG;QJ!nZOLJ7Djj4T`i+ kf*IXSjamJrPvAs%n%I({ + dialect: new MssqlDialect({ + tarn: { + ...Tarn, + options: { + min: 0, + max: 10, + }, + }, + tedious: { + ...Tedious, + connectionFactory: () => + new Tedious.Connection({ + authentication: { + options: { + password: 'KyselyTest0', + userName: 'sa', + }, + type: 'default', + }, + options: { + connectTimeout: 3000, + database: 'kysely_test', + encrypt: false, + port: 21433, + trustServerCertificate: true, + }, + server: 'localhost', + }), + }, + }), + }), ] if ( @@ -60,3 +95,5 @@ await Promise.all(dbs.map((db) => query.execute(db))) console.log('bun test passed') await Promise.all(dbs.map((db) => db.destroy())) + +process.exit(0) // hangs otherwise... diff --git a/test/bun/package.json b/test/bun/package.json index 08285b44f..05823019f 100644 --- a/test/bun/package.json +++ b/test/bun/package.json @@ -5,8 +5,14 @@ "test": "bun bun.test.ts" }, "dependencies": { - "kysely": "^0.25.0", + "kysely": "link:kysely", "mysql2": "^3.3.3", - "pg": "^8.11.0" + "pg": "^8.11.0", + "tarn": "^3.0.2", + "tedious": "^17.0.0" + }, + "devDependencies": { + "@types/bun": "^1.1.3", + "typescript": "^5.4.5" } } From 347f0ca1c6a59ecc07afa9283131a4b5d3792ca3 Mon Sep 17 00:00:00 2001 From: Dima Semyushkin Date: Wed, 5 Jun 2024 14:30:13 +0200 Subject: [PATCH 03/13] Fix typo (#1025) --- site/src/components/SectionFeatures/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/components/SectionFeatures/index.tsx b/site/src/components/SectionFeatures/index.tsx index c2c95f2ba..af7f97cfd 100644 --- a/site/src/components/SectionFeatures/index.tsx +++ b/site/src/components/SectionFeatures/index.tsx @@ -46,7 +46,7 @@ const FeatureList: FeatureItem[] = [ description: ( <> PostgreSQL, MySQL, or SQLite? We've got you covered. There's also a - growing ecosystem of third-party dialects, including PlanetScale, D3, + growing ecosystem of third-party dialects, including PlanetScale, D1, SurrealDB, and more. Learn more. ), From 42ac7c9c6982064a73540915bcce47033a46baea Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Mon, 10 Jun 2024 08:51:46 +0300 Subject: [PATCH 04/13] move `preventAwait` to `alter-column-builder`.ts. (#1031) --- src/schema/alter-column-builder.ts | 5 +++++ src/schema/alter-table-builder.ts | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/schema/alter-column-builder.ts b/src/schema/alter-column-builder.ts index caa41b04d..61cf708cd 100644 --- a/src/schema/alter-column-builder.ts +++ b/src/schema/alter-column-builder.ts @@ -8,6 +8,7 @@ import { DefaultValueExpression, parseDefaultValueExpression, } from '../parser/default-value-parser.js' +import { preventAwait } from '../util/prevent-await.js' export class AlterColumnBuilder { readonly #column: string @@ -63,6 +64,8 @@ export class AlterColumnBuilder { } } +preventAwait(AlterColumnBuilder, "don't await AlterColumnBuilder instances") + /** * Allows us to force consumers to do exactly one alteration to a column. * @@ -93,3 +96,5 @@ export class AlteredColumnBuilder implements OperationNodeSource { export type AlterColumnBuilderCallback = ( builder: AlterColumnBuilder, ) => AlteredColumnBuilder + +preventAwait(AlteredColumnBuilder, "don't await AlteredColumnBuilder instances") diff --git a/src/schema/alter-table-builder.ts b/src/schema/alter-table-builder.ts index c55901b8d..b7bee0308 100644 --- a/src/schema/alter-table-builder.ts +++ b/src/schema/alter-table-builder.ts @@ -323,6 +323,8 @@ export interface AlterTableBuilderProps { readonly node: AlterTableNode } +preventAwait(AlterTableBuilder, "don't await AlterTableBuilder instances") + export interface ColumnAlteringInterface { alterColumn( column: string, @@ -469,9 +471,6 @@ export class AlterTableColumnAlteringBuilder export interface AlterTableColumnAlteringBuilderProps extends AlterTableBuilderProps {} -preventAwait(AlterTableBuilder, "don't await AlterTableBuilder instances") -preventAwait(AlterColumnBuilder, "don't await AlterColumnBuilder instances") - preventAwait( AlterTableColumnAlteringBuilder, "don't await AlterTableColumnAlteringBuilder instances directly. To execute the query you need to call `execute`", From 9519ffd2b6ebb6a3e6ed95724f8c171fc4bec6cc Mon Sep 17 00:00:00 2001 From: Evan Boehs Date: Tue, 11 Jun 2024 03:24:23 -0400 Subject: [PATCH 05/13] feat: add the starts-with postgres comparison operator (#1029) https://www.postgresql.org/docs/current/spgist-builtin-opclasses.html#SPGIST-BUILTIN-OPCLASSES-TABLE --- src/operation-node/operator-node.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/operation-node/operator-node.ts b/src/operation-node/operator-node.ts index d7f81ecd2..8a6f68da5 100644 --- a/src/operation-node/operator-node.ts +++ b/src/operation-node/operator-node.ts @@ -21,6 +21,7 @@ export const COMPARISON_OPERATORS = [ 'not ilike', '@>', '<@', + '^@', '&&', '?', '?&', From 873671b758fd70679f440057595399d73813c0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Koskim=C3=A4ki?= Date: Thu, 13 Jun 2024 15:34:14 +0300 Subject: [PATCH 06/13] fixes #1039 --- src/query-creator.ts | 4 ++-- test/typings/test-d/select-from.test-d.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/query-creator.ts b/src/query-creator.ts index dfdca0cb1..d3c2caf6a 100644 --- a/src/query-creator.ts +++ b/src/query-creator.ts @@ -171,7 +171,7 @@ export class QueryCreator { from: TE[], ): SelectQueryBuilder, {}> - selectFrom>( + selectFrom>( from: TE[], ): SelectQueryBuilder, FromTables, {}> @@ -187,7 +187,7 @@ export class QueryCreator { {} > - selectFrom>( + selectFrom>( from: TE, ): SelectQueryBuilder, FromTables, {}> diff --git a/test/typings/test-d/select-from.test-d.ts b/test/typings/test-d/select-from.test-d.ts index 6750257ba..cd799e067 100644 --- a/test/typings/test-d/select-from.test-d.ts +++ b/test/typings/test-d/select-from.test-d.ts @@ -37,6 +37,16 @@ async function testFromSingle(db: Kysely) { .execute() expectType<{ strs: number }>(r4) + // Subquery factory list + const [r4_2] = await db + .selectFrom([ + (eb) => eb.selectFrom('movie').select('movie.stars as strs').as('m'), + (eb) => eb.selectFrom('pet').select('id').as('p'), + ]) + .selectAll(['m', 'p']) + .execute() + expectType<{ strs: number; id: string }>(r4_2) + // Table with schema const [r5] = await db .selectFrom('some_schema.movie') From a65a7f3856f3a413e1fd802941233e66e1439bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Koskim=C3=A4ki?= Date: Sat, 15 Jun 2024 07:38:04 +0300 Subject: [PATCH 07/13] fixes #1028 --- src/query-compiler/default-query-compiler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/query-compiler/default-query-compiler.ts b/src/query-compiler/default-query-compiler.ts index 321f41bb0..f9697079f 100644 --- a/src/query-compiler/default-query-compiler.ts +++ b/src/query-compiler/default-query-compiler.ts @@ -126,6 +126,7 @@ export class DefaultQueryCompiler compileQuery(node: RootOperationNode): CompiledQuery { this.#sql = '' this.#parameters = [] + this.nodeStack.splice(0, this.nodeStack.length) this.visitNode(node) From d45a8faf1fdb474526ff5091251242b57bb09ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Koskim=C3=A4ki?= Date: Sat, 15 Jun 2024 09:07:31 +0300 Subject: [PATCH 08/13] fixes #1036 --- src/util/object-utils.ts | 31 +++++++++++++++++----- test/node/src/camel-case.test.ts | 44 +++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/util/object-utils.ts b/src/util/object-utils.ts index 845f9ee87..4f7842cac 100644 --- a/src/util/object-utils.ts +++ b/src/util/object-utils.ts @@ -59,13 +59,20 @@ export function isArrayBufferOrView( } export function isPlainObject(obj: unknown): obj is Record { - return ( - isObject(obj) && - !Array.isArray(obj) && - !isDate(obj) && - !isBuffer(obj) && - !isArrayBufferOrView(obj) - ) + if (!isObject(obj) || getTag(obj) !== '[object Object]') { + return false + } + + if (Object.getPrototypeOf(obj) === null) { + return true + } + + let proto = obj + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto) + } + + return Object.getPrototypeOf(obj) === proto } export function getLast(arr: ArrayLike): T | undefined { @@ -169,3 +176,13 @@ function compareGenericObjects( return true } + +const toString = Object.prototype.toString + +function getTag(value: unknown): string { + if (value == null) { + return value === undefined ? '[object Undefined]' : '[object Null]' + } + + return toString.call(value) +} diff --git a/test/node/src/camel-case.test.ts b/test/node/src/camel-case.test.ts index 5ba4aeceb..923ce43fa 100644 --- a/test/node/src/camel-case.test.ts +++ b/test/node/src/camel-case.test.ts @@ -1,4 +1,11 @@ -import { CamelCasePlugin, Generated, Kysely, RawBuilder, sql } from '../../../' +import { + CamelCasePlugin, + Generated, + Kysely, + ParseJSONResultsPlugin, + RawBuilder, + sql, +} from '../../../' import { destroyTest, @@ -78,7 +85,7 @@ for (const dialect of DIALECTS) { // Can't run this test on SQLite because we can't access the same database // from the other Kysely instance. - if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') { + if (dialect !== 'sqlite') { it('should have created the table and its columns in snake_case', async () => { const result = await sql`select * from camel_person`.execute( ctx.db, @@ -262,18 +269,41 @@ for (const dialect of DIALECTS) { }) }) - it('should respect maintainNestedObjectKeys', async () => { - const data = await camelDb - .withoutPlugins() - .withPlugin(new CamelCasePlugin({ maintainNestedObjectKeys: true })) + it('should map nested objects by default', async () => { + let db = camelDb.withoutPlugins() + + if (dialect === 'mssql' || dialect === 'sqlite') { + db = db.withPlugin(new ParseJSONResultsPlugin()) + } + + db = db.withPlugin(new CamelCasePlugin()) + + const data = await db .selectFrom('camelPerson') .selectAll() .executeTakeFirstOrThrow() + expect(data.preferences).to.eql({ + disableEmails: true, + }) + }) + + it('should respect maintainNestedObjectKeys', async () => { + let db = camelDb.withoutPlugins() + if (dialect === 'mssql' || dialect === 'sqlite') { - data.preferences = JSON.parse(data.preferences.toString()) + db = db.withPlugin(new ParseJSONResultsPlugin()) } + db = db.withPlugin( + new CamelCasePlugin({ maintainNestedObjectKeys: true }), + ) + + const data = await db + .selectFrom('camelPerson') + .selectAll() + .executeTakeFirstOrThrow() + expect(data.preferences).to.eql({ disable_emails: true, }) From de7e560ad3ed61ff7bcd018b5393236417afc574 Mon Sep 17 00:00:00 2001 From: Heiko Osigus Date: Sat, 15 Jun 2024 11:48:39 +0200 Subject: [PATCH 09/13] postgres introspection getTables handle partition tables as well. (#1034) --- src/dialect/postgres/postgres-introspector.ts | 2 +- test/node/src/introspect.test.ts | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/dialect/postgres/postgres-introspector.ts b/src/dialect/postgres/postgres-introspector.ts index 6a359057f..956cf7ab2 100644 --- a/src/dialect/postgres/postgres-introspector.ts +++ b/src/dialect/postgres/postgres-introspector.ts @@ -73,7 +73,7 @@ export class PostgresIntrospector implements DatabaseIntrospector { ]) // r == normal table .where((eb) => - eb.or([eb('c.relkind', '=', 'r'), eb('c.relkind', '=', 'v')]), + eb.or([eb('c.relkind', '=', 'r'), eb('c.relkind', '=', 'v'), eb('c.relkind', '=', 'p')]), ) .where('ns.nspname', '!~', '^pg_') .where('ns.nspname', '!=', 'information_schema') diff --git a/test/node/src/introspect.test.ts b/test/node/src/introspect.test.ts index 86e1a6cac..1aaa58350 100644 --- a/test/node/src/introspect.test.ts +++ b/test/node/src/introspect.test.ts @@ -280,6 +280,22 @@ for (const dialect of DIALECTS) { }, ], }, + { + name: 'pet_partition', + isView: false, + schema: 'some_schema', + columns: [ + { + name: 'part_column', + dataType: 'text', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ] + } ]) } else if (dialect === 'mysql') { expect(meta).to.eql([ @@ -827,6 +843,11 @@ for (const dialect of DIALECTS) { .addColumn('some_column', 'serial', (col) => col.primaryKey()) .addColumn('spcies', sql`dtype_schema.species`) .execute() + await ctx.db.schema + .createTable('some_schema.pet_partition') + .addColumn('part_column', 'text') + .modifyEnd(sql`PARTITION by LIST ("part_column")`) + .execute() } else { await ctx.db.schema .createTable('some_schema.pet') @@ -842,6 +863,7 @@ for (const dialect of DIALECTS) { async function dropSchema() { await ctx.db.schema.dropTable('some_schema.pet').ifExists().execute() + await ctx.db.schema.dropTable('some_schema.pet_partition').ifExists().execute() await ctx.db.schema.dropSchema('some_schema').ifExists().execute() if (dialect === 'postgres') { From f63327e19b32bf67367d74c798808e8e8c5b0cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Koskim=C3=A4ki?= Date: Sun, 16 Jun 2024 08:58:55 +0300 Subject: [PATCH 10/13] closes #1021 --- src/query-builder/update-query-builder.ts | 98 ++++++++++--------- test/node/src/delete.test.ts | 29 ++++++ test/node/src/object-util.test.ts | 30 ++++++ test/node/src/update.test.ts | 28 ++++++ .../test-d/delete-query-builder.test-d.ts | 9 ++ test/typings/test-d/infer-result.test-d.ts | 20 +++- test/typings/test-d/update.test-d.ts | 16 +++ 7 files changed, 183 insertions(+), 47 deletions(-) create mode 100644 test/node/src/object-util.test.ts diff --git a/src/query-builder/update-query-builder.ts b/src/query-builder/update-query-builder.ts index f8422bfba..cbe670461 100644 --- a/src/query-builder/update-query-builder.ts +++ b/src/query-builder/update-query-builder.ts @@ -682,18 +682,28 @@ export class UpdateQueryBuilder }) } - returningAll(): UpdateQueryBuilder> { + returningAll( + tables: ReadonlyArray, + ): UpdateQueryBuilder> + + returningAll( + table: T, + ): UpdateQueryBuilder> + + returningAll(): UpdateQueryBuilder> + + returningAll(table?: any): any { return new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectAll(), + parseSelectAll(table), ), }) } output>( - selections: readonly OE[] + selections: readonly OE[], ): UpdateQueryBuilder< DB, UT, @@ -702,7 +712,7 @@ export class UpdateQueryBuilder > output>( - callback: CB + callback: CB, ): UpdateQueryBuilder< DB, UT, @@ -711,7 +721,7 @@ export class UpdateQueryBuilder > output>( - selection: OE + selection: OE, ): UpdateQueryBuilder< DB, UT, @@ -724,19 +734,19 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithOutput( this.#props.queryNode, - parseSelectArg(args) + parseSelectArg(args), ), }) } outputAll( - table: OutputPrefix + table: OutputPrefix, ): UpdateQueryBuilder> { return new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithOutput( this.#props.queryNode, - parseSelectAll(table) + parseSelectAll(table), ), }) } @@ -836,8 +846,8 @@ export class UpdateQueryBuilder ): O2 extends UpdateResult ? UpdateQueryBuilder : O2 extends O & infer E - ? UpdateQueryBuilder> - : UpdateQueryBuilder> { + ? UpdateQueryBuilder> + : UpdateQueryBuilder> { if (condition) { return func(this) as any } @@ -1099,12 +1109,12 @@ export type UpdateQueryBuilderWithInnerJoin< ? InnerJoinedBuilder : never : TE extends keyof DB - ? UpdateQueryBuilder - : TE extends AliasedExpression - ? InnerJoinedBuilder - : TE extends (qb: any) => AliasedExpression - ? InnerJoinedBuilder - : never + ? UpdateQueryBuilder + : TE extends AliasedExpression + ? InnerJoinedBuilder + : TE extends (qb: any) => AliasedExpression + ? InnerJoinedBuilder + : never type InnerJoinedBuilder< DB, @@ -1133,12 +1143,12 @@ export type UpdateQueryBuilderWithLeftJoin< ? LeftJoinedBuilder : never : TE extends keyof DB - ? LeftJoinedBuilder - : TE extends AliasedExpression - ? LeftJoinedBuilder - : TE extends (qb: any) => AliasedExpression - ? LeftJoinedBuilder - : never + ? LeftJoinedBuilder + : TE extends AliasedExpression + ? LeftJoinedBuilder + : TE extends (qb: any) => AliasedExpression + ? LeftJoinedBuilder + : never type LeftJoinedBuilder< DB, @@ -1156,8 +1166,8 @@ type LeftJoinedDB = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? Nullable : C extends keyof DB - ? DB[C] - : never + ? DB[C] + : never }> export type UpdateQueryBuilderWithRightJoin< @@ -1171,12 +1181,12 @@ export type UpdateQueryBuilderWithRightJoin< ? RightJoinedBuilder : never : TE extends keyof DB - ? RightJoinedBuilder - : TE extends AliasedExpression - ? RightJoinedBuilder - : TE extends (qb: any) => AliasedExpression - ? RightJoinedBuilder - : never + ? RightJoinedBuilder + : TE extends AliasedExpression + ? RightJoinedBuilder + : TE extends (qb: any) => AliasedExpression + ? RightJoinedBuilder + : never type RightJoinedBuilder< DB, @@ -1196,10 +1206,10 @@ type RightJoinedDB< [C in keyof DB | A]: C extends A ? R : C extends TB - ? Nullable - : C extends keyof DB - ? DB[C] - : never + ? Nullable + : C extends keyof DB + ? DB[C] + : never }> export type UpdateQueryBuilderWithFullJoin< @@ -1213,12 +1223,12 @@ export type UpdateQueryBuilderWithFullJoin< ? OuterJoinedBuilder : never : TE extends keyof DB - ? OuterJoinedBuilder - : TE extends AliasedExpression - ? OuterJoinedBuilder - : TE extends (qb: any) => AliasedExpression - ? OuterJoinedBuilder - : never + ? OuterJoinedBuilder + : TE extends AliasedExpression + ? OuterJoinedBuilder + : TE extends (qb: any) => AliasedExpression + ? OuterJoinedBuilder + : never type OuterJoinedBuilder< DB, @@ -1238,8 +1248,8 @@ type OuterJoinedBuilderDB< [C in keyof DB | A]: C extends A ? Nullable : C extends TB - ? Nullable - : C extends keyof DB - ? DB[C] - : never + ? Nullable + : C extends keyof DB + ? DB[C] + : never }> diff --git a/test/node/src/delete.test.ts b/test/node/src/delete.test.ts index efa0c61d4..b7024f73f 100644 --- a/test/node/src/delete.test.ts +++ b/test/node/src/delete.test.ts @@ -299,6 +299,35 @@ for (const dialect of DIALECTS) { await query.execute() }) + it('should delete from t1 using t2, t3 returning t2.*', async () => { + const query = ctx.db + .deleteFrom('toy') + .using(['pet', 'person']) + .whereRef('toy.pet_id', '=', 'pet.id') + .whereRef('pet.owner_id', '=', 'person.id') + .where('person.first_name', '=', 'Bob') + .returningAll('pet') + + testSql(query, dialect, { + postgres: { + sql: [ + 'delete from "toy"', + 'using "pet", "person"', + 'where "toy"."pet_id" = "pet"."id"', + 'and "pet"."owner_id" = "person"."id"', + 'and "person"."first_name" = $1', + 'returning "pet".*', + ], + parameters: ['Bob'], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + it('should delete from t1 returning *', async () => { const query = ctx.db .deleteFrom('pet') diff --git a/test/node/src/object-util.test.ts b/test/node/src/object-util.test.ts new file mode 100644 index 000000000..fd70c1bdc --- /dev/null +++ b/test/node/src/object-util.test.ts @@ -0,0 +1,30 @@ +import { isPlainObject } from '../../../dist/cjs/util/object-utils' + +import { expect } from './test-setup.js' + +describe('object util', () => { + it('isPlainObject', async () => { + class SomeClass {} + + for (const obj of [{ foo: 'bar' }, Object.create(null)]) { + expect(isPlainObject(obj)).to.equal(true) + } + + for (const obj of [ + [], + new Date(), + Buffer.allocUnsafe(10), + new ArrayBuffer(10), + new Int32Array(10), + new Float64Array(10), + '', + 42, + false, + null, + undefined, + new SomeClass(), + ]) { + expect(isPlainObject(obj)).to.equal(false) + } + }) +}) diff --git a/test/node/src/update.test.ts b/test/node/src/update.test.ts index 7a5b69c18..5e4639cd2 100644 --- a/test/node/src/update.test.ts +++ b/test/node/src/update.test.ts @@ -478,6 +478,34 @@ for (const dialect of DIALECTS) { }) } + if (dialect === 'postgres') { + it('should update some rows and return joined rows when `returningAll` is used', async () => { + const query = ctx.db + .updateTable('person') + .from('pet') + .set({ + first_name: (eb) => eb.ref('pet.name'), + }) + .whereRef('pet.owner_id', '=', 'person.id') + .where('person.first_name', '=', 'Arnold') + .returningAll('pet') + + testSql(query, dialect, { + postgres: { + sql: 'update "person" set "first_name" = "pet"."name" from "pet" where "pet"."owner_id" = "person"."id" and "person"."first_name" = $1 returning "pet".*', + parameters: ['Arnold'], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result[0].name).to.equal('Doggo') + expect(result[0].species).to.equal('dog') + }) + } + if (dialect === 'postgres') { it('should update multiple rows and stream returned results', async () => { const stream = ctx.db diff --git a/test/typings/test-d/delete-query-builder.test-d.ts b/test/typings/test-d/delete-query-builder.test-d.ts index f827d0a3b..fbf9a0590 100644 --- a/test/typings/test-d/delete-query-builder.test-d.ts +++ b/test/typings/test-d/delete-query-builder.test-d.ts @@ -52,6 +52,15 @@ async function testDelete(db: Kysely) { .executeTakeFirstOrThrow() expectType(r7) + const r8 = await db + .deleteFrom('pet') + .using('person') + .leftJoin('pet', 'pet.owner_id', 'person.id') + .where('person.id', '=', 1) + .returningAll('person') + .executeTakeFirstOrThrow() + expectType>(r8) + expectError(db.deleteFrom('NO_SUCH_TABLE')) expectError(db.deleteFrom('pet').where('NO_SUCH_COLUMN', '=', '1')) expectError(db.deleteFrom('pet').whereRef('owner_id', '=', 'NO_SUCH_COLUMN')) diff --git a/test/typings/test-d/infer-result.test-d.ts b/test/typings/test-d/infer-result.test-d.ts index e48cbac61..088a191b9 100644 --- a/test/typings/test-d/infer-result.test-d.ts +++ b/test/typings/test-d/infer-result.test-d.ts @@ -80,9 +80,23 @@ function testInferResultUpdateQuery(db: Kysely) { const query1 = query0.returningAll() const compiledQuery1 = query1.compile() - type Expected1 = Selectable[] - expectType>>(true) - expectType>>(true) + type Expected1 = { + id: string | number + first_name: string + last_name: string | null + age: number + gender: 'male' | 'female' | 'other' + marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + modified_at: Date + deleted_at: Date | null + name: string + owner_id: number + species: 'dog' | 'cat' + }[] + + const expected1: Expected1 = undefined! + expectType>(expected1) + expectType>(expected1) const query2 = query0.returning('modified_at') const compiledQuery2 = query2.compile() diff --git a/test/typings/test-d/update.test-d.ts b/test/typings/test-d/update.test-d.ts index e4b1ba883..3721de1eb 100644 --- a/test/typings/test-d/update.test-d.ts +++ b/test/typings/test-d/update.test-d.ts @@ -31,6 +31,22 @@ async function testUpdate(db: Kysely) { .executeTakeFirst() expectType(r4) + const r5 = await db + .updateTable('pet') + .from((eb) => + eb + .selectFrom('person') + .select(['person.id as person_id', 'first_name as fn']) + .where('person.first_name', '=', 'Jennifer') + .forUpdate() + .skipLocked() + .as('p'), + ) + .set('name', (eb) => eb.ref('p.fn')) + .returningAll('p') + .execute() + expectType<{ fn: string; person_id: number }[]>(r5) + // Non-existent column expectError( db From 8ae5cf4242500524809fd8b534ee8cd055f95ec3 Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Mon, 17 Jun 2024 10:23:47 +0300 Subject: [PATCH 11/13] fix `MssqlDialect` streaming not handling backpressure. (#1041) --- package-lock.json | 1004 +-------------------- package.json | 2 +- src/dialect/mssql/mssql-dialect-config.ts | 137 ++- src/dialect/mssql/mssql-driver.ts | 160 +++- test/node/src/stream.test.ts | 71 ++ test/node/src/test-setup.ts | 5 +- 6 files changed, 285 insertions(+), 1094 deletions(-) create mode 100644 test/node/src/stream.test.ts diff --git a/package-lock.json b/package-lock.json index 0e41d5d9f..129bcb747 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "prettier": "^3.1.1", "sinon": "^17.0.1", "tarn": "^3.0.2", - "tedious": "^17.0.0", + "tedious": "^18.2.0", "tsd": "^0.30.3", "typescript": "^5.4.2" }, @@ -1225,22 +1225,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -1250,28 +1234,6 @@ "node": ">=8" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1290,21 +1252,6 @@ "node": "*" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1437,25 +1384,6 @@ "node": ">=4" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1716,23 +1644,6 @@ "node": ">=4.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1742,23 +1653,6 @@ "node": ">=8" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -1840,135 +1734,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.1", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.0", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-aggregate-error": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.12.tgz", - "integrity": "sha512-j0PupcmELoVbYS2NNrsn5zcLLEsryQwP02x8fRawh7c2eEaPHwJFAxltZsqV7HJjsF57+SMpYyVRWgbVLfOagg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.1.0", - "function-bind": "^1.1.2", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.1", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/esbuild": { "version": "0.19.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", @@ -2151,15 +1916,6 @@ "flat": "cli.js" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2195,33 +1951,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -2249,42 +1978,6 @@ "node": "*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -2322,21 +2015,6 @@ "node": ">= 6" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2357,18 +2035,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -2378,15 +2044,6 @@ "node": ">=6" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2396,57 +2053,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", @@ -2591,20 +2197,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/irregular-plurals": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", @@ -2614,40 +2206,12 @@ "node": ">=8" } }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2660,34 +2224,6 @@ "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -2700,21 +2236,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -2734,159 +2255,56 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.12.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dev": true + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2899,18 +2317,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2923,12 +2329,6 @@ "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -2977,12 +2377,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", - "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==", - "dev": true - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -3435,12 +2829,6 @@ "node": ">=10" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true - }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -3465,42 +2853,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -3872,15 +3224,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/postgres-array": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", @@ -4248,24 +3591,6 @@ "node": ">=8" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4325,24 +3650,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-array-concat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", - "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "get-intrinsic": "^1.2.2", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4363,23 +3670,6 @@ } ] }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -4428,56 +3718,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -4660,51 +3900,6 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4831,22 +4026,20 @@ } }, "node_modules/tedious": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/tedious/-/tedious-17.0.0.tgz", - "integrity": "sha512-tXsl/kvDAFpnXU+ooEOQyrXdJFD0/OWvPq9i1bDhbOvoFGcrZURiXyUxbI8gJPsG6o2K5fs3HX6zRTSxuCUC5g==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-18.2.0.tgz", + "integrity": "sha512-PCELoE17gN71lk0A87+WITcIJ6uGagrV2hXVJT5ige/Yef+YCLVpQ/Je12rOZT7vBhVZoMp6MvaBmbfI8fw0ag==", "dev": true, "dependencies": { "@azure/identity": "^3.4.1", "@azure/keyvault-keys": "^4.4.0", - "@js-joda/core": "^5.5.3", - "bl": "^6.0.3", - "es-aggregate-error": "^1.0.9", + "@js-joda/core": "^5.6.1", + "@types/node": ">=18", + "bl": "^6.0.11", "iconv-lite": "^0.6.3", "js-md4": "^0.3.2", - "jsbi": "^4.3.0", "native-duplexpair": "^1.0.0", - "node-abort-controller": "^3.1.1", - "sprintf-js": "^1.1.2" + "sprintf-js": "^1.1.3" }, "engines": { "node": ">=18" @@ -4985,79 +4178,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", - "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typescript": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", @@ -5071,21 +4191,6 @@ "node": ">=14.17" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -5117,41 +4222,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", diff --git a/package.json b/package.json index a854a1977..debeb7c3f 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "prettier": "^3.1.1", "sinon": "^17.0.1", "tarn": "^3.0.2", - "tedious": "^17.0.0", + "tedious": "^18.2.0", "tsd": "^0.30.3", "typescript": "^5.4.2" } diff --git a/src/dialect/mssql/mssql-dialect-config.ts b/src/dialect/mssql/mssql-dialect-config.ts index f82abe9f5..e84528f04 100644 --- a/src/dialect/mssql/mssql-dialect-config.ts +++ b/src/dialect/mssql/mssql-dialect-config.ts @@ -52,98 +52,81 @@ export interface MssqlDialectConfig { export interface Tedious { connectionFactory: () => TediousConnection | Promise ISOLATION_LEVEL: TediousIsolationLevel - Request: typeof TediousRequest + Request: TediousRequestClass TYPES: TediousTypes } -export type TediousIsolationLevel = Record< - | 'NO_CHANGE' - | 'READ_UNCOMMITTED' - | 'READ_COMMITTED' - | 'REPEATABLE_READ' - | 'SERIALIZABLE' - | 'SNAPSHOT', - number -> - -export type TediousTypes = Record< - | 'BigInt' - | 'Binary' - | 'Bit' - | 'Char' - | 'Date' - | 'DateTime' - | 'DateTime2' - | 'DateTimeOffset' - | 'Decimal' - | 'Float' - | 'Image' - | 'Int' - | 'Money' - | 'NChar' - | 'NText' - | 'Null' - | 'Numeric' - | 'NVarChar' - | 'Real' - | 'SmallDateTime' - | 'SmallInt' - | 'SmallMoney' - | 'Text' - | 'Time' - | 'TinyInt' - | 'TVP' - | 'UDT' - | 'UniqueIdentifier' - | 'VarBinary' - | 'VarChar' - // TODO: uncomment once it is introduced in @types/tedious. See https://github.com/DefinitelyTyped/DefinitelyTyped/pull/66369 - // | 'Variant' - | 'Xml', - { name: string; type: string } -> - -export interface TediousType { - name: string - type: string -} - export interface TediousConnection { beginTransaction( - callback: (error?: Error) => void, - transactionId?: string | undefined, - isolationLevel?: number | undefined, + callback: (error?: Error | null, transactionDescriptor?: any) => void, + name?: string, + isolationLevel?: number, + ): void + commitTransaction( + callback: (error?: Error | null) => void, + name?: string, ): void - cancel(): void - close(): void - commitTransaction(callback: (error?: Error) => void): void - connect(callback: (error?: Error) => void): void execSql(request: TediousRequest): void - reset(callback: (error?: Error) => void): void - rollbackTransaction(callback: (error?: Error) => void): void - once(event: 'end', listener: () => void): void + rollbackTransaction( + callback: (error?: Error | null) => void, + name?: string, + ): void + saveTransaction(callback: (error?: Error | null) => void, name: string): void + cancel(): boolean + reset(callback: (error?: Error | null) => void): void + close(): void + once(event: 'end', listener: () => void): this + once(event: string, listener: (...args: any[]) => void): this + connect(callback?: (error?: Error) => void): void +} + +export type TediousIsolationLevel = Record + +export interface TediousRequestClass { + new ( + sqlTextOrProcedure: string | undefined, + callback: (error?: Error | null, rowCount?: number, rows?: any) => void, + options?: { + statementColumnEncryptionSetting?: any + }, + ): TediousRequest } export declare class TediousRequest { - constructor( - sql: string, - callback: (error: Error, rowCount: number, rows: any[]) => void, - ) addParameter( name: string, - type: TediousType, - value: any, - options?: { - length?: number | 'max' | undefined - precision?: number | undefined - scale?: number | undefined - }, + dataType: TediousDataType, + value?: unknown, + options?: Readonly<{ + output?: boolean + length?: number + precision?: number + scale?: number + }> | null, ): void - off(event: 'row', listener: (...args: any[]) => void): void - on(event: 'row', listener: (columns: TediousColumnValue[]) => void): void - once(event: 'requestCompleted', listener: (...args: any[]) => void): void + on(event: 'row', listener: (columns: any) => void): this + on(event: string, listener: (...args: any[]) => void): this + once(event: 'requestCompleted', listener: () => void): this + once(event: string, listener: (...args: any[]) => void): this + off(event: 'row', listener: (columns: any) => void): this + off(event: string, listener: (...args: any[]) => void): this + pause(): void + resume(): void +} + +export interface TediousTypes { + NVarChar: TediousDataType + BigInt: TediousDataType + Int: TediousDataType + Float: TediousDataType + Bit: TediousDataType + DateTime: TediousDataType + VarBinary: TediousDataType + [x: string]: TediousDataType } +export interface TediousDataType {} + export interface TediousColumnValue { metadata: { colName: string diff --git a/src/dialect/mssql/mssql-driver.ts b/src/dialect/mssql/mssql-driver.ts index 5d9b9cb12..ec749f685 100644 --- a/src/dialect/mssql/mssql-driver.ts +++ b/src/dialect/mssql/mssql-driver.ts @@ -136,11 +136,11 @@ class MssqlConnection implements DatabaseConnection { try { const deferred = new Deferred>() - const request = new MssqlRequest( - this.#tedious, + const request = new MssqlRequest({ compiledQuery, - deferred, - ) + tedious: this.#tedious, + onDone: deferred, + }) this.#connection.execSql(request.request) @@ -172,13 +172,17 @@ class MssqlConnection implements DatabaseConnection { throw new Error('chunkSize must be a positive integer') } - const request = new MssqlRequest(this.#tedious, compiledQuery) + const request = new MssqlRequest({ + compiledQuery, + streamChunkSize: chunkSize, + tedious: this.#tedious, + }) this.#connection.execSql(request.request) try { while (true) { - const rows = await request.readChunk(chunkSize) + const rows = await request.readChunk() if (rows.length === 0) { break @@ -191,7 +195,7 @@ class MssqlConnection implements DatabaseConnection { } } } finally { - this.#connection.cancel() + await this.#cancelRequest(request) } } @@ -199,11 +203,11 @@ class MssqlConnection implements DatabaseConnection { try { const deferred = new Deferred>() - const request = new MssqlRequest( - this.#tedious, - CompiledQuery.raw('select 1'), - deferred, - ) + const request = new MssqlRequest({ + compiledQuery: CompiledQuery.raw('select 1'), + onDone: deferred, + tedious: this.#tedious, + }) this.#connection.execSql(request.request) @@ -238,6 +242,19 @@ class MssqlConnection implements DatabaseConnection { return tediousIsolationLevel } + #cancelRequest(request: MssqlRequest): Promise { + return new Promise((resolve) => { + request.request.once('requestCompleted', resolve) + + const wasCanceled = this.#connection.cancel() + + if (!wasCanceled) { + request.request.off('requestCompleted', resolve) + resolve(undefined) + } + }) + } + [PRIVATE_RELEASE_METHOD](): Promise { return new Promise((resolve, reject) => { this.#connection.reset((error) => { @@ -271,50 +288,83 @@ interface PlainDeferred { class MssqlRequest { readonly #request: TediousRequest readonly #rows: O[] + readonly #streamChunkSize: number | undefined + readonly #subscribers: Record< + string, + (event: 'completed' | 'chunkReady' | 'error', error?: unknown) => void + > readonly #tedious: Tedious - #completed: boolean #error: Error | any[] | undefined #rowCount: number | undefined - constructor( - tedious: Tedious, - compiledQuery: CompiledQuery, - onDone?: Deferred> | PlainDeferred>, - ) { - this.#completed = false + constructor(props: MssqlRequestProps) { + const { compiledQuery, onDone, streamChunkSize, tedious } = props + this.#rows = [] + this.#streamChunkSize = streamChunkSize + this.#subscribers = {} this.#tedious = tedious - const { parameters, sql } = compiledQuery + if (onDone) { + const subscriptionKey = 'onDone' - this.#request = new this.#tedious.Request(sql, (err, rowCount) => { - if (err) { - this.#error = err instanceof AggregateError ? err.errors : err - onDone?.reject(this.#error) - } else { - this.#rowCount = rowCount + this.#subscribers[subscriptionKey] = (event, error) => { + if (event === 'chunkReady') { + return + } + + delete this.#subscribers[subscriptionKey] + + if (event === 'error') { + onDone.reject(error) + } else { + onDone.resolve({ + rowCount: this.#rowCount, + rows: this.#rows, + }) + } } - }) + } + + this.#request = new this.#tedious.Request( + compiledQuery.sql, + (err, rowCount) => { + if (err) { + Object.values(this.#subscribers).forEach((subscriber) => + subscriber( + 'error', + err instanceof AggregateError ? err.errors : err, + ), + ) + } else { + this.#rowCount = rowCount + } + }, + ) - this.#addParametersToRequest(parameters) - this.#attachListeners(onDone) + this.#addParametersToRequest(compiledQuery.parameters) + this.#attachListeners() } get request(): TediousRequest { return this.#request } - readChunk(chunkSize: number): Promise { + readChunk(): Promise { + const subscriptionKey = this.readChunk.name + return new Promise((resolve, reject) => { - const interval = setInterval(() => { - if (this.#error) { - clearInterval(interval) - reject(this.#error) - } else if (this.#completed || this.#rows.length >= chunkSize) { - clearInterval(interval) - resolve(this.#rows.splice(0, chunkSize)) + this.#subscribers[subscriptionKey] = (event, error) => { + delete this.#subscribers[subscriptionKey] + + if (event === 'error') { + reject(error) + } else { + resolve(this.#rows.splice(0, this.#streamChunkSize)) } - }, 0) + } + + this.#request.resume() }) } @@ -330,9 +380,19 @@ class MssqlRequest { } } - #attachListeners( - onDone: Deferred> | PlainDeferred> | undefined, - ): void { + #attachListeners(): void { + const pauseAndEmitChunkReady = this.#streamChunkSize + ? () => { + if (this.#streamChunkSize! <= this.#rows.length) { + this.#request.pause() + + Object.values(this.#subscribers).forEach((subscriber) => + subscriber('chunkReady'), + ) + } + } + : () => {} + const rowListener = (columns: TediousColumnValue[]) => { const row: Record = {} @@ -341,18 +401,17 @@ class MssqlRequest { } this.#rows.push(row as O) + + pauseAndEmitChunkReady() } this.#request.on('row', rowListener) this.#request.once('requestCompleted', () => { - this.#completed = true + Object.values(this.#subscribers).forEach((subscriber) => + subscriber('completed'), + ) this.#request.off('row', rowListener) - - onDone?.resolve({ - rowCount: this.#rowCount, - rows: this.#rows, - }) }) } @@ -388,3 +447,10 @@ class MssqlRequest { return this.#tedious.TYPES.NVarChar } } + +interface MssqlRequestProps { + compiledQuery: CompiledQuery + onDone?: Deferred> | PlainDeferred> + streamChunkSize?: number + tedious: Tedious +} diff --git a/test/node/src/stream.test.ts b/test/node/src/stream.test.ts new file mode 100644 index 000000000..427ee1152 --- /dev/null +++ b/test/node/src/stream.test.ts @@ -0,0 +1,71 @@ +import { + DIALECTS, + Database, + TestContext, + createTableWithId, + destroyTest, + expect, + initTest, +} from './test-setup' +import { GeneratedAlways, Kysely, sql } from '../../..' +import { Request } from 'tedious' +import { SinonSandbox, SinonSpy, createSandbox } from 'sinon' + +const CHUNK_SIZE = 10 +const DIALECT = 'mssql' +const ITEM_COUNT = 100 +const TABLE = 'stream_test' + +if (DIALECTS.includes(DIALECT)) { + describe(`mssql: stream`, () => { + let sandbox: SinonSandbox + let pauseSpy: SinonSpy + let resumeSpy: SinonSpy + let ctx: Omit & { + db: Kysely } }> + } + + before(async function () { + sandbox = createSandbox() + pauseSpy = sandbox.spy(Request.prototype, 'pause') + resumeSpy = sandbox.spy(Request.prototype, 'resume') + + ctx = (await initTest(this, DIALECT)) as any + try { + await ctx.db.schema.dropTable(TABLE).execute() + } catch (err) {} + await createTableWithId(ctx.db.schema, DIALECT, TABLE).execute() + await sql` + set identity_insert ${sql.table(TABLE)} on; + with cteNums(n) AS ( + SELECT 1 + UNION ALL + SELECT n + 1 + FROM cteNums WHERE n < ${sql.lit(ITEM_COUNT)} -- how many times to iterate + ) + INSERT ${sql.table(TABLE)} (id) + SELECT * FROM cteNums + OPTION (MAXRECURSION ${sql.lit(ITEM_COUNT)}); + set identity_insert ${sql.table(TABLE)} off + `.execute(ctx.db) + }) + + after(async () => { + await ctx.db.schema.dropTable(TABLE).execute() + await destroyTest(ctx as any) + sandbox.restore() + }) + + it('should pause/resume the request according to chunk size', async () => { + for await (const _ of ctx.db + .selectFrom(TABLE) + .selectAll() + .stream(CHUNK_SIZE)); + + const chunks = Math.ceil(ITEM_COUNT / CHUNK_SIZE) + + expect(pauseSpy.callCount).to.equal(chunks) + expect(resumeSpy.callCount).to.equal(chunks + 1) + }) + }) +} diff --git a/test/node/src/test-setup.ts b/test/node/src/test-setup.ts index a85d6e273..62d21c8ee 100644 --- a/test/node/src/test-setup.ts +++ b/test/node/src/test-setup.ts @@ -41,6 +41,7 @@ import { OrderByDirection, UndirectedOrderByExpression, } from '../../../dist/cjs/parser/order-by-parser' +import type { ConnectionConfiguration } from 'tedious' export type Gender = 'male' | 'female' | 'other' export type MaritalStatus = 'single' | 'married' | 'divorced' | 'widowed' @@ -158,7 +159,7 @@ export const DIALECT_CONFIGS = { trustServerCertificate: true, }, server: 'localhost', - } satisfies Tedious.ConnectionConfig, + } satisfies ConnectionConfiguration, sqlite: { databasePath: ':memory:', @@ -373,7 +374,7 @@ export function createTableWithId( if (dialect === 'mssql') { return builder.addColumn('id', 'integer', (col) => - col.identity().notNull().primaryKey() + col.identity().notNull().primaryKey(), ) } From 87f365e75326bc43bce7c8d2e14b85108ab5e614 Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Tue, 18 Jun 2024 11:35:59 +0300 Subject: [PATCH 12/13] mention `kysely-ctl` in migrations section. (#1035) --- site/docs/migrations.mdx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/site/docs/migrations.mdx b/site/docs/migrations.mdx index 263b96add..f6abc8232 100644 --- a/site/docs/migrations.mdx +++ b/site/docs/migrations.mdx @@ -4,6 +4,8 @@ sidebar_position: 4 # Migrations +## Migration files + Migration files should look like this: ```ts @@ -18,11 +20,11 @@ export async function down(db: Kysely): Promise { } ``` -The up function is called when you update your database schema to the next version and down when you go back to previous version. The only argument for the functions is an instance of `Kysely`. It's important to use ` Kysely` and not `Kysely`. +The `up` function is called when you update your database schema to the next version and `down` when you go back to previous version. The only argument for the functions is an instance of `Kysely`. It's important to use `Kysely` and not `Kysely`. Migrations should never depend on the current code of your app because they need to work even when the app changes. Migrations need to be "frozen in time". -Migrations can use the `Kysely.schema` module to modify the schema. Migrations can also run normal queries to modify data. +Migrations can use the `Kysely.schema` module to modify the schema. Migrations can also run normal queries to read/modify data. ## Execution order @@ -126,9 +128,16 @@ export async function down(db: Kysely): Promise { } ``` +## CLI (optional) + +Kysely offers a CLI you can use for migrations (and more). It can help you create and run migrations. +It is not part of the core, and your mileage may vary. + +For more information, visit https://github.com/kysely-org/kysely-ctl. + ## Running migrations -You can then use +You can then use: ```ts const migrator = new Migrator(migratorConfig) @@ -137,7 +146,7 @@ await migrator.migrateToLatest(pathToMigrationsFolder) to run all migrations that have not yet been run. See the Migrator class's documentation for more info. -Kysely doesn't have a CLI for running migrations and probably never will. This is because Kysely's migrations are also written in TypeScript. To run the migrations, you need to first build the TypeScript code into JavaScript. A CLI would cause confusion over which migrations are being run, the TypeScript ones or the JavaScript ones. If we added support for both, the CLI would need to depend on a TypeScript compiler, which most production environments don't (and shouldn't) have. You will probably want to add a simple migration script to your projects like this: +You will probably want to add a simple migration script to your projects like this: ```ts import * as path from 'path' From fb5bf4d75846261da93a5480cdefafefdd3df19f Mon Sep 17 00:00:00 2001 From: Igal Klebanov Date: Tue, 18 Jun 2024 12:16:11 +0300 Subject: [PATCH 13/13] handle connection errors @ `MssqlDriver`. (#1042) --- src/dialect/mssql/mssql-dialect-config.ts | 20 +++++---- src/dialect/mssql/mssql-driver.ts | 32 ++++++++++---- test/node/src/disconnects.test.ts | 52 +++++++++++++++++++++++ 3 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 test/node/src/disconnects.test.ts diff --git a/src/dialect/mssql/mssql-dialect-config.ts b/src/dialect/mssql/mssql-dialect-config.ts index e84528f04..6adc2f09d 100644 --- a/src/dialect/mssql/mssql-dialect-config.ts +++ b/src/dialect/mssql/mssql-dialect-config.ts @@ -62,22 +62,26 @@ export interface TediousConnection { name?: string, isolationLevel?: number, ): void + cancel(): boolean + close(): void commitTransaction( callback: (error?: Error | null) => void, name?: string, ): void + connect(callback?: (error?: Error) => void): void execSql(request: TediousRequest): void + off(event: 'error', listener: (error: unknown) => void): this + off(event: string, listener: (...args: any[]) => void): this + on(event: 'error', listener: (error: unknown) => void): this + on(event: string, listener: (...args: any[]) => void): this + once(event: 'end', listener: () => void): this + once(event: string, listener: (...args: any[]) => void): this + reset(callback: (error?: Error | null) => void): void rollbackTransaction( callback: (error?: Error | null) => void, name?: string, ): void saveTransaction(callback: (error?: Error | null) => void, name: string): void - cancel(): boolean - reset(callback: (error?: Error | null) => void): void - close(): void - once(event: 'end', listener: () => void): this - once(event: string, listener: (...args: any[]) => void): this - connect(callback?: (error?: Error) => void): void } export type TediousIsolationLevel = Record @@ -104,12 +108,12 @@ export declare class TediousRequest { scale?: number }> | null, ): void + off(event: 'row', listener: (columns: any) => void): this + off(event: string, listener: (...args: any[]) => void): this on(event: 'row', listener: (columns: any) => void): this on(event: string, listener: (...args: any[]) => void): this once(event: 'requestCompleted', listener: () => void): this once(event: string, listener: (...args: any[]) => void): this - off(event: 'row', listener: (columns: any) => void): this - off(event: string, listener: (...args: any[]) => void): this pause(): void resume(): void } diff --git a/src/dialect/mssql/mssql-driver.ts b/src/dialect/mssql/mssql-driver.ts index ec749f685..71807b37c 100644 --- a/src/dialect/mssql/mssql-driver.ts +++ b/src/dialect/mssql/mssql-driver.ts @@ -46,14 +46,10 @@ export class MssqlDriver implements Driver { create: async () => { const connection = await this.#config.tedious.connectionFactory() - await new Promise((resolve, reject) => - connection.connect((error) => { - if (error) reject(error) - else resolve(undefined) - }), - ) - - return new MssqlConnection(connection, this.#config.tedious) + return await new MssqlConnection( + connection, + this.#config.tedious, + ).connect() }, destroy: async (connection) => { await connection[PRIVATE_DESTROY_METHOD]() @@ -104,6 +100,11 @@ class MssqlConnection implements DatabaseConnection { constructor(connection: TediousConnection, tedious: Tedious) { this.#connection = connection this.#tedious = tedious + + this.#connection.on('error', console.error) + this.#connection.once('end', () => { + this.#connection.off('error', console.error) + }) } async beginTransaction(settings: TransactionSettings): Promise { @@ -132,6 +133,21 @@ class MssqlConnection implements DatabaseConnection { ) } + async connect(): Promise { + await new Promise((resolve, reject) => { + this.#connection.connect((error) => { + if (error) { + console.error(error) + reject(error) + } else { + resolve(undefined) + } + }) + }) + + return this + } + async executeQuery(compiledQuery: CompiledQuery): Promise> { try { const deferred = new Deferred>() diff --git a/test/node/src/disconnects.test.ts b/test/node/src/disconnects.test.ts new file mode 100644 index 000000000..56ae1ff36 --- /dev/null +++ b/test/node/src/disconnects.test.ts @@ -0,0 +1,52 @@ +import { Kysely, MssqlDialect, sql } from '../../..' +import { DIALECTS, DIALECT_CONFIGS, Database, expect } from './test-setup' +import * as tarn from 'tarn' +import * as tedious from 'tedious' + +const dialect = 'mssql' + +if (DIALECTS.includes(dialect)) { + describe(`${dialect}: disconnects`, () => { + let connection: tedious.Connection + let connectionFactoryTimesCalled = 0 + let db: Kysely + + before(async () => { + db = new Kysely({ + dialect: new MssqlDialect({ + tarn: { + ...tarn, + options: { + min: 0, + max: 1, + }, + }, + tedious: { + ...tedious, + connectionFactory: () => { + connectionFactoryTimesCalled++ + + return (connection = new tedious.Connection( + DIALECT_CONFIGS[dialect], + )) + }, + }, + }), + }) + }) + + after(async () => { + await db.destroy() + }) + + it('should be disconnection tolerant', async () => { + await sql`select 1`.execute(db) + expect(connectionFactoryTimesCalled).to.equal(1) + + connection.socketError(new Error('moshe')) + + await sql`select 1`.execute(db) + expect(connectionFactoryTimesCalled).to.equal(2) + }) + }) +}