Reference implementation for the Phoenix Architecture. Work in progress. aicoding.leaflet.pub/
ai coding crazy
1
fork

Configure Feed

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

feat: architecture targets — compile specs to working apps

Add Architecture interface and sqlite-web-api target (Hono + SQLite + Zod).
Modified pipeline: prompt builder injects architecture patterns, scaffold
writes shared files (db.ts, app.ts, server.ts), package.json gets real deps.

phoenix init --arch=sqlite-web-api && phoenix bootstrap now generates a
working REST API from specs. Tested with todo-app example: POST /todos
creates real SQLite records, returns 201 with Zod validation.

Known issue: each generated module creates its own DB connection instead
of importing from shared db.ts. Fix needed in architecture examples.

+3506 -28
examples/todo-app/app.db

This is a binary file and will not be displayed.

examples/todo-app/data.db

This is a binary file and will not be displayed.

examples/todo-app/data/app.db

This is a binary file and will not be displayed.

+3
examples/todo-app/migrations.json
··· 1 + [ 2 + "todos" 3 + ]
+2478
examples/todo-app/package-lock.json
··· 1 + { 2 + "name": "todo-app", 3 + "version": "0.1.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "todo-app", 9 + "version": "0.1.0", 10 + "dependencies": { 11 + "@hono/node-server": "^1.13.0", 12 + "better-sqlite3": "^11.7.0", 13 + "hono": "^4.6.0", 14 + "zod": "^3.24.0" 15 + }, 16 + "devDependencies": { 17 + "@types/better-sqlite3": "^7.6.0", 18 + "@types/node": "^22.0.0", 19 + "tsx": "^4.0.0", 20 + "typescript": "^5.4.0", 21 + "vitest": "^2.0.0" 22 + } 23 + }, 24 + "node_modules/@esbuild/aix-ppc64": { 25 + "version": "0.27.4", 26 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", 27 + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", 28 + "cpu": [ 29 + "ppc64" 30 + ], 31 + "dev": true, 32 + "license": "MIT", 33 + "optional": true, 34 + "os": [ 35 + "aix" 36 + ], 37 + "engines": { 38 + "node": ">=18" 39 + } 40 + }, 41 + "node_modules/@esbuild/android-arm": { 42 + "version": "0.27.4", 43 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", 44 + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", 45 + "cpu": [ 46 + "arm" 47 + ], 48 + "dev": true, 49 + "license": "MIT", 50 + "optional": true, 51 + "os": [ 52 + "android" 53 + ], 54 + "engines": { 55 + "node": ">=18" 56 + } 57 + }, 58 + "node_modules/@esbuild/android-arm64": { 59 + "version": "0.27.4", 60 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", 61 + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", 62 + "cpu": [ 63 + "arm64" 64 + ], 65 + "dev": true, 66 + "license": "MIT", 67 + "optional": true, 68 + "os": [ 69 + "android" 70 + ], 71 + "engines": { 72 + "node": ">=18" 73 + } 74 + }, 75 + "node_modules/@esbuild/android-x64": { 76 + "version": "0.27.4", 77 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", 78 + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", 79 + "cpu": [ 80 + "x64" 81 + ], 82 + "dev": true, 83 + "license": "MIT", 84 + "optional": true, 85 + "os": [ 86 + "android" 87 + ], 88 + "engines": { 89 + "node": ">=18" 90 + } 91 + }, 92 + "node_modules/@esbuild/darwin-arm64": { 93 + "version": "0.27.4", 94 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", 95 + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", 96 + "cpu": [ 97 + "arm64" 98 + ], 99 + "dev": true, 100 + "license": "MIT", 101 + "optional": true, 102 + "os": [ 103 + "darwin" 104 + ], 105 + "engines": { 106 + "node": ">=18" 107 + } 108 + }, 109 + "node_modules/@esbuild/darwin-x64": { 110 + "version": "0.27.4", 111 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", 112 + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", 113 + "cpu": [ 114 + "x64" 115 + ], 116 + "dev": true, 117 + "license": "MIT", 118 + "optional": true, 119 + "os": [ 120 + "darwin" 121 + ], 122 + "engines": { 123 + "node": ">=18" 124 + } 125 + }, 126 + "node_modules/@esbuild/freebsd-arm64": { 127 + "version": "0.27.4", 128 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", 129 + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", 130 + "cpu": [ 131 + "arm64" 132 + ], 133 + "dev": true, 134 + "license": "MIT", 135 + "optional": true, 136 + "os": [ 137 + "freebsd" 138 + ], 139 + "engines": { 140 + "node": ">=18" 141 + } 142 + }, 143 + "node_modules/@esbuild/freebsd-x64": { 144 + "version": "0.27.4", 145 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", 146 + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", 147 + "cpu": [ 148 + "x64" 149 + ], 150 + "dev": true, 151 + "license": "MIT", 152 + "optional": true, 153 + "os": [ 154 + "freebsd" 155 + ], 156 + "engines": { 157 + "node": ">=18" 158 + } 159 + }, 160 + "node_modules/@esbuild/linux-arm": { 161 + "version": "0.27.4", 162 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", 163 + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", 164 + "cpu": [ 165 + "arm" 166 + ], 167 + "dev": true, 168 + "license": "MIT", 169 + "optional": true, 170 + "os": [ 171 + "linux" 172 + ], 173 + "engines": { 174 + "node": ">=18" 175 + } 176 + }, 177 + "node_modules/@esbuild/linux-arm64": { 178 + "version": "0.27.4", 179 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", 180 + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", 181 + "cpu": [ 182 + "arm64" 183 + ], 184 + "dev": true, 185 + "license": "MIT", 186 + "optional": true, 187 + "os": [ 188 + "linux" 189 + ], 190 + "engines": { 191 + "node": ">=18" 192 + } 193 + }, 194 + "node_modules/@esbuild/linux-ia32": { 195 + "version": "0.27.4", 196 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", 197 + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", 198 + "cpu": [ 199 + "ia32" 200 + ], 201 + "dev": true, 202 + "license": "MIT", 203 + "optional": true, 204 + "os": [ 205 + "linux" 206 + ], 207 + "engines": { 208 + "node": ">=18" 209 + } 210 + }, 211 + "node_modules/@esbuild/linux-loong64": { 212 + "version": "0.27.4", 213 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", 214 + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", 215 + "cpu": [ 216 + "loong64" 217 + ], 218 + "dev": true, 219 + "license": "MIT", 220 + "optional": true, 221 + "os": [ 222 + "linux" 223 + ], 224 + "engines": { 225 + "node": ">=18" 226 + } 227 + }, 228 + "node_modules/@esbuild/linux-mips64el": { 229 + "version": "0.27.4", 230 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", 231 + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", 232 + "cpu": [ 233 + "mips64el" 234 + ], 235 + "dev": true, 236 + "license": "MIT", 237 + "optional": true, 238 + "os": [ 239 + "linux" 240 + ], 241 + "engines": { 242 + "node": ">=18" 243 + } 244 + }, 245 + "node_modules/@esbuild/linux-ppc64": { 246 + "version": "0.27.4", 247 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", 248 + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", 249 + "cpu": [ 250 + "ppc64" 251 + ], 252 + "dev": true, 253 + "license": "MIT", 254 + "optional": true, 255 + "os": [ 256 + "linux" 257 + ], 258 + "engines": { 259 + "node": ">=18" 260 + } 261 + }, 262 + "node_modules/@esbuild/linux-riscv64": { 263 + "version": "0.27.4", 264 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", 265 + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", 266 + "cpu": [ 267 + "riscv64" 268 + ], 269 + "dev": true, 270 + "license": "MIT", 271 + "optional": true, 272 + "os": [ 273 + "linux" 274 + ], 275 + "engines": { 276 + "node": ">=18" 277 + } 278 + }, 279 + "node_modules/@esbuild/linux-s390x": { 280 + "version": "0.27.4", 281 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", 282 + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", 283 + "cpu": [ 284 + "s390x" 285 + ], 286 + "dev": true, 287 + "license": "MIT", 288 + "optional": true, 289 + "os": [ 290 + "linux" 291 + ], 292 + "engines": { 293 + "node": ">=18" 294 + } 295 + }, 296 + "node_modules/@esbuild/linux-x64": { 297 + "version": "0.27.4", 298 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", 299 + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", 300 + "cpu": [ 301 + "x64" 302 + ], 303 + "dev": true, 304 + "license": "MIT", 305 + "optional": true, 306 + "os": [ 307 + "linux" 308 + ], 309 + "engines": { 310 + "node": ">=18" 311 + } 312 + }, 313 + "node_modules/@esbuild/netbsd-arm64": { 314 + "version": "0.27.4", 315 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", 316 + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", 317 + "cpu": [ 318 + "arm64" 319 + ], 320 + "dev": true, 321 + "license": "MIT", 322 + "optional": true, 323 + "os": [ 324 + "netbsd" 325 + ], 326 + "engines": { 327 + "node": ">=18" 328 + } 329 + }, 330 + "node_modules/@esbuild/netbsd-x64": { 331 + "version": "0.27.4", 332 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", 333 + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", 334 + "cpu": [ 335 + "x64" 336 + ], 337 + "dev": true, 338 + "license": "MIT", 339 + "optional": true, 340 + "os": [ 341 + "netbsd" 342 + ], 343 + "engines": { 344 + "node": ">=18" 345 + } 346 + }, 347 + "node_modules/@esbuild/openbsd-arm64": { 348 + "version": "0.27.4", 349 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", 350 + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", 351 + "cpu": [ 352 + "arm64" 353 + ], 354 + "dev": true, 355 + "license": "MIT", 356 + "optional": true, 357 + "os": [ 358 + "openbsd" 359 + ], 360 + "engines": { 361 + "node": ">=18" 362 + } 363 + }, 364 + "node_modules/@esbuild/openbsd-x64": { 365 + "version": "0.27.4", 366 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", 367 + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", 368 + "cpu": [ 369 + "x64" 370 + ], 371 + "dev": true, 372 + "license": "MIT", 373 + "optional": true, 374 + "os": [ 375 + "openbsd" 376 + ], 377 + "engines": { 378 + "node": ">=18" 379 + } 380 + }, 381 + "node_modules/@esbuild/openharmony-arm64": { 382 + "version": "0.27.4", 383 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", 384 + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", 385 + "cpu": [ 386 + "arm64" 387 + ], 388 + "dev": true, 389 + "license": "MIT", 390 + "optional": true, 391 + "os": [ 392 + "openharmony" 393 + ], 394 + "engines": { 395 + "node": ">=18" 396 + } 397 + }, 398 + "node_modules/@esbuild/sunos-x64": { 399 + "version": "0.27.4", 400 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", 401 + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", 402 + "cpu": [ 403 + "x64" 404 + ], 405 + "dev": true, 406 + "license": "MIT", 407 + "optional": true, 408 + "os": [ 409 + "sunos" 410 + ], 411 + "engines": { 412 + "node": ">=18" 413 + } 414 + }, 415 + "node_modules/@esbuild/win32-arm64": { 416 + "version": "0.27.4", 417 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", 418 + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", 419 + "cpu": [ 420 + "arm64" 421 + ], 422 + "dev": true, 423 + "license": "MIT", 424 + "optional": true, 425 + "os": [ 426 + "win32" 427 + ], 428 + "engines": { 429 + "node": ">=18" 430 + } 431 + }, 432 + "node_modules/@esbuild/win32-ia32": { 433 + "version": "0.27.4", 434 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", 435 + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", 436 + "cpu": [ 437 + "ia32" 438 + ], 439 + "dev": true, 440 + "license": "MIT", 441 + "optional": true, 442 + "os": [ 443 + "win32" 444 + ], 445 + "engines": { 446 + "node": ">=18" 447 + } 448 + }, 449 + "node_modules/@esbuild/win32-x64": { 450 + "version": "0.27.4", 451 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", 452 + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", 453 + "cpu": [ 454 + "x64" 455 + ], 456 + "dev": true, 457 + "license": "MIT", 458 + "optional": true, 459 + "os": [ 460 + "win32" 461 + ], 462 + "engines": { 463 + "node": ">=18" 464 + } 465 + }, 466 + "node_modules/@hono/node-server": { 467 + "version": "1.19.11", 468 + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz", 469 + "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==", 470 + "license": "MIT", 471 + "engines": { 472 + "node": ">=18.14.1" 473 + }, 474 + "peerDependencies": { 475 + "hono": "^4" 476 + } 477 + }, 478 + "node_modules/@jridgewell/sourcemap-codec": { 479 + "version": "1.5.5", 480 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 481 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 482 + "dev": true, 483 + "license": "MIT" 484 + }, 485 + "node_modules/@rollup/rollup-android-arm-eabi": { 486 + "version": "4.60.0", 487 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz", 488 + "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==", 489 + "cpu": [ 490 + "arm" 491 + ], 492 + "dev": true, 493 + "license": "MIT", 494 + "optional": true, 495 + "os": [ 496 + "android" 497 + ] 498 + }, 499 + "node_modules/@rollup/rollup-android-arm64": { 500 + "version": "4.60.0", 501 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz", 502 + "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==", 503 + "cpu": [ 504 + "arm64" 505 + ], 506 + "dev": true, 507 + "license": "MIT", 508 + "optional": true, 509 + "os": [ 510 + "android" 511 + ] 512 + }, 513 + "node_modules/@rollup/rollup-darwin-arm64": { 514 + "version": "4.60.0", 515 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz", 516 + "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==", 517 + "cpu": [ 518 + "arm64" 519 + ], 520 + "dev": true, 521 + "license": "MIT", 522 + "optional": true, 523 + "os": [ 524 + "darwin" 525 + ] 526 + }, 527 + "node_modules/@rollup/rollup-darwin-x64": { 528 + "version": "4.60.0", 529 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz", 530 + "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==", 531 + "cpu": [ 532 + "x64" 533 + ], 534 + "dev": true, 535 + "license": "MIT", 536 + "optional": true, 537 + "os": [ 538 + "darwin" 539 + ] 540 + }, 541 + "node_modules/@rollup/rollup-freebsd-arm64": { 542 + "version": "4.60.0", 543 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz", 544 + "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==", 545 + "cpu": [ 546 + "arm64" 547 + ], 548 + "dev": true, 549 + "license": "MIT", 550 + "optional": true, 551 + "os": [ 552 + "freebsd" 553 + ] 554 + }, 555 + "node_modules/@rollup/rollup-freebsd-x64": { 556 + "version": "4.60.0", 557 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz", 558 + "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==", 559 + "cpu": [ 560 + "x64" 561 + ], 562 + "dev": true, 563 + "license": "MIT", 564 + "optional": true, 565 + "os": [ 566 + "freebsd" 567 + ] 568 + }, 569 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 570 + "version": "4.60.0", 571 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz", 572 + "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==", 573 + "cpu": [ 574 + "arm" 575 + ], 576 + "dev": true, 577 + "license": "MIT", 578 + "optional": true, 579 + "os": [ 580 + "linux" 581 + ] 582 + }, 583 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 584 + "version": "4.60.0", 585 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz", 586 + "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==", 587 + "cpu": [ 588 + "arm" 589 + ], 590 + "dev": true, 591 + "license": "MIT", 592 + "optional": true, 593 + "os": [ 594 + "linux" 595 + ] 596 + }, 597 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 598 + "version": "4.60.0", 599 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz", 600 + "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==", 601 + "cpu": [ 602 + "arm64" 603 + ], 604 + "dev": true, 605 + "license": "MIT", 606 + "optional": true, 607 + "os": [ 608 + "linux" 609 + ] 610 + }, 611 + "node_modules/@rollup/rollup-linux-arm64-musl": { 612 + "version": "4.60.0", 613 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz", 614 + "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==", 615 + "cpu": [ 616 + "arm64" 617 + ], 618 + "dev": true, 619 + "license": "MIT", 620 + "optional": true, 621 + "os": [ 622 + "linux" 623 + ] 624 + }, 625 + "node_modules/@rollup/rollup-linux-loong64-gnu": { 626 + "version": "4.60.0", 627 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz", 628 + "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==", 629 + "cpu": [ 630 + "loong64" 631 + ], 632 + "dev": true, 633 + "license": "MIT", 634 + "optional": true, 635 + "os": [ 636 + "linux" 637 + ] 638 + }, 639 + "node_modules/@rollup/rollup-linux-loong64-musl": { 640 + "version": "4.60.0", 641 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz", 642 + "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==", 643 + "cpu": [ 644 + "loong64" 645 + ], 646 + "dev": true, 647 + "license": "MIT", 648 + "optional": true, 649 + "os": [ 650 + "linux" 651 + ] 652 + }, 653 + "node_modules/@rollup/rollup-linux-ppc64-gnu": { 654 + "version": "4.60.0", 655 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz", 656 + "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==", 657 + "cpu": [ 658 + "ppc64" 659 + ], 660 + "dev": true, 661 + "license": "MIT", 662 + "optional": true, 663 + "os": [ 664 + "linux" 665 + ] 666 + }, 667 + "node_modules/@rollup/rollup-linux-ppc64-musl": { 668 + "version": "4.60.0", 669 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz", 670 + "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==", 671 + "cpu": [ 672 + "ppc64" 673 + ], 674 + "dev": true, 675 + "license": "MIT", 676 + "optional": true, 677 + "os": [ 678 + "linux" 679 + ] 680 + }, 681 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 682 + "version": "4.60.0", 683 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz", 684 + "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==", 685 + "cpu": [ 686 + "riscv64" 687 + ], 688 + "dev": true, 689 + "license": "MIT", 690 + "optional": true, 691 + "os": [ 692 + "linux" 693 + ] 694 + }, 695 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 696 + "version": "4.60.0", 697 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz", 698 + "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==", 699 + "cpu": [ 700 + "riscv64" 701 + ], 702 + "dev": true, 703 + "license": "MIT", 704 + "optional": true, 705 + "os": [ 706 + "linux" 707 + ] 708 + }, 709 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 710 + "version": "4.60.0", 711 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz", 712 + "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==", 713 + "cpu": [ 714 + "s390x" 715 + ], 716 + "dev": true, 717 + "license": "MIT", 718 + "optional": true, 719 + "os": [ 720 + "linux" 721 + ] 722 + }, 723 + "node_modules/@rollup/rollup-linux-x64-gnu": { 724 + "version": "4.60.0", 725 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.0.tgz", 726 + "integrity": "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==", 727 + "cpu": [ 728 + "x64" 729 + ], 730 + "dev": true, 731 + "license": "MIT", 732 + "optional": true, 733 + "os": [ 734 + "linux" 735 + ] 736 + }, 737 + "node_modules/@rollup/rollup-linux-x64-musl": { 738 + "version": "4.60.0", 739 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.0.tgz", 740 + "integrity": "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==", 741 + "cpu": [ 742 + "x64" 743 + ], 744 + "dev": true, 745 + "license": "MIT", 746 + "optional": true, 747 + "os": [ 748 + "linux" 749 + ] 750 + }, 751 + "node_modules/@rollup/rollup-openbsd-x64": { 752 + "version": "4.60.0", 753 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz", 754 + "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==", 755 + "cpu": [ 756 + "x64" 757 + ], 758 + "dev": true, 759 + "license": "MIT", 760 + "optional": true, 761 + "os": [ 762 + "openbsd" 763 + ] 764 + }, 765 + "node_modules/@rollup/rollup-openharmony-arm64": { 766 + "version": "4.60.0", 767 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz", 768 + "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==", 769 + "cpu": [ 770 + "arm64" 771 + ], 772 + "dev": true, 773 + "license": "MIT", 774 + "optional": true, 775 + "os": [ 776 + "openharmony" 777 + ] 778 + }, 779 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 780 + "version": "4.60.0", 781 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz", 782 + "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==", 783 + "cpu": [ 784 + "arm64" 785 + ], 786 + "dev": true, 787 + "license": "MIT", 788 + "optional": true, 789 + "os": [ 790 + "win32" 791 + ] 792 + }, 793 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 794 + "version": "4.60.0", 795 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz", 796 + "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==", 797 + "cpu": [ 798 + "ia32" 799 + ], 800 + "dev": true, 801 + "license": "MIT", 802 + "optional": true, 803 + "os": [ 804 + "win32" 805 + ] 806 + }, 807 + "node_modules/@rollup/rollup-win32-x64-gnu": { 808 + "version": "4.60.0", 809 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz", 810 + "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==", 811 + "cpu": [ 812 + "x64" 813 + ], 814 + "dev": true, 815 + "license": "MIT", 816 + "optional": true, 817 + "os": [ 818 + "win32" 819 + ] 820 + }, 821 + "node_modules/@rollup/rollup-win32-x64-msvc": { 822 + "version": "4.60.0", 823 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz", 824 + "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==", 825 + "cpu": [ 826 + "x64" 827 + ], 828 + "dev": true, 829 + "license": "MIT", 830 + "optional": true, 831 + "os": [ 832 + "win32" 833 + ] 834 + }, 835 + "node_modules/@types/better-sqlite3": { 836 + "version": "7.6.13", 837 + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", 838 + "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", 839 + "dev": true, 840 + "license": "MIT", 841 + "dependencies": { 842 + "@types/node": "*" 843 + } 844 + }, 845 + "node_modules/@types/estree": { 846 + "version": "1.0.8", 847 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 848 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 849 + "dev": true, 850 + "license": "MIT" 851 + }, 852 + "node_modules/@types/node": { 853 + "version": "22.19.15", 854 + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", 855 + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", 856 + "dev": true, 857 + "license": "MIT", 858 + "dependencies": { 859 + "undici-types": "~6.21.0" 860 + } 861 + }, 862 + "node_modules/@vitest/expect": { 863 + "version": "2.1.9", 864 + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", 865 + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", 866 + "dev": true, 867 + "license": "MIT", 868 + "dependencies": { 869 + "@vitest/spy": "2.1.9", 870 + "@vitest/utils": "2.1.9", 871 + "chai": "^5.1.2", 872 + "tinyrainbow": "^1.2.0" 873 + }, 874 + "funding": { 875 + "url": "https://opencollective.com/vitest" 876 + } 877 + }, 878 + "node_modules/@vitest/mocker": { 879 + "version": "2.1.9", 880 + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", 881 + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", 882 + "dev": true, 883 + "license": "MIT", 884 + "dependencies": { 885 + "@vitest/spy": "2.1.9", 886 + "estree-walker": "^3.0.3", 887 + "magic-string": "^0.30.12" 888 + }, 889 + "funding": { 890 + "url": "https://opencollective.com/vitest" 891 + }, 892 + "peerDependencies": { 893 + "msw": "^2.4.9", 894 + "vite": "^5.0.0" 895 + }, 896 + "peerDependenciesMeta": { 897 + "msw": { 898 + "optional": true 899 + }, 900 + "vite": { 901 + "optional": true 902 + } 903 + } 904 + }, 905 + "node_modules/@vitest/pretty-format": { 906 + "version": "2.1.9", 907 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", 908 + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", 909 + "dev": true, 910 + "license": "MIT", 911 + "dependencies": { 912 + "tinyrainbow": "^1.2.0" 913 + }, 914 + "funding": { 915 + "url": "https://opencollective.com/vitest" 916 + } 917 + }, 918 + "node_modules/@vitest/runner": { 919 + "version": "2.1.9", 920 + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", 921 + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", 922 + "dev": true, 923 + "license": "MIT", 924 + "dependencies": { 925 + "@vitest/utils": "2.1.9", 926 + "pathe": "^1.1.2" 927 + }, 928 + "funding": { 929 + "url": "https://opencollective.com/vitest" 930 + } 931 + }, 932 + "node_modules/@vitest/snapshot": { 933 + "version": "2.1.9", 934 + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", 935 + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", 936 + "dev": true, 937 + "license": "MIT", 938 + "dependencies": { 939 + "@vitest/pretty-format": "2.1.9", 940 + "magic-string": "^0.30.12", 941 + "pathe": "^1.1.2" 942 + }, 943 + "funding": { 944 + "url": "https://opencollective.com/vitest" 945 + } 946 + }, 947 + "node_modules/@vitest/spy": { 948 + "version": "2.1.9", 949 + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", 950 + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", 951 + "dev": true, 952 + "license": "MIT", 953 + "dependencies": { 954 + "tinyspy": "^3.0.2" 955 + }, 956 + "funding": { 957 + "url": "https://opencollective.com/vitest" 958 + } 959 + }, 960 + "node_modules/@vitest/utils": { 961 + "version": "2.1.9", 962 + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", 963 + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", 964 + "dev": true, 965 + "license": "MIT", 966 + "dependencies": { 967 + "@vitest/pretty-format": "2.1.9", 968 + "loupe": "^3.1.2", 969 + "tinyrainbow": "^1.2.0" 970 + }, 971 + "funding": { 972 + "url": "https://opencollective.com/vitest" 973 + } 974 + }, 975 + "node_modules/assertion-error": { 976 + "version": "2.0.1", 977 + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 978 + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 979 + "dev": true, 980 + "license": "MIT", 981 + "engines": { 982 + "node": ">=12" 983 + } 984 + }, 985 + "node_modules/base64-js": { 986 + "version": "1.5.1", 987 + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 988 + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 989 + "funding": [ 990 + { 991 + "type": "github", 992 + "url": "https://github.com/sponsors/feross" 993 + }, 994 + { 995 + "type": "patreon", 996 + "url": "https://www.patreon.com/feross" 997 + }, 998 + { 999 + "type": "consulting", 1000 + "url": "https://feross.org/support" 1001 + } 1002 + ], 1003 + "license": "MIT" 1004 + }, 1005 + "node_modules/better-sqlite3": { 1006 + "version": "11.10.0", 1007 + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz", 1008 + "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==", 1009 + "hasInstallScript": true, 1010 + "license": "MIT", 1011 + "dependencies": { 1012 + "bindings": "^1.5.0", 1013 + "prebuild-install": "^7.1.1" 1014 + } 1015 + }, 1016 + "node_modules/bindings": { 1017 + "version": "1.5.0", 1018 + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", 1019 + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", 1020 + "license": "MIT", 1021 + "dependencies": { 1022 + "file-uri-to-path": "1.0.0" 1023 + } 1024 + }, 1025 + "node_modules/bl": { 1026 + "version": "4.1.0", 1027 + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 1028 + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 1029 + "license": "MIT", 1030 + "dependencies": { 1031 + "buffer": "^5.5.0", 1032 + "inherits": "^2.0.4", 1033 + "readable-stream": "^3.4.0" 1034 + } 1035 + }, 1036 + "node_modules/buffer": { 1037 + "version": "5.7.1", 1038 + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 1039 + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 1040 + "funding": [ 1041 + { 1042 + "type": "github", 1043 + "url": "https://github.com/sponsors/feross" 1044 + }, 1045 + { 1046 + "type": "patreon", 1047 + "url": "https://www.patreon.com/feross" 1048 + }, 1049 + { 1050 + "type": "consulting", 1051 + "url": "https://feross.org/support" 1052 + } 1053 + ], 1054 + "license": "MIT", 1055 + "dependencies": { 1056 + "base64-js": "^1.3.1", 1057 + "ieee754": "^1.1.13" 1058 + } 1059 + }, 1060 + "node_modules/cac": { 1061 + "version": "6.7.14", 1062 + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 1063 + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 1064 + "dev": true, 1065 + "license": "MIT", 1066 + "engines": { 1067 + "node": ">=8" 1068 + } 1069 + }, 1070 + "node_modules/chai": { 1071 + "version": "5.3.3", 1072 + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", 1073 + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", 1074 + "dev": true, 1075 + "license": "MIT", 1076 + "dependencies": { 1077 + "assertion-error": "^2.0.1", 1078 + "check-error": "^2.1.1", 1079 + "deep-eql": "^5.0.1", 1080 + "loupe": "^3.1.0", 1081 + "pathval": "^2.0.0" 1082 + }, 1083 + "engines": { 1084 + "node": ">=18" 1085 + } 1086 + }, 1087 + "node_modules/check-error": { 1088 + "version": "2.1.3", 1089 + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", 1090 + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", 1091 + "dev": true, 1092 + "license": "MIT", 1093 + "engines": { 1094 + "node": ">= 16" 1095 + } 1096 + }, 1097 + "node_modules/chownr": { 1098 + "version": "1.1.4", 1099 + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 1100 + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", 1101 + "license": "ISC" 1102 + }, 1103 + "node_modules/debug": { 1104 + "version": "4.4.3", 1105 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", 1106 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 1107 + "dev": true, 1108 + "license": "MIT", 1109 + "dependencies": { 1110 + "ms": "^2.1.3" 1111 + }, 1112 + "engines": { 1113 + "node": ">=6.0" 1114 + }, 1115 + "peerDependenciesMeta": { 1116 + "supports-color": { 1117 + "optional": true 1118 + } 1119 + } 1120 + }, 1121 + "node_modules/decompress-response": { 1122 + "version": "6.0.0", 1123 + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", 1124 + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", 1125 + "license": "MIT", 1126 + "dependencies": { 1127 + "mimic-response": "^3.1.0" 1128 + }, 1129 + "engines": { 1130 + "node": ">=10" 1131 + }, 1132 + "funding": { 1133 + "url": "https://github.com/sponsors/sindresorhus" 1134 + } 1135 + }, 1136 + "node_modules/deep-eql": { 1137 + "version": "5.0.2", 1138 + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1139 + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1140 + "dev": true, 1141 + "license": "MIT", 1142 + "engines": { 1143 + "node": ">=6" 1144 + } 1145 + }, 1146 + "node_modules/deep-extend": { 1147 + "version": "0.6.0", 1148 + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 1149 + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 1150 + "license": "MIT", 1151 + "engines": { 1152 + "node": ">=4.0.0" 1153 + } 1154 + }, 1155 + "node_modules/detect-libc": { 1156 + "version": "2.1.2", 1157 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", 1158 + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", 1159 + "license": "Apache-2.0", 1160 + "engines": { 1161 + "node": ">=8" 1162 + } 1163 + }, 1164 + "node_modules/end-of-stream": { 1165 + "version": "1.4.5", 1166 + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", 1167 + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", 1168 + "license": "MIT", 1169 + "dependencies": { 1170 + "once": "^1.4.0" 1171 + } 1172 + }, 1173 + "node_modules/es-module-lexer": { 1174 + "version": "1.7.0", 1175 + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 1176 + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 1177 + "dev": true, 1178 + "license": "MIT" 1179 + }, 1180 + "node_modules/esbuild": { 1181 + "version": "0.27.4", 1182 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", 1183 + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", 1184 + "dev": true, 1185 + "hasInstallScript": true, 1186 + "license": "MIT", 1187 + "bin": { 1188 + "esbuild": "bin/esbuild" 1189 + }, 1190 + "engines": { 1191 + "node": ">=18" 1192 + }, 1193 + "optionalDependencies": { 1194 + "@esbuild/aix-ppc64": "0.27.4", 1195 + "@esbuild/android-arm": "0.27.4", 1196 + "@esbuild/android-arm64": "0.27.4", 1197 + "@esbuild/android-x64": "0.27.4", 1198 + "@esbuild/darwin-arm64": "0.27.4", 1199 + "@esbuild/darwin-x64": "0.27.4", 1200 + "@esbuild/freebsd-arm64": "0.27.4", 1201 + "@esbuild/freebsd-x64": "0.27.4", 1202 + "@esbuild/linux-arm": "0.27.4", 1203 + "@esbuild/linux-arm64": "0.27.4", 1204 + "@esbuild/linux-ia32": "0.27.4", 1205 + "@esbuild/linux-loong64": "0.27.4", 1206 + "@esbuild/linux-mips64el": "0.27.4", 1207 + "@esbuild/linux-ppc64": "0.27.4", 1208 + "@esbuild/linux-riscv64": "0.27.4", 1209 + "@esbuild/linux-s390x": "0.27.4", 1210 + "@esbuild/linux-x64": "0.27.4", 1211 + "@esbuild/netbsd-arm64": "0.27.4", 1212 + "@esbuild/netbsd-x64": "0.27.4", 1213 + "@esbuild/openbsd-arm64": "0.27.4", 1214 + "@esbuild/openbsd-x64": "0.27.4", 1215 + "@esbuild/openharmony-arm64": "0.27.4", 1216 + "@esbuild/sunos-x64": "0.27.4", 1217 + "@esbuild/win32-arm64": "0.27.4", 1218 + "@esbuild/win32-ia32": "0.27.4", 1219 + "@esbuild/win32-x64": "0.27.4" 1220 + } 1221 + }, 1222 + "node_modules/estree-walker": { 1223 + "version": "3.0.3", 1224 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1225 + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1226 + "dev": true, 1227 + "license": "MIT", 1228 + "dependencies": { 1229 + "@types/estree": "^1.0.0" 1230 + } 1231 + }, 1232 + "node_modules/expand-template": { 1233 + "version": "2.0.3", 1234 + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", 1235 + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", 1236 + "license": "(MIT OR WTFPL)", 1237 + "engines": { 1238 + "node": ">=6" 1239 + } 1240 + }, 1241 + "node_modules/expect-type": { 1242 + "version": "1.3.0", 1243 + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", 1244 + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", 1245 + "dev": true, 1246 + "license": "Apache-2.0", 1247 + "engines": { 1248 + "node": ">=12.0.0" 1249 + } 1250 + }, 1251 + "node_modules/file-uri-to-path": { 1252 + "version": "1.0.0", 1253 + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", 1254 + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", 1255 + "license": "MIT" 1256 + }, 1257 + "node_modules/fs-constants": { 1258 + "version": "1.0.0", 1259 + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 1260 + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", 1261 + "license": "MIT" 1262 + }, 1263 + "node_modules/fsevents": { 1264 + "version": "2.3.3", 1265 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1266 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1267 + "dev": true, 1268 + "hasInstallScript": true, 1269 + "license": "MIT", 1270 + "optional": true, 1271 + "os": [ 1272 + "darwin" 1273 + ], 1274 + "engines": { 1275 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1276 + } 1277 + }, 1278 + "node_modules/get-tsconfig": { 1279 + "version": "4.13.7", 1280 + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", 1281 + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", 1282 + "dev": true, 1283 + "license": "MIT", 1284 + "dependencies": { 1285 + "resolve-pkg-maps": "^1.0.0" 1286 + }, 1287 + "funding": { 1288 + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 1289 + } 1290 + }, 1291 + "node_modules/github-from-package": { 1292 + "version": "0.0.0", 1293 + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", 1294 + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", 1295 + "license": "MIT" 1296 + }, 1297 + "node_modules/hono": { 1298 + "version": "4.12.9", 1299 + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.9.tgz", 1300 + "integrity": "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA==", 1301 + "license": "MIT", 1302 + "engines": { 1303 + "node": ">=16.9.0" 1304 + } 1305 + }, 1306 + "node_modules/ieee754": { 1307 + "version": "1.2.1", 1308 + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1309 + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 1310 + "funding": [ 1311 + { 1312 + "type": "github", 1313 + "url": "https://github.com/sponsors/feross" 1314 + }, 1315 + { 1316 + "type": "patreon", 1317 + "url": "https://www.patreon.com/feross" 1318 + }, 1319 + { 1320 + "type": "consulting", 1321 + "url": "https://feross.org/support" 1322 + } 1323 + ], 1324 + "license": "BSD-3-Clause" 1325 + }, 1326 + "node_modules/inherits": { 1327 + "version": "2.0.4", 1328 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1329 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1330 + "license": "ISC" 1331 + }, 1332 + "node_modules/ini": { 1333 + "version": "1.3.8", 1334 + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 1335 + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 1336 + "license": "ISC" 1337 + }, 1338 + "node_modules/loupe": { 1339 + "version": "3.2.1", 1340 + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", 1341 + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", 1342 + "dev": true, 1343 + "license": "MIT" 1344 + }, 1345 + "node_modules/magic-string": { 1346 + "version": "0.30.21", 1347 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 1348 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 1349 + "dev": true, 1350 + "license": "MIT", 1351 + "dependencies": { 1352 + "@jridgewell/sourcemap-codec": "^1.5.5" 1353 + } 1354 + }, 1355 + "node_modules/mimic-response": { 1356 + "version": "3.1.0", 1357 + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", 1358 + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", 1359 + "license": "MIT", 1360 + "engines": { 1361 + "node": ">=10" 1362 + }, 1363 + "funding": { 1364 + "url": "https://github.com/sponsors/sindresorhus" 1365 + } 1366 + }, 1367 + "node_modules/minimist": { 1368 + "version": "1.2.8", 1369 + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1370 + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1371 + "license": "MIT", 1372 + "funding": { 1373 + "url": "https://github.com/sponsors/ljharb" 1374 + } 1375 + }, 1376 + "node_modules/mkdirp-classic": { 1377 + "version": "0.5.3", 1378 + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 1379 + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", 1380 + "license": "MIT" 1381 + }, 1382 + "node_modules/ms": { 1383 + "version": "2.1.3", 1384 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1385 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1386 + "dev": true, 1387 + "license": "MIT" 1388 + }, 1389 + "node_modules/nanoid": { 1390 + "version": "3.3.11", 1391 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1392 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1393 + "dev": true, 1394 + "funding": [ 1395 + { 1396 + "type": "github", 1397 + "url": "https://github.com/sponsors/ai" 1398 + } 1399 + ], 1400 + "license": "MIT", 1401 + "bin": { 1402 + "nanoid": "bin/nanoid.cjs" 1403 + }, 1404 + "engines": { 1405 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1406 + } 1407 + }, 1408 + "node_modules/napi-build-utils": { 1409 + "version": "2.0.0", 1410 + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", 1411 + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", 1412 + "license": "MIT" 1413 + }, 1414 + "node_modules/node-abi": { 1415 + "version": "3.89.0", 1416 + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", 1417 + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", 1418 + "license": "MIT", 1419 + "dependencies": { 1420 + "semver": "^7.3.5" 1421 + }, 1422 + "engines": { 1423 + "node": ">=10" 1424 + } 1425 + }, 1426 + "node_modules/once": { 1427 + "version": "1.4.0", 1428 + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1429 + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1430 + "license": "ISC", 1431 + "dependencies": { 1432 + "wrappy": "1" 1433 + } 1434 + }, 1435 + "node_modules/pathe": { 1436 + "version": "1.1.2", 1437 + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", 1438 + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", 1439 + "dev": true, 1440 + "license": "MIT" 1441 + }, 1442 + "node_modules/pathval": { 1443 + "version": "2.0.1", 1444 + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", 1445 + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", 1446 + "dev": true, 1447 + "license": "MIT", 1448 + "engines": { 1449 + "node": ">= 14.16" 1450 + } 1451 + }, 1452 + "node_modules/picocolors": { 1453 + "version": "1.1.1", 1454 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1455 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1456 + "dev": true, 1457 + "license": "ISC" 1458 + }, 1459 + "node_modules/postcss": { 1460 + "version": "8.5.8", 1461 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", 1462 + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", 1463 + "dev": true, 1464 + "funding": [ 1465 + { 1466 + "type": "opencollective", 1467 + "url": "https://opencollective.com/postcss/" 1468 + }, 1469 + { 1470 + "type": "tidelift", 1471 + "url": "https://tidelift.com/funding/github/npm/postcss" 1472 + }, 1473 + { 1474 + "type": "github", 1475 + "url": "https://github.com/sponsors/ai" 1476 + } 1477 + ], 1478 + "license": "MIT", 1479 + "dependencies": { 1480 + "nanoid": "^3.3.11", 1481 + "picocolors": "^1.1.1", 1482 + "source-map-js": "^1.2.1" 1483 + }, 1484 + "engines": { 1485 + "node": "^10 || ^12 || >=14" 1486 + } 1487 + }, 1488 + "node_modules/prebuild-install": { 1489 + "version": "7.1.3", 1490 + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", 1491 + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", 1492 + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", 1493 + "license": "MIT", 1494 + "dependencies": { 1495 + "detect-libc": "^2.0.0", 1496 + "expand-template": "^2.0.3", 1497 + "github-from-package": "0.0.0", 1498 + "minimist": "^1.2.3", 1499 + "mkdirp-classic": "^0.5.3", 1500 + "napi-build-utils": "^2.0.0", 1501 + "node-abi": "^3.3.0", 1502 + "pump": "^3.0.0", 1503 + "rc": "^1.2.7", 1504 + "simple-get": "^4.0.0", 1505 + "tar-fs": "^2.0.0", 1506 + "tunnel-agent": "^0.6.0" 1507 + }, 1508 + "bin": { 1509 + "prebuild-install": "bin.js" 1510 + }, 1511 + "engines": { 1512 + "node": ">=10" 1513 + } 1514 + }, 1515 + "node_modules/pump": { 1516 + "version": "3.0.4", 1517 + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", 1518 + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", 1519 + "license": "MIT", 1520 + "dependencies": { 1521 + "end-of-stream": "^1.1.0", 1522 + "once": "^1.3.1" 1523 + } 1524 + }, 1525 + "node_modules/rc": { 1526 + "version": "1.2.8", 1527 + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 1528 + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 1529 + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", 1530 + "dependencies": { 1531 + "deep-extend": "^0.6.0", 1532 + "ini": "~1.3.0", 1533 + "minimist": "^1.2.0", 1534 + "strip-json-comments": "~2.0.1" 1535 + }, 1536 + "bin": { 1537 + "rc": "cli.js" 1538 + } 1539 + }, 1540 + "node_modules/readable-stream": { 1541 + "version": "3.6.2", 1542 + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1543 + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1544 + "license": "MIT", 1545 + "dependencies": { 1546 + "inherits": "^2.0.3", 1547 + "string_decoder": "^1.1.1", 1548 + "util-deprecate": "^1.0.1" 1549 + }, 1550 + "engines": { 1551 + "node": ">= 6" 1552 + } 1553 + }, 1554 + "node_modules/resolve-pkg-maps": { 1555 + "version": "1.0.0", 1556 + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 1557 + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 1558 + "dev": true, 1559 + "license": "MIT", 1560 + "funding": { 1561 + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 1562 + } 1563 + }, 1564 + "node_modules/rollup": { 1565 + "version": "4.60.0", 1566 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.0.tgz", 1567 + "integrity": "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==", 1568 + "dev": true, 1569 + "license": "MIT", 1570 + "dependencies": { 1571 + "@types/estree": "1.0.8" 1572 + }, 1573 + "bin": { 1574 + "rollup": "dist/bin/rollup" 1575 + }, 1576 + "engines": { 1577 + "node": ">=18.0.0", 1578 + "npm": ">=8.0.0" 1579 + }, 1580 + "optionalDependencies": { 1581 + "@rollup/rollup-android-arm-eabi": "4.60.0", 1582 + "@rollup/rollup-android-arm64": "4.60.0", 1583 + "@rollup/rollup-darwin-arm64": "4.60.0", 1584 + "@rollup/rollup-darwin-x64": "4.60.0", 1585 + "@rollup/rollup-freebsd-arm64": "4.60.0", 1586 + "@rollup/rollup-freebsd-x64": "4.60.0", 1587 + "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", 1588 + "@rollup/rollup-linux-arm-musleabihf": "4.60.0", 1589 + "@rollup/rollup-linux-arm64-gnu": "4.60.0", 1590 + "@rollup/rollup-linux-arm64-musl": "4.60.0", 1591 + "@rollup/rollup-linux-loong64-gnu": "4.60.0", 1592 + "@rollup/rollup-linux-loong64-musl": "4.60.0", 1593 + "@rollup/rollup-linux-ppc64-gnu": "4.60.0", 1594 + "@rollup/rollup-linux-ppc64-musl": "4.60.0", 1595 + "@rollup/rollup-linux-riscv64-gnu": "4.60.0", 1596 + "@rollup/rollup-linux-riscv64-musl": "4.60.0", 1597 + "@rollup/rollup-linux-s390x-gnu": "4.60.0", 1598 + "@rollup/rollup-linux-x64-gnu": "4.60.0", 1599 + "@rollup/rollup-linux-x64-musl": "4.60.0", 1600 + "@rollup/rollup-openbsd-x64": "4.60.0", 1601 + "@rollup/rollup-openharmony-arm64": "4.60.0", 1602 + "@rollup/rollup-win32-arm64-msvc": "4.60.0", 1603 + "@rollup/rollup-win32-ia32-msvc": "4.60.0", 1604 + "@rollup/rollup-win32-x64-gnu": "4.60.0", 1605 + "@rollup/rollup-win32-x64-msvc": "4.60.0", 1606 + "fsevents": "~2.3.2" 1607 + } 1608 + }, 1609 + "node_modules/safe-buffer": { 1610 + "version": "5.2.1", 1611 + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1612 + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1613 + "funding": [ 1614 + { 1615 + "type": "github", 1616 + "url": "https://github.com/sponsors/feross" 1617 + }, 1618 + { 1619 + "type": "patreon", 1620 + "url": "https://www.patreon.com/feross" 1621 + }, 1622 + { 1623 + "type": "consulting", 1624 + "url": "https://feross.org/support" 1625 + } 1626 + ], 1627 + "license": "MIT" 1628 + }, 1629 + "node_modules/semver": { 1630 + "version": "7.7.4", 1631 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", 1632 + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", 1633 + "license": "ISC", 1634 + "bin": { 1635 + "semver": "bin/semver.js" 1636 + }, 1637 + "engines": { 1638 + "node": ">=10" 1639 + } 1640 + }, 1641 + "node_modules/siginfo": { 1642 + "version": "2.0.0", 1643 + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 1644 + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 1645 + "dev": true, 1646 + "license": "ISC" 1647 + }, 1648 + "node_modules/simple-concat": { 1649 + "version": "1.0.1", 1650 + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", 1651 + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", 1652 + "funding": [ 1653 + { 1654 + "type": "github", 1655 + "url": "https://github.com/sponsors/feross" 1656 + }, 1657 + { 1658 + "type": "patreon", 1659 + "url": "https://www.patreon.com/feross" 1660 + }, 1661 + { 1662 + "type": "consulting", 1663 + "url": "https://feross.org/support" 1664 + } 1665 + ], 1666 + "license": "MIT" 1667 + }, 1668 + "node_modules/simple-get": { 1669 + "version": "4.0.1", 1670 + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", 1671 + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", 1672 + "funding": [ 1673 + { 1674 + "type": "github", 1675 + "url": "https://github.com/sponsors/feross" 1676 + }, 1677 + { 1678 + "type": "patreon", 1679 + "url": "https://www.patreon.com/feross" 1680 + }, 1681 + { 1682 + "type": "consulting", 1683 + "url": "https://feross.org/support" 1684 + } 1685 + ], 1686 + "license": "MIT", 1687 + "dependencies": { 1688 + "decompress-response": "^6.0.0", 1689 + "once": "^1.3.1", 1690 + "simple-concat": "^1.0.0" 1691 + } 1692 + }, 1693 + "node_modules/source-map-js": { 1694 + "version": "1.2.1", 1695 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1696 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1697 + "dev": true, 1698 + "license": "BSD-3-Clause", 1699 + "engines": { 1700 + "node": ">=0.10.0" 1701 + } 1702 + }, 1703 + "node_modules/stackback": { 1704 + "version": "0.0.2", 1705 + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 1706 + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 1707 + "dev": true, 1708 + "license": "MIT" 1709 + }, 1710 + "node_modules/std-env": { 1711 + "version": "3.10.0", 1712 + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", 1713 + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", 1714 + "dev": true, 1715 + "license": "MIT" 1716 + }, 1717 + "node_modules/string_decoder": { 1718 + "version": "1.3.0", 1719 + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1720 + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1721 + "license": "MIT", 1722 + "dependencies": { 1723 + "safe-buffer": "~5.2.0" 1724 + } 1725 + }, 1726 + "node_modules/strip-json-comments": { 1727 + "version": "2.0.1", 1728 + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1729 + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", 1730 + "license": "MIT", 1731 + "engines": { 1732 + "node": ">=0.10.0" 1733 + } 1734 + }, 1735 + "node_modules/tar-fs": { 1736 + "version": "2.1.4", 1737 + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", 1738 + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", 1739 + "license": "MIT", 1740 + "dependencies": { 1741 + "chownr": "^1.1.1", 1742 + "mkdirp-classic": "^0.5.2", 1743 + "pump": "^3.0.0", 1744 + "tar-stream": "^2.1.4" 1745 + } 1746 + }, 1747 + "node_modules/tar-stream": { 1748 + "version": "2.2.0", 1749 + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 1750 + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 1751 + "license": "MIT", 1752 + "dependencies": { 1753 + "bl": "^4.0.3", 1754 + "end-of-stream": "^1.4.1", 1755 + "fs-constants": "^1.0.0", 1756 + "inherits": "^2.0.3", 1757 + "readable-stream": "^3.1.1" 1758 + }, 1759 + "engines": { 1760 + "node": ">=6" 1761 + } 1762 + }, 1763 + "node_modules/tinybench": { 1764 + "version": "2.9.0", 1765 + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 1766 + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 1767 + "dev": true, 1768 + "license": "MIT" 1769 + }, 1770 + "node_modules/tinyexec": { 1771 + "version": "0.3.2", 1772 + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 1773 + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 1774 + "dev": true, 1775 + "license": "MIT" 1776 + }, 1777 + "node_modules/tinypool": { 1778 + "version": "1.1.1", 1779 + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", 1780 + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", 1781 + "dev": true, 1782 + "license": "MIT", 1783 + "engines": { 1784 + "node": "^18.0.0 || >=20.0.0" 1785 + } 1786 + }, 1787 + "node_modules/tinyrainbow": { 1788 + "version": "1.2.0", 1789 + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", 1790 + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", 1791 + "dev": true, 1792 + "license": "MIT", 1793 + "engines": { 1794 + "node": ">=14.0.0" 1795 + } 1796 + }, 1797 + "node_modules/tinyspy": { 1798 + "version": "3.0.2", 1799 + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 1800 + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 1801 + "dev": true, 1802 + "license": "MIT", 1803 + "engines": { 1804 + "node": ">=14.0.0" 1805 + } 1806 + }, 1807 + "node_modules/tsx": { 1808 + "version": "4.21.0", 1809 + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", 1810 + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", 1811 + "dev": true, 1812 + "license": "MIT", 1813 + "dependencies": { 1814 + "esbuild": "~0.27.0", 1815 + "get-tsconfig": "^4.7.5" 1816 + }, 1817 + "bin": { 1818 + "tsx": "dist/cli.mjs" 1819 + }, 1820 + "engines": { 1821 + "node": ">=18.0.0" 1822 + }, 1823 + "optionalDependencies": { 1824 + "fsevents": "~2.3.3" 1825 + } 1826 + }, 1827 + "node_modules/tunnel-agent": { 1828 + "version": "0.6.0", 1829 + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1830 + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 1831 + "license": "Apache-2.0", 1832 + "dependencies": { 1833 + "safe-buffer": "^5.0.1" 1834 + }, 1835 + "engines": { 1836 + "node": "*" 1837 + } 1838 + }, 1839 + "node_modules/typescript": { 1840 + "version": "5.9.3", 1841 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", 1842 + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", 1843 + "dev": true, 1844 + "license": "Apache-2.0", 1845 + "bin": { 1846 + "tsc": "bin/tsc", 1847 + "tsserver": "bin/tsserver" 1848 + }, 1849 + "engines": { 1850 + "node": ">=14.17" 1851 + } 1852 + }, 1853 + "node_modules/undici-types": { 1854 + "version": "6.21.0", 1855 + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", 1856 + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", 1857 + "dev": true, 1858 + "license": "MIT" 1859 + }, 1860 + "node_modules/util-deprecate": { 1861 + "version": "1.0.2", 1862 + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1863 + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1864 + "license": "MIT" 1865 + }, 1866 + "node_modules/vite": { 1867 + "version": "5.4.21", 1868 + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", 1869 + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", 1870 + "dev": true, 1871 + "license": "MIT", 1872 + "dependencies": { 1873 + "esbuild": "^0.21.3", 1874 + "postcss": "^8.4.43", 1875 + "rollup": "^4.20.0" 1876 + }, 1877 + "bin": { 1878 + "vite": "bin/vite.js" 1879 + }, 1880 + "engines": { 1881 + "node": "^18.0.0 || >=20.0.0" 1882 + }, 1883 + "funding": { 1884 + "url": "https://github.com/vitejs/vite?sponsor=1" 1885 + }, 1886 + "optionalDependencies": { 1887 + "fsevents": "~2.3.3" 1888 + }, 1889 + "peerDependencies": { 1890 + "@types/node": "^18.0.0 || >=20.0.0", 1891 + "less": "*", 1892 + "lightningcss": "^1.21.0", 1893 + "sass": "*", 1894 + "sass-embedded": "*", 1895 + "stylus": "*", 1896 + "sugarss": "*", 1897 + "terser": "^5.4.0" 1898 + }, 1899 + "peerDependenciesMeta": { 1900 + "@types/node": { 1901 + "optional": true 1902 + }, 1903 + "less": { 1904 + "optional": true 1905 + }, 1906 + "lightningcss": { 1907 + "optional": true 1908 + }, 1909 + "sass": { 1910 + "optional": true 1911 + }, 1912 + "sass-embedded": { 1913 + "optional": true 1914 + }, 1915 + "stylus": { 1916 + "optional": true 1917 + }, 1918 + "sugarss": { 1919 + "optional": true 1920 + }, 1921 + "terser": { 1922 + "optional": true 1923 + } 1924 + } 1925 + }, 1926 + "node_modules/vite-node": { 1927 + "version": "2.1.9", 1928 + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", 1929 + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", 1930 + "dev": true, 1931 + "license": "MIT", 1932 + "dependencies": { 1933 + "cac": "^6.7.14", 1934 + "debug": "^4.3.7", 1935 + "es-module-lexer": "^1.5.4", 1936 + "pathe": "^1.1.2", 1937 + "vite": "^5.0.0" 1938 + }, 1939 + "bin": { 1940 + "vite-node": "vite-node.mjs" 1941 + }, 1942 + "engines": { 1943 + "node": "^18.0.0 || >=20.0.0" 1944 + }, 1945 + "funding": { 1946 + "url": "https://opencollective.com/vitest" 1947 + } 1948 + }, 1949 + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { 1950 + "version": "0.21.5", 1951 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 1952 + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 1953 + "cpu": [ 1954 + "ppc64" 1955 + ], 1956 + "dev": true, 1957 + "license": "MIT", 1958 + "optional": true, 1959 + "os": [ 1960 + "aix" 1961 + ], 1962 + "engines": { 1963 + "node": ">=12" 1964 + } 1965 + }, 1966 + "node_modules/vite/node_modules/@esbuild/android-arm": { 1967 + "version": "0.21.5", 1968 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 1969 + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 1970 + "cpu": [ 1971 + "arm" 1972 + ], 1973 + "dev": true, 1974 + "license": "MIT", 1975 + "optional": true, 1976 + "os": [ 1977 + "android" 1978 + ], 1979 + "engines": { 1980 + "node": ">=12" 1981 + } 1982 + }, 1983 + "node_modules/vite/node_modules/@esbuild/android-arm64": { 1984 + "version": "0.21.5", 1985 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 1986 + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 1987 + "cpu": [ 1988 + "arm64" 1989 + ], 1990 + "dev": true, 1991 + "license": "MIT", 1992 + "optional": true, 1993 + "os": [ 1994 + "android" 1995 + ], 1996 + "engines": { 1997 + "node": ">=12" 1998 + } 1999 + }, 2000 + "node_modules/vite/node_modules/@esbuild/android-x64": { 2001 + "version": "0.21.5", 2002 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 2003 + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 2004 + "cpu": [ 2005 + "x64" 2006 + ], 2007 + "dev": true, 2008 + "license": "MIT", 2009 + "optional": true, 2010 + "os": [ 2011 + "android" 2012 + ], 2013 + "engines": { 2014 + "node": ">=12" 2015 + } 2016 + }, 2017 + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { 2018 + "version": "0.21.5", 2019 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 2020 + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 2021 + "cpu": [ 2022 + "arm64" 2023 + ], 2024 + "dev": true, 2025 + "license": "MIT", 2026 + "optional": true, 2027 + "os": [ 2028 + "darwin" 2029 + ], 2030 + "engines": { 2031 + "node": ">=12" 2032 + } 2033 + }, 2034 + "node_modules/vite/node_modules/@esbuild/darwin-x64": { 2035 + "version": "0.21.5", 2036 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 2037 + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 2038 + "cpu": [ 2039 + "x64" 2040 + ], 2041 + "dev": true, 2042 + "license": "MIT", 2043 + "optional": true, 2044 + "os": [ 2045 + "darwin" 2046 + ], 2047 + "engines": { 2048 + "node": ">=12" 2049 + } 2050 + }, 2051 + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { 2052 + "version": "0.21.5", 2053 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 2054 + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 2055 + "cpu": [ 2056 + "arm64" 2057 + ], 2058 + "dev": true, 2059 + "license": "MIT", 2060 + "optional": true, 2061 + "os": [ 2062 + "freebsd" 2063 + ], 2064 + "engines": { 2065 + "node": ">=12" 2066 + } 2067 + }, 2068 + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { 2069 + "version": "0.21.5", 2070 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 2071 + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 2072 + "cpu": [ 2073 + "x64" 2074 + ], 2075 + "dev": true, 2076 + "license": "MIT", 2077 + "optional": true, 2078 + "os": [ 2079 + "freebsd" 2080 + ], 2081 + "engines": { 2082 + "node": ">=12" 2083 + } 2084 + }, 2085 + "node_modules/vite/node_modules/@esbuild/linux-arm": { 2086 + "version": "0.21.5", 2087 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 2088 + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 2089 + "cpu": [ 2090 + "arm" 2091 + ], 2092 + "dev": true, 2093 + "license": "MIT", 2094 + "optional": true, 2095 + "os": [ 2096 + "linux" 2097 + ], 2098 + "engines": { 2099 + "node": ">=12" 2100 + } 2101 + }, 2102 + "node_modules/vite/node_modules/@esbuild/linux-arm64": { 2103 + "version": "0.21.5", 2104 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 2105 + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 2106 + "cpu": [ 2107 + "arm64" 2108 + ], 2109 + "dev": true, 2110 + "license": "MIT", 2111 + "optional": true, 2112 + "os": [ 2113 + "linux" 2114 + ], 2115 + "engines": { 2116 + "node": ">=12" 2117 + } 2118 + }, 2119 + "node_modules/vite/node_modules/@esbuild/linux-ia32": { 2120 + "version": "0.21.5", 2121 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 2122 + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 2123 + "cpu": [ 2124 + "ia32" 2125 + ], 2126 + "dev": true, 2127 + "license": "MIT", 2128 + "optional": true, 2129 + "os": [ 2130 + "linux" 2131 + ], 2132 + "engines": { 2133 + "node": ">=12" 2134 + } 2135 + }, 2136 + "node_modules/vite/node_modules/@esbuild/linux-loong64": { 2137 + "version": "0.21.5", 2138 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 2139 + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 2140 + "cpu": [ 2141 + "loong64" 2142 + ], 2143 + "dev": true, 2144 + "license": "MIT", 2145 + "optional": true, 2146 + "os": [ 2147 + "linux" 2148 + ], 2149 + "engines": { 2150 + "node": ">=12" 2151 + } 2152 + }, 2153 + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { 2154 + "version": "0.21.5", 2155 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 2156 + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 2157 + "cpu": [ 2158 + "mips64el" 2159 + ], 2160 + "dev": true, 2161 + "license": "MIT", 2162 + "optional": true, 2163 + "os": [ 2164 + "linux" 2165 + ], 2166 + "engines": { 2167 + "node": ">=12" 2168 + } 2169 + }, 2170 + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { 2171 + "version": "0.21.5", 2172 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 2173 + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 2174 + "cpu": [ 2175 + "ppc64" 2176 + ], 2177 + "dev": true, 2178 + "license": "MIT", 2179 + "optional": true, 2180 + "os": [ 2181 + "linux" 2182 + ], 2183 + "engines": { 2184 + "node": ">=12" 2185 + } 2186 + }, 2187 + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { 2188 + "version": "0.21.5", 2189 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 2190 + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 2191 + "cpu": [ 2192 + "riscv64" 2193 + ], 2194 + "dev": true, 2195 + "license": "MIT", 2196 + "optional": true, 2197 + "os": [ 2198 + "linux" 2199 + ], 2200 + "engines": { 2201 + "node": ">=12" 2202 + } 2203 + }, 2204 + "node_modules/vite/node_modules/@esbuild/linux-s390x": { 2205 + "version": "0.21.5", 2206 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 2207 + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 2208 + "cpu": [ 2209 + "s390x" 2210 + ], 2211 + "dev": true, 2212 + "license": "MIT", 2213 + "optional": true, 2214 + "os": [ 2215 + "linux" 2216 + ], 2217 + "engines": { 2218 + "node": ">=12" 2219 + } 2220 + }, 2221 + "node_modules/vite/node_modules/@esbuild/linux-x64": { 2222 + "version": "0.21.5", 2223 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 2224 + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 2225 + "cpu": [ 2226 + "x64" 2227 + ], 2228 + "dev": true, 2229 + "license": "MIT", 2230 + "optional": true, 2231 + "os": [ 2232 + "linux" 2233 + ], 2234 + "engines": { 2235 + "node": ">=12" 2236 + } 2237 + }, 2238 + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { 2239 + "version": "0.21.5", 2240 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 2241 + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 2242 + "cpu": [ 2243 + "x64" 2244 + ], 2245 + "dev": true, 2246 + "license": "MIT", 2247 + "optional": true, 2248 + "os": [ 2249 + "netbsd" 2250 + ], 2251 + "engines": { 2252 + "node": ">=12" 2253 + } 2254 + }, 2255 + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { 2256 + "version": "0.21.5", 2257 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 2258 + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 2259 + "cpu": [ 2260 + "x64" 2261 + ], 2262 + "dev": true, 2263 + "license": "MIT", 2264 + "optional": true, 2265 + "os": [ 2266 + "openbsd" 2267 + ], 2268 + "engines": { 2269 + "node": ">=12" 2270 + } 2271 + }, 2272 + "node_modules/vite/node_modules/@esbuild/sunos-x64": { 2273 + "version": "0.21.5", 2274 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 2275 + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 2276 + "cpu": [ 2277 + "x64" 2278 + ], 2279 + "dev": true, 2280 + "license": "MIT", 2281 + "optional": true, 2282 + "os": [ 2283 + "sunos" 2284 + ], 2285 + "engines": { 2286 + "node": ">=12" 2287 + } 2288 + }, 2289 + "node_modules/vite/node_modules/@esbuild/win32-arm64": { 2290 + "version": "0.21.5", 2291 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 2292 + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 2293 + "cpu": [ 2294 + "arm64" 2295 + ], 2296 + "dev": true, 2297 + "license": "MIT", 2298 + "optional": true, 2299 + "os": [ 2300 + "win32" 2301 + ], 2302 + "engines": { 2303 + "node": ">=12" 2304 + } 2305 + }, 2306 + "node_modules/vite/node_modules/@esbuild/win32-ia32": { 2307 + "version": "0.21.5", 2308 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 2309 + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 2310 + "cpu": [ 2311 + "ia32" 2312 + ], 2313 + "dev": true, 2314 + "license": "MIT", 2315 + "optional": true, 2316 + "os": [ 2317 + "win32" 2318 + ], 2319 + "engines": { 2320 + "node": ">=12" 2321 + } 2322 + }, 2323 + "node_modules/vite/node_modules/@esbuild/win32-x64": { 2324 + "version": "0.21.5", 2325 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 2326 + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 2327 + "cpu": [ 2328 + "x64" 2329 + ], 2330 + "dev": true, 2331 + "license": "MIT", 2332 + "optional": true, 2333 + "os": [ 2334 + "win32" 2335 + ], 2336 + "engines": { 2337 + "node": ">=12" 2338 + } 2339 + }, 2340 + "node_modules/vite/node_modules/esbuild": { 2341 + "version": "0.21.5", 2342 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 2343 + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 2344 + "dev": true, 2345 + "hasInstallScript": true, 2346 + "license": "MIT", 2347 + "bin": { 2348 + "esbuild": "bin/esbuild" 2349 + }, 2350 + "engines": { 2351 + "node": ">=12" 2352 + }, 2353 + "optionalDependencies": { 2354 + "@esbuild/aix-ppc64": "0.21.5", 2355 + "@esbuild/android-arm": "0.21.5", 2356 + "@esbuild/android-arm64": "0.21.5", 2357 + "@esbuild/android-x64": "0.21.5", 2358 + "@esbuild/darwin-arm64": "0.21.5", 2359 + "@esbuild/darwin-x64": "0.21.5", 2360 + "@esbuild/freebsd-arm64": "0.21.5", 2361 + "@esbuild/freebsd-x64": "0.21.5", 2362 + "@esbuild/linux-arm": "0.21.5", 2363 + "@esbuild/linux-arm64": "0.21.5", 2364 + "@esbuild/linux-ia32": "0.21.5", 2365 + "@esbuild/linux-loong64": "0.21.5", 2366 + "@esbuild/linux-mips64el": "0.21.5", 2367 + "@esbuild/linux-ppc64": "0.21.5", 2368 + "@esbuild/linux-riscv64": "0.21.5", 2369 + "@esbuild/linux-s390x": "0.21.5", 2370 + "@esbuild/linux-x64": "0.21.5", 2371 + "@esbuild/netbsd-x64": "0.21.5", 2372 + "@esbuild/openbsd-x64": "0.21.5", 2373 + "@esbuild/sunos-x64": "0.21.5", 2374 + "@esbuild/win32-arm64": "0.21.5", 2375 + "@esbuild/win32-ia32": "0.21.5", 2376 + "@esbuild/win32-x64": "0.21.5" 2377 + } 2378 + }, 2379 + "node_modules/vitest": { 2380 + "version": "2.1.9", 2381 + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", 2382 + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", 2383 + "dev": true, 2384 + "license": "MIT", 2385 + "dependencies": { 2386 + "@vitest/expect": "2.1.9", 2387 + "@vitest/mocker": "2.1.9", 2388 + "@vitest/pretty-format": "^2.1.9", 2389 + "@vitest/runner": "2.1.9", 2390 + "@vitest/snapshot": "2.1.9", 2391 + "@vitest/spy": "2.1.9", 2392 + "@vitest/utils": "2.1.9", 2393 + "chai": "^5.1.2", 2394 + "debug": "^4.3.7", 2395 + "expect-type": "^1.1.0", 2396 + "magic-string": "^0.30.12", 2397 + "pathe": "^1.1.2", 2398 + "std-env": "^3.8.0", 2399 + "tinybench": "^2.9.0", 2400 + "tinyexec": "^0.3.1", 2401 + "tinypool": "^1.0.1", 2402 + "tinyrainbow": "^1.2.0", 2403 + "vite": "^5.0.0", 2404 + "vite-node": "2.1.9", 2405 + "why-is-node-running": "^2.3.0" 2406 + }, 2407 + "bin": { 2408 + "vitest": "vitest.mjs" 2409 + }, 2410 + "engines": { 2411 + "node": "^18.0.0 || >=20.0.0" 2412 + }, 2413 + "funding": { 2414 + "url": "https://opencollective.com/vitest" 2415 + }, 2416 + "peerDependencies": { 2417 + "@edge-runtime/vm": "*", 2418 + "@types/node": "^18.0.0 || >=20.0.0", 2419 + "@vitest/browser": "2.1.9", 2420 + "@vitest/ui": "2.1.9", 2421 + "happy-dom": "*", 2422 + "jsdom": "*" 2423 + }, 2424 + "peerDependenciesMeta": { 2425 + "@edge-runtime/vm": { 2426 + "optional": true 2427 + }, 2428 + "@types/node": { 2429 + "optional": true 2430 + }, 2431 + "@vitest/browser": { 2432 + "optional": true 2433 + }, 2434 + "@vitest/ui": { 2435 + "optional": true 2436 + }, 2437 + "happy-dom": { 2438 + "optional": true 2439 + }, 2440 + "jsdom": { 2441 + "optional": true 2442 + } 2443 + } 2444 + }, 2445 + "node_modules/why-is-node-running": { 2446 + "version": "2.3.0", 2447 + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2448 + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2449 + "dev": true, 2450 + "license": "MIT", 2451 + "dependencies": { 2452 + "siginfo": "^2.0.0", 2453 + "stackback": "0.0.2" 2454 + }, 2455 + "bin": { 2456 + "why-is-node-running": "cli.js" 2457 + }, 2458 + "engines": { 2459 + "node": ">=8" 2460 + } 2461 + }, 2462 + "node_modules/wrappy": { 2463 + "version": "1.0.2", 2464 + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2465 + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2466 + "license": "ISC" 2467 + }, 2468 + "node_modules/zod": { 2469 + "version": "3.25.76", 2470 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 2471 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 2472 + "license": "MIT", 2473 + "funding": { 2474 + "url": "https://github.com/sponsors/colinhacks" 2475 + } 2476 + } 2477 + } 2478 + }
+27
examples/todo-app/package.json
··· 1 + { 2 + "name": "todo-app", 3 + "version": "0.1.0", 4 + "description": "Generated by Phoenix VCS — 1 services", 5 + "type": "module", 6 + "scripts": { 7 + "build": "tsc", 8 + "typecheck": "tsc --noEmit", 9 + "test": "vitest run", 10 + "test:watch": "vitest", 11 + "dev": "tsx watch src/server.ts", 12 + "start": "tsx src/server.ts" 13 + }, 14 + "dependencies": { 15 + "hono": "^4.6.0", 16 + "@hono/node-server": "^1.13.0", 17 + "better-sqlite3": "^11.7.0", 18 + "zod": "^3.24.0" 19 + }, 20 + "devDependencies": { 21 + "typescript": "^5.4.0", 22 + "vitest": "^2.0.0", 23 + "@types/node": "^22.0.0", 24 + "@types/better-sqlite3": "^7.6.0", 25 + "tsx": "^4.0.0" 26 + } 27 + }
+46
examples/todo-app/spec/todos.md
··· 1 + # Todo API 2 + 3 + A simple REST API for managing todo items. 4 + 5 + ## Data Model 6 + 7 + - A todo has: id (integer, auto-increment primary key), title (text, required), completed (boolean, default false), and created_at (timestamp, set automatically on creation) 8 + 9 + ## List Todos 10 + 11 + - GET /todos must return all todos as a JSON array ordered by created_at descending 12 + - The response must include all fields: id, title, completed, created_at 13 + 14 + ## Get Todo 15 + 16 + - GET /todos/:id must return a single todo as a JSON object 17 + - If the todo does not exist, the endpoint must return 404 with an error message 18 + 19 + ## Create Todo 20 + 21 + - POST /todos must create a new todo from a JSON request body 22 + - The request body must include a title field 23 + - Title must not be empty 24 + - Title must be at most 200 characters 25 + - The endpoint must return the created todo with status 201 26 + 27 + ## Update Todo 28 + 29 + - PATCH /todos/:id must update a todo from a JSON request body 30 + - The request body may include title and/or completed fields 31 + - If title is provided, it must not be empty and must be at most 200 characters 32 + - If completed is provided, it must be a boolean 33 + - If the todo does not exist, the endpoint must return 404 34 + - The endpoint must return the updated todo 35 + 36 + ## Delete Todo 37 + 38 + - DELETE /todos/:id must delete a todo 39 + - If the todo does not exist, the endpoint must return 404 40 + - On success, the endpoint must return 204 with no body 41 + 42 + ## Error Handling 43 + 44 + - All error responses must be JSON objects with an "error" field containing a human-readable message 45 + - Invalid JSON request bodies must return 400 46 + - Validation failures must return 400 with a description of what failed
+19
examples/todo-app/src/app.ts
··· 1 + import { Hono } from 'hono'; 2 + import { logger } from 'hono/logger'; 3 + import { cors } from 'hono/cors'; 4 + 5 + const app = new Hono(); 6 + 7 + app.use('*', logger()); 8 + app.use('*', cors()); 9 + 10 + app.get('/health', (c) => c.json({ status: 'ok', uptime: process.uptime() })); 11 + 12 + /** 13 + * Mount a route module. Call this for each generated module. 14 + */ 15 + export function mount(path: string, router: Hono): void { 16 + app.route(path, router); 17 + } 18 + 19 + export { app };
+34
examples/todo-app/src/db.ts
··· 1 + import Database from 'better-sqlite3'; 2 + import { existsSync, mkdirSync } from 'node:fs'; 3 + import { dirname } from 'node:path'; 4 + 5 + const DB_PATH = process.env.DB_PATH ?? 'data/app.db'; 6 + 7 + // Ensure directory exists 8 + const dir = dirname(DB_PATH); 9 + if (!existsSync(dir)) mkdirSync(dir, { recursive: true }); 10 + 11 + const db = new Database(DB_PATH); 12 + 13 + // Enable WAL mode for better concurrent read performance 14 + db.pragma('journal_mode = WAL'); 15 + db.pragma('foreign_keys = ON'); 16 + 17 + /** 18 + * Run migrations. Each migration is idempotent (CREATE TABLE IF NOT EXISTS). 19 + * Modules register their migrations at import time. 20 + */ 21 + const migrations: Array<{ name: string; sql: string }> = []; 22 + 23 + export function registerMigration(name: string, sql: string): void { 24 + migrations.push({ name, sql }); 25 + } 26 + 27 + export function runMigrations(): void { 28 + for (const m of migrations) { 29 + db.exec(m.sql); 30 + } 31 + } 32 + 33 + export { db }; 34 + export type { Database };
+11
examples/todo-app/src/generated/index.ts
··· 1 + /** 2 + * Phoenix VCS — Generated Service Registry 3 + * 4 + * AUTO-GENERATED by Phoenix VCS 5 + */ 6 + 7 + export * as todos from './todos/index.js'; 8 + 9 + export const services = [ 10 + { name: 'Todos', dir: 'todos', port: 3000, modules: 6 }, 11 + ] as const;
+51
examples/todo-app/src/generated/todos/__tests__/todos.test.ts
··· 1 + /** 2 + * Todos — Generated Tests 3 + * AUTO-GENERATED by Phoenix VCS 4 + */ 5 + 6 + import { describe, it, expect } from 'vitest'; 7 + import create_todo from '../create-todo.js'; 8 + import delete_todo from '../delete-todo.js'; 9 + import error_handling from '../error-handling.js'; 10 + import get_todo from '../get-todo.js'; 11 + import list_todos from '../list-todos.js'; 12 + import update_todo from '../update-todo.js'; 13 + 14 + describe('Todos modules', () => { 15 + describe('Create Todo', () => { 16 + it('exports a Hono router as default', () => { 17 + expect(create_todo).toBeDefined(); 18 + expect(typeof create_todo.fetch).toBe('function'); 19 + }); 20 + }); 21 + describe('Delete Todo', () => { 22 + it('exports a Hono router as default', () => { 23 + expect(delete_todo).toBeDefined(); 24 + expect(typeof delete_todo.fetch).toBe('function'); 25 + }); 26 + }); 27 + describe('Error Handling', () => { 28 + it('exports a Hono router as default', () => { 29 + expect(error_handling).toBeDefined(); 30 + expect(typeof error_handling.fetch).toBe('function'); 31 + }); 32 + }); 33 + describe('Get Todo', () => { 34 + it('exports a Hono router as default', () => { 35 + expect(get_todo).toBeDefined(); 36 + expect(typeof get_todo.fetch).toBe('function'); 37 + }); 38 + }); 39 + describe('List Todos', () => { 40 + it('exports a Hono router as default', () => { 41 + expect(list_todos).toBeDefined(); 42 + expect(typeof list_todos.fetch).toBe('function'); 43 + }); 44 + }); 45 + describe('Update Todo', () => { 46 + it('exports a Hono router as default', () => { 47 + expect(update_todo).toBeDefined(); 48 + expect(typeof update_todo.fetch).toBe('function'); 49 + }); 50 + }); 51 + });
+42
examples/todo-app/src/generated/todos/create-todo.ts
··· 1 + import { Hono } from 'hono'; 2 + import { z } from 'zod'; 3 + import Database from 'better-sqlite3'; 4 + 5 + const db = new Database('app.db'); 6 + 7 + // Register table migration 8 + db.exec(` 9 + CREATE TABLE IF NOT EXISTS todos ( 10 + id INTEGER PRIMARY KEY AUTOINCREMENT, 11 + title TEXT NOT NULL, 12 + created_at TEXT NOT NULL DEFAULT (datetime('now')), 13 + updated_at TEXT NOT NULL DEFAULT (datetime('now')) 14 + ) 15 + `); 16 + 17 + const CreateTodoSchema = z.object({ 18 + title: z.string().min(1, 'Title must not be empty').max(200, 'Title must not exceed 200 characters'), 19 + }); 20 + 21 + const router = new Hono(); 22 + 23 + // Create todo 24 + router.post('/', async (c) => { 25 + const result = CreateTodoSchema.safeParse(await c.req.json()); 26 + if (!result.success) return c.json({ error: result.error.issues[0].message }, 400); 27 + 28 + const { title } = result.data; 29 + const info = db.prepare('INSERT INTO todos (title) VALUES (?)').run(title); 30 + const todo = db.prepare('SELECT * FROM todos WHERE id = ?').get(info.lastInsertRowid); 31 + return c.json(todo, 201); 32 + }); 33 + 34 + export default router; 35 + 36 + /** @internal Phoenix VCS traceability — do not remove. */ 37 + export const _phoenix = { 38 + iu_id: '088be9c52621e3f6408f91eb003afcc59616238c00e70963dc7d1e900486eb6f', 39 + name: 'Create Todo', 40 + risk_tier: 'high', 41 + canon_ids: [6 as const], 42 + } as const;
+56
examples/todo-app/src/generated/todos/delete-todo.ts
··· 1 + import { Hono } from 'hono'; 2 + import Database from 'better-sqlite3'; 3 + import { readFileSync, writeFileSync, existsSync } from 'node:fs'; 4 + import { join } from 'node:path'; 5 + 6 + // Simple database setup 7 + const dbPath = join(process.cwd(), 'data.db'); 8 + const db = new Database(dbPath); 9 + 10 + // Migration tracking 11 + const migrationsPath = join(process.cwd(), 'migrations.json'); 12 + let appliedMigrations: string[] = []; 13 + 14 + if (existsSync(migrationsPath)) { 15 + appliedMigrations = JSON.parse(readFileSync(migrationsPath, 'utf-8')); 16 + } 17 + 18 + function registerMigration(name: string, sql: string) { 19 + if (!appliedMigrations.includes(name)) { 20 + db.exec(sql); 21 + appliedMigrations.push(name); 22 + writeFileSync(migrationsPath, JSON.stringify(appliedMigrations, null, 2)); 23 + } 24 + } 25 + 26 + // Register table migration 27 + registerMigration('todos', ` 28 + CREATE TABLE IF NOT EXISTS todos ( 29 + id INTEGER PRIMARY KEY AUTOINCREMENT, 30 + title TEXT NOT NULL, 31 + completed BOOLEAN NOT NULL DEFAULT 0, 32 + created_at TEXT NOT NULL DEFAULT (datetime('now')), 33 + updated_at TEXT NOT NULL DEFAULT (datetime('now')) 34 + ) 35 + `); 36 + 37 + const router = new Hono(); 38 + 39 + // Delete todo 40 + router.delete('/:id', (c) => { 41 + const id = c.req.param('id'); 42 + const existing = db.prepare('SELECT * FROM todos WHERE id = ?').get(id); 43 + if (!existing) return c.json({ error: 'Todo not found' }, 404); 44 + db.prepare('DELETE FROM todos WHERE id = ?').run(id); 45 + return c.body(null, 204); 46 + }); 47 + 48 + export default router; 49 + 50 + /** @internal Phoenix VCS traceability — do not remove. */ 51 + export const _phoenix = { 52 + iu_id: '125a8c73ae939f4ba0acfe73d08b7124f40105d27ce351aff1edc6278e5440e9', 53 + name: 'Delete Todo', 54 + risk_tier: 'low', 55 + canon_ids: [3 as const], 56 + } as const;
+54
examples/todo-app/src/generated/todos/error-handling.ts
··· 1 + import { Hono } from 'hono'; 2 + import { z } from 'zod'; 3 + 4 + const router = new Hono(); 5 + 6 + // Global error handler middleware 7 + router.onError((err, c) => { 8 + console.error('Unhandled error:', err); 9 + return c.json({ error: 'Internal server error' }, 500); 10 + }); 11 + 12 + // Middleware to handle invalid JSON 13 + router.use('*', async (c, next) => { 14 + if (c.req.method === 'POST' || c.req.method === 'PUT' || c.req.method === 'PATCH') { 15 + const contentType = c.req.header('content-type'); 16 + if (contentType && contentType.includes('application/json')) { 17 + try { 18 + await c.req.json(); 19 + } catch (error) { 20 + return c.json({ error: 'Invalid JSON in request body' }, 400); 21 + } 22 + } 23 + } 24 + await next(); 25 + }); 26 + 27 + // Helper function to format Zod validation errors 28 + export function formatValidationError(error: z.ZodError): string { 29 + const issues = error.issues.map(issue => { 30 + const path = issue.path.length > 0 ? ` at ${issue.path.join('.')}` : ''; 31 + return `${issue.message}${path}`; 32 + }); 33 + return issues.join(', '); 34 + } 35 + 36 + // Helper function to handle validation failures 37 + export function handleValidationError(result: z.SafeParseError<any>) { 38 + return { error: formatValidationError(result.error) }; 39 + } 40 + 41 + // Helper function to create standardized error responses 42 + export function createErrorResponse(message: string, status: number = 400) { 43 + return { error: message }; 44 + } 45 + 46 + export default router; 47 + 48 + /** @internal Phoenix VCS traceability — do not remove. */ 49 + export const _phoenix = { 50 + iu_id: '1c24c3f052838c88bb9df110ee8d74cace83ad14ca7788e1dea362979cc526b9', 51 + name: 'Error Handling', 52 + risk_tier: 'low', 53 + canon_ids: [3 as const], 54 + } as const;
+37
examples/todo-app/src/generated/todos/get-todo.ts
··· 1 + import { Hono } from 'hono'; 2 + import Database from 'better-sqlite3'; 3 + import { z } from 'zod'; 4 + 5 + // Initialize database 6 + const db = new Database('todos.db'); 7 + 8 + // Register table migration 9 + db.exec(` 10 + CREATE TABLE IF NOT EXISTS todos ( 11 + id INTEGER PRIMARY KEY AUTOINCREMENT, 12 + title TEXT NOT NULL, 13 + description TEXT NOT NULL DEFAULT '', 14 + completed BOOLEAN NOT NULL DEFAULT 0, 15 + created_at TEXT NOT NULL DEFAULT (datetime('now')), 16 + updated_at TEXT NOT NULL DEFAULT (datetime('now')) 17 + ) 18 + `); 19 + 20 + const router = new Hono(); 21 + 22 + // Get single todo 23 + router.get('/:id', (c) => { 24 + const todo = db.prepare('SELECT * FROM todos WHERE id = ?').get(c.req.param('id')); 25 + if (!todo) return c.json({ error: 'Todo not found' }, 404); 26 + return c.json(todo); 27 + }); 28 + 29 + export default router; 30 + 31 + /** @internal Phoenix VCS traceability — do not remove. */ 32 + export const _phoenix = { 33 + iu_id: '816a02acf9b0b67d12cff867447f8fefa205fae6ab5339d68df019eaed49590a', 34 + name: 'Get Todo', 35 + risk_tier: 'low', 36 + canon_ids: [2 as const], 37 + } as const;
+13
examples/todo-app/src/generated/todos/index.ts
··· 1 + /** 2 + * Todos 3 + * 4 + * AUTO-GENERATED by Phoenix VCS 5 + * Barrel export for all Todos modules. 6 + */ 7 + 8 + export * as createTodo from './create-todo.js'; 9 + export * as deleteTodo from './delete-todo.js'; 10 + export * as errorHandling from './error-handling.js'; 11 + export * as getTodo from './get-todo.js'; 12 + export * as listTodos from './list-todos.js'; 13 + export * as updateTodo from './update-todo.js';
+38
examples/todo-app/src/generated/todos/list-todos.ts
··· 1 + import { Hono } from 'hono'; 2 + import Database from 'better-sqlite3'; 3 + import { z } from 'zod'; 4 + 5 + // Initialize database 6 + const db = new Database('todos.db'); 7 + 8 + // Register table migration 9 + const registerMigration = (name: string, sql: string) => { 10 + db.exec(sql); 11 + }; 12 + 13 + registerMigration('todos', ` 14 + CREATE TABLE IF NOT EXISTS todos ( 15 + id INTEGER PRIMARY KEY AUTOINCREMENT, 16 + title TEXT NOT NULL, 17 + completed INTEGER NOT NULL DEFAULT 0, 18 + created_at TEXT NOT NULL DEFAULT (datetime('now')) 19 + ) 20 + `); 21 + 22 + const router = new Hono(); 23 + 24 + // List all todos 25 + router.get('/', (c) => { 26 + const todos = db.prepare('SELECT * FROM todos ORDER BY created_at DESC').all(); 27 + return c.json(todos); 28 + }); 29 + 30 + export default router; 31 + 32 + /** @internal Phoenix VCS traceability — do not remove. */ 33 + export const _phoenix = { 34 + iu_id: 'b4ca84ec9f97151d78e179fd1d2450329d547e78e438c71413713fe74fb940d5', 35 + name: 'List Todos', 36 + risk_tier: 'low', 37 + canon_ids: [2 as const], 38 + } as const;
+53
examples/todo-app/src/generated/todos/update-todo.ts
··· 1 + import { Hono } from 'hono'; 2 + import { z } from 'zod'; 3 + import Database from 'better-sqlite3'; 4 + 5 + const db = new Database('todos.db'); 6 + 7 + // Register table migration 8 + db.exec(` 9 + CREATE TABLE IF NOT EXISTS todos ( 10 + id INTEGER PRIMARY KEY AUTOINCREMENT, 11 + title TEXT NOT NULL, 12 + completed BOOLEAN NOT NULL DEFAULT 0, 13 + created_at TEXT NOT NULL DEFAULT (datetime('now')) 14 + ) 15 + `); 16 + 17 + const UpdateTodoSchema = z.object({ 18 + title: z.string().min(1).max(200).optional(), 19 + completed: z.boolean().optional(), 20 + }); 21 + 22 + const router = new Hono(); 23 + 24 + // Update todo 25 + router.patch('/:id', async (c) => { 26 + const id = c.req.param('id'); 27 + const existing = db.prepare('SELECT * FROM todos WHERE id = ?').get(id); 28 + if (!existing) return c.json({ error: 'Todo not found' }, 404); 29 + 30 + const result = UpdateTodoSchema.safeParse(await c.req.json()); 31 + if (!result.success) return c.json({ error: result.error.issues[0].message }, 400); 32 + 33 + const updates = result.data; 34 + if (updates.title !== undefined) { 35 + db.prepare('UPDATE todos SET title = ? WHERE id = ?').run(updates.title, id); 36 + } 37 + if (updates.completed !== undefined) { 38 + db.prepare('UPDATE todos SET completed = ? WHERE id = ?').run(updates.completed ? 1 : 0, id); 39 + } 40 + 41 + const updated = db.prepare('SELECT * FROM todos WHERE id = ?').get(id); 42 + return c.json(updated); 43 + }); 44 + 45 + export default router; 46 + 47 + /** @internal Phoenix VCS traceability — do not remove. */ 48 + export const _phoenix = { 49 + iu_id: 'f919a513e6f8d05e248debc46ac84046e17e891472f61fc9c0cf35619ebff8f9', 50 + name: 'Update Todo', 51 + risk_tier: 'high', 52 + canon_ids: [8 as const], 53 + } as const;
+24
examples/todo-app/src/server.ts
··· 1 + import { serve } from '@hono/node-server'; 2 + import { app, mount } from './app.js'; 3 + import { runMigrations } from './db.js'; 4 + 5 + // Generated route modules 6 + import create_todo from './generated/todos/create-todo.js'; 7 + import delete_todo from './generated/todos/delete-todo.js'; 8 + import error_handling from './generated/todos/error-handling.js'; 9 + import get_todo from './generated/todos/get-todo.js'; 10 + import list_todos from './generated/todos/list-todos.js'; 11 + import update_todo from './generated/todos/update-todo.js'; 12 + 13 + // Mount routes 14 + mount('/todos', create_todo); 15 + mount('/todos', delete_todo); 16 + mount('/todos', error_handling); 17 + mount('/todos', get_todo); 18 + mount('/todos', list_todos); 19 + mount('/todos', update_todo); 20 + 21 + const port = parseInt(process.env.PORT ?? '3000', 10); 22 + runMigrations(); 23 + console.log(`Server running at http://localhost:${port}`); 24 + serve({ fetch: app.fetch, port });
examples/todo-app/todos.db

This is a binary file and will not be displayed.

+1
examples/todo-app/todos.json
··· 1 + {"todos":[]}
+23
examples/todo-app/tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "target": "ES2022", 4 + "module": "ESNext", 5 + "moduleResolution": "bundler", 6 + "declaration": true, 7 + "outDir": "dist", 8 + "rootDir": "src", 9 + "strict": true, 10 + "esModuleInterop": true, 11 + "skipLibCheck": true, 12 + "forceConsistentCasingInFileNames": true, 13 + "resolveJsonModule": true, 14 + "sourceMap": true 15 + }, 16 + "include": [ 17 + "src/**/*" 18 + ], 19 + "exclude": [ 20 + "node_modules", 21 + "dist" 22 + ] 23 + }
+7
examples/todo-app/vitest.config.ts
··· 1 + import { defineConfig } from 'vitest/config'; 2 + 3 + export default defineConfig({ 4 + test: { 5 + include: ['src/**/__tests__/**/*.test.ts'], 6 + }, 7 + });
+18
src/architectures/index.ts
··· 1 + /** 2 + * Architecture Registry — built-in architecture targets. 3 + */ 4 + 5 + import type { Architecture } from '../models/architecture.js'; 6 + import { sqliteWebApi } from './sqlite-web-api.js'; 7 + 8 + const ARCHITECTURES: Record<string, Architecture> = { 9 + 'sqlite-web-api': sqliteWebApi, 10 + }; 11 + 12 + export function getArchitecture(name: string): Architecture | null { 13 + return ARCHITECTURES[name] ?? null; 14 + } 15 + 16 + export function listArchitectures(): string[] { 17 + return Object.keys(ARCHITECTURES); 18 + }
+244
src/architectures/sqlite-web-api.ts
··· 1 + /** 2 + * Architecture Target: sqlite-web-api 3 + * 4 + * A lightweight REST API backed by SQLite. 5 + * Stack: Hono (HTTP) + better-sqlite3 (DB) + Zod (validation) 6 + */ 7 + 8 + import type { Architecture } from '../models/architecture.js'; 9 + 10 + // ─── Shared files (written once, not generated by LLM) ───────────────────── 11 + 12 + const DB_FILE = `import Database from 'better-sqlite3'; 13 + import { existsSync, mkdirSync } from 'node:fs'; 14 + import { dirname } from 'node:path'; 15 + 16 + const DB_PATH = process.env.DB_PATH ?? 'data/app.db'; 17 + 18 + // Ensure directory exists 19 + const dir = dirname(DB_PATH); 20 + if (!existsSync(dir)) mkdirSync(dir, { recursive: true }); 21 + 22 + const db = new Database(DB_PATH); 23 + 24 + // Enable WAL mode for better concurrent read performance 25 + db.pragma('journal_mode = WAL'); 26 + db.pragma('foreign_keys = ON'); 27 + 28 + /** 29 + * Run migrations. Each migration is idempotent (CREATE TABLE IF NOT EXISTS). 30 + * Modules register their migrations at import time. 31 + */ 32 + const migrations: Array<{ name: string; sql: string }> = []; 33 + 34 + export function registerMigration(name: string, sql: string): void { 35 + migrations.push({ name, sql }); 36 + } 37 + 38 + export function runMigrations(): void { 39 + for (const m of migrations) { 40 + db.exec(m.sql); 41 + } 42 + } 43 + 44 + export { db }; 45 + export type { Database }; 46 + `; 47 + 48 + const APP_FILE = `import { Hono } from 'hono'; 49 + import { logger } from 'hono/logger'; 50 + import { cors } from 'hono/cors'; 51 + 52 + const app = new Hono(); 53 + 54 + app.use('*', logger()); 55 + app.use('*', cors()); 56 + 57 + app.get('/health', (c) => c.json({ status: 'ok', uptime: process.uptime() })); 58 + 59 + /** 60 + * Mount a route module. Call this for each generated module. 61 + */ 62 + export function mount(path: string, router: Hono): void { 63 + app.route(path, router); 64 + } 65 + 66 + export { app }; 67 + `; 68 + 69 + const SERVER_FILE = `import { serve } from '@hono/node-server'; 70 + import { app } from './app.js'; 71 + import { runMigrations } from './db.js'; 72 + 73 + // Import generated route modules (populated by scaffold) 74 + // __ROUTE_IMPORTS__ 75 + 76 + const port = parseInt(process.env.PORT ?? '3000', 10); 77 + 78 + // Run database migrations before starting 79 + runMigrations(); 80 + 81 + console.log(\`Server running at http://localhost:\${port}\`); 82 + serve({ fetch: app.fetch, port }); 83 + `; 84 + 85 + // ─── LLM prompt extension ─────────────────────────────────────────────────── 86 + 87 + const SYSTEM_PROMPT_EXTENSION = ` 88 + ## Architecture: sqlite-web-api 89 + 90 + You are generating a route handler module for a Hono REST API backed by SQLite. 91 + 92 + ### Rules 93 + - Each module exports a Hono router instance as the DEFAULT export. 94 + - Import \`{ Hono }\` from 'hono' for routing. 95 + - Import \`{ db, registerMigration }\` from '../db.js' for database access. 96 + - Import \`{ z }\` from 'zod' for request body validation. 97 + - Use better-sqlite3 synchronous API (db.prepare().run(), .get(), .all()). 98 + - Register your table schema via registerMigration() at module scope. 99 + - Use parameterized queries ALWAYS — never interpolate user input into SQL. 100 + - Return proper HTTP status codes: 200 (ok), 201 (created), 204 (no content), 400 (bad request), 404 (not found). 101 + - Return JSON for all responses. Errors: { error: "message" }. 102 + - Parse request bodies with c.req.json() and validate with Zod. 103 + - Use integer primary keys with AUTOINCREMENT for IDs. 104 + - Include created_at/updated_at timestamps where the spec mentions them. 105 + - Export the _phoenix metadata constant as required. 106 + `; 107 + 108 + const CODE_EXAMPLES = ` 109 + ## Architecture Pattern Examples 110 + 111 + ### Example 1: CRUD route module for a "notes" resource 112 + 113 + \`\`\`typescript 114 + import { Hono } from 'hono'; 115 + import { z } from 'zod'; 116 + import { db, registerMigration } from '../db.js'; 117 + 118 + // Register table migration 119 + registerMigration('notes', \` 120 + CREATE TABLE IF NOT EXISTS notes ( 121 + id INTEGER PRIMARY KEY AUTOINCREMENT, 122 + title TEXT NOT NULL, 123 + body TEXT NOT NULL DEFAULT '', 124 + created_at TEXT NOT NULL DEFAULT (datetime('now')) 125 + ) 126 + \`); 127 + 128 + const CreateNoteSchema = z.object({ 129 + title: z.string().min(1).max(200), 130 + body: z.string().optional().default(''), 131 + }); 132 + 133 + const UpdateNoteSchema = z.object({ 134 + title: z.string().min(1).max(200).optional(), 135 + body: z.string().optional(), 136 + }); 137 + 138 + const router = new Hono(); 139 + 140 + // List all notes 141 + router.get('/', (c) => { 142 + const notes = db.prepare('SELECT * FROM notes ORDER BY created_at DESC').all(); 143 + return c.json(notes); 144 + }); 145 + 146 + // Get single note 147 + router.get('/:id', (c) => { 148 + const note = db.prepare('SELECT * FROM notes WHERE id = ?').get(c.req.param('id')); 149 + if (!note) return c.json({ error: 'Note not found' }, 404); 150 + return c.json(note); 151 + }); 152 + 153 + // Create note 154 + router.post('/', async (c) => { 155 + const result = CreateNoteSchema.safeParse(await c.req.json()); 156 + if (!result.success) return c.json({ error: result.error.issues[0].message }, 400); 157 + const { title, body } = result.data; 158 + const info = db.prepare('INSERT INTO notes (title, body) VALUES (?, ?)').run(title, body); 159 + const note = db.prepare('SELECT * FROM notes WHERE id = ?').get(info.lastInsertRowid); 160 + return c.json(note, 201); 161 + }); 162 + 163 + // Update note 164 + router.patch('/:id', async (c) => { 165 + const id = c.req.param('id'); 166 + const existing = db.prepare('SELECT * FROM notes WHERE id = ?').get(id); 167 + if (!existing) return c.json({ error: 'Note not found' }, 404); 168 + const result = UpdateNoteSchema.safeParse(await c.req.json()); 169 + if (!result.success) return c.json({ error: result.error.issues[0].message }, 400); 170 + const updates = result.data; 171 + if (updates.title !== undefined) db.prepare('UPDATE notes SET title = ? WHERE id = ?').run(updates.title, id); 172 + if (updates.body !== undefined) db.prepare('UPDATE notes SET body = ? WHERE id = ?').run(updates.body, id); 173 + const updated = db.prepare('SELECT * FROM notes WHERE id = ?').get(id); 174 + return c.json(updated); 175 + }); 176 + 177 + // Delete note 178 + router.delete('/:id', (c) => { 179 + const id = c.req.param('id'); 180 + const existing = db.prepare('SELECT * FROM notes WHERE id = ?').get(id); 181 + if (!existing) return c.json({ error: 'Note not found' }, 404); 182 + db.prepare('DELETE FROM notes WHERE id = ?').run(id); 183 + return c.body(null, 204); 184 + }); 185 + 186 + export default router; 187 + 188 + export const _phoenix = { 189 + iu_id: 'example', 190 + name: 'Notes', 191 + risk_tier: 'medium', 192 + canon_ids: [], 193 + } as const; 194 + \`\`\` 195 + 196 + ### Key patterns to follow: 197 + 1. registerMigration() at module scope — idempotent CREATE TABLE IF NOT EXISTS 198 + 2. Zod schemas for create/update request validation 199 + 3. .safeParse() + early return with 400 on failure 200 + 4. Parameterized SQL queries (? placeholders) 201 + 5. Return the created/updated resource after mutation 202 + 6. 404 checks before update/delete 203 + 7. Export default router + export _phoenix metadata 204 + `; 205 + 206 + // ─── Architecture definition ──────────────────────────────────────────────── 207 + 208 + export const sqliteWebApi: Architecture = { 209 + name: 'sqlite-web-api', 210 + description: 'REST API backed by SQLite — Hono + better-sqlite3 + Zod', 211 + runtime: 'node', 212 + 213 + packages: { 214 + 'hono': '^4.6.0', 215 + '@hono/node-server': '^1.13.0', 216 + 'better-sqlite3': '^11.7.0', 217 + 'zod': '^3.24.0', 218 + }, 219 + 220 + devPackages: { 221 + 'typescript': '^5.4.0', 222 + 'vitest': '^2.0.0', 223 + '@types/node': '^22.0.0', 224 + '@types/better-sqlite3': '^7.6.0', 225 + 'tsx': '^4.0.0', 226 + }, 227 + 228 + systemPromptExtension: SYSTEM_PROMPT_EXTENSION, 229 + codeExamples: CODE_EXAMPLES, 230 + 231 + sharedFiles: { 232 + 'src/db.ts': DB_FILE, 233 + 'src/app.ts': APP_FILE, 234 + }, 235 + 236 + packageJsonExtras: { 237 + scripts: { 238 + dev: 'tsx watch src/server.ts', 239 + start: 'tsx src/server.ts', 240 + build: 'tsc', 241 + test: 'vitest run', 242 + }, 243 + }, 244 + };
+39 -3
src/cli.ts
··· 56 56 // LLM 57 57 import { resolveProvider, describeAvailability } from './llm/resolve.js'; 58 58 59 + // Architectures 60 + import { getArchitecture, listArchitectures } from './architectures/index.js'; 61 + import type { Architecture } from './models/architecture.js'; 62 + 59 63 // Audit & Fowler gaps 60 64 import { auditIU, auditAll } from './audit.js'; 61 65 import type { AuditResult, ReadinessLevel } from './audit.js'; ··· 231 235 232 236 // ─── Commands ──────────────────────────────────────────────────────────────── 233 237 234 - function cmdInit(): void { 238 + function cmdInit(args?: string[]): void { 235 239 const projectRoot = process.cwd(); 236 240 const phoenixDir = join(projectRoot, '.phoenix'); 237 241 ··· 247 251 const machine = new BootstrapStateMachine(); 248 252 saveBootstrapState(phoenixDir, machine); 249 253 254 + // Save architecture choice if specified 255 + const archArg = args?.find(a => a.startsWith('--arch='))?.split('=')[1]; 256 + if (archArg) { 257 + const arch = getArchitecture(archArg); 258 + if (!arch) { 259 + console.log(red(`✖ Unknown architecture: ${archArg}`)); 260 + console.log(` Available: ${listArchitectures().join(', ')}`); 261 + return; 262 + } 263 + const configPath = join(phoenixDir, 'config.json'); 264 + const config = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf8')) : {}; 265 + config.architecture = archArg; 266 + writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8'); 267 + } 268 + 250 269 // Ensure spec/ directory exists 251 270 const specDir = join(projectRoot, 'spec'); 252 271 if (!existsSync(specDir)) { ··· 264 283 console.log(` ${dim('Project root:')} ${projectRoot}`); 265 284 console.log(` ${dim('Phoenix dir:')} ${phoenixDir}`); 266 285 console.log(` ${dim('State:')} ${BootstrapState.BOOTSTRAP_COLD}`); 286 + if (archArg) { 287 + console.log(` ${dim('Architecture:')} ${cyan(archArg)}`); 288 + } 267 289 console.log(); 268 290 console.log(` ${dim('Next steps:')}`); 269 291 console.log(` 1. Add spec documents to ${cyan('spec/')}`); ··· 353 375 console.log(` ${dim(hint)}`); 354 376 } 355 377 378 + // Load architecture from config 379 + const configPath = join(phoenixDir, 'config.json'); 380 + let arch: Architecture | null = null; 381 + if (existsSync(configPath)) { 382 + try { 383 + const config = JSON.parse(readFileSync(configPath, 'utf8')); 384 + if (config.architecture) { 385 + arch = getArchitecture(config.architecture); 386 + if (arch) console.log(` ${dim('Architecture:')} ${cyan(arch.name)} — ${arch.description}`); 387 + } 388 + } catch { /* ignore */ } 389 + } 390 + 356 391 const regenCtx: RegenContext = { 357 392 llm: llm ?? undefined, 358 393 canonNodes, 359 394 allIUs: ius, 360 395 projectRoot, 396 + architecture: arch, 361 397 onProgress: (iu, status, msg) => { 362 398 if (status === 'start') process.stdout.write(` ⏳ ${iu.name}…`); 363 399 else if (status === 'done') process.stdout.write(` ${green('✔')}\n`); ··· 384 420 console.log(` ${dim('Scaffold:')} Service wiring + project config`); 385 421 const services = deriveServices(ius); 386 422 const projectName = basename(projectRoot); 387 - const scaffold = generateScaffold(services, projectName); 423 + const scaffold = generateScaffold(services, projectName, arch); 388 424 for (const [filePath, content] of scaffold.files) { 389 425 const fullPath = join(projectRoot, filePath); 390 426 mkdirSync(join(fullPath, '..'), { recursive: true }); ··· 1433 1469 1434 1470 switch (command) { 1435 1471 case 'init': 1436 - cmdInit(); 1472 + cmdInit(commandArgs); 1437 1473 break; 1438 1474 case 'bootstrap': 1439 1475 await cmdBootstrap();
+39
src/llm/prompt.ts
··· 7 7 8 8 import type { ImplementationUnit } from '../models/iu.js'; 9 9 import type { CanonicalNode } from '../models/canonical.js'; 10 + import type { Architecture } from '../models/architecture.js'; 10 11 11 12 export const SYSTEM_PROMPT = `You are a senior TypeScript engineer generating production-quality module implementations for Phoenix VCS. 12 13 ··· 31 32 /** 32 33 * Build the user prompt for generating an IU implementation. 33 34 */ 35 + /** 36 + * Get the system prompt, optionally extended with architecture-specific rules. 37 + */ 38 + export function getSystemPrompt(arch?: Architecture | null): string { 39 + if (!arch) return SYSTEM_PROMPT; 40 + 41 + const allowedPkgs = Object.keys(arch.packages).map(p => `'${p}'`).join(', '); 42 + 43 + // Build a fresh system prompt for architecture mode — don't try to patch the generic one 44 + return `You are a senior TypeScript engineer generating production-quality module implementations. 45 + 46 + Rules: 47 + - Output ONLY the TypeScript module code. No markdown fences, no explanation. 48 + - The module must be a valid ES module (.ts) that compiles under strict mode. 49 + - Export all public functions and types. 50 + - Use descriptive types (not \`any\` or \`unknown\` where a real type is appropriate). 51 + - Implement the actual logic described in the requirements — not stubs or TODOs. 52 + - Keep the code clean, readable, and minimal. No over-engineering. 53 + - Include the _phoenix metadata constant exactly as specified. 54 + - You MUST import from these packages: ${allowedPkgs}. Use them as shown in the architecture examples below. 55 + - You may also use Node.js built-in modules (node:crypto, node:path, etc.). 56 + - Do NOT import any other packages. Do NOT re-implement functionality that the allowed packages provide. 57 + - Do NOT define your own Hono, Database, or Zod types — import them from the packages. 58 + - The code must compile under TypeScript strict mode (strict: true, no implicit any). 59 + - If the requirements describe validation rules, use Zod schemas. 60 + ${arch.systemPromptExtension}`; 61 + } 62 + 63 + /** 64 + * Build the user prompt for generating an IU implementation. 65 + */ 34 66 export function buildPrompt( 35 67 iu: ImplementationUnit, 36 68 canonNodes: CanonicalNode[], 37 69 siblingModules?: string[], 70 + arch?: Architecture | null, 38 71 ): string { 39 72 const lines: string[] = []; 40 73 ··· 112 145 lines.push(`} as const;`); 113 146 lines.push('```'); 114 147 lines.push(''); 148 + 149 + // Architecture patterns (few-shot examples) 150 + if (arch?.codeExamples) { 151 + lines.push(arch.codeExamples); 152 + lines.push(''); 153 + } 115 154 116 155 lines.push('Output the complete TypeScript module now.'); 117 156
+27
src/models/architecture.ts
··· 1 + /** 2 + * Architecture Target — defines how canonical requirements compile to code. 3 + * 4 + * An architecture target provides the stable patterns, frameworks, and conventions 5 + * that generated code is compiled *into*. The spec says WHAT, the architecture says HOW. 6 + */ 7 + 8 + export interface Architecture { 9 + /** Unique name, e.g., 'sqlite-web-api' */ 10 + name: string; 11 + /** Human description */ 12 + description: string; 13 + /** Runtime platform */ 14 + runtime: string; 15 + /** Production dependencies: package name → version range */ 16 + packages: Record<string, string>; 17 + /** Dev dependencies: package name → version range */ 18 + devPackages: Record<string, string>; 19 + /** Appended to the LLM system prompt — architectural rules and constraints */ 20 + systemPromptExtension: string; 21 + /** Few-shot code examples showing the exact patterns to follow */ 22 + codeExamples: string; 23 + /** Shared boilerplate files: relative path → file content */ 24 + sharedFiles: Record<string, string>; 25 + /** Extra package.json fields (scripts, etc.) */ 26 + packageJsonExtras: Record<string, unknown>; 27 + }
+10 -5
src/regen.ts
··· 17 17 import type { CanonicalNode } from './models/canonical.js'; 18 18 import type { IUManifest, RegenMetadata, FileManifestEntry } from './models/manifest.js'; 19 19 import type { LLMProvider } from './llm/provider.js'; 20 - import { buildPrompt, SYSTEM_PROMPT } from './llm/prompt.js'; 20 + import { buildPrompt, getSystemPrompt } from './llm/prompt.js'; 21 + import type { Architecture } from './models/architecture.js'; 21 22 import { sha256 } from './semhash.js'; 22 23 23 24 const TOOLCHAIN_VERSION = 'phoenix-regen/0.1.0'; ··· 37 38 allIUs?: ImplementationUnit[]; 38 39 /** Project root directory (for typecheck-and-retry). */ 39 40 projectRoot?: string; 41 + /** Architecture target (e.g., sqlite-web-api). */ 42 + architecture?: Architecture | null; 40 43 /** Callback for progress reporting. */ 41 44 onProgress?: (iu: ImplementationUnit, status: 'start' | 'done' | 'error', message?: string) => void; 42 45 } ··· 55 58 if (ctx?.llm && ctx.canonNodes) { 56 59 ctx.onProgress?.(iu, 'start', `Generating ${iu.name} via ${ctx.llm.name}…`); 57 60 try { 58 - content = await generateWithLLM(iu, ctx.llm, ctx.canonNodes, ctx.allIUs, ctx.projectRoot); 61 + content = await generateWithLLM(iu, ctx.llm, ctx.canonNodes, ctx.allIUs, ctx.projectRoot, ctx.architecture); 59 62 ctx.onProgress?.(iu, 'done'); 60 63 } catch (err) { 61 64 const msg = err instanceof Error ? err.message : String(err); ··· 128 131 canonNodes: CanonicalNode[], 129 132 allIUs?: ImplementationUnit[], 130 133 projectRoot?: string, 134 + arch?: Architecture | null, 131 135 ): Promise<string> { 132 136 // Find sibling modules in the same service 133 137 const iuDir = iu.output_files[0]?.split('/').slice(0, -1).join('/'); ··· 135 139 ?.filter(other => other.iu_id !== iu.iu_id && other.output_files[0]?.startsWith(iuDir || '')) 136 140 .map(other => other.name) ?? []; 137 141 138 - const prompt = buildPrompt(iu, canonNodes, siblings); 142 + const systemPrompt = getSystemPrompt(arch); 143 + const prompt = buildPrompt(iu, canonNodes, siblings, arch); 139 144 140 145 let code = cleanCodeResponse(await llm.generate(prompt, { 141 - system: SYSTEM_PROMPT, 146 + system: systemPrompt, 142 147 temperature: 0.2, 143 148 maxTokens: 8192, 144 149 })); ··· 152 157 // Feed errors back to LLM 153 158 const fixPrompt = buildFixPrompt(code, errors); 154 159 code = cleanCodeResponse(await llm.generate(fixPrompt, { 155 - system: SYSTEM_PROMPT, 160 + system: systemPrompt, 156 161 temperature: 0.1, 157 162 maxTokens: 8192, 158 163 }));
+112 -20
src/scaffold.ts
··· 10 10 */ 11 11 12 12 import type { ImplementationUnit } from './models/iu.js'; 13 + import type { Architecture } from './models/architecture.js'; 13 14 import { sha256 } from './semhash.js'; 14 15 15 16 export interface ServiceDescriptor { ··· 70 71 export function generateScaffold( 71 72 services: ServiceDescriptor[], 72 73 projectName: string = 'phoenix-project', 74 + arch?: Architecture | null, 73 75 ): ScaffoldResult { 74 76 const files = new Map<string, string>(); 75 77 78 + // Architecture shared files (db.ts, app.ts, etc.) 79 + if (arch) { 80 + for (const [path, content] of Object.entries(arch.sharedFiles)) { 81 + files.set(path, content); 82 + } 83 + 84 + // Generate architecture-specific server entry point that mounts all generated modules 85 + const routeImports: string[] = []; 86 + const routeMounts: string[] = []; 87 + for (const svc of services) { 88 + for (const mod of svc.modules) { 89 + const modName = mod.replace('.ts', '').replace(/-/g, '_').replace(/[^a-zA-Z0-9_]/g, '_'); 90 + const importPath = `./generated/${svc.dir}/${mod.replace('.ts', '.js')}`; 91 + routeImports.push(`import ${modName} from '${importPath}';`); 92 + // Use the service dir as the route prefix 93 + const prefix = `/${svc.dir}`; 94 + routeMounts.push(`mount('${prefix}', ${modName});`); 95 + } 96 + } 97 + 98 + const serverContent = [ 99 + `import { serve } from '@hono/node-server';`, 100 + `import { app, mount } from './app.js';`, 101 + `import { runMigrations } from './db.js';`, 102 + ``, 103 + `// Generated route modules`, 104 + ...routeImports, 105 + ``, 106 + `// Mount routes`, 107 + ...routeMounts, 108 + ``, 109 + `const port = parseInt(process.env.PORT ?? '3000', 10);`, 110 + `runMigrations();`, 111 + `console.log(\`Server running at http://localhost:\${port}\`);`, 112 + `serve({ fetch: app.fetch, port });`, 113 + ``, 114 + ].join('\n'); 115 + 116 + files.set('src/server.ts', serverContent); 117 + } 118 + 76 119 for (const svc of services) { 77 120 // Service barrel index 78 121 files.set( ··· 80 123 generateServiceIndex(svc), 81 124 ); 82 125 83 - // Service HTTP server 84 - files.set( 85 - `src/generated/${svc.dir}/server.ts`, 86 - generateServiceServer(svc), 87 - ); 126 + if (!arch) { 127 + // Only generate per-service servers when no architecture is set 128 + files.set( 129 + `src/generated/${svc.dir}/server.ts`, 130 + generateServiceServer(svc), 131 + ); 132 + } 88 133 89 134 // Service tests 90 135 files.set( 91 136 `src/generated/${svc.dir}/__tests__/${svc.dir}.test.ts`, 92 - generateServiceTests(svc), 137 + arch ? generateArchTests(svc) : generateServiceTests(svc), 93 138 ); 94 139 } 95 140 ··· 97 142 files.set('src/generated/index.ts', generateRootIndex(services)); 98 143 99 144 // Project config 100 - files.set('package.json', generatePackageJson(services, projectName)); 145 + files.set('package.json', generatePackageJson(services, projectName, arch)); 101 146 files.set('tsconfig.json', generateTsConfig()); 102 147 files.set('vitest.config.ts', generateVitestConfig()); 103 148 104 149 return { files }; 150 + } 151 + 152 + /** 153 + * Generate tests for architecture-based services. 154 + */ 155 + function generateArchTests(svc: ServiceDescriptor): string { 156 + const lines: string[] = []; 157 + lines.push(`/**`); 158 + lines.push(` * ${svc.name} — Generated Tests`); 159 + lines.push(` * AUTO-GENERATED by Phoenix VCS`); 160 + lines.push(` */`); 161 + lines.push(``); 162 + lines.push(`import { describe, it, expect } from 'vitest';`); 163 + 164 + for (const mod of svc.modules) { 165 + const importName = mod.replace('.ts', '').replace(/-/g, '_'); 166 + lines.push(`import ${importName} from '../${mod.replace('.ts', '.js')}';`); 167 + } 168 + 169 + lines.push(``); 170 + lines.push(`describe('${svc.name} modules', () => {`); 171 + 172 + for (const mod of svc.modules) { 173 + const importName = mod.replace('.ts', '').replace(/-/g, '_'); 174 + const displayName = mod.replace('.ts', '').replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); 175 + lines.push(` describe('${displayName}', () => {`); 176 + lines.push(` it('exports a Hono router as default', () => {`); 177 + lines.push(` expect(${importName}).toBeDefined();`); 178 + lines.push(` expect(typeof ${importName}.fetch).toBe('function');`); 179 + lines.push(` });`); 180 + lines.push(` });`); 181 + } 182 + 183 + lines.push(`});`); 184 + lines.push(``); 185 + return lines.join('\n'); 105 186 } 106 187 107 188 // ─── Service Index ─────────────────────────────────────────────────────────── ··· 689 770 function generatePackageJson( 690 771 services: ServiceDescriptor[], 691 772 projectName: string, 773 + arch?: Architecture | null, 692 774 ): string { 693 - const scripts: Record<string, string> = { 775 + let scripts: Record<string, string> = { 694 776 build: 'tsc', 695 777 typecheck: 'tsc --noEmit', 696 778 test: 'vitest run', 697 779 'test:watch': 'vitest', 698 780 }; 699 781 700 - // Add start script per service (build first, then run) 701 - for (const svc of services) { 702 - scripts[`start:${svc.dir}`] = `tsc && node dist/generated/${svc.dir}/server.js`; 782 + if (arch) { 783 + // Architecture provides its own scripts 784 + const archScripts = (arch.packageJsonExtras?.scripts ?? {}) as Record<string, string>; 785 + scripts = { ...scripts, ...archScripts }; 786 + } else { 787 + // Add start script per service (build first, then run) 788 + for (const svc of services) { 789 + scripts[`start:${svc.dir}`] = `tsc && node dist/generated/${svc.dir}/server.js`; 790 + } 791 + if (services.length > 0) { 792 + scripts.start = `tsc && node dist/generated/${services[0].dir}/server.js`; 793 + } 703 794 } 704 795 705 - // Default start = first service 706 - if (services.length > 0) { 707 - scripts.start = `tsc && node dist/generated/${services[0].dir}/server.js`; 708 - } 709 - 710 - const pkg = { 796 + const pkg: Record<string, unknown> = { 711 797 name: projectName, 712 798 version: '0.1.0', 713 799 description: `Generated by Phoenix VCS — ${services.length} services`, 714 800 type: 'module', 715 801 scripts, 716 - devDependencies: { 802 + }; 803 + 804 + if (arch) { 805 + pkg.dependencies = arch.packages; 806 + pkg.devDependencies = arch.devPackages; 807 + } else { 808 + pkg.devDependencies = { 717 809 typescript: '^5.4.0', 718 810 vitest: '^2.0.0', 719 811 '@types/node': '^22.0.0', 720 - }, 721 - }; 812 + }; 813 + } 722 814 723 815 return JSON.stringify(pkg, null, 2) + '\n'; 724 816 }