diff --git a/bun.lock b/bun.lock index b629b68..c203110 100644 --- a/bun.lock +++ b/bun.lock @@ -15,7 +15,6 @@ "@unhead/vue": "^2.1.1", "@vueuse/core": "^14.1.0", "clsx": "^2.1.1", - "firebase": "^12.8.0", "firebase-admin": "^13.6.0", "hono": "^4.11.3", "is-mobile": "^5.0.0", @@ -258,94 +257,24 @@ "@fastify/busboy": ["@fastify/busboy@3.2.0", "", {}, "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA=="], - "@firebase/ai": ["@firebase/ai@2.7.0", "", { "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x", "@firebase/app-types": "0.x" } }, "sha512-PwpCz+TtAMWICM7uQNO0mkSPpUKwrMV4NSwHkbVKDvPKoaQmSlO96vIz+Suw2Ao1EaUUsxYb5LGImHWt/fSnRQ=="], - - "@firebase/analytics": ["@firebase/analytics@0.10.19", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/installations": "0.6.19", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-3wU676fh60gaiVYQEEXsbGS4HbF2XsiBphyvvqDbtC1U4/dO4coshbYktcCHq+HFaGIK07iHOh4pME0hEq1fcg=="], - - "@firebase/analytics-compat": ["@firebase/analytics-compat@0.2.25", "", { "dependencies": { "@firebase/analytics": "0.10.19", "@firebase/analytics-types": "0.8.3", "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-fdzoaG0BEKbqksRDhmf4JoyZf16Wosrl0Y7tbZtJyVDOOwziE0vrFjmZuTdviL0yhak+Nco6rMsUUbkbD+qb6Q=="], - - "@firebase/analytics-types": ["@firebase/analytics-types@0.8.3", "", {}, "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg=="], - - "@firebase/app": ["@firebase/app@0.14.7", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "idb": "7.1.1", "tslib": "^2.1.0" } }, "sha512-o3ZfnOx0AWBD5n/36p2zPoB0rDDxQP8H/A60zDLvvfRLtW8b3LfCyV97GKpJaAVV1JMMl/BC89EDzMyzxFZxTw=="], - - "@firebase/app-check": ["@firebase/app-check@0.11.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-XAvALQayUMBJo58U/rxW02IhsesaxxfWVmVkauZvGEz3vOAjMEQnzFlyblqkc2iAaO82uJ2ZVyZv9XzPfxjJ6w=="], - - "@firebase/app-check-compat": ["@firebase/app-check-compat@0.4.0", "", { "dependencies": { "@firebase/app-check": "0.11.0", "@firebase/app-check-types": "0.5.3", "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-UfK2Q8RJNjYM/8MFORltZRG9lJj11k0nW84rrffiKvcJxLf1jf6IEjCIkCamykHE73C6BwqhVfhIBs69GXQV0g=="], - "@firebase/app-check-interop-types": ["@firebase/app-check-interop-types@0.3.3", "", {}, "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A=="], - "@firebase/app-check-types": ["@firebase/app-check-types@0.5.3", "", {}, "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng=="], - - "@firebase/app-compat": ["@firebase/app-compat@0.5.7", "", { "dependencies": { "@firebase/app": "0.14.7", "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" } }, "sha512-MO+jfap8IBZQ+K8L2QCiHObyMgpYHrxo4Hc7iJgfb9hjGRW/z1y6LWVdT9wBBK+VJ7cRP2DjAiWQP+thu53hHA=="], - "@firebase/app-types": ["@firebase/app-types@0.9.3", "", {}, "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw=="], - "@firebase/auth": ["@firebase/auth@1.12.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x", "@react-native-async-storage/async-storage": "^2.2.0" }, "optionalPeers": ["@react-native-async-storage/async-storage"] }, "sha512-zkvLpsrxynWHk07qGrUDfCSqKf4AvfZGEqJ7mVCtYGjNNDbGE71k0Yn84rg8QEZu4hQw1BC0qDEHzpNVBcSVmA=="], - - "@firebase/auth-compat": ["@firebase/auth-compat@0.6.2", "", { "dependencies": { "@firebase/auth": "1.12.0", "@firebase/auth-types": "0.13.0", "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-8UhCzF6pav9bw/eXA8Zy1QAKssPRYEYXaWagie1ewLTwHkXv6bKp/j6/IwzSYQP67sy/BMFXIFaCCsoXzFLr7A=="], - "@firebase/auth-interop-types": ["@firebase/auth-interop-types@0.2.4", "", {}, "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA=="], - "@firebase/auth-types": ["@firebase/auth-types@0.13.0", "", { "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg=="], - "@firebase/component": ["@firebase/component@0.7.0", "", { "dependencies": { "@firebase/util": "1.13.0", "tslib": "^2.1.0" } }, "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg=="], - "@firebase/data-connect": ["@firebase/data-connect@0.3.12", "", { "dependencies": { "@firebase/auth-interop-types": "0.2.4", "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-baPddcoNLj/+vYo+HSJidJUdr5W4OkhT109c5qhR8T1dJoZcyJpkv/dFpYlw/VJ3dV66vI8GHQFrmAZw/xUS4g=="], - "@firebase/database": ["@firebase/database@1.1.0", "", { "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "faye-websocket": "0.11.4", "tslib": "^2.1.0" } }, "sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg=="], "@firebase/database-compat": ["@firebase/database-compat@2.1.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/database": "1.1.0", "@firebase/database-types": "1.0.16", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" } }, "sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg=="], "@firebase/database-types": ["@firebase/database-types@1.0.16", "", { "dependencies": { "@firebase/app-types": "0.9.3", "@firebase/util": "1.13.0" } }, "sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw=="], - "@firebase/firestore": ["@firebase/firestore@4.10.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "@firebase/webchannel-wrapper": "1.0.5", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-fgF6EbpoagGWh5Vwfu/7/jYgBFwUCwTlPNVF/aSjHcoEDRXpRsIqVfAFTp1LD+dWAUcAKEK3h+osk8spMJXtxA=="], - - "@firebase/firestore-compat": ["@firebase/firestore-compat@0.4.4", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/firestore": "4.10.0", "@firebase/firestore-types": "3.0.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-JvxxIgi+D5v9BecjLA1YomdyF7LA6CXhJuVK10b4GtRrB3m2O2hT1jJWbKYZYHUAjTaajkvnos+4U5VNxqkI2w=="], - - "@firebase/firestore-types": ["@firebase/firestore-types@3.0.3", "", { "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q=="], - - "@firebase/functions": ["@firebase/functions@0.13.1", "", { "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", "@firebase/component": "0.7.0", "@firebase/messaging-interop-types": "0.2.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-sUeWSb0rw5T+6wuV2o9XNmh9yHxjFI9zVGFnjFi+n7drTEWpl7ZTz1nROgGrSu472r+LAaj+2YaSicD4R8wfbw=="], - - "@firebase/functions-compat": ["@firebase/functions-compat@0.4.1", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/functions": "0.13.1", "@firebase/functions-types": "0.6.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-AxxUBXKuPrWaVNQ8o1cG1GaCAtXT8a0eaTDfqgS5VsRYLAR0ALcfqDLwo/QyijZj1w8Qf8n3Qrfy/+Im245hOQ=="], - - "@firebase/functions-types": ["@firebase/functions-types@0.6.3", "", {}, "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg=="], - - "@firebase/installations": ["@firebase/installations@0.6.19", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", "idb": "7.1.1", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q=="], - - "@firebase/installations-compat": ["@firebase/installations-compat@0.2.19", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/installations": "0.6.19", "@firebase/installations-types": "0.5.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-khfzIY3EI5LePePo7vT19/VEIH1E3iYsHknI/6ek9T8QCozAZshWT9CjlwOzZrKvTHMeNcbpo/VSOSIWDSjWdQ=="], - - "@firebase/installations-types": ["@firebase/installations-types@0.5.3", "", { "peerDependencies": { "@firebase/app-types": "0.x" } }, "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA=="], - "@firebase/logger": ["@firebase/logger@0.5.0", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g=="], - "@firebase/messaging": ["@firebase/messaging@0.12.23", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/installations": "0.6.19", "@firebase/messaging-interop-types": "0.2.3", "@firebase/util": "1.13.0", "idb": "7.1.1", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg=="], - - "@firebase/messaging-compat": ["@firebase/messaging-compat@0.2.23", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/messaging": "0.12.23", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-SN857v/kBUvlQ9X/UjAqBoQ2FEaL1ZozpnmL1ByTe57iXkmnVVFm9KqAsTfmf+OEwWI4kJJe9NObtN/w22lUgg=="], - - "@firebase/messaging-interop-types": ["@firebase/messaging-interop-types@0.2.3", "", {}, "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q=="], - - "@firebase/performance": ["@firebase/performance@0.7.9", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/installations": "0.6.19", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0", "web-vitals": "^4.2.4" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-UzybENl1EdM2I1sjYm74xGt/0JzRnU/0VmfMAKo2LSpHJzaj77FCLZXmYQ4oOuE+Pxtt8Wy2BVJEENiZkaZAzQ=="], - - "@firebase/performance-compat": ["@firebase/performance-compat@0.2.22", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/performance": "0.7.9", "@firebase/performance-types": "0.2.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-xLKxaSAl/FVi10wDX/CHIYEUP13jXUjinL+UaNXT9ByIvxII5Ne5150mx6IgM8G6Q3V+sPiw9C8/kygkyHUVxg=="], - - "@firebase/performance-types": ["@firebase/performance-types@0.2.3", "", {}, "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ=="], - - "@firebase/remote-config": ["@firebase/remote-config@0.8.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/installations": "0.6.19", "@firebase/logger": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-sJz7C2VACeE257Z/3kY9Ap2WXbFsgsDLfaGfZmmToKAK39ipXxFan+vzB9CSbF6mP7bzjyzEnqPcMXhAnYE6fQ=="], - - "@firebase/remote-config-compat": ["@firebase/remote-config-compat@0.2.21", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", "@firebase/remote-config": "0.8.0", "@firebase/remote-config-types": "0.5.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-9+lm0eUycxbu8GO25JfJe4s6R2xlDqlVt0CR6CvN9E6B4AFArEV4qfLoDVRgIEB7nHKwvH2nYRocPWfmjRQTnw=="], - - "@firebase/remote-config-types": ["@firebase/remote-config-types@0.5.0", "", {}, "sha512-vI3bqLoF14L/GchtgayMiFpZJF+Ao3uR8WCde0XpYNkSokDpAKca2DxvcfeZv7lZUqkUwQPL2wD83d3vQ4vvrg=="], - - "@firebase/storage": ["@firebase/storage@0.14.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "sha512-xWWbb15o6/pWEw8H01UQ1dC5U3rf8QTAzOChYyCpafV6Xki7KVp3Yaw2nSklUwHEziSWE9KoZJS7iYeyqWnYFA=="], - - "@firebase/storage-compat": ["@firebase/storage-compat@0.4.0", "", { "dependencies": { "@firebase/component": "0.7.0", "@firebase/storage": "0.14.0", "@firebase/storage-types": "0.8.3", "@firebase/util": "1.13.0", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "sha512-vDzhgGczr1OfcOy285YAPur5pWDEvD67w4thyeCUh6Ys0izN9fNYtA1MJERmNBfqjqu0lg0FM5GLbw0Il21M+g=="], - - "@firebase/storage-types": ["@firebase/storage-types@0.8.3", "", { "peerDependencies": { "@firebase/app-types": "0.x", "@firebase/util": "1.x" } }, "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg=="], - "@firebase/util": ["@firebase/util@1.13.0", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ=="], - "@firebase/webchannel-wrapper": ["@firebase/webchannel-wrapper@1.0.5", "", {}, "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw=="], - "@google-cloud/firestore": ["@google-cloud/firestore@7.11.6", "", { "dependencies": { "@opentelemetry/api": "^1.3.0", "fast-deep-equal": "^3.1.1", "functional-red-black-tree": "^1.0.1", "google-gax": "^4.3.3", "protobufjs": "^7.2.6" } }, "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw=="], "@google-cloud/paginator": ["@google-cloud/paginator@5.0.2", "", { "dependencies": { "arrify": "^2.0.0", "extend": "^3.0.2" } }, "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg=="], @@ -356,7 +285,7 @@ "@google-cloud/storage": ["@google-cloud/storage@7.18.0", "", { "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", "fast-xml-parser": "^4.4.1", "gaxios": "^6.0.2", "google-auth-library": "^9.6.3", "html-entities": "^2.5.2", "mime": "^3.0.0", "p-limit": "^3.0.1", "retry-request": "^7.0.0", "teeny-request": "^9.0.0", "uuid": "^8.0.0" } }, "sha512-r3ZwDMiz4nwW6R922Z1pwpePxyRwE5GdevYX63hRmAQUkUQJcBH/79EnQPDv5cOv1mFBgevdNWQfi3tie3dHrQ=="], - "@grpc/grpc-js": ["@grpc/grpc-js@1.9.15", "", { "dependencies": { "@grpc/proto-loader": "^0.7.8", "@types/node": ">=12.12.47" } }, "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ=="], + "@grpc/grpc-js": ["@grpc/grpc-js@1.14.3", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA=="], "@grpc/proto-loader": ["@grpc/proto-loader@0.7.15", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ=="], @@ -896,8 +825,6 @@ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - "firebase": ["firebase@12.8.0", "", { "dependencies": { "@firebase/ai": "2.7.0", "@firebase/analytics": "0.10.19", "@firebase/analytics-compat": "0.2.25", "@firebase/app": "0.14.7", "@firebase/app-check": "0.11.0", "@firebase/app-check-compat": "0.4.0", "@firebase/app-compat": "0.5.7", "@firebase/app-types": "0.9.3", "@firebase/auth": "1.12.0", "@firebase/auth-compat": "0.6.2", "@firebase/data-connect": "0.3.12", "@firebase/database": "1.1.0", "@firebase/database-compat": "2.1.0", "@firebase/firestore": "4.10.0", "@firebase/firestore-compat": "0.4.4", "@firebase/functions": "0.13.1", "@firebase/functions-compat": "0.4.1", "@firebase/installations": "0.6.19", "@firebase/installations-compat": "0.2.19", "@firebase/messaging": "0.12.23", "@firebase/messaging-compat": "0.2.23", "@firebase/performance": "0.7.9", "@firebase/performance-compat": "0.2.22", "@firebase/remote-config": "0.8.0", "@firebase/remote-config-compat": "0.2.21", "@firebase/storage": "0.14.0", "@firebase/storage-compat": "0.4.0", "@firebase/util": "1.13.0" } }, "sha512-S1tCIR3ENecee0tY2cfTHfMkXqkitHfbsvqpCtvsT0Zi9vDB7A4CodAjHfHCjVvu/XtGy1LHLjOasVcF10rCVw=="], - "firebase-admin": ["firebase-admin@13.6.0", "", { "dependencies": { "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^2.0.0", "@firebase/database-types": "^1.0.6", "@types/node": "^22.8.7", "farmhash-modern": "^1.1.0", "fast-deep-equal": "^3.1.1", "google-auth-library": "^9.14.2", "jsonwebtoken": "^9.0.0", "jwks-rsa": "^3.1.0", "node-forge": "^1.3.1", "uuid": "^11.0.2" }, "optionalDependencies": { "@google-cloud/firestore": "^7.11.0", "@google-cloud/storage": "^7.14.0" } }, "sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw=="], "form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], @@ -952,8 +879,6 @@ "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - "idb": ["idb@7.1.1", "", {}, "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="], - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], @@ -1184,8 +1109,6 @@ "vue-router": ["vue-router@4.6.4", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg=="], - "web-vitals": ["web-vitals@4.2.4", "", {}, "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="], - "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], @@ -1234,6 +1157,8 @@ "@google-cloud/storage/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], + "@grpc/grpc-js/@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="], + "@jridgewell/gen-mapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], "@jridgewell/remapping/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], @@ -1262,8 +1187,6 @@ "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "google-gax/@grpc/grpc-js": ["@grpc/grpc-js@1.14.3", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA=="], - "google-gax/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], @@ -1308,8 +1231,6 @@ "firebase-admin/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - "google-gax/@grpc/grpc-js/@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="], - "lru-memoizer/lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], diff --git a/docs.json b/docs.json new file mode 100644 index 0000000..08db3c7 --- /dev/null +++ b/docs.json @@ -0,0 +1,518 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is the API server for Stream application.", + "title": "Stream API", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "host": "localhost:8080", + "basePath": "/", + "paths": { + "/payments": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create a new payment", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "payment" + ], + "summary": "Create Payment", + "parameters": [ + { + "description": "Payment Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/payment.CreatePaymentRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/plans": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get all active plans", + "produces": [ + "application/json" + ], + "tags": [ + "plan" + ], + "summary": "List Plans", + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Plan" + } + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/videos": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get paginated videos", + "produces": [ + "application/json" + ], + "tags": [ + "video" + ], + "summary": "List Videos", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "default": 10, + "description": "Page size", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Create video record after upload", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "video" + ], + "summary": "Create Video", + "parameters": [ + { + "description": "Video Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/video.CreateVideoRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Video" + } + } + } + ] + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/videos/upload-url": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Generate presigned URL for video upload", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "video" + ], + "summary": "Get Upload URL", + "parameters": [ + { + "description": "File Info", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/video.UploadURLRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/videos/{id}": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get video details by ID", + "produces": [ + "application/json" + ], + "tags": [ + "video" + ], + "summary": "Get Video", + "parameters": [ + { + "type": "string", + "description": "Video ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/model.Video" + } + } + } + ] + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + } + }, + "definitions": { + "model.Plan": { + "type": "object", + "properties": { + "cycle": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration_limit": { + "type": "integer" + }, + "features": { + "type": "string" + }, + "id": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "price": { + "type": "number" + }, + "quality_limit": { + "type": "string" + }, + "storage_limit": { + "type": "integer" + }, + "upload_limit": { + "type": "integer" + } + } + }, + "model.Video": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "description": { + "type": "string" + }, + "duration": { + "type": "integer" + }, + "format": { + "type": "string" + }, + "hls_path": { + "type": "string" + }, + "hls_token": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "processing_status": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "status": { + "type": "string" + }, + "storage_type": { + "type": "string" + }, + "thumbnail": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "url": { + "type": "string" + }, + "user_id": { + "type": "string" + }, + "views": { + "type": "integer" + } + } + }, + "payment.CreatePaymentRequest": { + "type": "object", + "required": [ + "amount", + "plan_id" + ], + "properties": { + "amount": { + "type": "number" + }, + "plan_id": { + "type": "string" + } + } + }, + "response.Response": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "data": {}, + "message": { + "type": "string" + } + } + }, + "video.CreateVideoRequest": { + "type": "object", + "required": [ + "size", + "title", + "url" + ], + "properties": { + "description": { + "type": "string" + }, + "duration": { + "description": "Maybe client knows, or we process later", + "type": "integer" + }, + "format": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "url": { + "description": "The S3 Key or Full URL", + "type": "string" + } + } + }, + "video.UploadURLRequest": { + "type": "object", + "required": [ + "content_type", + "filename", + "size" + ], + "properties": { + "content_type": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "size": { + "type": "integer" + } + } + } + }, + "securityDefinitions": { + "BearerAuth": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 7476f95..386f2a0 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "@unhead/vue": "^2.1.1", "@vueuse/core": "^14.1.0", "clsx": "^2.1.1", - "firebase": "^12.8.0", "firebase-admin": "^13.6.0", "hono": "^4.11.3", "is-mobile": "^5.0.0", diff --git a/src/api/client.ts b/src/api/client.ts new file mode 100644 index 0000000..0e8bb74 --- /dev/null +++ b/src/api/client.ts @@ -0,0 +1,678 @@ +/* eslint-disable */ +/* tslint:disable */ +// @ts-nocheck +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ +import { customFetch } from "@httpClientAdapter"; +export interface AuthForgotPasswordRequest { + email: string; +} + +export interface AuthLoginRequest { + email: string; + password: string; +} + +export interface AuthRegisterRequest { + email: string; + /** @minLength 6 */ + password: string; + username: string; +} + +export interface AuthResetPasswordRequest { + /** @minLength 6 */ + new_password: string; + token: string; +} + +export interface ModelPlan { + cycle?: string; + description?: string; + duration_limit?: number; + features?: string; + id?: string; + is_active?: boolean; + name?: string; + price?: number; + quality_limit?: string; + storage_limit?: number; + upload_limit?: number; +} + +export interface ModelUser { + avatar?: string; + created_at?: string; + email?: string; + google_id?: string; + id?: string; + password?: string; + plan_id?: string; + role?: string; + storage_used?: number; + updated_at?: string; + username?: string; +} + +export interface ModelVideo { + created_at?: string; + description?: string; + duration?: number; + format?: string; + hls_path?: string; + hls_token?: string; + id?: string; + name?: string; + processing_status?: string; + size?: number; + status?: string; + storage_type?: string; + thumbnail?: string; + title?: string; + updated_at?: string; + url?: string; + user_id?: string; + views?: number; +} + +export interface PaymentCreatePaymentRequest { + amount: number; + plan_id: string; +} + +export interface ResponseResponse { + code?: number; + message?: string; +} + +export interface VideoCreateVideoRequest { + description?: string; + /** Maybe client knows, or we process later */ + duration?: number; + format?: string; + size: number; + title: string; + /** The S3 Key or Full URL */ + url: string; +} + +export interface VideoUploadURLRequest { + content_type: string; + filename: string; + size: number; +} + +export type QueryParamsType = Record; +export type ResponseFormat = keyof Omit; + +export interface FullRequestParams extends Omit { + /** set parameter to `true` for call `securityWorker` for this request */ + secure?: boolean; + /** request path */ + path: string; + /** content type of request body */ + type?: ContentType; + /** query params */ + query?: QueryParamsType; + /** format of response (i.e. response.json() -> format: "json") */ + format?: ResponseFormat; + /** request body */ + body?: unknown; + /** base url */ + baseUrl?: string; + /** request cancellation token */ + cancelToken?: CancelToken; +} + +export type RequestParams = Omit< + FullRequestParams, + "body" | "method" | "query" | "path" +>; + +export interface ApiConfig { + baseUrl?: string; + baseApiParams?: Omit; + securityWorker?: ( + securityData: SecurityDataType | null, + ) => Promise | RequestParams | void; + customFetch?: typeof fetch; +} + +export interface HttpResponse + extends Response { + data: D; + error: E; +} + +type CancelToken = Symbol | string | number; + +export enum ContentType { + Json = "application/json", + JsonApi = "application/vnd.api+json", + FormData = "multipart/form-data", + UrlEncoded = "application/x-www-form-urlencoded", + Text = "text/plain", +} + +export class HttpClient { + public baseUrl: string = ""; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => + fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter( + (key) => "undefined" !== typeof query[key], + ); + return keys + .map((key) => + Array.isArray(query[key]) + ? this.addArrayQueryParam(query, key) + : this.addQueryParam(query, key), + ) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? `?${queryString}` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.JsonApi]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.Text]: (input: any) => + input !== null && typeof input !== "string" + ? JSON.stringify(input) + : input, + [ContentType.FormData]: (input: any) => { + if (input instanceof FormData) { + return input; + } + + return Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : `${property}`, + ); + return formData; + }, new FormData()); + }, + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams( + params1: RequestParams, + params2?: RequestParams, + ): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, + }; + } + + protected createAbortSignal = ( + cancelToken: CancelToken, + ): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; + } + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); + } + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise> => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + + return this.customFetch( + `${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, + { + ...requestParams, + headers: { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData + ? { "Content-Type": type } + : {}), + }, + signal: + (cancelToken + ? this.createAbortSignal(cancelToken) + : requestParams.signal) || null, + body: + typeof body === "undefined" || body === null + ? null + : payloadFormatter(body) + }, + ).then(async (response) => { + const r = response as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const responseToParse = responseFormat ? response.clone() : response; + const data = !responseFormat + ? r + : await responseToParse[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { + this.abortControllers.delete(cancelToken); + } + + if (!response.ok) throw data; + return data; + }); + }; +} + +/** + * @title Stream API + * @version 1.0 + * @license Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html) + * @termsOfService http://swagger.io/terms/ + * @contact API Support (http://www.swagger.io/support) + * + * This is the API server for Stream application. + */ +export class Api< + SecurityDataType extends unknown, +> extends HttpClient { + auth = { + /** + * @description Request password reset link + * + * @tags auth + * @name ForgotPasswordCreate + * @summary Forgot Password + * @request POST:/auth/forgot-password + */ + forgotPasswordCreate: ( + request: AuthForgotPasswordRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/auth/forgot-password`, + method: "POST", + body: request, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Callback for Google Login + * + * @tags auth + * @name GoogleCallbackList + * @summary Google Callback + * @request GET:/auth/google/callback + */ + googleCallbackList: (params: RequestParams = {}) => + this.request< + ResponseResponse & { + data?: ModelUser; + }, + ResponseResponse + >({ + path: `/auth/google/callback`, + method: "GET", + ...params, + }), + + /** + * @description Redirect to Google for Login + * + * @tags auth + * @name GoogleLoginList + * @summary Google Login + * @request GET:/auth/google/login + */ + googleLoginList: (params: RequestParams = {}) => + this.request({ + path: `/auth/google/login`, + method: "GET", + ...params, + }), + + /** + * @description Login with email and password + * + * @tags auth + * @name LoginCreate + * @summary Login + * @request POST:/auth/login + */ + loginCreate: (request: AuthLoginRequest, params: RequestParams = {}) => + this.request< + ResponseResponse & { + data?: ModelUser; + }, + ResponseResponse + >({ + path: `/auth/login`, + method: "POST", + body: request, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Logout user and clear cookies + * + * @tags auth + * @name LogoutCreate + * @summary Logout + * @request POST:/auth/logout + */ + logoutCreate: (params: RequestParams = {}) => + this.request({ + path: `/auth/logout`, + method: "POST", + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Register a new user + * + * @tags auth + * @name RegisterCreate + * @summary Register + * @request POST:/auth/register + */ + registerCreate: ( + request: AuthRegisterRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/auth/register`, + method: "POST", + body: request, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Reset password using token + * + * @tags auth + * @name ResetPasswordCreate + * @summary Reset Password + * @request POST:/auth/reset-password + */ + resetPasswordCreate: ( + request: AuthResetPasswordRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/auth/reset-password`, + method: "POST", + body: request, + type: ContentType.Json, + format: "json", + ...params, + }), + }; + payments = { + /** + * @description Create a new payment + * + * @tags payment + * @name PaymentsCreate + * @summary Create Payment + * @request POST:/payments + * @secure + */ + paymentsCreate: ( + request: PaymentCreatePaymentRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/payments`, + method: "POST", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + }; + plans = { + /** + * @description Get all active plans + * + * @tags plan + * @name PlansList + * @summary List Plans + * @request GET:/plans + * @secure + */ + plansList: (params: RequestParams = {}) => + this.request< + ResponseResponse & { + data?: ModelPlan[]; + }, + ResponseResponse + >({ + path: `/plans`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + }; + videos = { + /** + * @description Get paginated videos + * + * @tags video + * @name VideosList + * @summary List Videos + * @request GET:/videos + * @secure + */ + videosList: ( + query?: { + /** + * Page number + * @default 1 + */ + page?: number; + /** + * Page size + * @default 10 + */ + limit?: number; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/videos`, + method: "GET", + query: query, + secure: true, + format: "json", + ...params, + }), + + /** + * @description Create video record after upload + * + * @tags video + * @name VideosCreate + * @summary Create Video + * @request POST:/videos + * @secure + */ + videosCreate: ( + request: VideoCreateVideoRequest, + params: RequestParams = {}, + ) => + this.request< + ResponseResponse & { + data?: ModelVideo; + }, + ResponseResponse + >({ + path: `/videos`, + method: "POST", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Generate presigned URL for video upload + * + * @tags video + * @name UploadUrlCreate + * @summary Get Upload URL + * @request POST:/videos/upload-url + * @secure + */ + uploadUrlCreate: ( + request: VideoUploadURLRequest, + params: RequestParams = {}, + ) => + this.request({ + path: `/videos/upload-url`, + method: "POST", + body: request, + secure: true, + type: ContentType.Json, + format: "json", + ...params, + }), + + /** + * @description Get video details by ID + * + * @tags video + * @name VideosDetail + * @summary Get Video + * @request GET:/videos/{id} + * @secure + */ + videosDetail: (id: string, params: RequestParams = {}) => + this.request< + ResponseResponse & { + data?: ModelVideo; + }, + ResponseResponse + >({ + path: `/videos/${id}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + }; +} + +export const client = new Api({ + baseUrl: 'http://localhost:8080', + customFetch +}); \ No newline at end of file diff --git a/src/api/httpClientAdapter.client.ts b/src/api/httpClientAdapter.client.ts index 6431b06..3095c53 100644 --- a/src/api/httpClientAdapter.client.ts +++ b/src/api/httpClientAdapter.client.ts @@ -1,65 +1,6 @@ -import { TinyRpcClientAdapter, TinyRpcError } from "@hiogawa/tiny-rpc"; -import { Result } from "@hiogawa/utils"; - -const GET_PAYLOAD_PARAM = "payload"; - -export function httpClientAdapter(opts: { - url: string; - pathsForGET?: string[]; - headers?: () => Promise> | Record; -}): TinyRpcClientAdapter { - return { - send: async (data) => { - const url = [opts.url, data.path].join("/"); - const payload = JSON.stringify(data.args); - const method = opts.pathsForGET?.includes(data.path) - ? "GET" - : "POST"; - - const extraHeaders = opts.headers ? await opts.headers() : {}; - - let req: Request; - if (method === "GET") { - req = new Request( - url + - "?" + - new URLSearchParams({ [GET_PAYLOAD_PARAM]: payload }), - { - headers: extraHeaders - } - ); - } else { - req = new Request(url, { - method: "POST", - body: payload, - headers: { - "content-type": "application/json; charset=utf-8", - ...extraHeaders - }, - credentials: "include", - }); - } - let res: Response; - res = await fetch(req); - if (!res.ok) { - // throw new Error(`HTTP error: ${res.status}`); - throw new Error( - JSON.stringify({ - status: res.status, - statusText: res.statusText, - data: { message: await res.text() }, - internal: true, - }) - ); - // throw TinyRpcError.deserialize(res.status); - } - const result: Result = JSON.parse( - await res.text() - ); - if (!result.ok) { - throw TinyRpcError.deserialize(result.value); - } - return result.value; - }, - }; +export const customFetch = (url: string, options: RequestInit) => { + return fetch(url, { + ...options, + credentials: "include", + }); } \ No newline at end of file diff --git a/src/api/httpClientAdapter.server.ts b/src/api/httpClientAdapter.server.ts index 5ac17f6..96256d9 100644 --- a/src/api/httpClientAdapter.server.ts +++ b/src/api/httpClientAdapter.server.ts @@ -1,70 +1,19 @@ -import { TinyRpcClientAdapter, TinyRpcError } from "@hiogawa/tiny-rpc"; -import { Result } from "@hiogawa/utils"; import { tryGetContext } from "hono/context-storage"; -const GET_PAYLOAD_PARAM = "payload"; - -export function httpClientAdapter(opts: { - url: string; - pathsForGET?: string[]; - headers?: () => Promise> | Record; -}): TinyRpcClientAdapter { - return { - send: async (data) => { - const url = [opts.url, data.path].join("/"); - const payload = JSON.stringify(data.args); - const method = opts.pathsForGET?.includes(data.path) - ? "GET" - : "POST"; - let req: Request; - if (method === "GET") { - req = new Request( - url + - "?" + - new URLSearchParams({ [GET_PAYLOAD_PARAM]: payload }) - ); - } else { - req = new Request(url, { - method: "POST", - body: payload, - headers: { - "content-type": "application/json; charset=utf-8", - }, - credentials: "include", - }); - } - let res: Response; - if (import.meta.env.SSR) { - const c = tryGetContext(); - if (!c) { - throw new Error("Hono context not found in SSR"); - } - Object.entries(c.req.header()).forEach(([k, v]) => { - req.headers.append(k, v); - }); - res = await c.get("fetch")(req); - } else { - res = await fetch(req); - } - if (!res.ok) { - // throw new Error(`HTTP error: ${res.status}`); - throw new Error( - JSON.stringify({ - status: res.status, - statusText: res.statusText, - data: { message: await res.text() }, - internal: true, - }) - ); - // throw TinyRpcError.deserialize(res.status); - } - const result: Result = JSON.parse( - await res.text() - ); - if (!result.ok) { - throw TinyRpcError.deserialize(result.value); - } - return result.value; - }, - }; +export const customFetch = async (url: string, options: RequestInit) => { + options.credentials = "include"; + if (!options.headers) { + options.headers = {}; + } + if (import.meta.env.SSR) { + const c = tryGetContext(); + if (!c) { + throw new Error("Hono context not found in SSR"); + } + Object.entries(c.req.header()).forEach(([k, v]) => { + Object.assign(options.headers!, { [k]: v }); + }); + return await c.get("fetch")(url, options); + } + return fetch(url, options); } \ No newline at end of file diff --git a/src/api/rpcclient.ts b/src/api/rpcclient.ts deleted file mode 100644 index 608bc4d..0000000 --- a/src/api/rpcclient.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { - proxyTinyRpc, - TinyRpcClientAdapter, - TinyRpcError, -} from "@hiogawa/tiny-rpc"; -import type { RpcRoutes } from "./rpc"; -import { Result } from "@hiogawa/utils"; -import { httpClientAdapter } from "@httpClientAdapter"; -// console.log("httpClientAdapter module:", httpClientAdapter.toString()); -declare let __host__: string; -const endpoint = "/rpc"; -const url = import.meta.env.SSR ? "http://localhost" : ""; -import { auth } from "../lib/firebase"; - -export const client = proxyTinyRpc({ - adapter: httpClientAdapter({ - url: url + endpoint, - pathsForGET: [], - headers: async () => { - if (import.meta.env.SSR) return {}; // No client auth on server for now - const user = auth.currentUser; - if (user) { - // Force refresh if needed or just get token - const token = await user.getIdToken(); - return { Authorization: `Bearer ${token}` }; - } - return {}; - } - }), -}); diff --git a/src/lib/firebase.ts b/src/lib/firebase.ts deleted file mode 100644 index 0c84959..0000000 --- a/src/lib/firebase.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { initializeApp } from "firebase/app"; -import { createUserWithEmailAndPassword, getAuth, GoogleAuthProvider, sendPasswordResetEmail, signInWithEmailAndPassword, signInWithPopup } from "firebase/auth"; -// TODO: Add SDKs for Firebase products that you want to use -// https://firebase.google.com/docs/web/setup#available-libraries - -// Your web app's Firebase configuration -const firebaseConfig = { - apiKey: "AIzaSyBTr0L5qxdrVEtWuP2oAicJXQvVyeXkMts", - authDomain: "trello-7ea39.firebaseapp.com", - projectId: "trello-7ea39", - storageBucket: "trello-7ea39.firebasestorage.app", - messagingSenderId: "321067890572", - appId: "1:321067890572:web:e34e1e657125d37be688a9" -}; - -// Initialize Firebase -const appFirebase = initializeApp(firebaseConfig); -const provider = new GoogleAuthProvider(); -export const auth = getAuth(appFirebase); -export const googleAuth = () => signInWithPopup(auth, provider).then((result) => { - console.log('User signed in:', result.user); - return result; -}) -export const emailAuth = (username: string, password: string) => { - return signInWithEmailAndPassword(auth, username, password) -} -export const forgotPassword = (email: string) => { - return sendPasswordResetEmail(auth, email) - .then(() => { - console.log('Password reset email sent'); - }) - .catch((error) => { - console.error('Error sending password reset email:', error); - throw error; - }); -} -export const signUp = (email: string, password: string) => { - return createUserWithEmailAndPassword(auth, email, password) - .then((userCredential) => { - console.log('User signed up:', userCredential.user); - return userCredential.user; - }) - .catch((error) => { - console.error('Error signing up:', error); - throw error; - }); -} \ No newline at end of file diff --git a/src/lib/firebaseAdmin.ts b/src/lib/firebaseAdmin.ts deleted file mode 100644 index 7f1d4c9..0000000 --- a/src/lib/firebaseAdmin.ts +++ /dev/null @@ -1,12 +0,0 @@ -// import { initializeApp, getApps, cert } from 'firebase-admin/app'; -// import { getAuth } from 'firebase-admin/auth'; -// import certJson from './cert.json'; -// const firebaseAdminConfig = { -// credential: cert(certJson as any) -// }; - -// if (getApps().length === 0) { -// initializeApp(firebaseAdminConfig); -// } - -// export const adminAuth = getAuth(); diff --git a/src/routes/index.ts b/src/routes/index.ts index 6a18c76..68e95f6 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -76,7 +76,7 @@ const routes: RouteData[] = [ { path: "upload", name: "upload", - component: () => import("./add/Add.vue"), + component: () => import("./upload/Upload.vue"), meta: { head: { title: 'Upload - Holistream', @@ -86,7 +86,7 @@ const routes: RouteData[] = [ { path: "video", name: "video", - component: () => import("./add/Add.vue"), + component: () => import("./video/Videos.vue"), meta: { head: { title: 'Videos - Holistream', @@ -99,7 +99,7 @@ const routes: RouteData[] = [ { path: "plans", name: "plans", - component: () => import("./add/Add.vue"), + component: () => import("./plans/Plans.vue"), meta: { head: { title: 'Plans & Billing', @@ -130,28 +130,28 @@ const routes: RouteData[] = [ }, ]; const createAppRouter = () => { -const router = createRouter({ - history: import.meta.env.SSR - ? createMemoryHistory() // server - : createWebHistory(), // client - routes, -}); + const router = createRouter({ + history: import.meta.env.SSR + ? createMemoryHistory() // server + : createWebHistory(), // client + routes, + }); -router.beforeEach((to, from, next) => { - const auth = useAuthStore(); - const head = inject(headSymbol); - (head as any).push(to.meta.head || {}); - if (to.matched.some((record) => record.meta.requiresAuth)) { - if (!auth.user) { - next({ name: "login" }); + router.beforeEach((to, from, next) => { + const auth = useAuthStore(); + const head = inject(headSymbol); + (head as any).push(to.meta.head || {}); + if (to.matched.some((record) => record.meta.requiresAuth)) { + if (!auth.user) { + next({ name: "login" }); + } else { + next(); + } } else { next(); } - } else { - next(); - } -}); -return router; + }); + return router; } export default createAppRouter; diff --git a/src/routes/plans/Plans.vue b/src/routes/plans/Plans.vue new file mode 100644 index 0000000..5b0d401 --- /dev/null +++ b/src/routes/plans/Plans.vue @@ -0,0 +1,117 @@ + + + diff --git a/src/routes/upload/Upload.vue b/src/routes/upload/Upload.vue new file mode 100644 index 0000000..9ec15a9 --- /dev/null +++ b/src/routes/upload/Upload.vue @@ -0,0 +1,181 @@ + + + diff --git a/src/routes/video/Videos.vue b/src/routes/video/Videos.vue new file mode 100644 index 0000000..d636341 --- /dev/null +++ b/src/routes/video/Videos.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/stores/auth.ts b/src/stores/auth.ts index b347404..79c50f1 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -1,115 +1,128 @@ import { defineStore } from 'pinia'; import { useRouter } from 'vue-router'; -// import { client } from '@/api/rpcclient'; // client no longer used for auth actions -import { ref, onMounted } from 'vue'; -import { emailAuth, signUp, auth, googleAuth } from '@/lib/firebase'; -import { onAuthStateChanged, signOut, User as FirebaseUser } from 'firebase/auth'; - -interface User { - id: string; - username: string; - email: string; - name: string; -} +import { ref } from 'vue'; +import { client, ResponseResponse, type ModelUser } from '@/api/client'; export const useAuthStore = defineStore('auth', () => { - const user = ref(null); + const user = ref(null); const router = useRouter(); const loading = ref(false); const error = ref(null); const initialized = ref(false); - // Check auth status on init using Firebase observer + // Initial check for session could go here if there was a /me endpoint or token check async function init() { - if (initialized.value) return; - - return new Promise((resolve) => { - const unsubscribe = onAuthStateChanged(auth, (currentUser) => { - if (currentUser) { - user.value = mapFirebaseUser(currentUser); - } else { - user.value = null; - } - initialized.value = true; - resolve(); - // We could unsubscribe here if we only want initial load, - // but keeping it listens for changes (token refresh etc) - // However, 'init' usually implies just ONCE waiter. - // For reactivity, user.value is updated. - }); - // Note: onAuthStateChanged returns an unsubscribe function. - // If we want to keep listening, we shouldn't unsubscribe immediately, - // but for 'await auth.init()' we just want to wait for the first known state. + // if (initialized.value) return; + const response = await client.request< + ResponseResponse & { + data?: ModelUser; + }, + ResponseResponse + >({ + path: '/me', + method: 'GET' }); - } - - function mapFirebaseUser(fwUser: FirebaseUser): User { - return { - id: fwUser.uid, - username: fwUser.email?.split('@')[0] || 'user', // fallback - email: fwUser.email || '', - name: fwUser.displayName || fwUser.email?.split('@')[0] || 'User' - }; + if (response.ok) { + // user.value = response.data?.data; + if (response.data?.data) { + user.value = response.data.data; + } + initialized.value = true; + } } async function login(username: string, password: string) { loading.value = true; error.value = null; - // Assuming username is email for Firebase, or we need to look it up? - // Firebase works with Email. If input is username, this might fail. - // For now assume email. - return emailAuth(username, password).then((userCredential) => { - user.value = mapFirebaseUser(userCredential.user); - router.push('/'); - }).catch((e: any) => { + try { + const response = await client.auth.loginCreate({ + email: username, + password: password + }); + + // Expected response structure: { data: { code: 200, data: User, message: "..." } } based on typical wrapper + schema + // BUT client.ts generated code typically returns the body directly in .data property of HttpResponse + // And schema says ResponseResponse has 'data': {} + // So: response.data (HttpResponse body) -> .data (ResponseResponse payload) + + const body = response.data as any; // Cast to access potential 'data' property if types are loose + if (body && body.data) { + user.value = body.data; + router.push('/'); + } else { + throw new Error('Login failed: No user data received'); + } + } catch (e: any) { console.error(e); error.value = 'Login failed: ' + (e.message || 'Unknown error'); throw e; - }).finally(() => { + } finally { loading.value = false; - }); + } } async function loginWithGoogle() { - loading.value = true; - error.value = null; - return googleAuth().then((result) => { - user.value = mapFirebaseUser(result.user); - router.push('/'); - }).catch((e: any) => { - console.error(e); - error.value = 'Google Login failed'; - throw e; - }).finally(() => { - loading.value = false; - }); + // usually this initiates a redirect loop. + // Doing it via client.request might follow redirect or return html. + // Best to just redirect the window. + window.location.href = `${client.baseUrl}/auth/google/login`; } async function register(username: string, email: string, password: string) { loading.value = true; error.value = null; - return signUp(email, password).then((fwUser) => { - // update profile with username? - // updateProfile(fwUser, { displayName: username }); - user.value = mapFirebaseUser(fwUser); - router.push('/'); - }).catch((e: any) => { + try { + const response = await client.auth.registerCreate({ + username, + email, + password + }); + + // Check success + const body = response.data as any; + if (response.ok) { + // Auto login or redirect to login? + // Usually register returns success, user must login. + router.push('/login'); + } else { + throw new Error(body.message || 'Registration failed'); + } + } catch (e: any) { console.error(e); error.value = 'Registration failed: ' + (e.message || 'Unknown error'); throw e; - }).finally(() => { + } finally { loading.value = false; - }); + } } async function logout() { - return signOut(auth).then(() => { + loading.value = true; + try { + await client.auth.logoutCreate(); user.value = null; - router.push('/'); - }) + router.push('/login'); + } catch (e: any) { + console.error('Logout error', e); + // Force local logout anyway + user.value = null; + router.push('/login'); + } finally { + loading.value = false; + } } + return { - user, loading, error, initialized, init, login, loginWithGoogle, register, logout, $reset: () => { + user, + loading, + error, + initialized, + init, + login, + loginWithGoogle, + register, + logout, + $reset: () => { user.value = null; loading.value = false; error.value = null; diff --git a/src/type.d.ts b/src/type.d.ts index cf68c16..c7cbac6 100644 --- a/src/type.d.ts +++ b/src/type.d.ts @@ -2,10 +2,5 @@ /// declare module "@httpClientAdapter" { - import { TinyRpcClientAdapter } from "@hiogawa/tiny-rpc"; - export function httpClientAdapter(opts: { - url: string; - pathsForGET?: string[]; - headers?: () => Promise<{ Authorization?: undefined; } | { Authorization: string; }> - }): TinyRpcClientAdapter; + export const customFetch: (url: string, options: RequestInit) => Promise; } \ No newline at end of file