From 4f454e6abfaaa914dcb79b77e1541fefbb775f82 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Wed, 7 Aug 2024 16:47:34 +1000 Subject: [PATCH 1/5] initial jsr migration --- Dockerfile | 5 +---- connection/auth.ts | 4 ++-- connection/connection.ts | 13 ++++--------- connection/connection_params.ts | 2 +- connection/packet.ts | 2 +- connection/scram.ts | 10 +++++----- deno.json | 12 +++++++++++- deps.ts | 18 ------------------ query/decode.ts | 2 +- query/decoders.ts | 2 +- tests/auth_test.ts | 2 +- tests/connection_params_test.ts | 2 +- tests/connection_test.ts | 9 +++------ tests/data_types_test.ts | 10 ++++++---- tests/decode_test.ts | 2 +- tests/encode_test.ts | 2 +- tests/pool_test.ts | 3 ++- tests/query_client_test.ts | 22 +++++++++++----------- tests/test_deps.ts | 12 ------------ tests/utils_test.ts | 2 +- utils/utils.ts | 2 +- 21 files changed, 55 insertions(+), 83 deletions(-) delete mode 100644 deps.ts delete mode 100644 tests/test_deps.ts diff --git a/Dockerfile b/Dockerfile index c3bcd7c1..c402f96e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,10 +9,7 @@ RUN chmod +x /wait USER deno # Cache external libraries -# Test deps caches all main dependencies as well -COPY tests/test_deps.ts tests/test_deps.ts -COPY deps.ts deps.ts -RUN deno cache tests/test_deps.ts +RUN deno cache deno.json ADD . . RUN deno cache mod.ts diff --git a/connection/auth.ts b/connection/auth.ts index c32e7b88..e52aac90 100644 --- a/connection/auth.ts +++ b/connection/auth.ts @@ -1,9 +1,9 @@ -import { crypto, hex } from "../deps.ts"; +import { encodeHex } from "@std/encoding"; const encoder = new TextEncoder(); async function md5(bytes: Uint8Array): Promise { - return hex.encodeHex(await crypto.subtle.digest("MD5", bytes)); + return encodeHex(await crypto.subtle.digest("MD5", bytes)); } // AuthenticationMD5Password diff --git a/connection/connection.ts b/connection/connection.ts index 7ce3d38d..5b31ec49 100644 --- a/connection/connection.ts +++ b/connection/connection.ts @@ -26,15 +26,10 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { - bold, - BufReader, - BufWriter, - delay, - joinPath, - rgb24, - yellow, -} from "../deps.ts"; +import { BufReader, BufWriter } from "@std/io"; +import { delay } from "@std/async"; +import { bold, rgb24, yellow } from "@std/fmt/colors"; +import { join as joinPath } from "@std/path"; import { DeferredStack } from "../utils/deferred.ts"; import { getSocketName, readUInt32BE } from "../utils/utils.ts"; import { PacketWriter } from "./packet.ts"; diff --git a/connection/connection_params.ts b/connection/connection_params.ts index ac4f650e..b192f270 100644 --- a/connection/connection_params.ts +++ b/connection/connection_params.ts @@ -1,6 +1,6 @@ import { parseConnectionUri } from "../utils/utils.ts"; import { ConnectionParamsError } from "../client/error.ts"; -import { fromFileUrl, isAbsolute } from "../deps.ts"; +import { fromFileUrl, isAbsolute } from "@std/path"; import { OidType } from "../query/oid.ts"; import { DebugControls } from "../debug.ts"; import { ParseArrayFunction } from "../query/array_parser.ts"; diff --git a/connection/packet.ts b/connection/packet.ts index 36abae18..030bb4c9 100644 --- a/connection/packet.ts +++ b/connection/packet.ts @@ -25,7 +25,7 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { copy } from "../deps.ts"; +import { copy } from "@std/bytes"; import { readInt16BE, readInt32BE } from "../utils/utils.ts"; export class PacketReader { diff --git a/connection/scram.ts b/connection/scram.ts index 1ef2661e..2edaffd1 100644 --- a/connection/scram.ts +++ b/connection/scram.ts @@ -1,4 +1,4 @@ -import { base64 } from "../deps.ts"; +import { decodeBase64, encodeBase64 } from "@std/encoding"; /** Number of random bytes used to generate a nonce */ const defaultNonceSize = 16; @@ -132,7 +132,7 @@ function escape(str: string): string { } function generateRandomNonce(size: number): string { - return base64.encodeBase64(crypto.getRandomValues(new Uint8Array(size))); + return encodeBase64(crypto.getRandomValues(new Uint8Array(size))); } function parseScramAttributes(message: string): Record { @@ -221,7 +221,7 @@ export class Client { throw new Error(Reason.BadSalt); } try { - salt = base64.decodeBase64(attrs.s); + salt = decodeBase64(attrs.s); } catch { throw new Error(Reason.BadSalt); } @@ -261,7 +261,7 @@ export class Client { this.#auth_message += "," + responseWithoutProof; - const proof = base64.encodeBase64( + const proof = encodeBase64( computeScramProof( await computeScramSignature( this.#auth_message, @@ -294,7 +294,7 @@ export class Client { throw new Error(attrs.e ?? Reason.Rejected); } - const verifier = base64.encodeBase64( + const verifier = encodeBase64( await computeScramSignature( this.#auth_message, this.#key_signatures.server, diff --git a/deno.json b/deno.json index f4697e7c..b042410e 100644 --- a/deno.json +++ b/deno.json @@ -2,5 +2,15 @@ "lock": false, "name": "@bartlomieju/postgres", "version": "0.19.3", - "exports": "./mod.ts" + "exports": "./mod.ts", + "imports": { + "@std/assert": "jsr:@std/assert@^1.0.2", + "@std/async": "jsr:@std/async@^1.0.3", + "@std/bytes": "jsr:@std/bytes@^1.0.2", + "@std/datetime": "jsr:@std/datetime@^0.224.4", + "@std/encoding": "jsr:@std/encoding@^1.0.1", + "@std/fmt": "jsr:@std/fmt@^1.0.0", + "@std/io": "jsr:@std/io@^0.224.4", + "@std/path": "jsr:@std/path@^1.0.2" + } } diff --git a/deps.ts b/deps.ts deleted file mode 100644 index 3d10e31c..00000000 --- a/deps.ts +++ /dev/null @@ -1,18 +0,0 @@ -export * as base64 from "https://deno.land/std@0.214.0/encoding/base64.ts"; -export * as hex from "https://deno.land/std@0.214.0/encoding/hex.ts"; -export { parse as parseDate } from "https://deno.land/std@0.214.0/datetime/parse.ts"; -export { BufReader } from "https://deno.land/std@0.214.0/io/buf_reader.ts"; -export { BufWriter } from "https://deno.land/std@0.214.0/io/buf_writer.ts"; -export { copy } from "https://deno.land/std@0.214.0/bytes/copy.ts"; -export { crypto } from "https://deno.land/std@0.214.0/crypto/crypto.ts"; -export { delay } from "https://deno.land/std@0.214.0/async/delay.ts"; -export { - bold, - rgb24, - yellow, -} from "https://deno.land/std@0.214.0/fmt/colors.ts"; -export { - fromFileUrl, - isAbsolute, - join as joinPath, -} from "https://deno.land/std@0.214.0/path/mod.ts"; diff --git a/query/decode.ts b/query/decode.ts index 38df157e..2a1e2a96 100644 --- a/query/decode.ts +++ b/query/decode.ts @@ -1,5 +1,5 @@ +import { bold, yellow } from "@std/fmt/colors"; import { Oid, OidType, OidTypes, OidValue } from "./oid.ts"; -import { bold, yellow } from "../deps.ts"; import { decodeBigint, decodeBigintArray, diff --git a/query/decoders.ts b/query/decoders.ts index 4edbb03a..b1acc8a9 100644 --- a/query/decoders.ts +++ b/query/decoders.ts @@ -1,4 +1,4 @@ -import { parseDate } from "../deps.ts"; +import { parse as parseDate } from "@std/datetime"; import { parseArray } from "./array_parser.ts"; import type { Box, diff --git a/tests/auth_test.ts b/tests/auth_test.ts index f7ed38db..e73316b0 100644 --- a/tests/auth_test.ts +++ b/tests/auth_test.ts @@ -1,4 +1,4 @@ -import { assertEquals, assertNotEquals, assertRejects } from "./test_deps.ts"; +import { assertEquals, assertNotEquals, assertRejects } from "@std/assert"; import { Client as ScramClient, Reason } from "../connection/scram.ts"; Deno.test("Scram client reproduces RFC 7677 example", async () => { diff --git a/tests/connection_params_test.ts b/tests/connection_params_test.ts index d5138784..5de95843 100644 --- a/tests/connection_params_test.ts +++ b/tests/connection_params_test.ts @@ -1,4 +1,4 @@ -import { assertEquals, assertThrows, fromFileUrl } from "./test_deps.ts"; +import { assertEquals, assertThrows, fromFileUrl } from "@std/assert"; import { createParams } from "../connection/connection_params.ts"; import { ConnectionParamsError } from "../client/error.ts"; diff --git a/tests/connection_test.ts b/tests/connection_test.ts index 5cc85539..2e52b411 100644 --- a/tests/connection_test.ts +++ b/tests/connection_test.ts @@ -1,9 +1,6 @@ -import { - assertEquals, - assertRejects, - copyStream, - joinPath, -} from "./test_deps.ts"; +import { join as joinPath } from "@std/path"; +import { assertEquals, assertRejects } from "@std/assert"; +import { copy as copyStream } from "@std/io"; import { getClearConfiguration, getClearSocketConfiguration, diff --git a/tests/data_types_test.ts b/tests/data_types_test.ts index d4d56103..008697fa 100644 --- a/tests/data_types_test.ts +++ b/tests/data_types_test.ts @@ -1,4 +1,6 @@ -import { assertEquals, base64, formatDate, parseDate } from "./test_deps.ts"; +import { decodeBase64, encodeBase64 } from "@std/encoding"; +import { format as formatDate, parse as parseDate } from "@std/datetime"; +import { assertEquals } from "@std/assert"; import { getMainConfiguration } from "./config.ts"; import { generateSimpleClientTest } from "./helpers.ts"; import type { @@ -34,7 +36,7 @@ function generateRandomPoint(max_value = 100): Point { const CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; function randomBase64(): string { - return base64.encodeBase64( + return encodeBase64( Array.from( { length: Math.ceil(Math.random() * 256) }, () => CHARS[Math.floor(Math.random() * CHARS.length)], @@ -671,7 +673,7 @@ Deno.test( `SELECT decode('${base64_string}','base64')`, ); - assertEquals(result.rows[0][0], base64.decodeBase64(base64_string)); + assertEquals(result.rows[0][0], decodeBase64(base64_string)); }), ); @@ -691,7 +693,7 @@ Deno.test( assertEquals( result.rows[0][0], - strings.map(base64.decodeBase64), + strings.map(decodeBase64), ); }), ); diff --git a/tests/decode_test.ts b/tests/decode_test.ts index 06512911..75b3d40a 100644 --- a/tests/decode_test.ts +++ b/tests/decode_test.ts @@ -1,3 +1,4 @@ +import { assertEquals, assertThrows } from "@std/assert"; import { Column, decode } from "../query/decode.ts"; import { decodeBigint, @@ -17,7 +18,6 @@ import { decodePoint, decodeTid, } from "../query/decoders.ts"; -import { assertEquals, assertThrows } from "./test_deps.ts"; import { Oid } from "../query/oid.ts"; Deno.test("decodeBigint", function () { diff --git a/tests/encode_test.ts b/tests/encode_test.ts index 784fdaab..ced1826b 100644 --- a/tests/encode_test.ts +++ b/tests/encode_test.ts @@ -1,4 +1,4 @@ -import { assertEquals } from "./test_deps.ts"; +import { assertEquals } from "@std/assert"; import { encodeArgument } from "../query/encode.ts"; // internally `encodeArguments` uses `getTimezoneOffset` to encode Date diff --git a/tests/pool_test.ts b/tests/pool_test.ts index c8ecac91..b1ec55d5 100644 --- a/tests/pool_test.ts +++ b/tests/pool_test.ts @@ -1,4 +1,5 @@ -import { assertEquals, delay } from "./test_deps.ts"; +import { delay } from "@std/async"; +import { assertEquals } from "@std/assert"; import { getMainConfiguration } from "./config.ts"; import { generatePoolClientTest } from "./helpers.ts"; diff --git a/tests/query_client_test.ts b/tests/query_client_test.ts index c096049a..ef8c4a03 100644 --- a/tests/query_client_test.ts +++ b/tests/query_client_test.ts @@ -1,10 +1,3 @@ -import { - Client, - ConnectionError, - Pool, - PostgresError, - TransactionError, -} from "../mod.ts"; import { assert, assertEquals, @@ -12,7 +5,14 @@ import { assertObjectMatch, assertRejects, assertThrows, -} from "./test_deps.ts"; +} from "@std/assert"; +import { + Client, + ConnectionError, + Pool, + PostgresError, + TransactionError, +} from "../mod.ts"; import { getMainConfiguration } from "./config.ts"; import { PoolClient, QueryClient } from "../client.ts"; import { ClientOptions } from "../connection/connection_params.ts"; @@ -124,7 +124,7 @@ Deno.test( `SELECT 'Y'::BOOLEAN AS _bool, 3.14::REAL AS _float, - ARRAY[1, 2, 3] AS _int_array, + ARRAY[1, 2, 3] AS _int_array, '{"test": "foo", "arr": [1,2,3]}'::JSONB AS _jsonb, 'DATA' AS _text ;`, @@ -152,7 +152,7 @@ Deno.test( `SELECT 'Y'::BOOLEAN AS _bool, 3.14::REAL AS _float, - ARRAY[1, 2, 3] AS _int_array, + ARRAY[1, 2, 3] AS _int_array, '{"test": "foo", "arr": [1,2,3]}'::JSONB AS _jsonb, 'DATA' AS _text ;`, @@ -246,7 +246,7 @@ Deno.test( withClient( async (client) => { const result = await client.queryObject( - `SELECT + `SELECT ARRAY[true, false, true] AS _bool_array, ARRAY['2024-01-01'::date, '2024-01-02'::date, '2024-01-03'::date] AS _date_array, ARRAY[1.5:: REAL, 2.5::REAL, 3.5::REAL] AS _float_array, diff --git a/tests/test_deps.ts b/tests/test_deps.ts deleted file mode 100644 index 3ec05aaa..00000000 --- a/tests/test_deps.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from "../deps.ts"; -export { - assert, - assertEquals, - assertInstanceOf, - assertNotEquals, - assertObjectMatch, - assertRejects, - assertThrows, -} from "https://deno.land/std@0.214.0/assert/mod.ts"; -export { format as formatDate } from "https://deno.land/std@0.214.0/datetime/format.ts"; -export { copy as copyStream } from "https://deno.land/std@0.214.0/io/copy.ts"; diff --git a/tests/utils_test.ts b/tests/utils_test.ts index d5e418d3..fe12b23f 100644 --- a/tests/utils_test.ts +++ b/tests/utils_test.ts @@ -1,4 +1,4 @@ -import { assertEquals, assertThrows } from "./test_deps.ts"; +import { assertEquals, assertThrows } from "@std/assert"; import { parseConnectionUri, Uri } from "../utils/utils.ts"; import { DeferredAccessStack, DeferredStack } from "../utils/deferred.ts"; diff --git a/utils/utils.ts b/utils/utils.ts index ae7ccee8..f25550cf 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -1,4 +1,4 @@ -import { bold, yellow } from "../deps.ts"; +import { bold, yellow } from "@std/fmt/colors"; export function readInt16BE(buffer: Uint8Array, offset: number): number { offset = offset >>> 0; From b6775eccdab1e6f6d8ab5b8a879378ec14072226 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Wed, 7 Aug 2024 17:24:21 +1000 Subject: [PATCH 2/5] fixes and code quality --- .github/workflows/publish_jsr.yml | 10 ++----- Dockerfile | 2 +- client/error.ts | 2 +- connection/connection.ts | 47 +++++++++++++++---------------- deno.json | 3 ++ tests/config.ts | 2 +- tests/connection_params_test.ts | 29 ++++++++++--------- tests/connection_test.ts | 14 ++++----- tests/data_types_test.ts | 33 ++++++++++++---------- tests/decode_test.ts | 38 ++++++++++++------------- tests/encode_test.ts | 24 ++++++++-------- tests/helpers.ts | 2 +- tests/query_client_test.ts | 28 +++++++++--------- tests/utils_test.ts | 7 +++-- tools/convert_to_jsr.ts | 38 ------------------------- utils/deferred.ts | 3 +- utils/utils.ts | 7 +++-- 17 files changed, 128 insertions(+), 161 deletions(-) delete mode 100644 tools/convert_to_jsr.ts diff --git a/.github/workflows/publish_jsr.yml b/.github/workflows/publish_jsr.yml index 50285a66..546c00ba 100644 --- a/.github/workflows/publish_jsr.yml +++ b/.github/workflows/publish_jsr.yml @@ -22,16 +22,10 @@ jobs: - name: Set up Deno uses: denoland/setup-deno@v1 - + - name: Check Format run: deno fmt --check - - name: Convert to JSR package - run: deno run -A tools/convert_to_jsr.ts - - - name: Format converted code - run: deno fmt - - name: Lint run: deno lint @@ -40,7 +34,7 @@ jobs: - name: Build tests container run: docker-compose build tests - + - name: Run tests run: docker-compose run tests diff --git a/Dockerfile b/Dockerfile index c402f96e..398a1734 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM denoland/deno:alpine-1.40.3 +FROM denoland/deno:alpine WORKDIR /app # Install wait utility diff --git a/client/error.ts b/client/error.ts index 7fc4cccd..35d05993 100644 --- a/client/error.ts +++ b/client/error.ts @@ -1,4 +1,4 @@ -import { type Notice } from "../connection/message.ts"; +import type { Notice } from "../connection/message.ts"; /** * A connection error diff --git a/connection/connection.ts b/connection/connection.ts index 5b31ec49..83fd1f7a 100644 --- a/connection/connection.ts +++ b/connection/connection.ts @@ -49,7 +49,7 @@ import { type QueryResult, ResultType, } from "../query/query.ts"; -import { type ClientConfiguration } from "./connection_params.ts"; +import type { ClientConfiguration } from "./connection_params.ts"; import * as scram from "./scram.ts"; import { ConnectionError, @@ -124,7 +124,7 @@ const encoder = new TextEncoder(); export class Connection { #bufReader!: BufReader; #bufWriter!: BufWriter; - #conn!: Deno.Conn; + #conn!: Deno.TcpConn | Deno.TlsConn; connected = false; #connection_params: ClientConfiguration; #message_header = new Uint8Array(5); @@ -290,7 +290,7 @@ export class Connection { } async #openTlsConnection( - connection: Deno.Conn, + connection: Deno.TcpConn, options: { hostname: string; caCerts: string[] }, ) { this.#conn = await Deno.startTls(connection, options); @@ -349,7 +349,7 @@ export class Connection { // https://www.postgresql.org/docs/14/protocol-flow.html#id-1.10.5.7.11 if (accepts_tls) { try { - await this.#openTlsConnection(this.#conn, { + await this.#openTlsConnection(this.#conn as Deno.TcpConn, { hostname, caCerts: caCertificates, }); @@ -357,10 +357,11 @@ export class Connection { } catch (e) { if (!tls_enforced) { console.error( - bold(yellow("TLS connection failed with message: ")) + - e.message + - "\n" + - bold("Defaulting to non-encrypted connection"), + `${ + bold(yellow("TLS connection failed with message:")) + } ${e.message}\n${ + bold("Defaulting to non-encrypted connection") + }`, ); await this.#openConnection({ hostname, port, transport: "tcp" }); this.#tls = false; @@ -379,7 +380,7 @@ export class Connection { } try { - let startup_response; + let startup_response: Message | undefined; try { startup_response = await this.#sendStartupMessage(); } catch (e) { @@ -390,18 +391,16 @@ export class Connection { throw new Error( "The certificate used to secure the TLS connection is invalid.", ); - } else { - console.error( - bold(yellow("TLS connection failed with message: ")) + - e.message + - "\n" + - bold("Defaulting to non-encrypted connection"), - ); - await this.#openConnection({ hostname, port, transport: "tcp" }); - this.#tls = false; - this.#transport = "tcp"; - startup_response = await this.#sendStartupMessage(); } + console.error( + `${ + bold(yellow("TLS connection failed with message:")) + } ${e.message}\n${bold("Defaulting to non-encrypted connection")}`, + ); + await this.#openConnection({ hostname, port, transport: "tcp" }); + this.#tls = false; + this.#transport = "tcp"; + startup_response = await this.#sendStartupMessage(); } else { throw e; } @@ -778,16 +777,16 @@ export class Connection { if (hasBinaryArgs) { this.#packetWriter.addInt16(query.args.length); - query.args.forEach((arg) => { + for (const arg of query.args) { this.#packetWriter.addInt16(arg instanceof Uint8Array ? 1 : 0); - }); + } } else { this.#packetWriter.addInt16(0); } this.#packetWriter.addInt16(query.args.length); - query.args.forEach((arg) => { + for (const arg of query.args) { if (arg === null || typeof arg === "undefined") { this.#packetWriter.addInt32(-1); } else if (arg instanceof Uint8Array) { @@ -798,7 +797,7 @@ export class Connection { this.#packetWriter.addInt32(byteLength); this.#packetWriter.addString(arg); } - }); + } this.#packetWriter.addInt16(0); const buffer = this.#packetWriter.flush(0x42); diff --git a/deno.json b/deno.json index b042410e..36fa0e44 100644 --- a/deno.json +++ b/deno.json @@ -12,5 +12,8 @@ "@std/fmt": "jsr:@std/fmt@^1.0.0", "@std/io": "jsr:@std/io@^0.224.4", "@std/path": "jsr:@std/path@^1.0.2" + }, + "tasks": { + "test": "deno test --allow-net --allow-env --allow-read" } } diff --git a/tests/config.ts b/tests/config.ts index 17bf701c..4a6784cf 100644 --- a/tests/config.ts +++ b/tests/config.ts @@ -1,4 +1,4 @@ -import { +import type { ClientConfiguration, ClientOptions, } from "../connection/connection_params.ts"; diff --git a/tests/connection_params_test.ts b/tests/connection_params_test.ts index 5de95843..b75fc272 100644 --- a/tests/connection_params_test.ts +++ b/tests/connection_params_test.ts @@ -1,4 +1,5 @@ -import { assertEquals, assertThrows, fromFileUrl } from "@std/assert"; +import { fromFileUrl } from "@std/path"; +import { assertEquals, assertThrows } from "@std/assert"; import { createParams } from "../connection/connection_params.ts"; import { ConnectionParamsError } from "../client/error.ts"; @@ -53,7 +54,7 @@ function withEnv( }; } -Deno.test("Parses connection string", function () { +Deno.test("Parses connection string", () => { const p = createParams( "postgres://some_user@some_host:10101/deno_postgres", ); @@ -65,7 +66,7 @@ Deno.test("Parses connection string", function () { assertEquals(p.user, "some_user"); }); -Deno.test("Parses connection string with socket host", function () { +Deno.test("Parses connection string with socket host", () => { const socket = "/var/run/postgresql"; const p = createParams( @@ -79,7 +80,7 @@ Deno.test("Parses connection string with socket host", function () { assertEquals(p.user, "some_user"); }); -Deno.test('Parses connection string with "postgresql" as driver', function () { +Deno.test('Parses connection string with "postgresql" as driver', () => { const p = createParams( "postgresql://some_user@some_host:10101/deno_postgres", ); @@ -90,7 +91,7 @@ Deno.test('Parses connection string with "postgresql" as driver', function () { assertEquals(p.port, 10101); }); -Deno.test("Parses connection string without port", function () { +Deno.test("Parses connection string without port", () => { const p = createParams( "postgres://some_user@some_host/deno_postgres", ); @@ -101,7 +102,7 @@ Deno.test("Parses connection string without port", function () { assertEquals(p.port, 5432); }); -Deno.test("Parses connection string with application name", function () { +Deno.test("Parses connection string with application name", () => { const p = createParams( "postgres://some_user@some_host:10101/deno_postgres?application_name=test_app", ); @@ -122,7 +123,7 @@ Deno.test("Parses connection string with reserved URL parameters", () => { assertEquals(p.user, "some_user"); }); -Deno.test("Parses connection string with sslmode required", function () { +Deno.test("Parses connection string with sslmode required", () => { const p = createParams( "postgres://some_user@some_host:10101/deno_postgres?sslmode=require", ); @@ -176,7 +177,7 @@ Deno.test("Throws on connection string with invalid options", () => { assertThrows( () => createParams( - `postgres://some_user@some_host:10101/deno_postgres?options=z`, + "postgres://some_user@some_host:10101/deno_postgres?options=z", ), Error, `Value "z" is not a valid options argument`, @@ -216,7 +217,7 @@ Deno.test("Throws on connection string with invalid options", () => { ); }); -Deno.test("Throws on connection string with invalid driver", function () { +Deno.test("Throws on connection string with invalid driver", () => { assertThrows( () => createParams( @@ -227,7 +228,7 @@ Deno.test("Throws on connection string with invalid driver", function () { ); }); -Deno.test("Throws on connection string with invalid port", function () { +Deno.test("Throws on connection string with invalid port", () => { assertThrows( () => createParams( @@ -238,7 +239,7 @@ Deno.test("Throws on connection string with invalid port", function () { ); }); -Deno.test("Throws on connection string with invalid ssl mode", function () { +Deno.test("Throws on connection string with invalid ssl mode", () => { assertThrows( () => createParams( @@ -249,7 +250,7 @@ Deno.test("Throws on connection string with invalid ssl mode", function () { ); }); -Deno.test("Parses connection options", function () { +Deno.test("Parses connection options", () => { const p = createParams({ user: "some_user", hostname: "some_host", @@ -264,7 +265,7 @@ Deno.test("Parses connection options", function () { assertEquals(p.port, 10101); }); -Deno.test("Throws on invalid tls options", function () { +Deno.test("Throws on invalid tls options", () => { assertThrows( () => createParams({ @@ -493,7 +494,7 @@ Deno.test("Throws when host is a URL and host type is socket", () => { } if (!(error.cause instanceof Error)) { - throw new Error(`Expected cause for error`); + throw new Error("Expected cause for error"); } const expected_message = "The provided host is not a file path"; diff --git a/tests/connection_test.ts b/tests/connection_test.ts index 2e52b411..0474be02 100644 --- a/tests/connection_test.ts +++ b/tests/connection_test.ts @@ -229,7 +229,7 @@ Deno.test("Defaults to unencrypted when certificate is invalid and TLS is not en } }); -Deno.test("Handles bad authentication correctly", async function () { +Deno.test("Handles bad authentication correctly", async () => { const badConnectionData = getMainConfiguration(); badConnectionData.password += getRandomString(); const client = new Client(badConnectionData); @@ -249,7 +249,7 @@ Deno.test("Handles bad authentication correctly", async function () { // This test requires current user database connection permissions // on "pg_hba.conf" set to "all" -Deno.test("Startup error when database does not exist", async function () { +Deno.test("Startup error when database does not exist", async () => { const badConnectionData = getMainConfiguration(); badConnectionData.database += getRandomString(); const client = new Client(badConnectionData); @@ -361,7 +361,7 @@ Deno.test("Attempts to guess socket route", async () => { ); }); -Deno.test("Closes connection on bad TLS availability verification", async function () { +Deno.test("Closes connection on bad TLS availability verification", async () => { const server = new Worker( new URL("./workers/postgres_server.ts", import.meta.url).href, { @@ -501,14 +501,14 @@ async function mockReconnection(attempts: number) { ); } -Deno.test("Attempts reconnection on connection startup", async function () { +Deno.test("Attempts reconnection on connection startup", async () => { await mockReconnection(5); await mockReconnection(0); }); // This test ensures a failed query that is disconnected after execution but before // status report is only executed one (regression test) -Deno.test("Attempts reconnection on disconnection", async function () { +Deno.test("Attempts reconnection on disconnection", async () => { const client = new Client({ ...getMainConfiguration(), connection: { @@ -583,7 +583,7 @@ Deno.test("Attempts reconnection on socket disconnection", async () => { // TODO // Find a way to unlink the socket to simulate unexpected socket disconnection -Deno.test("Attempts reconnection when connection is lost", async function () { +Deno.test("Attempts reconnection when connection is lost", async () => { const cfg = getMainConfiguration(); const listener = Deno.listen({ hostname: "127.0.0.1", port: 0 }); @@ -621,7 +621,7 @@ Deno.test("Attempts reconnection when connection is lost", async function () { await proxy; }); -Deno.test("Doesn't attempt reconnection when attempts are set to zero", async function () { +Deno.test("Doesn't attempt reconnection when attempts are set to zero", async () => { const client = new Client({ ...getMainConfiguration(), connection: { attempts: 0 }, diff --git a/tests/data_types_test.ts b/tests/data_types_test.ts index 008697fa..f6f02ddd 100644 --- a/tests/data_types_test.ts +++ b/tests/data_types_test.ts @@ -142,7 +142,7 @@ Deno.test( "name", testClient(async (client) => { const name = "some"; - const result = await client.queryArray(`SELECT $1::name`, [name]); + const result = await client.queryArray("SELECT $1::name", [name]); assertEquals(result.rows[0], [name]); }), ); @@ -160,7 +160,7 @@ Deno.test( Deno.test( "oid", testClient(async (client) => { - const result = await client.queryArray(`SELECT 1::oid`); + const result = await client.queryArray("SELECT 1::oid"); assertEquals(result.rows[0][0], "1"); }), ); @@ -168,7 +168,7 @@ Deno.test( Deno.test( "oid array", testClient(async (client) => { - const result = await client.queryArray(`SELECT ARRAY[1::oid, 452, 1023]`); + const result = await client.queryArray("SELECT ARRAY[1::oid, 452, 1023]"); assertEquals(result.rows[0][0], ["1", "452", "1023"]); }), ); @@ -349,7 +349,7 @@ Deno.test( const user = getMainConfiguration().user; const result = await client.queryArray( - `SELECT ($1)::regrole`, + "SELECT ($1)::regrole", [user], ); @@ -363,7 +363,7 @@ Deno.test( const user = getMainConfiguration().user; const result = await client.queryArray( - `SELECT ARRAY[($1)::regrole]`, + "SELECT ARRAY[($1)::regrole]", [user], ); @@ -447,7 +447,7 @@ Deno.test( "numeric", testClient(async (client) => { const number = "1234567890.1234567890"; - const result = await client.queryArray(`SELECT $1::numeric`, [number]); + const result = await client.queryArray("SELECT $1::numeric", [number]); assertEquals(result.rows[0][0], number); }), ); @@ -457,7 +457,7 @@ Deno.test( testClient(async (client) => { const numeric = ["1234567890.1234567890", "6107693.123123124"]; const result = await client.queryArray( - `SELECT ARRAY[$1::numeric, $2]`, + "SELECT ARRAY[$1::numeric, $2]", [numeric[0], numeric[1]], ); assertEquals(result.rows[0][0], numeric); @@ -498,13 +498,13 @@ Deno.test( "char", testClient(async (client) => { await client.queryArray( - `CREATE TEMP TABLE CHAR_TEST (X CHARACTER(2));`, + "CREATE TEMP TABLE CHAR_TEST (X CHARACTER(2));", ); await client.queryArray( `INSERT INTO CHAR_TEST (X) VALUES ('A');`, ); const result = await client.queryArray( - `SELECT X FROM CHAR_TEST`, + "SELECT X FROM CHAR_TEST", ); assertEquals(result.rows[0][0], "A "); }), @@ -574,7 +574,7 @@ Deno.test( "uuid", testClient(async (client) => { const uuid_text = "c4792ecb-c00a-43a2-bd74-5b0ed551c599"; - const result = await client.queryArray(`SELECT $1::uuid`, [uuid_text]); + const result = await client.queryArray("SELECT $1::uuid", [uuid_text]); assertEquals(result.rows[0][0], uuid_text); }), ); @@ -719,7 +719,7 @@ Deno.test( ]); const result2 = await client.queryArray( - `SELECT array[ array[ point(1,2), point(3.5, 4.1) ], array[ point(25, 50), point(-10, -17.5) ] ]`, + "SELECT array[ array[ point(1,2), point(3.5, 4.1) ], array[ point(25, 50), point(-10, -17.5) ] ]", ); assertEquals(result2.rows[0], [ [ @@ -757,7 +757,7 @@ Deno.test( [date], ); - assertEquals(result.rows[0], [new Date(date), Infinity]); + assertEquals(result.rows[0], [new Date(date), Number.POSITIVE_INFINITY]); }), ); @@ -787,7 +787,10 @@ Deno.test( [timestamp], ); - assertEquals(result.rows[0], [new Date(timestamp), Infinity]); + assertEquals(result.rows[0], [ + new Date(timestamp), + Number.POSITIVE_INFINITY, + ]); }), ); @@ -800,7 +803,7 @@ Deno.test( ]; const result = await client.queryArray<[[Timestamp, Timestamp]]>( - `SELECT ARRAY[$1::TIMESTAMPTZ, $2]`, + "SELECT ARRAY[$1::TIMESTAMPTZ, $2]", timestamps, ); @@ -934,7 +937,7 @@ Deno.test( assertEquals(result.rows[0], [ parseDate(date_text, "yyyy-MM-dd"), - Infinity, + Number.POSITIVE_INFINITY, ]); }), ); diff --git a/tests/decode_test.ts b/tests/decode_test.ts index 75b3d40a..9bf1b36a 100644 --- a/tests/decode_test.ts +++ b/tests/decode_test.ts @@ -20,11 +20,11 @@ import { } from "../query/decoders.ts"; import { Oid } from "../query/oid.ts"; -Deno.test("decodeBigint", function () { +Deno.test("decodeBigint", () => { assertEquals(decodeBigint("18014398509481984"), 18014398509481984n); }); -Deno.test("decodeBigintArray", function () { +Deno.test("decodeBigintArray", () => { assertEquals( decodeBigintArray( "{17365398509481972,9007199254740992,-10414398509481984}", @@ -33,7 +33,7 @@ Deno.test("decodeBigintArray", function () { ); }); -Deno.test("decodeBoolean", function () { +Deno.test("decodeBoolean", () => { assertEquals(decodeBoolean("True"), true); assertEquals(decodeBoolean("yEs"), true); assertEquals(decodeBoolean("T"), true); @@ -50,12 +50,12 @@ Deno.test("decodeBoolean", function () { assertEquals(decodeBoolean(""), false); }); -Deno.test("decodeBooleanArray", function () { +Deno.test("decodeBooleanArray", () => { assertEquals(decodeBooleanArray("{True,0,T}"), [true, false, true]); assertEquals(decodeBooleanArray("{no,Y,1}"), [false, true, true]); }); -Deno.test("decodeBox", function () { +Deno.test("decodeBox", () => { assertEquals(decodeBox("(12.4,2),(33,4.33)"), { a: { x: "12.4", y: "2" }, b: { x: "33", y: "4.33" }, @@ -86,7 +86,7 @@ Deno.test("decodeBox", function () { ); }); -Deno.test("decodeCircle", function () { +Deno.test("decodeCircle", () => { assertEquals(decodeCircle("<(12.4,2),3.5>"), { point: { x: "12.4", y: "2" }, radius: "3.5", @@ -105,11 +105,11 @@ Deno.test("decodeCircle", function () { ); }); -Deno.test("decodeDate", function () { +Deno.test("decodeDate", () => { assertEquals(decodeDate("2021-08-01"), new Date("2021-08-01 00:00:00-00")); }); -Deno.test("decodeDatetime", function () { +Deno.test("decodeDatetime", () => { assertEquals( decodeDatetime("2021-08-01"), new Date("2021-08-01 00:00:00-00"), @@ -120,17 +120,17 @@ Deno.test("decodeDatetime", function () { ); }); -Deno.test("decodeFloat", function () { +Deno.test("decodeFloat", () => { assertEquals(decodeFloat("3.14"), 3.14); - assertEquals(decodeFloat("q743 44 23i4"), NaN); + assertEquals(decodeFloat("q743 44 23i4"), Number.NaN); }); -Deno.test("decodeInt", function () { +Deno.test("decodeInt", () => { assertEquals(decodeInt("42"), 42); - assertEquals(decodeInt("q743 44 23i4"), NaN); + assertEquals(decodeInt("q743 44 23i4"), Number.NaN); }); -Deno.test("decodeJson", function () { +Deno.test("decodeJson", () => { assertEquals( decodeJson( '{"key_1": "MY VALUE", "key_2": null, "key_3": 10, "key_4": {"subkey_1": true, "subkey_2": ["1",2]}}', @@ -145,7 +145,7 @@ Deno.test("decodeJson", function () { assertThrows(() => decodeJson("{ 'eqw' ; ddd}")); }); -Deno.test("decodeLine", function () { +Deno.test("decodeLine", () => { assertEquals(decodeLine("{100,50,0}"), { a: "100", b: "50", c: "0" }); let testValue = "{100,50,0,100}"; assertThrows( @@ -161,7 +161,7 @@ Deno.test("decodeLine", function () { ); }); -Deno.test("decodeLineSegment", function () { +Deno.test("decodeLineSegment", () => { assertEquals(decodeLineSegment("((100,50),(350,350))"), { a: { x: "100", y: "50" }, b: { x: "350", y: "350" }, @@ -192,7 +192,7 @@ Deno.test("decodeLineSegment", function () { ); }); -Deno.test("decodePath", function () { +Deno.test("decodePath", () => { assertEquals(decodePath("[(100,50),(350,350)]"), [ { x: "100", y: "50" }, { x: "350", y: "350" }, @@ -216,7 +216,7 @@ Deno.test("decodePath", function () { ); }); -Deno.test("decodePoint", function () { +Deno.test("decodePoint", () => { assertEquals(decodePoint("(10.555,50.8)"), { x: "10.555", y: "50.8" }); let testValue = "(1000)"; assertThrows( @@ -244,14 +244,14 @@ Deno.test("decodePoint", function () { ); }); -Deno.test("decodeTid", function () { +Deno.test("decodeTid", () => { assertEquals(decodeTid("(19714398509481984,29383838509481984)"), [ 19714398509481984n, 29383838509481984n, ]); }); -Deno.test("decode strategy", function () { +Deno.test("decode strategy", () => { const testValues = [ { value: "40", diff --git a/tests/encode_test.ts b/tests/encode_test.ts index ced1826b..9a6e64dd 100644 --- a/tests/encode_test.ts +++ b/tests/encode_test.ts @@ -10,12 +10,12 @@ function resetTimezoneOffset() { } function overrideTimezoneOffset(offset: number) { - Date.prototype.getTimezoneOffset = function () { + Date.prototype.getTimezoneOffset = () => { return offset; }; } -Deno.test("encodeDatetime", function () { +Deno.test("encodeDatetime", () => { // GMT overrideTimezoneOffset(0); @@ -35,33 +35,33 @@ Deno.test("encodeDatetime", function () { resetTimezoneOffset(); }); -Deno.test("encodeUndefined", function () { +Deno.test("encodeUndefined", () => { assertEquals(encodeArgument(undefined), null); }); -Deno.test("encodeNull", function () { +Deno.test("encodeNull", () => { assertEquals(encodeArgument(null), null); }); -Deno.test("encodeBoolean", function () { +Deno.test("encodeBoolean", () => { assertEquals(encodeArgument(true), "true"); assertEquals(encodeArgument(false), "false"); }); -Deno.test("encodeNumber", function () { +Deno.test("encodeNumber", () => { assertEquals(encodeArgument(1), "1"); assertEquals(encodeArgument(1.2345), "1.2345"); }); -Deno.test("encodeString", function () { +Deno.test("encodeString", () => { assertEquals(encodeArgument("deno-postgres"), "deno-postgres"); }); -Deno.test("encodeObject", function () { +Deno.test("encodeObject", () => { assertEquals(encodeArgument({ x: 1 }), '{"x":1}'); }); -Deno.test("encodeUint8Array", function () { +Deno.test("encodeUint8Array", () => { const buf1 = new Uint8Array([1, 2, 3]); const buf2 = new Uint8Array([2, 10, 500]); const buf3 = new Uint8Array([11]); @@ -71,20 +71,20 @@ Deno.test("encodeUint8Array", function () { assertEquals("\\x0b", encodeArgument(buf3)); }); -Deno.test("encodeArray", function () { +Deno.test("encodeArray", () => { const array = [null, "postgres", 1, ["foo", "bar"]]; const encodedArray = encodeArgument(array); assertEquals(encodedArray, '{NULL,"postgres","1",{"foo","bar"}}'); }); -Deno.test("encodeObjectArray", function () { +Deno.test("encodeObjectArray", () => { const array = [{ x: 1 }, { y: 2 }]; const encodedArray = encodeArgument(array); assertEquals(encodedArray, '{"{\\"x\\":1}","{\\"y\\":2}"}'); }); -Deno.test("encodeDateArray", function () { +Deno.test("encodeDateArray", () => { overrideTimezoneOffset(0); const array = [new Date(2019, 1, 10, 20, 30, 40, 5)]; diff --git a/tests/helpers.ts b/tests/helpers.ts index d1630d3e..e26a7f27 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -1,6 +1,6 @@ import { Client } from "../client.ts"; import { Pool } from "../pool.ts"; -import { type ClientOptions } from "../connection/connection_params.ts"; +import type { ClientOptions } from "../connection/connection_params.ts"; export function generateSimpleClientTest( client_options: ClientOptions, diff --git a/tests/query_client_test.ts b/tests/query_client_test.ts index ef8c4a03..131df20d 100644 --- a/tests/query_client_test.ts +++ b/tests/query_client_test.ts @@ -6,6 +6,7 @@ import { assertRejects, assertThrows, } from "@std/assert"; +import type { QueryResult } from "../mod.ts"; import { Client, ConnectionError, @@ -14,8 +15,8 @@ import { TransactionError, } from "../mod.ts"; import { getMainConfiguration } from "./config.ts"; -import { PoolClient, QueryClient } from "../client.ts"; -import { ClientOptions } from "../connection/connection_params.ts"; +import type { PoolClient, QueryClient } from "../client.ts"; +import type { ClientOptions } from "../connection/connection_params.ts"; import { Oid } from "../query/oid.ts"; function withClient( @@ -34,7 +35,7 @@ function withClient( async function poolWrapper() { const pool = new Pool(getMainConfiguration(config), 1); - let client; + let client: PoolClient | undefined; try { client = await pool.connect(); await t(client); @@ -65,7 +66,8 @@ function withClientGenerator( clients.push(client); client_count++; return client; - } else throw new Error("Max client size exceeded"); + } + throw new Error("Max client size exceeded"); }); } finally { for (const client of clients) { @@ -211,9 +213,9 @@ Deno.test( return new Date(d.setDate(d.getDate() + 2)); }, // multiply by 100 - 5 = 785 - float4: (value: string) => parseFloat(value) * 100 - 5, + float4: (value: string) => Number.parseFloat(value) * 100 - 5, // convert to int and add 100 = 200 - [Oid.int4]: (value: string) => parseInt(value, 10) + 100, + [Oid.int4]: (value: string) => Number.parseInt(value, 10) + 100, // parse with multiple conditions jsonb: (value: string) => { const obj = JSON.parse(value); @@ -294,15 +296,15 @@ Deno.test( return new Date(d.setDate(d.getDate() + 10)); }, // multiply by 20, should not be used! - float4: (value: string) => parseFloat(value) * 20, + float4: (value: string) => Number.parseFloat(value) * 20, // multiply by 10 float4_array: (value: string, _, parseArray) => - parseArray(value, (v) => parseFloat(v) * 10), + parseArray(value, (v) => Number.parseFloat(v) * 10), // return 0, should not be used! [Oid.int4]: () => 0, // add 100 [Oid.int4_array]: (value: string, _, parseArray) => - parseArray(value, (v) => parseInt(v, 10) + 100), + parseArray(value, (v) => Number.parseInt(v, 10) + 100), // split string and reverse, should not be used! [Oid.text]: (value: string) => value.split("").reverse(), // 1009 = text_array : append "_!" to each string @@ -596,7 +598,7 @@ Deno.test( const item_1 = "Test;Azer"; const item_2 = "123;456"; - const { rows: result_1 } = await client.queryArray(`SELECT ARRAY[$1, $2]`, [ + const { rows: result_1 } = await client.queryArray("SELECT ARRAY[$1, $2]", [ item_1, item_2, ]); @@ -705,7 +707,7 @@ Deno.test( ); const { rows: result } = await client.queryObject<{ res: number }>({ - text: `SELECT 1`, + text: "SELECT 1", fields: ["res"], }); assertEquals(result[0].res, 1); @@ -820,7 +822,7 @@ Deno.test( await client .queryArray`INSERT INTO METADATA VALUES (100), (200), (300), (400), (500), (600)`; - let result; + let result: QueryResult; // simple select result = await client.queryArray( @@ -1087,7 +1089,7 @@ Deno.test( Deno.test( "Object query throws when multiple query results don't have the same number of rows", - withClient(async function (client) { + withClient(async (client) => { await assertRejects( () => client.queryObject<{ result: number }>({ diff --git a/tests/utils_test.ts b/tests/utils_test.ts index fe12b23f..683e7aa7 100644 --- a/tests/utils_test.ts +++ b/tests/utils_test.ts @@ -1,5 +1,6 @@ import { assertEquals, assertThrows } from "@std/assert"; -import { parseConnectionUri, Uri } from "../utils/utils.ts"; +import type { Uri } from "../utils/utils.ts"; +import { parseConnectionUri } from "../utils/utils.ts"; import { DeferredAccessStack, DeferredStack } from "../utils/deferred.ts"; class LazilyInitializedObject { @@ -67,7 +68,7 @@ const dns_examples: Partial[] = [ }, ]; -Deno.test("Parses connection string into config", async function (context) { +Deno.test("Parses connection string into config", async (context) => { for ( const { driver, @@ -136,7 +137,7 @@ Deno.test("Throws on invalid parameters", () => { ); }); -Deno.test("Parses connection string params into param object", function () { +Deno.test("Parses connection string params into param object", () => { const params = { param_1: "asd", param_2: "xyz", diff --git a/tools/convert_to_jsr.ts b/tools/convert_to_jsr.ts deleted file mode 100644 index 9843f572..00000000 --- a/tools/convert_to_jsr.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { walk } from "https://deno.land/std@0.214.0/fs/walk.ts"; -import denoConfig from "../deno.json" with { type: "json" }; - -const STD_SPECIFIER_REGEX = - /https:\/\/deno\.land\/std@(\d+\.\d+\.\d+)\/(\w+)\/(.+)\.ts/g; -const POSTGRES_X_SPECIFIER = "https://deno.land/x/postgres/mod.ts"; -const POSTGRES_JSR_SPECIFIER = `jsr:${denoConfig.name}`; - -function toStdJsrSpecifier( - _full: string, - _version: string, - module: string, - path: string, -): string { - /** - * @todo(iuioiua) Restore the dynamic use of the `version` argument - * once 0.214.0 is released. - */ - const version = "0.213.1"; - return path === "mod" - ? `jsr:@std/${module}@${version}` - : `jsr:@std/${module}@${version}/${path}`; -} - -for await ( - const entry of walk(".", { - includeDirs: false, - exts: [".ts", ".md"], - skip: [/docker/, /.github/, /tools/], - followSymlinks: false, - }) -) { - const text = await Deno.readTextFile(entry.path); - const newText = text - .replaceAll(STD_SPECIFIER_REGEX, toStdJsrSpecifier) - .replaceAll(POSTGRES_X_SPECIFIER, POSTGRES_JSR_SPECIFIER); - await Deno.writeTextFile(entry.path, newText); -} diff --git a/utils/deferred.ts b/utils/deferred.ts index f4b4c10a..b71c1aef 100644 --- a/utils/deferred.ts +++ b/utils/deferred.ts @@ -22,7 +22,8 @@ export class DeferredStack { async pop(): Promise { if (this.#elements.length > 0) { return this.#elements.pop()!; - } else if (this.#size < this.#max_size && this.#creator) { + } + if (this.#size < this.#max_size && this.#creator) { this.#size++; return await this.#creator(); } diff --git a/utils/utils.ts b/utils/utils.ts index f25550cf..f0280fb7 100644 --- a/utils/utils.ts +++ b/utils/utils.ts @@ -93,7 +93,7 @@ export function parseConnectionUri(uri: string): Uri { } } catch (_e) { console.error( - bold(yellow("Failed to decode URL host") + "\nDefaulting to raw host"), + bold(`${yellow("Failed to decode URL host")}\nDefaulting to raw host`), ); } @@ -108,8 +108,9 @@ export function parseConnectionUri(uri: string): Uri { } catch (_e) { console.error( bold( - yellow("Failed to decode URL password") + - "\nDefaulting to raw password", + `${ + yellow("Failed to decode URL password") + }\nDefaulting to raw password`, ), ); } From 6cfdd934878972b50cc965f2ca02399a4c867b7c Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Wed, 7 Aug 2024 17:26:05 +1000 Subject: [PATCH 3/5] bump version --- deno.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno.json b/deno.json index 36fa0e44..9a18d7d3 100644 --- a/deno.json +++ b/deno.json @@ -1,7 +1,7 @@ { "lock": false, "name": "@bartlomieju/postgres", - "version": "0.19.3", + "version": "0.20.0", "exports": "./mod.ts", "imports": { "@std/assert": "jsr:@std/assert@^1.0.2", From 1f57140a83c9f4a2f02dba4f21ad9307c488574c Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Wed, 7 Aug 2024 17:34:05 +1000 Subject: [PATCH 4/5] more lints --- connection/connection_params.ts | 6 ++-- query/decode.ts | 22 +++++++------- query/decoders.ts | 52 +++++++++++++++++---------------- query/encode.ts | 15 ++++++---- query/query.ts | 4 +-- query/transaction.ts | 27 +++++++---------- 6 files changed, 62 insertions(+), 64 deletions(-) diff --git a/connection/connection_params.ts b/connection/connection_params.ts index b192f270..0d718c9a 100644 --- a/connection/connection_params.ts +++ b/connection/connection_params.ts @@ -1,9 +1,9 @@ import { parseConnectionUri } from "../utils/utils.ts"; import { ConnectionParamsError } from "../client/error.ts"; import { fromFileUrl, isAbsolute } from "@std/path"; -import { OidType } from "../query/oid.ts"; -import { DebugControls } from "../debug.ts"; -import { ParseArrayFunction } from "../query/array_parser.ts"; +import type { OidType } from "../query/oid.ts"; +import type { DebugControls } from "../debug.ts"; +import type { ParseArrayFunction } from "../query/array_parser.ts"; /** * The connection string must match the following URI structure. All parameters but database and user are optional diff --git a/query/decode.ts b/query/decode.ts index 2a1e2a96..1602d570 100644 --- a/query/decode.ts +++ b/query/decode.ts @@ -1,5 +1,6 @@ import { bold, yellow } from "@std/fmt/colors"; -import { Oid, OidType, OidTypes, OidValue } from "./oid.ts"; +import type { OidType, OidValue } from "./oid.ts"; +import { Oid, OidTypes } from "./oid.ts"; import { decodeBigint, decodeBigintArray, @@ -35,7 +36,7 @@ import { decodeTid, decodeTidArray, } from "./decoders.ts"; -import { ClientControls } from "../connection/connection_params.ts"; +import type { ClientControls } from "../connection/connection_params.ts"; import { parseArray } from "./array_parser.ts"; export class Column { @@ -198,10 +199,9 @@ function decodeText(value: string, typeOid: number) { } } catch (_e) { console.error( - bold(yellow(`Error decoding type Oid ${typeOid} value`)) + - _e.message + - "\n" + - bold("Defaulting to null."), + `${ + bold(yellow(`Error decoding type Oid ${typeOid} value`)) + }${_e.message}\n${bold("Defaulting to null.")}`, ); // If an error occurred during decoding, return null return null; @@ -224,9 +224,9 @@ export function decode( if (decoderFunc) { return decoderFunc(strValue, column.typeOid, parseArray); - } // if no custom decoder is found and the oid is for an array type, check if there is + } // a decoder for the base type and use that with the array parser - else if (oidType?.includes("_array")) { + if (oidType?.includes("_array")) { const baseOidType = oidType.replace("_array", "") as OidType; // check if the base type is in the Oid object if (baseOidType in Oid) { @@ -251,9 +251,9 @@ export function decode( // else, default to 'auto' mode, which uses the typeOid to determine the decoding strategy if (column.format === Format.BINARY) { return decodeBinary(); - } else if (column.format === Format.TEXT) { + } + if (column.format === Format.TEXT) { return decodeText(strValue, column.typeOid); - } else { - throw new Error(`Unknown column format: ${column.format}`); } + throw new Error(`Unknown column format: ${column.format}`); } diff --git a/query/decoders.ts b/query/decoders.ts index b1acc8a9..ec25e57b 100644 --- a/query/decoders.ts +++ b/query/decoders.ts @@ -75,9 +75,8 @@ export function decodeBoxArray(value: string) { export function decodeBytea(byteaStr: string): Uint8Array { if (HEX_PREFIX_REGEX.test(byteaStr)) { return decodeByteaHex(byteaStr); - } else { - return decodeByteaEscape(byteaStr); } + return decodeByteaEscape(byteaStr); } export function decodeByteaArray(value: string) { @@ -94,7 +93,7 @@ function decodeByteaEscape(byteaStr: string): Uint8Array { ++i; } else { if (/[0-7]{3}/.test(byteaStr.substr(i + 1, 3))) { - bytes.push(parseInt(byteaStr.substr(i + 1, 3), 8)); + bytes.push(Number.parseInt(byteaStr.substr(i + 1, 3), 8)); i += 4; } else { let backslashes = 1; @@ -118,7 +117,7 @@ function decodeByteaHex(byteaStr: string): Uint8Array { const bytesStr = byteaStr.slice(2); const bytes = new Uint8Array(bytesStr.length / 2); for (let i = 0, j = 0; i < bytesStr.length; i += 2, j++) { - bytes[j] = parseInt(bytesStr[i] + bytesStr[i + 1], HEX); + bytes[j] = Number.parseInt(bytesStr[i] + bytesStr[i + 1], HEX); } return bytes; } @@ -128,7 +127,7 @@ export function decodeCircle(value: string): Circle { .substring(1, value.length - 1) .split(/,(?![^(]*\))/) as [string, Float8]; - if (Number.isNaN(parseFloat(radius))) { + if (Number.isNaN(Number.parseFloat(radius))) { throw new Error( `Invalid Circle: "${value}". Circle radius "${radius}" must be a valid number.`, ); @@ -152,9 +151,10 @@ export function decodeDate(dateStr: string): Date | number { // there are special `infinity` and `-infinity` // cases representing out-of-range dates if (dateStr === "infinity") { - return Number(Infinity); - } else if (dateStr === "-infinity") { - return Number(-Infinity); + return Number(Number.POSITIVE_INFINITY); + } + if (dateStr === "-infinity") { + return Number(Number.NEGATIVE_INFINITY); } return parseDate(dateStr, "yyyy-MM-dd"); @@ -178,16 +178,16 @@ export function decodeDatetime(dateStr: string): number | Date { const isBC = BC_RE.test(dateStr); - const year = parseInt(matches[1], 10) * (isBC ? -1 : 1); + const year = Number.parseInt(matches[1], 10) * (isBC ? -1 : 1); // remember JS dates are 0-based - const month = parseInt(matches[2], 10) - 1; - const day = parseInt(matches[3], 10); - const hour = parseInt(matches[4], 10); - const minute = parseInt(matches[5], 10); - const second = parseInt(matches[6], 10); + const month = Number.parseInt(matches[2], 10) - 1; + const day = Number.parseInt(matches[3], 10); + const hour = Number.parseInt(matches[4], 10); + const minute = Number.parseInt(matches[5], 10); + const second = Number.parseInt(matches[6], 10); // ms are written as .007 const msMatch = matches[7]; - const ms = msMatch ? 1000 * parseFloat(msMatch) : 0; + const ms = msMatch ? 1000 * Number.parseFloat(msMatch) : 0; let date: Date; @@ -213,7 +213,7 @@ export function decodeDatetimeArray(value: string) { } export function decodeInt(value: string): number { - return parseInt(value, 10); + return Number.parseInt(value, 10); } export function decodeIntArray(value: string) { @@ -221,7 +221,7 @@ export function decodeIntArray(value: string) { } export function decodeFloat(value: string): number { - return parseFloat(value); + return Number.parseFloat(value); } export function decodeFloatArray(value: string) { @@ -249,13 +249,13 @@ export function decodeLine(value: string): Line { ); } - equationConsts.forEach((c) => { - if (Number.isNaN(parseFloat(c))) { + for (const c of equationConsts) { + if (Number.isNaN(Number.parseFloat(c))) { throw new Error( `Invalid Line: "${value}". Line constant "${c}" must be a valid number.`, ); } - }); + } const [a, b, c] = equationConsts; @@ -326,10 +326,12 @@ export function decodePoint(value: string): Point { const [x, y] = coordinates; - if (Number.isNaN(parseFloat(x)) || Number.isNaN(parseFloat(y))) { + if ( + Number.isNaN(Number.parseFloat(x)) || Number.isNaN(Number.parseFloat(y)) + ) { throw new Error( `Invalid Point: "${value}". Coordinate "${ - Number.isNaN(parseFloat(x)) ? x : y + Number.isNaN(Number.parseFloat(x)) ? x : y }" must be a valid number.`, ); } @@ -393,9 +395,9 @@ function decodeTimezoneOffset(dateStr: string): null | number { // offsets and vice-versa const sign = type === "-" ? 1 : -1; - const hours = parseInt(matches[2], 10); - const minutes = parseInt(matches[3] || "0", 10); - const seconds = parseInt(matches[4] || "0", 10); + const hours = Number.parseInt(matches[2], 10); + const minutes = Number.parseInt(matches[3] || "0", 10); + const seconds = Number.parseInt(matches[4] || "0", 10); const offset = hours * 3600 + minutes * 60 + seconds; diff --git a/query/encode.ts b/query/encode.ts index 36407bf2..d77f104a 100644 --- a/query/encode.ts +++ b/query/encode.ts @@ -91,15 +91,18 @@ export type EncodedArg = null | string | Uint8Array; export function encodeArgument(value: unknown): EncodedArg { if (value === null || typeof value === "undefined") { return null; - } else if (value instanceof Uint8Array) { + } + if (value instanceof Uint8Array) { return encodeBytes(value); - } else if (value instanceof Date) { + } + if (value instanceof Date) { return encodeDate(value); - } else if (value instanceof Array) { + } + if (Array.isArray(value)) { return encodeArray(value); - } else if (value instanceof Object) { + } + if (value instanceof Object) { return JSON.stringify(value); - } else { - return String(value); } + return String(value); } diff --git a/query/query.ts b/query/query.ts index 58977459..ba02a5d9 100644 --- a/query/query.ts +++ b/query/query.ts @@ -1,7 +1,7 @@ import { encodeArgument, type EncodedArg } from "./encode.ts"; import { type Column, decode } from "./decode.ts"; -import { type Notice } from "../connection/message.ts"; -import { type ClientControls } from "../connection/connection_params.ts"; +import type { Notice } from "../connection/message.ts"; +import type { ClientControls } from "../connection/connection_params.ts"; // TODO // Limit the type of parameters that can be passed diff --git a/query/transaction.ts b/query/transaction.ts index 3dadd33a..f198f648 100644 --- a/query/transaction.ts +++ b/query/transaction.ts @@ -1,4 +1,4 @@ -import { type QueryClient } from "../client.ts"; +import type { QueryClient } from "../client.ts"; import { Query, type QueryArguments, @@ -218,7 +218,7 @@ export class Transaction { ); } - let isolation_level; + let isolation_level: string; switch (this.#isolation_level) { case "read_committed": { isolation_level = "READ COMMITTED"; @@ -238,7 +238,7 @@ export class Transaction { ); } - let permissions; + let permissions: string; if (this.#read_only) { permissions = "READ ONLY"; } else { @@ -257,9 +257,8 @@ export class Transaction { } catch (e) { if (e instanceof PostgresError) { throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } this.#updateClientLock(this.name); @@ -312,9 +311,8 @@ export class Transaction { } catch (e) { if (e instanceof PostgresError) { throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } } @@ -467,9 +465,8 @@ export class Transaction { if (e instanceof PostgresError) { await this.commit(); throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } } @@ -565,9 +562,8 @@ export class Transaction { if (e instanceof PostgresError) { await this.commit(); throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } } @@ -701,9 +697,8 @@ export class Transaction { if (e instanceof PostgresError) { await this.commit(); throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } this.#resetTransaction(); @@ -792,9 +787,8 @@ export class Transaction { if (e instanceof PostgresError) { await this.commit(); throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } } else { savepoint = new Savepoint( @@ -813,9 +807,8 @@ export class Transaction { if (e instanceof PostgresError) { await this.commit(); throw new TransactionError(this.name, e); - } else { - throw e; } + throw e; } this.#savepoints.push(savepoint); } From d92d4a36d2fcace59e8423eb063a55163e94dd8b Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Sat, 10 Aug 2024 16:15:32 +1000 Subject: [PATCH 5/5] Fix broken comment --- query/decode.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/query/decode.ts b/query/decode.ts index 1602d570..1e7d96f1 100644 --- a/query/decode.ts +++ b/query/decode.ts @@ -225,6 +225,7 @@ export function decode( if (decoderFunc) { return decoderFunc(strValue, column.typeOid, parseArray); } + // if no custom decoder is found and the oid is for an array type, check if there is // a decoder for the base type and use that with the array parser if (oidType?.includes("_array")) { const baseOidType = oidType.replace("_array", "") as OidType;