diff --git a/.dockerignore b/.dockerignore index 77763cf..6ef9371 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,6 @@ -# .dockerignore -/.nuxt -/.output -/node_modules - -.gitignore -README.md \ No newline at end of file +node_modules +npm-debug* +.nuxt +dist +tests +.output diff --git a/.eslintignore b/.eslintignore index e69de29..d3dff7b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -0,0 +1,10 @@ +dist +public + +# ignore generate imports +auto-imports.d.ts +components.d.ts + +dist +.output +node_modules diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..741577d --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,57 @@ +name: Node.js CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + testCodebase: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 20 + uses: actions/setup-node@v3 + with: + node-version: 20 + + # Install pnpm and packages + - run: npm install -g pnpm + - run: pnpm install + + # Generate prisma client & push to db + - run: echo "DATABASE_URL=file:./db.sqlite" > .env + - run: npx prisma db push + - run: npx prisma generate + + # Run linting and typechecking + - run: pnpm run lint + - run: pnpm run typecheck + + # Run tests + - run: pnpm run test + + testAppBuildsAndStarts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 20 + uses: actions/setup-node@v3 + with: + node-version: 20 + + # Install pnpm and packages + - run: npm install -g pnpm + - run: pnpm install + + # Generate prisma client & push to db + - run: echo "DATABASE_URL=file:./db.sqlite" > .env + - run: npx prisma db push + - run: npx prisma generate + + # Start app in dev mode and load `/`-index page + - run: '(timeout 60 pnpm run dev & (sleep 10 && curl --fail localhost:3000)) && echo Run development check successful' + + # Build & start app in production mode and load `/`-index page + - run: 'pnpm run build && (timeout 60 pnpm run preview & (sleep 10 && curl --fail localhost:3000)) && echo Run production check successful' \ No newline at end of file diff --git a/.gitignore b/.gitignore index 768a14e..239c57c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,83 @@ -# Nuxt dev/build outputs -.output +# Logs and databases # +###################### +*.log +*.sql +*.sqlite +*.db +*.sqlite-journal +/logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# helmsman generated tmp folder +.helmsman-tmp + +# Coverage directory used by tools like istanbul +coverage + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# Nuxt +*.log* .nuxt .nitro .cache +.output +.env dist -# Node dependencies -node_modules +# vuepress build output +.vuepress/dist -# Logs -logs -*.log +# Serverless directories +.serverless -# Misc -.DS_Store -.fleet +# IDE / Editor .idea -# Local env files -.env -.env.* -!.env.example +# Service worker +sw.* + +# Vim swap files +*.swp + +# Auto generate on postinstall step +auto-imports.d.ts +components.d.ts diff --git a/.npmrc b/.npmrc index 75ed8c8..2629f36 100644 --- a/.npmrc +++ b/.npmrc @@ -1,5 +1,4 @@ shamefully-hoist=true strict-peer-dependencies=false - sharp_binary_host="https://npmmirror.com/mirrors/sharp" sharp_libvips_binary_host="https://npmmirror.com/mirrors/sharp-libvips" \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..d9f8800 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +16.14.2 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..c410058 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", + "vue.volar", + "bradlc.vscode-tailwindcss", + "Prisma.prisma-insider" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 42f4c9b..f2251b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,76 +1,46 @@ { + "[vue]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[js]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "[ts]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "tailwindCSS.experimental.configFile": ".nuxt/tailwind.config.cjs", "files.associations": { "*.css": "tailwindcss" }, - "editor.quickSuggestions": { - "strings": true - }, - "tailwindCSS.experimental.classRegex": [ - [ - "ui:\\s*{([^)]*)\\s*}", - "[\"'`]([^\"'`]*).*?[\"'`]" - ], - [ - "/\\*ui\\*/\\s*{([^;]*)}", - ":\\s*[\"'`]([^\"'`]*).*?[\"'`]" - ] - ], - "tailwindCSS.classAttributes": [ - "class", - "className", - "ngClass", - "ui" - ], - "nuxt.isNuxtApp": false, + "volar.autoCompleteRefs": true, + "prisma.fileWatcher": true, // Enable the ESlint flat config support "eslint.experimental.useFlatConfig": true, + // Disable the default formatter, use eslint instead "prettier.enable": false, "editor.formatOnSave": false, + // Auto fix "editor.codeActionsOnSave": { - "source.fixAll": "explicit", + "source.fixAll.eslint": "explicit", "source.organizeImports": "never" }, + // Silent the stylistic rules in you IDE, but still auto fix them "eslint.rules.customizations": [ - { - "rule": "style/*", - "severity": "off" - }, - { - "rule": "*-indent", - "severity": "off" - }, - { - "rule": "*-spacing", - "severity": "off" - }, - { - "rule": "*-spaces", - "severity": "off" - }, - { - "rule": "*-order", - "severity": "off" - }, - { - "rule": "*-dangle", - "severity": "off" - }, - { - "rule": "*-newline", - "severity": "off" - }, - { - "rule": "*quotes", - "severity": "off" - }, - { - "rule": "*semi", - "severity": "off" - } + { "rule": "style/*", "severity": "off" }, + { "rule": "format/*", "severity": "off" }, + { "rule": "*-indent", "severity": "off" }, + { "rule": "*-spacing", "severity": "off" }, + { "rule": "*-spaces", "severity": "off" }, + { "rule": "*-order", "severity": "off" }, + { "rule": "*-dangle", "severity": "off" }, + { "rule": "*-newline", "severity": "off" }, + { "rule": "*quotes", "severity": "off" }, + { "rule": "*semi", "severity": "off" } ], + // Enable eslint for all supported languages "eslint.validate": [ "javascript", @@ -82,6 +52,7 @@ "markdown", "json", "jsonc", - "yaml" + "yaml", + "toml" ] } diff --git a/Dockerfile b/Dockerfile index 993d147..3a6d770 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,46 @@ -# 第一阶段:构建阶段 -FROM node:20.11.1-alpine as build +# Use a smaller base image +ARG NODE_VERSION=node:20-alpine -WORKDIR /src +# Stage 1: Build dependencies +FROM $NODE_VERSION AS dependency-base -# 将依赖项安装到单独的图层中 -COPY package.json pnpm-lock.yaml .npmrc ./ -RUN npm config set registry https://registry.npmmirror.com && \ - npm install -g pnpm && \ - pnpm install +# Create app directory +WORKDIR /app -# 复制应用程序代码并构建 +# Install pnpm +RUN npm install -g pnpm + +# Copy the package files +COPY package.json pnpm-lock.yaml ./ + +# Install dependencies using pnpm +RUN pnpm install --frozen-lockfile + +# Stage 2: Build the application +FROM dependency-base AS production-base + +# Copy the source code COPY . . -RUN pnpm build -# 第二阶段:运行阶段 -FROM node:20.11.1-alpine as base +# Build the application +RUN pnpm run build -EXPOSE 3000 +# Stage 3: Production image +FROM $NODE_VERSION AS production + +# Copy built assets from previous stage +COPY --from=production-base /app/.output /app/.output -WORKDIR /src +# Define environment variables +ENV NUXT_HOST=0.0.0.0 \ + NUXT_APP_VERSION=latest \ + DATABASE_URL=file:./db.sqlite \ + NODE_ENV=production -# 复制构建阶段生成的代码和依赖项(仅复制构建所需的文件和依赖项) -COPY --from=build /src/.output /src/.output +# Set the working directory +WORKDIR /app + +EXPOSE 3000 -CMD [ "node", ".output/server/index.mjs" ] \ No newline at end of file +# Start the app +CMD ["node", "/app/.output/server/index.mjs"] \ No newline at end of file diff --git a/app.config.ts b/app.config.ts index 974e894..4fd67fe 100644 --- a/app.config.ts +++ b/app.config.ts @@ -3,8 +3,8 @@ export default defineAppConfig({ primary: 'red', gray: 'cool', icons: { - dynamic: true - } + dynamic: true, + }, }, }) diff --git a/app.vue b/app.vue index 6c0568b..687fe19 100644 --- a/app.vue +++ b/app.vue @@ -1,3 +1,17 @@ + + diff --git a/assets/css/tailwind.css b/assets/css/tailwind.css deleted file mode 100644 index a9bac45..0000000 --- a/assets/css/tailwind.css +++ /dev/null @@ -1,9 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer components { - .card { - @apply hover:scale-105 hover:shadow-2xl transition-all bg-white text-sm leading-6 shadow-md ring-1 ring-gray-900/5; - } -} diff --git a/components/LinkIcon.vue b/components/LinkIcon.vue new file mode 100644 index 0000000..73514ad --- /dev/null +++ b/components/LinkIcon.vue @@ -0,0 +1,19 @@ + + + diff --git a/components/flow/Index.vue b/components/flow/Index.vue index 4aed75b..5f139dd 100644 --- a/components/flow/Index.vue +++ b/components/flow/Index.vue @@ -1,25 +1,28 @@ - @@ -27,14 +30,4 @@ const res = computed(() => data.value.data) .flow-body { @apply grid grid-cols-1 gap-7 mt-5 mb-16 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4; } -@media (min-width: 1280px) { - .flow-body a:nth-child(n+10) { - display: none; - } -} -@media (min-width: 1536px) { - .flow-body a:nth-child(n+9) { - display: none; - } -} diff --git a/components/flow/Project.vue b/components/flow/Project.vue deleted file mode 100644 index b1f2f5e..0000000 --- a/components/flow/Project.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/components/index/Catalog.vue b/components/index/Catalog.vue index 5ce2486..b1d7fa8 100644 --- a/components/index/Catalog.vue +++ b/components/index/Catalog.vue @@ -1,8 +1,12 @@