├── .github └── workflows │ ├── CI.yml │ └── codeql.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── sql ├── createTable.pb.sql ├── createTable.sql ├── insertRow.pb.sql ├── insertRow.sql ├── setup.pb.sql └── setup.sql ├── src ├── format │ ├── detectPbWriteQuery.ts │ ├── expectReplaceAll.ts │ ├── pbQueryToSql.ts │ └── test │ │ ├── expectReplaceAll.local.test.ts │ │ └── pbQueryToSql.local.test.ts ├── index.ts └── test │ ├── compareDb.ts │ ├── delay.ts │ ├── getPbSetupLog.ts │ ├── local │ └── turboBase.local.test.ts │ ├── localTurso.ts │ ├── readFileFormatted.ts │ └── replicateSetup.ts ├── tsconfig.json └── tsconfig.types.json /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: [20.x] 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Use Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | cache: 'npm' 22 | - run: npm i 23 | - run: npm run test:local 24 | - run: npm run tsc 25 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | analyze: 11 | name: Analyze 12 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 13 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 14 | permissions: 15 | security-events: write 16 | actions: read 17 | contents: read 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | language: [ 'javascript-typescript' ] 23 | steps: 24 | - name: Checkout repository 25 | uses: actions/checkout@v4 26 | - name: Initialize CodeQL 27 | uses: github/codeql-action/init@v3 28 | with: 29 | languages: ${{ matrix.language }} 30 | - name: Autobuild 31 | uses: github/codeql-action/autobuild@v3 32 | - name: Perform CodeQL Analysis 33 | uses: github/codeql-action/analyze@v3 34 | with: 35 | category: "/language:${{matrix.language}}" 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Test folders 2 | .local 3 | .remote 4 | 5 | # Typescript output 6 | dist 7 | 8 | # Node dependencies 9 | **/node_modules 10 | 11 | # Env variables 12 | .env 13 | .env.* 14 | 15 | .DS_Store 16 | 17 | # Misc 18 | **/fullstack 19 | dockerfile 20 | .dockerignore 21 | compose.yml 22 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Do not include src folder 2 | src 3 | 4 | # Do not include sql scripts 5 | sql 6 | 7 | # Test folders 8 | .local 9 | .remote 10 | 11 | # Do not include test scripts 12 | **/test 13 | 14 | # Node dependencies 15 | **/node_modules 16 | 17 | # Env variables 18 | .env 19 | .env.* 20 | 21 | .DS_Store 22 | 23 | # Misc 24 | **/fullstack 25 | dockerfile 26 | .dockerignore 27 | compose.yml 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Meng Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TursoBase 2 | 3 | **Recommend using an auth library instead. Eg: Lucia + Turso. Real time websockets are platform specific, so that would require some backend architecting** 4 | 5 | Sync your PocketBase data with Turso. This library enables distributed PocketBase with Turso primary database as master. 6 | 7 | Note: PocketBase is not designed to be distributed. 8 | This test package is highly experimental. 9 | 10 | ## Motivation 11 | 12 | I intend to use PocketBase only for oauth2 and require app scalability. Turso enables replicas. 13 | 14 | ## Usage 15 | 16 | Install node package 17 | `npm i tursobase` 18 | 19 | 20 | ``` 21 | import { tursoBase } from "tursobase" 22 | 23 | const tursoClient = createClient({ 24 | url: "file:pb_data/data.db", 25 | syncUrl: process.env.TURSO_SYNC_URL, 26 | authToken: process.env.TURSO_AUTH_TOKEN, 27 | }) 28 | 29 | const pbProcess = await tursoBase("pb_data", 8090, tursoClient) 30 | ``` 31 | 32 | Stopping process 33 | ``` 34 | const pbProcess = await tursoBase("pb_data", 8090, tursoClient) 35 | pbProcess.kill() 36 | ``` 37 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tursobase", 3 | "version": "0.1.10", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "tursobase", 9 | "version": "0.1.10", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@libsql/client": "^0.5.1" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^20.11.20", 16 | "oxlint": "^0.2.10", 17 | "prettier": "^3.2.5", 18 | "typescript": "^5.3.3", 19 | "vitest": "^1.3.1" 20 | } 21 | }, 22 | "node_modules/@esbuild/aix-ppc64": { 23 | "version": "0.19.12", 24 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", 25 | "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", 26 | "cpu": [ 27 | "ppc64" 28 | ], 29 | "dev": true, 30 | "optional": true, 31 | "os": [ 32 | "aix" 33 | ], 34 | "engines": { 35 | "node": ">=12" 36 | } 37 | }, 38 | "node_modules/@esbuild/android-arm": { 39 | "version": "0.19.12", 40 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", 41 | "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", 42 | "cpu": [ 43 | "arm" 44 | ], 45 | "dev": true, 46 | "optional": true, 47 | "os": [ 48 | "android" 49 | ], 50 | "engines": { 51 | "node": ">=12" 52 | } 53 | }, 54 | "node_modules/@esbuild/android-arm64": { 55 | "version": "0.19.12", 56 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", 57 | "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", 58 | "cpu": [ 59 | "arm64" 60 | ], 61 | "dev": true, 62 | "optional": true, 63 | "os": [ 64 | "android" 65 | ], 66 | "engines": { 67 | "node": ">=12" 68 | } 69 | }, 70 | "node_modules/@esbuild/android-x64": { 71 | "version": "0.19.12", 72 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", 73 | "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", 74 | "cpu": [ 75 | "x64" 76 | ], 77 | "dev": true, 78 | "optional": true, 79 | "os": [ 80 | "android" 81 | ], 82 | "engines": { 83 | "node": ">=12" 84 | } 85 | }, 86 | "node_modules/@esbuild/darwin-arm64": { 87 | "version": "0.19.12", 88 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", 89 | "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", 90 | "cpu": [ 91 | "arm64" 92 | ], 93 | "dev": true, 94 | "optional": true, 95 | "os": [ 96 | "darwin" 97 | ], 98 | "engines": { 99 | "node": ">=12" 100 | } 101 | }, 102 | "node_modules/@esbuild/darwin-x64": { 103 | "version": "0.19.12", 104 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", 105 | "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", 106 | "cpu": [ 107 | "x64" 108 | ], 109 | "dev": true, 110 | "optional": true, 111 | "os": [ 112 | "darwin" 113 | ], 114 | "engines": { 115 | "node": ">=12" 116 | } 117 | }, 118 | "node_modules/@esbuild/freebsd-arm64": { 119 | "version": "0.19.12", 120 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", 121 | "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", 122 | "cpu": [ 123 | "arm64" 124 | ], 125 | "dev": true, 126 | "optional": true, 127 | "os": [ 128 | "freebsd" 129 | ], 130 | "engines": { 131 | "node": ">=12" 132 | } 133 | }, 134 | "node_modules/@esbuild/freebsd-x64": { 135 | "version": "0.19.12", 136 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", 137 | "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", 138 | "cpu": [ 139 | "x64" 140 | ], 141 | "dev": true, 142 | "optional": true, 143 | "os": [ 144 | "freebsd" 145 | ], 146 | "engines": { 147 | "node": ">=12" 148 | } 149 | }, 150 | "node_modules/@esbuild/linux-arm": { 151 | "version": "0.19.12", 152 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", 153 | "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", 154 | "cpu": [ 155 | "arm" 156 | ], 157 | "dev": true, 158 | "optional": true, 159 | "os": [ 160 | "linux" 161 | ], 162 | "engines": { 163 | "node": ">=12" 164 | } 165 | }, 166 | "node_modules/@esbuild/linux-arm64": { 167 | "version": "0.19.12", 168 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", 169 | "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", 170 | "cpu": [ 171 | "arm64" 172 | ], 173 | "dev": true, 174 | "optional": true, 175 | "os": [ 176 | "linux" 177 | ], 178 | "engines": { 179 | "node": ">=12" 180 | } 181 | }, 182 | "node_modules/@esbuild/linux-ia32": { 183 | "version": "0.19.12", 184 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", 185 | "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", 186 | "cpu": [ 187 | "ia32" 188 | ], 189 | "dev": true, 190 | "optional": true, 191 | "os": [ 192 | "linux" 193 | ], 194 | "engines": { 195 | "node": ">=12" 196 | } 197 | }, 198 | "node_modules/@esbuild/linux-loong64": { 199 | "version": "0.19.12", 200 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", 201 | "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", 202 | "cpu": [ 203 | "loong64" 204 | ], 205 | "dev": true, 206 | "optional": true, 207 | "os": [ 208 | "linux" 209 | ], 210 | "engines": { 211 | "node": ">=12" 212 | } 213 | }, 214 | "node_modules/@esbuild/linux-mips64el": { 215 | "version": "0.19.12", 216 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", 217 | "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", 218 | "cpu": [ 219 | "mips64el" 220 | ], 221 | "dev": true, 222 | "optional": true, 223 | "os": [ 224 | "linux" 225 | ], 226 | "engines": { 227 | "node": ">=12" 228 | } 229 | }, 230 | "node_modules/@esbuild/linux-ppc64": { 231 | "version": "0.19.12", 232 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", 233 | "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", 234 | "cpu": [ 235 | "ppc64" 236 | ], 237 | "dev": true, 238 | "optional": true, 239 | "os": [ 240 | "linux" 241 | ], 242 | "engines": { 243 | "node": ">=12" 244 | } 245 | }, 246 | "node_modules/@esbuild/linux-riscv64": { 247 | "version": "0.19.12", 248 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", 249 | "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", 250 | "cpu": [ 251 | "riscv64" 252 | ], 253 | "dev": true, 254 | "optional": true, 255 | "os": [ 256 | "linux" 257 | ], 258 | "engines": { 259 | "node": ">=12" 260 | } 261 | }, 262 | "node_modules/@esbuild/linux-s390x": { 263 | "version": "0.19.12", 264 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", 265 | "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", 266 | "cpu": [ 267 | "s390x" 268 | ], 269 | "dev": true, 270 | "optional": true, 271 | "os": [ 272 | "linux" 273 | ], 274 | "engines": { 275 | "node": ">=12" 276 | } 277 | }, 278 | "node_modules/@esbuild/linux-x64": { 279 | "version": "0.19.12", 280 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", 281 | "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", 282 | "cpu": [ 283 | "x64" 284 | ], 285 | "dev": true, 286 | "optional": true, 287 | "os": [ 288 | "linux" 289 | ], 290 | "engines": { 291 | "node": ">=12" 292 | } 293 | }, 294 | "node_modules/@esbuild/netbsd-x64": { 295 | "version": "0.19.12", 296 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", 297 | "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", 298 | "cpu": [ 299 | "x64" 300 | ], 301 | "dev": true, 302 | "optional": true, 303 | "os": [ 304 | "netbsd" 305 | ], 306 | "engines": { 307 | "node": ">=12" 308 | } 309 | }, 310 | "node_modules/@esbuild/openbsd-x64": { 311 | "version": "0.19.12", 312 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", 313 | "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", 314 | "cpu": [ 315 | "x64" 316 | ], 317 | "dev": true, 318 | "optional": true, 319 | "os": [ 320 | "openbsd" 321 | ], 322 | "engines": { 323 | "node": ">=12" 324 | } 325 | }, 326 | "node_modules/@esbuild/sunos-x64": { 327 | "version": "0.19.12", 328 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", 329 | "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", 330 | "cpu": [ 331 | "x64" 332 | ], 333 | "dev": true, 334 | "optional": true, 335 | "os": [ 336 | "sunos" 337 | ], 338 | "engines": { 339 | "node": ">=12" 340 | } 341 | }, 342 | "node_modules/@esbuild/win32-arm64": { 343 | "version": "0.19.12", 344 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", 345 | "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", 346 | "cpu": [ 347 | "arm64" 348 | ], 349 | "dev": true, 350 | "optional": true, 351 | "os": [ 352 | "win32" 353 | ], 354 | "engines": { 355 | "node": ">=12" 356 | } 357 | }, 358 | "node_modules/@esbuild/win32-ia32": { 359 | "version": "0.19.12", 360 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", 361 | "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", 362 | "cpu": [ 363 | "ia32" 364 | ], 365 | "dev": true, 366 | "optional": true, 367 | "os": [ 368 | "win32" 369 | ], 370 | "engines": { 371 | "node": ">=12" 372 | } 373 | }, 374 | "node_modules/@esbuild/win32-x64": { 375 | "version": "0.19.12", 376 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", 377 | "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", 378 | "cpu": [ 379 | "x64" 380 | ], 381 | "dev": true, 382 | "optional": true, 383 | "os": [ 384 | "win32" 385 | ], 386 | "engines": { 387 | "node": ">=12" 388 | } 389 | }, 390 | "node_modules/@jest/schemas": { 391 | "version": "29.6.3", 392 | "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", 393 | "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", 394 | "dev": true, 395 | "dependencies": { 396 | "@sinclair/typebox": "^0.27.8" 397 | }, 398 | "engines": { 399 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 400 | } 401 | }, 402 | "node_modules/@jridgewell/sourcemap-codec": { 403 | "version": "1.4.15", 404 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 405 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 406 | "dev": true 407 | }, 408 | "node_modules/@libsql/client": { 409 | "version": "0.5.1", 410 | "resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.5.1.tgz", 411 | "integrity": "sha512-gzdQVPVi/64BRKP6sg+JvHTht95OHNjaldjhBrfB79H8hc/djUwWYuo9+C/+zCQ73IR+js2xTtUgNzn8bLZ/7A==", 412 | "dependencies": { 413 | "@libsql/core": "^0.5.1", 414 | "@libsql/hrana-client": "^0.5.6", 415 | "js-base64": "^3.7.5", 416 | "libsql": "^0.3.2" 417 | } 418 | }, 419 | "node_modules/@libsql/core": { 420 | "version": "0.5.1", 421 | "resolved": "https://registry.npmjs.org/@libsql/core/-/core-0.5.1.tgz", 422 | "integrity": "sha512-oEkns102z5bLbGSQjZGAm4Ce+TwOuA8g7a86dRkGtEhOSIErw21yL0+t1oYrPtOXluDtTQ80cTvru8EoMMr78Q==", 423 | "dependencies": { 424 | "js-base64": "^3.7.5" 425 | } 426 | }, 427 | "node_modules/@libsql/darwin-arm64": { 428 | "version": "0.3.2", 429 | "resolved": "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.3.2.tgz", 430 | "integrity": "sha512-w5CTHTM7mBovE0W3Sz/71DPF1fmfQFZtAFCHz+TI+X19PLNFsozBD73xkHdpX4fED5+NejCI58Q8sNYj6g26QQ==", 431 | "cpu": [ 432 | "arm64" 433 | ], 434 | "optional": true, 435 | "os": [ 436 | "darwin" 437 | ] 438 | }, 439 | "node_modules/@libsql/darwin-x64": { 440 | "version": "0.3.2", 441 | "resolved": "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.3.2.tgz", 442 | "integrity": "sha512-2Ts7uzeKgZ7MFMxaRFpokr8cAsut7jbi2PIWyCq/XmPpWrQUZBEnNCEwuJMVbj+yew6lf4E3PGQlRHJDLIds/A==", 443 | "cpu": [ 444 | "x64" 445 | ], 446 | "optional": true, 447 | "os": [ 448 | "darwin" 449 | ] 450 | }, 451 | "node_modules/@libsql/hrana-client": { 452 | "version": "0.5.6", 453 | "resolved": "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.5.6.tgz", 454 | "integrity": "sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==", 455 | "dependencies": { 456 | "@libsql/isomorphic-fetch": "^0.1.12", 457 | "@libsql/isomorphic-ws": "^0.1.5", 458 | "js-base64": "^3.7.5", 459 | "node-fetch": "^3.3.2" 460 | } 461 | }, 462 | "node_modules/@libsql/isomorphic-fetch": { 463 | "version": "0.1.12", 464 | "resolved": "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.1.12.tgz", 465 | "integrity": "sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==", 466 | "dependencies": { 467 | "@types/node-fetch": "^2.6.11", 468 | "node-fetch": "^2.7.0" 469 | } 470 | }, 471 | "node_modules/@libsql/isomorphic-fetch/node_modules/node-fetch": { 472 | "version": "2.7.0", 473 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 474 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 475 | "dependencies": { 476 | "whatwg-url": "^5.0.0" 477 | }, 478 | "engines": { 479 | "node": "4.x || >=6.0.0" 480 | }, 481 | "peerDependencies": { 482 | "encoding": "^0.1.0" 483 | }, 484 | "peerDependenciesMeta": { 485 | "encoding": { 486 | "optional": true 487 | } 488 | } 489 | }, 490 | "node_modules/@libsql/isomorphic-ws": { 491 | "version": "0.1.5", 492 | "resolved": "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz", 493 | "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", 494 | "dependencies": { 495 | "@types/ws": "^8.5.4", 496 | "ws": "^8.13.0" 497 | } 498 | }, 499 | "node_modules/@libsql/linux-arm64-gnu": { 500 | "version": "0.3.2", 501 | "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.3.2.tgz", 502 | "integrity": "sha512-dwOQSJCst7FgMAB19NY037nJUTpmREKBgk86Fx/cv0Ins9XArvlwLqtJ41gZUWsbgxSP/Zm6CPdfFtt0P5RzTA==", 503 | "cpu": [ 504 | "arm64" 505 | ], 506 | "optional": true, 507 | "os": [ 508 | "linux" 509 | ] 510 | }, 511 | "node_modules/@libsql/linux-arm64-musl": { 512 | "version": "0.3.2", 513 | "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.3.2.tgz", 514 | "integrity": "sha512-OEHMfqq7+FFExtjPu1nMBN55wjPrVYdii/4n4l0Z+InHKtZciFJIVJ8sYfe64L1szZ7TrLWsi2fEmOL16ZonjQ==", 515 | "cpu": [ 516 | "arm64" 517 | ], 518 | "optional": true, 519 | "os": [ 520 | "linux" 521 | ] 522 | }, 523 | "node_modules/@libsql/linux-x64-gnu": { 524 | "version": "0.3.2", 525 | "resolved": "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.3.2.tgz", 526 | "integrity": "sha512-dVeM9S0x2ImtKBuOcq2K4Xqd/IyMYD5BSdwmOxOFQ3lPAkE0q4YtRhvaJ00ZWaesG5/iarZE7uJA7x2xmxEOWw==", 527 | "cpu": [ 528 | "x64" 529 | ], 530 | "optional": true, 531 | "os": [ 532 | "linux" 533 | ] 534 | }, 535 | "node_modules/@libsql/linux-x64-musl": { 536 | "version": "0.3.2", 537 | "resolved": "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.3.2.tgz", 538 | "integrity": "sha512-XG812Z/zXqx1m+pTjVtdBah2WvsvrmGE55dO4pXuRJKyvpPb5qg8m/t3PaKhtA9KDru9laP24+xCMyUWYnqkjw==", 539 | "cpu": [ 540 | "x64" 541 | ], 542 | "optional": true, 543 | "os": [ 544 | "linux" 545 | ] 546 | }, 547 | "node_modules/@libsql/win32-x64-msvc": { 548 | "version": "0.3.2", 549 | "resolved": "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.3.2.tgz", 550 | "integrity": "sha512-IMcfr1fV8o9PalLeozGF5AegZEPSriiXKT9vn5JEWk0Pc6Fm4LX3UVqwO47XTdJf/vJuizxZgxeWrlmm26shKA==", 551 | "cpu": [ 552 | "x64" 553 | ], 554 | "optional": true, 555 | "os": [ 556 | "win32" 557 | ] 558 | }, 559 | "node_modules/@neon-rs/load": { 560 | "version": "0.0.4", 561 | "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz", 562 | "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==" 563 | }, 564 | "node_modules/@oxlint/darwin-arm64": { 565 | "version": "0.2.10", 566 | "resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-0.2.10.tgz", 567 | "integrity": "sha512-WHRio7x8uKgXUAq01HiKL+3FIidir34THjvuwl/xgYMxzyPQ0v0ymn6gkXp+FMaytssLoF6y/QyKXayU8rmjRg==", 568 | "cpu": [ 569 | "arm64" 570 | ], 571 | "dev": true, 572 | "optional": true, 573 | "os": [ 574 | "darwin" 575 | ] 576 | }, 577 | "node_modules/@oxlint/darwin-x64": { 578 | "version": "0.2.10", 579 | "resolved": "https://registry.npmjs.org/@oxlint/darwin-x64/-/darwin-x64-0.2.10.tgz", 580 | "integrity": "sha512-nQt/JHnfIlJe5Ie2CFKO53VIjedCwq7DYjV9vn27+E5bgQLmkt9/HIYyQ7gl4tjqZdmSXBA3uCUTjehx4HlVZw==", 581 | "cpu": [ 582 | "x64" 583 | ], 584 | "dev": true, 585 | "optional": true, 586 | "os": [ 587 | "darwin" 588 | ] 589 | }, 590 | "node_modules/@oxlint/linux-arm64-gnu": { 591 | "version": "0.2.10", 592 | "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-0.2.10.tgz", 593 | "integrity": "sha512-vBpkbHMjcZkYaTvE2/D7tCPx/A9zBynWD0YTslGlze0vFRTuQMoLV6qWn7T9nUAWicAtFQlTihHexUrbGof5pA==", 594 | "cpu": [ 595 | "arm64" 596 | ], 597 | "dev": true, 598 | "optional": true, 599 | "os": [ 600 | "linux" 601 | ] 602 | }, 603 | "node_modules/@oxlint/linux-arm64-musl": { 604 | "version": "0.2.10", 605 | "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-musl/-/linux-arm64-musl-0.2.10.tgz", 606 | "integrity": "sha512-du8DAlVBWgAhCNoTdr5QAIUKQNweslvTA4W2xlqd8mMPLOOMLVDfmmnmNtXXrJYUbp/jbh4dbah0gEl7zL3kPg==", 607 | "cpu": [ 608 | "arm64" 609 | ], 610 | "dev": true, 611 | "optional": true, 612 | "os": [ 613 | "linux" 614 | ] 615 | }, 616 | "node_modules/@oxlint/linux-x64-gnu": { 617 | "version": "0.2.10", 618 | "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-gnu/-/linux-x64-gnu-0.2.10.tgz", 619 | "integrity": "sha512-WGEkL4EunIKeTqyMDxi/XjhyiDjUTcrcEaYEhIqbIQ1nIo3zkA+sX+94iSgNMmXhSeXfRBk/ONjFka1EYgIplw==", 620 | "cpu": [ 621 | "x64" 622 | ], 623 | "dev": true, 624 | "optional": true, 625 | "os": [ 626 | "linux" 627 | ] 628 | }, 629 | "node_modules/@oxlint/linux-x64-musl": { 630 | "version": "0.2.10", 631 | "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-musl/-/linux-x64-musl-0.2.10.tgz", 632 | "integrity": "sha512-qykmF9TdeWcYxUWEhm8m/znkViGoSP/vNvfz9LK7W601hTNCLCp/LjuFyYIJ7vAeGp5sFJ+5L4KvkPq+Wh6YUw==", 633 | "cpu": [ 634 | "x64" 635 | ], 636 | "dev": true, 637 | "optional": true, 638 | "os": [ 639 | "linux" 640 | ] 641 | }, 642 | "node_modules/@oxlint/win32-arm64": { 643 | "version": "0.2.10", 644 | "resolved": "https://registry.npmjs.org/@oxlint/win32-arm64/-/win32-arm64-0.2.10.tgz", 645 | "integrity": "sha512-ebs57qIOjHrJyyvnm8y0rRwnehG+mvQb76EMaZ8YEziWSC5WX5ifMlTSMayEGDBV14YPSaZDtAhmOK7PP67Zow==", 646 | "cpu": [ 647 | "arm64" 648 | ], 649 | "dev": true, 650 | "optional": true, 651 | "os": [ 652 | "win32" 653 | ] 654 | }, 655 | "node_modules/@oxlint/win32-x64": { 656 | "version": "0.2.10", 657 | "resolved": "https://registry.npmjs.org/@oxlint/win32-x64/-/win32-x64-0.2.10.tgz", 658 | "integrity": "sha512-Kxe2Nan3BsX7mUVYnFEBf2mICk4e3QSr7bWlASdW5n3XbjFtDpV3sFK28dlTQ2TgxhviDFUvod3yctVqP+yrtg==", 659 | "cpu": [ 660 | "x64" 661 | ], 662 | "dev": true, 663 | "optional": true, 664 | "os": [ 665 | "win32" 666 | ] 667 | }, 668 | "node_modules/@rollup/rollup-android-arm-eabi": { 669 | "version": "4.12.0", 670 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", 671 | "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", 672 | "cpu": [ 673 | "arm" 674 | ], 675 | "dev": true, 676 | "optional": true, 677 | "os": [ 678 | "android" 679 | ] 680 | }, 681 | "node_modules/@rollup/rollup-android-arm64": { 682 | "version": "4.12.0", 683 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", 684 | "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", 685 | "cpu": [ 686 | "arm64" 687 | ], 688 | "dev": true, 689 | "optional": true, 690 | "os": [ 691 | "android" 692 | ] 693 | }, 694 | "node_modules/@rollup/rollup-darwin-arm64": { 695 | "version": "4.12.0", 696 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", 697 | "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", 698 | "cpu": [ 699 | "arm64" 700 | ], 701 | "dev": true, 702 | "optional": true, 703 | "os": [ 704 | "darwin" 705 | ] 706 | }, 707 | "node_modules/@rollup/rollup-darwin-x64": { 708 | "version": "4.12.0", 709 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", 710 | "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", 711 | "cpu": [ 712 | "x64" 713 | ], 714 | "dev": true, 715 | "optional": true, 716 | "os": [ 717 | "darwin" 718 | ] 719 | }, 720 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 721 | "version": "4.12.0", 722 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", 723 | "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", 724 | "cpu": [ 725 | "arm" 726 | ], 727 | "dev": true, 728 | "optional": true, 729 | "os": [ 730 | "linux" 731 | ] 732 | }, 733 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 734 | "version": "4.12.0", 735 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", 736 | "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", 737 | "cpu": [ 738 | "arm64" 739 | ], 740 | "dev": true, 741 | "optional": true, 742 | "os": [ 743 | "linux" 744 | ] 745 | }, 746 | "node_modules/@rollup/rollup-linux-arm64-musl": { 747 | "version": "4.12.0", 748 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", 749 | "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", 750 | "cpu": [ 751 | "arm64" 752 | ], 753 | "dev": true, 754 | "optional": true, 755 | "os": [ 756 | "linux" 757 | ] 758 | }, 759 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 760 | "version": "4.12.0", 761 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", 762 | "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", 763 | "cpu": [ 764 | "riscv64" 765 | ], 766 | "dev": true, 767 | "optional": true, 768 | "os": [ 769 | "linux" 770 | ] 771 | }, 772 | "node_modules/@rollup/rollup-linux-x64-gnu": { 773 | "version": "4.12.0", 774 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", 775 | "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", 776 | "cpu": [ 777 | "x64" 778 | ], 779 | "dev": true, 780 | "optional": true, 781 | "os": [ 782 | "linux" 783 | ] 784 | }, 785 | "node_modules/@rollup/rollup-linux-x64-musl": { 786 | "version": "4.12.0", 787 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", 788 | "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", 789 | "cpu": [ 790 | "x64" 791 | ], 792 | "dev": true, 793 | "optional": true, 794 | "os": [ 795 | "linux" 796 | ] 797 | }, 798 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 799 | "version": "4.12.0", 800 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", 801 | "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", 802 | "cpu": [ 803 | "arm64" 804 | ], 805 | "dev": true, 806 | "optional": true, 807 | "os": [ 808 | "win32" 809 | ] 810 | }, 811 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 812 | "version": "4.12.0", 813 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", 814 | "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", 815 | "cpu": [ 816 | "ia32" 817 | ], 818 | "dev": true, 819 | "optional": true, 820 | "os": [ 821 | "win32" 822 | ] 823 | }, 824 | "node_modules/@rollup/rollup-win32-x64-msvc": { 825 | "version": "4.12.0", 826 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", 827 | "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", 828 | "cpu": [ 829 | "x64" 830 | ], 831 | "dev": true, 832 | "optional": true, 833 | "os": [ 834 | "win32" 835 | ] 836 | }, 837 | "node_modules/@sinclair/typebox": { 838 | "version": "0.27.8", 839 | "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", 840 | "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", 841 | "dev": true 842 | }, 843 | "node_modules/@types/estree": { 844 | "version": "1.0.5", 845 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", 846 | "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", 847 | "dev": true 848 | }, 849 | "node_modules/@types/node": { 850 | "version": "20.11.20", 851 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", 852 | "integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", 853 | "dependencies": { 854 | "undici-types": "~5.26.4" 855 | } 856 | }, 857 | "node_modules/@types/node-fetch": { 858 | "version": "2.6.11", 859 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", 860 | "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", 861 | "dependencies": { 862 | "@types/node": "*", 863 | "form-data": "^4.0.0" 864 | } 865 | }, 866 | "node_modules/@types/ws": { 867 | "version": "8.5.10", 868 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", 869 | "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", 870 | "dependencies": { 871 | "@types/node": "*" 872 | } 873 | }, 874 | "node_modules/@vitest/expect": { 875 | "version": "1.3.1", 876 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", 877 | "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", 878 | "dev": true, 879 | "dependencies": { 880 | "@vitest/spy": "1.3.1", 881 | "@vitest/utils": "1.3.1", 882 | "chai": "^4.3.10" 883 | }, 884 | "funding": { 885 | "url": "https://opencollective.com/vitest" 886 | } 887 | }, 888 | "node_modules/@vitest/runner": { 889 | "version": "1.3.1", 890 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", 891 | "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", 892 | "dev": true, 893 | "dependencies": { 894 | "@vitest/utils": "1.3.1", 895 | "p-limit": "^5.0.0", 896 | "pathe": "^1.1.1" 897 | }, 898 | "funding": { 899 | "url": "https://opencollective.com/vitest" 900 | } 901 | }, 902 | "node_modules/@vitest/snapshot": { 903 | "version": "1.3.1", 904 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", 905 | "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", 906 | "dev": true, 907 | "dependencies": { 908 | "magic-string": "^0.30.5", 909 | "pathe": "^1.1.1", 910 | "pretty-format": "^29.7.0" 911 | }, 912 | "funding": { 913 | "url": "https://opencollective.com/vitest" 914 | } 915 | }, 916 | "node_modules/@vitest/spy": { 917 | "version": "1.3.1", 918 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", 919 | "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", 920 | "dev": true, 921 | "dependencies": { 922 | "tinyspy": "^2.2.0" 923 | }, 924 | "funding": { 925 | "url": "https://opencollective.com/vitest" 926 | } 927 | }, 928 | "node_modules/@vitest/utils": { 929 | "version": "1.3.1", 930 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", 931 | "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", 932 | "dev": true, 933 | "dependencies": { 934 | "diff-sequences": "^29.6.3", 935 | "estree-walker": "^3.0.3", 936 | "loupe": "^2.3.7", 937 | "pretty-format": "^29.7.0" 938 | }, 939 | "funding": { 940 | "url": "https://opencollective.com/vitest" 941 | } 942 | }, 943 | "node_modules/acorn": { 944 | "version": "8.11.3", 945 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", 946 | "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", 947 | "dev": true, 948 | "bin": { 949 | "acorn": "bin/acorn" 950 | }, 951 | "engines": { 952 | "node": ">=0.4.0" 953 | } 954 | }, 955 | "node_modules/acorn-walk": { 956 | "version": "8.3.2", 957 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", 958 | "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", 959 | "dev": true, 960 | "engines": { 961 | "node": ">=0.4.0" 962 | } 963 | }, 964 | "node_modules/ansi-styles": { 965 | "version": "5.2.0", 966 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", 967 | "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", 968 | "dev": true, 969 | "engines": { 970 | "node": ">=10" 971 | }, 972 | "funding": { 973 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 974 | } 975 | }, 976 | "node_modules/assertion-error": { 977 | "version": "1.1.0", 978 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 979 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 980 | "dev": true, 981 | "engines": { 982 | "node": "*" 983 | } 984 | }, 985 | "node_modules/asynckit": { 986 | "version": "0.4.0", 987 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 988 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 989 | }, 990 | "node_modules/cac": { 991 | "version": "6.7.14", 992 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 993 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 994 | "dev": true, 995 | "engines": { 996 | "node": ">=8" 997 | } 998 | }, 999 | "node_modules/chai": { 1000 | "version": "4.4.1", 1001 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", 1002 | "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", 1003 | "dev": true, 1004 | "dependencies": { 1005 | "assertion-error": "^1.1.0", 1006 | "check-error": "^1.0.3", 1007 | "deep-eql": "^4.1.3", 1008 | "get-func-name": "^2.0.2", 1009 | "loupe": "^2.3.6", 1010 | "pathval": "^1.1.1", 1011 | "type-detect": "^4.0.8" 1012 | }, 1013 | "engines": { 1014 | "node": ">=4" 1015 | } 1016 | }, 1017 | "node_modules/check-error": { 1018 | "version": "1.0.3", 1019 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", 1020 | "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", 1021 | "dev": true, 1022 | "dependencies": { 1023 | "get-func-name": "^2.0.2" 1024 | }, 1025 | "engines": { 1026 | "node": "*" 1027 | } 1028 | }, 1029 | "node_modules/combined-stream": { 1030 | "version": "1.0.8", 1031 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1032 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1033 | "dependencies": { 1034 | "delayed-stream": "~1.0.0" 1035 | }, 1036 | "engines": { 1037 | "node": ">= 0.8" 1038 | } 1039 | }, 1040 | "node_modules/cross-spawn": { 1041 | "version": "7.0.3", 1042 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1043 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1044 | "dev": true, 1045 | "dependencies": { 1046 | "path-key": "^3.1.0", 1047 | "shebang-command": "^2.0.0", 1048 | "which": "^2.0.1" 1049 | }, 1050 | "engines": { 1051 | "node": ">= 8" 1052 | } 1053 | }, 1054 | "node_modules/data-uri-to-buffer": { 1055 | "version": "4.0.1", 1056 | "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", 1057 | "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", 1058 | "engines": { 1059 | "node": ">= 12" 1060 | } 1061 | }, 1062 | "node_modules/debug": { 1063 | "version": "4.3.4", 1064 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1065 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1066 | "dev": true, 1067 | "dependencies": { 1068 | "ms": "2.1.2" 1069 | }, 1070 | "engines": { 1071 | "node": ">=6.0" 1072 | }, 1073 | "peerDependenciesMeta": { 1074 | "supports-color": { 1075 | "optional": true 1076 | } 1077 | } 1078 | }, 1079 | "node_modules/deep-eql": { 1080 | "version": "4.1.3", 1081 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", 1082 | "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", 1083 | "dev": true, 1084 | "dependencies": { 1085 | "type-detect": "^4.0.0" 1086 | }, 1087 | "engines": { 1088 | "node": ">=6" 1089 | } 1090 | }, 1091 | "node_modules/delayed-stream": { 1092 | "version": "1.0.0", 1093 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1094 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 1095 | "engines": { 1096 | "node": ">=0.4.0" 1097 | } 1098 | }, 1099 | "node_modules/detect-libc": { 1100 | "version": "2.0.2", 1101 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", 1102 | "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", 1103 | "engines": { 1104 | "node": ">=8" 1105 | } 1106 | }, 1107 | "node_modules/diff-sequences": { 1108 | "version": "29.6.3", 1109 | "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", 1110 | "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", 1111 | "dev": true, 1112 | "engines": { 1113 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 1114 | } 1115 | }, 1116 | "node_modules/esbuild": { 1117 | "version": "0.19.12", 1118 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", 1119 | "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", 1120 | "dev": true, 1121 | "hasInstallScript": true, 1122 | "bin": { 1123 | "esbuild": "bin/esbuild" 1124 | }, 1125 | "engines": { 1126 | "node": ">=12" 1127 | }, 1128 | "optionalDependencies": { 1129 | "@esbuild/aix-ppc64": "0.19.12", 1130 | "@esbuild/android-arm": "0.19.12", 1131 | "@esbuild/android-arm64": "0.19.12", 1132 | "@esbuild/android-x64": "0.19.12", 1133 | "@esbuild/darwin-arm64": "0.19.12", 1134 | "@esbuild/darwin-x64": "0.19.12", 1135 | "@esbuild/freebsd-arm64": "0.19.12", 1136 | "@esbuild/freebsd-x64": "0.19.12", 1137 | "@esbuild/linux-arm": "0.19.12", 1138 | "@esbuild/linux-arm64": "0.19.12", 1139 | "@esbuild/linux-ia32": "0.19.12", 1140 | "@esbuild/linux-loong64": "0.19.12", 1141 | "@esbuild/linux-mips64el": "0.19.12", 1142 | "@esbuild/linux-ppc64": "0.19.12", 1143 | "@esbuild/linux-riscv64": "0.19.12", 1144 | "@esbuild/linux-s390x": "0.19.12", 1145 | "@esbuild/linux-x64": "0.19.12", 1146 | "@esbuild/netbsd-x64": "0.19.12", 1147 | "@esbuild/openbsd-x64": "0.19.12", 1148 | "@esbuild/sunos-x64": "0.19.12", 1149 | "@esbuild/win32-arm64": "0.19.12", 1150 | "@esbuild/win32-ia32": "0.19.12", 1151 | "@esbuild/win32-x64": "0.19.12" 1152 | } 1153 | }, 1154 | "node_modules/estree-walker": { 1155 | "version": "3.0.3", 1156 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1157 | "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1158 | "dev": true, 1159 | "dependencies": { 1160 | "@types/estree": "^1.0.0" 1161 | } 1162 | }, 1163 | "node_modules/execa": { 1164 | "version": "8.0.1", 1165 | "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", 1166 | "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", 1167 | "dev": true, 1168 | "dependencies": { 1169 | "cross-spawn": "^7.0.3", 1170 | "get-stream": "^8.0.1", 1171 | "human-signals": "^5.0.0", 1172 | "is-stream": "^3.0.0", 1173 | "merge-stream": "^2.0.0", 1174 | "npm-run-path": "^5.1.0", 1175 | "onetime": "^6.0.0", 1176 | "signal-exit": "^4.1.0", 1177 | "strip-final-newline": "^3.0.0" 1178 | }, 1179 | "engines": { 1180 | "node": ">=16.17" 1181 | }, 1182 | "funding": { 1183 | "url": "https://github.com/sindresorhus/execa?sponsor=1" 1184 | } 1185 | }, 1186 | "node_modules/fetch-blob": { 1187 | "version": "3.2.0", 1188 | "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", 1189 | "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 1190 | "funding": [ 1191 | { 1192 | "type": "github", 1193 | "url": "https://github.com/sponsors/jimmywarting" 1194 | }, 1195 | { 1196 | "type": "paypal", 1197 | "url": "https://paypal.me/jimmywarting" 1198 | } 1199 | ], 1200 | "dependencies": { 1201 | "node-domexception": "^1.0.0", 1202 | "web-streams-polyfill": "^3.0.3" 1203 | }, 1204 | "engines": { 1205 | "node": "^12.20 || >= 14.13" 1206 | } 1207 | }, 1208 | "node_modules/form-data": { 1209 | "version": "4.0.0", 1210 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 1211 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 1212 | "dependencies": { 1213 | "asynckit": "^0.4.0", 1214 | "combined-stream": "^1.0.8", 1215 | "mime-types": "^2.1.12" 1216 | }, 1217 | "engines": { 1218 | "node": ">= 6" 1219 | } 1220 | }, 1221 | "node_modules/formdata-polyfill": { 1222 | "version": "4.0.10", 1223 | "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", 1224 | "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", 1225 | "dependencies": { 1226 | "fetch-blob": "^3.1.2" 1227 | }, 1228 | "engines": { 1229 | "node": ">=12.20.0" 1230 | } 1231 | }, 1232 | "node_modules/fsevents": { 1233 | "version": "2.3.3", 1234 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1235 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1236 | "dev": true, 1237 | "hasInstallScript": true, 1238 | "optional": true, 1239 | "os": [ 1240 | "darwin" 1241 | ], 1242 | "engines": { 1243 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1244 | } 1245 | }, 1246 | "node_modules/get-func-name": { 1247 | "version": "2.0.2", 1248 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", 1249 | "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", 1250 | "dev": true, 1251 | "engines": { 1252 | "node": "*" 1253 | } 1254 | }, 1255 | "node_modules/get-stream": { 1256 | "version": "8.0.1", 1257 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", 1258 | "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", 1259 | "dev": true, 1260 | "engines": { 1261 | "node": ">=16" 1262 | }, 1263 | "funding": { 1264 | "url": "https://github.com/sponsors/sindresorhus" 1265 | } 1266 | }, 1267 | "node_modules/human-signals": { 1268 | "version": "5.0.0", 1269 | "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", 1270 | "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", 1271 | "dev": true, 1272 | "engines": { 1273 | "node": ">=16.17.0" 1274 | } 1275 | }, 1276 | "node_modules/is-stream": { 1277 | "version": "3.0.0", 1278 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", 1279 | "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", 1280 | "dev": true, 1281 | "engines": { 1282 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1283 | }, 1284 | "funding": { 1285 | "url": "https://github.com/sponsors/sindresorhus" 1286 | } 1287 | }, 1288 | "node_modules/isexe": { 1289 | "version": "2.0.0", 1290 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1291 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1292 | "dev": true 1293 | }, 1294 | "node_modules/js-base64": { 1295 | "version": "3.7.7", 1296 | "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", 1297 | "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" 1298 | }, 1299 | "node_modules/js-tokens": { 1300 | "version": "8.0.3", 1301 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", 1302 | "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", 1303 | "dev": true 1304 | }, 1305 | "node_modules/jsonc-parser": { 1306 | "version": "3.2.1", 1307 | "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", 1308 | "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", 1309 | "dev": true 1310 | }, 1311 | "node_modules/libsql": { 1312 | "version": "0.3.2", 1313 | "resolved": "https://registry.npmjs.org/libsql/-/libsql-0.3.2.tgz", 1314 | "integrity": "sha512-lKJQG6VATgNVNLxxPjGkKkjKF3HnEVP5OpesCz+zaftLzZlIti8ZCRwGcwGwjr3kyV0K5U2rlw0vQpTMCew3FA==", 1315 | "cpu": [ 1316 | "x64", 1317 | "arm64" 1318 | ], 1319 | "os": [ 1320 | "darwin", 1321 | "linux", 1322 | "win32" 1323 | ], 1324 | "dependencies": { 1325 | "@neon-rs/load": "^0.0.4", 1326 | "detect-libc": "2.0.2" 1327 | }, 1328 | "optionalDependencies": { 1329 | "@libsql/darwin-arm64": "0.3.2", 1330 | "@libsql/darwin-x64": "0.3.2", 1331 | "@libsql/linux-arm64-gnu": "0.3.2", 1332 | "@libsql/linux-arm64-musl": "0.3.2", 1333 | "@libsql/linux-x64-gnu": "0.3.2", 1334 | "@libsql/linux-x64-musl": "0.3.2", 1335 | "@libsql/win32-x64-msvc": "0.3.2" 1336 | } 1337 | }, 1338 | "node_modules/local-pkg": { 1339 | "version": "0.5.0", 1340 | "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", 1341 | "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", 1342 | "dev": true, 1343 | "dependencies": { 1344 | "mlly": "^1.4.2", 1345 | "pkg-types": "^1.0.3" 1346 | }, 1347 | "engines": { 1348 | "node": ">=14" 1349 | }, 1350 | "funding": { 1351 | "url": "https://github.com/sponsors/antfu" 1352 | } 1353 | }, 1354 | "node_modules/loupe": { 1355 | "version": "2.3.7", 1356 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", 1357 | "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", 1358 | "dev": true, 1359 | "dependencies": { 1360 | "get-func-name": "^2.0.1" 1361 | } 1362 | }, 1363 | "node_modules/magic-string": { 1364 | "version": "0.30.7", 1365 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", 1366 | "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", 1367 | "dev": true, 1368 | "dependencies": { 1369 | "@jridgewell/sourcemap-codec": "^1.4.15" 1370 | }, 1371 | "engines": { 1372 | "node": ">=12" 1373 | } 1374 | }, 1375 | "node_modules/merge-stream": { 1376 | "version": "2.0.0", 1377 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 1378 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", 1379 | "dev": true 1380 | }, 1381 | "node_modules/mime-db": { 1382 | "version": "1.52.0", 1383 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1384 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1385 | "engines": { 1386 | "node": ">= 0.6" 1387 | } 1388 | }, 1389 | "node_modules/mime-types": { 1390 | "version": "2.1.35", 1391 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1392 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1393 | "dependencies": { 1394 | "mime-db": "1.52.0" 1395 | }, 1396 | "engines": { 1397 | "node": ">= 0.6" 1398 | } 1399 | }, 1400 | "node_modules/mimic-fn": { 1401 | "version": "4.0.0", 1402 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", 1403 | "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", 1404 | "dev": true, 1405 | "engines": { 1406 | "node": ">=12" 1407 | }, 1408 | "funding": { 1409 | "url": "https://github.com/sponsors/sindresorhus" 1410 | } 1411 | }, 1412 | "node_modules/mlly": { 1413 | "version": "1.6.0", 1414 | "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.0.tgz", 1415 | "integrity": "sha512-YOvg9hfYQmnaB56Yb+KrJE2u0Yzz5zR+sLejEvF4fzwzV1Al6hkf2vyHTwqCRyv0hCi9rVCqVoXpyYevQIRwLQ==", 1416 | "dev": true, 1417 | "dependencies": { 1418 | "acorn": "^8.11.3", 1419 | "pathe": "^1.1.2", 1420 | "pkg-types": "^1.0.3", 1421 | "ufo": "^1.3.2" 1422 | } 1423 | }, 1424 | "node_modules/ms": { 1425 | "version": "2.1.2", 1426 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1427 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1428 | "dev": true 1429 | }, 1430 | "node_modules/nanoid": { 1431 | "version": "3.3.7", 1432 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", 1433 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", 1434 | "dev": true, 1435 | "funding": [ 1436 | { 1437 | "type": "github", 1438 | "url": "https://github.com/sponsors/ai" 1439 | } 1440 | ], 1441 | "bin": { 1442 | "nanoid": "bin/nanoid.cjs" 1443 | }, 1444 | "engines": { 1445 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1446 | } 1447 | }, 1448 | "node_modules/node-domexception": { 1449 | "version": "1.0.0", 1450 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 1451 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 1452 | "funding": [ 1453 | { 1454 | "type": "github", 1455 | "url": "https://github.com/sponsors/jimmywarting" 1456 | }, 1457 | { 1458 | "type": "github", 1459 | "url": "https://paypal.me/jimmywarting" 1460 | } 1461 | ], 1462 | "engines": { 1463 | "node": ">=10.5.0" 1464 | } 1465 | }, 1466 | "node_modules/node-fetch": { 1467 | "version": "3.3.2", 1468 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", 1469 | "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", 1470 | "dependencies": { 1471 | "data-uri-to-buffer": "^4.0.0", 1472 | "fetch-blob": "^3.1.4", 1473 | "formdata-polyfill": "^4.0.10" 1474 | }, 1475 | "engines": { 1476 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1477 | }, 1478 | "funding": { 1479 | "type": "opencollective", 1480 | "url": "https://opencollective.com/node-fetch" 1481 | } 1482 | }, 1483 | "node_modules/npm-run-path": { 1484 | "version": "5.3.0", 1485 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", 1486 | "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", 1487 | "dev": true, 1488 | "dependencies": { 1489 | "path-key": "^4.0.0" 1490 | }, 1491 | "engines": { 1492 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1493 | }, 1494 | "funding": { 1495 | "url": "https://github.com/sponsors/sindresorhus" 1496 | } 1497 | }, 1498 | "node_modules/npm-run-path/node_modules/path-key": { 1499 | "version": "4.0.0", 1500 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", 1501 | "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", 1502 | "dev": true, 1503 | "engines": { 1504 | "node": ">=12" 1505 | }, 1506 | "funding": { 1507 | "url": "https://github.com/sponsors/sindresorhus" 1508 | } 1509 | }, 1510 | "node_modules/onetime": { 1511 | "version": "6.0.0", 1512 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", 1513 | "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", 1514 | "dev": true, 1515 | "dependencies": { 1516 | "mimic-fn": "^4.0.0" 1517 | }, 1518 | "engines": { 1519 | "node": ">=12" 1520 | }, 1521 | "funding": { 1522 | "url": "https://github.com/sponsors/sindresorhus" 1523 | } 1524 | }, 1525 | "node_modules/oxlint": { 1526 | "version": "0.2.10", 1527 | "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-0.2.10.tgz", 1528 | "integrity": "sha512-c3vDPUUn1Rm08hWvOcF6eLAlfkZAGXJei5qydU8vlY2XJ4W4EbGfrS5cwwtDvOEnh/ULfmSxQECyr6uJye1bpg==", 1529 | "dev": true, 1530 | "bin": { 1531 | "oxlint": "bin/oxlint" 1532 | }, 1533 | "engines": { 1534 | "node": ">=14.*" 1535 | }, 1536 | "funding": { 1537 | "url": "https://github.com/sponsors/Boshen" 1538 | }, 1539 | "optionalDependencies": { 1540 | "@oxlint/darwin-arm64": "0.2.10", 1541 | "@oxlint/darwin-x64": "0.2.10", 1542 | "@oxlint/linux-arm64-gnu": "0.2.10", 1543 | "@oxlint/linux-arm64-musl": "0.2.10", 1544 | "@oxlint/linux-x64-gnu": "0.2.10", 1545 | "@oxlint/linux-x64-musl": "0.2.10", 1546 | "@oxlint/win32-arm64": "0.2.10", 1547 | "@oxlint/win32-x64": "0.2.10" 1548 | } 1549 | }, 1550 | "node_modules/p-limit": { 1551 | "version": "5.0.0", 1552 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", 1553 | "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", 1554 | "dev": true, 1555 | "dependencies": { 1556 | "yocto-queue": "^1.0.0" 1557 | }, 1558 | "engines": { 1559 | "node": ">=18" 1560 | }, 1561 | "funding": { 1562 | "url": "https://github.com/sponsors/sindresorhus" 1563 | } 1564 | }, 1565 | "node_modules/path-key": { 1566 | "version": "3.1.1", 1567 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1568 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1569 | "dev": true, 1570 | "engines": { 1571 | "node": ">=8" 1572 | } 1573 | }, 1574 | "node_modules/pathe": { 1575 | "version": "1.1.2", 1576 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", 1577 | "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", 1578 | "dev": true 1579 | }, 1580 | "node_modules/pathval": { 1581 | "version": "1.1.1", 1582 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 1583 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 1584 | "dev": true, 1585 | "engines": { 1586 | "node": "*" 1587 | } 1588 | }, 1589 | "node_modules/picocolors": { 1590 | "version": "1.0.0", 1591 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1592 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1593 | "dev": true 1594 | }, 1595 | "node_modules/pkg-types": { 1596 | "version": "1.0.3", 1597 | "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", 1598 | "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", 1599 | "dev": true, 1600 | "dependencies": { 1601 | "jsonc-parser": "^3.2.0", 1602 | "mlly": "^1.2.0", 1603 | "pathe": "^1.1.0" 1604 | } 1605 | }, 1606 | "node_modules/postcss": { 1607 | "version": "8.4.35", 1608 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", 1609 | "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", 1610 | "dev": true, 1611 | "funding": [ 1612 | { 1613 | "type": "opencollective", 1614 | "url": "https://opencollective.com/postcss/" 1615 | }, 1616 | { 1617 | "type": "tidelift", 1618 | "url": "https://tidelift.com/funding/github/npm/postcss" 1619 | }, 1620 | { 1621 | "type": "github", 1622 | "url": "https://github.com/sponsors/ai" 1623 | } 1624 | ], 1625 | "dependencies": { 1626 | "nanoid": "^3.3.7", 1627 | "picocolors": "^1.0.0", 1628 | "source-map-js": "^1.0.2" 1629 | }, 1630 | "engines": { 1631 | "node": "^10 || ^12 || >=14" 1632 | } 1633 | }, 1634 | "node_modules/prettier": { 1635 | "version": "3.2.5", 1636 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", 1637 | "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", 1638 | "dev": true, 1639 | "bin": { 1640 | "prettier": "bin/prettier.cjs" 1641 | }, 1642 | "engines": { 1643 | "node": ">=14" 1644 | }, 1645 | "funding": { 1646 | "url": "https://github.com/prettier/prettier?sponsor=1" 1647 | } 1648 | }, 1649 | "node_modules/pretty-format": { 1650 | "version": "29.7.0", 1651 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", 1652 | "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", 1653 | "dev": true, 1654 | "dependencies": { 1655 | "@jest/schemas": "^29.6.3", 1656 | "ansi-styles": "^5.0.0", 1657 | "react-is": "^18.0.0" 1658 | }, 1659 | "engines": { 1660 | "node": "^14.15.0 || ^16.10.0 || >=18.0.0" 1661 | } 1662 | }, 1663 | "node_modules/react-is": { 1664 | "version": "18.2.0", 1665 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", 1666 | "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", 1667 | "dev": true 1668 | }, 1669 | "node_modules/rollup": { 1670 | "version": "4.12.0", 1671 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", 1672 | "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", 1673 | "dev": true, 1674 | "dependencies": { 1675 | "@types/estree": "1.0.5" 1676 | }, 1677 | "bin": { 1678 | "rollup": "dist/bin/rollup" 1679 | }, 1680 | "engines": { 1681 | "node": ">=18.0.0", 1682 | "npm": ">=8.0.0" 1683 | }, 1684 | "optionalDependencies": { 1685 | "@rollup/rollup-android-arm-eabi": "4.12.0", 1686 | "@rollup/rollup-android-arm64": "4.12.0", 1687 | "@rollup/rollup-darwin-arm64": "4.12.0", 1688 | "@rollup/rollup-darwin-x64": "4.12.0", 1689 | "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", 1690 | "@rollup/rollup-linux-arm64-gnu": "4.12.0", 1691 | "@rollup/rollup-linux-arm64-musl": "4.12.0", 1692 | "@rollup/rollup-linux-riscv64-gnu": "4.12.0", 1693 | "@rollup/rollup-linux-x64-gnu": "4.12.0", 1694 | "@rollup/rollup-linux-x64-musl": "4.12.0", 1695 | "@rollup/rollup-win32-arm64-msvc": "4.12.0", 1696 | "@rollup/rollup-win32-ia32-msvc": "4.12.0", 1697 | "@rollup/rollup-win32-x64-msvc": "4.12.0", 1698 | "fsevents": "~2.3.2" 1699 | } 1700 | }, 1701 | "node_modules/shebang-command": { 1702 | "version": "2.0.0", 1703 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1704 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1705 | "dev": true, 1706 | "dependencies": { 1707 | "shebang-regex": "^3.0.0" 1708 | }, 1709 | "engines": { 1710 | "node": ">=8" 1711 | } 1712 | }, 1713 | "node_modules/shebang-regex": { 1714 | "version": "3.0.0", 1715 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1716 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1717 | "dev": true, 1718 | "engines": { 1719 | "node": ">=8" 1720 | } 1721 | }, 1722 | "node_modules/siginfo": { 1723 | "version": "2.0.0", 1724 | "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 1725 | "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 1726 | "dev": true 1727 | }, 1728 | "node_modules/signal-exit": { 1729 | "version": "4.1.0", 1730 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 1731 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 1732 | "dev": true, 1733 | "engines": { 1734 | "node": ">=14" 1735 | }, 1736 | "funding": { 1737 | "url": "https://github.com/sponsors/isaacs" 1738 | } 1739 | }, 1740 | "node_modules/source-map-js": { 1741 | "version": "1.0.2", 1742 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 1743 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", 1744 | "dev": true, 1745 | "engines": { 1746 | "node": ">=0.10.0" 1747 | } 1748 | }, 1749 | "node_modules/stackback": { 1750 | "version": "0.0.2", 1751 | "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 1752 | "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 1753 | "dev": true 1754 | }, 1755 | "node_modules/std-env": { 1756 | "version": "3.7.0", 1757 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", 1758 | "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", 1759 | "dev": true 1760 | }, 1761 | "node_modules/strip-final-newline": { 1762 | "version": "3.0.0", 1763 | "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", 1764 | "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", 1765 | "dev": true, 1766 | "engines": { 1767 | "node": ">=12" 1768 | }, 1769 | "funding": { 1770 | "url": "https://github.com/sponsors/sindresorhus" 1771 | } 1772 | }, 1773 | "node_modules/strip-literal": { 1774 | "version": "2.0.0", 1775 | "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.0.0.tgz", 1776 | "integrity": "sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==", 1777 | "dev": true, 1778 | "dependencies": { 1779 | "js-tokens": "^8.0.2" 1780 | }, 1781 | "funding": { 1782 | "url": "https://github.com/sponsors/antfu" 1783 | } 1784 | }, 1785 | "node_modules/tinybench": { 1786 | "version": "2.6.0", 1787 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", 1788 | "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", 1789 | "dev": true 1790 | }, 1791 | "node_modules/tinypool": { 1792 | "version": "0.8.2", 1793 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz", 1794 | "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==", 1795 | "dev": true, 1796 | "engines": { 1797 | "node": ">=14.0.0" 1798 | } 1799 | }, 1800 | "node_modules/tinyspy": { 1801 | "version": "2.2.1", 1802 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", 1803 | "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", 1804 | "dev": true, 1805 | "engines": { 1806 | "node": ">=14.0.0" 1807 | } 1808 | }, 1809 | "node_modules/tr46": { 1810 | "version": "0.0.3", 1811 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1812 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1813 | }, 1814 | "node_modules/type-detect": { 1815 | "version": "4.0.8", 1816 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1817 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1818 | "dev": true, 1819 | "engines": { 1820 | "node": ">=4" 1821 | } 1822 | }, 1823 | "node_modules/typescript": { 1824 | "version": "5.3.3", 1825 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", 1826 | "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", 1827 | "dev": true, 1828 | "bin": { 1829 | "tsc": "bin/tsc", 1830 | "tsserver": "bin/tsserver" 1831 | }, 1832 | "engines": { 1833 | "node": ">=14.17" 1834 | } 1835 | }, 1836 | "node_modules/ufo": { 1837 | "version": "1.4.0", 1838 | "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", 1839 | "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", 1840 | "dev": true 1841 | }, 1842 | "node_modules/undici-types": { 1843 | "version": "5.26.5", 1844 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 1845 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" 1846 | }, 1847 | "node_modules/vite": { 1848 | "version": "5.1.4", 1849 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", 1850 | "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", 1851 | "dev": true, 1852 | "dependencies": { 1853 | "esbuild": "^0.19.3", 1854 | "postcss": "^8.4.35", 1855 | "rollup": "^4.2.0" 1856 | }, 1857 | "bin": { 1858 | "vite": "bin/vite.js" 1859 | }, 1860 | "engines": { 1861 | "node": "^18.0.0 || >=20.0.0" 1862 | }, 1863 | "funding": { 1864 | "url": "https://github.com/vitejs/vite?sponsor=1" 1865 | }, 1866 | "optionalDependencies": { 1867 | "fsevents": "~2.3.3" 1868 | }, 1869 | "peerDependencies": { 1870 | "@types/node": "^18.0.0 || >=20.0.0", 1871 | "less": "*", 1872 | "lightningcss": "^1.21.0", 1873 | "sass": "*", 1874 | "stylus": "*", 1875 | "sugarss": "*", 1876 | "terser": "^5.4.0" 1877 | }, 1878 | "peerDependenciesMeta": { 1879 | "@types/node": { 1880 | "optional": true 1881 | }, 1882 | "less": { 1883 | "optional": true 1884 | }, 1885 | "lightningcss": { 1886 | "optional": true 1887 | }, 1888 | "sass": { 1889 | "optional": true 1890 | }, 1891 | "stylus": { 1892 | "optional": true 1893 | }, 1894 | "sugarss": { 1895 | "optional": true 1896 | }, 1897 | "terser": { 1898 | "optional": true 1899 | } 1900 | } 1901 | }, 1902 | "node_modules/vite-node": { 1903 | "version": "1.3.1", 1904 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", 1905 | "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", 1906 | "dev": true, 1907 | "dependencies": { 1908 | "cac": "^6.7.14", 1909 | "debug": "^4.3.4", 1910 | "pathe": "^1.1.1", 1911 | "picocolors": "^1.0.0", 1912 | "vite": "^5.0.0" 1913 | }, 1914 | "bin": { 1915 | "vite-node": "vite-node.mjs" 1916 | }, 1917 | "engines": { 1918 | "node": "^18.0.0 || >=20.0.0" 1919 | }, 1920 | "funding": { 1921 | "url": "https://opencollective.com/vitest" 1922 | } 1923 | }, 1924 | "node_modules/vitest": { 1925 | "version": "1.3.1", 1926 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", 1927 | "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", 1928 | "dev": true, 1929 | "dependencies": { 1930 | "@vitest/expect": "1.3.1", 1931 | "@vitest/runner": "1.3.1", 1932 | "@vitest/snapshot": "1.3.1", 1933 | "@vitest/spy": "1.3.1", 1934 | "@vitest/utils": "1.3.1", 1935 | "acorn-walk": "^8.3.2", 1936 | "chai": "^4.3.10", 1937 | "debug": "^4.3.4", 1938 | "execa": "^8.0.1", 1939 | "local-pkg": "^0.5.0", 1940 | "magic-string": "^0.30.5", 1941 | "pathe": "^1.1.1", 1942 | "picocolors": "^1.0.0", 1943 | "std-env": "^3.5.0", 1944 | "strip-literal": "^2.0.0", 1945 | "tinybench": "^2.5.1", 1946 | "tinypool": "^0.8.2", 1947 | "vite": "^5.0.0", 1948 | "vite-node": "1.3.1", 1949 | "why-is-node-running": "^2.2.2" 1950 | }, 1951 | "bin": { 1952 | "vitest": "vitest.mjs" 1953 | }, 1954 | "engines": { 1955 | "node": "^18.0.0 || >=20.0.0" 1956 | }, 1957 | "funding": { 1958 | "url": "https://opencollective.com/vitest" 1959 | }, 1960 | "peerDependencies": { 1961 | "@edge-runtime/vm": "*", 1962 | "@types/node": "^18.0.0 || >=20.0.0", 1963 | "@vitest/browser": "1.3.1", 1964 | "@vitest/ui": "1.3.1", 1965 | "happy-dom": "*", 1966 | "jsdom": "*" 1967 | }, 1968 | "peerDependenciesMeta": { 1969 | "@edge-runtime/vm": { 1970 | "optional": true 1971 | }, 1972 | "@types/node": { 1973 | "optional": true 1974 | }, 1975 | "@vitest/browser": { 1976 | "optional": true 1977 | }, 1978 | "@vitest/ui": { 1979 | "optional": true 1980 | }, 1981 | "happy-dom": { 1982 | "optional": true 1983 | }, 1984 | "jsdom": { 1985 | "optional": true 1986 | } 1987 | } 1988 | }, 1989 | "node_modules/web-streams-polyfill": { 1990 | "version": "3.3.3", 1991 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", 1992 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", 1993 | "engines": { 1994 | "node": ">= 8" 1995 | } 1996 | }, 1997 | "node_modules/webidl-conversions": { 1998 | "version": "3.0.1", 1999 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2000 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 2001 | }, 2002 | "node_modules/whatwg-url": { 2003 | "version": "5.0.0", 2004 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2005 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2006 | "dependencies": { 2007 | "tr46": "~0.0.3", 2008 | "webidl-conversions": "^3.0.0" 2009 | } 2010 | }, 2011 | "node_modules/which": { 2012 | "version": "2.0.2", 2013 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2014 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2015 | "dev": true, 2016 | "dependencies": { 2017 | "isexe": "^2.0.0" 2018 | }, 2019 | "bin": { 2020 | "node-which": "bin/node-which" 2021 | }, 2022 | "engines": { 2023 | "node": ">= 8" 2024 | } 2025 | }, 2026 | "node_modules/why-is-node-running": { 2027 | "version": "2.2.2", 2028 | "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", 2029 | "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", 2030 | "dev": true, 2031 | "dependencies": { 2032 | "siginfo": "^2.0.0", 2033 | "stackback": "0.0.2" 2034 | }, 2035 | "bin": { 2036 | "why-is-node-running": "cli.js" 2037 | }, 2038 | "engines": { 2039 | "node": ">=8" 2040 | } 2041 | }, 2042 | "node_modules/ws": { 2043 | "version": "8.16.0", 2044 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", 2045 | "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", 2046 | "engines": { 2047 | "node": ">=10.0.0" 2048 | }, 2049 | "peerDependencies": { 2050 | "bufferutil": "^4.0.1", 2051 | "utf-8-validate": ">=5.0.2" 2052 | }, 2053 | "peerDependenciesMeta": { 2054 | "bufferutil": { 2055 | "optional": true 2056 | }, 2057 | "utf-8-validate": { 2058 | "optional": true 2059 | } 2060 | } 2061 | }, 2062 | "node_modules/yocto-queue": { 2063 | "version": "1.0.0", 2064 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", 2065 | "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", 2066 | "dev": true, 2067 | "engines": { 2068 | "node": ">=12.20" 2069 | }, 2070 | "funding": { 2071 | "url": "https://github.com/sponsors/sindresorhus" 2072 | } 2073 | } 2074 | } 2075 | } 2076 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tursobase", 3 | "version": "0.1.10", 4 | "description": "Sync your PocketBase data with Turso. This library enables distributed PocketBase with Turso primary database as master.", 5 | "author": "menglinmaker", 6 | "license": "MIT", 7 | "type": "module", 8 | "keywords": [ 9 | "pocketbase", 10 | "turso" 11 | ], 12 | "publishConfig": { 13 | "access": "public" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/MengLinMaker/TursoBase.git" 18 | }, 19 | "main": "./dist/esm/index.js", 20 | "types": "./dist/types/index.d.ts", 21 | "scripts": { 22 | "test": "vitest local.test", 23 | "test:local": "vitest run local.test", 24 | "test:remote": "vitest run remote.test", 25 | "format": "prettier --no-semi --write .", 26 | "lint": "oxlint --jest-plugin --import-plugin .", 27 | "tsc": "rm -rf dist && tsc" 28 | }, 29 | "dependencies": { 30 | "@libsql/client": "^0.5.1" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "^20.11.20", 34 | "oxlint": "^0.2.10", 35 | "prettier": "^3.2.5", 36 | "typescript": "^5.3.3", 37 | "vitest": "^1.3.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sql/createTable.pb.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `_migrations` ( file VARCHAR(255) PRIMARY KEY NOT NULL, applied INTEGER NOT NULL ) 2 | 3 | CREATE TABLE {{_admins}} ( 4 | [[id]] TEXT PRIMARY KEY NOT NULL, 5 | [[avatar]] INTEGER DEFAULT 0 NOT NULL, 6 | [[email]] TEXT UNIQUE NOT NULL, 7 | [[tokenKey]] TEXT UNIQUE NOT NULL, 8 | [[passwordHash]] TEXT NOT NULL, 9 | [[lastResetSentAt]] TEXT DEFAULT "" NOT NULL, 10 | [[created]] TEXT DEFAULT (strftime ('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 11 | [[updated]] TEXT DEFAULT (strftime ('%Y-%m-%d %H:%M:%fZ')) NOT NULL 12 | ) -------------------------------------------------------------------------------- /sql/createTable.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE 2 | IF NOT EXISTS `_migrations` ( 3 | file VARCHAR(255) PRIMARY KEY NOT NULL, 4 | applied INTEGER NOT NULL 5 | ) 6 | CREATE TABLE 7 | IF NOT EXISTS `_admins` ( 8 | `id` TEXT PRIMARY KEY NOT NULL, 9 | `avatar` INTEGER DEFAULT 0 NOT NULL, 10 | `email` TEXT UNIQUE NOT NULL, 11 | `tokenKey` TEXT UNIQUE NOT NULL, 12 | `passwordHash` TEXT NOT NULL, 13 | `lastResetSentAt` TEXT DEFAULT "" NOT NULL, 14 | `created` TEXT DEFAULT (strftime ('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 15 | `updated` TEXT DEFAULT (strftime ('%Y-%m-%d %H:%M:%fZ')) NOT NULL 16 | ) -------------------------------------------------------------------------------- /sql/insertRow.pb.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO 2 | _collections ( 3 | createRule, 4 | created, 5 | deleteRule, 6 | id, 7 | indexes, 8 | listRule, 9 | name, 10 | options, 11 | schema, 12 | system, 13 | type, 14 | updateRule, 15 | updated, 16 | viewRule 17 | ) 18 | VALUES 19 | ( 20 | '', 21 | '2024-02-20 15:14:25.687Z', 22 | 'id = @request.auth.id', 23 | '_pb_users_auth_', 24 | '[]', 25 | 'id = @request.auth.id', 26 | 'users', 27 | '{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', 28 | '[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', 29 | false, 30 | 'auth', 31 | 'id = @request.auth.id', 32 | '2024-02-20 15:14:25.687Z', 33 | 'id = @request.auth.id' 34 | ) 35 | -------------------------------------------------------------------------------- /sql/insertRow.sql: -------------------------------------------------------------------------------- 1 | INSERT 2 | OR IGNORE INTO _collections ( 3 | createRule, 4 | created, 5 | deleteRule, 6 | id, 7 | indexes, 8 | listRule, 9 | name, 10 | options, 11 | schema, 12 | system, 13 | type, 14 | updateRule, 15 | updated, 16 | viewRule 17 | ) 18 | VALUES 19 | ( 20 | '', 21 | '2024-02-20 15:14:25.687Z', 22 | 'id = @request.auth.id', 23 | '_pb_users_auth_', 24 | '[]', 25 | 'id = @request.auth.id', 26 | 'users', 27 | '{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', 28 | '[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', 29 | false, 30 | 'auth', 31 | 'id = @request.auth.id', 32 | '2024-02-20 15:14:25.687Z', 33 | 'id = @request.auth.id' 34 | ) 35 | -------------------------------------------------------------------------------- /sql/setup.pb.sql: -------------------------------------------------------------------------------- 1 | [1.00ms] SELECT {{_params}}.* FROM `_params` WHERE `key`='settings' LIMIT 1 2 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 3 | [0.00ms] CREATE TABLE IF NOT EXISTS `_migrations` (file VARCHAR(255) PRIMARY KEY NOT NULL, applied INTEGER NOT NULL) 4 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1640988000_init.go' LIMIT 1 5 | [0.00ms] 6 | CREATE TABLE {{_admins}} ( 7 | [[id]] TEXT PRIMARY KEY NOT NULL, 8 | [[avatar]] INTEGER DEFAULT 0 NOT NULL, 9 | [[email]] TEXT UNIQUE NOT NULL, 10 | [[tokenKey]] TEXT UNIQUE NOT NULL, 11 | [[passwordHash]] TEXT NOT NULL, 12 | [[lastResetSentAt]] TEXT DEFAULT "" NOT NULL, 13 | [[created]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 14 | [[updated]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL 15 | ); 16 | 17 | CREATE TABLE {{_collections}} ( 18 | [[id]] TEXT PRIMARY KEY NOT NULL, 19 | [[system]] BOOLEAN DEFAULT FALSE NOT NULL, 20 | [[type]] TEXT DEFAULT "base" NOT NULL, 21 | [[name]] TEXT UNIQUE NOT NULL, 22 | [[schema]] JSON DEFAULT "[]" NOT NULL, 23 | [[indexes]] JSON DEFAULT "[]" NOT NULL, 24 | [[listRule]] TEXT DEFAULT NULL, 25 | [[viewRule]] TEXT DEFAULT NULL, 26 | [[createRule]] TEXT DEFAULT NULL, 27 | [[updateRule]] TEXT DEFAULT NULL, 28 | [[deleteRule]] TEXT DEFAULT NULL, 29 | [[options]] JSON DEFAULT "{}" NOT NULL, 30 | [[created]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 31 | [[updated]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL 32 | ); 33 | 34 | CREATE TABLE {{_params}} ( 35 | [[id]] TEXT PRIMARY KEY NOT NULL, 36 | [[key]] TEXT UNIQUE NOT NULL, 37 | [[value]] JSON DEFAULT NULL, 38 | [[created]] TEXT DEFAULT "" NOT NULL, 39 | [[updated]] TEXT DEFAULT "" NOT NULL 40 | ); 41 | 42 | CREATE TABLE {{_externalAuths}} ( 43 | [[id]] TEXT PRIMARY KEY NOT NULL, 44 | [[collectionId]] TEXT NOT NULL, 45 | [[recordId]] TEXT NOT NULL, 46 | [[provider]] TEXT NOT NULL, 47 | [[providerId]] TEXT NOT NULL, 48 | [[created]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 49 | [[updated]] TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 50 | --- 51 | FOREIGN KEY ([[collectionId]]) REFERENCES {{_collections}} ([[id]]) ON UPDATE CASCADE ON DELETE CASCADE 52 | ); 53 | 54 | CREATE UNIQUE INDEX _externalAuths_record_provider_idx on {{_externalAuths}} ([[collectionId]], [[recordId]], [[provider]]); 55 | CREATE UNIQUE INDEX _externalAuths_collection_provider_idx on {{_externalAuths}} ([[collectionId]], [[provider]], [[providerId]]); 56 | 57 | [0.00ms] SELECT {{_params}}.* FROM `_params` WHERE `key`='settings' LIMIT 1 58 | [0.00ms] INSERT INTO `_params` (`created`, `id`, `key`, `updated`, `value`) VALUES ('2024-02-22 23:46:41.564Z', 'petoxtodh5mpg2n', 'settings', '2024-02-22 23:46:41.564Z', '{"meta":{"appName":"Acme","appUrl":"http://localhost:8090","hideControls":false,"senderName":"Support","senderAddress":"support@example.com","verificationTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eThank you for joining us at {APP_NAME}.\u003c/p\u003e\n\u003cp\u003eClick on the button below to verify your email address.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eVerify\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Verify your {APP_NAME} email","actionUrl":"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}","hidden":false},"resetPasswordTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to reset your password.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eReset password\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn''t ask to reset your password, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Reset your {APP_NAME} password","actionUrl":"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}","hidden":false},"confirmEmailChangeTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to confirm your new email address.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eConfirm new email\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn''t ask to change your email address, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Confirm your {APP_NAME} new email address","actionUrl":"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}","hidden":false}},"logs":{"maxDays":5,"minLevel":0,"logIp":true},"smtp":{"enabled":false,"host":"smtp.example.com","port":587,"username":"","password":"","authMethod":"","tls":false,"localName":""},"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"","forcePathStyle":false},"backups":{"cron":"","cronMaxKeep":3,"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"","forcePathStyle":false}},"adminAuthToken":{"secret":"65kgUm2iQ78IhdTA3w3t2fiiVZajVQQ13sM7dl5FWbsgyeCVSS","duration":1209600},"adminPasswordResetToken":{"secret":"T1klgkrHwAT17tDNPSK493BO83r7k4jHGHEtb2L4gGQjqpl3iL","duration":1800},"adminFileToken":{"secret":"EytZHZ8oHYGPdTDOKtIdQIvjxyokO248Yylxv8STSFl4ypNFT8","duration":120},"recordAuthToken":{"secret":"njJBA3Xtgz0G1mNedwDNf19TyNhWffrUb3l0QYctNb1LlfD0XV","duration":1209600},"recordPasswordResetToken":{"secret":"bWx4P1NgGt6BpSb5NT5iRr797XtY6NFTXONOEJglMJOGzfc8pB","duration":1800},"recordEmailChangeToken":{"secret":"FQUrD88YWQu2G6pbHoOV5G9ynknldjbXt0K4iVZomyaPmVkiEf","duration":1800},"recordVerificationToken":{"secret":"xcFdY73VncflV5ORbiKBKixkFh7qsIvJJWI1z5RRvpI2B9jXLB","duration":604800},"recordFileToken":{"secret":"0y2H3nYtesARcOIlsQV1o0l32TGFiqaYwbolb2iZez1aCElpLT","duration":120},"emailAuth":{"enabled":false,"exceptDomains":null,"onlyDomains":null,"minPasswordLength":0},"googleAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"facebookAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"githubAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"gitlabAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"discordAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"twitterAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"microsoftAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"spotifyAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"kakaoAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"twitchAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"stravaAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"giteeAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"livechatAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"giteaAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidcAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidc2Auth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidc3Auth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"appleAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"instagramAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"vkAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"yandexAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"patreonAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"mailcowAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"bitbucketAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null}}') 59 | [0.00ms] INSERT INTO `_collections` (`createRule`, `created`, `deleteRule`, `id`, `indexes`, `listRule`, `name`, `options`, `schema`, `system`, `type`, `updateRule`, `updated`, `viewRule`) VALUES ('', '2024-02-22 23:46:41.564Z', 'id = @request.auth.id', '_pb_users_auth_', '[]', 'id = @request.auth.id', 'users', '{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', '[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', false, 'auth', 'id = @request.auth.id', '2024-02-22 23:46:41.564Z', 'id = @request.auth.id') 60 | [0.00ms] CREATE TABLE `users` (`avatar` TEXT DEFAULT '' NOT NULL, `created` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, `email` TEXT DEFAULT '' NOT NULL, `emailVisibility` BOOLEAN DEFAULT FALSE NOT NULL, `id` TEXT PRIMARY KEY DEFAULT ('r'||lower(hex(randomblob(7)))) NOT NULL, `lastResetSentAt` TEXT DEFAULT '' NOT NULL, `lastVerificationSentAt` TEXT DEFAULT '' NOT NULL, `name` TEXT DEFAULT '' NOT NULL, `passwordHash` TEXT NOT NULL, `tokenKey` TEXT NOT NULL, `updated` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, `username` TEXT NOT NULL, `verified` BOOLEAN DEFAULT FALSE NOT NULL) 61 | [0.00ms] 62 | CREATE UNIQUE INDEX __pb_users_auth__username_idx ON {{users}} ([[username]]); 63 | CREATE UNIQUE INDEX __pb_users_auth__email_idx ON {{users}} ([[email]]) WHERE [[email]] != ''; 64 | CREATE UNIQUE INDEX __pb_users_auth__tokenKey_idx ON {{users}} ([[tokenKey]]); 65 | 66 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` WHERE `type`='view' ORDER BY `created` ASC 67 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601564480, '1640988000_init.go') 68 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1673167670_multi_match_migrate.go' LIMIT 1 69 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 70 | [0.00ms] UPDATE `_collections` SET `createRule`='', `created`='2024-02-22 23:46:41.564Z', `deleteRule`='id = @request.auth.id', `indexes`='[]', `listRule`='id = @request.auth.id', `name`='users', `options`='{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', `schema`='[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', `system`=false, `type`='auth', `updateRule`='id = @request.auth.id', `updated`='2024-02-22 23:46:41.564Z', `viewRule`='id = @request.auth.id' WHERE `id`='_pb_users_auth_' 71 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601564788, '1673167670_multi_match_migrate.go') 72 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1677152688_rename_authentik_to_oidc.go' LIMIT 1 73 | [0.00ms] 74 | UPDATE {{_params}} 75 | SET [[value]] = replace([[value]], '"authentikAuth":', '"oidcAuth":') 76 | WHERE [[key]] = 'settings' 77 | 78 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601564867, '1677152688_rename_authentik_to_oidc.go') 79 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1679943780_normalize_single_multiple_values.go' LIMIT 1 80 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 81 | [0.00ms] UPDATE {{users}} set [[avatar]] = ( 82 | CASE 83 | WHEN COALESCE([[avatar]], '[]') = '[]' 84 | THEN '' 85 | ELSE ( 86 | CASE 87 | WHEN json_valid([[avatar]]) AND json_type([[avatar]]) == 'array' 88 | THEN COALESCE(json_extract([[avatar]], '$[#-1]'), '') 89 | ELSE [[avatar]] 90 | END 91 | ) 92 | END 93 | ) 94 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601564988, '1679943780_normalize_single_multiple_values.go') 95 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1679943781_add_indexes_column.go' LIMIT 1 96 | [0.00ms] SELECT `name` FROM `sqlite_schema` WHERE (`type`='view') AND ([[name]] LIKE '\_temp\_%' ESCAPE '\') 97 | [0.00ms] SELECT name FROM PRAGMA_TABLE_INFO('_collections') 98 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` WHERE type != 'view' 99 | [0.00ms] SELECT * FROM sqlite_master WHERE type = "index" and sql is not null 100 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565187, '1679943781_add_indexes_column.go') 101 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1685164450_check_fk.go' LIMIT 1 102 | [0.00ms] 103 | DELETE FROM {{_externalAuths}} 104 | WHERE [[collectionId]] NOT IN (SELECT [[id]] FROM {{_collections}}) 105 | 106 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565232, '1685164450_check_fk.go') 107 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1689579878_renormalize_single_multiple_values.go' LIMIT 1 108 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 109 | [0.00ms] UPDATE {{users}} set [[avatar]] = ( 110 | CASE 111 | WHEN COALESCE([[avatar]], '[]') = '[]' 112 | THEN '' 113 | ELSE ( 114 | CASE 115 | WHEN json_valid([[avatar]]) AND json_type([[avatar]]) == 'array' 116 | THEN COALESCE(json_extract([[avatar]], '$[#-1]'), '') 117 | ELSE [[avatar]] 118 | END 119 | ) 120 | END 121 | ) 122 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565339, '1689579878_renormalize_single_multiple_values.go') 123 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1690319366_reset_null_values.go' LIMIT 1 124 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 125 | [0.00ms] UPDATE {{users}} SET [[name]] = '' WHERE [[name]] IS NULL 126 | [0.00ms] UPDATE {{users}} SET [[avatar]] = '' WHERE [[avatar]] IS NULL 127 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565446, '1690319366_reset_null_values.go') 128 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1690454337_transform_relations_to_views.go' LIMIT 1 129 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` WHERE `type`='view' ORDER BY `created` ASC 130 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565502, '1690454337_transform_relations_to_views.go') 131 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1691747913_resave_views.go' LIMIT 1 132 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` WHERE `type`='view' ORDER BY `created` ASC 133 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565554, '1691747913_resave_views.go') 134 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1692609521_copy_display_fields.go' LIMIT 1 135 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 136 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565636, '1692609521_copy_display_fields.go') 137 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1701496825_allow_single_oauth2_provider_in_multiple_auth_collections.go' LIMIT 1 138 | [0.00ms] CREATE UNIQUE INDEX IF NOT EXISTS _externalAuths_collection_provider_idx on {{_externalAuths}} ([[collectionId]], [[provider]], [[providerId]]) 139 | [0.00ms] DROP INDEX IF EXISTS _externalAuths_provider_providerId_idx 140 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565677, '1701496825_allow_single_oauth2_provider_in_multiple_auth_collections.go') 141 | [0.00ms] SELECT count(*) FROM `_migrations` WHERE `file`='1702134272_set_default_json_max_size.go' LIMIT 1 142 | [0.00ms] SELECT {{_collections}}.* FROM `_collections` 143 | [0.00ms] INSERT INTO `_migrations` (`applied`, `file`) VALUES (1708645601565743, '1702134272_set_default_json_max_size.go') 144 | -------------------------------------------------------------------------------- /sql/setup.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS `_migrations` (file VARCHAR(255) PRIMARY KEY NOT NULL, applied INTEGER NOT NULL) 2 | ; 3 | CREATE TABLE IF NOT EXISTS `_admins` ( 4 | `id` TEXT PRIMARY KEY NOT NULL, 5 | `avatar` INTEGER DEFAULT 0 NOT NULL, 6 | `email` TEXT UNIQUE NOT NULL, 7 | `tokenKey` TEXT UNIQUE NOT NULL, 8 | `passwordHash` TEXT NOT NULL, 9 | `lastResetSentAt` TEXT DEFAULT "" NOT NULL, 10 | `created` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 11 | `updated` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL 12 | ); 13 | 14 | CREATE TABLE IF NOT EXISTS `_collections` ( 15 | `id` TEXT PRIMARY KEY NOT NULL, 16 | `system` BOOLEAN DEFAULT FALSE NOT NULL, 17 | `type` TEXT DEFAULT "base" NOT NULL, 18 | `name` TEXT UNIQUE NOT NULL, 19 | `schema` JSON DEFAULT "[]" NOT NULL, 20 | `indexes` JSON DEFAULT "[]" NOT NULL, 21 | `listRule` TEXT DEFAULT NULL, 22 | `viewRule` TEXT DEFAULT NULL, 23 | `createRule` TEXT DEFAULT NULL, 24 | `updateRule` TEXT DEFAULT NULL, 25 | `deleteRule` TEXT DEFAULT NULL, 26 | `options` JSON DEFAULT "{}" NOT NULL, 27 | `created` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 28 | `updated` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL 29 | ); 30 | 31 | CREATE TABLE IF NOT EXISTS `_params` ( 32 | `id` TEXT PRIMARY KEY NOT NULL, 33 | `key` TEXT UNIQUE NOT NULL, 34 | `value` JSON DEFAULT NULL, 35 | `created` TEXT DEFAULT "" NOT NULL, 36 | `updated` TEXT DEFAULT "" NOT NULL 37 | ); 38 | 39 | CREATE TABLE IF NOT EXISTS `_externalAuths` ( 40 | `id` TEXT PRIMARY KEY NOT NULL, 41 | `collectionId` TEXT NOT NULL, 42 | `recordId` TEXT NOT NULL, 43 | `provider` TEXT NOT NULL, 44 | `providerId` TEXT NOT NULL, 45 | `created` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 46 | `updated` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, 47 | --- 48 | FOREIGN KEY (`collectionId`) REFERENCES `_collections` (`id`) ON UPDATE CASCADE ON DELETE CASCADE 49 | ); 50 | 51 | CREATE UNIQUE INDEX IF NOT EXISTS _externalAuths_record_provider_idx on `_externalAuths` (`collectionId`, `recordId`, `provider`); 52 | CREATE UNIQUE INDEX IF NOT EXISTS _externalAuths_collection_provider_idx on `_externalAuths` (`collectionId`, `provider`, `providerId`); 53 | 54 | ;INSERT OR IGNORE INTO `_params` (`created`, `id`, `key`, `updated`, `value`) VALUES ('2024-02-22 23:46:41.564Z', 'petoxtodh5mpg2n', 'settings', '2024-02-22 23:46:41.564Z', '{"meta":{"appName":"Acme","appUrl":"http://localhost:8090","hideControls":false,"senderName":"Support","senderAddress":"support@example.com","verificationTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eThank you for joining us at {APP_NAME}.\u003c/p\u003e\n\u003cp\u003eClick on the button below to verify your email address.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eVerify\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Verify your {APP_NAME} email","actionUrl":"{APP_URL}/_/#/auth/confirm-verification/{TOKEN}","hidden":false},"resetPasswordTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to reset your password.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eReset password\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn''t ask to reset your password, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Reset your {APP_NAME} password","actionUrl":"{APP_URL}/_/#/auth/confirm-password-reset/{TOKEN}","hidden":false},"confirmEmailChangeTemplate":{"body":"\u003cp\u003eHello,\u003c/p\u003e\n\u003cp\u003eClick on the button below to confirm your new email address.\u003c/p\u003e\n\u003cp\u003e\n \u003ca class=\"btn\" href=\"{ACTION_URL}\" target=\"_blank\" rel=\"noopener\"\u003eConfirm new email\u003c/a\u003e\n\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eIf you didn''t ask to change your email address, you can ignore this email.\u003c/i\u003e\u003c/p\u003e\n\u003cp\u003e\n Thanks,\u003cbr/\u003e\n {APP_NAME} team\n\u003c/p\u003e","subject":"Confirm your {APP_NAME} new email address","actionUrl":"{APP_URL}/_/#/auth/confirm-email-change/{TOKEN}","hidden":false}},"logs":{"maxDays":5,"minLevel":0,"logIp":true},"smtp":{"enabled":false,"host":"smtp.example.com","port":587,"username":"","password":"","authMethod":"","tls":false,"localName":""},"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"","forcePathStyle":false},"backups":{"cron":"","cronMaxKeep":3,"s3":{"enabled":false,"bucket":"","region":"","endpoint":"","accessKey":"","secret":"","forcePathStyle":false}},"adminAuthToken":{"secret":"65kgUm2iQ78IhdTA3w3t2fiiVZajVQQ13sM7dl5FWbsgyeCVSS","duration":1209600},"adminPasswordResetToken":{"secret":"T1klgkrHwAT17tDNPSK493BO83r7k4jHGHEtb2L4gGQjqpl3iL","duration":1800},"adminFileToken":{"secret":"EytZHZ8oHYGPdTDOKtIdQIvjxyokO248Yylxv8STSFl4ypNFT8","duration":120},"recordAuthToken":{"secret":"njJBA3Xtgz0G1mNedwDNf19TyNhWffrUb3l0QYctNb1LlfD0XV","duration":1209600},"recordPasswordResetToken":{"secret":"bWx4P1NgGt6BpSb5NT5iRr797XtY6NFTXONOEJglMJOGzfc8pB","duration":1800},"recordEmailChangeToken":{"secret":"FQUrD88YWQu2G6pbHoOV5G9ynknldjbXt0K4iVZomyaPmVkiEf","duration":1800},"recordVerificationToken":{"secret":"xcFdY73VncflV5ORbiKBKixkFh7qsIvJJWI1z5RRvpI2B9jXLB","duration":604800},"recordFileToken":{"secret":"0y2H3nYtesARcOIlsQV1o0l32TGFiqaYwbolb2iZez1aCElpLT","duration":120},"emailAuth":{"enabled":false,"exceptDomains":null,"onlyDomains":null,"minPasswordLength":0},"googleAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"facebookAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"githubAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"gitlabAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"discordAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"twitterAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"microsoftAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"spotifyAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"kakaoAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"twitchAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"stravaAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"giteeAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"livechatAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"giteaAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidcAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidc2Auth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"oidc3Auth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"appleAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"instagramAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"vkAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"yandexAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"patreonAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"mailcowAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null},"bitbucketAuth":{"enabled":false,"clientId":"","clientSecret":"","authUrl":"","tokenUrl":"","userApiUrl":"","displayName":"","pkce":null}}') 55 | ;INSERT OR IGNORE INTO `_collections` (`createRule`, `created`, `deleteRule`, `id`, `indexes`, `listRule`, `name`, `options`, `schema`, `system`, `type`, `updateRule`, `updated`, `viewRule`) VALUES ('', '2024-02-22 23:46:41.564Z', 'id = @request.auth.id', '_pb_users_auth_', '[]', 'id = @request.auth.id', 'users', '{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', '[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', false, 'auth', 'id = @request.auth.id', '2024-02-22 23:46:41.564Z', 'id = @request.auth.id') 56 | ;CREATE TABLE IF NOT EXISTS `users` (`avatar` TEXT DEFAULT '' NOT NULL, `created` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, `email` TEXT DEFAULT '' NOT NULL, `emailVisibility` BOOLEAN DEFAULT FALSE NOT NULL, `id` TEXT PRIMARY KEY DEFAULT ('r'||lower(hex(randomblob(7)))) NOT NULL, `lastResetSentAt` TEXT DEFAULT '' NOT NULL, `lastVerificationSentAt` TEXT DEFAULT '' NOT NULL, `name` TEXT DEFAULT '' NOT NULL, `passwordHash` TEXT NOT NULL, `tokenKey` TEXT NOT NULL, `updated` TEXT DEFAULT (strftime('%Y-%m-%d %H:%M:%fZ')) NOT NULL, `username` TEXT NOT NULL, `verified` BOOLEAN DEFAULT FALSE NOT NULL) 57 | ; 58 | CREATE UNIQUE INDEX IF NOT EXISTS __pb_users_auth__username_idx ON `users` (`username`); 59 | CREATE UNIQUE INDEX IF NOT EXISTS __pb_users_auth__email_idx ON `users` (`email`) WHERE `email` != ''; 60 | CREATE UNIQUE INDEX IF NOT EXISTS __pb_users_auth__tokenKey_idx ON `users` (`tokenKey`); 61 | 62 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601564480, '1640988000_init.go') 63 | ;UPDATE `_collections` SET `createRule`='', `created`='2024-02-22 23:46:41.564Z', `deleteRule`='id = @request.auth.id', `indexes`='[]', `listRule`='id = @request.auth.id', `name`='users', `options`='{"allowEmailAuth":true,"allowOAuth2Auth":true,"allowUsernameAuth":true,"exceptEmailDomains":null,"manageRule":null,"minPasswordLength":8,"onlyEmailDomains":null,"onlyVerified":false,"requireEmail":false}', `schema`='[{"system":false,"id":"users_name","name":"name","type":"text","required":false,"presentable":false,"unique":false,"options":{"min":null,"max":null,"pattern":""}},{"system":false,"id":"users_avatar","name":"avatar","type":"file","required":false,"presentable":false,"unique":false,"options":{"mimeTypes":["image/jpeg","image/png","image/svg+xml","image/gif","image/webp"],"thumbs":null,"maxSelect":1,"maxSize":5242880,"protected":false}}]', `system`=false, `type`='auth', `updateRule`='id = @request.auth.id', `updated`='2024-02-22 23:46:41.564Z', `viewRule`='id = @request.auth.id' WHERE `id`='_pb_users_auth_' 64 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601564788, '1673167670_multi_match_migrate.go') 65 | ; 66 | UPDATE `_params` 67 | SET `value` = replace(`value`, '"authentikAuth":', '"oidcAuth":') 68 | WHERE `key` = 'settings' 69 | 70 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601564867, '1677152688_rename_authentik_to_oidc.go') 71 | ;UPDATE `users` set `avatar` = ( 72 | CASE 73 | WHEN COALESCE(`avatar`, '[]') = '[]' 74 | THEN '' 75 | ELSE ( 76 | CASE 77 | WHEN json_valid(`avatar`) AND json_type(`avatar`) == 'array' 78 | THEN COALESCE(json_extract(`avatar`, '$[#-1]'), '') 79 | ELSE `avatar` 80 | END 81 | ) 82 | END 83 | ) 84 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601564988, '1679943780_normalize_single_multiple_values.go') 85 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565187, '1679943781_add_indexes_column.go') 86 | ; 87 | DELETE FROM `_externalAuths` 88 | WHERE `collectionId` NOT IN (SELECT `id` FROM `_collections`) 89 | 90 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565232, '1685164450_check_fk.go') 91 | ;UPDATE `users` set `avatar` = ( 92 | CASE 93 | WHEN COALESCE(`avatar`, '[]') = '[]' 94 | THEN '' 95 | ELSE ( 96 | CASE 97 | WHEN json_valid(`avatar`) AND json_type(`avatar`) == 'array' 98 | THEN COALESCE(json_extract(`avatar`, '$[#-1]'), '') 99 | ELSE `avatar` 100 | END 101 | ) 102 | END 103 | ) 104 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565339, '1689579878_renormalize_single_multiple_values.go') 105 | ;UPDATE `users` SET `name` = '' WHERE `name` IS NULL 106 | ;UPDATE `users` SET `avatar` = '' WHERE `avatar` IS NULL 107 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565446, '1690319366_reset_null_values.go') 108 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565502, '1690454337_transform_relations_to_views.go') 109 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565554, '1691747913_resave_views.go') 110 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565636, '1692609521_copy_display_fields.go') 111 | ;CREATE UNIQUE INDEX IF NOT EXISTS _externalAuths_collection_provider_idx on `_externalAuths` (`collectionId`, `provider`, `providerId`) 112 | ;DROP INDEX IF EXISTS _externalAuths_provider_providerId_idx 113 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565677, '1701496825_allow_single_oauth2_provider_in_multiple_auth_collections.go') 114 | ;INSERT OR IGNORE INTO `_migrations` (`applied`, `file`) VALUES (1708645601565743, '1702134272_set_default_json_max_size.go') 115 | ; -------------------------------------------------------------------------------- /src/format/detectPbWriteQuery.ts: -------------------------------------------------------------------------------- 1 | // Only update write commands from SQL 2 | const WRITE_SQL_CMD = Object.freeze([ 3 | "CREATE", 4 | "DROP", 5 | "ALTER", 6 | "TRUNCATE", 7 | "INSERT", 8 | "UPDATE", 9 | "DELETE", 10 | ]) 11 | 12 | export const detectPbWriteQuery = (pbStdout: string) => { 13 | let pbQuery = "" 14 | for (const pbQueryChunk of pbStdout.split(/[[.0-9]*ms] /g)) { 15 | if (WRITE_SQL_CMD.some((cmd) => pbQueryChunk.includes(cmd))) { 16 | pbQuery += pbQueryChunk + ";" 17 | } 18 | } 19 | return pbQuery 20 | } 21 | -------------------------------------------------------------------------------- /src/format/expectReplaceAll.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from "crypto" 2 | 3 | export const expectReplaceAll = ( 4 | oldString: string, 5 | replacee: string, 6 | replacer: string, 7 | ) => { 8 | if (!oldString.includes(replacee)) return oldString 9 | if (!oldString.includes(replacer)) 10 | return oldString.replaceAll(replacee, replacer) 11 | // Manage the case where "expected" includes "replace" 12 | const expectedProxy = randomUUID() 13 | const proxiedOldString = oldString.replaceAll(replacer, expectedProxy) 14 | return proxiedOldString 15 | .replaceAll(replacee, replacer) 16 | .replaceAll(expectedProxy, replacer) 17 | } 18 | -------------------------------------------------------------------------------- /src/format/pbQueryToSql.ts: -------------------------------------------------------------------------------- 1 | import { expectReplaceAll } from "./expectReplaceAll.js" 2 | 3 | export const pbQueryToSql = (pbQuery: string) => { 4 | // Remove PocketBase brackets [[]] {{}} in SQL 5 | let rawSql = pbQuery 6 | .replace(/\[\[([_a-z]+)\]\]/gi, "`$1`") 7 | .replace(/ \{\{([_a-z]+)\}\}/gi, " `$1`") 8 | // Avoid SQL errors with "IF NOT EXISTS" 9 | rawSql = expectReplaceAll( 10 | rawSql, 11 | "CREATE TABLE", 12 | "CREATE TABLE IF NOT EXISTS", 13 | ) 14 | rawSql = expectReplaceAll( 15 | rawSql, 16 | "CREATE UNIQUE INDEX", 17 | "CREATE UNIQUE INDEX IF NOT EXISTS", 18 | ) 19 | rawSql = expectReplaceAll(rawSql, "INSERT INTO", "INSERT OR IGNORE INTO") 20 | return rawSql 21 | } 22 | -------------------------------------------------------------------------------- /src/format/test/expectReplaceAll.local.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from "vitest" 2 | import { expectReplaceAll } from "../expectReplaceAll" 3 | 4 | describe("expectReplaceAll", () => { 5 | test("nothing to replace", () => { 6 | const original = "original" 7 | const expected = "original" 8 | const result = expectReplaceAll(original, "nothing", "new") 9 | expect(result).toBe(expected) 10 | }) 11 | test("normally replace", () => { 12 | const original = "original" 13 | const expected = "new" 14 | const result = expectReplaceAll(original, "original", "new") 15 | expect(result).toBe(expected) 16 | }) 17 | test("already replaced", () => { 18 | const original = "new original" 19 | const expected = "new original" 20 | const result = expectReplaceAll(original, "original", "new original") 21 | expect(result).toBe(expected) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /src/format/test/pbQueryToSql.local.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from "vitest" 2 | import { readFileFormatted } from "../../test/readFileFormatted" 3 | import { pbQueryToSql } from "../pbQueryToSql" 4 | 5 | describe("pbQueryFormatter", () => { 6 | test("createTable", () => { 7 | const pbQuery = readFileFormatted("sql/createTable.pb.sql") 8 | const expectedSql = readFileFormatted("sql/createTable.sql") 9 | const resultSql = pbQueryToSql(pbQuery) 10 | expect(resultSql).toBe(expectedSql) 11 | }) 12 | test("insert", () => { 13 | const pbQuery = readFileFormatted("sql/insertRow.pb.sql") 14 | const expectedSql = readFileFormatted("sql/insertRow.sql") 15 | const resultSql = pbQueryToSql(pbQuery) 16 | expect(resultSql).toBe(expectedSql) 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from "node:child_process" 2 | import { Client } from "@libsql/client" 3 | import { pbQueryToSql } from "./format/pbQueryToSql.js" 4 | import { detectPbWriteQuery } from "./format/detectPbWriteQuery.js" 5 | 6 | export const tursoBase = ( 7 | databaseDir: string, 8 | port: number, 9 | tursoClient: Client, 10 | ) => { 11 | const pbUrl = `http://localhost:${port}` 12 | let pbStdout = "" 13 | let pbServed = false // Do not update database before setup 14 | 15 | const pbProcess = spawn("pocketbase", [ 16 | "serve", 17 | "--dev", 18 | `--http=localhost:${port}`, 19 | `--dir=${databaseDir}`, 20 | ]) 21 | pbProcess.stderr.on("data", async (stderr: Buffer) => 22 | console.error("\x1B[31m" + stderr.toString()), 23 | ) 24 | pbProcess.stdout.on("data", async (stdout: Buffer) => { 25 | pbStdout += stdout.toString() 26 | if (pbServed == true) { 27 | const sql = pbQueryToSql(detectPbWriteQuery(pbStdout)) 28 | await tursoClient.executeMultiple(sql) 29 | pbStdout = "" 30 | } else if (pbStdout.includes("http://")) { 31 | console.info("\x1B[32mPocketBase served at:", pbUrl) 32 | pbServed = true 33 | } 34 | }) 35 | return pbProcess 36 | } 37 | -------------------------------------------------------------------------------- /src/test/compareDb.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from "child_process" 2 | import { createHash } from "crypto" 3 | import { readFileSync } from "fs" 4 | 5 | export const compareDb = (databaseDir: string) => { 6 | execSync(`sqlite3 ${databaseDir}/data.db .dump > ${databaseDir}/setup.sql`) 7 | const data = readFileSync(`${databaseDir}/setup.sql`) 8 | return createHash("sha512").update(data).digest("hex") 9 | } 10 | -------------------------------------------------------------------------------- /src/test/delay.ts: -------------------------------------------------------------------------------- 1 | export const delay = (delayInMs: number) => { 2 | return new Promise((resolve) => setTimeout(resolve, delayInMs)) 3 | } 4 | -------------------------------------------------------------------------------- /src/test/getPbSetupLog.ts: -------------------------------------------------------------------------------- 1 | import { spawn } from "node:child_process" 2 | import { delay } from "./delay" 3 | 4 | export const getPbSetupLog = async (databaseDir: string, port: number) => { 5 | let pbStdout = "" 6 | let pbServed = false // Do not update database before setup 7 | 8 | const pbProcess = spawn("pocketbase", [ 9 | "serve", 10 | "--dev", 11 | `--http="localhost:${port}"`, 12 | `--dir=${databaseDir}`, 13 | ]) 14 | pbProcess.stdout.on("data", async (stdout: Buffer) => { 15 | pbStdout += stdout.toString() 16 | if (pbStdout.includes("http://")) { 17 | pbServed = true 18 | spawn("sqlite3", [`${databaseDir}/data.db`, "VACUUM"]) 19 | spawn("sqlite3", [`${databaseDir}/data.db`, "VACUUM"]) 20 | pbProcess.kill() 21 | } 22 | }) 23 | while (pbServed == false) await delay(100) 24 | pbProcess.kill() 25 | return pbStdout 26 | } 27 | -------------------------------------------------------------------------------- /src/test/local/turboBase.local.test.ts: -------------------------------------------------------------------------------- 1 | import { rmSync, writeFileSync } from "fs" 2 | import { createClient } from "@libsql/client" 3 | import { describe, expect, test } from "vitest" 4 | import { tursoBase } from "../.." 5 | import { getPbSetupLog } from "../getPbSetupLog" 6 | import { detectPbWriteQuery } from "../../format/detectPbWriteQuery" 7 | import { pbQueryToSql } from "../../format/pbQueryToSql" 8 | import { compareDb } from "../compareDb" 9 | import { replicateSetup } from "../replicateSetup" 10 | import { localTurso } from "../localTurso" 11 | import { delay } from "../delay" 12 | import { execSync } from "child_process" 13 | 14 | describe("TurboBase Local Setup", async () => { 15 | const databaseDir = ".local" 16 | rmSync(databaseDir, { recursive: true, force: true }) 17 | execSync(`mkdir ${databaseDir}`) 18 | 19 | test("Compare setup dump: Setup vs Manual", async () => { 20 | const setupLog = await getPbSetupLog(databaseDir + "/setup", 5000) 21 | writeFileSync("sql/setup.pb.sql", setupLog) 22 | const setupSql = pbQueryToSql(detectPbWriteQuery(setupLog)) 23 | writeFileSync("sql/setup.sql", setupSql) 24 | replicateSetup(databaseDir + "/manual") 25 | 26 | const hashSetup = compareDb(databaseDir + "/setup") 27 | const manualHashSetup = compareDb(databaseDir + "/manual") 28 | 29 | expect(hashSetup).toBe(manualHashSetup) 30 | }) 31 | 32 | test("Compare setup dump: PocketBase vs Local Turso", async () => { 33 | const tursoProcess = localTurso(databaseDir + "/turso", 5101) 34 | const tursoClient = createClient({ 35 | url: `file:${databaseDir}/pb/data.db`, 36 | syncUrl: `http://localhost:${5101}`, 37 | }) 38 | const pbProcess = tursoBase(databaseDir + "/pb", 5100, tursoClient) 39 | await delay(100) 40 | 41 | const localHashSetup = compareDb(databaseDir + "/pb") 42 | const tursoHashSetup = compareDb(databaseDir + "/turso") 43 | pbProcess.kill() 44 | tursoProcess.kill() 45 | 46 | expect(localHashSetup).toBe(tursoHashSetup) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/test/localTurso.ts: -------------------------------------------------------------------------------- 1 | import { execSync, spawn } from "child_process" 2 | 3 | export const localTurso = (databaseDir: string, port: number) => { 4 | execSync(`mkdir ${databaseDir}`) 5 | return spawn("turso", [ 6 | "dev", 7 | "-p", 8 | `${port}`, 9 | "-f", 10 | `${databaseDir}/data.db`, 11 | ]) 12 | } 13 | -------------------------------------------------------------------------------- /src/test/readFileFormatted.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from "fs" 2 | 3 | export const readFileFormatted = (filePath: string) => { 4 | return readFileSync(filePath) 5 | .toString() 6 | .replaceAll(/[\n ]+/g, " ") 7 | } 8 | -------------------------------------------------------------------------------- /src/test/replicateSetup.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from "child_process" 2 | 3 | export const replicateSetup = (databaseDir: string) => { 4 | execSync(`mkdir ${databaseDir} && touch ${databaseDir}/data.db`) 5 | execSync(`cat sql/setup.sql | sqlite3 ${databaseDir}/data.db`) 6 | } 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist/esm", 4 | "declarationDir": "dist/types", 5 | "target": "ESNext", 6 | "lib": ["ESNext"], 7 | "module": "NodeNext", 8 | "moduleResolution": "NodeNext", 9 | "declaration": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "alwaysStrict": true, 13 | "skipLibCheck": true 14 | }, 15 | "include": ["src"], 16 | "exclude": ["**/test"] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.types.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist/types", 5 | "declaration": true, 6 | "emitDeclarationOnly": true 7 | } 8 | } 9 | --------------------------------------------------------------------------------