@ykdz/template 0.0.0

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +353 -0
  6. package/dist/declarations.d.ts +166 -0
  7. package/dist/declarations.d.ts.map +1 -0
  8. package/dist/declarations.js +340 -0
  9. package/dist/hono-api.d.ts +2 -0
  10. package/dist/hono-api.d.ts.map +1 -0
  11. package/dist/hono-api.js +247 -0
  12. package/dist/package-addition.d.ts +7 -0
  13. package/dist/package-addition.d.ts.map +1 -0
  14. package/dist/package-addition.js +580 -0
  15. package/dist/renderer.d.ts +44 -0
  16. package/dist/renderer.d.ts.map +1 -0
  17. package/dist/renderer.js +379 -0
  18. package/dist/rust-bin.d.ts +2 -0
  19. package/dist/rust-bin.d.ts.map +1 -0
  20. package/dist/rust-bin.js +206 -0
  21. package/dist/ts-lib.d.ts +2 -0
  22. package/dist/ts-lib.d.ts.map +1 -0
  23. package/dist/ts-lib.js +220 -0
  24. package/dist/vue-app.d.ts +2 -0
  25. package/dist/vue-app.d.ts.map +1 -0
  26. package/dist/vue-app.js +339 -0
  27. package/dist/vue-hono-app.d.ts +4 -0
  28. package/dist/vue-hono-app.d.ts.map +1 -0
  29. package/dist/vue-hono-app.js +484 -0
  30. package/package.json +54 -0
  31. package/templates/hono-api/src/app.ts +5 -0
  32. package/templates/hono-api/src/server.ts +14 -0
  33. package/templates/hono-api/test/app.test.ts +10 -0
  34. package/templates/hono-api/vitest.config.ts +13 -0
  35. package/templates/rust-bin/src/main.rs +18 -0
  36. package/templates/ts-lib/src/index.ts +7 -0
  37. package/templates/vue-app/env.d.ts +1 -0
  38. package/templates/vue-app/index.html +12 -0
  39. package/templates/vue-app/playwright.config.ts +20 -0
  40. package/templates/vue-app/src/App.vue +33 -0
  41. package/templates/vue-app/src/main.ts +6 -0
  42. package/templates/vue-app/src/stores/counter.ts +12 -0
  43. package/templates/vue-app/src/style.css +1 -0
  44. package/templates/vue-app/test/app.test.ts +13 -0
  45. package/templates/vue-app/test/e2e/app.spec.ts +9 -0
  46. package/templates/vue-app/vite.config.ts +13 -0
  47. package/templates/vue-app/vitest.config.ts +14 -0
  48. package/templates/vue-hono-app/api/src/index.ts +3 -0
  49. package/templates/vue-hono-app/api/src/runtime.ts +5 -0
  50. package/templates/vue-hono-app/api/src/server.ts +14 -0
  51. package/templates/vue-hono-app/api/test/app.test.ts +10 -0
  52. package/templates/vue-hono-app/api/vitest.config.ts +7 -0
  53. package/templates/vue-hono-app/web/env.d.ts +9 -0
  54. package/templates/vue-hono-app/web/index.html +12 -0
  55. package/templates/vue-hono-app/web/playwright.config.ts +21 -0
  56. package/templates/vue-hono-app/web/src/App.vue +42 -0
  57. package/templates/vue-hono-app/web/src/api.ts +8 -0
  58. package/templates/vue-hono-app/web/src/main.ts +6 -0
  59. package/templates/vue-hono-app/web/src/stores/counter.ts +12 -0
  60. package/templates/vue-hono-app/web/src/style.css +1 -0
  61. package/templates/vue-hono-app/web/test/app.test.ts +13 -0
  62. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +10 -0
  63. package/templates/vue-hono-app/web/vite.config.ts +29 -0
  64. package/templates/vue-hono-app/web/vitest.config.ts +16 -0
@@ -0,0 +1,484 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { renderNewProject } from "./renderer.js";
4
+ const features = [
5
+ "pnpm-catalog",
6
+ "oxc-format-lint",
7
+ "strict-typescript",
8
+ "root-check",
9
+ "fix-command",
10
+ "devcontainer",
11
+ "github-actions",
12
+ "dependabot"
13
+ ];
14
+ const generatedBy = {
15
+ packageName: "@ykdz/template",
16
+ version: "0.0.0",
17
+ command: "template init --preset vue-hono-app"
18
+ };
19
+ function projectNameFromDir(targetDir) {
20
+ return path.basename(path.resolve(targetDir));
21
+ }
22
+ function packageName(packageScope, leaf) {
23
+ return `@${packageScope}/${leaf}`;
24
+ }
25
+ function workspacePackageFilter(packageScope, leaf) {
26
+ return `--filter ${packageName(packageScope, leaf)}`;
27
+ }
28
+ function rootPackageJson(projectName) {
29
+ return {
30
+ name: projectName,
31
+ version: "0.0.0",
32
+ private: true,
33
+ type: "module",
34
+ scripts: {
35
+ check: "turbo run check",
36
+ dev: "turbo run dev --parallel",
37
+ fix: "turbo run fix"
38
+ },
39
+ devDependencies: {
40
+ turbo: "catalog:"
41
+ },
42
+ engines: {
43
+ node: ">=22.0.0"
44
+ },
45
+ packageManager: "pnpm@10.0.0"
46
+ };
47
+ }
48
+ function apiPackageJson(packageScope) {
49
+ return {
50
+ name: packageName(packageScope, "api"),
51
+ version: "0.0.0",
52
+ private: true,
53
+ type: "module",
54
+ types: "./dist/index.d.ts",
55
+ exports: {
56
+ ".": "./dist/index.js"
57
+ },
58
+ scripts: {
59
+ build: "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
60
+ check: "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test",
61
+ dev: "tsx watch src/server.ts",
62
+ fix: "pnpm run format:write && pnpm run lint:fix",
63
+ "format:check": "oxfmt --check .",
64
+ "format:write": "oxfmt --write .",
65
+ lint: "oxlint . --deny-warnings",
66
+ "lint:fix": "oxlint . --fix --deny-warnings",
67
+ start: "node dist/server.js",
68
+ test: "vitest run",
69
+ typecheck: "tsc -p tsconfig.json --noEmit"
70
+ },
71
+ dependencies: {
72
+ "@hono/node-server": "catalog:",
73
+ hono: "catalog:"
74
+ },
75
+ devDependencies: {
76
+ "@types/node": "catalog:",
77
+ oxfmt: "catalog:",
78
+ oxlint: "catalog:",
79
+ "tsc-alias": "catalog:",
80
+ tsx: "catalog:",
81
+ typescript: "catalog:",
82
+ vitest: "catalog:"
83
+ },
84
+ engines: {
85
+ node: ">=22.0.0"
86
+ }
87
+ };
88
+ }
89
+ function webPackageJson(packageScope) {
90
+ return {
91
+ name: packageName(packageScope, "web"),
92
+ version: "0.0.0",
93
+ private: true,
94
+ type: "module",
95
+ scripts: {
96
+ build: "vite build",
97
+ check: "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run build && pnpm run test && pnpm run test:e2e",
98
+ dev: "vite",
99
+ fix: "pnpm run format:write && pnpm run lint:fix",
100
+ "format:check": "oxfmt --check .",
101
+ "format:write": "oxfmt --write .",
102
+ lint: "oxlint . --deny-warnings",
103
+ "lint:fix": "oxlint . --fix --deny-warnings",
104
+ preview: "vite preview",
105
+ test: "vitest run",
106
+ "test:e2e": "pnpm run build && playwright test",
107
+ typecheck: "vue-tsc --build"
108
+ },
109
+ dependencies: {
110
+ [packageName(packageScope, "api")]: "workspace:*",
111
+ "@vueuse/core": "catalog:",
112
+ hono: "catalog:",
113
+ pinia: "catalog:",
114
+ vue: "catalog:"
115
+ },
116
+ devDependencies: {
117
+ "@playwright/test": "catalog:",
118
+ "@tailwindcss/vite": "catalog:",
119
+ "@types/node": "catalog:",
120
+ "@types/web-bluetooth": "catalog:",
121
+ "@vitejs/plugin-vue": "catalog:",
122
+ "@vue/tsconfig": "catalog:",
123
+ oxfmt: "catalog:",
124
+ oxlint: "catalog:",
125
+ tailwindcss: "catalog:",
126
+ typescript: "catalog:",
127
+ vite: "catalog:",
128
+ vitest: "catalog:",
129
+ "vue-tsc": "catalog:"
130
+ },
131
+ engines: {
132
+ node: ">=22.0.0"
133
+ }
134
+ };
135
+ }
136
+ function operationsForVueHonoApp(projectName, packageScope) {
137
+ const apiName = packageName(packageScope, "api");
138
+ const webName = packageName(packageScope, "web");
139
+ const webFilter = workspacePackageFilter(packageScope, "web");
140
+ return [
141
+ { kind: "writeJson", to: "package.json", value: rootPackageJson(projectName) },
142
+ {
143
+ kind: "writeText",
144
+ to: "pnpm-workspace.yaml",
145
+ text: [
146
+ "packages:",
147
+ " - apps/*",
148
+ "",
149
+ "allowBuilds:",
150
+ " esbuild: true",
151
+ "",
152
+ "catalog:",
153
+ ' "@hono/node-server": ^2.0.6',
154
+ ' "@playwright/test": ^1.57.0',
155
+ ' "@tailwindcss/vite": ^4.1.18',
156
+ ' "@types/node": ^24.0.0',
157
+ ' "@types/web-bluetooth": ^0.0.21',
158
+ ' "@vitejs/plugin-vue": ^6.0.2',
159
+ ' "@vue/tsconfig": ^0.8.1',
160
+ ' "@vueuse/core": ^14.1.0',
161
+ " hono: ^4.12.27",
162
+ " oxfmt: ^0.56.0",
163
+ " oxlint: ^1.71.0",
164
+ " pinia: ^3.0.4",
165
+ " tailwindcss: ^4.1.18",
166
+ " tsc-alias: ^1.8.17",
167
+ " tsx: ^4.20.0",
168
+ " turbo: ^2.7.0",
169
+ " typescript: ^5.8.0",
170
+ " vite: ^7.3.0",
171
+ " vitest: ^4.1.9",
172
+ " vue: ^3.5.26",
173
+ " vue-tsc: ^3.1.8",
174
+ ""
175
+ ].join("\n")
176
+ },
177
+ {
178
+ kind: "writeJson",
179
+ to: "turbo.json",
180
+ value: {
181
+ tasks: {
182
+ build: {
183
+ dependsOn: ["^build"],
184
+ outputs: ["dist/**"]
185
+ },
186
+ check: {
187
+ dependsOn: ["^build"]
188
+ },
189
+ dev: {
190
+ cache: false,
191
+ persistent: true
192
+ },
193
+ fix: {
194
+ cache: false
195
+ }
196
+ }
197
+ }
198
+ },
199
+ {
200
+ kind: "writeJson",
201
+ to: "tsconfig.json",
202
+ value: {
203
+ files: [],
204
+ references: [
205
+ { path: "./apps/api/tsconfig.json" },
206
+ { path: "./apps/web/tsconfig.app.json" },
207
+ { path: "./apps/web/tsconfig.test.json" },
208
+ { path: "./apps/web/tsconfig.node.json" }
209
+ ]
210
+ }
211
+ },
212
+ {
213
+ kind: "writeJson",
214
+ to: ".project-kit/blueprint.json",
215
+ value: {
216
+ schemaVersion: 1,
217
+ preset: "vue-hono-app",
218
+ packageManager: "pnpm",
219
+ projectKind: "multi-package",
220
+ features,
221
+ packages: [
222
+ { name: webName, path: "apps/web" },
223
+ { name: apiName, path: "apps/api" }
224
+ ]
225
+ }
226
+ },
227
+ {
228
+ kind: "writeJson",
229
+ to: ".project-kit/generated-by.json",
230
+ value: generatedBy
231
+ },
232
+ {
233
+ kind: "writeJson",
234
+ to: ".devcontainer/devcontainer.json",
235
+ value: {
236
+ name: `${projectName} full-stack development`,
237
+ image: "mcr.microsoft.com/devcontainers/typescript-node:22",
238
+ postCreateCommand: `corepack enable && pnpm install && pnpm ${webFilter} exec playwright install chromium`,
239
+ customizations: {
240
+ vscode: {
241
+ extensions: ["Vue.volar", "oxc.oxc-vscode"]
242
+ }
243
+ }
244
+ }
245
+ },
246
+ {
247
+ kind: "writeText",
248
+ to: ".gitignore",
249
+ text: ["node_modules", "dist", "playwright-report", "test-results", ".env", ""].join("\n")
250
+ },
251
+ {
252
+ kind: "writeText",
253
+ to: ".github/workflows/check.yml",
254
+ text: [
255
+ "name: Check",
256
+ "",
257
+ "on:",
258
+ " pull_request:",
259
+ " push:",
260
+ " branches:",
261
+ " - main",
262
+ "",
263
+ "jobs:",
264
+ " check:",
265
+ " runs-on: ubuntu-latest",
266
+ " steps:",
267
+ " - uses: actions/checkout@v4",
268
+ " - uses: pnpm/action-setup@v4",
269
+ " with:",
270
+ " version: 10.0.0",
271
+ " - uses: actions/setup-node@v4",
272
+ " with:",
273
+ " node-version: 22",
274
+ " - run: pnpm install",
275
+ ` - run: pnpm ${webFilter} exec playwright install --with-deps chromium`,
276
+ " - run: pnpm run check",
277
+ ""
278
+ ].join("\n")
279
+ },
280
+ {
281
+ kind: "writeText",
282
+ to: ".github/dependabot.yml",
283
+ text: [
284
+ "version: 2",
285
+ "updates:",
286
+ " - package-ecosystem: npm",
287
+ " directory: /",
288
+ " schedule:",
289
+ " interval: weekly",
290
+ " - package-ecosystem: github-actions",
291
+ " directory: /",
292
+ " schedule:",
293
+ " interval: weekly",
294
+ ""
295
+ ].join("\n")
296
+ },
297
+ { kind: "writeJson", to: "apps/api/package.json", value: apiPackageJson(packageScope) },
298
+ {
299
+ kind: "writeJson",
300
+ to: "apps/api/tsconfig.json",
301
+ value: {
302
+ compilerOptions: {
303
+ composite: true,
304
+ declaration: true,
305
+ declarationMap: true,
306
+ module: "NodeNext",
307
+ moduleResolution: "NodeNext",
308
+ noEmitOnError: true,
309
+ paths: {
310
+ "@/*": ["./src/*"]
311
+ },
312
+ skipLibCheck: false,
313
+ strict: true,
314
+ target: "ES2022",
315
+ types: ["node", "vitest/globals"]
316
+ },
317
+ include: ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts"]
318
+ }
319
+ },
320
+ {
321
+ kind: "writeJson",
322
+ to: "apps/api/tsconfig.build.json",
323
+ value: {
324
+ extends: "./tsconfig.json",
325
+ compilerOptions: {
326
+ outDir: "dist",
327
+ rootDir: "src",
328
+ types: ["node"]
329
+ },
330
+ include: ["src/**/*.ts"]
331
+ }
332
+ },
333
+ {
334
+ kind: "writeJson",
335
+ to: "apps/api/.oxlintrc.json",
336
+ value: {
337
+ categories: {
338
+ correctness: "error",
339
+ suspicious: "error"
340
+ },
341
+ plugins: ["typescript", "oxc"]
342
+ }
343
+ },
344
+ {
345
+ kind: "writeJson",
346
+ to: "apps/api/.oxfmtrc.json",
347
+ value: {
348
+ printWidth: 100,
349
+ singleQuote: false,
350
+ trailingComma: "none"
351
+ }
352
+ },
353
+ { kind: "copyFile", from: "api/src/index.ts", to: "apps/api/src/index.ts" },
354
+ { kind: "copyFile", from: "api/src/runtime.ts", to: "apps/api/src/runtime.ts" },
355
+ { kind: "copyFile", from: "api/src/server.ts", to: "apps/api/src/server.ts" },
356
+ { kind: "copyFile", from: "api/test/app.test.ts", to: "apps/api/test/app.test.ts" },
357
+ { kind: "copyFile", from: "api/vitest.config.ts", to: "apps/api/vitest.config.ts" },
358
+ { kind: "writeJson", to: "apps/web/package.json", value: webPackageJson(packageScope) },
359
+ {
360
+ kind: "writeJson",
361
+ to: "apps/web/tsconfig.json",
362
+ value: {
363
+ files: [],
364
+ references: [
365
+ { path: "./tsconfig.app.json" },
366
+ { path: "./tsconfig.test.json" },
367
+ { path: "./tsconfig.node.json" }
368
+ ]
369
+ }
370
+ },
371
+ {
372
+ kind: "writeJson",
373
+ to: "apps/web/tsconfig.app.json",
374
+ value: {
375
+ extends: "@vue/tsconfig/tsconfig.dom.json",
376
+ compilerOptions: {
377
+ baseUrl: ".",
378
+ composite: true,
379
+ module: "ESNext",
380
+ moduleResolution: "Bundler",
381
+ noEmitOnError: true,
382
+ paths: {
383
+ "@/*": ["./src/*"],
384
+ [apiName]: ["../api/src/index.ts"]
385
+ },
386
+ skipLibCheck: false,
387
+ strict: true,
388
+ target: "ES2022",
389
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
390
+ types: ["web-bluetooth"]
391
+ },
392
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue"],
393
+ references: [{ path: "../api/tsconfig.build.json" }]
394
+ }
395
+ },
396
+ {
397
+ kind: "writeJson",
398
+ to: "apps/web/tsconfig.test.json",
399
+ value: {
400
+ extends: "./tsconfig.app.json",
401
+ compilerOptions: {
402
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
403
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.test.tsbuildinfo",
404
+ types: ["node", "vitest/globals", "web-bluetooth"]
405
+ },
406
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue", "test/**/*.ts"],
407
+ references: [{ path: "../api/tsconfig.build.json" }]
408
+ }
409
+ },
410
+ {
411
+ kind: "writeJson",
412
+ to: "apps/web/tsconfig.node.json",
413
+ value: {
414
+ compilerOptions: {
415
+ composite: true,
416
+ module: "ESNext",
417
+ moduleResolution: "Bundler",
418
+ noEmitOnError: true,
419
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
420
+ outDir: "./node_modules/.tmp/tsconfig.node",
421
+ skipLibCheck: false,
422
+ strict: true,
423
+ target: "ES2022",
424
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
425
+ types: ["node"]
426
+ },
427
+ include: ["playwright.config.ts", "vite.config.ts", "vitest.config.ts"]
428
+ }
429
+ },
430
+ {
431
+ kind: "writeJson",
432
+ to: "apps/web/.oxlintrc.json",
433
+ value: {
434
+ categories: {
435
+ correctness: "error",
436
+ suspicious: "error"
437
+ },
438
+ plugins: ["typescript", "oxc", "vue"]
439
+ }
440
+ },
441
+ {
442
+ kind: "writeJson",
443
+ to: "apps/web/.oxfmtrc.json",
444
+ value: {
445
+ printWidth: 100,
446
+ singleQuote: false,
447
+ trailingComma: "none"
448
+ }
449
+ },
450
+ { kind: "copyFile", from: "web/env.d.ts", to: "apps/web/env.d.ts" },
451
+ { kind: "copyFile", from: "web/index.html", to: "apps/web/index.html" },
452
+ { kind: "copyFile", from: "web/playwright.config.ts", to: "apps/web/playwright.config.ts" },
453
+ { kind: "copyFile", from: "web/vite.config.ts", to: "apps/web/vite.config.ts" },
454
+ { kind: "copyFile", from: "web/vitest.config.ts", to: "apps/web/vitest.config.ts" },
455
+ { kind: "copyFile", from: "web/src/api.ts", to: "apps/web/src/api.ts" },
456
+ {
457
+ kind: "replaceAnchors",
458
+ path: "apps/web/src/api.ts",
459
+ language: "typescript",
460
+ replacements: {
461
+ "api-type-import-start": `import type { AppType } from "${apiName}";\n/*`,
462
+ "api-type-import-end": "*/"
463
+ }
464
+ },
465
+ { kind: "copyFile", from: "web/src/App.vue", to: "apps/web/src/App.vue" },
466
+ { kind: "copyFile", from: "web/src/main.ts", to: "apps/web/src/main.ts" },
467
+ { kind: "copyFile", from: "web/src/style.css", to: "apps/web/src/style.css" },
468
+ { kind: "copyFile", from: "web/src/stores/counter.ts", to: "apps/web/src/stores/counter.ts" },
469
+ { kind: "copyFile", from: "web/test/app.test.ts", to: "apps/web/test/app.test.ts" },
470
+ { kind: "copyFile", from: "web/test/e2e/app.spec.ts", to: "apps/web/test/e2e/app.spec.ts" }
471
+ ];
472
+ }
473
+ function templateSourceRoot() {
474
+ return path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "templates", "vue-hono-app");
475
+ }
476
+ export async function initVueHonoAppProject(targetDir, options = {}) {
477
+ const projectName = projectNameFromDir(targetDir);
478
+ const packageScope = options.scope ?? projectName;
479
+ await renderNewProject({
480
+ sourceRoot: templateSourceRoot(),
481
+ targetRoot: targetDir,
482
+ operations: operationsForVueHonoApp(projectName, packageScope)
483
+ });
484
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@ykdz/template",
3
+ "version": "0.0.0",
4
+ "description": "Project template generator for YKDZ starter projects.",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "bin": {
9
+ "template": "dist/cli.js"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/YKDZ/template.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/YKDZ/template/issues"
20
+ },
21
+ "homepage": "https://github.com/YKDZ/template#readme",
22
+ "keywords": [
23
+ "cli",
24
+ "project-template",
25
+ "starter"
26
+ ],
27
+ "files": [
28
+ "dist",
29
+ "templates"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.build.json",
33
+ "prepack": "pnpm run build",
34
+ "check": "pnpm run typecheck && pnpm run test && pnpm run check:fixtures",
35
+ "check:fixtures": "tsx scripts/check-fixtures.ts",
36
+ "fix": "pnpm run build",
37
+ "typecheck": "tsc -p tsconfig.json --noEmit",
38
+ "test": "vitest run"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^24.0.0",
42
+ "execa": "^9.6.0",
43
+ "tsx": "^4.20.0",
44
+ "vitest": "^3.2.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=22.0.0"
48
+ },
49
+ "packageManager": "pnpm@11.8.0",
50
+ "dependencies": {
51
+ "typescript": "^5.8.0",
52
+ "valibot": "^1.4.2"
53
+ }
54
+ }
@@ -0,0 +1,5 @@
1
+ import { Hono } from "hono";
2
+
3
+ export const app = new Hono();
4
+
5
+ app.get("/health", (context) => context.json({ status: "ok" }));
@@ -0,0 +1,14 @@
1
+ import { serve } from "@hono/node-server";
2
+ import { app } from "@/app.js";
3
+
4
+ const port = Number.parseInt(process.env.PORT ?? "3000", 10);
5
+
6
+ serve(
7
+ {
8
+ fetch: app.fetch,
9
+ port
10
+ },
11
+ (info) => {
12
+ console.log(`Hono API listening on http://localhost:${info.port}`);
13
+ }
14
+ );
@@ -0,0 +1,10 @@
1
+ import { app } from "@/app.js";
2
+
3
+ describe("Hono API", () => {
4
+ it("responds to the health route", async () => {
5
+ const response = await app.request("/health");
6
+
7
+ expect(response.status).toBe(200);
8
+ await expect(response.json()).resolves.toEqual({ status: "ok" });
9
+ });
10
+ });
@@ -0,0 +1,13 @@
1
+ import { fileURLToPath, URL } from "node:url";
2
+ import { defineConfig } from "vitest/config";
3
+
4
+ export default defineConfig({
5
+ resolve: {
6
+ alias: {
7
+ "@": fileURLToPath(new URL("./src", import.meta.url))
8
+ }
9
+ },
10
+ test: {
11
+ globals: true
12
+ }
13
+ });
@@ -0,0 +1,18 @@
1
+ fn greeting() -> String {
2
+ format!("Hello from {}", env!("CARGO_PKG_NAME"))
3
+ }
4
+
5
+ fn main() {
6
+ println!("{}", greeting());
7
+ }
8
+
9
+ #[cfg(test)]
10
+ mod tests {
11
+ #[test]
12
+ fn greeting_names_package() {
13
+ assert_eq!(
14
+ super::greeting(),
15
+ format!("Hello from {}", env!("CARGO_PKG_NAME"))
16
+ );
17
+ }
18
+ }
@@ -0,0 +1,7 @@
1
+ export type Greeting = {
2
+ message: string;
3
+ };
4
+
5
+ export function greet(name: string): Greeting {
6
+ return { message: `Hello, ${name}` };
7
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Vue App</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.ts"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,20 @@
1
+ import { defineConfig, devices } from "@playwright/test";
2
+
3
+ export default defineConfig({
4
+ testDir: "./test/e2e",
5
+ use: {
6
+ baseURL: "http://127.0.0.1:4173",
7
+ trace: "on-first-retry"
8
+ },
9
+ webServer: {
10
+ command: "pnpm run preview --host 127.0.0.1 --port 4173",
11
+ reuseExistingServer: !process.env.CI,
12
+ url: "http://127.0.0.1:4173"
13
+ },
14
+ projects: [
15
+ {
16
+ name: "chromium",
17
+ use: { ...devices["Desktop Chrome"] }
18
+ }
19
+ ]
20
+ });
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ import { usePreferredDark } from "@vueuse/core";
3
+ import { storeToRefs } from "pinia";
4
+ import { computed } from "vue";
5
+ import { useCounterStore } from "@/stores/counter";
6
+
7
+ const counter = useCounterStore();
8
+ const { count } = storeToRefs(counter);
9
+ const prefersDark = usePreferredDark();
10
+ const themeLabel = computed(() => (prefersDark.value ? "dark" : "light"));
11
+ </script>
12
+
13
+ <template>
14
+ <main class="min-h-screen bg-slate-950 text-white">
15
+ <section class="mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-16">
16
+ <p class="text-sm font-medium uppercase tracking-wide text-cyan-300">Vue app preset</p>
17
+ <h1 class="mt-4 text-4xl font-semibold">Vue, Vite, Tailwind, and Pinia</h1>
18
+ <p class="mt-4 text-lg text-slate-300">
19
+ This generated app is ready for strict TypeScript checks, unit tests, and Playwright.
20
+ </p>
21
+ <div class="mt-8 flex items-center gap-4">
22
+ <button
23
+ class="rounded bg-cyan-300 px-4 py-2 font-semibold text-slate-950 hover:bg-cyan-200"
24
+ type="button"
25
+ @click="counter.increment()"
26
+ >
27
+ Count is {{ count }}
28
+ </button>
29
+ <span class="text-sm text-slate-400">Preferred theme: {{ themeLabel }}</span>
30
+ </div>
31
+ </section>
32
+ </main>
33
+ </template>