From 0711002c37b4b00f6f2f8793594b0c090093b397 Mon Sep 17 00:00:00 2001 From: Christopher Monsanto Date: Mon, 17 Aug 2026 17:36:24 -0400 Subject: [PATCH] Drop make-promises-safe and better-sqlite3 Unhandled rejections crash Node by default since v15, and node:sqlite covers the Store: readBigInts replaces defaultSafeIntegers, a manual BEGIN/COMMIT helper replaces transaction(), busy detection keys on errcode, and lookupRule normalizes the null-prototype rows. No native build step remains (allowBuilds gone from the workspace). Co-Authored-By: Claude Fable 5 --- pnpm-lock.yaml | 269 --------------------------------- pnpm-workspace.yaml | 8 +- tools/build/package.json | 2 - tools/build/store.ts | 95 +++++++----- tools/build/test/store.test.ts | 11 +- tools/sheet/index.ts | 1 - tools/sheet/package.json | 3 +- 7 files changed, 70 insertions(+), 319 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 744e9ad6..18c6301f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,18 +39,12 @@ importers: tools/build: dependencies: - '@types/better-sqlite3': - specifier: ^7.6.13 - version: 7.6.13 '@types/debug': specifier: ^4.1.5 version: 4.1.13 '@types/node': specifier: ^24.10.7 version: 24.13.3 - better-sqlite3: - specifier: ^12.4.1 - version: 12.11.1 debug: specifier: ^4.1.1 version: 4.4.3 @@ -84,9 +78,6 @@ importers: '@types/node': specifier: ^24.10.7 version: 24.13.3 - make-promises-safe: - specifier: ^5.1.0 - version: 5.1.0 tools/smogdexspritesheet: dependencies: @@ -111,9 +102,6 @@ importers: packages: - '@types/better-sqlite3@7.6.13': - resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} - '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -326,34 +314,15 @@ packages: resolution: {integrity: sha512-mlmkfc2WqdDtMl/id4qm3A7RjW6jxcbAoMjdRmsPiwQP0ufD4oXItYMnPgVHe80lnAIy+1xwzhHE1s4FoIceSw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - better-sqlite3@12.11.1: - resolution: {integrity: sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==} - engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x || 26.x} - bin-pack@1.0.2: resolution: {integrity: sha512-aOk0SxEon5LF9cMxQFViSKb4qccG6rs7XKyMXIb1J8f8LA2acTIWnHdT0IOTe4gYBbqgjdbuTZ5f+UP+vlh4Mw==} - bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - clone-stats@0.0.1: resolution: {integrity: sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==} @@ -398,35 +367,16 @@ packages: supports-color: optional: true - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - events-universal@1.0.1: resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} - expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -443,9 +393,6 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - first-chunk-stream@1.0.0: resolution: {integrity: sha512-ArRi5axuv66gEsyl3UuK80CzW7t56hem73YGNYxNWTGNKFJUadSb9Gu9SHijYEUi8ulQMf1bJomYNwSCPHhtTQ==} engines: {node: '>=0.10.0'} @@ -457,9 +404,6 @@ packages: resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} engines: {node: '>= 0.12'} - fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - get-pixels@3.3.3: resolution: {integrity: sha512-5kyGBn90i9tSMUVHTqkgCHsoWoR+/lGbl4yC83Gefyr0HLIhgSWEx/2F/3YgsZ7UpYNuM6pDhDK7zebrUJ5nXg==} @@ -470,9 +414,6 @@ packages: resolution: {integrity: sha512-HMfSa+EIng62NbDhM63QGYoc49/m8DcZ9hhBtw+CXX9mKboSpeFVxjZ2WEWaMFZ14MUjfACK7jsrxrJffIVrCg==} engines: {node: '>= 0.8.0'} - github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -489,15 +430,9 @@ packages: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} engines: {node: '>=0.8', npm: '>=1.3.7'} - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - iota-array@1.0.0: resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} @@ -547,9 +482,6 @@ packages: resolution: {integrity: sha512-+kdgg25XW11BA4cl9vF+SH01HaBipld2Nf/PlU2kSYncAbdUbDoahzrlh6yhR93N/wR2TGgcFoxebzR1LKmZUg==} engines: {node: '>= 0.8.0'} - make-promises-safe@5.1.0: - resolution: {integrity: sha512-AfdZ49rtyhQR/6cqVKGoH7y4ql7XkS5HJI1lZm0/5N6CQosy1eYbBJ/qbhkKHzo17UH7M918Bysf6XB9f3kS1g==} - mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -558,22 +490,9 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - napi-build-utils@2.0.0: - resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} - ndarray-ops@1.2.2: resolution: {integrity: sha512-BppWAFRjMYF7N/r6Ie51q6D4fs0iiGmeXIACKY66fLpnwIui3Wc3CXiD/30mgLbDjPpSLrsqcp3Z62+IcHZsDw==} @@ -583,10 +502,6 @@ packages: ndarray@1.0.19: resolution: {integrity: sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==} - node-abi@3.94.0: - resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} - engines: {node: '>=10'} - node-bitmap@0.0.1: resolution: {integrity: sha512-Jx5lPaaLdIaOsj2mVLWMWulXF6GQVdyLvNSxmiYCvZ8Ma2hfKX0POoR2kgKOqz+oFsRreq0yYZjQ2wjE9VNzCA==} engines: {node: '>=v0.6.5'} @@ -600,9 +515,6 @@ packages: omggif@1.0.10: resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - parse-data-uri@0.2.0: resolution: {integrity: sha512-uOtts8NqDcaCt1rIsO3VFDRsAfgE4c6osG4d9z3l4dCBlxYFzni6Di/oNU270SDrjkfZuUvLZx1rxMyqh46Y9w==} @@ -621,12 +533,6 @@ packages: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} - prebuild-install@7.1.3: - resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} - engines: {node: '>=10'} - deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. - hasBin: true - process-nextick-args@1.0.7: resolution: {integrity: sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==} @@ -636,9 +542,6 @@ packages: psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -647,10 +550,6 @@ packages: resolution: {integrity: sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==} engines: {node: '>=0.6'} - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - readable-stream@1.0.34: resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} @@ -663,10 +562,6 @@ packages: readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - replace-ext@0.0.1: resolution: {integrity: sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==} engines: {node: '>= 0.4'} @@ -692,17 +587,6 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - semver@7.8.5: - resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} - engines: {node: '>=10'} - hasBin: true - - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - spritesmith@3.5.1: resolution: {integrity: sha512-FrzGx9cD5SkH3Kxuk24vJJLBYHLyDskUJ2t6DSWfWkCd8+yFQAfBGVE7F0IhOpKu+aq1CZ9rgXnpaa4luIQgGg==} engines: {node: '>= 4.0.0'} @@ -721,9 +605,6 @@ packages: string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-bom-stream@1.0.0: resolution: {integrity: sha512-7jfJB9YpI2Z0aH3wu10ZqitvYJaE0s5IzFuWE+0pbb4Q/armTloEUShymkDO47YSLnjAW52mlXT//hs9wXNNJQ==} engines: {node: '>=0.10.0'} @@ -732,17 +613,6 @@ packages: resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} engines: {node: '>=0.10.0'} - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - tar-fs@2.1.5: - resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==} - - tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - tar-stream@3.2.0: resolution: {integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==} @@ -809,19 +679,12 @@ packages: resolution: {integrity: sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==} engines: {node: '>= 0.9'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} snapshots: - '@types/better-sqlite3@7.6.13': - dependencies: - '@types/node': 24.13.3 - '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -963,38 +826,14 @@ snapshots: dependencies: to-data-view: 2.0.0 - base64-js@1.5.1: {} - bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 - better-sqlite3@12.11.1: - dependencies: - bindings: 1.5.0 - prebuild-install: 7.1.3 - bin-pack@1.0.2: {} - bindings@1.5.0: - dependencies: - file-uri-to-path: 1.0.0 - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - caseless@0.12.0: {} - chownr@1.1.4: {} - clone-stats@0.0.1: {} clone@1.0.4: {} @@ -1031,33 +870,19 @@ snapshots: dependencies: ms: 2.1.3 - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - - deep-extend@0.6.0: {} - delayed-stream@1.0.0: {} - detect-libc@2.1.2: {} - ecc-jsbn@0.1.2: dependencies: jsbn: 0.1.1 safer-buffer: 2.1.2 - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - events-universal@1.0.1: dependencies: bare-events: 2.9.1 transitivePeerDependencies: - bare-abort-controller - expand-template@2.0.3: {} - extend@3.0.2: {} extsprintf@1.3.0: {} @@ -1068,8 +893,6 @@ snapshots: fast-json-stable-stringify@2.1.0: {} - file-uri-to-path@1.0.0: {} - first-chunk-stream@1.0.0: {} forever-agent@0.6.1: {} @@ -1080,8 +903,6 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - fs-constants@1.0.0: {} - get-pixels@3.3.3: dependencies: data-uri-to-buffer: 0.0.3 @@ -1104,8 +925,6 @@ snapshots: dependencies: readable-stream: 1.1.14 - github-from-package@0.0.0: {} - graceful-fs@4.2.11: {} har-schema@2.0.0: {} @@ -1121,12 +940,8 @@ snapshots: jsprim: 1.4.2 sshpk: 1.18.0 - ieee754@1.2.1: {} - inherits@2.0.4: {} - ini@1.3.8: {} - iota-array@1.0.0: {} is-buffer@1.1.6: {} @@ -1164,24 +979,14 @@ snapshots: dependencies: bin-pack: 1.0.2 - make-promises-safe@5.1.0: {} - mime-db@1.52.0: {} mime-types@2.1.35: dependencies: mime-db: 1.52.0 - mimic-response@3.1.0: {} - - minimist@1.2.8: {} - - mkdirp-classic@0.5.3: {} - ms@2.1.3: {} - napi-build-utils@2.0.0: {} - ndarray-ops@1.2.2: dependencies: cwise-compiler: 1.1.3 @@ -1196,10 +1001,6 @@ snapshots: iota-array: 1.0.0 is-buffer: 1.1.6 - node-abi@3.94.0: - dependencies: - semver: 7.8.5 - node-bitmap@0.0.1: {} oauth-sign@0.9.0: {} @@ -1208,10 +1009,6 @@ snapshots: omggif@1.0.10: {} - once@1.4.0: - dependencies: - wrappy: 1.0.2 - parse-data-uri@0.2.0: dependencies: data-uri-to-buffer: 0.0.3 @@ -1233,21 +1030,6 @@ snapshots: pngjs@3.4.0: {} - prebuild-install@7.1.3: - dependencies: - detect-libc: 2.1.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 2.0.0 - node-abi: 3.94.0 - pump: 3.0.4 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.5 - tunnel-agent: 0.6.0 - process-nextick-args@1.0.7: {} process-nextick-args@2.0.1: {} @@ -1256,22 +1038,10 @@ snapshots: dependencies: punycode: 2.3.1 - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - punycode@2.3.1: {} qs@6.5.5: {} - rc@1.2.8: - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - readable-stream@1.0.34: dependencies: core-util-is: 1.0.3 @@ -1305,12 +1075,6 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - replace-ext@0.0.1: {} request@2.88.2: @@ -1354,16 +1118,6 @@ snapshots: semver@5.7.2: {} - semver@7.8.5: {} - - simple-concat@1.0.1: {} - - simple-get@4.0.1: - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - spritesmith@3.5.1: dependencies: concat-stream: 1.5.2 @@ -1399,10 +1153,6 @@ snapshots: dependencies: safe-buffer: 5.1.2 - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - strip-bom-stream@1.0.0: dependencies: first-chunk-stream: 1.0.0 @@ -1412,23 +1162,6 @@ snapshots: dependencies: is-utf8: 0.2.1 - strip-json-comments@2.0.1: {} - - tar-fs@2.1.5: - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.4 - tar-stream: 2.2.0 - - tar-stream@2.2.0: - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.5 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - tar-stream@3.2.0: dependencies: b4a: 1.8.1 @@ -1529,6 +1262,4 @@ snapshots: clone-stats: 0.0.1 replace-ext: 0.0.1 - wrappy@1.0.2: {} - xtend@4.0.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f2b045c2..9fe7d5e0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,6 @@ packages: - - 'tools/*' - - 'lib/*' - - "data/lib" + - 'tools/*' + - 'lib/*' + - "data/lib" allowBuilds: - better-sqlite3: true + better-sqlite3: set this to true or false diff --git a/tools/build/package.json b/tools/build/package.json index 50fa4957..fa68074f 100644 --- a/tools/build/package.json +++ b/tools/build/package.json @@ -1,9 +1,7 @@ { "dependencies": { - "@types/better-sqlite3": "^7.6.13", "@types/debug": "^4.1.5", "@types/node": "^24.10.7", - "better-sqlite3": "^12.4.1", "debug": "^4.1.1" }, "scripts": { diff --git a/tools/build/store.ts b/tools/build/store.ts index 13dc6e21..eea64bfb 100644 --- a/tools/build/store.ts +++ b/tools/build/store.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import pathlib from 'path'; -import Database from 'better-sqlite3'; +import {DatabaseSync} from 'node:sqlite'; import {BuildError} from './errors.ts'; import type {FileStat} from './hash.ts'; @@ -39,21 +39,37 @@ CREATE TABLE IF NOT EXISTS rule_outputs ( ); `; +function userVersion(db : DatabaseSync) : number { + const row = db.prepare('PRAGMA user_version').get() as {user_version : bigint | number}; + return Number(row.user_version); +} + export class Store { - private db : Database.Database; + private db : DatabaseSync; constructor(dbPath : string) { fs.mkdirSync(pathlib.dirname(dbPath), {recursive: true}); - this.db = new Database(dbPath); - this.db.defaultSafeIntegers(true); - this.db.pragma('journal_mode = WAL'); - this.db.pragma('foreign_keys = ON'); - this.db.pragma('synchronous = NORMAL'); + this.db = new DatabaseSync(dbPath, {readBigInts: true}); + this.db.exec('PRAGMA journal_mode = WAL'); + this.db.exec('PRAGMA foreign_keys = ON'); + this.db.exec('PRAGMA synchronous = NORMAL'); this.migrate(); } + private transaction(fn : () => T) : T { + this.db.exec('BEGIN'); + try { + const result = fn(); + this.db.exec('COMMIT'); + return result; + } catch (err) { + this.db.exec('ROLLBACK'); + throw err; + } + } + private migrate() : void { - const version = Number(this.db.pragma('user_version', {simple: true})); + const version = userVersion(this.db); if (version === 0) { this.db.exec('BEGIN;' + DDL + 'PRAGMA user_version = 2; COMMIT;'); } else if (version === 1) { @@ -74,10 +90,12 @@ export class Store { loadFileCache() : Map { const result = new Map(); - const rows = this.db.prepare<[], {path : string, size : bigint, mtime_ns : bigint, hash : Buffer}>( - 'SELECT path, size, mtime_ns, hash FROM file_cache').all(); + const rows = this.db.prepare('SELECT path, size, mtime_ns, hash FROM file_cache').all() as + unknown as {path : string, size : bigint, mtime_ns : bigint, hash : Uint8Array}[]; for (const row of rows) { - result.set(row.path, {size: row.size, mtimeNs: row.mtime_ns, hash: row.hash}); + const h = row.hash; + result.set(row.path, {size: row.size, mtimeNs: row.mtime_ns, + hash: Buffer.from(h.buffer, h.byteOffset, h.byteLength)}); } return result; } @@ -87,79 +105,84 @@ export class Store { INSERT INTO file_cache (path, size, mtime_ns, hash) VALUES (?, ?, ?, ?) ON CONFLICT(path) DO UPDATE SET size = excluded.size, mtime_ns = excluded.mtime_ns, hash = excluded.hash`); - this.db.transaction(() => { + this.transaction(() => { for (const [path, stat] of entries) { upsert.run(path, stat.size, stat.mtimeNs, stat.hash); } - })(); + }); } pruneFileCache(live : Set) : void { - const paths = this.db.prepare<[], {path : string}>('SELECT path FROM file_cache').all(); + const paths = this.db.prepare('SELECT path FROM file_cache').all() as + unknown as {path : string}[]; const del = this.db.prepare('DELETE FROM file_cache WHERE path = ?'); - this.db.transaction(() => { + this.transaction(() => { for (const {path} of paths) { if (!live.has(path)) { del.run(path); } } - })(); + }); } lookupRule(key : string) : StoredOutput[] | null { - return this.db.transaction(() => { - const rule = this.db.prepare<[string], {id : bigint}>( - 'SELECT id FROM rules WHERE key = ?').get(key); + return this.transaction(() => { + const rule = this.db.prepare('SELECT id FROM rules WHERE key = ?').get(key) as + {id : bigint} | undefined; if (rule === undefined) { return null; } - return this.db.prepare<[bigint], StoredOutput>( - 'SELECT digest, ext, size FROM rule_outputs WHERE rule_id = ? ORDER BY ord').all(rule.id); - })(); + const rows = this.db.prepare( + 'SELECT digest, ext, size FROM rule_outputs WHERE rule_id = ? ORDER BY ord') + .all(rule.id) as unknown as StoredOutput[]; + // node:sqlite rows have a null prototype; return plain objects. + return rows.map(r => ({digest: r.digest, ext: r.ext, size: r.size})); + }); } // One transaction per completed rule: an interrupted build only ever // contains fully-recorded rules. recordRule(key : string, cmds : string[], outputs : StoredOutput[]) : void { - const upsert = this.db.prepare<[string, string], {id : bigint}>(` + const upsert = this.db.prepare(` INSERT INTO rules (key, cmds) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET cmds = excluded.cmds RETURNING id`); const delOutputs = this.db.prepare('DELETE FROM rule_outputs WHERE rule_id = ?'); const insOutput = this.db.prepare( 'INSERT INTO rule_outputs (rule_id, ord, digest, ext, size) VALUES (?, ?, ?, ?, ?)'); - this.db.transaction(() => { - const {id} = upsert.get(key, cmds.join('\n'))!; + this.transaction(() => { + const {id} = upsert.get(key, cmds.join('\n')) as {id : bigint}; delOutputs.run(id); outputs.forEach((o, i) => insOutput.run(id, i, o.digest, o.ext, o.size)); - })(); + }); } // GC: drop every rule whose key is not live. Returns the removal count. deleteKeysNotIn(live : Set) : number { - const keys = this.db.prepare<[], {id : bigint, key : string}>('SELECT id, key FROM rules').all(); + const keys = this.db.prepare('SELECT id, key FROM rules').all() as + unknown as {id : bigint, key : string}[]; const del = this.db.prepare('DELETE FROM rules WHERE id = ?'); let removed = 0; - this.db.transaction(() => { + this.transaction(() => { for (const {id, key} of keys) { if (!live.has(key)) { del.run(id); removed++; } } - })(); + }); return removed; } // Every CAS object referenced by some rule, as "." basenames. liveObjects() : Set { - const rows = this.db.prepare<[], {digest : string, ext : string}>( - 'SELECT digest, ext FROM rule_outputs').all(); + const rows = this.db.prepare('SELECT digest, ext FROM rule_outputs').all() as + unknown as {digest : string, ext : string}[]; return new Set(rows.map(r => `${r.digest}.${r.ext}`)); } close() : void { - this.db.pragma('wal_checkpoint(TRUNCATE)'); + this.db.exec('PRAGMA wal_checkpoint(TRUNCATE)'); this.db.close(); } } @@ -170,9 +193,9 @@ export function dbVersion(dbPath : string) : number | null { if (!fs.existsSync(dbPath)) { return null; } - const db = new Database(dbPath, {readonly: true}); + const db = new DatabaseSync(dbPath, {readOnly: true}); try { - return Number(db.pragma('user_version', {simple: true})); + return userVersion(db); } finally { db.close(); } @@ -182,12 +205,12 @@ export function dbVersion(dbPath : string) : number | null { // by the OS on any crash, so there are no stale lock files. export function acquireLock(lockPath : string) : () => void { fs.mkdirSync(pathlib.dirname(lockPath), {recursive: true}); - const lock = new Database(lockPath, {timeout: 0}); + const lock = new DatabaseSync(lockPath, {timeout: 0}); try { lock.exec('BEGIN EXCLUSIVE'); } catch (err) { lock.close(); - if ((err as {code? : string}).code === 'SQLITE_BUSY') { + if ((err as {errcode? : number}).errcode === 5) { // SQLITE_BUSY throw new BuildError('Another build is already running.'); } throw err; diff --git a/tools/build/test/store.test.ts b/tools/build/test/store.test.ts index c75709f0..d9203abd 100644 --- a/tools/build/test/store.test.ts +++ b/tools/build/test/store.test.ts @@ -5,7 +5,7 @@ import os from 'node:os'; import pathlib from 'node:path'; import {test} from 'node:test'; -import Database from 'better-sqlite3'; +import {DatabaseSync} from 'node:sqlite'; import {Store} from '../store.ts'; @@ -45,7 +45,7 @@ test('file cache roundtrip and prune', () => { test('migrates a v1 db: drops rule tables, keeps file_cache', () => { const dbPath = makeDbPath(); - const v1 = new Database(dbPath); + const v1 = new DatabaseSync(dbPath); v1.exec(`BEGIN; CREATE TABLE file_cache ( path TEXT PRIMARY KEY, size INTEGER NOT NULL, @@ -81,14 +81,15 @@ test('migrates a v1 db: drops rule tables, keeps file_cache', () => { assert.deepEqual(store.lookupRule('new'), [{digest: 'd', ext: 'png', size: 1n}]); store.close(); - const check = new Database(dbPath); - assert.equal(Number(check.pragma('user_version', {simple: true})), 2); + const check = new DatabaseSync(dbPath); + const {user_version} = check.prepare('PRAGMA user_version').get() as {user_version : number}; + assert.equal(Number(user_version), 2); check.close(); }); test('rejects unknown schema versions', () => { const dbPath = makeDbPath(); - const weird = new Database(dbPath); + const weird = new DatabaseSync(dbPath); weird.exec('PRAGMA user_version = 7'); weird.close(); assert.throws(() => new Store(dbPath), /Unknown build db schema version 7/); diff --git a/tools/sheet/index.ts b/tools/sheet/index.ts index a37a605e..b98256cd 100644 --- a/tools/sheet/index.ts +++ b/tools/sheet/index.ts @@ -1,5 +1,4 @@ -import 'make-promises-safe'; import cp from 'child_process'; import path from 'path'; diff --git a/tools/sheet/package.json b/tools/sheet/package.json index e11f0fca..5432c01b 100644 --- a/tools/sheet/package.json +++ b/tools/sheet/package.json @@ -1,7 +1,6 @@ { "type": "module", "dependencies": { - "@types/node": "^24.10.7", - "make-promises-safe": "^5.1.0" + "@types/node": "^24.10.7" } }