@ykdz/template 0.0.2 → 0.0.3

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 (102) hide show
  1. package/dist/src/cli.d.ts.map +1 -0
  2. package/dist/{cli.js → src/cli.js} +77 -56
  3. package/dist/{declarations.d.ts → src/declarations.d.ts} +1 -2
  4. package/dist/src/declarations.d.ts.map +1 -0
  5. package/dist/{declarations.js → src/declarations.js} +2 -109
  6. package/dist/src/dependency-catalog.d.ts +10 -0
  7. package/dist/src/dependency-catalog.d.ts.map +1 -0
  8. package/dist/src/dependency-catalog.js +63 -0
  9. package/dist/{devcontainer.d.ts → src/devcontainer.d.ts} +1 -0
  10. package/dist/src/devcontainer.d.ts.map +1 -0
  11. package/dist/{devcontainer.js → src/devcontainer.js} +1 -0
  12. package/dist/src/editor-customization.d.ts +13 -0
  13. package/dist/src/editor-customization.d.ts.map +1 -0
  14. package/dist/src/editor-customization.js +101 -0
  15. package/dist/{generation-context.d.ts → src/generation-context.d.ts} +2 -2
  16. package/dist/src/generation-context.d.ts.map +1 -0
  17. package/dist/{module-graph.d.ts → src/module-graph.d.ts} +0 -14
  18. package/dist/src/module-graph.d.ts.map +1 -0
  19. package/dist/src/module-graph.js +48 -0
  20. package/dist/{next-step-instructions.d.ts → src/next-step-instructions.d.ts} +2 -3
  21. package/dist/src/next-step-instructions.d.ts.map +1 -0
  22. package/dist/{next-step-instructions.js → src/next-step-instructions.js} +14 -24
  23. package/dist/src/package-addition.d.ts.map +1 -0
  24. package/dist/src/package-addition.js +188 -0
  25. package/dist/src/preset-projection.d.ts +66 -0
  26. package/dist/src/preset-projection.d.ts.map +1 -0
  27. package/dist/src/preset-projection.js +7 -0
  28. package/dist/{project-github.d.ts → src/project-github.d.ts} +0 -7
  29. package/dist/src/project-github.d.ts.map +1 -0
  30. package/dist/{project-github.js → src/project-github.js} +3 -36
  31. package/dist/src/renderer.d.ts.map +1 -0
  32. package/dist/src/runtime-paths.d.ts +2 -0
  33. package/dist/src/runtime-paths.d.ts.map +1 -0
  34. package/dist/src/runtime-paths.js +11 -0
  35. package/dist/src/toolchain-resolution.d.ts.map +1 -0
  36. package/dist/{toolchain-resolution.js → src/toolchain-resolution.js} +1 -1
  37. package/dist/templates/hono-api/projection.d.ts +7 -0
  38. package/dist/templates/hono-api/projection.d.ts.map +1 -0
  39. package/dist/templates/hono-api/projection.js +377 -0
  40. package/dist/templates/projection-plans.d.ts +8 -0
  41. package/dist/templates/projection-plans.d.ts.map +1 -0
  42. package/dist/templates/projection-plans.js +94 -0
  43. package/dist/templates/registry.d.ts +8 -0
  44. package/dist/templates/registry.d.ts.map +1 -0
  45. package/dist/templates/registry.js +42 -0
  46. package/dist/templates/rust-bin/projection.d.ts +10 -0
  47. package/dist/templates/rust-bin/projection.d.ts.map +1 -0
  48. package/dist/templates/rust-bin/projection.js +282 -0
  49. package/dist/templates/ts-lib/projection.d.ts +7 -0
  50. package/dist/templates/ts-lib/projection.d.ts.map +1 -0
  51. package/dist/templates/ts-lib/projection.js +372 -0
  52. package/dist/templates/vue-app/projection.d.ts +7 -0
  53. package/dist/templates/vue-app/projection.d.ts.map +1 -0
  54. package/dist/templates/vue-app/projection.js +594 -0
  55. package/dist/templates/vue-hono-app/projection.d.ts +9 -0
  56. package/dist/templates/vue-hono-app/projection.d.ts.map +1 -0
  57. package/dist/{vue-hono-app.js → templates/vue-hono-app/projection.js} +250 -101
  58. package/package.json +29 -24
  59. package/pnpm-workspace.yaml +34 -0
  60. package/templates/hono-api/projection.ts +453 -0
  61. package/templates/projection-plans.ts +135 -0
  62. package/templates/registry.ts +59 -0
  63. package/templates/rust-bin/projection.ts +346 -0
  64. package/templates/ts-lib/projection.ts +454 -0
  65. package/templates/vue-app/projection.ts +687 -0
  66. package/templates/vue-app/test/e2e/app.spec.ts +4 -1
  67. package/templates/vue-hono-app/projection.ts +669 -0
  68. package/templates/vue-hono-app/web/test/e2e/app.spec.ts +4 -1
  69. package/dist/cli.d.ts.map +0 -1
  70. package/dist/declarations.d.ts.map +0 -1
  71. package/dist/devcontainer.d.ts.map +0 -1
  72. package/dist/generation-context.d.ts.map +0 -1
  73. package/dist/hono-api.d.ts +0 -3
  74. package/dist/hono-api.d.ts.map +0 -1
  75. package/dist/hono-api.js +0 -210
  76. package/dist/module-graph.d.ts.map +0 -1
  77. package/dist/module-graph.js +0 -187
  78. package/dist/next-step-instructions.d.ts.map +0 -1
  79. package/dist/package-addition.d.ts.map +0 -1
  80. package/dist/package-addition.js +0 -560
  81. package/dist/project-github.d.ts.map +0 -1
  82. package/dist/renderer.d.ts.map +0 -1
  83. package/dist/rust-bin.d.ts +0 -8
  84. package/dist/rust-bin.d.ts.map +0 -1
  85. package/dist/rust-bin.js +0 -208
  86. package/dist/toolchain-resolution.d.ts.map +0 -1
  87. package/dist/ts-lib.d.ts +0 -8
  88. package/dist/ts-lib.d.ts.map +0 -1
  89. package/dist/ts-lib.js +0 -214
  90. package/dist/vue-app.d.ts +0 -3
  91. package/dist/vue-app.d.ts.map +0 -1
  92. package/dist/vue-app.js +0 -301
  93. package/dist/vue-hono-app.d.ts +0 -7
  94. package/dist/vue-hono-app.d.ts.map +0 -1
  95. package/templates/shared/oxc/package.json +0 -18
  96. package/templates/shared/oxc/tsconfig.json +0 -11
  97. /package/dist/{cli.d.ts → src/cli.d.ts} +0 -0
  98. /package/dist/{generation-context.js → src/generation-context.js} +0 -0
  99. /package/dist/{package-addition.d.ts → src/package-addition.d.ts} +0 -0
  100. /package/dist/{renderer.d.ts → src/renderer.d.ts} +0 -0
  101. /package/dist/{renderer.js → src/renderer.js} +0 -0
  102. /package/dist/{toolchain-resolution.d.ts → src/toolchain-resolution.d.ts} +0 -0
@@ -0,0 +1,687 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ import type {
7
+ BuiltInPreset,
8
+ ProjectBlueprint,
9
+ } from "../../src/declarations.js";
10
+ import { renderGeneratedPnpmWorkspaceYaml } from "../../src/dependency-catalog.js";
11
+ import { nodePnpmDevcontainer } from "../../src/devcontainer.js";
12
+ import { editorCustomizationForCapabilities } from "../../src/editor-customization.js";
13
+ import type { GenerationContext } from "../../src/generation-context.js";
14
+ import {
15
+ type CheckPlan,
16
+ renderFixCommand,
17
+ renderRootCheckCommand,
18
+ } from "../../src/module-graph.js";
19
+ import type {
20
+ PresetPackageAdditionOptions,
21
+ PresetPackageAdditionPlan,
22
+ PresetProjection,
23
+ PresetProjectionPlan,
24
+ } from "../../src/preset-projection.js";
25
+ import {
26
+ projectCheckWorkflow,
27
+ projectDependabotConfig,
28
+ type DependencyMaintenancePolicy,
29
+ } from "../../src/project-github.js";
30
+ import { renderNewProject, type RenderOperation } from "../../src/renderer.js";
31
+ import { planNodeChecks, planNodeFixes } from "../projection-plans.js";
32
+
33
+ const generatedBy = {
34
+ packageName: "@ykdz/template",
35
+ version: "0.0.0",
36
+ command: "template init --preset vue-app",
37
+ };
38
+
39
+ export const vueAppPresetMetadata: BuiltInPreset = {
40
+ name: "vue-app",
41
+ title: "Vue app",
42
+ description:
43
+ "Single-package Vue app with Vite, Tailwind, Pinia, and test tooling.",
44
+ generation: "supported",
45
+ supportedPackageManagers: ["pnpm"],
46
+ supportedProjectKinds: ["single-package"],
47
+ features: [
48
+ "pnpm-catalog",
49
+ "oxc-format-lint",
50
+ "strict-typescript",
51
+ "root-check",
52
+ "fix-command",
53
+ "devcontainer",
54
+ "github-actions",
55
+ "dependabot",
56
+ ],
57
+ };
58
+
59
+ const dependencyMaintenancePolicy: DependencyMaintenancePolicy = {
60
+ ecosystems: ["npm", "github-actions"],
61
+ interval: "weekly",
62
+ };
63
+
64
+ export function vueAppBlueprint(): ProjectBlueprint {
65
+ return {
66
+ schemaVersion: 1,
67
+ preset: "vue-app",
68
+ packageManager: "pnpm",
69
+ projectKind: "single-package",
70
+ features: [...vueAppPresetMetadata.features],
71
+ };
72
+ }
73
+
74
+ export function projectVueAppPackageScripts(): Record<string, string> {
75
+ return {
76
+ build: "vite build",
77
+ check: renderRootCheckCommand(planNodeChecks("vue-app")),
78
+ dev: "vite",
79
+ fix: renderFixCommand(planNodeFixes("vue-app")),
80
+ "format:check": "oxfmt --check .",
81
+ "format:write": "oxfmt --write .",
82
+ lint: "oxlint . --deny-warnings",
83
+ "lint:fix": "oxlint . --fix --deny-warnings",
84
+ preview: "vite preview",
85
+ test: "vitest run",
86
+ "test:e2e": "pnpm run build && playwright test",
87
+ typecheck: "vue-tsc --build --noEmit",
88
+ };
89
+ }
90
+
91
+ function packageJson(
92
+ context: GenerationContext,
93
+ packageScripts: Record<string, string>,
94
+ ): Record<string, unknown> {
95
+ return {
96
+ name: context.projectName.value,
97
+ version: "0.0.0",
98
+ private: true,
99
+ type: "module",
100
+ scripts: packageScripts,
101
+ dependencies: {
102
+ "@vueuse/core": "catalog:",
103
+ pinia: "catalog:",
104
+ vue: "catalog:",
105
+ },
106
+ devDependencies: {
107
+ "@playwright/test": "catalog:",
108
+ "@tailwindcss/vite": "catalog:",
109
+ "@types/node": "catalog:",
110
+ "@types/web-bluetooth": "catalog:",
111
+ "@vitejs/plugin-vue": "catalog:",
112
+ "@vue/tsconfig": "catalog:",
113
+ oxfmt: "catalog:",
114
+ oxlint: "catalog:",
115
+ tailwindcss: "catalog:",
116
+ typescript: "catalog:",
117
+ vite: "catalog:",
118
+ vitest: "catalog:",
119
+ "vue-tsc": "catalog:",
120
+ },
121
+ engines: {
122
+ node: context.toolchain.nodeLtsMajor.value,
123
+ },
124
+ packageManager: context.toolchain.packageManagerPin.value,
125
+ };
126
+ }
127
+
128
+ function generationRecord(context: GenerationContext): Record<string, unknown> {
129
+ return {
130
+ ...generatedBy,
131
+ toolchain: {
132
+ nodeLtsMajor: context.toolchain.nodeLtsMajor.value,
133
+ packageManagerPin: context.toolchain.packageManagerPin.value,
134
+ source: context.toolchain.source,
135
+ },
136
+ };
137
+ }
138
+
139
+ function operationsForVueApp(
140
+ context: GenerationContext,
141
+ packageScripts: Record<string, string>,
142
+ checkPlan: CheckPlan,
143
+ ): RenderOperation[] {
144
+ const editorCustomization = editorCustomizationForCapabilities([
145
+ "oxc-format-lint",
146
+ "vue",
147
+ "tailwind",
148
+ "vitest",
149
+ ]);
150
+
151
+ return [
152
+ {
153
+ kind: "writeJson",
154
+ to: "package.json",
155
+ value: packageJson(context, packageScripts),
156
+ },
157
+ {
158
+ kind: "writeText",
159
+ to: "pnpm-workspace.yaml",
160
+ text: renderGeneratedPnpmWorkspaceYaml({
161
+ dependencies: [
162
+ "@playwright/test",
163
+ "@tailwindcss/vite",
164
+ "@types/node",
165
+ "@types/web-bluetooth",
166
+ "@vitejs/plugin-vue",
167
+ "@vue/tsconfig",
168
+ "@vueuse/core",
169
+ "oxfmt",
170
+ "oxlint",
171
+ "pinia",
172
+ "tailwindcss",
173
+ "typescript",
174
+ "vite",
175
+ "vitest",
176
+ "vue",
177
+ "vue-tsc",
178
+ ],
179
+ allowBuilds: {
180
+ esbuild: true,
181
+ },
182
+ }),
183
+ },
184
+ {
185
+ kind: "writeJson",
186
+ to: "tsconfig.json",
187
+ value: {
188
+ files: [],
189
+ references: [
190
+ { path: "./tsconfig.app.json" },
191
+ { path: "./tsconfig.test.json" },
192
+ { path: "./tsconfig.node.json" },
193
+ ],
194
+ },
195
+ },
196
+ {
197
+ kind: "writeJson",
198
+ to: "tsconfig.app.json",
199
+ value: {
200
+ extends: "@vue/tsconfig/tsconfig.dom.json",
201
+ compilerOptions: {
202
+ composite: true,
203
+ module: "ESNext",
204
+ moduleResolution: "Bundler",
205
+ noEmitOnError: true,
206
+ paths: {
207
+ "@/*": ["./src/*"],
208
+ },
209
+ skipLibCheck: false,
210
+ strict: true,
211
+ target: "ES2022",
212
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
213
+ types: ["web-bluetooth"],
214
+ },
215
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue"],
216
+ },
217
+ },
218
+ {
219
+ kind: "writeJson",
220
+ to: "tsconfig.test.json",
221
+ value: {
222
+ extends: "./tsconfig.app.json",
223
+ compilerOptions: {
224
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
225
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.test.tsbuildinfo",
226
+ types: ["node", "vitest/globals", "web-bluetooth"],
227
+ },
228
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue", "test/**/*.ts"],
229
+ },
230
+ },
231
+ {
232
+ kind: "writeJson",
233
+ to: "tsconfig.node.json",
234
+ value: {
235
+ compilerOptions: {
236
+ composite: true,
237
+ module: "ESNext",
238
+ moduleResolution: "Bundler",
239
+ noEmitOnError: true,
240
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
241
+ skipLibCheck: false,
242
+ strict: true,
243
+ target: "ES2022",
244
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
245
+ types: ["node"],
246
+ },
247
+ include: ["playwright.config.ts", "vite.config.ts", "vitest.config.ts"],
248
+ },
249
+ },
250
+ {
251
+ kind: "copyFile",
252
+ sourceRoot: "sharedOxc",
253
+ from: "vue/oxlint.config.ts",
254
+ to: "oxlint.config.ts",
255
+ },
256
+ {
257
+ kind: "copyFile",
258
+ sourceRoot: "sharedOxc",
259
+ from: "oxfmt.config.ts",
260
+ to: "oxfmt.config.ts",
261
+ },
262
+ {
263
+ kind: "writeText",
264
+ to: ".gitignore",
265
+ text: [
266
+ "node_modules",
267
+ "dist",
268
+ "playwright-report",
269
+ "test-results",
270
+ ".env",
271
+ "",
272
+ ].join("\n"),
273
+ },
274
+ { kind: "copyFile", from: "env.d.ts", to: "env.d.ts" },
275
+ { kind: "copyFile", from: "index.html", to: "index.html" },
276
+ {
277
+ kind: "copyFile",
278
+ from: "playwright.config.ts",
279
+ to: "playwright.config.ts",
280
+ },
281
+ { kind: "copyFile", from: "vite.config.ts", to: "vite.config.ts" },
282
+ { kind: "copyFile", from: "vitest.config.ts", to: "vitest.config.ts" },
283
+ { kind: "copyFile", from: "src/App.vue", to: "src/App.vue" },
284
+ { kind: "copyFile", from: "src/main.ts", to: "src/main.ts" },
285
+ { kind: "copyFile", from: "src/style.css", to: "src/style.css" },
286
+ {
287
+ kind: "copyFile",
288
+ from: "src/stores/counter.ts",
289
+ to: "src/stores/counter.ts",
290
+ },
291
+ { kind: "copyFile", from: "test/app.test.ts", to: "test/app.test.ts" },
292
+ {
293
+ kind: "copyFile",
294
+ from: "test/e2e/app.spec.ts",
295
+ to: "test/e2e/app.spec.ts",
296
+ },
297
+ {
298
+ kind: "writeJson",
299
+ to: ".project-kit/blueprint.json",
300
+ value: vueAppBlueprint(),
301
+ },
302
+ {
303
+ kind: "writeJson",
304
+ to: ".project-kit/generated-by.json",
305
+ value: generationRecord(context),
306
+ },
307
+ {
308
+ kind: "writeJson",
309
+ to: ".devcontainer/devcontainer.json",
310
+ value: nodePnpmDevcontainer({
311
+ name: `${context.projectName.value} Vue development`,
312
+ nodeVersion: context.toolchain.nodeLtsMajor.value,
313
+ packageManagerPin: context.toolchain.packageManagerPin.value,
314
+ extensions: editorCustomization.extensions,
315
+ settings: editorCustomization.settings,
316
+ }),
317
+ },
318
+ {
319
+ kind: "writeJson",
320
+ to: ".vscode/extensions.json",
321
+ value: {
322
+ recommendations: editorCustomization.extensions,
323
+ },
324
+ multilineArrays: ["recommendations"],
325
+ },
326
+ {
327
+ kind: "writeJson",
328
+ to: ".vscode/settings.json",
329
+ value: editorCustomization.settings,
330
+ },
331
+ {
332
+ kind: "writeText",
333
+ to: ".github/workflows/check.yml",
334
+ text: projectCheckWorkflow({ checkPlan }),
335
+ },
336
+ {
337
+ kind: "writeText",
338
+ to: ".github/dependabot.yml",
339
+ text: projectDependabotConfig(dependencyMaintenancePolicy),
340
+ },
341
+ ];
342
+ }
343
+
344
+ function isNodeError(error: unknown): error is NodeJS.ErrnoException {
345
+ return error instanceof Error && "code" in error;
346
+ }
347
+
348
+ function localPortsFromText(text: string): number[] {
349
+ return [
350
+ ...text.matchAll(/port:\s*(\d+)/g),
351
+ ...text.matchAll(/--port\s+(\d+)/g),
352
+ ...text.matchAll(/https?:\/\/(?:localhost|127\.0\.0\.1):(\d+)/g),
353
+ ].map((match) => Number(match[1]));
354
+ }
355
+
356
+ async function usedPlaywrightPorts(
357
+ root: string,
358
+ blueprint: ProjectBlueprint,
359
+ ): Promise<Set<number>> {
360
+ const ports = new Set<number>();
361
+
362
+ for (const projectPackage of blueprint.packages ?? []) {
363
+ try {
364
+ const configText = await readFile(
365
+ path.join(root, projectPackage.path, "playwright.config.ts"),
366
+ "utf8",
367
+ );
368
+
369
+ for (const port of localPortsFromText(configText)) {
370
+ ports.add(port);
371
+ }
372
+ } catch (error: unknown) {
373
+ if (!isNodeError(error) || error.code !== "ENOENT") {
374
+ throw error;
375
+ }
376
+ }
377
+ }
378
+
379
+ return ports;
380
+ }
381
+
382
+ async function nextVuePreviewPort(
383
+ root: string,
384
+ blueprint: ProjectBlueprint,
385
+ ): Promise<number> {
386
+ const usedPorts = await usedPlaywrightPorts(root, blueprint);
387
+ let port = 4173;
388
+
389
+ while (usedPorts.has(port)) {
390
+ port += 1;
391
+ }
392
+
393
+ return port;
394
+ }
395
+
396
+ function vueAppPlaywrightConfig(previewPort: number): string {
397
+ return `import { defineConfig, devices } from "@playwright/test";
398
+
399
+ const previewUrl = "http://127.0.0.1:${previewPort}";
400
+
401
+ export default defineConfig({
402
+ testDir: "./test/e2e",
403
+ use: {
404
+ baseURL: previewUrl,
405
+ trace: "on-first-retry"
406
+ },
407
+ webServer: {
408
+ command: "pnpm run preview --host 127.0.0.1 --port ${previewPort}",
409
+ reuseExistingServer: !process.env.CI,
410
+ url: previewUrl
411
+ },
412
+ projects: [
413
+ {
414
+ name: "chromium",
415
+ use: { ...devices["Desktop Chrome"] }
416
+ }
417
+ ]
418
+ });
419
+ `;
420
+ }
421
+
422
+ function packageAdditionOperations(
423
+ packagePath: string,
424
+ packageName: string,
425
+ nodeVersion: string,
426
+ ): RenderOperation[] {
427
+ return [
428
+ {
429
+ kind: "writeJson",
430
+ to: `${packagePath}/package.json`,
431
+ value: {
432
+ name: packageName,
433
+ version: "0.0.0",
434
+ private: true,
435
+ type: "module",
436
+ scripts: projectVueAppPackageScripts(),
437
+ dependencies: {
438
+ "@vueuse/core": "catalog:",
439
+ pinia: "catalog:",
440
+ vue: "catalog:",
441
+ },
442
+ devDependencies: {
443
+ "@playwright/test": "catalog:",
444
+ "@tailwindcss/vite": "catalog:",
445
+ "@types/node": "catalog:",
446
+ "@types/web-bluetooth": "catalog:",
447
+ "@vitejs/plugin-vue": "catalog:",
448
+ "@vue/tsconfig": "catalog:",
449
+ oxfmt: "catalog:",
450
+ oxlint: "catalog:",
451
+ tailwindcss: "catalog:",
452
+ typescript: "catalog:",
453
+ vite: "catalog:",
454
+ vitest: "catalog:",
455
+ "vue-tsc": "catalog:",
456
+ },
457
+ engines: {
458
+ node: nodeVersion,
459
+ },
460
+ },
461
+ },
462
+ {
463
+ kind: "writeJson",
464
+ to: `${packagePath}/tsconfig.json`,
465
+ value: {
466
+ files: [],
467
+ references: [
468
+ { path: "./tsconfig.app.json" },
469
+ { path: "./tsconfig.test.json" },
470
+ { path: "./tsconfig.node.json" },
471
+ ],
472
+ },
473
+ },
474
+ {
475
+ kind: "writeJson",
476
+ to: `${packagePath}/tsconfig.app.json`,
477
+ value: {
478
+ extends: "@vue/tsconfig/tsconfig.dom.json",
479
+ compilerOptions: {
480
+ composite: true,
481
+ module: "ESNext",
482
+ moduleResolution: "Bundler",
483
+ noEmitOnError: true,
484
+ paths: {
485
+ "@/*": ["./src/*"],
486
+ },
487
+ skipLibCheck: false,
488
+ strict: true,
489
+ target: "ES2022",
490
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
491
+ types: ["web-bluetooth"],
492
+ },
493
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue"],
494
+ },
495
+ },
496
+ {
497
+ kind: "writeJson",
498
+ to: `${packagePath}/tsconfig.test.json`,
499
+ value: {
500
+ extends: "./tsconfig.app.json",
501
+ compilerOptions: {
502
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
503
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.test.tsbuildinfo",
504
+ types: ["node", "vitest/globals", "web-bluetooth"],
505
+ },
506
+ include: ["env.d.ts", "src/**/*.ts", "src/**/*.vue", "test/**/*.ts"],
507
+ },
508
+ },
509
+ {
510
+ kind: "writeJson",
511
+ to: `${packagePath}/tsconfig.node.json`,
512
+ value: {
513
+ compilerOptions: {
514
+ composite: true,
515
+ module: "ESNext",
516
+ moduleResolution: "Bundler",
517
+ noEmitOnError: true,
518
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
519
+ skipLibCheck: false,
520
+ strict: true,
521
+ target: "ES2022",
522
+ tsBuildInfoFile: "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
523
+ types: ["node"],
524
+ },
525
+ include: ["playwright.config.ts", "vite.config.ts", "vitest.config.ts"],
526
+ },
527
+ },
528
+ {
529
+ kind: "copyFile",
530
+ sourceRoot: "sharedOxc",
531
+ from: "vue/oxlint.config.ts",
532
+ to: `${packagePath}/oxlint.config.ts`,
533
+ },
534
+ {
535
+ kind: "copyFile",
536
+ sourceRoot: "sharedOxc",
537
+ from: "oxfmt.config.ts",
538
+ to: `${packagePath}/oxfmt.config.ts`,
539
+ },
540
+ { kind: "copyFile", from: "env.d.ts", to: `${packagePath}/env.d.ts` },
541
+ { kind: "copyFile", from: "index.html", to: `${packagePath}/index.html` },
542
+ {
543
+ kind: "copyFile",
544
+ from: "playwright.config.ts",
545
+ to: `${packagePath}/playwright.config.ts`,
546
+ },
547
+ {
548
+ kind: "copyFile",
549
+ from: "vite.config.ts",
550
+ to: `${packagePath}/vite.config.ts`,
551
+ },
552
+ {
553
+ kind: "copyFile",
554
+ from: "vitest.config.ts",
555
+ to: `${packagePath}/vitest.config.ts`,
556
+ },
557
+ { kind: "copyFile", from: "src/App.vue", to: `${packagePath}/src/App.vue` },
558
+ { kind: "copyFile", from: "src/main.ts", to: `${packagePath}/src/main.ts` },
559
+ {
560
+ kind: "copyFile",
561
+ from: "src/style.css",
562
+ to: `${packagePath}/src/style.css`,
563
+ },
564
+ {
565
+ kind: "copyFile",
566
+ from: "src/stores/counter.ts",
567
+ to: `${packagePath}/src/stores/counter.ts`,
568
+ },
569
+ {
570
+ kind: "copyFile",
571
+ from: "test/app.test.ts",
572
+ to: `${packagePath}/test/app.test.ts`,
573
+ },
574
+ {
575
+ kind: "copyFile",
576
+ from: "test/e2e/app.spec.ts",
577
+ to: `${packagePath}/test/e2e/app.spec.ts`,
578
+ },
579
+ ];
580
+ }
581
+
582
+ async function packageAdditionPlan({
583
+ root,
584
+ blueprint,
585
+ packageLeafName,
586
+ packageName,
587
+ nodeVersion,
588
+ }: PresetPackageAdditionOptions): Promise<PresetPackageAdditionPlan> {
589
+ const packagePath = `apps/${packageLeafName}`;
590
+ const previewPort = await nextVuePreviewPort(root, blueprint);
591
+
592
+ return {
593
+ packagePath,
594
+ workspacePackageGlob: "apps/*",
595
+ rootTsconfigReferences: [
596
+ `./${packagePath}/tsconfig.app.json`,
597
+ `./${packagePath}/tsconfig.test.json`,
598
+ `./${packagePath}/tsconfig.node.json`,
599
+ ],
600
+ sourceRoot: templateSourceRoot(),
601
+ sourceRoots: { sharedOxc: sharedOxcSourceRoot() },
602
+ operations: packageAdditionOperations(
603
+ packagePath,
604
+ packageName,
605
+ nodeVersion,
606
+ ),
607
+ textFiles: [
608
+ {
609
+ path: `${packagePath}/playwright.config.ts`,
610
+ text: vueAppPlaywrightConfig(previewPort),
611
+ },
612
+ ],
613
+ };
614
+ }
615
+
616
+ function templateSourceRoot(): string {
617
+ const projectionDir = path.dirname(fileURLToPath(import.meta.url));
618
+ const publishedTemplateRoot = path.join(
619
+ projectionDir,
620
+ "..",
621
+ "..",
622
+ "..",
623
+ "templates",
624
+ "vue-app",
625
+ );
626
+
627
+ return existsSync(path.join(publishedTemplateRoot, "src", "App.vue"))
628
+ ? publishedTemplateRoot
629
+ : projectionDir;
630
+ }
631
+
632
+ function sharedOxcSourceRoot(): string {
633
+ const projectionDir = path.dirname(fileURLToPath(import.meta.url));
634
+ const publishedSharedRoot = path.join(
635
+ projectionDir,
636
+ "..",
637
+ "..",
638
+ "..",
639
+ "templates",
640
+ "shared",
641
+ "oxc",
642
+ );
643
+
644
+ return existsSync(path.join(publishedSharedRoot, "oxfmt.config.ts"))
645
+ ? publishedSharedRoot
646
+ : path.join(projectionDir, "..", "shared", "oxc");
647
+ }
648
+
649
+ export const vueAppPresetProjection: PresetProjection = {
650
+ metadata: vueAppPresetMetadata,
651
+ capabilities: {
652
+ packageAddition: {
653
+ planPackageAddition: packageAdditionPlan,
654
+ },
655
+ },
656
+ blueprint: vueAppBlueprint,
657
+ project(context: GenerationContext): PresetProjectionPlan {
658
+ const checkPlan = planNodeChecks("vue-app");
659
+ const fixPlan = planNodeFixes("vue-app");
660
+ const packageScripts = projectVueAppPackageScripts();
661
+
662
+ return {
663
+ sourceRoot: templateSourceRoot(),
664
+ sourceRoots: { sharedOxc: sharedOxcSourceRoot() },
665
+ operations: operationsForVueApp(context, packageScripts, checkPlan),
666
+ checkPlan,
667
+ fixPlan,
668
+ dependencyMaintenancePolicy,
669
+ packageScripts,
670
+ capabilities: {
671
+ rootCheck: true,
672
+ fixCommand: true,
673
+ githubActions: true,
674
+ dependabot: true,
675
+ devcontainer: true,
676
+ },
677
+ };
678
+ },
679
+ async render({ targetDir, plan }): Promise<void> {
680
+ await renderNewProject({
681
+ sourceRoot: plan.sourceRoot,
682
+ sourceRoots: plan.sourceRoots,
683
+ targetRoot: targetDir,
684
+ operations: [...plan.operations],
685
+ });
686
+ },
687
+ };
@@ -6,6 +6,9 @@ test("renders and updates the counter", async ({ page }) => {
6
6
  await expect(
7
7
  page.getByRole("heading", { name: "Vue, Vite, Tailwind, and Pinia" }),
8
8
  ).toBeVisible();
9
- await page.getByRole("button", { name: "Count is 0" }).click();
9
+ const counterButton = page.getByRole("button", { name: "Count is 0" });
10
+
11
+ await expect(counterButton).toBeVisible();
12
+ await counterButton.click({ force: true });
10
13
  await expect(page.getByRole("button", { name: "Count is 1" })).toBeVisible();
11
14
  });