[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
5

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #43 from bombshell-dev/codspeed-wizard-1779643506234

Adds performance benchmarks with tinybench, benchmark CI via CodSpeed

authored by

Nate Moore and committed by
GitHub
(May 26, 2026, 5:46 PM EDT) c9fec361 819da8ee

+632 -22
+48
.github/workflows/benchmark.yml
··· 1 + name: Benchmark 2 + 3 + on: 4 + push: 5 + branches: [main] 6 + pull_request: 7 + branches: [main] 8 + # `workflow_dispatch` allows CodSpeed to trigger backtest 9 + # performance analysis in order to generate initial data. 10 + workflow_dispatch: 11 + 12 + permissions: 13 + contents: read 14 + id-token: write 15 + 16 + jobs: 17 + benchmarks: 18 + name: Run benchmarks 19 + runs-on: ubuntu-latest 20 + 21 + steps: 22 + - name: Checkout 23 + uses: actions/checkout@v4 24 + with: 25 + submodules: true 26 + 27 + - name: Setup Deno 28 + uses: denoland/setup-deno@v2 29 + with: 30 + deno-version: v2.x 31 + 32 + - name: Setup Node 33 + uses: actions/setup-node@v4 34 + with: 35 + node-version: 22 36 + 37 + - name: Build WASM 38 + run: make 39 + 40 + - name: Install dependencies 41 + run: deno install 42 + 43 + - name: Run benchmarks 44 + uses: CodSpeedHQ/action@v4 45 + with: 46 + mode: simulation 47 + # IMPORTANT! deno task bench fails in CI due to incompatible V8 bindings 48 + run: node bench/mod.ts
+22 -19
README.md
··· 149 149 pointer events in addition to the byte sequence. 150 150 151 151 ```typescript 152 - let { output, events } = term.render([ 153 - open("root", { 154 - layout: { width: grow(), height: grow(), direction: "ltr" }, 155 - }), 156 - open("sidebar", { 157 - layout: { width: fixed(20), height: grow() }, 158 - bg: rgba(30, 30, 40), 159 - }), 160 - text("Sidebar"), 161 - close(), 162 - open("main", { 163 - layout: { width: grow(), height: grow() }, 164 - }), 165 - text("Main content"), 166 - close(), 167 - close(), 168 - ], { 169 - pointer: { x: mouseX, y: mouseY, down: mouseDown }, 170 - }); 152 + let { output, events } = term.render( 153 + [ 154 + open("root", { 155 + layout: { width: grow(), height: grow(), direction: "ltr" }, 156 + }), 157 + open("sidebar", { 158 + layout: { width: fixed(20), height: grow() }, 159 + bg: rgba(30, 30, 40), 160 + }), 161 + text("Sidebar"), 162 + close(), 163 + open("main", { 164 + layout: { width: grow(), height: grow() }, 165 + }), 166 + text("Main content"), 167 + close(), 168 + close(), 169 + ], 170 + { 171 + pointer: { x: mouseX, y: mouseY, down: mouseDown }, 172 + }, 173 + ); 171 174 172 175 for (let event of events) { 173 176 // { type: "pointerenter", id: "sidebar" }
+55
bench/input.bench.ts
··· 1 + import { Bench } from "tinybench"; 2 + import { withCodSpeed } from "@codspeed/tinybench-plugin"; 3 + import { createInput } from "../input.ts"; 4 + 5 + function bytes(...values: number[]): Uint8Array { 6 + return new Uint8Array(values); 7 + } 8 + 9 + function str(s: string): Uint8Array { 10 + return new TextEncoder().encode(s); 11 + } 12 + 13 + let input = await createInput({ escLatency: 25 }); 14 + 15 + let longBurst = new Uint8Array(200); 16 + for (let i = 0; i < 200; i++) { 17 + longBurst[i] = 0x61 + (i % 26); 18 + } 19 + 20 + let bench = withCodSpeed(new Bench()); 21 + 22 + bench 23 + .add("printable ASCII (single char)", () => { 24 + input.scan(bytes(0x61)); 25 + }) 26 + .add("printable ASCII (short string)", () => { 27 + input.scan(str("hello world")); 28 + }) 29 + .add("arrow key (CSI sequence)", () => { 30 + input.scan(bytes(0x1b, 0x5b, 0x41)); 31 + }) 32 + .add("modifier combo (Ctrl+Shift+Arrow)", () => { 33 + input.scan(bytes(0x1b, 0x5b, 0x31, 0x3b, 0x38, 0x41)); 34 + }) 35 + .add("SGR mouse press", () => { 36 + input.scan(str("\x1b[<0;35;12M")); 37 + }) 38 + .add("multi-event burst (arrows + text)", () => { 39 + input.scan(bytes(0x1b, 0x5b, 0x41, 0x1b, 0x5b, 0x42, 0x68, 0x69)); 40 + }) 41 + .add("UTF-8 3-byte character", () => { 42 + input.scan(bytes(0xe4, 0xb8, 0xad)); 43 + }) 44 + .add("UTF-8 4-byte emoji", () => { 45 + input.scan(bytes(0xf0, 0x9f, 0x8e, 0x89)); 46 + }) 47 + .add("Kitty protocol (CSI u with modifiers)", () => { 48 + input.scan(str("\x1b[97;3u")); 49 + }) 50 + .add("long input burst (200 bytes)", () => { 51 + input.scan(longBurst); 52 + }); 53 + 54 + await bench.run(); 55 + console.table(bench.table());
+3
bench/mod.ts
··· 1 + import "./input.bench.ts"; 2 + import "./render.bench.ts"; 3 + import "./ops.bench.ts";
+124
bench/ops.bench.ts
··· 1 + import { Bench } from "tinybench"; 2 + import { withCodSpeed } from "@codspeed/tinybench-plugin"; 3 + import { close, fixed, grow, open, pack, rgba, text } from "../ops.ts"; 4 + import type { Op } from "../ops.ts"; 5 + 6 + function makeBuf(size: number): ArrayBuffer { 7 + return new ArrayBuffer(size); 8 + } 9 + 10 + let simpleOps: Op[] = [ 11 + open("root", { 12 + layout: { width: grow(), height: grow(), direction: "ttb" }, 13 + }), 14 + text("Hello, World!"), 15 + close(), 16 + ]; 17 + 18 + let complexOps: Op[] = [ 19 + open("root", { 20 + layout: { width: grow(), height: grow(), direction: "ttb" }, 21 + }), 22 + open("header", { 23 + layout: { 24 + width: grow(), 25 + height: fixed(3), 26 + padding: { left: 1, right: 1 }, 27 + direction: "ltr", 28 + }, 29 + bg: rgba(30, 30, 40), 30 + border: { 31 + color: rgba(100, 100, 120), 32 + bottom: 1, 33 + }, 34 + }), 35 + text("Title", { color: rgba(255, 255, 255), fontSize: 1 }), 36 + close(), 37 + open("body", { 38 + layout: { 39 + width: grow(), 40 + height: grow(), 41 + direction: "ltr", 42 + gap: 1, 43 + }, 44 + }), 45 + open("sidebar", { 46 + layout: { 47 + width: fixed(20), 48 + height: grow(), 49 + direction: "ttb", 50 + padding: { left: 1, right: 1, top: 1 }, 51 + }, 52 + bg: rgba(25, 25, 35), 53 + border: { 54 + color: rgba(60, 60, 80), 55 + right: 1, 56 + }, 57 + }), 58 + text("Menu Item 1"), 59 + text("Menu Item 2"), 60 + text("Menu Item 3"), 61 + close(), 62 + open("main", { 63 + layout: { 64 + width: grow(), 65 + height: grow(), 66 + direction: "ttb", 67 + padding: { left: 2, top: 1 }, 68 + }, 69 + }), 70 + text("Main content area with longer text to exercise the encoder"), 71 + close(), 72 + close(), 73 + open("footer", { 74 + layout: { 75 + width: grow(), 76 + height: fixed(1), 77 + padding: { left: 1 }, 78 + direction: "ltr", 79 + }, 80 + bg: rgba(30, 30, 40), 81 + }), 82 + text("Status: OK"), 83 + close(), 84 + close(), 85 + ]; 86 + 87 + let listOps: Op[] = [ 88 + open("root", { 89 + layout: { width: grow(), height: grow(), direction: "ttb" }, 90 + }), 91 + ...Array.from({ length: 50 }, (_, i) => [ 92 + open(`item-${i}`, { 93 + layout: { 94 + width: grow(), 95 + height: fixed(1), 96 + padding: { left: 2 }, 97 + direction: "ltr", 98 + }, 99 + bg: i % 2 === 0 ? rgba(30, 30, 40) : rgba(35, 35, 45), 100 + }), 101 + text(`List item ${i}: some description text`), 102 + close(), 103 + ]).flat(), 104 + close(), 105 + ]; 106 + 107 + let bench = withCodSpeed(new Bench()); 108 + 109 + bench 110 + .add("simple tree (root + text)", () => { 111 + let buf = makeBuf(4096); 112 + pack(simpleOps, buf, 0); 113 + }) 114 + .add("complex layout (header + sidebar + main + footer)", () => { 115 + let buf = makeBuf(8192); 116 + pack(complexOps, buf, 0); 117 + }) 118 + .add("large list (50 items)", () => { 119 + let buf = makeBuf(32768); 120 + pack(listOps, buf, 0); 121 + }); 122 + 123 + await bench.run(); 124 + console.table(bench.table());
+158
bench/render.bench.ts
··· 1 + import { Bench } from "tinybench"; 2 + import { withCodSpeed } from "@codspeed/tinybench-plugin"; 3 + import { createTerm } from "../term.ts"; 4 + import { close, fixed, grow, open, rgba, text } from "../ops.ts"; 5 + import type { Op } from "../ops.ts"; 6 + 7 + let term = await createTerm({ width: 80, height: 24 }); 8 + let termPtr = await createTerm({ width: 80, height: 24 }); 9 + 10 + let helloOps: Op[] = [ 11 + open("root", { 12 + layout: { width: grow(), height: grow(), direction: "ttb" }, 13 + }), 14 + text("Hello, World!"), 15 + close(), 16 + ]; 17 + 18 + let borderedOps: Op[] = [ 19 + open("root", { 20 + layout: { width: grow(), height: grow(), direction: "ttb" }, 21 + }), 22 + open("box", { 23 + layout: { 24 + width: grow(), 25 + height: grow(), 26 + padding: { left: 1, right: 1, top: 1, bottom: 1 }, 27 + direction: "ttb", 28 + }, 29 + border: { 30 + color: rgba(0, 255, 0), 31 + left: 1, 32 + right: 1, 33 + top: 1, 34 + bottom: 1, 35 + }, 36 + cornerRadius: { tl: 1, tr: 1, bl: 1, br: 1 }, 37 + }), 38 + text("Bordered content"), 39 + close(), 40 + close(), 41 + ]; 42 + 43 + let dashboardOps: Op[] = [ 44 + open("root", { 45 + layout: { width: grow(), height: grow(), direction: "ttb" }, 46 + }), 47 + open("header", { 48 + layout: { 49 + width: grow(), 50 + height: fixed(3), 51 + padding: { left: 1 }, 52 + direction: "ltr", 53 + }, 54 + bg: rgba(30, 30, 40), 55 + border: { color: rgba(80, 80, 100), bottom: 1 }, 56 + }), 57 + text("Dashboard", { color: rgba(255, 255, 255) }), 58 + close(), 59 + open("body", { 60 + layout: { width: grow(), height: grow(), direction: "ltr" }, 61 + }), 62 + open("sidebar", { 63 + layout: { 64 + width: fixed(20), 65 + height: grow(), 66 + direction: "ttb", 67 + padding: { left: 1, top: 1 }, 68 + }, 69 + bg: rgba(25, 25, 35), 70 + border: { color: rgba(60, 60, 80), right: 1 }, 71 + }), 72 + text("Nav 1"), 73 + text("Nav 2"), 74 + text("Nav 3"), 75 + text("Nav 4"), 76 + close(), 77 + open("main", { 78 + layout: { 79 + width: grow(), 80 + height: grow(), 81 + direction: "ttb", 82 + padding: { left: 2, top: 1 }, 83 + }, 84 + }), 85 + ...Array.from({ length: 10 }, (_, i) => [ 86 + open(`row-${i}`, { 87 + layout: { 88 + width: grow(), 89 + height: fixed(1), 90 + direction: "ltr", 91 + }, 92 + bg: i % 2 === 0 ? rgba(35, 35, 45) : undefined, 93 + }), 94 + text(`Row ${i}: data value ${i * 42}`), 95 + close(), 96 + ]).flat(), 97 + close(), 98 + close(), 99 + open("footer", { 100 + layout: { 101 + width: grow(), 102 + height: fixed(1), 103 + padding: { left: 1 }, 104 + }, 105 + bg: rgba(30, 30, 40), 106 + }), 107 + text("Ready"), 108 + close(), 109 + close(), 110 + ]; 111 + 112 + let uiOps: Op[] = [ 113 + open("root", { 114 + layout: { width: grow(), height: grow(), direction: "ttb" }, 115 + }), 116 + open("button", { 117 + layout: { 118 + width: fixed(20), 119 + height: fixed(3), 120 + padding: { left: 1, right: 1 }, 121 + }, 122 + bg: rgba(50, 50, 200), 123 + border: { 124 + color: rgba(100, 100, 255), 125 + left: 1, 126 + right: 1, 127 + top: 1, 128 + bottom: 1, 129 + }, 130 + cornerRadius: { tl: 1, tr: 1, bl: 1, br: 1 }, 131 + }), 132 + text("Click me"), 133 + close(), 134 + close(), 135 + ]; 136 + 137 + let bench = withCodSpeed(new Bench()); 138 + 139 + bench 140 + .add("simple text", () => { 141 + term.render(helloOps); 142 + }) 143 + .add("bordered box with corner radius", () => { 144 + term.render(borderedOps); 145 + }) 146 + .add("dashboard layout", () => { 147 + term.render(dashboardOps); 148 + }) 149 + .add("diff render (second frame)", () => { 150 + term.render(dashboardOps); 151 + term.render(dashboardOps); 152 + }) 153 + .add("render with pointer hit testing", () => { 154 + termPtr.render(uiOps, { pointer: { x: 10, y: 1, down: false } }); 155 + }); 156 + 157 + await bench.run(); 158 + console.table(bench.table());
+6 -2
deno.json
··· 7 7 "fmt:check": "deno fmt --check && clang-format --dry-run --Werror src/*.c src/*.h", 8 8 "build:npm": "deno run -A tasks/build-npm.ts", 9 9 "build:jsr": "deno run -A tasks/build-jsr.ts", 10 - "demo": "deno run demo/keyboard.ts" 10 + "demo": "deno run demo/keyboard.ts", 11 + "bench": "deno run -A bench/mod.ts" 11 12 }, 12 13 "imports": { 13 14 "@std/testing": "jsr:@std/testing@1", ··· 15 16 "@sinclair/typebox": "npm:@sinclair/typebox@^0.34", 16 17 "dnt": "jsr:@deno/dnt@0.42.3", 17 18 "effection": "npm:effection@^4.0.2", 18 - "@std/encoding": "jsr:@std/encoding@1" 19 + "@std/encoding": "jsr:@std/encoding@1", 20 + "@codspeed/tinybench-plugin": "npm:@codspeed/tinybench-plugin@^5.4.0", 21 + "tinybench": "npm:tinybench@^5.0.0" 19 22 }, 20 23 "exports": { 21 24 ".": "./mod.ts", ··· 25 28 "include": ["*.ts"], 26 29 "exclude": ["!wasm.ts"] 27 30 }, 31 + "nodeModulesDir": "auto", 28 32 "fmt": { 29 33 "exclude": ["clay", "build"] 30 34 },
+213 -1
deno.lock
··· 20 20 "jsr:@std/testing@1": "1.0.17", 21 21 "jsr:@ts-morph/bootstrap@0.27": "0.27.0", 22 22 "jsr:@ts-morph/common@0.27": "0.27.0", 23 + "npm:@codspeed/tinybench-plugin@^5.4.0": "5.4.0_tinybench@5.1.0", 23 24 "npm:@sinclair/typebox@*": "0.34.48", 24 25 "npm:@sinclair/typebox@0.34": "0.34.48", 25 26 "npm:effection@^4.0.2": "4.0.2", 27 + "npm:tinybench@5": "5.1.0", 26 28 "npm:valrs@*": "0.1.0" 27 29 }, 28 30 "jsr": { ··· 109 111 } 110 112 }, 111 113 "npm": { 114 + "@codspeed/core@5.4.0": { 115 + "integrity": "sha512-SwGjXDixN/zX1awBR95LzS0KxIs931qwf7Hbk7BRWv1jAdlMYf9o9GlSnWER4zGBHz941BvzFQJ1O2RIofW3cg==", 116 + "dependencies": [ 117 + "axios", 118 + "find-up", 119 + "form-data", 120 + "node-gyp-build" 121 + ] 122 + }, 123 + "@codspeed/tinybench-plugin@5.4.0_tinybench@5.1.0": { 124 + "integrity": "sha512-jzuFoyyoGxc3Lc+TTl54PnRsgqO3CYbbbnwYSVp/m/4rqvCwSUZChY9EuQJ6uZFbamT3UhWF2N6tDEGShkvsrw==", 125 + "dependencies": [ 126 + "@codspeed/core", 127 + "stack-trace", 128 + "tinybench" 129 + ] 130 + }, 112 131 "@sinclair/typebox@0.34.48": { 113 132 "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==" 114 133 }, 134 + "agent-base@6.0.2": { 135 + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 136 + "dependencies": [ 137 + "debug" 138 + ] 139 + }, 140 + "asynckit@0.4.0": { 141 + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 142 + }, 143 + "axios@1.16.1": { 144 + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", 145 + "dependencies": [ 146 + "follow-redirects", 147 + "form-data", 148 + "https-proxy-agent", 149 + "proxy-from-env" 150 + ] 151 + }, 152 + "call-bind-apply-helpers@1.0.2": { 153 + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 154 + "dependencies": [ 155 + "es-errors", 156 + "function-bind" 157 + ] 158 + }, 159 + "combined-stream@1.0.8": { 160 + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 161 + "dependencies": [ 162 + "delayed-stream" 163 + ] 164 + }, 165 + "debug@4.4.3": { 166 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 167 + "dependencies": [ 168 + "ms" 169 + ] 170 + }, 171 + "delayed-stream@1.0.0": { 172 + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" 173 + }, 174 + "dunder-proto@1.0.1": { 175 + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 176 + "dependencies": [ 177 + "call-bind-apply-helpers", 178 + "es-errors", 179 + "gopd" 180 + ] 181 + }, 115 182 "effection@4.0.2": { 116 183 "integrity": "sha512-O8WMGP10nPuJDwbNGILcaCNWS+CvDYjcdsUSD79nWZ+WtUQ8h1MEV7JJwCSZCSeKx8+TdEaZ/8r6qPTR2o/o8w==" 117 184 }, 185 + "es-define-property@1.0.1": { 186 + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" 187 + }, 188 + "es-errors@1.3.0": { 189 + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" 190 + }, 191 + "es-object-atoms@1.1.2": { 192 + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", 193 + "dependencies": [ 194 + "es-errors" 195 + ] 196 + }, 197 + "es-set-tostringtag@2.1.0": { 198 + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 199 + "dependencies": [ 200 + "es-errors", 201 + "get-intrinsic", 202 + "has-tostringtag", 203 + "hasown" 204 + ] 205 + }, 206 + "find-up@6.3.0": { 207 + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", 208 + "dependencies": [ 209 + "locate-path", 210 + "path-exists" 211 + ] 212 + }, 213 + "follow-redirects@1.16.0": { 214 + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==" 215 + }, 216 + "form-data@4.0.5": { 217 + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", 218 + "dependencies": [ 219 + "asynckit", 220 + "combined-stream", 221 + "es-set-tostringtag", 222 + "hasown", 223 + "mime-types" 224 + ] 225 + }, 226 + "function-bind@1.1.2": { 227 + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" 228 + }, 229 + "get-intrinsic@1.3.0": { 230 + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 231 + "dependencies": [ 232 + "call-bind-apply-helpers", 233 + "es-define-property", 234 + "es-errors", 235 + "es-object-atoms", 236 + "function-bind", 237 + "get-proto", 238 + "gopd", 239 + "has-symbols", 240 + "hasown", 241 + "math-intrinsics" 242 + ] 243 + }, 244 + "get-proto@1.0.1": { 245 + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 246 + "dependencies": [ 247 + "dunder-proto", 248 + "es-object-atoms" 249 + ] 250 + }, 251 + "gopd@1.2.0": { 252 + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" 253 + }, 254 + "has-symbols@1.1.0": { 255 + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" 256 + }, 257 + "has-tostringtag@1.0.2": { 258 + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 259 + "dependencies": [ 260 + "has-symbols" 261 + ] 262 + }, 263 + "hasown@2.0.3": { 264 + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", 265 + "dependencies": [ 266 + "function-bind" 267 + ] 268 + }, 269 + "https-proxy-agent@5.0.1": { 270 + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 271 + "dependencies": [ 272 + "agent-base", 273 + "debug" 274 + ] 275 + }, 276 + "locate-path@7.2.0": { 277 + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", 278 + "dependencies": [ 279 + "p-locate" 280 + ] 281 + }, 282 + "math-intrinsics@1.1.0": { 283 + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" 284 + }, 285 + "mime-db@1.52.0": { 286 + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 287 + }, 288 + "mime-types@2.1.35": { 289 + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 290 + "dependencies": [ 291 + "mime-db" 292 + ] 293 + }, 294 + "ms@2.1.3": { 295 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 296 + }, 297 + "node-gyp-build@4.8.4": { 298 + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", 299 + "bin": true 300 + }, 301 + "p-limit@4.0.0": { 302 + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", 303 + "dependencies": [ 304 + "yocto-queue" 305 + ] 306 + }, 307 + "p-locate@6.0.0": { 308 + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", 309 + "dependencies": [ 310 + "p-limit" 311 + ] 312 + }, 313 + "path-exists@5.0.0": { 314 + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==" 315 + }, 316 + "proxy-from-env@2.1.0": { 317 + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==" 318 + }, 319 + "stack-trace@1.0.0-pre2": { 320 + "integrity": "sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==" 321 + }, 322 + "tinybench@5.1.0": { 323 + "integrity": "sha512-LXKNtFualiKOm6gADe1UXPtf8+Nfn1CtPMEHAT33Fd2YjQatrujkDcK0+4wRC1X6t7fxUDXUs6BsvuIgfkDgDg==" 324 + }, 118 325 "valrs@0.1.0": { 119 326 "integrity": "sha512-BqVkjx3qhsRLHerblLDoqEx0OEx7ms0DB6LPv40oWkMfFKUVKrqVuklaGdrPrHyubC5hSHYfEtUiQXrCkC6xHQ==" 327 + }, 328 + "yocto-queue@1.2.2": { 329 + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==" 120 330 } 121 331 }, 122 332 "workspace": { ··· 125 335 "jsr:@std/encoding@1", 126 336 "jsr:@std/expect@1", 127 337 "jsr:@std/testing@1", 338 + "npm:@codspeed/tinybench-plugin@^5.4.0", 128 339 "npm:@sinclair/typebox@0.34", 129 - "npm:effection@^4.0.2" 340 + "npm:effection@^4.0.2", 341 + "npm:tinybench@5" 130 342 ] 131 343 } 132 344 }
+3
package.json
··· 1 + { 2 + "type": "module" 3 + }