Merge branch 'vercel' into dev

This commit is contained in:
ccbikai 2024-12-24 22:00:39 +08:00
commit 2a172494e7
22 changed files with 3461 additions and 2436 deletions

50
.vscode/settings.json vendored
View file

@ -1,4 +1,50 @@
{ {
// Enable ESlint flat config support // Disable the default formatter, use eslint instead
"eslint.useFlatConfig": true "prettier.enable": false,
"editor.formatOnSave": false,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
// Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [
{ "rule": "style/*", "severity": "off", "fixable": true },
{ "rule": "format/*", "severity": "off", "fixable": true },
{ "rule": "*-indent", "severity": "off", "fixable": true },
{ "rule": "*-spacing", "severity": "off", "fixable": true },
{ "rule": "*-spaces", "severity": "off", "fixable": true },
{ "rule": "*-order", "severity": "off", "fixable": true },
{ "rule": "*-dangle", "severity": "off", "fixable": true },
{ "rule": "*-newline", "severity": "off", "fixable": true },
{ "rule": "*quotes", "severity": "off", "fixable": true },
{ "rule": "*semi", "severity": "off", "fixable": true }
],
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml",
"gql",
"graphql",
"astro",
"svelte",
"css",
"less",
"scss",
"pcss",
"postcss"
]
} }

View file

@ -1,6 +1,6 @@
<script setup> <script setup>
import { Flame, MousePointerClick, Users } from 'lucide-vue-next'
import NumberFlow from '@number-flow/vue' import NumberFlow from '@number-flow/vue'
import { Flame, MousePointerClick, Users } from 'lucide-vue-next'
const defaultData = Object.freeze({ const defaultData = Object.freeze({
visits: 0, visits: 0,

View file

@ -1,11 +1,11 @@
<script setup> <script setup>
import { z } from 'zod'
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import { Shuffle, Sparkles } from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import { DependencyType } from '@/components/ui/auto-form/interface' import { DependencyType } from '@/components/ui/auto-form/interface'
import { LinkSchema, nanoid } from '@/schemas/link' import { LinkSchema, nanoid } from '@/schemas/link'
import { toTypedSchema } from '@vee-validate/zod'
import { Shuffle, Sparkles } from 'lucide-vue-next'
import { useForm } from 'vee-validate'
import { toast } from 'vue-sonner'
import { z } from 'zod'
const props = defineProps({ const props = defineProps({
link: { link: {

View file

@ -1,6 +1,6 @@
<script setup> <script setup>
import { Loader } from 'lucide-vue-next'
import { useInfiniteScroll } from '@vueuse/core' import { useInfiniteScroll } from '@vueuse/core'
import { Loader } from 'lucide-vue-next'
const links = ref([]) const links = ref([])
const limit = 24 const limit = 24

View file

@ -1,8 +1,8 @@
<script setup> <script setup>
import { CalendarPlus2, Copy, CopyCheck, Eraser, Hourglass, Link as LinkIcon, QrCode, SquareChevronDown, SquarePen } from 'lucide-vue-next'
import { useClipboard } from '@vueuse/core' import { useClipboard } from '@vueuse/core'
import { toast } from 'vue-sonner' import { CalendarPlus2, Copy, CopyCheck, Eraser, Hourglass, Link as LinkIcon, QrCode, SquareChevronDown, SquarePen } from 'lucide-vue-next'
import { parseURL } from 'ufo' import { parseURL } from 'ufo'
import { toast } from 'vue-sonner'
import QRCode from './QRCode.vue' import QRCode from './QRCode.vue'
const props = defineProps({ const props = defineProps({

View file

@ -63,7 +63,7 @@ onMounted(() => {
</Button> </Button>
<Dialog :open="isOpen" @update:open="isOpen = !isOpen"> <Dialog :open="isOpen" @update:open="isOpen = !isOpen">
<DialogContent class="overflow-hidden p-0 shadow-lg"> <DialogContent class="overflow-hidden p-0 shadow-lg">
<Command v-model:searchTerm="searchTerm" v-model="selectedLink" class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> <Command v-model:search-term="searchTerm" v-model="selectedLink" class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
<CommandInput placeholder="Type to search..." /> <CommandInput placeholder="Type to search..." />
<CommandList> <CommandList>
<CommandEmpty v-if="searchTerm"> <CommandEmpty v-if="searchTerm">

View file

@ -1,6 +1,6 @@
<script setup> <script setup>
import { VisSingleContainer, VisTopoJSONMap, VisTopoJSONMapSelectors } from '@unovis/vue'
import { ChartTooltip } from '@/components/ui/chart' import { ChartTooltip } from '@/components/ui/chart'
import { VisSingleContainer, VisTopoJSONMap, VisTopoJSONMapSelectors } from '@unovis/vue'
const id = inject('id') const id = inject('id')
const startAt = inject('startAt') const startAt = inject('startAt')

View file

@ -1,4 +1,13 @@
<script setup> <script setup>
import {
Globe,
Laptop,
MonitorCheck,
Smartphone,
Tablet,
Terminal,
} from 'lucide-vue-next'
// https://vue3-simple-icons.wyatt-herkamp.dev/ // https://vue3-simple-icons.wyatt-herkamp.dev/
import { import {
AndroidIcon, AndroidIcon,
@ -20,23 +29,14 @@ import {
SamsungIcon, SamsungIcon,
UbuntuIcon, UbuntuIcon,
VivoIcon, VivoIcon,
WeChatIcon,
WearOsIcon, WearOsIcon,
WeChatIcon,
XiaomiIcon,
// WindowsIcon, // WindowsIcon,
XIcon, XIcon,
XiaomiIcon,
YandexCloudIcon, YandexCloudIcon,
} from 'vue3-simple-icons' } from 'vue3-simple-icons'
import {
Globe,
Laptop,
MonitorCheck,
Smartphone,
Tablet,
Terminal,
} from 'lucide-vue-next'
defineProps({ defineProps({
name: { name: {
type: String, type: String,

View file

@ -1,7 +1,7 @@
<script setup> <script setup>
import heroImg from '@/assets/images/hero.svg?raw'
import { AreaChart } from 'lucide-vue-next' import { AreaChart } from 'lucide-vue-next'
import { GitHubIcon } from 'vue3-simple-icons' import { GitHubIcon } from 'vue3-simple-icons'
import heroImg from '@/assets/images/hero.svg?raw'
const { title, description, github } = useAppConfig() const { title, description, github } = useAppConfig()
</script> </script>

View file

@ -1,6 +1,6 @@
<script setup> <script setup>
import { XIcon } from 'vue3-simple-icons'
import { ArrowRight } from 'lucide-vue-next' import { ArrowRight } from 'lucide-vue-next'
import { XIcon } from 'vue3-simple-icons'
const { twitter } = useAppConfig() const { twitter } = useAppConfig()
</script> </script>

View file

@ -1,7 +1,7 @@
<script setup> <script setup>
import { AlertCircle } from 'lucide-vue-next' import { AlertCircle } from 'lucide-vue-next'
import { z } from 'zod'
import { toast } from 'vue-sonner' import { toast } from 'vue-sonner'
import { z } from 'zod'
const LoginSchema = z.object({ const LoginSchema = z.object({
token: z.string().describe('SiteToken'), token: z.string().describe('SiteToken'),

View file

@ -1,6 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config // https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({ export default defineNuxtConfig({
devtools: { enabled: true },
modules: [ modules: [
'@nuxthub/core', '@nuxthub/core',
@ -9,46 +8,12 @@ export default defineNuxtConfig({
'@nuxtjs/tailwindcss', '@nuxtjs/tailwindcss',
'@nuxtjs/color-mode', '@nuxtjs/color-mode',
], ],
devtools: { enabled: true },
colorMode: { colorMode: {
classSuffix: '', classSuffix: '',
}, },
routeRules: {
'/': {
prerender: true,
},
'/dashboard/**': {
ssr: false,
},
'/dashboard': {
redirect: '/dashboard/links',
},
},
hub: {
ai: true,
analytics: true,
blob: false,
cache: false,
database: false,
kv: true,
},
eslint: {
config: {
stylistic: true,
standalone: false,
},
},
nitro: {
experimental: {
// Enable Server API documentation within NuxtHub
openAPI: true,
},
},
runtimeConfig: { runtimeConfig: {
siteToken: 'SinkCool', siteToken: 'SinkCool',
redirectStatusCode: '301', redirectStatusCode: '301',
@ -67,5 +32,40 @@ export default defineNuxtConfig({
}, },
}, },
routeRules: {
'/': {
prerender: true,
},
'/dashboard/**': {
ssr: false,
},
'/dashboard': {
redirect: '/dashboard/links',
},
},
compatibilityDate: '2024-07-08', compatibilityDate: '2024-07-08',
nitro: {
experimental: {
// Enable Server API documentation within NuxtHub
openAPI: true,
},
},
hub: {
ai: true,
analytics: true,
blob: false,
cache: false,
database: false,
kv: true,
},
eslint: {
config: {
stylistic: true,
standalone: false,
},
},
}) })

View file

@ -3,7 +3,7 @@
"type": "module", "type": "module",
"version": "0.1.7", "version": "0.1.7",
"private": true, "private": true,
"packageManager": "pnpm@9.7.1", "packageManager": "pnpm@9.15.1",
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"
}, },
@ -22,44 +22,44 @@
}, },
"dependencies": { "dependencies": {
"@number-flow/vue": "^0.3.3", "@number-flow/vue": "^0.3.3",
"@unovis/ts": "^1.4.4", "@unovis/ts": "^1.5.0",
"@unovis/vue": "^1.4.4", "@unovis/vue": "^1.5.0",
"@vee-validate/zod": "^4.13.2", "@vee-validate/zod": "^4.15.0",
"@vueuse/core": "^11.0.0", "@vueuse/core": "^12.2.0",
"fuse.js": "^7.0.0", "fuse.js": "^7.0.0",
"intl-parse-accept-language": "^1.0.0", "intl-parse-accept-language": "^1.0.0",
"lucide-vue-next": "^0.428.0", "lucide-vue-next": "^0.469.0",
"mysql-bricks": "^1.1.2", "mysql-bricks": "^1.1.2",
"nanoid": "^5.0.7", "nanoid": "^5.0.9",
"pluralize": "^8.0.0", "pluralize": "^8.0.0",
"qr-code-styling": "1.6.0-rc.1", "qr-code-styling": "1.6.0-rc.1",
"radix-vue": "^1.9.4", "radix-vue": "^1.9.11",
"ua-parser-js": "next", "ua-parser-js": "next",
"vee-validate": "^4.13.2", "vee-validate": "^4.15.0",
"virtua": "^0.33.7", "virtua": "^0.39.2",
"vue-sonner": "^1.1.4", "vue-sonner": "^1.3.0",
"vue3-simple-icons": "^13.2.0", "vue3-simple-icons": "^13.2.0",
"zod": "^3.23.8" "zod": "^3.24.1"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^2.26.0", "@antfu/eslint-config": "^3.12.1",
"@nuxt/eslint": "^0.5.0", "@nuxt/eslint": "^0.7.4",
"@nuxt/eslint-config": "^0.5.0", "@nuxt/eslint-config": "^0.7.4",
"@nuxthub/core": "^0.7.3", "@nuxthub/core": "^0.8.10",
"@nuxtjs/color-mode": "^3.4.4", "@nuxtjs/color-mode": "^3.5.2",
"@nuxtjs/tailwindcss": "^6.12.1", "@nuxtjs/tailwindcss": "^6.12.2",
"@vueuse/integrations": "^12.2.0", "@vueuse/integrations": "^12.2.0",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"eslint": "^9.9.0", "eslint": "^9.17.0",
"lint-staged": "^15.2.9", "lint-staged": "^15.2.11",
"nuxt": "^3.12.4", "nuxt": "^3.14.1592",
"shadcn-nuxt": "^0.10.4", "shadcn-nuxt": "^0.11.3",
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.11.1",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"vue-tsc": "^2.0.29", "vue-tsc": "^2.2.0",
"wrangler": "^3.72.0" "wrangler": "^3.99.0"
}, },
"simple-git-hooks": { "simple-git-hooks": {
"pre-commit": "npm run lint-staged" "pre-commit": "npm run lint-staged"

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
import { z } from 'zod'
import { customAlphabet } from 'nanoid' import { customAlphabet } from 'nanoid'
import { z } from 'zod'
const { slugRegex } = useAppConfig() const { slugRegex } = useAppConfig()
const { caseSensitive } = useRuntimeConfig() const { caseSensitive } = useRuntimeConfig()

View file

@ -1,5 +1,5 @@
import { z } from 'zod'
import { destr } from 'destr' import { destr } from 'destr'
import { z } from 'zod'
export default eventHandler(async (event) => { export default eventHandler(async (event) => {
const url = (await getValidatedQuery(event, z.object({ const url = (await getValidatedQuery(event, z.object({

View file

@ -1,6 +1,6 @@
import type { H3Event } from 'h3' import type { H3Event } from 'h3'
import { z } from 'zod'
import { QuerySchema } from '@/schemas/query' import { QuerySchema } from '@/schemas/query'
import { z } from 'zod'
const { select } = SqlBricks const { select } = SqlBricks

View file

@ -1,6 +1,6 @@
import type { H3Event } from 'h3' import type { H3Event } from 'h3'
import { z } from 'zod'
import { QuerySchema } from '@/schemas/query' import { QuerySchema } from '@/schemas/query'
import { z } from 'zod'
const { select } = SqlBricks const { select } = SqlBricks

View file

@ -1,6 +1,6 @@
import type { LinkSchema } from '@/schemas/link'
import type { z } from 'zod' import type { z } from 'zod'
import { parsePath, withQuery } from 'ufo' import { parsePath, withQuery } from 'ufo'
import type { LinkSchema } from '@/schemas/link'
export default eventHandler(async (event) => { export default eventHandler(async (event) => {
const { pathname: slug } = parsePath(event.path.replace(/^\/|\/$/g, '')) // remove leading and trailing slashes const { pathname: slug } = parsePath(event.path.replace(/^\/|\/$/g, '')) // remove leading and trailing slashes

View file

@ -1,5 +1,6 @@
import type { H3Event } from 'h3' import type { H3Event } from 'h3'
import { parseURL } from 'ufo' import { getFlag } from '@/utils/flag'
import { parseAcceptLanguage } from 'intl-parse-accept-language'
import { UAParser } from 'ua-parser-js' import { UAParser } from 'ua-parser-js'
import { import {
CLIs, CLIs,
@ -11,8 +12,7 @@ import {
MediaPlayers, MediaPlayers,
Modules, Modules,
} from 'ua-parser-js/extensions' } from 'ua-parser-js/extensions'
import { parseAcceptLanguage } from 'intl-parse-accept-language' import { parseURL } from 'ufo'
import { getFlag } from '@/utils/flag'
function toBlobNumber(blob: string) { function toBlobNumber(blob: string) {
return +blob.replace(/\D/g, '') return +blob.replace(/\D/g, '')

View file

@ -1,6 +1,6 @@
import type { z } from 'zod'
import type { SelectStatement } from 'sql-bricks'
import type { FilterSchema, QuerySchema } from '@/schemas/query' import type { FilterSchema, QuerySchema } from '@/schemas/query'
import type { SelectStatement } from 'sql-bricks'
import type { z } from 'zod'
export type Query = z.infer<typeof QuerySchema> export type Query = z.infer<typeof QuerySchema>
export type Filter = z.infer<typeof FilterSchema> export type Filter = z.infer<typeof FilterSchema>

View file

@ -1,3 +1,3 @@
export function colorGradation(count: number) { export function colorGradation(count: number) {
return Array.from(Array(count).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / count) * i})`) return Array.from({ length: count }, (_, i) => `hsl(var(--vis-secondary-color) / ${1 - (1 / count) * i})`)
} }