From 5d5e5a6846a8f0a51954aaa557b8b1351c483a1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 03:33:21 +0000 Subject: [PATCH 1/2] chore: bump the npm-development group with 2 updates Bumps the npm-development group with 2 updates: [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) and [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node). Updates `@biomejs/biome` from 2.5.8 to 2.5.11 - [Release notes](https://github.com/biomejs/biome/releases) - [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md) - [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.5.11/packages/@biomejs/biome) Updates `@types/node` from 26.2.0 to 26.4.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@biomejs/biome" dependency-version: 2.5.11 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-development - dependency-name: "@types/node" dependency-version: 26.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-development ... Signed-off-by: dependabot[bot] --- package-lock.json | 80 +++++++++++++++++++++++------------------------ package.json | 4 +-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1744190..0b45605 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "testcontainers": "12.1.0" }, "devDependencies": { - "@biomejs/biome": "2.5.8", - "@types/node": "26.2.0", + "@biomejs/biome": "2.5.11", + "@types/node": "26.4.0", "get-port": "7.2.0", "tsx": "4.23.12", "typescript": "7.0.2" @@ -26,9 +26,9 @@ "license": "Apache-2.0" }, "node_modules/@biomejs/biome": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.8.tgz", - "integrity": "sha512-aeAeeJB9fSDc7Gq+2GqpQxA0qBj6gj1k2R6L1cYqGePKP/baIq1WX8y6B+D+nRsO5ViQL22K/8IwbqERW0q1nw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.11.tgz", + "integrity": "sha512-Tj0dnkLPdW0ASjHfj2D/ZkkvPU2wrFmnE1jWTD2xzV1ycapV1DutbYXk4NDnR3rYTi1ZCbNFD4G2gRMEY65WaA==", "dev": true, "license": "MIT OR Apache-2.0", "bin": { @@ -42,20 +42,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.5.8", - "@biomejs/cli-darwin-x64": "2.5.8", - "@biomejs/cli-linux-arm64": "2.5.8", - "@biomejs/cli-linux-arm64-musl": "2.5.8", - "@biomejs/cli-linux-x64": "2.5.8", - "@biomejs/cli-linux-x64-musl": "2.5.8", - "@biomejs/cli-win32-arm64": "2.5.8", - "@biomejs/cli-win32-x64": "2.5.8" + "@biomejs/cli-darwin-arm64": "2.5.11", + "@biomejs/cli-darwin-x64": "2.5.11", + "@biomejs/cli-linux-arm64": "2.5.11", + "@biomejs/cli-linux-arm64-musl": "2.5.11", + "@biomejs/cli-linux-x64": "2.5.11", + "@biomejs/cli-linux-x64-musl": "2.5.11", + "@biomejs/cli-win32-arm64": "2.5.11", + "@biomejs/cli-win32-x64": "2.5.11" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.8.tgz", - "integrity": "sha512-mk1QON9PHllvvLN5gU3f4rMxeh4syK5p9OvKyWH6/W8ueh04uaC8TUXXByhGufWf/y5mQc03ZLM45zU+cmqMjA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.11.tgz", + "integrity": "sha512-6SGZxoKbXvUjMn1t6A98HqWISPnGNbYs0R/Rt2JarmXBSev+lva4QxUMWEBX9lX1Wo1XTJ78uk5xVDtG58SRZg==", "cpu": [ "arm64" ], @@ -70,9 +70,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.8.tgz", - "integrity": "sha512-bsGwFMBNyHPyiLSsQcZJxdoRrg1V4JL+d7wEsvUBczlP9U9lwM+7mzQHxI4o1mhBsTmdOBbAb6fHU3Z3snN45w==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.11.tgz", + "integrity": "sha512-nYkXY7tLBEgnGbYapDKAyKzgt44ZEyG+AKalvTXtCWKYgepI9dw327q+cVgedxm+Udi1ZzHKUyZrIusHi/KQbw==", "cpu": [ "x64" ], @@ -87,9 +87,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.8.tgz", - "integrity": "sha512-XmFiA0WPYFC+uiUDC8WRFzAIH9bo7vwQLav38Uoq4ETC+T/+uBi0TsYGJECkugY3r8USl3jc+Ae2/irAF6F2lQ==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.11.tgz", + "integrity": "sha512-3PVLSTD9RR73rvVPt5G3T1gc+ycggWEGfTD7RvzzbtcDPD27NxgxBbAFfpm7DXJKW6VLHWE1lLMGvFt2Qxjcow==", "cpu": [ "arm64" ], @@ -107,9 +107,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.8.tgz", - "integrity": "sha512-VcJNbstduTHx83NGAdhp78/JOcP45BZHXL7yNsfI1uGzdUgegAz2s+mSoT7wK6PBNzLoqG0zDOXaz/RQYVtSiw==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.11.tgz", + "integrity": "sha512-qhyZUMyCbWYFV2bAwRNVvfMVZ+hv7WYl6mossGrxC+uiQQXhvsuWWU8zz6jYX0mChZd9MgQZbm4vozTmG/5iGw==", "cpu": [ "arm64" ], @@ -127,9 +127,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.8.tgz", - "integrity": "sha512-S5wcm9OBDvLHodD4PUaN488hCpco9QD/9ZxuYJiw4euWtr/oQvLR72z2ixItH8Wd5BCm6FZaeb+YNvOoM1xHtQ==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.11.tgz", + "integrity": "sha512-JOytptlsgM33B2MMFUg8iBrb4IKpbD5JnJrSeYiaFEeAj4vuXx0iQSQZ4qK7sqyMtfjZxxPdNdMZZVL4y/mFyA==", "cpu": [ "x64" ], @@ -147,9 +147,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.8.tgz", - "integrity": "sha512-kKmiyokeISRGq2FLwvr+TzsgBusfxaZ0FZNLcOYOpCK/78tRrEjeEBLvq3xLZMpqbANgJdRPI7vZX8ZL37u9/w==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.11.tgz", + "integrity": "sha512-oRRlrchG5EfrEL/EmtT1qUjSNHk3/5LGeZhQqADBBAJF1b1ET6964xEKe7aGlGARzDfza8H/seEsFJl7S6Ql9w==", "cpu": [ "x64" ], @@ -167,9 +167,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.8.tgz", - "integrity": "sha512-nILH0mzm3Hi3iEdd7o7GpB8kBR/mSQwfQG/tyBqyNrY2GFtcgwfV9nV8xLmbtUpMNY/Oi0Ml1XgfR4flOdq+AA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.11.tgz", + "integrity": "sha512-e49E6K9hzH/ohJNx8Y26mY8HaV4I4ZViIeoqhKsmoXLKHhQnMeBAVqCgsGf2Wa3lXlS7RkporDXMHHWkzvZzFw==", "cpu": [ "arm64" ], @@ -184,9 +184,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.8.tgz", - "integrity": "sha512-I2czzXTY61f3nFJxXoMDq80t7MivxDEnCjE+8sDKoFfcKMaoQdkqhIFQ3KyY0XLzeSpUBYeNAXgD+iOV/BU0VA==", + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.11.tgz", + "integrity": "sha512-QSQr/KjOgXA7OzXJUWS+oguKyAZ3Q0l/lnlDGbu397eKo83atuWUjBPJrsqbKNF6CARGw8XXJLGzpHC8Ryhd4Q==", "cpu": [ "x64" ], @@ -816,9 +816,9 @@ } }, "node_modules/@types/node": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", - "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.0.tgz", + "integrity": "sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==", "license": "MIT", "dependencies": { "undici-types": "~8.3.0" diff --git a/package.json b/package.json index 4b9dfa3..ba9360d 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ "testcontainers": "12.1.0" }, "devDependencies": { - "@biomejs/biome": "2.5.8", - "@types/node": "26.2.0", + "@biomejs/biome": "2.5.11", + "@types/node": "26.4.0", "get-port": "7.2.0", "tsx": "4.23.12", "typescript": "7.0.2" From 76baa2db4129ed1aa24c46504ec67639f7c0cba8 Mon Sep 17 00:00:00 2001 From: Golo Roden Date: Sat, 5 Sep 2026 22:09:36 +0200 Subject: [PATCH 2/2] chore: Say what these types are instead of asserting them. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Biome 2.5.11 adds `noUnsafeTypeAssertion`, which reports seven casts. None are suppressed; each one had a way to state the same thing that the compiler can check. In hasShapeOf: - `shape[key] as unknown` was a widening cast — it can hide nothing by construction, and an annotation says it plainly: `const spec: unknown = …`. - `Object.keys(shape) as Array` and `value[key as string]` both fall out of iterating `Object.entries(shape)`, where the key is a string already and the value comes along with it. - `spec as Guard<…>` and `spec as Shape<…>` become the predicates `isGuard` and `isShape`, which is the pattern this directory already uses for isRecord and isString. The recursive call no longer passes `Extract` explicitly; its result is only read as a boolean, and the outer `value is T` is unaffected. In runEventQlQuery.test.ts, two rows were cast to `any` to read their fields. `assert.ok(isRecord(row))` narrows them instead, so the test now checks the shape it was previously casting away — and the two existing noExplicitAny suppressions are no longer needed either. `npm run qa` passes: tsc, biome with --error-on-warnings, and all 64 tests against real containers. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01X8dhqV77bgg5oT5pVQdi5y --- src/runEventQlQuery.test.ts | 11 +++++++---- src/types/hasShapeOf.ts | 23 +++++++++-------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/runEventQlQuery.test.ts b/src/runEventQlQuery.test.ts index 13a7b25..0b98b82 100644 --- a/src/runEventQlQuery.test.ts +++ b/src/runEventQlQuery.test.ts @@ -3,6 +3,7 @@ import { afterEach, beforeEach, suite, test } from 'node:test'; import { Container } from './Container.js'; import type { EventCandidate } from './EventCandidate.js'; import { getImageVersionFromDockerfile } from './getImageVersionFromDockerfile.js'; +import { isRecord } from './types/isRecord.js'; suite('runEventQlQuery', { timeout: 30_000 }, () => { let container: Container; @@ -58,14 +59,16 @@ suite('runEventQlQuery', { timeout: 30_000 }, () => { assert.equal(rowsRead.length, 2); - // biome-ignore lint/suspicious/noExplicitAny: Here, the cast is okay. - const firstRow = rowsRead[0] as any; + const firstRow = rowsRead[0]; + assert.ok(isRecord(firstRow)); assert.equal(firstRow.id, '0'); + assert.ok(isRecord(firstRow.data)); assert.equal(firstRow.data.value, 23); - // biome-ignore lint/suspicious/noExplicitAny: Here, the cast is okay. - const secondRow = rowsRead[1] as any; + const secondRow = rowsRead[1]; + assert.ok(isRecord(secondRow)); assert.equal(secondRow.id, '1'); + assert.ok(isRecord(secondRow.data)); assert.equal(secondRow.data.value, 42); }); diff --git a/src/types/hasShapeOf.ts b/src/types/hasShapeOf.ts index dca529a..a69c43c 100644 --- a/src/types/hasShapeOf.ts +++ b/src/types/hasShapeOf.ts @@ -6,35 +6,30 @@ type Shape = { [K in keyof T]: T[K] extends object ? Shape | Guard : Guard; }; +const isGuard = (value: unknown): value is Guard => typeof value === 'function'; +const isShape = (value: unknown): value is Shape => isRecord(value); + const hasShapeOf = (value: unknown, shape: Shape): value is T => { if (!isRecord(value)) { return false; } - for (const key of Object.keys(shape) as Array) { - const spec = shape[key] as unknown; - const val = value[key as string]; - - if (typeof spec === 'function') { - const guard = spec as Guard; + for (const [key, spec] of Object.entries(shape)) { + const val = value[key]; - if (!guard(val)) { + if (isGuard(spec)) { + if (!spec(val)) { return false; } continue; } - if (!isRecord(val)) { + if (!(isRecord(val) && isShape(spec))) { return false; } - if ( - !hasShapeOf>( - val, - spec as Shape>, - ) - ) { + if (!hasShapeOf(val, spec)) { return false; } }