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 9961da9..0e2dd0e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..76ef786 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[install] +registry = "https://registry.npmjs.org" \ No newline at end of file diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..fba73fb --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +export default { extends: ["@commitlint/config-conventional"] } diff --git a/controllers/template/index.ts b/controllers/template/index.ts index 437b535..078d6f7 100644 --- a/controllers/template/index.ts +++ b/controllers/template/index.ts @@ -2,6 +2,6 @@ const templateFunc = () => {} 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<UserRecordModel>( async () => await pbClient.collection("user").getOne(id) - ); + ) const getOneByUserId = (user_id: number) => { return managePb404<UserRecordModel>( @@ -23,24 +23,24 @@ const getOneByUserId = (user_id: number) => { .getFirstListItem(`user_id="${user_id}"`, { sort: "-created", }) - ); -}; + ) +} const create = async (data: Partial<UserRecordModel>) => - await pbClient.collection("user").create<UserRecordModel>(data); + await pbClient.collection("user").create<UserRecordModel>(data) const upsert = async (data: Partial<UserRecordModel>) => { - 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 <T>(dbFunc: Function): Promise<T | null> => { 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 } -}; +}