vợ bảo okeoke
This commit is contained in:
90
auto-imports.d.ts
vendored
Normal file
90
auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue').EffectScope
|
||||
const acceptHMRUpdate: typeof import('pinia').acceptHMRUpdate
|
||||
const computed: typeof import('vue').computed
|
||||
const createApp: typeof import('vue').createApp
|
||||
const createPinia: typeof import('pinia').createPinia
|
||||
const customRef: typeof import('vue').customRef
|
||||
const defineAsyncComponent: typeof import('vue').defineAsyncComponent
|
||||
const defineComponent: typeof import('vue').defineComponent
|
||||
const defineStore: typeof import('pinia').defineStore
|
||||
const effectScope: typeof import('vue').effectScope
|
||||
const getActivePinia: typeof import('pinia').getActivePinia
|
||||
const getCurrentInstance: typeof import('vue').getCurrentInstance
|
||||
const getCurrentScope: typeof import('vue').getCurrentScope
|
||||
const getCurrentWatcher: typeof import('vue').getCurrentWatcher
|
||||
const h: typeof import('vue').h
|
||||
const inject: typeof import('vue').inject
|
||||
const isProxy: typeof import('vue').isProxy
|
||||
const isReactive: typeof import('vue').isReactive
|
||||
const isReadonly: typeof import('vue').isReadonly
|
||||
const isRef: typeof import('vue').isRef
|
||||
const isShallow: typeof import('vue').isShallow
|
||||
const mapActions: typeof import('pinia').mapActions
|
||||
const mapGetters: typeof import('pinia').mapGetters
|
||||
const mapState: typeof import('pinia').mapState
|
||||
const mapStores: typeof import('pinia').mapStores
|
||||
const mapWritableState: typeof import('pinia').mapWritableState
|
||||
const markRaw: typeof import('vue').markRaw
|
||||
const nextTick: typeof import('vue').nextTick
|
||||
const onActivated: typeof import('vue').onActivated
|
||||
const onBeforeMount: typeof import('vue').onBeforeMount
|
||||
const onBeforeRouteLeave: typeof import('vue-router').onBeforeRouteLeave
|
||||
const onBeforeRouteUpdate: typeof import('vue-router').onBeforeRouteUpdate
|
||||
const onBeforeUnmount: typeof import('vue').onBeforeUnmount
|
||||
const onBeforeUpdate: typeof import('vue').onBeforeUpdate
|
||||
const onDeactivated: typeof import('vue').onDeactivated
|
||||
const onErrorCaptured: typeof import('vue').onErrorCaptured
|
||||
const onMounted: typeof import('vue').onMounted
|
||||
const onRenderTracked: typeof import('vue').onRenderTracked
|
||||
const onRenderTriggered: typeof import('vue').onRenderTriggered
|
||||
const onScopeDispose: typeof import('vue').onScopeDispose
|
||||
const onServerPrefetch: typeof import('vue').onServerPrefetch
|
||||
const onUnmounted: typeof import('vue').onUnmounted
|
||||
const onUpdated: typeof import('vue').onUpdated
|
||||
const onWatcherCleanup: typeof import('vue').onWatcherCleanup
|
||||
const provide: typeof import('vue').provide
|
||||
const reactive: typeof import('vue').reactive
|
||||
const readonly: typeof import('vue').readonly
|
||||
const ref: typeof import('vue').ref
|
||||
const resolveComponent: typeof import('vue').resolveComponent
|
||||
const setActivePinia: typeof import('pinia').setActivePinia
|
||||
const setMapStoreSuffix: typeof import('pinia').setMapStoreSuffix
|
||||
const shallowReactive: typeof import('vue').shallowReactive
|
||||
const shallowReadonly: typeof import('vue').shallowReadonly
|
||||
const shallowRef: typeof import('vue').shallowRef
|
||||
const storeToRefs: typeof import('pinia').storeToRefs
|
||||
const toRaw: typeof import('vue').toRaw
|
||||
const toRef: typeof import('vue').toRef
|
||||
const toRefs: typeof import('vue').toRefs
|
||||
const toValue: typeof import('vue').toValue
|
||||
const triggerRef: typeof import('vue').triggerRef
|
||||
const unref: typeof import('vue').unref
|
||||
const useAttrs: typeof import('vue').useAttrs
|
||||
const useCssModule: typeof import('vue').useCssModule
|
||||
const useCssVars: typeof import('vue').useCssVars
|
||||
const useId: typeof import('vue').useId
|
||||
const useLink: typeof import('vue-router').useLink
|
||||
const useModel: typeof import('vue').useModel
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
const useSlots: typeof import('vue').useSlots
|
||||
const useTemplateRef: typeof import('vue').useTemplateRef
|
||||
const watch: typeof import('vue').watch
|
||||
const watchEffect: typeof import('vue').watchEffect
|
||||
const watchPostEffect: typeof import('vue').watchPostEffect
|
||||
const watchSyncEffect: typeof import('vue').watchSyncEffect
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, Slot, Slots, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, ShallowRef, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
21
bun.lock
21
bun.lock
@@ -30,6 +30,7 @@
|
||||
"@vitejs/plugin-vue": "^6.0.3",
|
||||
"@vitejs/plugin-vue-jsx": "^5.1.3",
|
||||
"unocss": "^66.5.12",
|
||||
"unplugin-auto-import": "^20.3.0",
|
||||
"unplugin-vue-components": "^30.0.0",
|
||||
"vite": "^7.3.0",
|
||||
"vite-ssr-components": "^0.5.2",
|
||||
@@ -654,7 +655,9 @@
|
||||
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
"escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||
|
||||
"exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="],
|
||||
|
||||
@@ -752,6 +755,8 @@
|
||||
|
||||
"rollup": ["rollup@4.54.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.54.0", "@rollup/rollup-android-arm64": "4.54.0", "@rollup/rollup-darwin-arm64": "4.54.0", "@rollup/rollup-darwin-x64": "4.54.0", "@rollup/rollup-freebsd-arm64": "4.54.0", "@rollup/rollup-freebsd-x64": "4.54.0", "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", "@rollup/rollup-linux-arm-musleabihf": "4.54.0", "@rollup/rollup-linux-arm64-gnu": "4.54.0", "@rollup/rollup-linux-arm64-musl": "4.54.0", "@rollup/rollup-linux-loong64-gnu": "4.54.0", "@rollup/rollup-linux-ppc64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-musl": "4.54.0", "@rollup/rollup-linux-s390x-gnu": "4.54.0", "@rollup/rollup-linux-x64-gnu": "4.54.0", "@rollup/rollup-linux-x64-musl": "4.54.0", "@rollup/rollup-openharmony-arm64": "4.54.0", "@rollup/rollup-win32-arm64-msvc": "4.54.0", "@rollup/rollup-win32-ia32-msvc": "4.54.0", "@rollup/rollup-win32-x64-gnu": "4.54.0", "@rollup/rollup-win32-x64-msvc": "4.54.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw=="],
|
||||
|
||||
"scule": ["scule@1.3.0", "", {}, "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="],
|
||||
|
||||
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||
@@ -766,6 +771,8 @@
|
||||
|
||||
"stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="],
|
||||
|
||||
"strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
|
||||
|
||||
"strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="],
|
||||
|
||||
"superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="],
|
||||
@@ -796,10 +803,14 @@
|
||||
|
||||
"unhead": ["unhead@2.1.1", "", { "dependencies": { "hookable": "^5.5.3" } }, "sha512-NOt8n2KybAOxSLfNXegAVai4SGU8bPKqWnqCzNAvnRH2i8mW+0bbFjN/L75LBgCSTiOjJSpANe5w2V34Grr7Cw=="],
|
||||
|
||||
"unimport": ["unimport@5.6.0", "", { "dependencies": { "acorn": "^8.15.0", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "pathe": "^2.0.3", "picomatch": "^4.0.3", "pkg-types": "^2.3.0", "scule": "^1.3.0", "strip-literal": "^3.1.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" } }, "sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A=="],
|
||||
|
||||
"unocss": ["unocss@66.5.12", "", { "dependencies": { "@unocss/astro": "66.5.12", "@unocss/cli": "66.5.12", "@unocss/core": "66.5.12", "@unocss/postcss": "66.5.12", "@unocss/preset-attributify": "66.5.12", "@unocss/preset-icons": "66.5.12", "@unocss/preset-mini": "66.5.12", "@unocss/preset-tagify": "66.5.12", "@unocss/preset-typography": "66.5.12", "@unocss/preset-uno": "66.5.12", "@unocss/preset-web-fonts": "66.5.12", "@unocss/preset-wind": "66.5.12", "@unocss/preset-wind3": "66.5.12", "@unocss/preset-wind4": "66.5.12", "@unocss/transformer-attributify-jsx": "66.5.12", "@unocss/transformer-compile-class": "66.5.12", "@unocss/transformer-directives": "66.5.12", "@unocss/transformer-variant-group": "66.5.12", "@unocss/vite": "66.5.12" }, "peerDependencies": { "@unocss/webpack": "66.5.12", "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0" }, "optionalPeers": ["@unocss/webpack", "vite"] }, "sha512-3WdSuM+SOjVpXDtffTuSvYTMuufpFzBehu2b4Tr7DcoIUxGouZn3mdxCLx3PiEuK0ih40Fo7Sjm+J4mccHfwLg=="],
|
||||
|
||||
"unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="],
|
||||
|
||||
"unplugin-auto-import": ["unplugin-auto-import@20.3.0", "", { "dependencies": { "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "picomatch": "^4.0.3", "unimport": "^5.5.0", "unplugin": "^2.3.11", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "@nuxt/kit": "^4.0.0", "@vueuse/core": "*" }, "optionalPeers": ["@nuxt/kit", "@vueuse/core"] }, "sha512-RcSEQiVv7g0mLMMXibYVKk8mpteKxvyffGuDKqZZiFr7Oq3PB1HwgHdK5O7H4AzbhzHoVKG0NnMnsk/1HIVYzQ=="],
|
||||
|
||||
"unplugin-utils": ["unplugin-utils@0.3.1", "", { "dependencies": { "pathe": "^2.0.3", "picomatch": "^4.0.3" } }, "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog=="],
|
||||
|
||||
"unplugin-vue-components": ["unplugin-vue-components@30.0.0", "", { "dependencies": { "chokidar": "^4.0.3", "debug": "^4.4.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.19", "mlly": "^1.8.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.10", "unplugin-utils": "^0.3.1" }, "peerDependencies": { "@babel/parser": "^7.15.8", "@nuxt/kit": "^3.2.2 || ^4.0.0", "vue": "2 || 3" }, "optionalPeers": ["@babel/parser", "@nuxt/kit"] }, "sha512-4qVE/lwCgmdPTp6h0qsRN2u642tt4boBQtcpn4wQcWZAsr8TQwq+SPT3NDu/6kBFxzo/sSEK4ioXhOOBrXc3iw=="],
|
||||
@@ -856,6 +867,10 @@
|
||||
|
||||
"@vitejs/plugin-vue-jsx/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.9-commit.d91dfb5", "", {}, "sha512-8sExkWRK+zVybw3+2/kBkYBFeLnEUWz1fT7BLHplpzmtqkOfTbAQ9gkt4pzwGIIZmg4Qn5US5ACjUBenrhezwQ=="],
|
||||
|
||||
"@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"@vue/devtools-kit/perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
|
||||
|
||||
"miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="],
|
||||
@@ -866,10 +881,14 @@
|
||||
|
||||
"sharp/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||
|
||||
"strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
|
||||
|
||||
"unconfig/quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="],
|
||||
|
||||
"unconfig-core/quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="],
|
||||
|
||||
"unimport/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"unplugin/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||
|
||||
"vue-router/@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="],
|
||||
|
||||
58
components.d.ts
vendored
Normal file
58
components.d.ts
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import { GlobalComponents } from 'vue'
|
||||
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
Add: typeof import('./src/components/icons/Add.vue')['default']
|
||||
AddFilled: typeof import('./src/components/icons/AddFilled.vue')['default']
|
||||
Bell: typeof import('./src/components/icons/Bell.vue')['default']
|
||||
BellFilled: typeof import('./src/components/icons/BellFilled.vue')['default']
|
||||
Button: typeof import('primevue/button')['default']
|
||||
Checkbox: typeof import('primevue/checkbox')['default']
|
||||
DashboardLayout: typeof import('./src/components/DashboardLayout.vue')['default']
|
||||
Home: typeof import('./src/components/icons/Home.vue')['default']
|
||||
HomeFilled: typeof import('./src/components/icons/HomeFilled.vue')['default']
|
||||
InputText: typeof import('primevue/inputtext')['default']
|
||||
Layout: typeof import('./src/components/icons/Layout.vue')['default']
|
||||
LayoutFilled: typeof import('./src/components/icons/LayoutFilled.vue')['default']
|
||||
Message: typeof import('primevue/message')['default']
|
||||
Password: typeof import('primevue/password')['default']
|
||||
RootLayout: typeof import('./src/components/RootLayout.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
TestIcon: typeof import('./src/components/icons/TestIcon.vue')['default']
|
||||
VueHead: typeof import('./src/components/VueHead.tsx')['default']
|
||||
}
|
||||
}
|
||||
|
||||
// For TSX support
|
||||
declare global {
|
||||
const Add: typeof import('./src/components/icons/Add.vue')['default']
|
||||
const AddFilled: typeof import('./src/components/icons/AddFilled.vue')['default']
|
||||
const Bell: typeof import('./src/components/icons/Bell.vue')['default']
|
||||
const BellFilled: typeof import('./src/components/icons/BellFilled.vue')['default']
|
||||
const Button: typeof import('primevue/button')['default']
|
||||
const Checkbox: typeof import('primevue/checkbox')['default']
|
||||
const DashboardLayout: typeof import('./src/components/DashboardLayout.vue')['default']
|
||||
const Home: typeof import('./src/components/icons/Home.vue')['default']
|
||||
const HomeFilled: typeof import('./src/components/icons/HomeFilled.vue')['default']
|
||||
const InputText: typeof import('primevue/inputtext')['default']
|
||||
const Layout: typeof import('./src/components/icons/Layout.vue')['default']
|
||||
const LayoutFilled: typeof import('./src/components/icons/LayoutFilled.vue')['default']
|
||||
const Message: typeof import('primevue/message')['default']
|
||||
const Password: typeof import('primevue/password')['default']
|
||||
const RootLayout: typeof import('./src/components/RootLayout.vue')['default']
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
const TestIcon: typeof import('./src/components/icons/TestIcon.vue')['default']
|
||||
const VueHead: typeof import('./src/components/VueHead.tsx')['default']
|
||||
}
|
||||
@@ -35,6 +35,7 @@
|
||||
"@vitejs/plugin-vue": "^6.0.3",
|
||||
"@vitejs/plugin-vue-jsx": "^5.1.3",
|
||||
"unocss": "^66.5.12",
|
||||
"unplugin-auto-import": "^20.3.0",
|
||||
"unplugin-vue-components": "^30.0.0",
|
||||
"vite": "^7.3.0",
|
||||
"vite-ssr-components": "^0.5.2",
|
||||
|
||||
57
src/api/httpClientAdapter.client.ts
Normal file
57
src/api/httpClientAdapter.client.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
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[];
|
||||
}): 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;
|
||||
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<unknown, unknown> = JSON.parse(
|
||||
await res.text()
|
||||
);
|
||||
if (!result.ok) {
|
||||
throw TinyRpcError.deserialize(result.value);
|
||||
}
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
}
|
||||
69
src/api/httpClientAdapter.server.ts
Normal file
69
src/api/httpClientAdapter.server.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
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[];
|
||||
}): 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<any>();
|
||||
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<unknown, unknown> = JSON.parse(
|
||||
await res.text()
|
||||
);
|
||||
if (!result.ok) {
|
||||
throw TinyRpcError.deserialize(result.value);
|
||||
}
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -164,6 +164,7 @@ const login = async (username: string, password: string) => {
|
||||
};
|
||||
|
||||
async function checkAuth() {
|
||||
console.log("Check auth called");
|
||||
const context = getContext<HonoVarTypes>();
|
||||
const token = getCookie(context, 'auth_token');
|
||||
|
||||
@@ -182,6 +183,7 @@ async function checkAuth() {
|
||||
if (!userRecord) {
|
||||
return { authenticated: false, user: null };
|
||||
}
|
||||
// console.log("Check auth called 2", userRecord);
|
||||
|
||||
return {
|
||||
authenticated: true,
|
||||
|
||||
@@ -5,6 +5,8 @@ import {
|
||||
} 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" : "";
|
||||
@@ -15,65 +17,3 @@ export const client = proxyTinyRpc<RpcRoutes>({
|
||||
pathsForGET: [],
|
||||
}),
|
||||
});
|
||||
const GET_PAYLOAD_PARAM = "payload";
|
||||
function httpClientAdapter(opts: {
|
||||
url: string;
|
||||
pathsForGET?: string[];
|
||||
}): 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 { getContext } = await import("hono/context-storage");
|
||||
const c = getContext<any>();
|
||||
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<unknown, unknown> = JSON.parse(
|
||||
await res.text()
|
||||
);
|
||||
if (!result.ok) {
|
||||
throw TinyRpcError.deserialize(result.value);
|
||||
}
|
||||
return result.value;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
15
src/components/VueHead.tsx
Normal file
15
src/components/VueHead.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useHead, UseHeadInput, UseHeadOptions } from "@unhead/vue";
|
||||
import { defineComponent, toRef } from "vue";
|
||||
interface VueHeadProps {
|
||||
input: UseHeadInput;
|
||||
options?: UseHeadOptions;
|
||||
}
|
||||
export const VueHead = defineComponent<VueHeadProps>({
|
||||
name: "VueHead",
|
||||
props: ["input", "options"],
|
||||
setup(props) {
|
||||
useHead(toRef(props, "input") as any, props.options);
|
||||
return () => null;
|
||||
}
|
||||
});
|
||||
export default VueHead;
|
||||
@@ -8,11 +8,12 @@ import { contextStorage } from 'hono/context-storage';
|
||||
import { cors } from "hono/cors";
|
||||
import { jwtRpc, rpcServer } from './api/rpc';
|
||||
import isMobile from 'is-mobile';
|
||||
import { useAuthStore } from './stores/auth';
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
// app.use(renderer)
|
||||
|
||||
app.use('*', contextStorage());
|
||||
app.use(cors(), async (c, next) => {
|
||||
c.set("fetch", app.request.bind(app));
|
||||
const ua = c.req.header("User-Agent")
|
||||
@@ -21,15 +22,20 @@ app.use(cors(), async (c, next) => {
|
||||
};
|
||||
c.set("isMobile", isMobile({ ua }));
|
||||
await next();
|
||||
}, contextStorage(), rpcServer);
|
||||
}, rpcServer);
|
||||
app.get("/.well-known/*", (c) => {
|
||||
return c.json({ ok: true });
|
||||
});
|
||||
app.get("*", async (c) => {
|
||||
const url = new URL(c.req.url);
|
||||
const { app, router, head } = createApp();
|
||||
router.push(url.pathname);
|
||||
await router.isReady();
|
||||
const { app, router, head, pinia } = createApp();
|
||||
app.provide("honoContext", c);
|
||||
await router.push(url.pathname);
|
||||
await router.isReady().then(() => {
|
||||
const auth = useAuthStore();
|
||||
auth.initialized = false;
|
||||
auth.init();
|
||||
});
|
||||
return streamText(c, async (stream) => {
|
||||
c.header("Content-Type", "text/html; charset=utf-8");
|
||||
c.header("Content-Encoding", "Identity");
|
||||
@@ -43,8 +49,8 @@ app.get("*", async (c) => {
|
||||
await stream.write(buildBootstrapScript());
|
||||
await stream.write("</head><body class='font-sans bg-[#f9fafd] text-gray-800 antialiased flex flex-col min-h-screen'>");
|
||||
await stream.pipe(appStream);
|
||||
let json = htmlEscape(JSON.stringify(JSON.stringify(ctx)));
|
||||
await stream.write(`<script>window.__SSR_STATE__ = JSON.parse(${json});</script>`);
|
||||
await stream.write(`<script>window.__SSR_STATE__ = JSON.parse(${htmlEscape(JSON.stringify(JSON.stringify(ctx)))});</script>`);
|
||||
await stream.write(`<script>window.__PINIA_STATE__ = JSON.parse(${htmlEscape(JSON.stringify(JSON.stringify(pinia.state.value)))});</script>`);
|
||||
await stream.write("</body></html>");
|
||||
});
|
||||
// return c.body(renderToWebStream(app, {}));
|
||||
|
||||
@@ -10,10 +10,10 @@ export function withErrorBoundary(WrappedComponent: any) {
|
||||
<div class="p-8 space-y-lg max-w-lg w-full">
|
||||
<p>
|
||||
<b>500. </b>
|
||||
<ins class="text-gray-500 decoration-none">Đã xảy ra lỗi.</ins>
|
||||
<ins class="text-gray-500 decoration-none">Something went wrong.</ins>
|
||||
</p>
|
||||
<div class="font-thin">
|
||||
<p>Máy chủ đang gặp sự cố tạm thời và không thể xử lý yêu cầu của bạn. Vui lòng <a class="underline text-primary" href="/">thử lại</a> sau vài phút.</p>
|
||||
<p>The server is currently experiencing temporary issues and cannot process your request. Please <a class="underline text-primary" href="/">try again</a> in a few minutes.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,18 +10,21 @@ import Aura from '@primeuix/themes/aura';
|
||||
import { createPinia } from "pinia";
|
||||
import { useAuthStore } from './stores/auth';
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
export function createApp() {
|
||||
const pinia = createPinia();
|
||||
const app = createSSRApp(withErrorBoundary(RouterView));
|
||||
const head = import.meta.env.SSR ? SSRHead() : CSRHead();
|
||||
|
||||
app.use(head);
|
||||
app.use(PrimeVue, {
|
||||
// unstyled: true,
|
||||
theme: {
|
||||
preset: Aura,
|
||||
options: {
|
||||
darkModeSelector: '.my-app-dark',
|
||||
cssLayer: false,
|
||||
prefix: 'pv-',
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -42,5 +45,5 @@ export function createApp() {
|
||||
});
|
||||
}
|
||||
|
||||
return { app, router, head };
|
||||
return { app, router, head, pinia };
|
||||
}
|
||||
12
src/routes/NotFound.vue
Normal file
12
src/routes/NotFound.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<vue-head :input="{title: '404 - Page Not Found'}"/>
|
||||
<div class="mx-auto text-center mt-20 flex flex-col items-center gap-4">
|
||||
<h1>404 - Page Not Found</h1>
|
||||
<p>The page you are looking for does not exist.</p>
|
||||
<router-link class="btn btn-primary" to="/">Go back to Home</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { VueHead } from "@/components/VueHead";
|
||||
</script>
|
||||
@@ -75,6 +75,11 @@ const routes: RouteData[] = [
|
||||
component: () => import("./add/Add.vue"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "/:pathMatch(.*)*",
|
||||
name: "not-found",
|
||||
component: () => import("./NotFound.vue"),
|
||||
}
|
||||
],
|
||||
},
|
||||
@@ -88,6 +93,7 @@ const router = createRouter({
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const auth = useAuthStore();
|
||||
console.log("Call on server:", Math.random());
|
||||
if (to.matched.some((record) => record.meta.requiresAuth)) {
|
||||
if (!auth.user) {
|
||||
next({ name: "login" });
|
||||
|
||||
@@ -20,10 +20,15 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
|
||||
// Check auth status on init (reads from cookie)
|
||||
async function init() {
|
||||
if (initialized.value) return;
|
||||
console.log("Auth store init called");
|
||||
// if (initialized.value) return;
|
||||
|
||||
try {
|
||||
const response = await client.checkAuth();
|
||||
const response = await client.checkAuth().then((res) => {
|
||||
|
||||
console.log("call", res);
|
||||
return res;
|
||||
});
|
||||
if (response.authenticated && response.user) {
|
||||
user.value = response.user;
|
||||
// Get CSRF token if authenticated
|
||||
|
||||
10
src/type.d.ts
vendored
Normal file
10
src/type.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/// <reference types="vite/client" />
|
||||
/// <reference types="unplugin-vue-components/types/vue" />
|
||||
|
||||
declare module "@httpClientAdapter" {
|
||||
import { TinyRpcClientAdapter } from "@hiogawa/tiny-rpc";
|
||||
export function httpClientAdapter(opts: {
|
||||
url: string;
|
||||
pathsForGET?: string[];
|
||||
}): TinyRpcClientAdapter;
|
||||
}
|
||||
11
ssrPlugin.ts
11
ssrPlugin.ts
@@ -32,6 +32,7 @@ export function clientFirstBuild(): Plugin {
|
||||
// Client build first
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (clientEnvironment) {
|
||||
// console.log("Client First Build Plugin: Building client...", clientEnvironment.resolve);
|
||||
await builder.build(clientEnvironment);
|
||||
}
|
||||
|
||||
@@ -107,6 +108,16 @@ export default function ssrPlugin(): Plugin[] {
|
||||
config(config) {
|
||||
config.define = config.define || {};
|
||||
},
|
||||
resolveId(id, importer, options) {
|
||||
if (!id.startsWith('@httpClientAdapter')) return
|
||||
|
||||
return path.resolve(
|
||||
__dirname,
|
||||
options?.ssr
|
||||
? "./src/api/httpClientAdapter.server.ts"
|
||||
: "./src/api/httpClientAdapter.client.ts"
|
||||
);
|
||||
},
|
||||
async configResolved(config) {
|
||||
const viteConfig = config as any;
|
||||
|
||||
|
||||
@@ -16,4 +16,11 @@
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"auto-imports.d.ts",
|
||||
"components.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,30 +1,47 @@
|
||||
import { cloudflare } from "@cloudflare/vite-plugin";
|
||||
import { defineConfig, Manifest, Plugin } from "vite";
|
||||
import { PrimeVueResolver } from "@primevue/auto-import-resolver";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import vueJsx from "@vitejs/plugin-vue-jsx";
|
||||
import unocss from "unocss/vite";
|
||||
import path from "node:path";
|
||||
import unocss from "unocss/vite";
|
||||
import Components from "unplugin-vue-components/vite";
|
||||
import AutoImport from "unplugin-auto-import/vite";
|
||||
import { defineConfig } from "vite";
|
||||
import ssrPlugin from "./ssrPlugin";
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import {PrimeVueResolver} from '@primevue/auto-import-resolver';
|
||||
export default defineConfig((env) => {
|
||||
// console.log("env:", env, import.meta.env);
|
||||
return {
|
||||
plugins: [
|
||||
unocss(),
|
||||
vue(),
|
||||
vueJsx(),
|
||||
AutoImport({
|
||||
imports: ["vue", "vue-router", "pinia"], // Common presets
|
||||
dts: true, // Generate TypeScript declaration file
|
||||
}),
|
||||
Components({
|
||||
dirs: ["src/components"],
|
||||
extensions: ["vue", "tsx"],
|
||||
dts: true,
|
||||
dtsTsx: true,
|
||||
directives: false,
|
||||
resolvers: [PrimeVueResolver()],
|
||||
}),
|
||||
ssrPlugin(),
|
||||
cloudflare(),
|
||||
Components({
|
||||
resolvers: [
|
||||
PrimeVueResolver()
|
||||
]
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
// "httpClientAdapter": path.resolve(__dirname, "./src/api/httpClientAdapter.server.ts")
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
exclude: ["vue"],
|
||||
},
|
||||
|
||||
ssr: {
|
||||
noExternal: ["vue"],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user