feat: add pageview

This commit is contained in:
KazooTTT
2024-11-23 21:09:37 +08:00
parent 4afdf7572a
commit ff5a3a50bd
9 changed files with 295 additions and 87 deletions

View File

@ -15,7 +15,20 @@ import cloudflare from '@astrojs/cloudflare'
export default defineConfig({ export default defineConfig({
site: 'https://blog.kazoottt.top', site: 'https://blog.kazoottt.top',
output: 'server', output: 'server',
adapter: cloudflare(), adapter: cloudflare({
mode: 'directory',
runtime: {
mode: process.env.NODE_ENV === 'production' ? 'off' : 'local',
persistTo: process.env.NODE_ENV === 'production' ? undefined : '.wrangler/state/v3/d1',
bindings: {
DB: {
type: 'd1',
databaseName: 'blog-pageviews',
databaseId: 'ab9e5f7d-e254-4e7d-bd85-5d944a622682'
}
}
}
}),
redirects: { redirects: {
'/articles': '/posts', '/articles': '/posts',
'/articles/[...slug]': '/blogs/[...slug]', '/articles/[...slug]': '/blogs/[...slug]',
@ -57,5 +70,5 @@ export default defineConfig({
} }
} }
}, },
prefetch: true, prefetch: true
}) })

5
functions/_routes.json Normal file
View File

@ -0,0 +1,5 @@
{
"version": 1,
"include": ["/*"],
"exclude": []
}

View File

@ -0,0 +1,11 @@
-- Create pageviews table
CREATE TABLE IF NOT EXISTS pageviews (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL,
views INTEGER NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Create unique index on slug
CREATE UNIQUE INDEX IF NOT EXISTS idx_pageviews_slug ON pageviews(slug);

View File

@ -3,11 +3,13 @@
"type": "module", "type": "module",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"dev": "astro check --watch & astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",
"build": "astro check && astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro", "astro": "astro",
"deploy": "wrangler pages deploy ./dist",
"deploy:db": "node -e \"require('dotenv').config()\" && wrangler d1 execute blog-pageviews --file=./migrations/0000_create_pageviews.sql --remote",
"lint": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx,svelte,astro}\" && eslint --fix \"src/**/*.{js,ts,jsx,tsx,svelte,astro}\"", "lint": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx,svelte,astro}\" && eslint --fix \"src/**/*.{js,ts,jsx,tsx,svelte,astro}\"",
"sort": "node scripts/updateCategoryBatchly.cjs" "sort": "node scripts/updateCategoryBatchly.cjs"
}, },
@ -48,6 +50,7 @@
"@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@typescript-eslint/parser": "^7.1.1", "@typescript-eslint/parser": "^7.1.1",
"dotenv": "^16.4.5",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-astro": "^0.31.4", "eslint-plugin-astro": "^0.31.4",
"eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-jsx-a11y": "^6.8.0",
@ -55,6 +58,7 @@
"prettier": "^3.2.5", "prettier": "^3.2.5",
"prettier-config-standard": "^7.0.0", "prettier-config-standard": "^7.0.0",
"prettier-plugin-astro": "^0.13.0", "prettier-plugin-astro": "^0.13.0",
"prettier-plugin-tailwindcss": "^0.5.12" "prettier-plugin-tailwindcss": "^0.5.12",
"wrangler": "^3.90.0"
} }
} }

92
pnpm-lock.yaml generated
View File

@ -94,6 +94,9 @@ devDependencies:
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^7.1.1 specifier: ^7.1.1
version: 7.18.0(eslint@8.57.1)(typescript@5.7.2) version: 7.18.0(eslint@8.57.1)(typescript@5.7.2)
dotenv:
specifier: ^16.4.5
version: 16.4.5
eslint: eslint:
specifier: ^8.57.0 specifier: ^8.57.0
version: 8.57.1 version: 8.57.1
@ -118,6 +121,9 @@ devDependencies:
prettier-plugin-tailwindcss: prettier-plugin-tailwindcss:
specifier: ^0.5.12 specifier: ^0.5.12
version: 0.5.14(prettier-plugin-astro@0.13.0)(prettier@3.3.3) version: 0.5.14(prettier-plugin-astro@0.13.0)(prettier@3.3.3)
wrangler:
specifier: ^3.90.0
version: 3.90.0(@cloudflare/workers-types@4.20241112.0)
packages: packages:
@ -611,7 +617,6 @@ packages:
engines: {node: '>=16.13'} engines: {node: '>=16.13'}
dependencies: dependencies:
mime: 3.0.0 mime: 3.0.0
dev: false
/@cloudflare/workerd-darwin-64@1.20241106.1: /@cloudflare/workerd-darwin-64@1.20241106.1:
resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==} resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==}
@ -619,7 +624,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@cloudflare/workerd-darwin-arm64@1.20241106.1: /@cloudflare/workerd-darwin-arm64@1.20241106.1:
@ -628,7 +632,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@cloudflare/workerd-linux-64@1.20241106.1: /@cloudflare/workerd-linux-64@1.20241106.1:
@ -637,7 +640,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@cloudflare/workerd-linux-arm64@1.20241106.1: /@cloudflare/workerd-linux-arm64@1.20241106.1:
@ -646,7 +648,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@cloudflare/workerd-windows-64@1.20241106.1: /@cloudflare/workerd-windows-64@1.20241106.1:
@ -655,7 +656,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@cloudflare/workers-shared@0.8.0: /@cloudflare/workers-shared@0.8.0:
@ -664,18 +664,15 @@ packages:
dependencies: dependencies:
mime: 3.0.0 mime: 3.0.0
zod: 3.23.8 zod: 3.23.8
dev: false
/@cloudflare/workers-types@4.20241112.0: /@cloudflare/workers-types@4.20241112.0:
resolution: {integrity: sha512-Q4p9bAWZrX14bSCKY9to19xl0KMU7nsO5sJ2cTVspHoypsjPUMeQCsjHjmsO2C4Myo8/LPeDvmqFmkyNAPPYZw==} resolution: {integrity: sha512-Q4p9bAWZrX14bSCKY9to19xl0KMU7nsO5sJ2cTVspHoypsjPUMeQCsjHjmsO2C4Myo8/LPeDvmqFmkyNAPPYZw==}
dev: false
/@cspotcode/source-map-support@0.8.1: /@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dependencies: dependencies:
'@jridgewell/trace-mapping': 0.3.9 '@jridgewell/trace-mapping': 0.3.9
dev: false
/@ctrl/tinycolor@3.6.1: /@ctrl/tinycolor@3.6.1:
resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
@ -733,7 +730,6 @@ packages:
esbuild: '*' esbuild: '*'
dependencies: dependencies:
esbuild: 0.17.19 esbuild: 0.17.19
dev: false
/@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19): /@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19):
resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==}
@ -743,7 +739,6 @@ packages:
esbuild: 0.17.19 esbuild: 0.17.19
escape-string-regexp: 4.0.0 escape-string-regexp: 4.0.0
rollup-plugin-node-polyfills: 0.2.1 rollup-plugin-node-polyfills: 0.2.1
dev: false
/@esbuild/aix-ppc64@0.21.5: /@esbuild/aix-ppc64@0.21.5:
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
@ -760,7 +755,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/android-arm64@0.21.5: /@esbuild/android-arm64@0.21.5:
@ -778,7 +772,6 @@ packages:
cpu: [arm] cpu: [arm]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/android-arm@0.21.5: /@esbuild/android-arm@0.21.5:
@ -796,7 +789,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/android-x64@0.21.5: /@esbuild/android-x64@0.21.5:
@ -814,7 +806,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/darwin-arm64@0.21.5: /@esbuild/darwin-arm64@0.21.5:
@ -832,7 +823,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/darwin-x64@0.21.5: /@esbuild/darwin-x64@0.21.5:
@ -850,7 +840,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [freebsd] os: [freebsd]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/freebsd-arm64@0.21.5: /@esbuild/freebsd-arm64@0.21.5:
@ -868,7 +857,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/freebsd-x64@0.21.5: /@esbuild/freebsd-x64@0.21.5:
@ -886,7 +874,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-arm64@0.21.5: /@esbuild/linux-arm64@0.21.5:
@ -904,7 +891,6 @@ packages:
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-arm@0.21.5: /@esbuild/linux-arm@0.21.5:
@ -922,7 +908,6 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-ia32@0.21.5: /@esbuild/linux-ia32@0.21.5:
@ -940,7 +925,6 @@ packages:
cpu: [loong64] cpu: [loong64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-loong64@0.21.5: /@esbuild/linux-loong64@0.21.5:
@ -958,7 +942,6 @@ packages:
cpu: [mips64el] cpu: [mips64el]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-mips64el@0.21.5: /@esbuild/linux-mips64el@0.21.5:
@ -976,7 +959,6 @@ packages:
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-ppc64@0.21.5: /@esbuild/linux-ppc64@0.21.5:
@ -994,7 +976,6 @@ packages:
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-riscv64@0.21.5: /@esbuild/linux-riscv64@0.21.5:
@ -1012,7 +993,6 @@ packages:
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-s390x@0.21.5: /@esbuild/linux-s390x@0.21.5:
@ -1030,7 +1010,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/linux-x64@0.21.5: /@esbuild/linux-x64@0.21.5:
@ -1048,7 +1027,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [netbsd] os: [netbsd]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/netbsd-x64@0.21.5: /@esbuild/netbsd-x64@0.21.5:
@ -1066,7 +1044,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [openbsd] os: [openbsd]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/openbsd-x64@0.21.5: /@esbuild/openbsd-x64@0.21.5:
@ -1084,7 +1061,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [sunos] os: [sunos]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/sunos-x64@0.21.5: /@esbuild/sunos-x64@0.21.5:
@ -1102,7 +1078,6 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/win32-arm64@0.21.5: /@esbuild/win32-arm64@0.21.5:
@ -1120,7 +1095,6 @@ packages:
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/win32-ia32@0.21.5: /@esbuild/win32-ia32@0.21.5:
@ -1138,7 +1112,6 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: false
optional: true optional: true
/@esbuild/win32-x64@0.21.5: /@esbuild/win32-x64@0.21.5:
@ -1222,7 +1195,6 @@ packages:
/@fastify/busboy@2.1.1: /@fastify/busboy@2.1.1:
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'} engines: {node: '>=14'}
dev: false
/@giscus/react@3.0.0(react-dom@18.3.1)(react@18.3.1): /@giscus/react@3.0.0(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-hgCjLpg3Wgh8VbTF5p8ZLcIHI74wvDk1VIFv12+eKhenNVUDjgwNg2B1aq/3puyHOad47u/ZSyqiMtohjy/OOA==} resolution: {integrity: sha512-hgCjLpg3Wgh8VbTF5p8ZLcIHI74wvDk1VIFv12+eKhenNVUDjgwNg2B1aq/3puyHOad47u/ZSyqiMtohjy/OOA==}
@ -1539,7 +1511,6 @@ packages:
dependencies: dependencies:
'@jridgewell/resolve-uri': 3.1.2 '@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/sourcemap-codec': 1.5.0
dev: false
/@lit-labs/ssr-dom-shim@1.2.1: /@lit-labs/ssr-dom-shim@1.2.1:
resolution: {integrity: sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==} resolution: {integrity: sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==}
@ -1942,7 +1913,6 @@ packages:
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
dependencies: dependencies:
'@types/node': 22.9.3 '@types/node': 22.9.3
dev: false
/@types/node@17.0.45: /@types/node@17.0.45:
resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
@ -1952,7 +1922,6 @@ packages:
resolution: {integrity: sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==} resolution: {integrity: sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==}
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
dev: false
/@types/parse5@6.0.3: /@types/parse5@6.0.3:
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
@ -2192,7 +2161,6 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
dependencies: dependencies:
acorn: 8.14.0 acorn: 8.14.0
dev: false
/acorn@8.14.0: /acorn@8.14.0:
resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
@ -2334,7 +2302,6 @@ packages:
resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
dependencies: dependencies:
printable-characters: 1.0.42 printable-characters: 1.0.42
dev: false
/ast-types-flow@0.0.8: /ast-types-flow@0.0.8:
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
@ -2556,7 +2523,6 @@ packages:
/blake3-wasm@2.1.5: /blake3-wasm@2.1.5:
resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==}
dev: false
/boolbase@1.0.0: /boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@ -2645,7 +2611,6 @@ packages:
tslib: 2.8.1 tslib: 2.8.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false
/ccount@2.0.1: /ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@ -2727,7 +2692,6 @@ packages:
engines: {node: '>= 14.16.0'} engines: {node: '>= 14.16.0'}
dependencies: dependencies:
readdirp: 4.0.2 readdirp: 4.0.2
dev: false
/chownr@2.0.0: /chownr@2.0.0:
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
@ -2837,7 +2801,6 @@ packages:
/cookie@0.7.2: /cookie@0.7.2:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
dev: false
/cross-spawn@7.0.6: /cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
@ -2900,7 +2863,6 @@ packages:
/data-uri-to-buffer@2.0.2: /data-uri-to-buffer@2.0.2:
resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
dev: false
/data-view-buffer@1.0.1: /data-view-buffer@1.0.1:
resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==}
@ -2931,7 +2893,6 @@ packages:
/date-fns@4.1.0: /date-fns@4.1.0:
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
dev: false
/debug@4.3.7: /debug@4.3.7:
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
@ -2974,7 +2935,6 @@ packages:
/defu@6.1.4: /defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
dev: false
/delayed-stream@1.0.0: /delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
@ -3060,6 +3020,11 @@ packages:
domhandler: 5.0.3 domhandler: 5.0.3
dev: false dev: false
/dotenv@16.4.5:
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
engines: {node: '>=12'}
dev: true
/dset@3.1.4: /dset@3.1.4:
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -3255,7 +3220,6 @@ packages:
'@esbuild/win32-arm64': 0.17.19 '@esbuild/win32-arm64': 0.17.19
'@esbuild/win32-ia32': 0.17.19 '@esbuild/win32-ia32': 0.17.19
'@esbuild/win32-x64': 0.17.19 '@esbuild/win32-x64': 0.17.19
dev: false
/esbuild@0.21.5: /esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
@ -3492,7 +3456,6 @@ packages:
/estree-walker@0.6.1: /estree-walker@0.6.1:
resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
dev: false
/estree-walker@2.0.2: /estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@ -3516,7 +3479,6 @@ packages:
/exit-hook@2.2.1: /exit-hook@2.2.1:
resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==}
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false
/expressive-code@0.33.5: /expressive-code@0.33.5:
resolution: {integrity: sha512-UPg2jSvZEfXPiCa4MKtMoMQ5Hwiv7In5/LSCa/ukhjzZqPO48iVsCcEBgXWEUmEAQ02P0z00/xFfBmVnUKH+Zw==} resolution: {integrity: sha512-UPg2jSvZEfXPiCa4MKtMoMQ5Hwiv7In5/LSCa/ukhjzZqPO48iVsCcEBgXWEUmEAQ02P0z00/xFfBmVnUKH+Zw==}
@ -3756,7 +3718,6 @@ packages:
dependencies: dependencies:
data-uri-to-buffer: 2.0.2 data-uri-to-buffer: 2.0.2
source-map: 0.6.1 source-map: 0.6.1
dev: false
/get-stream@5.2.0: /get-stream@5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
@ -3798,7 +3759,6 @@ packages:
/glob-to-regexp@0.4.1: /glob-to-regexp@0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
dev: false
/glob@10.4.5: /glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
@ -4502,7 +4462,6 @@ packages:
/itty-time@1.0.6: /itty-time@1.0.6:
resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==} resolution: {integrity: sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==}
dev: false
/jackspeak@3.4.3: /jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
@ -4736,7 +4695,6 @@ packages:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
dependencies: dependencies:
sourcemap-codec: 1.4.8 sourcemap-codec: 1.4.8
dev: false
/magic-string@0.30.13: /magic-string@0.30.13:
resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==}
@ -5335,7 +5293,6 @@ packages:
resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
hasBin: true hasBin: true
dev: false
/mimic-function@5.0.1: /mimic-function@5.0.1:
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
@ -5363,7 +5320,6 @@ packages:
- bufferutil - bufferutil
- supports-color - supports-color
- utf-8-validate - utf-8-validate
dev: false
/minimatch@3.1.2: /minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@ -5436,7 +5392,6 @@ packages:
/mustache@4.2.0: /mustache@4.2.0:
resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==}
hasBin: true hasBin: true
dev: false
/mz@2.7.0: /mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@ -5474,7 +5429,6 @@ packages:
/node-forge@1.3.1: /node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'} engines: {node: '>= 6.13.0'}
dev: false
/node-releases@2.0.18: /node-releases@2.0.18:
resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
@ -5544,7 +5498,6 @@ packages:
/ohash@1.1.4: /ohash@1.1.4:
resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==}
dev: false
/once@1.4.0: /once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@ -5744,7 +5697,6 @@ packages:
/path-to-regexp@6.3.0: /path-to-regexp@6.3.0:
resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
dev: false
/path-type@4.0.0: /path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
@ -5753,7 +5705,6 @@ packages:
/pathe@1.1.2: /pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
dev: false
/pend@1.2.0: /pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@ -5976,7 +5927,6 @@ packages:
/printable-characters@1.0.42: /printable-characters@1.0.42:
resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
dev: false
/prismjs@1.29.0: /prismjs@1.29.0:
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
@ -6082,7 +6032,6 @@ packages:
/readdirp@4.0.2: /readdirp@4.0.2:
resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
engines: {node: '>= 14.16.0'} engines: {node: '>= 14.16.0'}
dev: false
/reading-time@1.5.0: /reading-time@1.5.0:
resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==}
@ -6346,7 +6295,6 @@ packages:
/resolve.exports@2.0.2: /resolve.exports@2.0.2:
resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
engines: {node: '>=10'} engines: {node: '>=10'}
dev: false
/resolve@1.22.8: /resolve@1.22.8:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
@ -6451,19 +6399,16 @@ packages:
estree-walker: 0.6.1 estree-walker: 0.6.1
magic-string: 0.25.9 magic-string: 0.25.9
rollup-pluginutils: 2.8.2 rollup-pluginutils: 2.8.2
dev: false
/rollup-plugin-node-polyfills@0.2.1: /rollup-plugin-node-polyfills@0.2.1:
resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==}
dependencies: dependencies:
rollup-plugin-inject: 3.0.2 rollup-plugin-inject: 3.0.2
dev: false
/rollup-pluginutils@2.8.2: /rollup-pluginutils@2.8.2:
resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==}
dependencies: dependencies:
estree-walker: 0.6.1 estree-walker: 0.6.1
dev: false
/rollup@4.27.4: /rollup@4.27.4:
resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==} resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==}
@ -6553,7 +6498,6 @@ packages:
dependencies: dependencies:
'@types/node-forge': 1.3.11 '@types/node-forge': 1.3.11
node-forge: 1.3.1 node-forge: 1.3.1
dev: false
/semver@6.3.1: /semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
@ -6685,7 +6629,6 @@ packages:
/source-map@0.6.1: /source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: false
/source-map@0.7.4: /source-map@0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
@ -6695,7 +6638,6 @@ packages:
/sourcemap-codec@1.4.8: /sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
deprecated: Please use @jridgewell/sourcemap-codec instead deprecated: Please use @jridgewell/sourcemap-codec instead
dev: false
/space-separated-tokens@2.0.2: /space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@ -6710,7 +6652,6 @@ packages:
dependencies: dependencies:
as-table: 1.0.55 as-table: 1.0.55
get-source: 2.0.12 get-source: 2.0.12
dev: false
/stdin-discarder@0.2.2: /stdin-discarder@0.2.2:
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
@ -6720,7 +6661,6 @@ packages:
/stoppable@1.1.0: /stoppable@1.1.0:
resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==}
engines: {node: '>=4', npm: '>=6'} engines: {node: '>=4', npm: '>=6'}
dev: false
/stream-replace-string@2.0.0: /stream-replace-string@2.0.0:
resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==}
@ -7085,7 +7025,6 @@ packages:
/ufo@1.5.4: /ufo@1.5.4:
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
dev: false
/ultrahtml@1.5.3: /ultrahtml@1.5.3:
resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==}
@ -7102,14 +7041,12 @@ packages:
/undici-types@6.19.8: /undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
dev: false
/undici@5.28.4: /undici@5.28.4:
resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
engines: {node: '>=14.0'} engines: {node: '>=14.0'}
dependencies: dependencies:
'@fastify/busboy': 2.1.1 '@fastify/busboy': 2.1.1
dev: false
/undici@6.21.0: /undici@6.21.0:
resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==} resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==}
@ -7123,7 +7060,6 @@ packages:
ohash: 1.1.4 ohash: 1.1.4
pathe: 1.1.2 pathe: 1.1.2
ufo: 1.5.4 ufo: 1.5.4
dev: false
/unherit@3.0.1: /unherit@3.0.1:
resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==}
@ -7673,7 +7609,6 @@ packages:
'@cloudflare/workerd-linux-64': 1.20241106.1 '@cloudflare/workerd-linux-64': 1.20241106.1
'@cloudflare/workerd-linux-arm64': 1.20241106.1 '@cloudflare/workerd-linux-arm64': 1.20241106.1
'@cloudflare/workerd-windows-64': 1.20241106.1 '@cloudflare/workerd-windows-64': 1.20241106.1
dev: false
/wrangler@3.90.0(@cloudflare/workers-types@4.20241112.0): /wrangler@3.90.0(@cloudflare/workers-types@4.20241112.0):
resolution: {integrity: sha512-E/6E9ORAl987+3kP8wDiE3L1lj9r4vQ32/dl5toIxIkSMssmPRQVdxqwgMxbxJrytbFNo8Eo6swgjd4y4nUaLg==} resolution: {integrity: sha512-E/6E9ORAl987+3kP8wDiE3L1lj9r4vQ32/dl5toIxIkSMssmPRQVdxqwgMxbxJrytbFNo8Eo6swgjd4y4nUaLg==}
@ -7711,7 +7646,6 @@ packages:
- bufferutil - bufferutil
- supports-color - supports-color
- utf-8-validate - utf-8-validate
dev: false
/wrap-ansi@7.0.0: /wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
@ -7752,11 +7686,9 @@ packages:
optional: true optional: true
utf-8-validate: utf-8-validate:
optional: true optional: true
dev: false
/xxhash-wasm@1.1.0: /xxhash-wasm@1.1.0:
resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
dev: false
/y18n@5.0.8: /y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
@ -7840,7 +7772,6 @@ packages:
cookie: 0.7.2 cookie: 0.7.2
mustache: 4.2.0 mustache: 4.2.0
stacktracey: 2.1.8 stacktracey: 2.1.8
dev: false
/zod-to-json-schema@3.23.5(zod@3.23.8): /zod-to-json-schema@3.23.5(zod@3.23.8):
resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==}
@ -7862,7 +7793,6 @@ packages:
/zod@3.23.8: /zod@3.23.8:
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
dev: false
/zwitch@2.0.4: /zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}

View File

@ -0,0 +1,79 @@
import { useEffect, useState } from 'react';
interface PageViewsProps {
slug: string;
}
export default function PageViews({ slug }: PageViewsProps) {
const [views, setViews] = useState<number | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
// Get initial views
const getResponse = await fetch(`/api/pageview/${slug}`);
if (!getResponse.ok) {
const errorData = await getResponse.json();
console.error('Error getting views:', errorData);
setError('Failed to get views');
return;
}
const getData = await getResponse.json();
setViews(getData.views);
// Increment views
const postResponse = await fetch(`/api/pageview/${slug}`, {
method: 'POST',
});
if (!postResponse.ok) {
const errorData = await postResponse.json();
console.error('Error incrementing views:', errorData);
return;
}
const postData = await postResponse.json();
setViews(postData.views);
} catch (error) {
console.error('Error with page views:', error);
setError('Failed to load views');
}
};
fetchData();
}, [slug]);
if (error) {
console.error('Page views error:', error);
return null;
}
if (views === null) {
return null;
}
return (
<div className="flex items-center gap-1 text-sm text-gray-500">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
/>
</svg>
<span>{views} views</span>
</div>
);
}

View File

@ -5,6 +5,7 @@ import BlogHero from '@/components/blog/Hero.astro'
import TOC from '@/components/blog/TOC.astro' import TOC from '@/components/blog/TOC.astro'
import Button from '@/components/Button.astro' import Button from '@/components/Button.astro'
import PageLayout from './BaseLayout.astro' import PageLayout from './BaseLayout.astro'
import PageViews from '@/components/PageViews'
interface Props { interface Props {
post: CollectionEntry<'post'> post: CollectionEntry<'post'>
@ -41,7 +42,12 @@ const { headings } = await post.render()
<div class='mt-8 gap-x-10 lg:flex lg:items-start'> <div class='mt-8 gap-x-10 lg:flex lg:items-start'>
{!!headings.length && <TOC headings={headings} />} {!!headings.length && <TOC headings={headings} />}
<article class='flex-1 flex-grow break-words' data-pagefind-body> <article class='flex-1 flex-grow break-words' data-pagefind-body>
<div id='blog-hero'><BlogHero content={post} /></div> <div id='blog-hero'>
<BlogHero content={post} />
<div class="mt-2">
<PageViews client:load slug={slug} />
</div>
</div>
<div <div
id='blog-gallery' id='blog-gallery'
class='prose prose-base prose-zinc mt-12 text-muted-foreground dark:prose-invert prose-headings:font-medium prose-headings:text-foreground prose-headings:before:absolute prose-headings:before:-ms-4 prose-th:before:content-none' class='prose prose-base prose-zinc mt-12 text-muted-foreground dark:prose-invert prose-headings:font-medium prose-headings:text-foreground prose-headings:before:absolute prose-headings:before:-ms-4 prose-th:before:content-none'

View File

@ -0,0 +1,147 @@
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, locals, request }) => {
const slug = params.slug;
if (!slug) {
return new Response(JSON.stringify({ error: 'Slug is required' }), {
status: 400,
headers: { 'Content-Type': 'application/json' },
});
}
// Access runtime environment through context
const ctx = locals as any;
const env = ctx.env || ctx.runtime?.env;
console.log('Context:', {
hasEnv: !!ctx.env,
hasRuntime: !!ctx.runtime,
envKeys: ctx.env ? Object.keys(ctx.env) : [],
runtimeEnvKeys: ctx.runtime?.env ? Object.keys(ctx.runtime.env) : []
});
const db = env?.DB;
if (!db) {
console.error('D1 database not available');
return new Response(
JSON.stringify({
error: 'Database not configured',
context: {
hasEnv: !!ctx.env,
hasRuntime: !!ctx.runtime,
envKeys: ctx.env ? Object.keys(ctx.env) : [],
runtimeEnvKeys: ctx.runtime?.env ? Object.keys(ctx.runtime.env) : []
}
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
try {
// Get current view count
const { results } = await db
.prepare('SELECT views FROM pageviews WHERE slug = ?')
.bind(slug)
.all();
const views = results.length > 0 ? results[0].views : 0;
return new Response(JSON.stringify({ views }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
console.error('Error getting page views:', error);
return new Response(
JSON.stringify({
error: 'Failed to get page views',
details: error instanceof Error ? error.message : String(error)
}), {
status: 500,
headers: {
'Content-Type': 'application/json',
},
});
}
};
export const POST: APIRoute = async ({ params, locals, request }) => {
const slug = params.slug;
if (!slug) {
return new Response(JSON.stringify({ error: 'Slug is required' }), {
status: 400,
headers: { 'Content-Type': 'application/json' },
});
}
// Access runtime environment through context
const ctx = locals as any;
const env = ctx.env || ctx.runtime?.env;
console.log('Context:', {
hasEnv: !!ctx.env,
hasRuntime: !!ctx.runtime,
envKeys: ctx.env ? Object.keys(ctx.env) : [],
runtimeEnvKeys: ctx.runtime?.env ? Object.keys(ctx.runtime.env) : []
});
const db = env?.DB;
if (!db) {
console.error('D1 database not available');
return new Response(
JSON.stringify({
error: 'Database not configured',
context: {
hasEnv: !!ctx.env,
hasRuntime: !!ctx.runtime,
envKeys: ctx.env ? Object.keys(ctx.env) : [],
runtimeEnvKeys: ctx.runtime?.env ? Object.keys(ctx.runtime.env) : []
}
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
try {
// Insert or update view count
await db
.prepare(
`INSERT INTO pageviews (slug, views)
VALUES (?, 1)
ON CONFLICT(slug)
DO UPDATE SET views = views + 1,
updated_at = CURRENT_TIMESTAMP`
)
.bind(slug)
.run();
// Get updated view count
const { results } = await db
.prepare('SELECT views FROM pageviews WHERE slug = ?')
.bind(slug)
.all();
return new Response(JSON.stringify({ views: results[0].views }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
console.error('Error updating page views:', error);
return new Response(
JSON.stringify({
error: 'Failed to update page views',
details: error instanceof Error ? error.message : String(error)
}), {
status: 500,
headers: {
'Content-Type': 'application/json',
},
});
}
};

13
wrangler.toml Normal file
View File

@ -0,0 +1,13 @@
name = "kazoottt-blog"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "blog-pageviews"
database_id = "ab9e5f7d-e254-4e7d-bd85-5d944a622682"
[build]
command = "pnpm build"
[build.upload]
format = "directory"