Browse Source

Add drizzle-zod and zod dependencies, refactor API handler for user retrieval, and introduce response handler utility

tags/pure-sql-nuxt4
npmrun 6 days ago
parent
commit
11003ae456
  1. 5
      README.md
  2. 1
      app/app.vue
  3. 6
      bun.lock
  4. 4
      package.json
  5. 11
      server/api/hello.ts
  6. 12
      server/service/auth/index.ts
  7. 27
      server/utils/handler.ts

5
README.md

@ -10,3 +10,8 @@
## 开发与部署 ## 开发与部署
用 Linux 开发与部署,包管理器采用 bun@1.3.11。数据库为 **postgres**(通过 `DATABASE_URL` 连接;本地可参考 `.env.example` 复制为 `.env.local`)。部署时可直接打包 `.output` 目录,在服务器环境执行迁移命令,省时省力。 用 Linux 开发与部署,包管理器采用 bun@1.3.11。数据库为 **postgres**(通过 `DATABASE_URL` 连接;本地可参考 `.env.example` 复制为 `.env.local`)。部署时可直接打包 `.output` 目录,在服务器环境执行迁移命令,省时省力。
## 计划
- [ ] 支持定时任务
- [ ]

1
app/app.vue

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
const { data, pending, error, refresh } = await useFetch('/api/hello') const { data, pending, error, refresh } = await useFetch('/api/hello')
const userCount = computed(() => data.value?.users?.length ?? 0) const userCount = computed(() => data.value?.users?.length ?? 0)
</script> </script>

6
bun.lock

@ -9,12 +9,14 @@
"drizzle-orm": "^0.45.2", "drizzle-orm": "^0.45.2",
"drizzle-pkg": "workspace:*", "drizzle-pkg": "workspace:*",
"drizzle-seed": "0.3.1", "drizzle-seed": "0.3.1",
"drizzle-zod": "^0.8.3",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"logger": "workspace:*", "logger": "workspace:*",
"nuxt": "4.4.2", "nuxt": "4.4.2",
"pg": "8.20.0", "pg": "8.20.0",
"vue": "3.5.32", "vue": "3.5.32",
"vue-router": "5.0.4", "vue-router": "5.0.4",
"zod": "^4.3.6",
}, },
"devDependencies": { "devDependencies": {
"@types/pg": "^8.20.0", "@types/pg": "^8.20.0",
@ -731,6 +733,8 @@
"drizzle-seed": ["drizzle-seed@0.3.1", "", { "dependencies": { "pure-rand": "^6.1.0" }, "peerDependencies": { "drizzle-orm": ">=0.36.4" }, "optionalPeers": ["drizzle-orm"] }, "sha512-F/0lgvfOAsqlYoHM/QAGut4xXIOXoE5VoAdv2FIl7DpGYVXlAzKuJO+IphkKUFK3Dz+rFlOsQLnMNrvoQ0cx7g=="], "drizzle-seed": ["drizzle-seed@0.3.1", "", { "dependencies": { "pure-rand": "^6.1.0" }, "peerDependencies": { "drizzle-orm": ">=0.36.4" }, "optionalPeers": ["drizzle-orm"] }, "sha512-F/0lgvfOAsqlYoHM/QAGut4xXIOXoE5VoAdv2FIl7DpGYVXlAzKuJO+IphkKUFK3Dz+rFlOsQLnMNrvoQ0cx7g=="],
"drizzle-zod": ["drizzle-zod@0.8.3", "", { "peerDependencies": { "drizzle-orm": ">=0.36.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-66yVOuvGhKJnTdiqj1/Xaaz9/qzOdRJADpDa68enqS6g3t0kpNkwNYjUuaeXgZfO/UWuIM9HIhSlJ6C5ZraMww=="],
"duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="], "duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="],
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
@ -1445,6 +1449,8 @@
"zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="],
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
"@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],

4
package.json

@ -23,12 +23,14 @@
"drizzle-orm": "^0.45.2", "drizzle-orm": "^0.45.2",
"drizzle-pkg": "workspace:*", "drizzle-pkg": "workspace:*",
"drizzle-seed": "0.3.1", "drizzle-seed": "0.3.1",
"drizzle-zod": "^0.8.3",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"logger": "workspace:*", "logger": "workspace:*",
"nuxt": "4.4.2", "nuxt": "4.4.2",
"pg": "8.20.0", "pg": "8.20.0",
"vue": "3.5.32", "vue": "3.5.32",
"vue-router": "5.0.4" "vue-router": "5.0.4",
"zod": "^4.3.6"
}, },
"devDependencies": { "devDependencies": {
"@types/pg": "^8.20.0", "@types/pg": "^8.20.0",

11
server/api/hello.ts

@ -1,13 +1,14 @@
import { usersTable } from "drizzle-pkg/lib/schema/schema";
import { dbGlobal } from "drizzle-pkg/lib/db";
import log4js from "logger"; import log4js from "logger";
import { getUsers } from "#server/service/auth";
const logger = log4js.getLogger("APP") const logger = log4js.getLogger("APP")
export default defineEventHandler(async (event) => { export default defineWrappedResponseHandler({
auth: true,
authType: 'token',
}, async (event) => {
logger.info("hello: world"); logger.info("hello: world");
const users = await dbGlobal.select().from(usersTable) const users = await getUsers(1)
logger.info("users (formatted): %s \n", JSON.stringify(users, null, 2));
return { return {
hello: 'world', hello: 'world',
users: users, users: users,

12
server/service/auth/index.ts

@ -0,0 +1,12 @@
import { dbGlobal } from "drizzle-pkg/lib/db";
import { usersTable } from "drizzle-pkg/lib/schema/schema";
import { eq } from "drizzle-orm";
import log4js from "logger";
const logger = log4js.getLogger("AUTH")
export async function getUsers(id: number) {
const users = await dbGlobal.select().from(usersTable)
logger.info("users (formatted): %s \n", JSON.stringify(users, null, 2));
return users;
}

27
server/utils/handler.ts

@ -0,0 +1,27 @@
interface IConfig {
auth?: boolean;
authType?: 'token' | 'basic';
}
export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D>(
handlerOrConfig?: EventHandler<T, D> | IConfig,
_handler?: EventHandler<T, D>,
): EventHandler<T, D> => {
const handler = typeof handlerOrConfig === 'function' ? handlerOrConfig : _handler;
if (!handler) {
throw new Error('handler or config is required');
}
const config = typeof handlerOrConfig === 'object' ? handlerOrConfig : {};
return defineEventHandler<T>(async (event) => {
try {
// do something before the route handler
const response = await handler(event)
// do something after the route handler
return { response }
} catch (err) {
// Error handling
return { err }
}
})
}
Loading…
Cancel
Save