From 68248c1d24c378993100601ba3f3139b3c68d2ec Mon Sep 17 00:00:00 2001 From: zhaoyingbo Date: Sat, 16 Nov 2024 11:14:55 +0000 Subject: [PATCH] =?UTF-8?q?feat(base):=20=E4=BC=98=E5=8C=96=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=9F=BA=E7=A1=80=E5=BC=80=E5=8F=91=E7=8E=AF=E5=A2=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/devcontainer.json | 31 +++++++++----- .env | 7 ++++ .gitignore | 4 +- .husky/commit-msg | 1 + .husky/pre-commit | 1 + .vscode/settings.json | 3 ++ bun.lockb | Bin 55727 -> 109050 bytes bunfig.toml | 2 + commitlint.config.js | 1 + controllers/template/index.ts | 4 +- db/index.ts | 6 +-- db/pbClient.ts | 8 ++-- db/prisma/user/index.ts | 19 +++++++++ db/user/index.ts | 38 +++++++++--------- docker/mysql/dev.docker-compose.yml | 16 ++++++++ docker/mysql/run.sh | 1 + docker/mysql/stop.sh | 1 + eslint.config.js | 24 +++++------ index.ts | 12 +++--- package.json | 29 ++++++++++--- prettier.config.js | 6 +++ .../20241116101639_init/migration.sql | 9 +++++ prisma/migrations/migration_lock.toml | 3 ++ prisma/schema.prisma | 20 +++++++++ schedule/index.ts | 4 +- service/index.ts | 18 ++++----- types/index.ts | 4 ++ utils/pbTools.ts | 8 ++-- 28 files changed, 201 insertions(+), 79 deletions(-) create mode 100644 .env create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .vscode/settings.json create mode 100644 bunfig.toml create mode 100644 commitlint.config.js create mode 100644 db/prisma/user/index.ts create mode 100644 docker/mysql/dev.docker-compose.yml create mode 100644 docker/mysql/run.sh create mode 100644 docker/mysql/stop.sh create mode 100644 prettier.config.js create mode 100644 prisma/migrations/20241116101639_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cbf9df2..c60a7f3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,12 @@ { "name": "replace_me", - "image": "micr.cloud.mioffice.cn/zhaoyingbo/dev:bun", - "remoteUser": "bun", - "containerUser": "bun", + "image": "mcr.microsoft.com/devcontainers/typescript-node:20", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "moby": true + } + }, "customizations": { "vscode": { "settings": { @@ -10,20 +14,25 @@ "editor.guides.bracketPairs": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, - "github.copilot.chat.localeOverride": "zh-CN" + "github.copilot.chat.localeOverride": "zh-CN", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "always" + } }, "extensions": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", + "jock.svg", + "GitHub.copilot", "eamodio.gitlens", "unifiedjs.vscode-mdx", - "oderwat.indent-rainbow", - "jock.svg", - "ChakrounAnas.turbo-console-log", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", "Gruntfuggly.todo-tree", + "ChakrounAnas.turbo-console-log", + "streetsidesoftware.code-spell-checker", "MS-CEINTL.vscode-language-pack-zh-hans", - "GitHub.copilot" + "Prisma.prisma" ] } - } + }, + "onCreateCommand": "curl -fsSL https://bun.sh/install | bash" } diff --git a/.env b/.env new file mode 100644 index 0000000..14f5aab --- /dev/null +++ b/.env @@ -0,0 +1,7 @@ +# Environment variables declared in this file are automatically made available to Prisma. +# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema + +# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. +# See the documentation for all the connection string options: https://pris.ly/d/connection-strings + +DATABASE_URL="mysql://root:rootpassword@localhost:3306/testdb" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 52962c2..1a74851 100644 --- a/.gitignore +++ b/.gitignore @@ -49,8 +49,8 @@ profile-* .idea # vscode -.vscode -*code-workspace +# .vscode +# *code-workspace # clinic profile* diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..0a4b97d --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npx --no -- commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..af5adff --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +lint-staged \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..04bbd13 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["bunx", "oxlint"] +} diff --git a/bun.lockb b/bun.lockb index 9961da94437656c854a98c1308fe0afd41989b6a..0e2dd0eda2b335e096657c9ef51aa600453c634a 100755 GIT binary patch literal 109050 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 LumsdoKil {} const template = { templateFunc, -}; +} -export default template; +export default template diff --git a/db/index.ts b/db/index.ts index 8570c84..1a300d5 100644 --- a/db/index.ts +++ b/db/index.ts @@ -1,7 +1,7 @@ -import user from "./user"; +import user from "./user" const db = { user, -}; +} -export default db; +export default db diff --git a/db/pbClient.ts b/db/pbClient.ts index 7999649..7bd419b 100644 --- a/db/pbClient.ts +++ b/db/pbClient.ts @@ -1,7 +1,7 @@ -import PocketBase from "pocketbase"; +import PocketBase from "pocketbase" -const pbClient = new PocketBase("https://ci-pb.xiaomiwh.cn"); +const pbClient = new PocketBase("https://ci-pb.xiaomiwh.cn") -pbClient.autoCancellation(false); +pbClient.autoCancellation(false) -export default pbClient; +export default pbClient diff --git a/db/prisma/user/index.ts b/db/prisma/user/index.ts new file mode 100644 index 0000000..3b76fe4 --- /dev/null +++ b/db/prisma/user/index.ts @@ -0,0 +1,19 @@ +import { PrismaClient } from "@prisma/client" + +const prisma = new PrismaClient() + +const main = async () => { + const user = await prisma.user.create({ + data: { + name: "Alice", + email: "alice@example.com", + }, + }) + console.log(user) + const users = await prisma.user.findMany() + console.log(users) +} + +main().then(() => { + prisma.$disconnect() +}) diff --git a/db/user/index.ts b/db/user/index.ts index 389a9ec..c7f52e5 100644 --- a/db/user/index.ts +++ b/db/user/index.ts @@ -1,19 +1,19 @@ -import { RecordModel } from "pocketbase"; -import { managePb404 } from "../../utils/pbTools"; -import pbClient from "../pbClient"; +import { RecordModel } from "pocketbase" +import { managePb404 } from "../../utils/pbTools" +import pbClient from "../pbClient" export interface UserRecordModel extends RecordModel { - user_id: number; - username: string; - name: string; - avatar_url: string; - web_url: string; + user_id: number + username: string + name: string + avatar_url: string + web_url: string } const getOne = (id: string) => managePb404( async () => await pbClient.collection("user").getOne(id) - ); + ) const getOneByUserId = (user_id: number) => { return managePb404( @@ -23,24 +23,24 @@ const getOneByUserId = (user_id: number) => { .getFirstListItem(`user_id="${user_id}"`, { sort: "-created", }) - ); -}; + ) +} const create = async (data: Partial) => - await pbClient.collection("user").create(data); + await pbClient.collection("user").create(data) const upsert = async (data: Partial) => { - if (!data.user_id) return null; - const userInfo = await getOneByUserId(data.user_id); - if (userInfo) return userInfo; - return await create(data); -}; + if (!data.user_id) return null + const userInfo = await getOneByUserId(data.user_id) + if (userInfo) return userInfo + return await create(data) +} const user = { create, upsert, getOne, getOneByUserId, -}; +} -export default user; +export default user diff --git a/docker/mysql/dev.docker-compose.yml b/docker/mysql/dev.docker-compose.yml new file mode 100644 index 0000000..fb3d905 --- /dev/null +++ b/docker/mysql/dev.docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.8" + +services: + mysql: + image: micr.cloud.mioffice.cn/zhaoyingbo/mysql:8.0 + container_name: mysql + environment: + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: testdb + ports: + - "3306:3306" + volumes: + - mysql-data:/var/lib/mysql + +volumes: + mysql-data: diff --git a/docker/mysql/run.sh b/docker/mysql/run.sh new file mode 100644 index 0000000..97001a0 --- /dev/null +++ b/docker/mysql/run.sh @@ -0,0 +1 @@ +docker compose -f dev.docker-compose.yml up -d \ No newline at end of file diff --git a/docker/mysql/stop.sh b/docker/mysql/stop.sh new file mode 100644 index 0000000..699e964 --- /dev/null +++ b/docker/mysql/stop.sh @@ -0,0 +1 @@ +docker compose -f dev.docker-compose.yml down \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js index ac8d057..88e3a2b 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,26 +1,26 @@ export default { languageOptions: { ecmaVersion: 2021, - sourceType: 'module', + sourceType: "module", }, - ignores: ['*.js', '*.cjs', '*.mjs', '/src/Backup/*'], - plugins: ['@typescript-eslint', 'simple-import-sort'], + ignores: ["*.js", "*.cjs", "*.mjs", "/src/Backup/*"], + plugins: ["@typescript-eslint", "simple-import-sort"], extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier', + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", ], rules: { - '@typescript-eslint/no-explicit-any': 'off', - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', + "@typescript-eslint/no-explicit-any": "off", + "simple-import-sort/imports": "error", + "simple-import-sort/exports": "error", }, overrides: [ { - files: ['**/*.ts', '**/*.tsx'], + files: ["**/*.ts", "**/*.tsx"], languageOptions: { - parser: '@typescript-eslint/parser', + parser: "@typescript-eslint/parser", }, }, ], -}; \ No newline at end of file +} diff --git a/index.ts b/index.ts index e67874e..0fea807 100644 --- a/index.ts +++ b/index.ts @@ -1,14 +1,14 @@ -import { initSchedule } from "./schedule"; +import { initSchedule } from "./schedule" initSchedule() Bun.serve({ async fetch(req) { - const url = new URL(req.url); + const url = new URL(req.url) // 根路由 - if (url.pathname === "/") return new Response("hello, glade to see you!"); - if (url.pathname === '/ci') return new Response("OK") - return new Response("OK"); + if (url.pathname === "/") return new Response("hello, glade to see you!") + if (url.pathname === "/ci") return new Response("OK") + return new Response("OK") }, port: 3000, -}); +}) diff --git a/package.json b/package.json index 7287580..af7995a 100644 --- a/package.json +++ b/package.json @@ -3,21 +3,40 @@ "module": "index.ts", "type": "module", "scripts": { - "start": "bun run index.ts" + "start": "NODE_ENV=production bun run index.ts", + "dev": "NODE_ENV=dev bun run index.ts --watch", + "lint": "oxlint --fix .", + "prepare": "husky", + "prettier": "prettier --write .", + "init:prisma": "bunx prisma migrate dev --name init" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "oxlint --fix", + "eslint --fix", + "prettier --write" + ] }, "devDependencies": { - "eslint": "^9.2.0", - "bun-types": "latest", + "@commitlint/cli": "^19.5.0", + "@commitlint/config-conventional": "^19.5.0", "@types/lodash": "^4.14.202", "@types/node-schedule": "^2.1.6", - "eslint-plugin-simple-import-sort": "^12.1.0", "@typescript-eslint/eslint-plugin": "^7.8.0", - "@typescript-eslint/parser": "^7.8.0" + "@typescript-eslint/parser": "^7.8.0", + "bun-types": "latest", + "eslint": "^9.2.0", + "eslint-plugin-simple-import-sort": "^12.1.0", + "husky": "^9.1.6", + "lint-staged": "^15.2.10", + "oxlint": "^0.11.1", + "prettier": "^3.3.3" }, "peerDependencies": { "typescript": "^5.0.0" }, "dependencies": { + "@prisma/client": "^5.22.0", "lodash": "^4.17.21", "node-schedule": "^2.1.1", "pocketbase": "^0.21.1" diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..db67959 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,6 @@ +export default { + trailingComma: "es5", + tabWidth: 2, + semi: false, + singleQuote: false, +} diff --git a/prisma/migrations/20241116101639_init/migration.sql b/prisma/migrations/20241116101639_init/migration.sql new file mode 100644 index 0000000..4166918 --- /dev/null +++ b/prisma/migrations/20241116101639_init/migration.sql @@ -0,0 +1,9 @@ +-- CreateTable +CREATE TABLE `User` ( + `id` INTEGER NOT NULL AUTO_INCREMENT, + `name` VARCHAR(191) NOT NULL, + `email` VARCHAR(191) NOT NULL, + + UNIQUE INDEX `User_email_key`(`email`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..e5a788a --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "mysql" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..f879a6e --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,20 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "mysql" + url = env("DATABASE_URL") +} + +model User { + id Int @id @default(autoincrement()) + name String + email String @unique +} \ No newline at end of file diff --git a/schedule/index.ts b/schedule/index.ts index 6a3ceec..e2b41d8 100644 --- a/schedule/index.ts +++ b/schedule/index.ts @@ -1,10 +1,10 @@ -import schedule from 'node-schedule' +import schedule from "node-schedule" const func = () => {} export const initSchedule = async () => { // 定时任务,每15分钟刷新一次token - schedule.scheduleJob('*/15 * * * *', func); + schedule.scheduleJob("*/15 * * * *", func) // 立即执行一次 func() } diff --git a/service/index.ts b/service/index.ts index 6fcaa20..a29ad0c 100644 --- a/service/index.ts +++ b/service/index.ts @@ -1,7 +1,7 @@ const fetchGetParams = { method: "GET", headers: { "PRIVATE-TOKEN": "Zd1UASPcMwVox5tNS6ep" }, -}; +} /** * 获取项目详情 @@ -12,17 +12,17 @@ const fetchTemplate = async (id: number) => { const response = await fetch( `https://git.n.xiaomi.com/api/v4/projects/${id}`, fetchGetParams - ); - const body = (await response.json()) as any; - if (body.message === "404 Project Not Found") return null; - return body; + ) + const body = (await response.json()) as any + if (body.message === "404 Project Not Found") return null + return body } catch { - return null; + return null } -}; +} const service = { fetchTemplate, -}; +} -export default service; +export default service diff --git a/types/index.ts b/types/index.ts index e69de29..92e97c4 100644 --- a/types/index.ts +++ b/types/index.ts @@ -0,0 +1,4 @@ +export interface FakeType { + name: string + age: number +} diff --git a/utils/pbTools.ts b/utils/pbTools.ts index 3d8a903..93a4bc1 100644 --- a/utils/pbTools.ts +++ b/utils/pbTools.ts @@ -1,9 +1,9 @@ export const managePb404 = async (dbFunc: Function): Promise => { try { - return await dbFunc(); + return await dbFunc() } catch (err: any) { if (err?.message === "The requested resource wasn't found.") { - return null; - } else throw err; + return null + } else throw err } -}; +}