diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..40bd99c --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ea6e20f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.env b/.env new file mode 100644 index 0000000..8bc9092 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_DOMAIN = http://192.168.3.17:3000/ diff --git a/.env.client b/.env.client new file mode 100644 index 0000000..8bc9092 --- /dev/null +++ b/.env.client @@ -0,0 +1 @@ +VITE_DOMAIN = http://192.168.3.17:3000/ diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..b84beaf --- /dev/null +++ b/.eslintignore @@ -0,0 +1,11 @@ +public +dist +*.d.ts +/src/assets +package.json +eslint.config.js +.prettierrc.js +commitlint.config.js +postcss.config.js +tailwind.config.js +stylelint.config.js \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..009f5bc --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,120 @@ +module.exports = { + root: true, + env: { + node: true + }, + globals: { + // Ref sugar (take 2) + $: "readonly", + $$: "readonly", + $ref: "readonly", + $shallowRef: "readonly", + $computed: "readonly", + + // index.d.ts + // global.d.ts + Fn: "readonly", + PromiseFn: "readonly", + RefType: "readonly", + LabelValueOptions: "readonly", + EmitType: "readonly", + TargetContext: "readonly", + ComponentElRef: "readonly", + ComponentRef: "readonly", + ElRef: "readonly", + global: "readonly", + ForDataType: "readonly", + ComponentRoutes: "readonly", + + // script setup + defineProps: "readonly", + defineEmits: "readonly", + defineExpose: "readonly", + withDefaults: "readonly" + }, + extends: [ + "plugin:vue/vue3-essential", + "eslint:recommended", + "@vue/typescript/recommended", + "@vue/prettier", + "@vue/eslint-config-typescript" + ], + parser: "vue-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + ecmaVersion: 2020, + sourceType: "module", + jsxPragma: "React", + ecmaFeatures: { + jsx: true + } + }, + overrides: [ + { + files: ["*.ts", "*.vue"], + rules: { + "no-undef": "off" + } + }, + { + files: ["*.vue"], + parser: "vue-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + extraFileExtensions: [".vue"], + ecmaVersion: "latest", + ecmaFeatures: { + jsx: true + } + }, + rules: { + "no-undef": "off" + } + } + ], + rules: { + "vue/no-v-html": "off", + "vue/require-default-prop": "off", + "vue/require-explicit-emits": "off", + "vue/multi-word-component-names": "off", + "@typescript-eslint/no-explicit-any": "off", // any + "no-debugger": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", // setup() + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "vue/html-self-closing": [ + "error", + { + html: { + void: "always", + normal: "always", + component: "always" + }, + svg: "always", + math: "always" + } + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + "no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + "prettier/prettier": [ + "error", + { + endOfLine: "auto" + } + ] + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47badfb --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +# wrangler files +.wrangler +.dev.vars diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..ee7d693 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": true, + "tabWidth": 2, + "singleQuote": false, + "printWidth": 100, + "trailingComma": "none" +} diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..0c34e61 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,4 @@ +/dist/* +/public/* +public/* +src/style/reset.scss \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..215c167 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# cloudflare-pages-demo + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Run/Debug on Webstorm + +Set Run/Debug Configuration -> npm -> Command: run, Scripts: dev + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` + +### Lint with [ESLint](https://eslint.org/) + +```sh +npm run lint +``` + +### Preview on Local Host + +```sh +npm run preview +``` + +### Deploy + +```sh +npm run deploy +``` + +## D1 + +### 查看数据库表 + +```sql +SELECT name FROM sqlite_master WHERE type='table'; +``` diff --git a/app/server.ts b/app/server.ts new file mode 100644 index 0000000..6d3d87e --- /dev/null +++ b/app/server.ts @@ -0,0 +1,30 @@ +// app/server.ts +import { Hono } from "hono"; +import { cors } from "hono/cors"; +import userRouters from "./user/api"; + +interface Env { + ASSETS: { + fetch: (request: Request) => Promise; + }; +} + +const app = new Hono(); +app.use("/*", cors()); + +/* +API +*/ +app.route("/api/user", userRouters); + +app.get("/api/hello-world", async (c) => { + return c.text("Hello World!"); +}); + +// 处理所有其他请求,返回 Vue 的打包好的静态资源 +app.get("/*", async (c) => { + const env = c.env as Env; + return env.ASSETS.fetch(c.req.raw); +}); + +export default app; diff --git a/app/user/api.md b/app/user/api.md new file mode 100644 index 0000000..e69de29 diff --git a/app/user/api.ts b/app/user/api.ts new file mode 100644 index 0000000..6b7172c --- /dev/null +++ b/app/user/api.ts @@ -0,0 +1,25 @@ +// api.ts +import { Hono } from "hono"; +import { saveUser, getUserById } from "./db"; +import type User from "./user"; +import type { D1Database } from "@cloudflare/workers-types"; + +const api = new Hono<{ Bindings: { DB: D1Database } }>(); + +api.post("/save", async (c) => { + const user: User = await c.req.json(); + await saveUser(c.env.DB, user); + return c.json({ success: true }); +}); + +api.get("/detail", async (c) => { + const id = parseInt(c.req.query("id") as string, 10); + const user = await getUserById(c.env.DB, id); + if (user) { + return c.json(user); + } else { + return c.json({ error: "User not found" }, 404); + } +}); + +export default api; diff --git a/app/user/db.ts b/app/user/db.ts new file mode 100644 index 0000000..29768ef --- /dev/null +++ b/app/user/db.ts @@ -0,0 +1,55 @@ +// db.ts +import type { D1Database } from "@cloudflare/workers-types"; +import type User from "./user"; + +export async function initializeUsersTable(DB: D1Database): Promise { + const query = ` + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + resolution VARCHAR(50), + local_language VARCHAR(10), + m1 VARCHAR(255), + oaid VARCHAR(255), + channel VARCHAR(50), + app_version VARCHAR(20), + app_name VARCHAR(100), + pkg_name VARCHAR(100), + device_id VARCHAR(100), + platform VARCHAR(20), + os_version VARCHAR(20), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + `; + await DB.prepare(query).run(); +} + +export async function saveUser(DB: D1Database, user: User): Promise { + await initializeUsersTable(DB); // Ensure the table exists + const query = ` + INSERT INTO users ( + resolution, local_language, m1, oaid, channel, app_version, app_name, pkg_name, device_id, platform, os_version + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `; + const values = [ + user.resolution, + user.local_language, + user.m1, + user.oaid, + user.channel, + user.app_version, + user.app_name, + user.pkg_name, + user.device_id, + user.platform, + user.os_version + ]; + await DB.prepare(query) + .bind(...values) + .run(); +} + +export async function getUserById(DB: D1Database, id: number): Promise { + const query = `SELECT * FROM users WHERE id = ?`; + const result = await DB.prepare(query).bind(id).first(); + return result || null; +} diff --git a/app/user/user.ts b/app/user/user.ts new file mode 100644 index 0000000..bf041f7 --- /dev/null +++ b/app/user/user.ts @@ -0,0 +1,17 @@ +// user.ts + +export default interface User { + id: number; + resolution: string; + local_language: string; + m1: string; + oaid: string; + channel: string; + app_version: string; + app_name: string; + pkg_name: string; + device_id: string; + platform: string; + os_version: string; + created_at: Date; +} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..8803bcf --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,171 @@ +import js from "@eslint/js"; +import pluginVue from "eslint-plugin-vue"; +import * as parserVue from "vue-eslint-parser"; +import configPrettier from "eslint-config-prettier"; +import pluginPrettier from "eslint-plugin-prettier"; +import { defineFlatConfig } from "eslint-define-config"; +import * as parserTypeScript from "@typescript-eslint/parser"; +import pluginTypeScript from "@typescript-eslint/eslint-plugin"; + +export default defineFlatConfig([ + { + ...js.configs.recommended, + ignores: ["src/assets/**", "src/**/iconfont/**"], + languageOptions: { + globals: { + // index.d.ts + RefType: "readonly", + EmitType: "readonly", + TargetContext: "readonly", + ComponentRef: "readonly", + ElRef: "readonly", + ForDataType: "readonly", + AnyFunction: "readonly", + PropType: "readonly", + Writable: "readonly", + Nullable: "readonly", + NonNullable: "readonly", + Recordable: "readonly", + ReadonlyRecordable: "readonly", + Indexable: "readonly", + DeepPartial: "readonly", + Without: "readonly", + Exclusive: "readonly", + TimeoutHandle: "readonly", + IntervalHandle: "readonly", + Effect: "readonly", + ChangeEvent: "readonly", + WheelEvent: "readonly", + ImportMetaEnv: "readonly", + Fn: "readonly", + PromiseFn: "readonly", + ComponentElRef: "readonly", + parseInt: "readonly", + parseFloat: "readonly" + } + }, + plugins: { + prettier: pluginPrettier + }, + rules: { + ...configPrettier.rules, + ...pluginPrettier.configs.recommended.rules, + "no-debugger": "off", + "no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + "prettier/prettier": [ + "error", + { + endOfLine: "auto" + } + ] + } + }, + { + files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"], + languageOptions: { + parser: parserTypeScript, + parserOptions: { + sourceType: "module" + } + }, + plugins: { + "@typescript-eslint": pluginTypeScript + }, + rules: { + ...pluginTypeScript.configs.strict.rules, + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-redeclare": "error", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/prefer-as-const": "warn", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-import-type-side-effects": "error", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/consistent-type-imports": [ + "error", + { disallowTypeAnnotations: false, fixStyle: "inline-type-imports" } + ], + "@typescript-eslint/prefer-literal-enum-member": ["error", { allowBitwiseExpressions: true }], + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ] + } + }, + { + files: ["**/*.d.ts"], + rules: { + "eslint-comments/no-unlimited-disable": "off", + "import/no-duplicates": "off", + "unused-imports/no-unused-vars": "off" + } + }, + { + files: ["**/*.?([cm])js"], + rules: { + "@typescript-eslint/no-require-imports": "off", + "@typescript-eslint/no-var-requires": "off" + } + }, + { + files: ["**/*.vue"], + languageOptions: { + globals: { + $: "readonly", + $$: "readonly", + $computed: "readonly", + $customRef: "readonly", + $ref: "readonly", + $shallowRef: "readonly", + $toRef: "readonly" + }, + parser: parserVue, + parserOptions: { + ecmaFeatures: { + jsx: true + }, + extraFileExtensions: [".vue"], + parser: "@typescript-eslint/parser", + sourceType: "module" + } + }, + plugins: { + vue: pluginVue + }, + processor: pluginVue.processors[".vue"], + rules: { + ...pluginVue.configs.base.rules, + ...pluginVue.configs["vue3-essential"].rules, + ...pluginVue.configs["vue3-recommended"].rules, + "no-undef": "off", + "no-unused-vars": "off", + "vue/no-v-html": "off", + "vue/require-default-prop": "off", + "vue/require-explicit-emits": "off", + "vue/multi-word-component-names": "off", + "vue/no-setup-props-reactivity-loss": "off", + "vue/html-self-closing": [ + "error", + { + html: { + void: "always", + normal: "always", + component: "always" + }, + svg: "always", + math: "always" + } + ] + } + } +]); diff --git a/index.html b/index.html new file mode 100644 index 0000000..a888544 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..1be96ab --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "cloudflare-pages-demo", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev:client": "vite --mode client", + "dev:optimize": "vite optimize", + "dev:server": "vite", + "dev": "npm run dev:optimize && concurrently \"npm run dev:client\" \"npm run dev:server\"", + "debug": "wrangler dev --log-level=debug", + "build": "vite build --mode client && vite build", + "preview": "npm run build && wrangler pages dev dist --log-level=debug", + "deploy": "npm run build && wrangler pages deploy dist --project-name \"cloudflare-pages-demo\"", + "build-only": "run-p type-check \"build-only {@}\" --", + "type-check": "vue-tsc --build --force", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier --write src/" + }, + "dependencies": { + "hono": "^4.6.2", + "pinia": "^2.1.7", + "qrcode": "^1.5.4", + "vue": "^3.4.29", + "vue-router": "^4.3.3" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240909.0", + "@eslint/js": "^9.10.0", + "@hono/vite-cloudflare-pages": "^0.4.2", + "@hono/vite-dev-server": "^0.16.0", + "@rushstack/eslint-patch": "^1.8.0", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@types/qrcode": "^1.5.5", + "@typescript-eslint/eslint-plugin": "^8.6.0", + "@typescript-eslint/parser": "^8.0.0", + "@vitejs/plugin-vue": "^5.0.5", + "@vitejs/plugin-vue-jsx": "^4.0.0", + "@vue/eslint-config-typescript": "^13.0.0", + "@vue/tsconfig": "^0.5.1", + "concurrently": "^9.0.1", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-define-config": "^2.1.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-vue": "^9.23.0", + "npm-run-all2": "^6.2.0", + "prettier": "^3.2.5", + "ts-node": "^10.9.2", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-eslint-parser": "^9.4.3", + "vue-tsc": "^2.0.21", + "wrangler": "^3.78.2" + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/schema.sql b/schema.sql new file mode 100644 index 0000000..baa2539 --- /dev/null +++ b/schema.sql @@ -0,0 +1,16 @@ +-- schema.sql +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + resolution VARCHAR(50), + local_language VARCHAR(10), + m1 VARCHAR(255), + oaid VARCHAR(255), + channel VARCHAR(50), + app_version VARCHAR(20), + app_name VARCHAR(100), + pkg_name VARCHAR(100), + device_id VARCHAR(100), + platform VARCHAR(20), + os_version VARCHAR(20), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..b911eeb --- /dev/null +++ b/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/src/assets/base.css b/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/main.css b/src/assets/main.css new file mode 100644 index 0000000..36fb845 --- /dev/null +++ b/src/assets/main.css @@ -0,0 +1,35 @@ +@import './base.css'; + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + font-weight: normal; +} + +a, +.green { + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} + +@media (min-width: 1024px) { + body { + display: flex; + place-items: center; + } + + #app { + display: grid; + grid-template-columns: 1fr 1fr; + padding: 0 2rem; + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..5c94f08 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,14 @@ +import "./assets/main.css"; + +import { createApp } from "vue"; +import { createPinia } from "pinia"; + +import App from "@/App.vue"; +import router from "./router"; + +const app = createApp(App); + +app.use(createPinia()); +app.use(router); + +app.mount("#app"); diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..a8358cd --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,15 @@ +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(import.meta.env.BASE_URL), + strict: true, + routes: [ + { + path: "/", + name: "Home", + component: () => import("@/views/helloworld/index.vue") + } + ] +}); + +export default router; diff --git a/src/views/helloworld/index.vue b/src/views/helloworld/index.vue new file mode 100644 index 0000000..58a3e8f --- /dev/null +++ b/src/views/helloworld/index.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..87eeb4f --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,15 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "noEmit": false, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ffadb15 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "strict": true, + "skipLibCheck": true, + "types": [ + "@cloudflare/workers-types/2023-07-01" + ] + } +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..5b8b8db --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "app/**/*", + ], + "compilerOptions": { + "composite": true, + "noEmit": false, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"], + } +} diff --git a/vite.config.d.ts b/vite.config.d.ts new file mode 100644 index 0000000..089eeef --- /dev/null +++ b/vite.config.d.ts @@ -0,0 +1,2 @@ +declare const _default: import("vite").UserConfigFnObject; +export default _default; diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..a8de01b --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,51 @@ +import { fileURLToPath, URL } from "node:url"; + +import { defineConfig } from "vite"; +import vue from "@vitejs/plugin-vue"; +import vueJsx from "@vitejs/plugin-vue-jsx"; +import pages from "@hono/vite-cloudflare-pages"; +import devServer from "@hono/vite-dev-server"; +import adapter from "@hono/vite-dev-server/cloudflare"; + +export default defineConfig(({ mode }) => { + if (mode === "client") { + return { + plugins: [vue(), vueJsx()], + resolve: { + alias: { + "@": fileURLToPath(new URL("./src", import.meta.url)) + } + }, + server: { + port: 3000, + proxy: { + "/api": { + target: "http://localhost:5173", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, "/api") + } + } + } + }; + } else { + return { + plugins: [ + pages(), + devServer({ + entry: "app/server.ts", + adapter + }) + ], + build: { + rollupOptions: { + input: "app/server.ts", + output: { + format: "es", + dir: "dist", + entryFileNames: "_worker.js" + } + } + } + }; + } +}); diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..48f4bd0 --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,3 @@ +name = "cloudflare-pages-demo" +compatibility_date = "2024-09-09" +main = "app/server.ts"