diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..0234064 --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'drizzle-kit'; + +export default defineConfig({ + schema: './server/db/schema.ts', + out: './server/db/migrations', + dialect: 'sqlite', + dbCredentials: { + url: 'file:./server/db/local.db', + }, + verbose: true, + strict: true, +}); \ No newline at end of file diff --git a/nuxt.config.ts b/nuxt.config.ts index 7b53d58..a6c8700 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -4,5 +4,8 @@ export default defineNuxtConfig({ devtools: { enabled: true }, modules: [ '@nuxtjs/tailwindcss' - ] + ], + runtimeConfig: { + adminPassword: '', // NUXT_ADMIN_PASSWORD + } }) diff --git a/package.json b/package.json index 3e564b1..c3bd33b 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,16 @@ "postinstall": "nuxt prepare" }, "dependencies": { + "@libsql/client": "^0.15.9", + "bcryptjs": "^3.0.2", + "drizzle-orm": "^0.44.2", "nuxt": "^3.17.5", "vue": "^3.5.16", "vue-router": "^4.5.1" }, "devDependencies": { - "@nuxtjs/tailwindcss": "7.0.0-beta.0" + "@nuxtjs/tailwindcss": "7.0.0-beta.0", + "@types/bcryptjs": "^3.0.0", + "drizzle-kit": "^0.31.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 333063f..60ac055 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,18 @@ importers: .: dependencies: + '@libsql/client': + specifier: ^0.15.9 + version: 0.15.9 + bcryptjs: + specifier: ^3.0.2 + version: 3.0.2 + drizzle-orm: + specifier: ^0.44.2 + version: 0.44.2(@libsql/client@0.15.9) nuxt: specifier: ^3.17.5 - version: 3.17.5(@parcel/watcher@2.5.1)(@types/node@24.0.3)(db0@0.3.2)(ioredis@5.6.1)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.43.0)(terser@5.43.0)(typescript@5.8.3)(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.0)(yaml@2.8.0))(yaml@2.8.0) + version: 3.17.5(@libsql/client@0.15.9)(@parcel/watcher@2.5.1)(@types/node@24.0.3)(db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)))(drizzle-orm@0.44.2(@libsql/client@0.15.9))(ioredis@5.6.1)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.43.0)(terser@5.43.0)(typescript@5.8.3)(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.0)(yaml@2.8.0))(yaml@2.8.0) vue: specifier: ^3.5.16 version: 3.5.16(typescript@5.8.3) @@ -21,6 +30,12 @@ importers: '@nuxtjs/tailwindcss': specifier: 7.0.0-beta.0 version: 7.0.0-beta.0(magicast@0.3.5)(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.0)(yaml@2.8.0)) + '@types/bcryptjs': + specifier: ^3.0.0 + version: 3.0.0 + drizzle-kit: + specifier: ^0.31.1 + version: 0.31.1 packages: @@ -160,6 +175,9 @@ packages: resolution: {integrity: sha512-Y6+WUMsTFWE5jb20IFP4YGa5IrGY/+a/FbOSjDF/wz9gepU2hwCYSXRHP/vPwBvwcY3SVMASt4yXxbXNXigmZQ==} engines: {node: '>=18'} + '@drizzle-team/brocli@0.10.2': + resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} + '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} @@ -169,102 +187,206 @@ packages: '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@esbuild-kit/core-utils@3.3.2': + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild-kit/esm-loader@2.6.5': + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + deprecated: 'Merged into tsx: https://tsx.is' + '@esbuild/aix-ppc64@0.25.5': resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.25.5': resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.25.5': resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.25.5': resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.25.5': resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.25.5': resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.25.5': resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.5': resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.25.5': resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.25.5': resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.25.5': resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.25.5': resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.25.5': resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.25.5': resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.25.5': resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.25.5': resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.25.5': resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} @@ -277,6 +399,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.5': resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} @@ -289,30 +417,60 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.5': resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.25.5': resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.25.5': resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.25.5': resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.25.5': resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} @@ -360,6 +518,67 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} + '@libsql/client@0.15.9': + resolution: {integrity: sha512-VT3do0a0vwYVaNcp/y05ikkKS3OrFR5UeEf5SUuYZVgKVl1Nc1k9ajoYSsOid8AD/vlhLDB5yFQaV4HmT/OB9w==} + + '@libsql/core@0.15.9': + resolution: {integrity: sha512-4OVdeAmuaCUq5hYT8NNn0nxlO9AcA/eTjXfUZ+QK8MT3Dz7Z76m73x7KxjU6I64WyXX98dauVH2b9XM+d84npw==} + + '@libsql/darwin-arm64@0.5.13': + resolution: {integrity: sha512-ASz/EAMLDLx3oq9PVvZ4zBXXHbz2TxtxUwX2xpTRFR4V4uSHAN07+jpLu3aK5HUBLuv58z7+GjaL5w/cyjR28Q==} + cpu: [arm64] + os: [darwin] + + '@libsql/darwin-x64@0.5.13': + resolution: {integrity: sha512-kzglniv1difkq8opusSXM7u9H0WoEPeKxw0ixIfcGfvlCVMJ+t9UNtXmyNHW68ljdllje6a4C6c94iPmIYafYA==} + cpu: [x64] + os: [darwin] + + '@libsql/hrana-client@0.7.0': + resolution: {integrity: sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==} + + '@libsql/isomorphic-fetch@0.3.1': + resolution: {integrity: sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==} + engines: {node: '>=18.0.0'} + + '@libsql/isomorphic-ws@0.1.5': + resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} + + '@libsql/linux-arm-gnueabihf@0.5.13': + resolution: {integrity: sha512-UEW+VZN2r0mFkfztKOS7cqfS8IemuekbjUXbXCwULHtusww2QNCXvM5KU9eJCNE419SZCb0qaEWYytcfka8qeA==} + cpu: [arm] + os: [linux] + + '@libsql/linux-arm-musleabihf@0.5.13': + resolution: {integrity: sha512-NMDgLqryYBv4Sr3WoO/m++XDjR5KLlw9r/JK4Ym6A1XBv2bxQQNhH0Lxx3bjLW8qqhBD4+0xfms4d2cOlexPyA==} + cpu: [arm] + os: [linux] + + '@libsql/linux-arm64-gnu@0.5.13': + resolution: {integrity: sha512-/wCxVdrwl1ee6D6LEjwl+w4SxuLm5UL9Kb1LD5n0bBGs0q+49ChdPPh7tp175iRgkcrTgl23emymvt1yj3KxVQ==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-arm64-musl@0.5.13': + resolution: {integrity: sha512-xnVAbZIanUgX57XqeI5sNaDnVilp0Di5syCLSEo+bRyBobe/1IAeehNZpyVbCy91U2N6rH1C/mZU7jicVI9x+A==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-x64-gnu@0.5.13': + resolution: {integrity: sha512-/mfMRxcQAI9f8t7tU3QZyh25lXgXKzgin9B9TOSnchD73PWtsVhlyfA6qOCfjQl5kr4sHscdXD5Yb3KIoUgrpQ==} + cpu: [x64] + os: [linux] + + '@libsql/linux-x64-musl@0.5.13': + resolution: {integrity: sha512-rdefPTpQCVwUjIQYbDLMv3qpd5MdrT0IeD0UZPGqhT9AWU8nJSQoj2lfyIDAWEz7PPOVCY4jHuEn7FS2sw9kRA==} + cpu: [x64] + os: [linux] + + '@libsql/win32-x64-msvc@0.5.13': + resolution: {integrity: sha512-aNcmDrD1Ws+dNZIv9ECbxBQumqB9MlSVEykwfXJpqv/593nABb8Ttg5nAGUPtnADyaGDTrGvPPP81d/KsKho4Q==} + cpu: [x64] + os: [win32] + '@mapbox/node-pre-gyp@2.0.0': resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==} engines: {node: '>=18'} @@ -368,6 +587,9 @@ packages: '@napi-rs/wasm-runtime@0.2.11': resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} + '@neon-rs/load@0.0.4': + resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + '@netlify/binary-info@1.0.0': resolution: {integrity: sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw==} @@ -939,6 +1161,10 @@ packages: '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/bcryptjs@3.0.0': + resolution: {integrity: sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg==} + deprecated: This is a stub types definition. bcryptjs provides its own type definitions, so you do not need this installed. + '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} @@ -961,6 +1187,9 @@ packages: '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} @@ -1193,6 +1422,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bcryptjs@3.0.2: + resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==} + hasBin: true + bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -1527,6 +1760,10 @@ packages: engines: {node: '>=0.10'} hasBin: true + detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + detect-libc@2.0.4: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} @@ -1602,6 +1839,102 @@ packages: resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} + drizzle-kit@0.31.1: + resolution: {integrity: sha512-PUjYKWtzOzPtdtQlTHQG3qfv4Y0XT8+Eas6UbxCmxTj7qgMf+39dDujf1BP1I+qqZtw9uzwTh8jYtkMuCq+B0Q==} + hasBin: true + + drizzle-orm@0.44.2: + resolution: {integrity: sha512-zGAqBzWWkVSFjZpwPOrmCrgO++1kZ5H/rZ4qTGeGOe18iXGVJWf3WPfHOVwFIbmi8kHjfJstC6rJomzGx8g/dQ==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@upstash/redis': '>=1.34.7' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@upstash/redis': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1667,6 +2000,16 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + esbuild@0.25.5: resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} @@ -1849,6 +2192,9 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + giget@2.0.0: resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} hasBin: true @@ -2082,6 +2428,9 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + js-base64@3.7.7: + resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2136,6 +2485,11 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} + libsql@0.5.13: + resolution: {integrity: sha512-5Bwoa/CqzgkTwySgqHA5TsaUDRrdLIbdM4egdPcaAnqO3aC+qAgS6BwdzuZwARA5digXwiskogZ8H7Yy4XfdOg==} + cpu: [x64, arm64, wasm32, arm] + os: [darwin, linux, win32] + lightningcss-darwin-arm64@1.30.1: resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} engines: {node: '>= 12.0.0'} @@ -2811,6 +3165,9 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + promise-limit@2.7.0: + resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -2895,6 +3252,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -3809,6 +4169,8 @@ snapshots: gonzales-pe: 4.3.0 node-source-walk: 7.0.1 + '@drizzle-team/brocli@0.10.2': {} + '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 @@ -3825,78 +4187,154 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.10.1 + '@esbuild/aix-ppc64@0.25.5': optional: true + '@esbuild/android-arm64@0.18.20': + optional: true + '@esbuild/android-arm64@0.25.5': optional: true + '@esbuild/android-arm@0.18.20': + optional: true + '@esbuild/android-arm@0.25.5': optional: true + '@esbuild/android-x64@0.18.20': + optional: true + '@esbuild/android-x64@0.25.5': optional: true + '@esbuild/darwin-arm64@0.18.20': + optional: true + '@esbuild/darwin-arm64@0.25.5': optional: true + '@esbuild/darwin-x64@0.18.20': + optional: true + '@esbuild/darwin-x64@0.25.5': optional: true + '@esbuild/freebsd-arm64@0.18.20': + optional: true + '@esbuild/freebsd-arm64@0.25.5': optional: true + '@esbuild/freebsd-x64@0.18.20': + optional: true + '@esbuild/freebsd-x64@0.25.5': optional: true + '@esbuild/linux-arm64@0.18.20': + optional: true + '@esbuild/linux-arm64@0.25.5': optional: true + '@esbuild/linux-arm@0.18.20': + optional: true + '@esbuild/linux-arm@0.25.5': optional: true + '@esbuild/linux-ia32@0.18.20': + optional: true + '@esbuild/linux-ia32@0.25.5': optional: true + '@esbuild/linux-loong64@0.18.20': + optional: true + '@esbuild/linux-loong64@0.25.5': optional: true + '@esbuild/linux-mips64el@0.18.20': + optional: true + '@esbuild/linux-mips64el@0.25.5': optional: true + '@esbuild/linux-ppc64@0.18.20': + optional: true + '@esbuild/linux-ppc64@0.25.5': optional: true + '@esbuild/linux-riscv64@0.18.20': + optional: true + '@esbuild/linux-riscv64@0.25.5': optional: true + '@esbuild/linux-s390x@0.18.20': + optional: true + '@esbuild/linux-s390x@0.25.5': optional: true + '@esbuild/linux-x64@0.18.20': + optional: true + '@esbuild/linux-x64@0.25.5': optional: true '@esbuild/netbsd-arm64@0.25.5': optional: true + '@esbuild/netbsd-x64@0.18.20': + optional: true + '@esbuild/netbsd-x64@0.25.5': optional: true '@esbuild/openbsd-arm64@0.25.5': optional: true + '@esbuild/openbsd-x64@0.18.20': + optional: true + '@esbuild/openbsd-x64@0.25.5': optional: true + '@esbuild/sunos-x64@0.18.20': + optional: true + '@esbuild/sunos-x64@0.25.5': optional: true + '@esbuild/win32-arm64@0.18.20': + optional: true + '@esbuild/win32-arm64@0.25.5': optional: true + '@esbuild/win32-ia32@0.18.20': + optional: true + '@esbuild/win32-ia32@0.25.5': optional: true + '@esbuild/win32-x64@0.18.20': + optional: true + '@esbuild/win32-x64@0.25.5': optional: true @@ -3947,6 +4385,68 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} + '@libsql/client@0.15.9': + dependencies: + '@libsql/core': 0.15.9 + '@libsql/hrana-client': 0.7.0 + js-base64: 3.7.7 + libsql: 0.5.13 + promise-limit: 2.7.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/core@0.15.9': + dependencies: + js-base64: 3.7.7 + + '@libsql/darwin-arm64@0.5.13': + optional: true + + '@libsql/darwin-x64@0.5.13': + optional: true + + '@libsql/hrana-client@0.7.0': + dependencies: + '@libsql/isomorphic-fetch': 0.3.1 + '@libsql/isomorphic-ws': 0.1.5 + js-base64: 3.7.7 + node-fetch: 3.3.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/isomorphic-fetch@0.3.1': {} + + '@libsql/isomorphic-ws@0.1.5': + dependencies: + '@types/ws': 8.18.1 + ws: 8.18.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/linux-arm-gnueabihf@0.5.13': + optional: true + + '@libsql/linux-arm-musleabihf@0.5.13': + optional: true + + '@libsql/linux-arm64-gnu@0.5.13': + optional: true + + '@libsql/linux-arm64-musl@0.5.13': + optional: true + + '@libsql/linux-x64-gnu@0.5.13': + optional: true + + '@libsql/linux-x64-musl@0.5.13': + optional: true + + '@libsql/win32-x64-msvc@0.5.13': + optional: true + '@mapbox/node-pre-gyp@2.0.0': dependencies: consola: 3.4.2 @@ -3967,6 +4467,8 @@ snapshots: '@tybys/wasm-util': 0.9.0 optional: true + '@neon-rs/load@0.0.4': {} + '@netlify/binary-info@1.0.0': {} '@netlify/blobs@9.1.2': @@ -4628,6 +5130,10 @@ snapshots: tslib: 2.8.1 optional: true + '@types/bcryptjs@3.0.0': + dependencies: + bcryptjs: 3.0.2 + '@types/estree@1.0.7': {} '@types/estree@1.0.8': {} @@ -4635,7 +5141,6 @@ snapshots: '@types/node@24.0.3': dependencies: undici-types: 7.8.0 - optional: true '@types/normalize-package-data@2.4.4': {} @@ -4647,6 +5152,10 @@ snapshots: '@types/triple-beam@1.3.5': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 24.0.3 + '@types/yauzl@2.10.3': dependencies: '@types/node': 24.0.3 @@ -4965,6 +5474,8 @@ snapshots: base64-js@1.5.1: {} + bcryptjs@3.0.2: {} + bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 @@ -5246,7 +5757,10 @@ snapshots: data-uri-to-buffer@4.0.1: {} - db0@0.3.2: {} + db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)): + optionalDependencies: + '@libsql/client': 0.15.9 + drizzle-orm: 0.44.2(@libsql/client@0.15.9) debug@4.4.1: dependencies: @@ -5279,6 +5793,8 @@ snapshots: detect-libc@1.0.3: {} + detect-libc@2.0.2: {} + detect-libc@2.0.4: {} detective-amd@6.0.1: @@ -5365,6 +5881,19 @@ snapshots: dotenv@16.5.0: {} + drizzle-kit@0.31.1: + dependencies: + '@drizzle-team/brocli': 0.10.2 + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.25.5 + esbuild-register: 3.6.0(esbuild@0.25.5) + transitivePeerDependencies: + - supports-color + + drizzle-orm@0.44.2(@libsql/client@0.15.9): + optionalDependencies: + '@libsql/client': 0.15.9 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -5414,6 +5943,38 @@ snapshots: dependencies: es-errors: 1.3.0 + esbuild-register@3.6.0(esbuild@0.25.5): + dependencies: + debug: 4.4.1 + esbuild: 0.25.5 + transitivePeerDependencies: + - supports-color + + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + esbuild@0.25.5: optionalDependencies: '@esbuild/aix-ppc64': 0.25.5 @@ -5611,6 +6172,10 @@ snapshots: get-stream@8.0.1: {} + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + giget@2.0.0: dependencies: citty: 0.1.6 @@ -5837,6 +6402,8 @@ snapshots: jiti@2.4.2: {} + js-base64@3.7.7: {} + js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -5874,6 +6441,21 @@ snapshots: dependencies: readable-stream: 2.3.8 + libsql@0.5.13: + dependencies: + '@neon-rs/load': 0.0.4 + detect-libc: 2.0.2 + optionalDependencies: + '@libsql/darwin-arm64': 0.5.13 + '@libsql/darwin-x64': 0.5.13 + '@libsql/linux-arm-gnueabihf': 0.5.13 + '@libsql/linux-arm-musleabihf': 0.5.13 + '@libsql/linux-arm64-gnu': 0.5.13 + '@libsql/linux-arm64-musl': 0.5.13 + '@libsql/linux-x64-gnu': 0.5.13 + '@libsql/linux-x64-musl': 0.5.13 + '@libsql/win32-x64-msvc': 0.5.13 + lightningcss-darwin-arm64@1.30.1: optional: true @@ -6083,7 +6665,7 @@ snapshots: p-wait-for: 5.0.2 qs: 6.14.0 - nitropack@2.11.12: + nitropack@2.11.12(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 '@netlify/functions': 3.1.10(rollup@4.43.0) @@ -6105,7 +6687,7 @@ snapshots: cookie-es: 2.0.0 croner: 9.1.0 crossws: 0.3.5 - db0: 0.3.2 + db0: 0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)) defu: 6.1.4 destr: 2.0.5 dot-prop: 9.0.0 @@ -6151,7 +6733,7 @@ snapshots: unenv: 2.0.0-rc.17 unimport: 5.0.1 unplugin-utils: 0.2.4 - unstorage: 1.16.0(db0@0.3.2)(ioredis@5.6.1) + unstorage: 1.16.0(db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)))(ioredis@5.6.1) untyped: 2.0.0 unwasm: 0.3.9 youch: 4.1.0-beta.8 @@ -6242,7 +6824,7 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxt@3.17.5(@parcel/watcher@2.5.1)(@types/node@24.0.3)(db0@0.3.2)(ioredis@5.6.1)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.43.0)(terser@5.43.0)(typescript@5.8.3)(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.0)(yaml@2.8.0))(yaml@2.8.0): + nuxt@3.17.5(@libsql/client@0.15.9)(@parcel/watcher@2.5.1)(@types/node@24.0.3)(db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)))(drizzle-orm@0.44.2(@libsql/client@0.15.9))(ioredis@5.6.1)(lightningcss@1.30.1)(magicast@0.3.5)(rollup@4.43.0)(terser@5.43.0)(typescript@5.8.3)(vite@6.3.5(@types/node@24.0.3)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.0)(yaml@2.8.0))(yaml@2.8.0): dependencies: '@nuxt/cli': 3.25.1(magicast@0.3.5) '@nuxt/devalue': 2.0.2 @@ -6277,7 +6859,7 @@ snapshots: mlly: 1.7.4 mocked-exports: 0.1.1 nanotar: 0.2.0 - nitropack: 2.11.12 + nitropack: 2.11.12(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)) nypm: 0.6.0 ofetch: 1.4.1 ohash: 2.0.11 @@ -6299,7 +6881,7 @@ snapshots: unimport: 5.0.1 unplugin: 2.3.5 unplugin-vue-router: 0.12.0(vue-router@4.5.1(vue@3.5.16(typescript@5.8.3)))(vue@3.5.16(typescript@5.8.3)) - unstorage: 1.16.0(db0@0.3.2)(ioredis@5.6.1) + unstorage: 1.16.0(db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)))(ioredis@5.6.1) untyped: 2.0.0 vue: 3.5.16(typescript@5.8.3) vue-bundle-renderer: 2.1.1 @@ -6708,6 +7290,8 @@ snapshots: process@0.11.10: {} + promise-limit@2.7.0: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -6801,6 +7385,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -7168,8 +7754,7 @@ snapshots: magic-string: 0.30.17 unplugin: 2.3.5 - undici-types@7.8.0: - optional: true + undici-types@7.8.0: {} unenv@2.0.0-rc.17: dependencies: @@ -7246,7 +7831,7 @@ snapshots: picomatch: 4.0.2 webpack-virtual-modules: 0.6.2 - unstorage@1.16.0(db0@0.3.2)(ioredis@5.6.1): + unstorage@1.16.0(db0@0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)))(ioredis@5.6.1): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -7257,7 +7842,7 @@ snapshots: ofetch: 1.4.1 ufo: 1.6.1 optionalDependencies: - db0: 0.3.2 + db0: 0.3.2(@libsql/client@0.15.9)(drizzle-orm@0.44.2(@libsql/client@0.15.9)) ioredis: 5.6.1 untun@0.1.3: diff --git a/server/api/login/admin.post.ts b/server/api/login/admin.post.ts index 353ae58..ac86132 100644 --- a/server/api/login/admin.post.ts +++ b/server/api/login/admin.post.ts @@ -1,21 +1,23 @@ -import { defineEventHandler, readBody, setResponseStatus } from 'h3'; +import { defineEventHandler, readBody, setResponseStatus, useRuntimeConfig } from 'h3'; export default defineEventHandler(async (event) => { const body = await readBody(event); const { password } = body; + const config = useRuntimeConfig(event); if (!password) { setResponseStatus(event, 400); return { message: '请填写密码' }; } - // TODO: Replace with a more secure admin authentication method - if (password === 'adminpassword') { - return { - message: '管理员登录成功!', - }; - } else { + const adminPassword = config.adminPassword; + + if (!adminPassword || password !== adminPassword) { setResponseStatus(event, 401); return { message: '密码错误' }; } + + return { + message: '管理员登录成功!', + }; }); \ No newline at end of file diff --git a/server/api/login/user.post.ts b/server/api/login/user.post.ts index 622aa4c..f6d7933 100644 --- a/server/api/login/user.post.ts +++ b/server/api/login/user.post.ts @@ -1,4 +1,7 @@ import { defineEventHandler, readBody, setResponseStatus } from 'h3'; +import { db, customers } from '~/server/db'; +import { eq } from 'drizzle-orm'; +import bcrypt from 'bcryptjs'; export default defineEventHandler(async (event) => { const body = await readBody(event); @@ -9,14 +12,31 @@ export default defineEventHandler(async (event) => { return { message: '请填写手机号和密码' }; } - // TODO: Replace with database user lookup and password verification - if (contact === '1234567890' && password === 'password') { + try { + const user = await db.query.customers.findFirst({ + where: eq(customers.contact, contact), + }); + + if (!user) { + setResponseStatus(event, 401); + return { message: '手机号或密码错误' }; + } + + const isPasswordValid = bcrypt.compareSync(password, user.password); + + if (!isPasswordValid) { + setResponseStatus(event, 401); + return { message: '手机号或密码错误' }; + } + return { message: '登录成功!', - customerId: 'dummy-customer-id-123', + customerId: user.id, }; - } else { - setResponseStatus(event, 401); - return { message: '手机号或密码错误' }; + + } catch (error) { + console.error('Login error:', error); + setResponseStatus(event, 500); + return { message: '登录失败,请稍后重试' }; } }); \ No newline at end of file diff --git a/server/api/register.post.ts b/server/api/register.post.ts index e3fe311..9876e3d 100644 --- a/server/api/register.post.ts +++ b/server/api/register.post.ts @@ -1,21 +1,43 @@ import { defineEventHandler, readBody, setResponseStatus } from 'h3'; +import { db, customers } from '~/server/db'; +import bcrypt from 'bcryptjs'; export default defineEventHandler(async (event) => { const body = await readBody(event); - const { name, gender, contact, idCard, password } = body; if (!name || !gender || !contact || !idCard || !password) { setResponseStatus(event, 400); - return { - message: '请填写完整信息', - }; + return { message: '请填写完整信息' }; } - // TODO: Add database logic to save the user - console.log('Registering new user:', { name, gender, contact, idCard }); + try { + const hashedPassword = bcrypt.hashSync(password, 10); - return { - message: '注册成功!', - }; + await db.insert(customers).values({ + name, + gender, + contact, + idCard, + password: hashedPassword, + }); + + return { message: '注册成功!' }; + + } catch (error: any) { + // Check for unique constraint violation + if (error.message?.includes('UNIQUE constraint failed')) { + setResponseStatus(event, 409); // Conflict + if (error.message.includes('customers.contact')) { + return { message: '该手机号已被注册' }; + } + if (error.message.includes('customers.id_card')) { + return { message: '该身份证号已被注册' }; + } + } + + console.error('Registration error:', error); + setResponseStatus(event, 500); + return { message: '注册失败,请稍后重试' }; + } }); \ No newline at end of file diff --git a/server/db/index.ts b/server/db/index.ts new file mode 100644 index 0000000..d5ddddf --- /dev/null +++ b/server/db/index.ts @@ -0,0 +1,10 @@ +import { drizzle } from 'drizzle-orm/libsql'; +import { createClient } from '@libsql/client'; +import * as schema from './schema'; + +const client = createClient({ + url: 'file:./server/db/local.db', +}); + +export const db = drizzle(client, { schema }); +export * from './schema'; \ No newline at end of file diff --git a/server/db/local.db b/server/db/local.db new file mode 100644 index 0000000..3013298 Binary files /dev/null and b/server/db/local.db differ diff --git a/server/db/migrations/0000_gifted_agent_brand.sql b/server/db/migrations/0000_gifted_agent_brand.sql new file mode 100644 index 0000000..d6e1392 --- /dev/null +++ b/server/db/migrations/0000_gifted_agent_brand.sql @@ -0,0 +1,35 @@ +CREATE TABLE `customers` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `name` text NOT NULL, + `gender` text NOT NULL, + `contact` text NOT NULL, + `id_card` text NOT NULL, + `password` text NOT NULL +); +--> statement-breakpoint +CREATE UNIQUE INDEX `customers_contact_unique` ON `customers` (`contact`);--> statement-breakpoint +CREATE UNIQUE INDEX `customers_id_card_unique` ON `customers` (`id_card`);--> statement-breakpoint +CREATE TABLE `reservations` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `customer_id` integer NOT NULL, + `room_id` integer NOT NULL, + `check_in_time` integer NOT NULL, + `stay_days` integer NOT NULL, + FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON UPDATE no action ON DELETE no action, + FOREIGN KEY (`room_id`) REFERENCES `rooms`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE TABLE `room_types` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `type_name` text NOT NULL, + `star_rating` integer NOT NULL +); +--> statement-breakpoint +CREATE TABLE `rooms` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `type_id` integer NOT NULL, + `price` real NOT NULL, + `feature` text, + `available_count` integer DEFAULT 0 NOT NULL, + FOREIGN KEY (`type_id`) REFERENCES `room_types`(`id`) ON UPDATE no action ON DELETE no action +); diff --git a/server/db/migrations/meta/0000_snapshot.json b/server/db/migrations/meta/0000_snapshot.json new file mode 100644 index 0000000..0864549 --- /dev/null +++ b/server/db/migrations/meta/0000_snapshot.json @@ -0,0 +1,248 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "4e2b0752-859c-462f-81a8-d794f837ca5b", + "prevId": "00000000-0000-0000-0000-000000000000", + "tables": { + "customers": { + "name": "customers", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "gender": { + "name": "gender", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "contact": { + "name": "contact", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "id_card": { + "name": "id_card", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "customers_contact_unique": { + "name": "customers_contact_unique", + "columns": [ + "contact" + ], + "isUnique": true + }, + "customers_id_card_unique": { + "name": "customers_id_card_unique", + "columns": [ + "id_card" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "reservations": { + "name": "reservations", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "customer_id": { + "name": "customer_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_id": { + "name": "room_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "check_in_time": { + "name": "check_in_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "stay_days": { + "name": "stay_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "reservations_customer_id_customers_id_fk": { + "name": "reservations_customer_id_customers_id_fk", + "tableFrom": "reservations", + "tableTo": "customers", + "columnsFrom": [ + "customer_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "reservations_room_id_rooms_id_fk": { + "name": "reservations_room_id_rooms_id_fk", + "tableFrom": "reservations", + "tableTo": "rooms", + "columnsFrom": [ + "room_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "room_types": { + "name": "room_types", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "type_name": { + "name": "type_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "star_rating": { + "name": "star_rating", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "rooms": { + "name": "rooms", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "type_id": { + "name": "type_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "price": { + "name": "price", + "type": "real", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "feature": { + "name": "feature", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "available_count": { + "name": "available_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": { + "rooms_type_id_room_types_id_fk": { + "name": "rooms_type_id_room_types_id_fk", + "tableFrom": "rooms", + "tableTo": "room_types", + "columnsFrom": [ + "type_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/server/db/migrations/meta/_journal.json b/server/db/migrations/meta/_journal.json new file mode 100644 index 0000000..d5739fe --- /dev/null +++ b/server/db/migrations/meta/_journal.json @@ -0,0 +1,13 @@ +{ + "version": "7", + "dialect": "sqlite", + "entries": [ + { + "idx": 0, + "version": "6", + "when": 1750234000729, + "tag": "0000_gifted_agent_brand", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/server/db/schema.ts b/server/db/schema.ts new file mode 100644 index 0000000..cd7b184 --- /dev/null +++ b/server/db/schema.ts @@ -0,0 +1,32 @@ +import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core'; + +export const customers = sqliteTable('customers', { + id: integer('id').primaryKey({ autoIncrement: true }), + name: text('name').notNull(), + gender: text('gender', { enum: ['male', 'female'] }).notNull(), + contact: text('contact').notNull().unique(), + idCard: text('id_card').notNull().unique(), + password: text('password').notNull(), +}); + +export const roomTypes = sqliteTable('room_types', { + id: integer('id').primaryKey({ autoIncrement: true }), + typeName: text('type_name').notNull(), + starRating: integer('star_rating').notNull(), +}); + +export const rooms = sqliteTable('rooms', { + id: integer('id').primaryKey({ autoIncrement: true }), + typeId: integer('type_id').notNull().references(() => roomTypes.id), + price: real('price').notNull(), + feature: text('feature'), + availableCount: integer('available_count').notNull().default(0), +}); + +export const reservations = sqliteTable('reservations', { + id: integer('id').primaryKey({ autoIncrement: true }), + customerId: integer('customer_id').notNull().references(() => customers.id), + roomId: integer('room_id').notNull().references(() => rooms.id), + checkInTime: integer('check_in_time', { mode: 'timestamp' }).notNull(), + stayDays: integer('stay_days').notNull(), +}); \ No newline at end of file