Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
- run: yarn run format:check
if: runner.os == 'Linux'
- run: yarn run build
- run: yarn run test
# Sanity-check `npm pack` only once (Linux + Node 24) to avoid
# 6-way artifact-name collisions; lint/build coverage is what
# the cross-OS matrix is actually for.
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
"build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
"typecheck": "vue-tsc --noEmit",
"lint": "eslint src demo",
"test": "tsx --test tests/*.test.ts",
"quality": "scoria",
"format": "prettier --write \"{src,demo}/**/*.{ts,tsx,vue,json,css}\" \"*.{ts,js,json}\"",
"format:check": "prettier --check \"{src,demo}/**/*.{ts,tsx,vue,json,css}\" \"*.{ts,js,json}\""
"format": "prettier --write \"{src,demo,tests}/**/*.{ts,tsx,vue,json,css}\" \"*.{ts,js,json}\"",
"format:check": "prettier --check \"{src,demo,tests}/**/*.{ts,tsx,vue,json,css}\" \"*.{ts,js,json}\""
},
"peerDependencies": {
"gui-chat-protocol": "^2.3.0",
Expand All @@ -53,6 +54,7 @@
"prettier": "^3.9.10",
"scoria": "^0.4.1",
"tailwindcss": "^4.3.3",
"tsx": "^4.23.15",
"typescript": "~6.0.3",
"vite": "^8.3.4",
"vue": "^3.5.44",
Expand Down
11 changes: 11 additions & 0 deletions plans/fix-35-move-position-bounds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# #35 — reject off-board and fractional move coordinates

`isLegalMove` indexed `board[row][col]` before checking the position, so a negative or fractional `row` threw a `TypeError` instead of producing the invalid-move response.

## How
- `src/core/position.ts`: `isOnBoard(row, col, size)` — both are whole numbers inside the board. Pure, so it is tested on its own.
- `isInBounds` delegates to it, and `isLegalMove` checks it before reading the board.
- `tests/position.test.ts` covers the check in both directions and `playGo` with off-board and fractional moves. Run with `yarn test`, the same `tsx --test` setup the other plugins use; CI now runs it.

## Left out
- Validating the shape of a caller-supplied `board`.
7 changes: 4 additions & 3 deletions src/core/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import type { Cell, Side, GoBoard, Command, GoState } from "./types";
import { isOnBoard } from "./position";

const BOARD_SIZE = 9;

Expand All @@ -16,7 +17,7 @@
function createEmptyBoard(): GoBoard {
const board: GoBoard = [];
for (let i = 0; i < BOARD_SIZE; i++) {
board[i] = new Array(BOARD_SIZE).fill(".") as Cell[];

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, ubuntu-latest)

Do not use any type assertions

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, windows-latest)

Do not use any type assertions

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, windows-latest)

Do not use any type assertions

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, ubuntu-latest)

Do not use any type assertions

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, macos-latest)

Do not use any type assertions

Check warning on line 20 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, macos-latest)

Do not use any type assertions
}
return board;
}
Expand All @@ -26,7 +27,7 @@
}

function isInBounds(row: number, col: number): boolean {
return row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE;
return isOnBoard(row, col, BOARD_SIZE);
}

function getOpponent(side: Side): Side {
Expand All @@ -42,7 +43,7 @@
const stack: { row: number; col: number }[] = [{ row, col }];

while (stack.length > 0) {
const pos = stack.pop()!;

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, ubuntu-latest)

Forbidden non-null assertion

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, windows-latest)

Forbidden non-null assertion

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, windows-latest)

Forbidden non-null assertion

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, ubuntu-latest)

Forbidden non-null assertion

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, macos-latest)

Forbidden non-null assertion

Check warning on line 46 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, macos-latest)

Forbidden non-null assertion
const r = pos.row;
const c = pos.col;

Expand Down Expand Up @@ -103,8 +104,8 @@

// Check if a move is legal (not suicide rule)
function isLegalMove(board: GoBoard, row: number, col: number, side: Side): boolean {
// Position must be empty
if (board[row][col] !== ".") {
// Position must be on the board and empty
if (!isInBounds(row, col) || board[row][col] !== ".") {
return false;
}

Expand Down Expand Up @@ -174,7 +175,7 @@
const adjacentColors = new Set<Cell>();

while (stack.length > 0) {
const pos = stack.pop()!;

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, ubuntu-latest)

Forbidden non-null assertion

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, windows-latest)

Forbidden non-null assertion

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, windows-latest)

Forbidden non-null assertion

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, ubuntu-latest)

Forbidden non-null assertion

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (24.x, macos-latest)

Forbidden non-null assertion

Check warning on line 178 in src/core/logic.ts

View workflow job for this annotation

GitHub Actions / lint_test (26.x, macos-latest)

Forbidden non-null assertion
const r = pos.row;
const c = pos.col;

Expand Down
4 changes: 4 additions & 0 deletions src/core/position.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** Whether (row, col) names a square of a size×size board: whole numbers, inside it. */
export function isOnBoard(row: number, col: number, size: number): boolean {
return [row, col].every((index) => Number.isInteger(index) && index >= 0 && index < size);
}
62 changes: 62 additions & 0 deletions tests/position.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { test, describe } from "node:test";
import assert from "node:assert";
import { isOnBoard } from "../src/core/position.js";
import { playGo } from "../src/core/logic.js";
import type { GoBoard } from "../src/core/types.js";

const SIZE = 9;
const emptyBoard = (): GoBoard => Array.from({ length: SIZE }, () => Array.from({ length: SIZE }, () => "."));
const moveTo = (row: number, col: number) =>
playGo({ action: "move", row, col, board: emptyBoard(), currentSide: "B", playerNames: { B: "user", W: "computer" }, capturedStones: { B: 0, W: 0 } });

describe("isOnBoard", () => {
test("accepts every square, corners included", () => {
[0, SIZE - 1].forEach((row) => [0, SIZE - 1].forEach((col) => assert.equal(isOnBoard(row, col, SIZE), true)));
assert.equal(isOnBoard(4, 4, SIZE), true);
});

test("rejects positions just outside each edge", () => {
[
[-1, 0],
[0, -1],
[SIZE, 0],
[0, SIZE],
].forEach(([row, col]) => assert.equal(isOnBoard(row, col, SIZE), false));
});

test("rejects values that are not whole numbers", () => {
[0.5, Number.NaN, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, -0.5].forEach((value) => {
assert.equal(isOnBoard(value, 0, SIZE), false);
assert.equal(isOnBoard(0, value, SIZE), false);
});
});

test("rejects a non-number from an untyped caller", () => {
const fromJson: { row: number } = JSON.parse('{"row":"__proto__"}');
assert.equal(isOnBoard(fromJson.row, 0, SIZE), false);
});
});

describe("playGo move coordinates", () => {
test("a square on the board is played", () => {
const state = moveTo(4, 4);
assert.equal(state.error, undefined);
assert.equal(state.board[4][4], "B");
});

test("a square off the board or between squares is an invalid move, not a throw", () => {
[
[-1, 0],
[0, -1],
[SIZE, 0],
[0, SIZE],
[1.5, 0],
[0, 0.5],
[Number.NaN, 0],
].forEach(([row, col]) => {
const state = moveTo(row, col);
assert.match(state.error ?? "", /Invalid move/);
assert.deepEqual(state.board, emptyBoard());
});
});
});
171 changes: 171 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,136 @@
dependencies:
tslib "^2.4.0"

"@esbuild/aix-ppc64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz#bf6e10303bcf2e7c686975fa52f937ec2728d8bc"
integrity sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==

"@esbuild/android-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz#0c6246bc8d2c4d172aac2db3fb1190d72bd65504"
integrity sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==

"@esbuild/android-arm@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz#2d84ece6a4e2684d92be26ee13d42757d831c381"
integrity sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==

"@esbuild/android-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz#fc38d4d6358d8dc1cf53f09f7589fe436eb64801"
integrity sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==

"@esbuild/darwin-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz#f83afeeac1d7dac01c7a2fd012b3e451a0591fcc"
integrity sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==

"@esbuild/darwin-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz#510147c055a795588dbbe14fd6b1b8ad0a2f30de"
integrity sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==

"@esbuild/freebsd-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz#093b9200ecf0b115ba4e5e248a7485c9c5f8bd5e"
integrity sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==

"@esbuild/freebsd-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz#0be22b6df925d213e841ea87123af5df80b0faf7"
integrity sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==

"@esbuild/linux-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz#1bdbc651cda9ba9995c53ed9c71ceaa65094762d"
integrity sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==

"@esbuild/linux-arm@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz#beb12ad72b84f72d28488cc1b8ee9f7eb141d753"
integrity sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==

"@esbuild/linux-ia32@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz#b81f9d55529b45c206a46a138214b1aa6879696b"
integrity sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==

"@esbuild/linux-loong64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz#598667241a04c99b76ed6ef940ac50038c419f98"
integrity sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==

"@esbuild/linux-mips64el@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz#1c51eb9cea903f53d97b5af3b1841db70f5596ca"
integrity sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==

"@esbuild/linux-ppc64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz#63dd61f17ceb31a81227f413feac8a71bc2c51f2"
integrity sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==

"@esbuild/linux-riscv64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz#3763b08fde5cf25ab1facb8e7752edfe45fbfc27"
integrity sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==

"@esbuild/linux-s390x@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz#1a137ff293a82906eb3176385bd7e8e0e5cfb7cb"
integrity sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==

"@esbuild/linux-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz#268b36211c146ca54f8fe12c578a8d6ef8979485"
integrity sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==

"@esbuild/netbsd-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz#22571ad951d62bb6accc82d8d1fad5c8c1ac0ba1"
integrity sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==

"@esbuild/netbsd-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz#42fcc57297eb0a0ca3f5fc475291f4c1a3f7c0de"
integrity sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==

"@esbuild/openbsd-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz#9eb32af104ac3dacf4edca01f596664aab0c73ef"
integrity sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==

"@esbuild/openbsd-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz#febed2402d6088225e91f20fb4ce2522ad0a4efd"
integrity sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==

"@esbuild/openharmony-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz#85641c3d466428bfbccea5f21c26836663fef5ce"
integrity sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==

"@esbuild/sunos-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz#a736f9d8962481045fc4c3e54f5479f22c870fb4"
integrity sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==

"@esbuild/win32-arm64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz#ee5ab40fad186201b652a33f8a5eb149e9e42532"
integrity sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==

"@esbuild/win32-ia32@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz#c40d28a6d99a127da6711f2afd74b11cb63b06a7"
integrity sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==

"@esbuild/win32-x64@0.28.2":
version "0.28.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz#b21affb804cc167c133d95f45b3a1dc1323b9a87"
integrity sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==

"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1":
version "4.10.1"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz#8911bd72b2c3640a543609e0400b8c4d2e7e7cb6"
Expand Down Expand Up @@ -1515,6 +1645,38 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
dependencies:
es-errors "^1.3.0"

esbuild@~0.28.0:
version "0.28.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.2.tgz#0f43bd1bad955b72d24e2261e3abe5957ccf0816"
integrity sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==
optionalDependencies:
"@esbuild/aix-ppc64" "0.28.2"
"@esbuild/android-arm" "0.28.2"
"@esbuild/android-arm64" "0.28.2"
"@esbuild/android-x64" "0.28.2"
"@esbuild/darwin-arm64" "0.28.2"
"@esbuild/darwin-x64" "0.28.2"
"@esbuild/freebsd-arm64" "0.28.2"
"@esbuild/freebsd-x64" "0.28.2"
"@esbuild/linux-arm" "0.28.2"
"@esbuild/linux-arm64" "0.28.2"
"@esbuild/linux-ia32" "0.28.2"
"@esbuild/linux-loong64" "0.28.2"
"@esbuild/linux-mips64el" "0.28.2"
"@esbuild/linux-ppc64" "0.28.2"
"@esbuild/linux-riscv64" "0.28.2"
"@esbuild/linux-s390x" "0.28.2"
"@esbuild/linux-x64" "0.28.2"
"@esbuild/netbsd-arm64" "0.28.2"
"@esbuild/netbsd-x64" "0.28.2"
"@esbuild/openbsd-arm64" "0.28.2"
"@esbuild/openbsd-x64" "0.28.2"
"@esbuild/openharmony-arm64" "0.28.2"
"@esbuild/sunos-x64" "0.28.2"
"@esbuild/win32-arm64" "0.28.2"
"@esbuild/win32-ia32" "0.28.2"
"@esbuild/win32-x64" "0.28.2"

escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
Expand Down Expand Up @@ -3137,6 +3299,15 @@ tslib@^2.4.0, tslib@^2.8.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==

tsx@^4.23.15:
version "4.23.15"
resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.23.15.tgz#f53901695685ad567fed0f08532f7782e631c251"
integrity sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==
dependencies:
esbuild "~0.28.0"
optionalDependencies:
fsevents "~2.3.3"

type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
Expand Down
Loading