@ykdz/template 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. package/dist/cli.js +9 -6
  2. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/components/CounterButton.vue +1 -1
  3. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/components/PageShell.vue +1 -1
  4. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/pages/+config.ts +2 -2
  5. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/pages/index/+Page.vue +8 -8
  6. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/playwright.config.ts +2 -1
  7. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/test/e2e/app.spec.ts +9 -3
  8. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/test/todos.test.ts +7 -9
  9. package/node_modules/@ykdz/template-builtin-source/templates/vike-app/vite.config.ts +7 -0
  10. package/node_modules/@ykdz/template-builtin-source/templates/vue-app/index.html +2 -2
  11. package/node_modules/@ykdz/template-builtin-source/templates/vue-app/src/App.vue +8 -12
  12. package/node_modules/@ykdz/template-builtin-source/templates/vue-app/test/e2e/app.spec.ts +3 -3
  13. package/node_modules/@ykdz/template-builtin-source/templates/vue-hono-app/web/index.html +2 -2
  14. package/node_modules/@ykdz/template-builtin-source/templates/vue-hono-app/web/src/App.vue +10 -13
  15. package/node_modules/@ykdz/template-builtin-source/templates/vue-hono-app/web/test/e2e/app.spec.ts +4 -4
  16. package/node_modules/@ykdz/template-core/dist/projection-capabilities.js +4 -3
  17. package/package.json +3 -3
package/dist/cli.js CHANGED
@@ -29,15 +29,18 @@ function usage() {
29
29
  " template preset-source validate <path>",
30
30
  " template blueprint validate <path>",
31
31
  "",
32
- "Options:",
33
- " --preset <name> Project preset to generate",
32
+ "Init options:",
33
+ " --preset <name> Project preset to generate",
34
+ " --scope <name> Package scope for workspace package names",
35
+ " --yes Accept defaults for non-interactive generation",
36
+ " --dry-run Print the planned generation without writing files",
37
+ " --json Print machine-readable output",
38
+ "",
39
+ "Add package options:",
40
+ " --preset <name> Package preset to add",
34
41
  " --name <name> Package name to add",
35
42
  " --path <path> Two-segment Package Path to add",
36
43
  " --link-from <path> Existing consumer Package Path to link from; repeatable",
37
- " --scope <name> Package scope for workspace package names",
38
- " --yes Accept defaults for non-interactive generation",
39
- " --dry-run Print the planned generation without writing files",
40
- " --json Print machine-readable output",
41
44
  ].join("\n");
42
45
  }
43
46
  function printJson(value) {
@@ -16,6 +16,6 @@ onMounted(() => {
16
16
  :disabled="!mounted"
17
17
  @click="count += 1"
18
18
  >
19
- Count {{ count }}
19
+ 计数:{{ count }}
20
20
  </button>
21
21
  </template>
@@ -7,7 +7,7 @@ import logoUrl from "#/assets/logo.svg";
7
7
  <header class="border-b border-slate-200 bg-white">
8
8
  <nav class="mx-auto flex max-w-4xl items-center gap-3 px-6 py-4">
9
9
  <img :src="logoUrl" alt="" class="size-8" />
10
- <a href="/" class="font-semibold text-slate-950">Vike App</a>
10
+ <a href="/" class="font-semibold text-slate-950">Vike 应用</a>
11
11
  </nav>
12
12
  </header>
13
13
  <main class="mx-auto max-w-4xl px-6 py-10">
@@ -2,8 +2,8 @@ import vikeVue from "vike-vue/config";
2
2
  import type { Config } from "vike/types";
3
3
 
4
4
  const config: Config = {
5
- title: "Vike App",
6
- description: "Vike, Hono, Telefunc, Drizzle, and Vue.",
5
+ title: "Vike 应用",
6
+ description: "使用 Vike、Hono、Telefunc、Drizzle 和 Vue 的示例应用。",
7
7
  extends: [vikeVue],
8
8
  };
9
9
 
@@ -18,8 +18,8 @@ async function refreshTodos() {
18
18
  } catch (unknownError) {
19
19
  error.value =
20
20
  unknownError instanceof Error
21
- ? unknownError.message
22
- : "Unable to load todos";
21
+ ? `待办加载失败:${unknownError.message}`
22
+ : "无法加载待办事项";
23
23
  }
24
24
  }
25
25
 
@@ -41,10 +41,10 @@ async function submitTodo() {
41
41
  <p class="text-sm font-semibold tracking-wide text-rose-600 uppercase">
42
42
  Vike + Hono
43
43
  </p>
44
- <h1 class="text-4xl font-bold tracking-tight">Full-stack Vike app</h1>
44
+ <h1 class="text-4xl font-bold tracking-tight">全栈 Vike 应用</h1>
45
45
  <p class="max-w-2xl text-lg text-slate-700">
46
- Server-rendered Vue with Hono routing, Telefunc actions, and Drizzle
47
- database access.
46
+ 使用 Hono 路由、Telefunc 动作和 Drizzle 数据访问构建服务端渲染 Vue
47
+ 应用。
48
48
  </p>
49
49
  <CounterButton />
50
50
  </div>
@@ -54,10 +54,10 @@ async function submitTodo() {
54
54
  v-model="title"
55
55
  class="min-w-0 flex-1 rounded border border-slate-300 px-3 py-2"
56
56
  name="title"
57
- placeholder="Add a database-backed todo"
57
+ placeholder="添加一条数据库待办"
58
58
  />
59
59
  <button class="rounded bg-slate-950 px-4 py-2 text-white" type="submit">
60
- Add
60
+ 添加
61
61
  </button>
62
62
  </form>
63
63
 
@@ -66,7 +66,7 @@ async function submitTodo() {
66
66
  type="button"
67
67
  @click="refreshTodos"
68
68
  >
69
- Load todos
69
+ 加载待办事项
70
70
  </button>
71
71
 
72
72
  <p
@@ -9,7 +9,8 @@ export default defineConfig({
9
9
  trace: "on-first-retry",
10
10
  },
11
11
  webServer: {
12
- command: "PORT=4173 node dist/server/index.mjs",
12
+ command:
13
+ "DATABASE_FILE=./node_modules/.tmp/e2e.sqlite pnpm run db:push && DATABASE_FILE=./node_modules/.tmp/e2e.sqlite PORT=4173 node dist/server/index.mjs",
13
14
  reuseExistingServer: !process.env.CI,
14
15
  url: previewUrl,
15
16
  },
@@ -1,10 +1,16 @@
1
1
  import { expect, test } from "@playwright/test";
2
2
 
3
3
  test("renders the Vike home page", async ({ page }) => {
4
+ const todoTitle = `编写生成项目端到端测试 ${Date.now()}`;
5
+
4
6
  await page.goto("/");
5
7
  await expect(
6
- page.getByRole("heading", { name: "Full-stack Vike app" }),
8
+ page.getByRole("heading", { name: "全栈 Vike 应用" }),
7
9
  ).toBeVisible();
8
- await page.getByRole("button", { name: "Count 0" }).click();
9
- await expect(page.getByRole("button", { name: "Count 1" })).toBeVisible();
10
+ await page.getByRole("button", { name: "计数:0" }).click();
11
+ await expect(page.getByRole("button", { name: "计数:1" })).toBeVisible();
12
+
13
+ await page.getByPlaceholder("添加一条数据库待办").fill(todoTitle);
14
+ await page.getByRole("button", { name: "添加" }).click();
15
+ await expect(page.getByText(todoTitle)).toBeVisible();
10
16
  });
@@ -5,16 +5,14 @@ import { createTodo, listTodos } from "#/database/queries/todos";
5
5
 
6
6
  describe("todo queries", () => {
7
7
  it("creates and lists todos through Drizzle SQLite", async () => {
8
- const db = createDatabase(":memory:");
8
+ const db = createDatabase();
9
+ const title = `发布模板 ${Date.now()}`;
9
10
 
10
- db.run(
11
- "CREATE TABLE todos (id integer PRIMARY KEY AUTOINCREMENT NOT NULL, title text NOT NULL, completed integer DEFAULT false NOT NULL, created_at text DEFAULT (CURRENT_TIMESTAMP) NOT NULL)",
12
- );
13
-
14
- await expect(createTodo(db, { title: "Ship" })).resolves.toMatchObject({
15
- id: 1,
16
- title: "Ship",
11
+ await expect(createTodo(db, { title })).resolves.toMatchObject({
12
+ title,
17
13
  });
18
- await expect(listTodos(db)).resolves.toMatchObject([{ title: "Ship" }]);
14
+ await expect(listTodos(db)).resolves.toEqual(
15
+ expect.arrayContaining([expect.objectContaining({ title })]),
16
+ );
19
17
  });
20
18
  });
@@ -1,3 +1,5 @@
1
+ import { fileURLToPath, URL } from "node:url";
2
+
1
3
  import tailwindcss from "@tailwindcss/vite";
2
4
  import vue from "@vitejs/plugin-vue";
3
5
  import telefunc from "telefunc/vite";
@@ -9,4 +11,9 @@ const telefuncPlugin = telefunc() as PluginOption;
9
11
 
10
12
  export default defineConfig({
11
13
  plugins: [vike(), telefuncPlugin, vue(), tailwindcss()],
14
+ resolve: {
15
+ alias: {
16
+ "#": fileURLToPath(new URL(".", import.meta.url)),
17
+ },
18
+ },
12
19
  });
@@ -1,9 +1,9 @@
1
1
  <!doctype html>
2
- <html lang="en">
2
+ <html lang="zh-CN">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Vue App</title>
6
+ <title>Vue 应用</title>
7
7
  </head>
8
8
  <body>
9
9
  <div id="app"></div>
@@ -6,12 +6,12 @@ import { useCounterStore } from "#/stores/counter";
6
6
 
7
7
  const counter = useCounterStore();
8
8
  const { count } = storeToRefs(counter);
9
- const themeLabel = ref<"dark" | "light">("light");
9
+ const themeLabel = ref<"深色" | "浅色">("浅色");
10
10
 
11
11
  let preferredThemeQuery: MediaQueryList | undefined;
12
12
 
13
13
  function updateThemeLabel(event: MediaQueryList | MediaQueryListEvent): void {
14
- themeLabel.value = event.matches ? "dark" : "light";
14
+ themeLabel.value = event.matches ? "深色" : "浅色";
15
15
  }
16
16
 
17
17
  onMounted(() => {
@@ -31,14 +31,12 @@ onUnmounted(() => {
31
31
  class="mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-16"
32
32
  >
33
33
  <p class="text-sm font-medium tracking-wide text-cyan-300 uppercase">
34
- Vue app preset
34
+ Vue 应用预设
35
35
  </p>
36
- <h1 class="mt-4 text-4xl font-semibold">
37
- Vue, Vite, Tailwind, and Pinia
38
- </h1>
36
+ <h1 class="mt-4 text-4xl font-semibold">Vue、Vite、Tailwind 和 Pinia</h1>
39
37
  <p class="mt-4 text-lg text-slate-300">
40
- This generated app is ready for strict TypeScript checks, unit tests,
41
- and Playwright.
38
+ 这个生成的应用已经接入严格 TypeScript 检查、单元测试和 Playwright
39
+ 端到端测试。
42
40
  </p>
43
41
  <div class="mt-8 flex items-center gap-4">
44
42
  <button
@@ -46,11 +44,9 @@ onUnmounted(() => {
46
44
  type="button"
47
45
  @click="counter.increment()"
48
46
  >
49
- Count is {{ count }}
47
+ 计数:{{ count }}
50
48
  </button>
51
- <span class="text-sm text-slate-400"
52
- >Preferred theme: {{ themeLabel }}</span
53
- >
49
+ <span class="text-sm text-slate-400">系统主题:{{ themeLabel }}</span>
54
50
  </div>
55
51
  </section>
56
52
  </main>
@@ -4,11 +4,11 @@ test("renders and updates the counter", async ({ page }) => {
4
4
  await page.goto("/");
5
5
 
6
6
  await expect(
7
- page.getByRole("heading", { name: "Vue, Vite, Tailwind, and Pinia" }),
7
+ page.getByRole("heading", { name: "Vue、Vite、Tailwind 和 Pinia" }),
8
8
  ).toBeVisible();
9
- const counterButton = page.getByRole("button", { name: "Count is 0" });
9
+ const counterButton = page.getByRole("button", { name: "计数:0" });
10
10
 
11
11
  await expect(counterButton).toBeVisible();
12
12
  await counterButton.click({ force: true });
13
- await expect(page.getByRole("button", { name: "Count is 1" })).toBeVisible();
13
+ await expect(page.getByRole("button", { name: "计数:1" })).toBeVisible();
14
14
  });
@@ -1,9 +1,9 @@
1
1
  <!doctype html>
2
- <html lang="en">
2
+ <html lang="zh-CN">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Vue Hono app</title>
6
+ <title>Vue Hono 应用</title>
7
7
  </head>
8
8
  <body>
9
9
  <div id="app"></div>
@@ -7,13 +7,13 @@ import { useCounterStore } from "#/stores/counter";
7
7
 
8
8
  const counter = useCounterStore();
9
9
  const { count } = storeToRefs(counter);
10
- const themeLabel = ref<"dark" | "light">("light");
11
- const apiStatus = ref("checking");
10
+ const themeLabel = ref<"深色" | "浅色">("浅色");
11
+ const apiStatus = ref("检查中");
12
12
 
13
13
  let preferredThemeQuery: MediaQueryList | undefined;
14
14
 
15
15
  function updateThemeLabel(event: MediaQueryList | MediaQueryListEvent): void {
16
- themeLabel.value = event.matches ? "dark" : "light";
16
+ themeLabel.value = event.matches ? "深色" : "浅色";
17
17
  }
18
18
 
19
19
  onMounted(() => {
@@ -29,7 +29,7 @@ onUnmounted(() => {
29
29
  onMounted(async () => {
30
30
  const response = await api.api.health.$get();
31
31
  const body = await response.json();
32
- apiStatus.value = body.status;
32
+ apiStatus.value = body.status === "ok" ? "正常" : body.status;
33
33
  });
34
34
  </script>
35
35
 
@@ -39,12 +39,11 @@ onMounted(async () => {
39
39
  class="mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-16"
40
40
  >
41
41
  <p class="text-sm font-medium tracking-wide text-cyan-300 uppercase">
42
- Vue Hono app preset
42
+ Vue + Hono 应用预设
43
43
  </p>
44
- <h1 class="mt-4 text-4xl font-semibold">Vue, Hono, and typed RPC</h1>
44
+ <h1 class="mt-4 text-4xl font-semibold">Vue、Hono 和类型化 RPC</h1>
45
45
  <p class="mt-4 text-lg text-slate-300">
46
- This generated workspace typechecks the web package against the API
47
- contract.
46
+ 这个生成的工作区会让 Web 包根据 API 契约进行类型检查。
48
47
  </p>
49
48
  <div class="mt-8 flex flex-wrap items-center gap-4">
50
49
  <button
@@ -52,12 +51,10 @@ onMounted(async () => {
52
51
  type="button"
53
52
  @click="counter.increment()"
54
53
  >
55
- Count is {{ count }}
54
+ 计数:{{ count }}
56
55
  </button>
57
- <span class="text-sm text-slate-400"
58
- >Preferred theme: {{ themeLabel }}</span
59
- >
60
- <span class="text-sm text-slate-400">API status: {{ apiStatus }}</span>
56
+ <span class="text-sm text-slate-400">系统主题:{{ themeLabel }}</span>
57
+ <span class="text-sm text-slate-400">API 状态:{{ apiStatus }}</span>
61
58
  </div>
62
59
  </section>
63
60
  </main>
@@ -4,12 +4,12 @@ test("renders the web app and calls the API", async ({ page }) => {
4
4
  await page.goto("/");
5
5
 
6
6
  await expect(
7
- page.getByRole("heading", { name: "Vue, Hono, and typed RPC" }),
7
+ page.getByRole("heading", { name: "Vue、Hono 和类型化 RPC" }),
8
8
  ).toBeVisible();
9
- await expect(page.getByText("API status: ok")).toBeVisible();
10
- const counterButton = page.getByRole("button", { name: "Count is 0" });
9
+ await expect(page.getByText("API 状态:正常")).toBeVisible();
10
+ const counterButton = page.getByRole("button", { name: "计数:0" });
11
11
 
12
12
  await expect(counterButton).toBeVisible();
13
13
  await counterButton.click({ force: true });
14
- await expect(page.getByRole("button", { name: "Count is 1" })).toBeVisible();
14
+ await expect(page.getByRole("button", { name: "计数:1" })).toBeVisible();
15
15
  });
@@ -1545,7 +1545,8 @@ function nodePackageScripts(nodePackage, workspace) {
1545
1545
  if (nodePackage.kind === "vike-app") {
1546
1546
  return {
1547
1547
  "build:run": "vike build",
1548
- dev: "vike dev",
1548
+ dev: "pnpm run db:push && vike dev",
1549
+ "db:push": "mkdir -p data node_modules/.tmp && drizzle-kit push",
1549
1550
  "drizzle:generate": "drizzle-kit generate",
1550
1551
  "drizzle:migrate": "drizzle-kit migrate",
1551
1552
  "drizzle:studio": "drizzle-kit studio",
@@ -1553,9 +1554,9 @@ function nodePackageScripts(nodePackage, workspace) {
1553
1554
  "format:write:run": "oxfmt --write --config ../../oxfmt.config.ts .",
1554
1555
  "lint:run": "oxlint --type-aware --config ../../oxlint.config.ts .",
1555
1556
  "lint:fix:run": "oxlint --type-aware --config ../../oxlint.config.ts . --fix",
1556
- preview: "vike preview",
1557
+ preview: "pnpm run db:push && vike preview",
1557
1558
  start: "node ./dist/server/index.mjs",
1558
- "test:run": "vitest run",
1559
+ "test:run": "DATABASE_FILE=./node_modules/.tmp/test.sqlite pnpm run db:push && DATABASE_FILE=./node_modules/.tmp/test.sqlite vitest run",
1559
1560
  "test:e2e:run": "playwright test --config playwright.config.ts",
1560
1561
  "typecheck:run": "vue-tsc --build --noEmit",
1561
1562
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ykdz/template",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "private": false,
5
5
  "description": "Project template generator for YKDZ starter projects.",
6
6
  "keywords": [
@@ -35,8 +35,8 @@
35
35
  "typescript": "^6.0.3",
36
36
  "valibot": "^1.4.2",
37
37
  "@ykdz/template-builtin-source": "0.0.0",
38
- "@ykdz/template-shared": "0.0.0",
39
- "@ykdz/template-core": "0.0.0"
38
+ "@ykdz/template-core": "0.0.0",
39
+ "@ykdz/template-shared": "0.0.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^24.0.0",