From 3b197febc1bbdbad7d9a78eb6d61183dd6b3e3fd Mon Sep 17 00:00:00 2001 From: Eric Jinks <3147296+Jinksi@users.noreply.github.com> Date: Sat, 16 Aug 2025 22:51:59 +1000 Subject: [PATCH 1/3] Add Astro DB integration with counter functionality - Add @astrojs/db integration to astro.config.mjs - Create Counter table with id, name, and count columns - Add database seeding with initial adminCounter - Implement Astro Actions for getting and incrementing counters - Update admin dashboard with interactive counter button - Add --remote flag to dev and build scripts for database connectivity - Fix typo in counter name reference (adminCouter -> adminCounter) --- astro.config.mjs | 14 +- db/config.ts | 13 ++ db/seed.ts | 8 + package-lock.json | 432 +++++++++++++++++++++++++++++++++++- package.json | 4 +- src/actions/index.ts | 50 +++++ src/pages/admin/index.astro | 53 ++++- 7 files changed, 557 insertions(+), 17 deletions(-) create mode 100644 db/config.ts create mode 100644 db/seed.ts create mode 100644 src/actions/index.ts diff --git a/astro.config.mjs b/astro.config.mjs index 3f856d7..4a4c35f 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,6 +1,7 @@ import pagefind from 'astro-pagefind' import { defineConfig, envField } from 'astro/config' +import db from '@astrojs/db' import mdx from '@astrojs/mdx' import netlify from '@astrojs/netlify' import react from '@astrojs/react' @@ -24,6 +25,7 @@ export default defineConfig({ applyBaseStyles: false, }), pagefind(), + db(), ], trailingSlash: 'always', markdown: { @@ -49,17 +51,17 @@ export default defineConfig({ schema: { ADMIN_USERNAME: envField.string({ context: 'server', - access: 'secret' + access: 'secret', }), ADMIN_PASSWORD: envField.string({ context: 'server', - access: 'secret' + access: 'secret', }), ADMIN_SECRET: envField.string({ context: 'server', - access: 'secret' - }) + access: 'secret', + }), }, - validateSecrets: true - } + validateSecrets: true, + }, }) diff --git a/db/config.ts b/db/config.ts new file mode 100644 index 0000000..f96063d --- /dev/null +++ b/db/config.ts @@ -0,0 +1,13 @@ +import { column, defineDb, defineTable } from 'astro:db' + +const Counter = defineTable({ + columns: { + id: column.text({ primaryKey: true }), + name: column.text({ unique: true }), + count: column.number({ default: 0 }), + }, +}) + +export default defineDb({ + tables: { Counter }, +}) diff --git a/db/seed.ts b/db/seed.ts new file mode 100644 index 0000000..2e8850e --- /dev/null +++ b/db/seed.ts @@ -0,0 +1,8 @@ +import { Counter, db } from 'astro:db' + +// https://astro.build/db/seed +export default async function seed() { + await db + .insert(Counter) + .values([{ id: crypto.randomUUID(), name: 'adminCounter', count: 0 }]) +} diff --git a/package-lock.json b/package-lock.json index dfc38ad..04326a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "@astrojs/check": "^0.9.4", + "@astrojs/db": "^0.17.1", "@astrojs/mdx": "^4.3.1", "@astrojs/netlify": "^6.5.2", "@astrojs/react": "^4.3.0", @@ -101,6 +102,161 @@ "integrity": "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==", "license": "MIT" }, + "node_modules/@astrojs/db": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@astrojs/db/-/db-0.17.1.tgz", + "integrity": "sha512-QL09xZf5Om8AshIlt+YhLDYf6M1QSzv+kfuljsPrhEXJ8U/tuKnbWs2M3wimFaLG3/fU0prFix8lWt7zU8ytfA==", + "license": "MIT", + "dependencies": { + "@libsql/client": "^0.15.2", + "deep-diff": "^1.0.2", + "drizzle-orm": "^0.42.0", + "kleur": "^4.1.5", + "nanoid": "^5.1.5", + "prompts": "^2.4.2", + "yargs-parser": "^21.1.1", + "zod": "^3.24.4" + } + }, + "node_modules/@astrojs/db/node_modules/drizzle-orm": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.42.0.tgz", + "integrity": "sha512-pS8nNJm2kBNZwrOjTHJfdKkaU+KuUQmV/vk5D57NojDq4FG+0uAYGMulXtYT///HfgsMF0hnFFvu1ezI3OwOkg==", + "license": "Apache-2.0", + "peerDependencies": { + "@aws-sdk/client-rds-data": ">=3", + "@cloudflare/workers-types": ">=4", + "@electric-sql/pglite": ">=0.2.0", + "@libsql/client": ">=0.10.0", + "@libsql/client-wasm": ">=0.10.0", + "@neondatabase/serverless": ">=0.10.0", + "@op-engineering/op-sqlite": ">=2", + "@opentelemetry/api": "^1.4.1", + "@planetscale/database": ">=1.13", + "@prisma/client": "*", + "@tidbcloud/serverless": "*", + "@types/better-sqlite3": "*", + "@types/pg": "*", + "@types/sql.js": "*", + "@vercel/postgres": ">=0.8.0", + "@xata.io/client": "*", + "better-sqlite3": ">=7", + "bun-types": "*", + "expo-sqlite": ">=14.0.0", + "gel": ">=2", + "knex": "*", + "kysely": "*", + "mysql2": ">=2", + "pg": ">=8", + "postgres": ">=3", + "sql.js": ">=1", + "sqlite3": ">=5" + }, + "peerDependenciesMeta": { + "@aws-sdk/client-rds-data": { + "optional": true + }, + "@cloudflare/workers-types": { + "optional": true + }, + "@electric-sql/pglite": { + "optional": true + }, + "@libsql/client": { + "optional": true + }, + "@libsql/client-wasm": { + "optional": true + }, + "@neondatabase/serverless": { + "optional": true + }, + "@op-engineering/op-sqlite": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@prisma/client": { + "optional": true + }, + "@tidbcloud/serverless": { + "optional": true + }, + "@types/better-sqlite3": { + "optional": true + }, + "@types/pg": { + "optional": true + }, + "@types/sql.js": { + "optional": true + }, + "@vercel/postgres": { + "optional": true + }, + "@xata.io/client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "bun-types": { + "optional": true + }, + "expo-sqlite": { + "optional": true + }, + "gel": { + "optional": true + }, + "knex": { + "optional": true + }, + "kysely": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "postgres": { + "optional": true + }, + "prisma": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + } + } + }, + "node_modules/@astrojs/db/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/@astrojs/internal-helpers": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.6.1.tgz", @@ -1804,6 +1960,212 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@libsql/client": { + "version": "0.15.11", + "resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.15.11.tgz", + "integrity": "sha512-JB8RWRs+cAbHX35/dQ9wD3m4W5EVGevq1fFqiHKTT4Pa5HR7WrcGRVT+8NL2M7gtTlOvyPh9zzms2DPLBCswig==", + "license": "MIT", + "dependencies": { + "@libsql/core": "^0.15.11", + "@libsql/hrana-client": "^0.7.0", + "js-base64": "^3.7.5", + "libsql": "^0.5.15", + "promise-limit": "^2.7.0" + } + }, + "node_modules/@libsql/client/node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" + }, + "node_modules/@libsql/core": { + "version": "0.15.11", + "resolved": "https://registry.npmjs.org/@libsql/core/-/core-0.15.11.tgz", + "integrity": "sha512-DQDYnEhCSYOsx30ASlOGuOqcQhvwELhOS2qM4dnIP+ZhKki2epZU1j5VZSNeQlrQXHkByMcWBy+wt7tBNx/9uA==", + "license": "MIT", + "dependencies": { + "js-base64": "^3.7.5" + } + }, + "node_modules/@libsql/core/node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" + }, + "node_modules/@libsql/darwin-arm64": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.5.17.tgz", + "integrity": "sha512-WTYG2skZsUnZmfZ2v7WFj7s3/5s2PfrYBZOWBKOnxHA8g4XCDc/4bFDaqob9Q2e88+GC7cWeJ8VNkVBFpD2Xxg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@libsql/darwin-x64": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.5.17.tgz", + "integrity": "sha512-ab0RlTR4KYrxgjNrZhAhY/10GibKoq6G0W4oi0kdm+eYiAv/Ip8GDMpSaZdAcoKA4T+iKR/ehczKHnMEB8MFxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@libsql/hrana-client": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.7.0.tgz", + "integrity": "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==", + "license": "MIT", + "dependencies": { + "@libsql/isomorphic-fetch": "^0.3.1", + "@libsql/isomorphic-ws": "^0.1.5", + "js-base64": "^3.7.5", + "node-fetch": "^3.3.2" + } + }, + "node_modules/@libsql/hrana-client/node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" + }, + "node_modules/@libsql/hrana-client/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/@libsql/isomorphic-fetch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.3.1.tgz", + "integrity": "sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@libsql/isomorphic-ws": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz", + "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", + "license": "MIT", + "dependencies": { + "@types/ws": "^8.5.4", + "ws": "^8.13.0" + } + }, + "node_modules/@libsql/linux-arm-gnueabihf": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm-gnueabihf/-/linux-arm-gnueabihf-0.5.17.tgz", + "integrity": "sha512-PcASh4k47RqC+kMWAbLUKf1y6Do0q8vnUGi0yhKY4ghJcimMExViBimjbjYRSa+WIb/zh3QxNoXOhQAXx3tiuw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-arm-musleabihf": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm-musleabihf/-/linux-arm-musleabihf-0.5.17.tgz", + "integrity": "sha512-vxOkSLG9Wspit+SNle84nuIzMtr2G2qaxFzW7BhsZBjlZ8+kErf9RXcT2YJQdJYxmBYRbsOrc91gg0jLEQVCqg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-arm64-gnu": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.5.17.tgz", + "integrity": "sha512-L8jnaN01TxjBJlDuDTX2W2BKzBkAOhcnKfCOf3xzvvygblxnDOK0whkYwIXeTfwtd/rr4jN/d6dZD/bcHiDxEQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-arm64-musl": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.5.17.tgz", + "integrity": "sha512-HfFD7TzQtmmTwyQsuiHhWZdMRtdNpKJ1p4tbMMTMRECk+971NFHrj69D64cc2ClVTAmn7fA9XibKPil7WN/Q7w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-x64-gnu": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.5.17.tgz", + "integrity": "sha512-5l3XxWqUPVFrtX0xnZaXwqsXs0BFbP4w6ahRFTPSdXU50YBfUOajFznJRB6bJTMsCvraDSD0IkHhjSNfrE1CuQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/linux-x64-musl": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.5.17.tgz", + "integrity": "sha512-FvSpWlwc+dIeYIFYlsSv+UdQ/NiZWr+SstwVji+QZ//8NnvzwWQU9cgP+Vpps6Qiq4jyYQm9chJhTYOVT9Y3BA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@libsql/win32-x64-msvc": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.5.17.tgz", + "integrity": "sha512-f5bGH8+3A5sn6Lrqg8FsQ09a1pYXPnKGXGTFiAYlfQXVst1tUTxDTugnuWcJYKXyzDe/T7ccxyIZXeSmPOhq8A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@lit-labs/ssr-dom-shim": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz", @@ -1940,6 +2302,12 @@ "tslib": "^2.3.1" } }, + "node_modules/@neon-rs/load": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz", + "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==", + "license": "MIT" + }, "node_modules/@netlify/api": { "version": "14.0.3", "resolved": "https://registry.npmjs.org/@netlify/api/-/api-14.0.3.tgz", @@ -3656,6 +4024,15 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -6144,6 +6521,12 @@ "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==", "license": "MIT" }, + "node_modules/deep-diff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", + "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==", + "license": "MIT" + }, "node_modules/deep-equal": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", @@ -9979,6 +10362,47 @@ "node": ">=6" } }, + "node_modules/libsql": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/libsql/-/libsql-0.5.17.tgz", + "integrity": "sha512-RRlj5XQI9+Wq+/5UY8EnugSWfRmHEw4hn3DKlPrkUgZONsge1PwTtHcpStP6MSNi8ohcbsRgEHJaymA33a8cBw==", + "cpu": [ + "x64", + "arm64", + "wasm32", + "arm" + ], + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32" + ], + "dependencies": { + "@neon-rs/load": "^0.0.4", + "detect-libc": "2.0.2" + }, + "optionalDependencies": { + "@libsql/darwin-arm64": "0.5.17", + "@libsql/darwin-x64": "0.5.17", + "@libsql/linux-arm-gnueabihf": "0.5.17", + "@libsql/linux-arm-musleabihf": "0.5.17", + "@libsql/linux-arm64-gnu": "0.5.17", + "@libsql/linux-arm64-musl": "0.5.17", + "@libsql/linux-x64-gnu": "0.5.17", + "@libsql/linux-x64-musl": "0.5.17", + "@libsql/win32-x64-msvc": "0.5.17" + } + }, + "node_modules/libsql/node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/lilconfig": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", @@ -12941,6 +13365,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/promise-limit": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz", + "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==", + "license": "ISC" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -16470,8 +16900,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 5edaa1b..46f37d8 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "private": true, "scripts": { "dev": "astro dev", + "dev:remote": "astro dev --remote", "start": "astro dev", - "build": "npm run fetch-stars && astro build && npm run build:pagefind", + "build": "npm run fetch-stars && astro build --remote && npm run build:pagefind", "build:pagefind": "node scripts/index-github-stars.js", "preview": "astro preview", "astro": "astro", @@ -15,6 +16,7 @@ }, "dependencies": { "@astrojs/check": "^0.9.4", + "@astrojs/db": "^0.17.1", "@astrojs/mdx": "^4.3.1", "@astrojs/netlify": "^6.5.2", "@astrojs/react": "^4.3.0", diff --git a/src/actions/index.ts b/src/actions/index.ts new file mode 100644 index 0000000..f2496f9 --- /dev/null +++ b/src/actions/index.ts @@ -0,0 +1,50 @@ +import { defineAction } from 'astro:actions' +import { Counter, db, eq } from 'astro:db' +import { z } from 'astro:schema' + +export const server = { + getCounter: defineAction({ + input: z.object({ + counterName: z.string(), + }), + handler: async (input) => { + const counterResult = await db + .select() + .from(Counter) + .where(eq(Counter.name, input.counterName)) + .limit(1) + const counter = counterResult?.[0] + + if (!counter) { + throw new Error(`Counter ${input.counterName} not found`) + } + + return counter + }, + }), + incrementCounter: defineAction({ + input: z.object({ + counterName: z.string(), + }), + handler: async (input) => { + const counterResult = await db + .select() + .from(Counter) + .where(eq(Counter.name, input.counterName)) + .limit(1) + const counter = counterResult?.[0] + + if (!counter) { + throw new Error(`Counter ${input.counterName} not found`) + } + + const result = await db + .update(Counter) + .set({ count: counter.count + 1 }) + .where(eq(Counter.name, input.counterName)) + .returning({ count: Counter.count }) + + return result[0] + }, + }), +} diff --git a/src/pages/admin/index.astro b/src/pages/admin/index.astro index c2b63b9..296e279 100644 --- a/src/pages/admin/index.astro +++ b/src/pages/admin/index.astro @@ -1,17 +1,26 @@ --- export const prerender = false // Enable SSR for authentication +import { actions } from 'astro:actions' +import { SITE_TITLE, SITE_DESCRIPTION } from '../../config' +import BaseHead from '../../components/BaseHead.astro' + // Get auth context from middleware const auth = Astro.locals.auth const user = auth?.user + +const { data: initialCounter, error } = await Astro.callAction( + actions.getCounter, + { + counterName: 'adminCounter', + } +) ---
- - -