create-einja-app 0.1.1

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 (235) hide show
  1. package/README.md +307 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +1041 -0
  4. package/dist/cli.js.map +1 -0
  5. package/package.json +62 -0
  6. package/templates/turborepo-pandacss/.biomeignore +15 -0
  7. package/templates/turborepo-pandacss/.claude/hooks/einja/biome-format.sh +49 -0
  8. package/templates/turborepo-pandacss/.claude/hooks/einja/design-doc-check.sh +61 -0
  9. package/templates/turborepo-pandacss/.claude/hooks/einja/detect-secrets.sh +62 -0
  10. package/templates/turborepo-pandacss/.claude/hooks/einja/large-file-warning.sh +42 -0
  11. package/templates/turborepo-pandacss/.claude/hooks/einja/playwright-resize.sh +36 -0
  12. package/templates/turborepo-pandacss/.claude/hooks/einja/typecheck.sh +37 -0
  13. package/templates/turborepo-pandacss/.claude/hooks/einja/unset-volta-recursion.sh +32 -0
  14. package/templates/turborepo-pandacss/.claude/hooks/einja/validate-git-commit.sh +239 -0
  15. package/templates/turborepo-pandacss/.claude/hooks/einja/warn-index-ts.sh +34 -0
  16. package/templates/turborepo-pandacss/.claude/hooks/einja/warn-relative-import.sh +48 -0
  17. package/templates/turborepo-pandacss/.claude/settings.json +174 -0
  18. package/templates/turborepo-pandacss/.claude/skills/create-einja-app-release/SKILL.md +186 -0
  19. package/templates/turborepo-pandacss/.claude/skills/dev-cli-release/SKILL.md +173 -0
  20. package/templates/turborepo-pandacss/.cursor/commands/spec-create.md +227 -0
  21. package/templates/turborepo-pandacss/.cursor/commands/start-dev.md +98 -0
  22. package/templates/turborepo-pandacss/.cursor/commands/task-exec.md +287 -0
  23. package/templates/turborepo-pandacss/.cursor/commands/task-vibe-kanban-loop.md +532 -0
  24. package/templates/turborepo-pandacss/.cursor/commands/update-docs-by-task-specs.md +448 -0
  25. package/templates/turborepo-pandacss/.cursor/mcp.json +45 -0
  26. package/templates/turborepo-pandacss/.cursor/rules/api-rules.mdc +171 -0
  27. package/templates/turborepo-pandacss/.cursor/rules/api-test-rules.mdc +181 -0
  28. package/templates/turborepo-pandacss/.cursor/rules/base-code.mdc +70 -0
  29. package/templates/turborepo-pandacss/.cursor/rules/base-commit-rules.mdc +174 -0
  30. package/templates/turborepo-pandacss/.cursor/rules/base-design.mdc +12 -0
  31. package/templates/turborepo-pandacss/.cursor/rules/base-rules.mdc +231 -0
  32. package/templates/turborepo-pandacss/.cursor/rules/error-handling-rules.mdc +188 -0
  33. package/templates/turborepo-pandacss/.cursor/rules/refactor-rules.mdc +93 -0
  34. package/templates/turborepo-pandacss/.dockerignore +126 -0
  35. package/templates/turborepo-pandacss/.einja-sync.json +35 -0
  36. package/templates/turborepo-pandacss/.env.ci +25 -0
  37. package/templates/turborepo-pandacss/.env.example +35 -0
  38. package/templates/turborepo-pandacss/.env.personal.example +27 -0
  39. package/templates/turborepo-pandacss/.envrc +4 -0
  40. package/templates/turborepo-pandacss/.gitattributes +5 -0
  41. package/templates/turborepo-pandacss/.husky/pre-commit +1 -0
  42. package/templates/turborepo-pandacss/.lintstagedrc.js +24 -0
  43. package/templates/turborepo-pandacss/.mcp.json +45 -0
  44. package/templates/turborepo-pandacss/.node-version +1 -0
  45. package/templates/turborepo-pandacss/.templateignore +60 -0
  46. package/templates/turborepo-pandacss/.vscode/extensions.json +3 -0
  47. package/templates/turborepo-pandacss/CLAUDE.md +415 -0
  48. package/templates/turborepo-pandacss/README.md +322 -0
  49. package/templates/turborepo-pandacss/apps/web/middleware.ts +28 -0
  50. package/templates/turborepo-pandacss/apps/web/next.config.ts +10 -0
  51. package/templates/turborepo-pandacss/apps/web/package.json +80 -0
  52. package/templates/turborepo-pandacss/apps/web/panda.config.ts +114 -0
  53. package/templates/turborepo-pandacss/apps/web/postcss.config.cjs +6 -0
  54. package/templates/turborepo-pandacss/apps/web/public/file.svg +1 -0
  55. package/templates/turborepo-pandacss/apps/web/public/globe.svg +1 -0
  56. package/templates/turborepo-pandacss/apps/web/public/next.svg +1 -0
  57. package/templates/turborepo-pandacss/apps/web/public/vercel.svg +1 -0
  58. package/templates/turborepo-pandacss/apps/web/public/window.svg +1 -0
  59. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/dashboard/page.tsx +79 -0
  60. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +203 -0
  61. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/data/page.tsx +57 -0
  62. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/layout-client.tsx +31 -0
  63. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/layout.tsx +17 -0
  64. package/templates/turborepo-pandacss/apps/web/src/app/(authenticated)/profile/page.tsx +59 -0
  65. package/templates/turborepo-pandacss/apps/web/src/app/api/auth/[...nextauth]/route.ts +3 -0
  66. package/templates/turborepo-pandacss/apps/web/src/app/api/auth/signup/route.ts +70 -0
  67. package/templates/turborepo-pandacss/apps/web/src/app/error.tsx +106 -0
  68. package/templates/turborepo-pandacss/apps/web/src/app/favicon.ico +0 -0
  69. package/templates/turborepo-pandacss/apps/web/src/app/global-error.tsx +110 -0
  70. package/templates/turborepo-pandacss/apps/web/src/app/globals.css +121 -0
  71. package/templates/turborepo-pandacss/apps/web/src/app/layout.tsx +28 -0
  72. package/templates/turborepo-pandacss/apps/web/src/app/not-found.tsx +54 -0
  73. package/templates/turborepo-pandacss/apps/web/src/app/page.module.css +165 -0
  74. package/templates/turborepo-pandacss/apps/web/src/app/page.test.tsx +52 -0
  75. package/templates/turborepo-pandacss/apps/web/src/app/page.tsx +284 -0
  76. package/templates/turborepo-pandacss/apps/web/src/app/signin/page.tsx +296 -0
  77. package/templates/turborepo-pandacss/apps/web/src/app/signup/page.tsx +395 -0
  78. package/templates/turborepo-pandacss/apps/web/src/application/use-cases/UserUseCases.test.ts +229 -0
  79. package/templates/turborepo-pandacss/apps/web/src/application/use-cases/UserUseCases.ts +115 -0
  80. package/templates/turborepo-pandacss/apps/web/src/components/auth/login-button.tsx +35 -0
  81. package/templates/turborepo-pandacss/apps/web/src/components/auth/logout-button.tsx +24 -0
  82. package/templates/turborepo-pandacss/apps/web/src/components/auth/user-avatar.test.tsx +68 -0
  83. package/templates/turborepo-pandacss/apps/web/src/components/auth/user-avatar.tsx +43 -0
  84. package/templates/turborepo-pandacss/apps/web/src/components/dashboard/dashboard-stats.tsx +128 -0
  85. package/templates/turborepo-pandacss/apps/web/src/components/providers/query-provider.tsx +30 -0
  86. package/templates/turborepo-pandacss/apps/web/src/components/providers/session-provider.tsx +12 -0
  87. package/templates/turborepo-pandacss/apps/web/src/components/shared/Sidebar.tsx +175 -0
  88. package/templates/turborepo-pandacss/apps/web/src/components/shared/header.tsx +166 -0
  89. package/templates/turborepo-pandacss/apps/web/src/components/ui/accordion.tsx +64 -0
  90. package/templates/turborepo-pandacss/apps/web/src/components/ui/alert-dialog.tsx +135 -0
  91. package/templates/turborepo-pandacss/apps/web/src/components/ui/alert.tsx +60 -0
  92. package/templates/turborepo-pandacss/apps/web/src/components/ui/aspect-ratio.tsx +9 -0
  93. package/templates/turborepo-pandacss/apps/web/src/components/ui/avatar.tsx +41 -0
  94. package/templates/turborepo-pandacss/apps/web/src/components/ui/badge.tsx +39 -0
  95. package/templates/turborepo-pandacss/apps/web/src/components/ui/breadcrumb.tsx +101 -0
  96. package/templates/turborepo-pandacss/apps/web/src/components/ui/button.tsx +56 -0
  97. package/templates/turborepo-pandacss/apps/web/src/components/ui/card.tsx +75 -0
  98. package/templates/turborepo-pandacss/apps/web/src/components/ui/checkbox.tsx +29 -0
  99. package/templates/turborepo-pandacss/apps/web/src/components/ui/data-table.tsx +189 -0
  100. package/templates/turborepo-pandacss/apps/web/src/components/ui/dialog-hook.tsx +210 -0
  101. package/templates/turborepo-pandacss/apps/web/src/components/ui/dialog.tsx +129 -0
  102. package/templates/turborepo-pandacss/apps/web/src/components/ui/drawer.tsx +124 -0
  103. package/templates/turborepo-pandacss/apps/web/src/components/ui/dropdown-menu.tsx +228 -0
  104. package/templates/turborepo-pandacss/apps/web/src/components/ui/form.tsx +152 -0
  105. package/templates/turborepo-pandacss/apps/web/src/components/ui/hover-card.tsx +38 -0
  106. package/templates/turborepo-pandacss/apps/web/src/components/ui/input.tsx +21 -0
  107. package/templates/turborepo-pandacss/apps/web/src/components/ui/label.tsx +21 -0
  108. package/templates/turborepo-pandacss/apps/web/src/components/ui/pagination.tsx +105 -0
  109. package/templates/turborepo-pandacss/apps/web/src/components/ui/popover.tsx +42 -0
  110. package/templates/turborepo-pandacss/apps/web/src/components/ui/progress.tsx +28 -0
  111. package/templates/turborepo-pandacss/apps/web/src/components/ui/select.tsx +170 -0
  112. package/templates/turborepo-pandacss/apps/web/src/components/ui/separator.tsx +28 -0
  113. package/templates/turborepo-pandacss/apps/web/src/components/ui/skeleton.tsx +13 -0
  114. package/templates/turborepo-pandacss/apps/web/src/components/ui/sonner.tsx +25 -0
  115. package/templates/turborepo-pandacss/apps/web/src/components/ui/table.tsx +92 -0
  116. package/templates/turborepo-pandacss/apps/web/src/components/ui/tabs.tsx +54 -0
  117. package/templates/turborepo-pandacss/apps/web/src/components/ui/textarea.tsx +18 -0
  118. package/templates/turborepo-pandacss/apps/web/src/components/ui/tooltip.tsx +57 -0
  119. package/templates/turborepo-pandacss/apps/web/src/components/ui/typography.tsx +158 -0
  120. package/templates/turborepo-pandacss/apps/web/src/lib/auth/guard.ts +36 -0
  121. package/templates/turborepo-pandacss/apps/web/src/lib/auth/index.ts +22 -0
  122. package/templates/turborepo-pandacss/apps/web/src/lib/prisma.ts +3 -0
  123. package/templates/turborepo-pandacss/apps/web/src/lib/utils.ts +6 -0
  124. package/templates/turborepo-pandacss/apps/web/test/globals.d.ts +1 -0
  125. package/templates/turborepo-pandacss/apps/web/test/matchers.d.ts +1 -0
  126. package/templates/turborepo-pandacss/apps/web/test/setup.ts +22 -0
  127. package/templates/turborepo-pandacss/apps/web/tsconfig.json +37 -0
  128. package/templates/turborepo-pandacss/apps/web/vitest.config.ts +20 -0
  129. package/templates/turborepo-pandacss/apps/web/vitest.d.ts +2 -0
  130. package/templates/turborepo-pandacss/biome.json +60 -0
  131. package/templates/turborepo-pandacss/components.json +21 -0
  132. package/templates/turborepo-pandacss/docker-compose.yml +27 -0
  133. package/templates/turborepo-pandacss/middleware.ts +32 -0
  134. package/templates/turborepo-pandacss/next.config.ts +10 -0
  135. package/templates/turborepo-pandacss/package-lock.json +9346 -0
  136. package/templates/turborepo-pandacss/package.json +64 -0
  137. package/templates/turborepo-pandacss/packages/config/package.json +41 -0
  138. package/templates/turborepo-pandacss/packages/config/panda.config.ts +114 -0
  139. package/templates/turborepo-pandacss/packages/config/src/index.ts +24 -0
  140. package/templates/turborepo-pandacss/packages/config/src/worktree-config-loader.ts +129 -0
  141. package/templates/turborepo-pandacss/packages/config/src/worktree-config.ts +75 -0
  142. package/templates/turborepo-pandacss/packages/config/tsconfig.build.json +19 -0
  143. package/templates/turborepo-pandacss/packages/config/tsconfig.json +24 -0
  144. package/templates/turborepo-pandacss/packages/config/typescript/base.json +19 -0
  145. package/templates/turborepo-pandacss/packages/front-core/package.json +24 -0
  146. package/templates/turborepo-pandacss/packages/front-core/src/auth/config.ts +84 -0
  147. package/templates/turborepo-pandacss/packages/front-core/src/auth/index.ts +5 -0
  148. package/templates/turborepo-pandacss/packages/front-core/src/auth/types/next-auth.d.ts +20 -0
  149. package/templates/turborepo-pandacss/packages/front-core/src/auth/utils.ts +29 -0
  150. package/templates/turborepo-pandacss/packages/front-core/src/context/index.ts +2 -0
  151. package/templates/turborepo-pandacss/packages/front-core/src/hooks/index.ts +2 -0
  152. package/templates/turborepo-pandacss/packages/front-core/src/index.ts +4 -0
  153. package/templates/turborepo-pandacss/packages/front-core/src/utils/index.ts +2 -0
  154. package/templates/turborepo-pandacss/packages/front-core/tsconfig.json +14 -0
  155. package/templates/turborepo-pandacss/packages/server-core/package.json +32 -0
  156. package/templates/turborepo-pandacss/packages/server-core/prisma/schema.prisma +102 -0
  157. package/templates/turborepo-pandacss/packages/server-core/prisma/seed.ts +67 -0
  158. package/templates/turborepo-pandacss/packages/server-core/prisma.config.ts +8 -0
  159. package/templates/turborepo-pandacss/packages/server-core/src/__generated__/fabbrica/index.d.ts +270 -0
  160. package/templates/turborepo-pandacss/packages/server-core/src/__generated__/fabbrica/index.js +484 -0
  161. package/templates/turborepo-pandacss/packages/server-core/src/core/result.test.ts +78 -0
  162. package/templates/turborepo-pandacss/packages/server-core/src/core/result.ts +53 -0
  163. package/templates/turborepo-pandacss/packages/server-core/src/domain/.gitkeep +0 -0
  164. package/templates/turborepo-pandacss/packages/server-core/src/domain/entities/User.test.ts +232 -0
  165. package/templates/turborepo-pandacss/packages/server-core/src/domain/entities/User.ts +105 -0
  166. package/templates/turborepo-pandacss/packages/server-core/src/domain/repository-interfaces/IUserRepository.ts +101 -0
  167. package/templates/turborepo-pandacss/packages/server-core/src/infrastructure/database/client.ts +15 -0
  168. package/templates/turborepo-pandacss/packages/server-core/src/infrastructure/database/mappers/UserMapper.test.ts +278 -0
  169. package/templates/turborepo-pandacss/packages/server-core/src/infrastructure/database/mappers/UserMapper.ts +103 -0
  170. package/templates/turborepo-pandacss/packages/server-core/src/infrastructure/database/repositories/UserRepository.test.ts +317 -0
  171. package/templates/turborepo-pandacss/packages/server-core/src/infrastructure/database/repositories/UserRepository.ts +169 -0
  172. package/templates/turborepo-pandacss/packages/server-core/src/testing/factories/index.ts +22 -0
  173. package/templates/turborepo-pandacss/packages/server-core/src/testing/factories/user.factory.ts +123 -0
  174. package/templates/turborepo-pandacss/packages/server-core/src/testing/fixtures/users.ts +92 -0
  175. package/templates/turborepo-pandacss/packages/server-core/src/testing/helpers/date.ts +49 -0
  176. package/templates/turborepo-pandacss/packages/server-core/src/testing/helpers/password.ts +50 -0
  177. package/templates/turborepo-pandacss/packages/server-core/src/testing/index.ts +26 -0
  178. package/templates/turborepo-pandacss/packages/server-core/tsconfig.json +14 -0
  179. package/templates/turborepo-pandacss/packages/server-core/vitest.config.ts +15 -0
  180. package/templates/turborepo-pandacss/packages/ui/package.json +37 -0
  181. package/templates/turborepo-pandacss/packages/ui/src/accordion.tsx +66 -0
  182. package/templates/turborepo-pandacss/packages/ui/src/alert-dialog.tsx +157 -0
  183. package/templates/turborepo-pandacss/packages/ui/src/alert.tsx +66 -0
  184. package/templates/turborepo-pandacss/packages/ui/src/aspect-ratio.tsx +11 -0
  185. package/templates/turborepo-pandacss/packages/ui/src/avatar.tsx +53 -0
  186. package/templates/turborepo-pandacss/packages/ui/src/badge.tsx +46 -0
  187. package/templates/turborepo-pandacss/packages/ui/src/breadcrumb.tsx +108 -0
  188. package/templates/turborepo-pandacss/packages/ui/src/button.tsx +59 -0
  189. package/templates/turborepo-pandacss/packages/ui/src/card.tsx +92 -0
  190. package/templates/turborepo-pandacss/packages/ui/src/checkbox.tsx +32 -0
  191. package/templates/turborepo-pandacss/packages/ui/src/data-table.tsx +216 -0
  192. package/templates/turborepo-pandacss/packages/ui/src/dialog-hook.tsx +226 -0
  193. package/templates/turborepo-pandacss/packages/ui/src/dialog.tsx +143 -0
  194. package/templates/turborepo-pandacss/packages/ui/src/drawer.tsx +135 -0
  195. package/templates/turborepo-pandacss/packages/ui/src/dropdown-menu.tsx +257 -0
  196. package/templates/turborepo-pandacss/packages/ui/src/form.tsx +168 -0
  197. package/templates/turborepo-pandacss/packages/ui/src/hover-card.tsx +44 -0
  198. package/templates/turborepo-pandacss/packages/ui/src/input.tsx +21 -0
  199. package/templates/turborepo-pandacss/packages/ui/src/label.tsx +24 -0
  200. package/templates/turborepo-pandacss/packages/ui/src/lib/utils.ts +6 -0
  201. package/templates/turborepo-pandacss/packages/ui/src/pagination.tsx +126 -0
  202. package/templates/turborepo-pandacss/packages/ui/src/popover.tsx +48 -0
  203. package/templates/turborepo-pandacss/packages/ui/src/progress.tsx +31 -0
  204. package/templates/turborepo-pandacss/packages/ui/src/select.tsx +185 -0
  205. package/templates/turborepo-pandacss/packages/ui/src/separator.tsx +28 -0
  206. package/templates/turborepo-pandacss/packages/ui/src/skeleton.tsx +13 -0
  207. package/templates/turborepo-pandacss/packages/ui/src/sonner.tsx +25 -0
  208. package/templates/turborepo-pandacss/packages/ui/src/table.tsx +116 -0
  209. package/templates/turborepo-pandacss/packages/ui/src/tabs.tsx +66 -0
  210. package/templates/turborepo-pandacss/packages/ui/src/textarea.tsx +18 -0
  211. package/templates/turborepo-pandacss/packages/ui/src/tooltip.tsx +61 -0
  212. package/templates/turborepo-pandacss/packages/ui/src/typography.tsx +187 -0
  213. package/templates/turborepo-pandacss/packages/ui/tsconfig.json +20 -0
  214. package/templates/turborepo-pandacss/panda.config.ts +114 -0
  215. package/templates/turborepo-pandacss/pnpm-lock.yaml +9032 -0
  216. package/templates/turborepo-pandacss/pnpm-workspace.yaml +11 -0
  217. package/templates/turborepo-pandacss/postcss.config.cjs +6 -0
  218. package/templates/turborepo-pandacss/prisma/schema.prisma +82 -0
  219. package/templates/turborepo-pandacss/public/file.svg +1 -0
  220. package/templates/turborepo-pandacss/public/globe.svg +1 -0
  221. package/templates/turborepo-pandacss/public/next.svg +1 -0
  222. package/templates/turborepo-pandacss/public/vercel.svg +1 -0
  223. package/templates/turborepo-pandacss/public/window.svg +1 -0
  224. package/templates/turborepo-pandacss/scripts/cli-template-update.ts +387 -0
  225. package/templates/turborepo-pandacss/scripts/env-show.ts +129 -0
  226. package/templates/turborepo-pandacss/scripts/env.ts +555 -0
  227. package/templates/turborepo-pandacss/scripts/init.sh +92 -0
  228. package/templates/turborepo-pandacss/scripts/setup-dev.ts +640 -0
  229. package/templates/turborepo-pandacss/scripts/template-update.ts +277 -0
  230. package/templates/turborepo-pandacss/scripts/worktree/dev.ts +872 -0
  231. package/templates/turborepo-pandacss/test/globals.d.ts +1 -0
  232. package/templates/turborepo-pandacss/test/setup.ts +22 -0
  233. package/templates/turborepo-pandacss/tsconfig.json +46 -0
  234. package/templates/turborepo-pandacss/turbo.json +57 -0
  235. package/templates/turborepo-pandacss/vitest.config.ts +20 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/create.ts","../src/prompts/project.ts","../src/generators/template.ts","../src/utils/fs.ts","../src/utils/logger.ts","../src/generators/post-setup.ts","../src/commands/setup.ts","../src/prompts/setup.ts","../src/generators/tools/direnv.ts","../src/generators/tools/dotenvx.ts","../src/utils/package-json.ts","../src/generators/tools/volta.ts","../src/generators/tools/biome.ts","../src/generators/tools/husky.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { readFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport { createCommand } from \"./commands/create.js\";\nimport { setupCommand } from \"./commands/setup.js\";\n\n// package.jsonからバージョン情報を読み込み\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJsonPath = join(__dirname, \"../package.json\");\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n\nconst program = new Command();\n\nprogram\n .name(\"create-einja-app\")\n .description(\"CLI tool to create new projects with Einja Management Template\")\n .version(packageJson.version);\n\n// createコマンド\nprogram\n .argument(\"[project-name]\", \"Project name\")\n .option(\"--template <template>\", \"Template to use\", \"turborepo-pandacss\")\n .option(\"--skip-git\", \"Skip git initialization\")\n .option(\"--skip-install\", \"Skip package installation\")\n .option(\"-y, --yes\", \"Skip interactive prompts\")\n .action(\n async (\n projectName: string | undefined,\n options: {\n template: string;\n skipGit?: boolean;\n skipInstall?: boolean;\n yes?: boolean;\n }\n ) => {\n await createCommand(projectName, options);\n }\n );\n\n// setupコマンド\nprogram\n .command(\"setup\")\n .description(\"Setup tools for existing project\")\n .action(async () => {\n await setupCommand();\n });\n\nprogram.parse();\n","import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport ora from \"ora\";\nimport { promptProjectConfig, type ProjectConfig } from \"../prompts/project.js\";\nimport { generateTemplate } from \"../generators/template.js\";\nimport { execPostSetup } from \"../generators/post-setup.js\";\nimport * as logger from \"../utils/logger.js\";\n\n/**\n * CreateOptions型\n * createコマンドのオプション\n */\ninterface CreateOptions {\n template?: string;\n skipGit?: boolean;\n skipInstall?: boolean;\n yes?: boolean;\n}\n\n/**\n * プロジェクト名のバリデーション\n * @param projectName - プロジェクト名\n * @returns エラーメッセージ(問題なければundefined)\n */\nfunction validateProjectName(projectName: string): string | undefined {\n const regex = /^[a-zA-Z][a-zA-Z0-9_-]{0,49}$/;\n if (!regex.test(projectName)) {\n return \"プロジェクト名は英字で始まり、英数字・ハイフン・アンダースコアのみ使用できます(1〜50文字)\";\n }\n return undefined;\n}\n\n/**\n * プロジェクトディレクトリの存在確認\n * @param targetPath - ターゲットパス\n * @returns 存在する場合true\n */\nfunction checkProjectExists(targetPath: string): boolean {\n return existsSync(targetPath);\n}\n\n\n/**\n * createコマンドの実装\n * @param projectName - プロジェクト名(オプション)\n * @param options - コマンドオプション\n */\nexport async function createCommand(\n projectName: string | undefined,\n options: CreateOptions\n): Promise<void> {\n try {\n // プロンプトで設定収集\n let config: ProjectConfig;\n\n if (options.yes && projectName) {\n // --yes オプション: デフォルト値を使用\n const error = validateProjectName(projectName);\n if (error) {\n logger.error(error);\n process.exit(1);\n }\n\n config = {\n projectName,\n packageScope: \"@repo\",\n template: (options.template as \"turborepo-pandacss\" | \"minimal\") || \"turborepo-pandacss\",\n authMethod: \"google\",\n tools: {\n direnv: true,\n dotenvx: true,\n volta: true,\n biome: true,\n husky: true,\n },\n setupEinjaCli: true,\n worktreeConfig: undefined,\n };\n\n logger.info(`プロジェクト名: ${config.projectName}`);\n logger.info(`テンプレート: ${config.template}`);\n logger.info(`認証方式: ${config.authMethod}`);\n } else {\n // 対話式プロンプト\n config = await promptProjectConfig(projectName);\n }\n\n // ターゲットパスの解決\n const targetPath = resolve(process.cwd(), config.projectName);\n\n // プロジェクトディレクトリの存在確認\n if (checkProjectExists(targetPath)) {\n logger.error(`ディレクトリ '${config.projectName}' は既に存在します`);\n logger.info(\"別の名前を指定するか、既存ディレクトリを削除してください\");\n process.exit(1);\n }\n\n // テンプレート展開\n const spinner = ora(\"プロジェクトを作成中...\").start();\n\n try {\n await generateTemplate(config, targetPath);\n spinner.succeed(\"プロジェクトを作成しました\");\n } catch (error) {\n spinner.fail(\"プロジェクトの作成に失敗しました\");\n throw error;\n }\n\n // 生成後セットアップ実行\n await execPostSetup(config, targetPath, {\n skipGit: options.skipGit,\n skipInstall: options.skipInstall,\n });\n } catch (error) {\n logger.error(\"エラーが発生しました:\");\n if (error instanceof Error) {\n logger.error(error.message);\n } else {\n logger.error(String(error));\n }\n process.exit(1);\n }\n}\n","import inquirer from \"inquirer\";\nimport type { ProjectConfig, WorktreeConfig, App } from \"../types/index.js\";\n\nexport type { ProjectConfig, WorktreeConfig, App };\n\n/**\n * プロジェクト作成用プロンプトを実行\n * @param defaultProjectName - デフォルトのプロジェクト名\n * @returns ProjectConfig - プロジェクト設定\n */\nexport async function promptProjectConfig(\n defaultProjectName?: string\n): Promise<ProjectConfig> {\n const answers = await inquirer.prompt([\n {\n type: \"input\",\n name: \"projectName\",\n message: \"プロジェクト名:\",\n default: defaultProjectName || \"my-project\",\n validate: (input: string): boolean | string => {\n // 英数字・ハイフン・アンダースコアのみ許可、先頭は英字、1〜50文字\n const regex = /^[a-zA-Z][a-zA-Z0-9_-]{0,49}$/;\n if (!regex.test(input)) {\n return \"プロジェクト名は英字で始まり、英数字・ハイフン・アンダースコアのみ使用できます(1〜50文字)\";\n }\n return true;\n },\n },\n {\n type: \"input\",\n name: \"packageScope\",\n message: \"パッケージスコープ:\",\n default: \"@repo\",\n validate: (input: string): boolean | string => {\n // @で始まり、英数字・ハイフン・アンダースコアのみ許可\n const regex = /^@[a-zA-Z][a-zA-Z0-9_-]{0,49}$/;\n if (!regex.test(input)) {\n return \"パッケージスコープは@で始まり、英数字・ハイフン・アンダースコアのみ使用できます\";\n }\n return true;\n },\n },\n {\n type: \"list\",\n name: \"template\",\n message: \"テンプレート:\",\n choices: [\n {\n name: \"turborepo-pandacss (フルスタック管理画面)\",\n value: \"turborepo-pandacss\",\n },\n { name: \"minimal (最小構成)\", value: \"minimal\" },\n ],\n default: \"turborepo-pandacss\",\n },\n {\n type: \"list\",\n name: \"authMethod\",\n message: \"認証方式:\",\n choices: [\n { name: \"NextAuth.js (Google OAuth)\", value: \"google\" },\n { name: \"NextAuth.js (Credentials)\", value: \"credentials\" },\n { name: \"NextAuth.js (GitHub OAuth)\", value: \"github\" },\n { name: \"なし\", value: \"none\" },\n ],\n default: \"google\",\n },\n {\n type: \"checkbox\",\n name: \"tools\",\n message: \"環境ツールを選択(複数選択可):\",\n choices: [\n {\n name: \"direnv(ディレクトリごとの環境変数管理)\",\n value: \"direnv\",\n checked: true,\n },\n {\n name: \"dotenvx(.env暗号化)\",\n value: \"dotenvx\",\n checked: true,\n },\n {\n name: \"Volta(Node.jsバージョン管理)\",\n value: \"volta\",\n checked: true,\n },\n ],\n },\n {\n type: \"confirm\",\n name: \"setupEinjaCli\",\n message: \"@einja/cli を自動セットアップしますか?\",\n default: true,\n },\n {\n type: \"confirm\",\n name: \"customizeWorktree\",\n message: \"Worktree設定をカスタマイズしますか?\",\n default: false,\n },\n ]);\n\n // ツール選択を boolean フラグに変換\n const toolsArray = answers.tools as string[];\n const tools = {\n direnv: toolsArray.includes(\"direnv\"),\n dotenvx: toolsArray.includes(\"dotenvx\"),\n volta: toolsArray.includes(\"volta\"),\n biome: true,\n husky: true,\n };\n\n let worktreeConfig: WorktreeConfig | undefined;\n\n // Worktree設定カスタマイズ\n if (answers.customizeWorktree) {\n const worktreeAnswers = await inquirer.prompt([\n {\n type: \"input\",\n name: \"postgresPort\",\n message: \"PostgreSQLポート番号:\",\n default: \"25432\",\n validate: (input: string): boolean | string => {\n const port = Number.parseInt(input, 10);\n if (Number.isNaN(port) || port < 1024 || port > 65535) {\n return \"ポート番号は1024〜65535の範囲で指定してください\";\n }\n return true;\n },\n },\n {\n type: \"input\",\n name: \"containerName\",\n message: \"Dockerコンテナ名:\",\n default: `${answers.projectName}-postgres`,\n },\n {\n type: \"input\",\n name: \"appId\",\n message: \"アプリケーションID:\",\n default: \"web\",\n },\n {\n type: \"input\",\n name: \"portRangeStart\",\n message: \"アプリポート範囲開始:\",\n default: \"3000\",\n validate: (input: string): boolean | string => {\n const port = Number.parseInt(input, 10);\n if (Number.isNaN(port) || port < 1024 || port > 65535) {\n return \"ポート番号は1024〜65535の範囲で指定してください\";\n }\n return true;\n },\n },\n {\n type: \"input\",\n name: \"rangeSize\",\n message: \"ポート範囲サイズ:\",\n default: \"1000\",\n validate: (input: string): boolean | string => {\n const size = Number.parseInt(input, 10);\n if (Number.isNaN(size) || size < 1 || size > 10000) {\n return \"範囲サイズは1〜10000の範囲で指定してください\";\n }\n return true;\n },\n },\n ]);\n\n worktreeConfig = {\n postgres: {\n port: Number.parseInt(worktreeAnswers.postgresPort, 10),\n containerName: worktreeAnswers.containerName,\n },\n apps: [\n {\n id: worktreeAnswers.appId,\n portRangeStart: Number.parseInt(worktreeAnswers.portRangeStart, 10),\n rangeSize: Number.parseInt(worktreeAnswers.rangeSize, 10),\n },\n ],\n };\n }\n\n return {\n projectName: answers.projectName,\n packageScope: answers.packageScope,\n template: answers.template,\n authMethod: answers.authMethod,\n tools,\n setupEinjaCli: answers.setupEinjaCli,\n worktreeConfig,\n };\n}\n","import fsExtra from \"fs-extra\";\nconst { copySync, readFileSync, writeFileSync, existsSync, removeSync } = fsExtra;\nimport { glob } from \"glob\";\nimport { dirname, join, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ProjectConfig } from \"../prompts/project.js\";\nimport { ensureDir } from \"../utils/fs.js\";\nimport * as logger from \"../utils/logger.js\";\n\n/**\n * TemplateVariables型\n * テンプレート変数(プレースホルダー置換用)\n */\nexport interface TemplateVariables {\n projectName: string;\n packageName: string;\n description: string;\n}\n\n/**\n * テンプレートディレクトリのパスを取得\n * @param templateName - テンプレート名\n * @returns テンプレートディレクトリパス\n */\nfunction getTemplatePath(templateName: string): string {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n\n // バンドル後(dist/cli.js)とソース実行(src/generators/template.ts)の両方に対応\n // dist/cli.js -> ../templates/ (1階層上)\n // src/generators/template.ts -> ../../templates/ (2階層上)\n const distPath = join(__dirname, \"../templates\", templateName);\n const srcPath = join(__dirname, \"../../templates\", templateName);\n\n if (existsSync(distPath)) {\n return distPath;\n }\n if (existsSync(srcPath)) {\n return srcPath;\n }\n\n // どちらも存在しない場合はdistPathを返す(エラーメッセージ用)\n return distPath;\n}\n\n/**\n * 認証方式に応じた除外パターンを取得\n * @param authMethod - 認証方式\n * @returns 除外パターン配列\n */\nfunction getAuthExcludePatterns(authMethod: string): string[] {\n if (authMethod === \"none\") {\n return [\n \"**/api/auth/**\",\n \"**/packages/auth/**\",\n \"**/signin/**\",\n \"**/signup/**\",\n ];\n }\n return [];\n}\n\n/**\n * ファイル内容のプレースホルダー変数を置換\n * @param content - ファイル内容\n * @param variables - 置換する変数\n * @returns 置換後の内容\n */\nfunction replacePlaceholders(\n content: string,\n variables: TemplateVariables\n): string {\n let result = content;\n\n // {{projectName}} の置換\n result = result.replaceAll(\"{{projectName}}\", variables.projectName);\n\n // {{packageName}}/ の置換(長いパターンを先に置換)\n result = result.replaceAll(\"{{packageName}}/\", `${variables.packageName}/`);\n\n // {{packageName}} の置換\n result = result.replaceAll(\"{{packageName}}\", variables.packageName);\n\n // {{description}} の置換\n result = result.replaceAll(\"{{description}}\", variables.description);\n\n // @repo/ の置換(パッケージスコープ)\n result = result.replaceAll(\"@repo/\", `${variables.packageName}/`);\n\n return result;\n}\n\n/**\n * ファイルの変数置換処理\n * @param filePath - ファイルパス\n * @param variables - 置換する変数\n */\nfunction processFileVariables(\n filePath: string,\n variables: TemplateVariables\n): void {\n // バイナリファイルは処理しない\n const binaryExtensions = [\".png\", \".jpg\", \".jpeg\", \".gif\", \".ico\", \".woff\", \".woff2\", \".ttf\", \".eot\"];\n if (binaryExtensions.some((ext) => filePath.endsWith(ext))) {\n return;\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\");\n const replaced = replacePlaceholders(content, variables);\n\n if (content !== replaced) {\n writeFileSync(filePath, replaced, \"utf-8\");\n }\n } catch (error) {\n // 読み込みに失敗した場合はスキップ(バイナリファイル等)\n logger.warn(`変数置換をスキップ: ${filePath}`);\n }\n}\n\n/**\n * .templateファイルのリネーム処理\n * @param targetPath - ターゲットディレクトリパス\n */\nfunction renameTemplateFiles(targetPath: string): void {\n const templateFiles = glob.sync(\"**/*.template\", {\n cwd: targetPath,\n absolute: true,\n dot: true,\n });\n\n for (const file of templateFiles) {\n const newPath = file.replace(/\\.template$/, \"\");\n copySync(file, newPath);\n removeSync(file);\n }\n}\n\n/**\n * 認証方式に応じたファイル除外処理\n * @param targetPath - ターゲットディレクトリパス\n * @param authMethod - 認証方式\n */\nfunction excludeAuthFiles(targetPath: string, authMethod: string): void {\n const excludePatterns = getAuthExcludePatterns(authMethod);\n\n if (excludePatterns.length === 0) {\n return;\n }\n\n logger.info(\"認証方式に応じたファイルを除外中...\");\n\n for (const pattern of excludePatterns) {\n const files = glob.sync(pattern, {\n cwd: targetPath,\n absolute: true,\n dot: true,\n });\n\n for (const file of files) {\n removeSync(file);\n }\n }\n}\n\n/**\n * テンプレートを展開\n * @param config - プロジェクト設定\n * @param targetPath - ターゲットディレクトリパス\n */\nexport async function generateTemplate(\n config: ProjectConfig,\n targetPath: string\n): Promise<void> {\n const templatePath = getTemplatePath(config.template);\n\n // テンプレートディレクトリの存在確認\n if (!existsSync(templatePath)) {\n throw new Error(`テンプレートが見つかりません: ${config.template}`);\n }\n\n logger.info(\"テンプレートをコピー中...\");\n\n // ターゲットディレクトリの作成\n await ensureDir(targetPath);\n\n // テンプレートファイルをコピー\n copySync(templatePath, targetPath, {\n filter: (src: string): boolean => {\n const relativePath = relative(templatePath, src);\n\n // 除外パターン(ディレクトリ名やファイル名として完全一致するもの)\n const excludePatterns = [\n \"node_modules\",\n \".git\",\n \".next\",\n \".turbo\",\n \"out\",\n \"dist\",\n \"logs\",\n \".env\",\n \".env.local\",\n \".DS_Store\",\n \"Thumbs.db\",\n \"coverage\",\n ];\n\n // ファイル拡張子パターン(*.log など)\n const excludeExtensions = [\".log\"];\n\n // パスセグメントに分割(/ または \\ で分割)\n const pathSegments = relativePath.split(/[/\\\\]/);\n\n // パスセグメント単位で完全一致チェック\n // これにより \"out\" は \"out/\" ディレクトリにマッチするが\n // \"logout-button.tsx\" にはマッチしない\n const matchesExcludePattern = excludePatterns.some((pattern) =>\n pathSegments.includes(pattern)\n );\n\n // 拡張子チェック\n const matchesExtension = excludeExtensions.some((ext) =>\n relativePath.endsWith(ext)\n );\n\n return !matchesExcludePattern && !matchesExtension;\n },\n });\n\n // 認証方式に応じたファイル除外\n excludeAuthFiles(targetPath, config.authMethod);\n\n // .templateファイルのリネーム\n renameTemplateFiles(targetPath);\n\n // 変数置換\n logger.info(\"プレースホルダー変数を置換中...\");\n\n const variables: TemplateVariables = {\n projectName: config.projectName,\n packageName: config.packageScope,\n description: `${config.projectName} - Einja Management Template`,\n };\n\n const allFiles = glob.sync(\"**/*\", {\n cwd: targetPath,\n absolute: true,\n nodir: true,\n dot: true,\n });\n\n for (const file of allFiles) {\n processFileVariables(file, variables);\n }\n\n logger.success(\"テンプレート展開完了\");\n}\n","import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type { ConflictStrategy } from \"../types/index.js\";\n\n/**\n * 競合戦略に基づいてファイルを書き込む\n */\nexport function writeWithStrategy(\n filePath: string,\n content: string,\n strategy: ConflictStrategy\n): boolean {\n const exists = existsSync(filePath);\n\n if (!exists) {\n ensureDir(dirname(filePath));\n writeFileSync(filePath, content, \"utf-8\");\n return true;\n }\n\n switch (strategy) {\n case \"overwrite\": {\n writeFileSync(filePath, content, \"utf-8\");\n return true;\n }\n\n case \"merge\": {\n const existingContent = readFileSync(filePath, \"utf-8\");\n const mergedContent = mergeContent(existingContent, content);\n writeFileSync(filePath, mergedContent, \"utf-8\");\n return true;\n }\n\n case \"skip\": {\n return false;\n }\n\n default: {\n const _exhaustiveCheck: never = strategy;\n throw new Error(`Unknown strategy: ${_exhaustiveCheck}`);\n }\n }\n}\n\n/**\n * 既存コンテンツと新規コンテンツをマージする\n */\nfunction mergeContent(existing: string, newContent: string): string {\n if (existing.includes(newContent)) {\n return existing;\n }\n return `${existing}\\n${newContent}`;\n}\n\n/**\n * ディレクトリが存在しない場合は作成する\n */\nexport function ensureDir(dirPath: string): void {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n}\n\n/**\n * .gitignoreに行を追加する\n */\nexport function appendToGitignore(targetDir: string, line: string): void {\n const gitignorePath = join(targetDir, \".gitignore\");\n\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, `${line}\\n`, \"utf-8\");\n return;\n }\n\n const content = readFileSync(gitignorePath, \"utf-8\");\n if (content.includes(line)) {\n return;\n }\n\n appendFileSync(gitignorePath, `\\n${line}\\n`, \"utf-8\");\n}\n\n/**\n * ファイルが存在するか確認する\n */\nexport function fileExists(filePath: string): boolean {\n return existsSync(filePath);\n}\n","import chalk from \"chalk\";\n\n/**\n * 情報メッセージを出力\n * @param message - メッセージ\n */\nexport function info(message: string): void {\n console.log(chalk.blue(\"ℹ\"), message);\n}\n\n/**\n * 成功メッセージを出力(緑色)\n * @param message - メッセージ\n */\nexport function success(message: string): void {\n console.log(chalk.green(\"✔\"), message);\n}\n\n/**\n * 警告メッセージを出力(黄色)\n * @param message - メッセージ\n */\nexport function warn(message: string): void {\n console.log(chalk.yellow(\"⚠\"), message);\n}\n\n/**\n * エラーメッセージを出力(赤色)\n * @param message - メッセージ\n */\nexport function error(message: string): void {\n console.error(chalk.red(\"✖\"), message);\n}\n","import { execa, execaSync } from \"execa\";\nimport chalk from \"chalk\";\nimport inquirer from \"inquirer\";\nimport ora from \"ora\";\nimport type { ProjectConfig } from \"../types/index.js\";\nimport * as logger from \"../utils/logger.js\";\n\n/**\n * PostSetupOptions型\n * 生成後セットアップのオプション\n */\nexport interface PostSetupOptions {\n skipGit?: boolean;\n skipInstall?: boolean;\n}\n\n/**\n * direnvコマンドが利用可能かチェック\n * @returns direnvコマンドが利用可能な場合true\n */\nfunction isDirenvAvailable(): boolean {\n try {\n execaSync(\"which\", [\"direnv\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * direnv allowの確認プロンプトを表示し、実行する\n * @param targetPath - プロジェクトディレクトリ\n */\nasync function promptAndExecuteDirenvAllow(targetPath: string): Promise<void> {\n try {\n const { shouldAllow } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"shouldAllow\",\n message: \"direnv allow を実行しますか?(環境変数を有効化します)\",\n default: true,\n },\n ]);\n\n if (shouldAllow) {\n try {\n await execa(\"direnv\", [\"allow\"], { cwd: targetPath });\n logger.success(\"direnv allow を実行しました\");\n } catch (error) {\n logger.warn(\"direnv allow の実行に失敗しました\");\n logger.info(\"後で手動で 'direnv allow' を実行してください\");\n }\n } else {\n logger.info(\"direnv allow をスキップしました\");\n logger.info(\"後で手動で 'direnv allow' を実行してください\");\n }\n } catch (error) {\n logger.info(\"direnv allow をスキップしました\");\n }\n}\n\n/**\n * 完了メッセージを表示\n * @param config - プロジェクト設定\n */\nfunction printCompletionMessage(config: ProjectConfig): void {\n console.log();\n logger.success(\"プロジェクトの作成が完了しました!\");\n console.log();\n console.log(chalk.bold(\"次のステップ:\"));\n console.log();\n console.log(chalk.cyan(` cd ${config.projectName}`));\n console.log(chalk.cyan(\" docker-compose up -d postgres\"));\n console.log(chalk.cyan(\" pnpm dev\"));\n console.log();\n console.log(chalk.gray(\"開発サーバー: http://localhost:3000\"));\n console.log();\n console.log(chalk.gray(\"詳細は README.md をご確認ください。\"));\n console.log();\n}\n\n/**\n * 生成後セットアップを実行\n * @param config - プロジェクト設定\n * @param targetPath - プロジェクトディレクトリ\n * @param options - セットアップオプション\n */\nexport async function execPostSetup(\n config: ProjectConfig,\n targetPath: string,\n options: PostSetupOptions\n): Promise<void> {\n const { skipGit, skipInstall } = options;\n\n // Git初期化\n if (!skipGit) {\n const gitSpinner = ora(\"Gitリポジトリを初期化中...\").start();\n try {\n await execa(\"git\", [\"init\"], { cwd: targetPath });\n await execa(\"git\", [\"add\", \".\"], { cwd: targetPath });\n await execa(\"git\", [\"commit\", \"-m\", \"Initial commit\"], { cwd: targetPath });\n gitSpinner.succeed(\"Gitリポジトリを初期化しました\");\n } catch (error) {\n gitSpinner.fail(\"Gitリポジトリの初期化に失敗しました\");\n logger.warn(\"後で手動で 'git init' を実行してください\");\n }\n }\n\n // 依存関係インストール\n if (!skipInstall) {\n const installSpinner = ora(\"依存関係をインストール中...\").start();\n try {\n await execa(\"pnpm\", [\"install\"], { cwd: targetPath });\n installSpinner.succeed(\"依存関係をインストールしました\");\n\n // Prismaクライアント生成\n const prismaSpinner = ora(\"Prismaクライアントを生成中...\").start();\n try {\n await execa(\"pnpm\", [\"db:generate\"], { cwd: targetPath });\n prismaSpinner.succeed(\"Prismaクライアントを生成しました\");\n } catch (error) {\n prismaSpinner.fail(\"Prismaクライアントの生成に失敗しました\");\n logger.warn(\"後で手動で 'pnpm db:generate' を実行してください\");\n }\n } catch (error) {\n installSpinner.fail(\"依存関係のインストールに失敗しました\");\n logger.warn(\"後で手動で 'pnpm install' を実行してください\");\n }\n }\n\n // direnv allow(direnvが有効で、コマンドが利用可能な場合)\n if (config.tools.direnv && isDirenvAvailable()) {\n await promptAndExecuteDirenvAllow(targetPath);\n }\n\n // @einja/cli init\n if (config.setupEinjaCli) {\n const einjaSpinner = ora(\"@einja/cli を初期化中...\").start();\n try {\n await execa(\"npx\", [\"@einja/cli\", \"init\"], { cwd: targetPath });\n einjaSpinner.succeed(\"@einja/cli を初期化しました\");\n } catch (error) {\n einjaSpinner.fail(\"@einja/cli の初期化に失敗しました\");\n logger.warn(\"後で手動で 'npx @einja/cli init' を実行してください\");\n }\n }\n\n // 完了メッセージ表示\n printCompletionMessage(config);\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ora from \"ora\";\nimport { promptSetupConfig } from \"../prompts/setup.js\";\nimport {\n setupDirenv,\n setupDotenvx,\n setupVolta,\n setupBiome,\n setupHusky,\n promptDirenvAllow,\n} from \"../generators/tools/index.js\";\nimport type { ToolSetupOptions } from \"../types/index.js\";\nimport * as logger from \"../utils/logger.js\";\n\n/**\n * setupコマンド - 既存プロジェクトへのツール追加\n *\n * US-002: 既存プロジェクトへの環境ツール追加\n * AC-002-1: `npx create-einja-app --setup` で対話式プロンプトが表示される\n * AC-002-2: 既存の設定ファイルがある場合、マージ・上書き・スキップを選択できる\n * AC-002-3: 選択したツールのみがセットアップされる\n * AC-002-4: 既存ファイルを破壊せずにツールが追加される(マージモード時)\n */\nexport async function setupCommand(): Promise<void> {\n const targetDir = process.cwd();\n\n // 1. プロジェクトディレクトリ確認(package.json存在確認)\n const packageJsonPath = join(targetDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n logger.error(\"エラー: package.jsonが見つかりません\");\n logger.info(\"このコマンドは既存のプロジェクトディレクトリで実行してください\");\n process.exit(1);\n }\n\n logger.info(\"既存プロジェクトへのツール追加を開始します\");\n logger.info(\"\");\n\n // 2. プロンプトで設定収集\n const config = await promptSetupConfig();\n\n logger.info(\"\");\n logger.info(\"セットアップを開始します...\");\n logger.info(\"\");\n\n const options: ToolSetupOptions = {\n targetDir,\n conflictStrategy: config.conflictStrategy,\n };\n\n // 3. 選択されたツールのセットアップ\n let setupCount = 0;\n\n if (config.tools.direnv) {\n const spin = ora(\"direnv をセットアップしています...\").start();\n try {\n setupDirenv(options);\n spin.succeed(\"direnv セットアップ完了\");\n setupCount++;\n } catch (error) {\n spin.fail(\"direnv セットアップ失敗\");\n logger.error(\n error instanceof Error ? error.message : \"予期しないエラーが発生しました\"\n );\n }\n }\n\n if (config.tools.dotenvx) {\n const spin = ora(\"dotenvx をセットアップしています...\").start();\n try {\n setupDotenvx(options);\n spin.succeed(\"dotenvx セットアップ完了\");\n setupCount++;\n } catch (error) {\n spin.fail(\"dotenvx セットアップ失敗\");\n logger.error(\n error instanceof Error ? error.message : \"予期しないエラーが発生しました\"\n );\n }\n }\n\n if (config.tools.volta) {\n const spin = ora(\"Volta をセットアップしています...\").start();\n try {\n setupVolta(options);\n spin.succeed(\"Volta セットアップ完了\");\n setupCount++;\n } catch (error) {\n spin.fail(\"Volta セットアップ失敗\");\n logger.error(\n error instanceof Error ? error.message : \"予期しないエラーが発生しました\"\n );\n }\n }\n\n if (config.tools.biome) {\n const spin = ora(\"Biome をセットアップしています...\").start();\n try {\n setupBiome(options);\n spin.succeed(\"Biome セットアップ完了\");\n setupCount++;\n } catch (error) {\n spin.fail(\"Biome セットアップ失敗\");\n logger.error(\n error instanceof Error ? error.message : \"予期しないエラーが発生しました\"\n );\n }\n }\n\n if (config.tools.husky) {\n const spin = ora(\"Husky をセットアップしています...\").start();\n try {\n setupHusky(options);\n spin.succeed(\"Husky セットアップ完了\");\n setupCount++;\n } catch (error) {\n spin.fail(\"Husky セットアップ失敗\");\n logger.error(\n error instanceof Error ? error.message : \"予期しないエラーが発生しました\"\n );\n }\n }\n\n logger.info(\"\");\n\n // 4. direnv allowの確認プロンプト(direnvがセットアップされた場合のみ)\n if (config.tools.direnv) {\n await promptDirenvAllow(targetDir);\n logger.info(\"\");\n }\n\n // 5. 完了メッセージ\n logger.success(`✅ セットアップが完了しました!(${setupCount}個のツール)`);\n logger.info(\"\");\n logger.info(\"次のステップ:\");\n\n if (config.tools.direnv) {\n logger.info(\" 1. .envrc を編集して環境変数を設定\");\n logger.info(\" 2. direnv allow を実行(まだの場合)\");\n }\n\n if (config.tools.dotenvx) {\n logger.info(\" - .env.example をコピーして .env を作成\");\n logger.info(\" - 必要に応じて pnpm env:encrypt で暗号化\");\n }\n\n if (config.tools.biome) {\n logger.info(\" - pnpm lint でコードをチェック\");\n logger.info(\" - pnpm format:fix でフォーマット\");\n }\n\n if (config.tools.husky) {\n logger.info(\" - pnpm install でHuskyフックをインストール\");\n }\n\n logger.info(\"\");\n logger.success(\"開発を開始できます!\");\n}\n","import inquirer from \"inquirer\";\n\n/**\n * SetupConfig型\n * 既存プロジェクトへのツール追加設定\n */\nexport interface SetupConfig {\n tools: {\n direnv: boolean;\n dotenvx: boolean;\n volta: boolean;\n biome: boolean;\n husky: boolean;\n };\n conflictStrategy: \"merge\" | \"overwrite\" | \"skip\";\n}\n\n/**\n * セットアップ用プロンプトを実行\n * @returns SetupConfig - セットアップ設定\n */\nexport async function promptSetupConfig(): Promise<SetupConfig> {\n const answers = await inquirer.prompt([\n {\n type: \"checkbox\",\n name: \"tools\",\n message: \"セットアップするツールを選択(複数選択可):\",\n choices: [\n {\n name: \"direnv(ディレクトリごとの環境変数管理)\",\n value: \"direnv\",\n checked: true,\n },\n {\n name: \"dotenvx(.env暗号化)\",\n value: \"dotenvx\",\n checked: true,\n },\n {\n name: \"Volta(Node.jsバージョン管理)\",\n value: \"volta\",\n checked: true,\n },\n {\n name: \"Biome(Linter / Formatter)\",\n value: \"biome\",\n checked: false,\n },\n {\n name: \"Husky + lint-staged(Git hooks)\",\n value: \"husky\",\n checked: false,\n },\n ],\n },\n {\n type: \"list\",\n name: \"conflictStrategy\",\n message: \"既存ファイルがある場合の動作:\",\n choices: [\n {\n name: \"マージ(既存設定を保持しつつ追加)\",\n value: \"merge\",\n },\n {\n name: \"上書き\",\n value: \"overwrite\",\n },\n {\n name: \"スキップ\",\n value: \"skip\",\n },\n ],\n default: \"merge\",\n },\n ]);\n\n // ツール選択を boolean フラグに変換\n const toolsArray = answers.tools as string[];\n const tools = {\n direnv: toolsArray.includes(\"direnv\"),\n dotenvx: toolsArray.includes(\"dotenvx\"),\n volta: toolsArray.includes(\"volta\"),\n biome: toolsArray.includes(\"biome\"),\n husky: toolsArray.includes(\"husky\"),\n };\n\n return {\n tools,\n conflictStrategy: answers.conflictStrategy,\n };\n}\n","import { join } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport inquirer from \"inquirer\";\nimport type { ToolSetupOptions } from \"../../types/index.js\";\nimport { writeWithStrategy, appendToGitignore } from \"../../utils/fs.js\";\nimport * as logger from \"../../utils/logger.js\";\n\nconst ENVRC_CONTENT = `# direnv configuration\n# Load .env if it exists\ndotenv_if_exists\n\n# Allow local overrides\ndotenv_if_exists .env.local\n`;\n\nconst ENVRC_EXAMPLE_CONTENT = `# Example direnv configuration\n# Copy this file to .envrc and run 'direnv allow'\n\n# Load environment variables from .env\ndotenv_if_exists\n\n# Load local overrides\ndotenv_if_exists .env.local\n`;\n\n/**\n * direnvのセットアップを実行する\n *\n * AC-003-1: .envrc ファイルが生成される\n * AC-003-2: .envrc.example ファイルが生成される\n * AC-003-3: .gitignore に .envrc が追加される\n */\nexport function setupDirenv(options: ToolSetupOptions): void {\n const { targetDir, conflictStrategy } = options;\n\n const envrcPath = join(targetDir, \".envrc\");\n const envrcExamplePath = join(targetDir, \".envrc.example\");\n\n writeWithStrategy(envrcPath, ENVRC_CONTENT, conflictStrategy);\n\n writeWithStrategy(envrcExamplePath, ENVRC_EXAMPLE_CONTENT, conflictStrategy);\n\n appendToGitignore(targetDir, \".envrc\");\n}\n\n/**\n * direnv allowの確認プロンプトを表示し、実行する\n *\n * AC-003-4: 確認後 `direnv allow` が実行される\n *\n * @param targetDir - ターゲットディレクトリ\n */\nexport async function promptDirenvAllow(targetDir: string): Promise<void> {\n try {\n const { shouldAllow } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"shouldAllow\",\n message: \"direnv allow を実行しますか?(環境変数を有効化します)\",\n default: true,\n },\n ]);\n\n if (shouldAllow) {\n try {\n execSync(\"direnv allow\", { cwd: targetDir, stdio: \"inherit\" });\n logger.success(\"direnv allow を実行しました\");\n } catch (error) {\n logger.warn(\"direnv allow の実行に失敗しました\");\n logger.info(\"後で手動で 'direnv allow' を実行してください\");\n }\n } else {\n logger.info(\"direnv allow をスキップしました\");\n logger.info(\"後で手動で 'direnv allow' を実行してください\");\n }\n } catch (error) {\n // プロンプトがキャンセルされた場合など\n logger.info(\"direnv allow をスキップしました\");\n }\n}\n","import { join } from \"node:path\";\nimport type { ToolSetupOptions } from \"../../types/index.js\";\nimport { writeWithStrategy } from \"../../utils/fs.js\";\nimport { addDependencies, addScripts } from \"../../utils/package-json.js\";\n\nconst ENV_EXAMPLE_CONTENT = `# Environment variables template\n# Copy this file to .env and fill in the values\n\n# Database\nDATABASE_URL=\"postgresql://user:password@localhost:25432/dbname\"\n\n# NextAuth\nNEXTAUTH_URL=\"http://localhost:3000\"\nNEXTAUTH_SECRET=\"your-secret-here\"\n\n# OAuth (if using)\n# GOOGLE_CLIENT_ID=\"\"\n# GOOGLE_CLIENT_SECRET=\"\"\n# GITHUB_CLIENT_ID=\"\"\n# GITHUB_CLIENT_SECRET=\"\"\n`;\n\n/**\n * dotenvxのセットアップを実行する\n *\n * AC-004-1: package.jsonに依存関係が追加される\n * AC-004-2: npm scriptsにdotenvxコマンドが追加される\n * AC-004-3: .env.example が生成される\n */\nexport function setupDotenvx(options: ToolSetupOptions): void {\n const { targetDir, conflictStrategy } = options;\n\n addDependencies(targetDir, {\n \"@dotenvx/dotenvx\": \"^1.29.0\",\n });\n\n addScripts(targetDir, {\n \"env:encrypt\": \"dotenvx encrypt\",\n \"env:decrypt\": \"dotenvx decrypt\",\n });\n\n const envExamplePath = join(targetDir, \".env.example\");\n writeWithStrategy(envExamplePath, ENV_EXAMPLE_CONTENT, conflictStrategy);\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fileExists } from \"./fs.js\";\n\ntype PackageJson = {\n name?: string;\n version?: string;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n volta?: {\n node?: string;\n pnpm?: string;\n };\n \"lint-staged\"?: Record<string, string | string[]>;\n [key: string]: unknown;\n};\n\n/**\n * package.jsonを読み込む\n */\nexport function readPackageJson(targetDir: string): PackageJson {\n const packageJsonPath = join(targetDir, \"package.json\");\n\n if (!fileExists(packageJsonPath)) {\n return {};\n }\n\n const content = readFileSync(packageJsonPath, \"utf-8\");\n return JSON.parse(content) as PackageJson;\n}\n\n/**\n * package.jsonに書き込む\n */\nexport function writePackageJson(targetDir: string, data: PackageJson): void {\n const packageJsonPath = join(targetDir, \"package.json\");\n const content = JSON.stringify(data, null, 2);\n writeFileSync(packageJsonPath, `${content}\\n`, \"utf-8\");\n}\n\n/**\n * package.jsonにスクリプトを追加する\n */\nexport function addScripts(\n targetDir: string,\n scripts: Record<string, string>\n): void {\n const pkg = readPackageJson(targetDir);\n pkg.scripts = { ...pkg.scripts, ...scripts };\n writePackageJson(targetDir, pkg);\n}\n\n/**\n * package.jsonに依存関係を追加する\n */\nexport function addDependencies(\n targetDir: string,\n dependencies: Record<string, string>,\n dev = false\n): void {\n const pkg = readPackageJson(targetDir);\n\n if (dev) {\n pkg.devDependencies = { ...pkg.devDependencies, ...dependencies };\n } else {\n pkg.dependencies = { ...pkg.dependencies, ...dependencies };\n }\n\n writePackageJson(targetDir, pkg);\n}\n\n/**\n * package.jsonにVoltaフィールドを追加する\n */\nexport function addVoltaField(\n targetDir: string,\n nodeVersion: string,\n pnpmVersion: string\n): void {\n const pkg = readPackageJson(targetDir);\n pkg.volta = {\n node: nodeVersion,\n pnpm: pnpmVersion,\n };\n writePackageJson(targetDir, pkg);\n}\n\n/**\n * package.jsonにlint-staged設定を追加する\n */\nexport function addLintStaged(\n targetDir: string,\n config: Record<string, string | string[]>\n): void {\n const pkg = readPackageJson(targetDir);\n pkg[\"lint-staged\"] = { ...pkg[\"lint-staged\"], ...config };\n writePackageJson(targetDir, pkg);\n}\n","import { join } from \"node:path\";\nimport type { ToolSetupOptions } from \"../../types/index.js\";\nimport { writeWithStrategy } from \"../../utils/fs.js\";\nimport { addVoltaField } from \"../../utils/package-json.js\";\n\nconst NODE_VERSION = \"22.16.0\";\nconst PNPM_VERSION = \"9.15.0\";\n\nconst NODE_VERSION_CONTENT = `${NODE_VERSION}\n`;\n\n/**\n * Voltaのセットアップを実行する\n *\n * AC-005-1: package.jsonにvoltaフィールドが追加される\n * AC-005-2: .node-version ファイルが生成される\n */\nexport function setupVolta(options: ToolSetupOptions): void {\n const { targetDir, conflictStrategy } = options;\n\n addVoltaField(targetDir, NODE_VERSION, PNPM_VERSION);\n\n const nodeVersionPath = join(targetDir, \".node-version\");\n writeWithStrategy(nodeVersionPath, NODE_VERSION_CONTENT, conflictStrategy);\n}\n","import { join } from \"node:path\";\nimport type { ToolSetupOptions } from \"../../types/index.js\";\nimport { writeWithStrategy, ensureDir } from \"../../utils/fs.js\";\nimport { addDependencies, addScripts } from \"../../utils/package-json.js\";\n\nconst BIOME_CONFIG = `{\n \"$schema\": \"https://biomejs.dev/schemas/1.9.4/schema.json\",\n \"vcs\": {\n \"enabled\": true,\n \"clientKind\": \"git\",\n \"useIgnoreFile\": true\n },\n \"files\": {\n \"ignoreUnknown\": false,\n \"ignore\": [\"node_modules\", \"dist\", \".next\", \"out\", \"build\", \"coverage\"]\n },\n \"formatter\": {\n \"enabled\": true,\n \"indentStyle\": \"space\",\n \"indentWidth\": 2,\n \"lineEnding\": \"lf\",\n \"lineWidth\": 100\n },\n \"organizeImports\": {\n \"enabled\": true\n },\n \"linter\": {\n \"enabled\": true,\n \"rules\": {\n \"recommended\": true\n }\n },\n \"javascript\": {\n \"formatter\": {\n \"quoteStyle\": \"double\",\n \"trailingCommas\": \"es5\",\n \"semicolons\": \"always\",\n \"arrowParentheses\": \"always\"\n }\n }\n}\n`;\n\nconst VSCODE_SETTINGS = `{\n \"editor.defaultFormatter\": \"biomejs.biome\",\n \"editor.formatOnSave\": true,\n \"editor.codeActionsOnSave\": {\n \"quickfix.biome\": \"explicit\",\n \"source.organizeImports.biome\": \"explicit\"\n },\n \"[javascript]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[typescript]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n },\n \"[json]\": {\n \"editor.defaultFormatter\": \"biomejs.biome\"\n }\n}\n`;\n\n/**\n * Biomeのセットアップを実行する(--setupモードのみ)\n *\n * AC-006-1: biome.json が生成される\n * AC-006-2: package.jsonにlint/formatスクリプトが追加される\n * AC-006-3: VSCode設定が追加される\n */\nexport function setupBiome(options: ToolSetupOptions): void {\n const { targetDir, conflictStrategy } = options;\n\n const biomeConfigPath = join(targetDir, \"biome.json\");\n writeWithStrategy(biomeConfigPath, BIOME_CONFIG, conflictStrategy);\n\n addDependencies(\n targetDir,\n {\n \"@biomejs/biome\": \"^1.9.4\",\n },\n true\n );\n\n addScripts(targetDir, {\n lint: \"biome lint .\",\n \"lint:fix\": \"biome lint --write .\",\n format: \"biome format .\",\n \"format:fix\": \"biome format --write .\",\n });\n\n const vscodeDir = join(targetDir, \".vscode\");\n ensureDir(vscodeDir);\n\n const vscodeSettingsPath = join(vscodeDir, \"settings.json\");\n writeWithStrategy(vscodeSettingsPath, VSCODE_SETTINGS, conflictStrategy);\n}\n","import { join } from \"node:path\";\nimport { writeFileSync } from \"node:fs\";\nimport type { ToolSetupOptions } from \"../../types/index.js\";\nimport { ensureDir } from \"../../utils/fs.js\";\nimport { addDependencies, addScripts, addLintStaged } from \"../../utils/package-json.js\";\n\nconst PRE_COMMIT_HOOK = `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\npnpm lint-staged\n`;\n\n/**\n * Husky + lint-stagedのセットアップを実行する(--setupモードのみ)\n *\n * AC-007-1: .husky/ ディレクトリが生成される\n * AC-007-2: pre-commitフックが設定される\n * AC-007-3: lint-staged設定が追加される\n */\nexport function setupHusky(options: ToolSetupOptions): void {\n const { targetDir } = options;\n\n addDependencies(\n targetDir,\n {\n husky: \"^9.1.7\",\n \"lint-staged\": \"^15.2.11\",\n },\n true\n );\n\n addScripts(targetDir, {\n prepare: \"husky\",\n });\n\n addLintStaged(targetDir, {\n \"*.{js,jsx,ts,tsx}\": [\"biome format --write\", \"biome lint --write\"],\n \"*.{json,md,yml,yaml}\": [\"biome format --write\"],\n });\n\n const huskyDir = join(targetDir, \".husky\");\n ensureDir(huskyDir);\n\n const preCommitPath = join(huskyDir, \"pre-commit\");\n writeFileSync(preCommitPath, PRE_COMMIT_HOOK, { mode: 0o755 });\n}\n"],"mappings":"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","names":["readFileSync","fileURLToPath","dirname","join","existsSync","ora","dirname","join","readFileSync","writeFileSync","existsSync","__filename","__dirname","dirname","join","error","chalk","inquirer","inquirer","error","chalk","existsSync","error","ora","existsSync","join","ora","inquirer","join","inquirer","join","inquirer","error","join","readFileSync","writeFileSync","join","packageJsonPath","join","readFileSync","writeFileSync","join","join","join","join","join","join","writeFileSync","join","writeFileSync","packageJsonPath","join","existsSync","ora","error","__filename","fileURLToPath","__dirname","dirname","join","readFileSync"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "create-einja-app",
3
+ "version": "0.1.1",
4
+ "description": "CLI tool to create new projects with Einja Management Template",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-einja-app": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "templates"
12
+ ],
13
+ "dependencies": {
14
+ "chalk": "^5.3.0",
15
+ "commander": "^12.1.0",
16
+ "execa": "^9.5.1",
17
+ "fs-extra": "^11.2.0",
18
+ "glob": "^11.0.0",
19
+ "ignore": "^7.0.0",
20
+ "inquirer": "^12.0.0",
21
+ "ora": "^8.1.1"
22
+ },
23
+ "devDependencies": {
24
+ "@biomejs/biome": "^1.9.4",
25
+ "@types/fs-extra": "^11.0.4",
26
+ "@types/inquirer": "^9.0.7",
27
+ "@types/node": "^22.10.2",
28
+ "tsup": "^8.3.5",
29
+ "tsx": "^4.7.0",
30
+ "typescript": "^5.7.2",
31
+ "vitest": "^2.1.8"
32
+ },
33
+ "engines": {
34
+ "node": ">=20.0.0"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/einja-inc/einja-management-template.git",
42
+ "directory": "packages/create-einja-app"
43
+ },
44
+ "keywords": [
45
+ "einja",
46
+ "cli",
47
+ "template",
48
+ "turborepo",
49
+ "nextjs"
50
+ ],
51
+ "license": "MIT",
52
+ "scripts": {
53
+ "prebuild": "pnpm template:update",
54
+ "build": "tsup",
55
+ "dev": "tsup --watch",
56
+ "typecheck": "tsc --noEmit",
57
+ "lint": "biome lint .",
58
+ "test": "vitest",
59
+ "test:coverage": "vitest run --coverage",
60
+ "template:update": "tsx scripts/template-update.ts"
61
+ }
62
+ }
@@ -0,0 +1,15 @@
1
+ # Biome ignore patterns
2
+ **/node_modules
3
+ **/.next
4
+ **/.turbo
5
+ **/dist
6
+ **/build
7
+ **/.cache
8
+ **/coverage
9
+ **/.vercel
10
+ **/.pnpm-store
11
+ styled-system
12
+ **/test-results
13
+ **/playwright-report
14
+ .claude
15
+ **/__generated__
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ # biome-check.sh - ファイル保存後にbiome check(format + lint)を実行するhook
3
+
4
+ # stdinからJSON入力を読み取る
5
+ input=$(cat)
6
+
7
+ # ファイルパスを抽出
8
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
9
+
10
+ # ファイルパスが存在しない場合は終了
11
+ if [ -z "$file_path" ]; then
12
+ exit 0
13
+ fi
14
+
15
+ # biome対象の拡張子かチェック (.ts, .tsx, .js, .jsx, .json)
16
+ if [[ "$file_path" =~ \.(ts|tsx|js|jsx|json)$ ]]; then
17
+ # プロジェクトルートに移動してbiomeを実行
18
+ cd "$CLAUDE_PROJECT_DIR" 2>/dev/null || exit 0
19
+
20
+ # biome check(format + lint)を実行、自動修正可能なものは修正
21
+ npx biome check --write "$file_path" 2>/dev/null || true
22
+
23
+ # 修正後に残っているlintエラーをチェック(any型など自動修正できないもの)
24
+ lint_errors=$(npx biome lint "$file_path" 2>&1 | grep -E "lint/|noExplicitAny|error" | head -20)
25
+
26
+ if [ -n "$lint_errors" ]; then
27
+ echo "" >&2
28
+ echo "⚠️ Biome lintエラーが検出されました" >&2
29
+ echo " ファイル: $file_path" >&2
30
+ echo "" >&2
31
+ echo "$lint_errors" | while read -r line; do
32
+ echo " $line" >&2
33
+ done
34
+ echo "" >&2
35
+
36
+ # エラー詳細をエスケープしてsystemMessageに含める
37
+ escaped_errors=$(echo "$lint_errors" | sed 's/"/\\"/g' | tr '\n' ' ' | head -c 500)
38
+
39
+ # any型が含まれているかチェック
40
+ if echo "$lint_errors" | grep -q "noExplicitAny"; then
41
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"⚠️ any型が検出されました。any型は禁止です。適切な型を指定してください。\\n詳細: ${escaped_errors}\"}"
42
+ else
43
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"⚠️ Biome lintエラーが検出されました。修正を検討してください。\\n詳細: ${escaped_errors}\"}"
44
+ fi
45
+ exit 0
46
+ fi
47
+ fi
48
+
49
+ exit 0
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+ # design-doc-check.sh - 設計書への実装コード混入検出
3
+
4
+ input=$(cat)
5
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
6
+ content=$(echo "$input" | jq -r '.tool_input.content // .tool_input.new_string // empty')
7
+
8
+ if [ -z "$file_path" ] || [ -z "$content" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ # docs/specs/配下のmarkdownファイルのみ対象
13
+ if [[ ! "$file_path" =~ docs/specs/.*\.md$ ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ # 実装コードパターンの検出
18
+ code_found=""
19
+
20
+ # 関数実装(アロー関数、function宣言)
21
+ if echo "$content" | grep -qE '(const|let|var)\s+\w+\s*=\s*(async\s*)?\([^)]*\)\s*=>\s*\{'; then
22
+ code_found="${code_found}\n - アロー関数の実装"
23
+ fi
24
+
25
+ if echo "$content" | grep -qE 'function\s+\w+\s*\([^)]*\)\s*\{[^}]+\}'; then
26
+ code_found="${code_found}\n - function実装"
27
+ fi
28
+
29
+ # if/for/while等の制御構文(コードブロック外)
30
+ # マークダウンのコードブロック内は許容するが、実際のロジックは警告
31
+ if echo "$content" | grep -qE '^\s*(if|for|while|switch)\s*\([^)]+\)\s*\{'; then
32
+ code_found="${code_found}\n - 制御構文の実装"
33
+ fi
34
+
35
+ # try-catch実装
36
+ if echo "$content" | grep -qE 'try\s*\{[^}]+\}\s*catch'; then
37
+ code_found="${code_found}\n - try-catch実装"
38
+ fi
39
+
40
+ # 具体的なビジネスロジック(計算、データ変換等)
41
+ if echo "$content" | grep -qE '\.(map|filter|reduce|forEach)\s*\(\s*(async\s*)?\([^)]*\)\s*=>\s*\{[^}]{50,}\}'; then
42
+ code_found="${code_found}\n - 配列操作の詳細実装"
43
+ fi
44
+
45
+ if [ -n "$code_found" ]; then
46
+ echo "" >&2
47
+ echo "⚠️ 警告: 設計書に実装コードが含まれています" >&2
48
+ echo " ファイル: $file_path" >&2
49
+ echo -e " 検出内容:$code_found" >&2
50
+ echo "" >&2
51
+ echo " 設計書には以下のみ記載してください:" >&2
52
+ echo " ✅ Class名、関数名、引数型、返却型" >&2
53
+ echo " ✅ 使用ライブラリの仕様" >&2
54
+ echo " ✅ アーキテクチャ図、構造図" >&2
55
+ echo " ❌ 具体的なロジックを含む実装コード" >&2
56
+ echo "" >&2
57
+
58
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"⚠️ 設計書に実装コードが含まれています。設計と実装は分離してください。\"}"
59
+ fi
60
+
61
+ exit 0
@@ -0,0 +1,62 @@
1
+ #!/bin/bash
2
+ # detect-secrets.sh - 機密情報の検出
3
+
4
+ input=$(cat)
5
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
6
+ content=$(echo "$input" | jq -r '.tool_input.content // .tool_input.new_string // empty')
7
+
8
+ if [ -z "$file_path" ] || [ -z "$content" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ # .envファイル自体は許可(ただし.env.exampleは除く)
13
+ if [[ "$file_path" =~ \.env$ ]] && [[ ! "$file_path" =~ \.example$ ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ # 機密情報パターンの検出
18
+ secrets_found=""
19
+
20
+ # APIキー・トークンパターン
21
+ if echo "$content" | grep -qiE '(api[_-]?key|api[_-]?secret|access[_-]?token|auth[_-]?token|bearer)\s*[:=]\s*["\047][a-zA-Z0-9_\-]{20,}["\047]'; then
22
+ secrets_found="${secrets_found}\n - APIキー/トークンのハードコード"
23
+ fi
24
+
25
+ # AWSキーパターン
26
+ if echo "$content" | grep -qE 'AKIA[0-9A-Z]{16}'; then
27
+ secrets_found="${secrets_found}\n - AWS Access Key ID"
28
+ fi
29
+
30
+ # パスワードパターン
31
+ if echo "$content" | grep -qiE '(password|passwd|pwd)\s*[:=]\s*["\047][^"\047]{8,}["\047]'; then
32
+ secrets_found="${secrets_found}\n - パスワードのハードコード"
33
+ fi
34
+
35
+ # 秘密鍵パターン
36
+ if echo "$content" | grep -qE '-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----'; then
37
+ secrets_found="${secrets_found}\n - 秘密鍵"
38
+ fi
39
+
40
+ # JWTシークレット
41
+ if echo "$content" | grep -qiE 'jwt[_-]?secret\s*[:=]\s*["\047][^"\047]{16,}["\047]'; then
42
+ secrets_found="${secrets_found}\n - JWTシークレット"
43
+ fi
44
+
45
+ # データベース接続文字列
46
+ if echo "$content" | grep -qiE '(mongodb|postgres|mysql|redis)://[^"\047\s]+:[^"\047\s]+@'; then
47
+ secrets_found="${secrets_found}\n - データベース接続文字列(認証情報含む)"
48
+ fi
49
+
50
+ if [ -n "$secrets_found" ]; then
51
+ echo "" >&2
52
+ echo "🚨 警告: 機密情報が検出されました" >&2
53
+ echo " ファイル: $file_path" >&2
54
+ echo -e " 検出内容:$secrets_found" >&2
55
+ echo "" >&2
56
+ echo " 環境変数または.envファイルの使用を検討してください" >&2
57
+ echo "" >&2
58
+
59
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"🚨 機密情報が検出されました。環境変数の使用を検討してください。\"}"
60
+ fi
61
+
62
+ exit 0
@@ -0,0 +1,42 @@
1
+ #!/bin/bash
2
+ # large-file-warning.sh - 大きすぎるファイルの警告
3
+
4
+ input=$(cat)
5
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
6
+ content=$(echo "$input" | jq -r '.tool_input.content // empty')
7
+
8
+ if [ -z "$file_path" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ # コード系ファイルのみ対象
13
+ if [[ ! "$file_path" =~ \.(ts|tsx|js|jsx|py|go|rs|java|rb|php)$ ]]; then
14
+ exit 0
15
+ fi
16
+
17
+ # 行数をカウント
18
+ line_count=0
19
+ if [ -n "$content" ]; then
20
+ # Writeの場合はcontentから行数を取得
21
+ line_count=$(echo "$content" | wc -l | tr -d ' ')
22
+ elif [ -f "$file_path" ]; then
23
+ # Editの場合はファイルから行数を取得
24
+ line_count=$(wc -l < "$file_path" | tr -d ' ')
25
+ fi
26
+
27
+ # 500行以上で警告
28
+ if [ "$line_count" -ge 500 ]; then
29
+ echo "" >&2
30
+ echo "⚠️ 警告: ファイルが大きすぎます(${line_count}行)" >&2
31
+ echo " ファイル: $file_path" >&2
32
+ echo "" >&2
33
+ echo " 推奨事項:" >&2
34
+ echo " - 500行を超えるファイルは分割を検討してください" >&2
35
+ echo " - 関連する機能ごとにモジュール化を検討してください" >&2
36
+ echo " - ヘルパー関数は別ファイルに切り出すことを検討してください" >&2
37
+ echo "" >&2
38
+
39
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"⚠️ ファイルが${line_count}行あります。分割を検討してください。\"}"
40
+ fi
41
+
42
+ exit 0
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # playwright-resize.sh - Playwright使用前にリサイズを強制するhook
3
+ # PreToolUseで実行され、リサイズ未実施ならブロックする
4
+
5
+ input=$(cat)
6
+ tool_name=$(echo "$input" | jq -r '.tool_name // empty')
7
+
8
+ # Playwrightツール以外は無視
9
+ if [[ ! "$tool_name" =~ ^mcp__playwright__ ]]; then
10
+ exit 0
11
+ fi
12
+
13
+ # browser_resize自体、browser_close、browser_installは許可
14
+ if [[ "$tool_name" == "mcp__playwright__browser_resize" ]] || \
15
+ [[ "$tool_name" == "mcp__playwright__browser_close" ]] || \
16
+ [[ "$tool_name" == "mcp__playwright__browser_install" ]]; then
17
+ # リサイズ実行時にフラグファイルを作成
18
+ if [[ "$tool_name" == "mcp__playwright__browser_resize" ]]; then
19
+ mkdir -p /tmp/claude-hooks
20
+ touch /tmp/claude-hooks/playwright-resized-$$
21
+ fi
22
+ exit 0
23
+ fi
24
+
25
+ # フラグファイルが存在するか確認(現在のセッションでリサイズ済み)
26
+ # セッションIDがないので、最近のフラグファイル(5分以内)をチェック
27
+ recent_flag=$(find /tmp/claude-hooks -name "playwright-resized-*" -mmin -5 2>/dev/null | head -1)
28
+
29
+ if [ -n "$recent_flag" ]; then
30
+ # リサイズ済みなら許可
31
+ exit 0
32
+ fi
33
+
34
+ # リサイズ未実施ならブロック
35
+ echo '{"decision":"block","reason":"Playwright使用前にブラウザサイズの設定が必要です","systemMessage":"⚠️ Playwrightを使用する前に、まず以下を実行してブラウザサイズを設定してください:\n\nmcp__playwright__browser_resize({ width: 1280, height: 720 })\n\nその後、再度操作を実行してください。"}'
36
+ exit 2
@@ -0,0 +1,37 @@
1
+ #!/bin/bash
2
+ # typecheck.sh - TypeScriptファイル編集後に型チェック(編集ファイルのみ)
3
+
4
+ input=$(cat)
5
+ file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
6
+
7
+ if [ -z "$file_path" ]; then
8
+ exit 0
9
+ fi
10
+
11
+ # TypeScriptファイルのみ対象
12
+ if [[ ! "$file_path" =~ \.(ts|tsx)$ ]]; then
13
+ exit 0
14
+ fi
15
+
16
+ cd "$CLAUDE_PROJECT_DIR" 2>/dev/null || exit 0
17
+
18
+ # 該当ファイルのエラーのみ抽出(ファイルパスで始まる行のみ)
19
+ # tscの出力形式: "path/to/file.ts(line,col): error TS..."
20
+ errors=$(npx tsc --noEmit 2>&1 | grep "^${file_path}(" | head -10)
21
+
22
+ if [ -n "$errors" ]; then
23
+ echo "" >&2
24
+ echo "⚠️ 型エラーが検出されました" >&2
25
+ echo " ファイル: $file_path" >&2
26
+ echo "" >&2
27
+ echo "$errors" | while read -r line; do
28
+ echo " $line" >&2
29
+ done
30
+ echo "" >&2
31
+
32
+ # エラー数をカウント
33
+ error_count=$(echo "$errors" | wc -l | tr -d ' ')
34
+ echo "{\"decision\":\"approve\",\"systemMessage\":\"⚠️ 型エラーが${error_count}件検出されました。修正を検討してください。\"}"
35
+ fi
36
+
37
+ exit 0
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+ # Bash実行前に_VOLTA_TOOL_RECURSIONを無効化する
3
+ # Claude Code環境でVoltaが正しく動作しない問題への対処
4
+ #
5
+ # PreToolUseのenvフィールドはサポートされていないため、
6
+ # updatedInputでコマンド自体を修正する
7
+
8
+ input=$(cat)
9
+ tool_name=$(echo "$input" | jq -r '.tool_name // empty')
10
+
11
+ # Bashツール以外は無視
12
+ if [[ ! "$tool_name" =~ ^Bash ]]; then
13
+ exit 0
14
+ fi
15
+
16
+ # 元のコマンドを取得
17
+ original_command=$(echo "$input" | jq -r '.tool_input.command // empty')
18
+
19
+ # コマンドの先頭にunsetを追加
20
+ # jqでJSON安全にエスケープ
21
+ updated_command="unset _VOLTA_TOOL_RECURSION && $original_command"
22
+
23
+ # updatedInputでコマンドを変更
24
+ jq -n --arg cmd "$updated_command" '{
25
+ "hookSpecificOutput": {
26
+ "hookEventName": "PreToolUse",
27
+ "permissionDecision": "allow",
28
+ "updatedInput": {
29
+ "command": $cmd
30
+ }
31
+ }
32
+ }'