create-einja-app 0.3.2 → 0.3.4

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 (65) hide show
  1. package/README.md +33 -0
  2. package/dist/cli.js +60 -64
  3. package/dist/cli.js.map +1 -1
  4. package/package.json +1 -1
  5. package/templates/default/.changeset/config.json +11 -0
  6. package/templates/default/.claude/hooks/einja/plan-mode-skill-loader.sh +5 -1
  7. package/templates/default/.claude/settings.json +14 -4
  8. package/templates/default/.claude/skills/_einja-general-context-loader/SKILL.md +258 -0
  9. package/templates/default/.claude/skills/_einja-output-format/SKILL.md +211 -0
  10. package/templates/default/.claude/skills/_einja-project-overview/SKILL.md +29 -0
  11. package/templates/default/.claude/skills/_einja-spec-context-loader/SKILL.md +181 -0
  12. package/templates/default/.claude/skills/cli-package-specs/SKILL.md +294 -0
  13. package/templates/default/.einja-sync.json +1 -1
  14. package/templates/default/.github/release.yml +10 -0
  15. package/templates/default/.github/workflows/changeset-status.yml +60 -0
  16. package/templates/default/.github/workflows/deploy-stable-branches.yml +289 -59
  17. package/templates/default/CLAUDE.md +50 -10
  18. package/templates/default/README.md +20 -8
  19. package/templates/default/docs/plans/agile-munching-knuth.md +161 -0
  20. package/templates/default/docs/plans/agile-riding-nova.md +158 -0
  21. package/templates/default/docs/plans/agile-wibbling-dusk.md +91 -0
  22. package/templates/default/docs/plans/ancient-watching-otter.md +152 -0
  23. package/templates/default/docs/plans/bright-sauteeing-bumblebee.md +30 -0
  24. package/templates/default/docs/plans/composed-doodling-mountain.md +362 -0
  25. package/templates/default/docs/plans/dazzling-foraging-cascade.md +32 -0
  26. package/templates/default/docs/plans/enchanted-wiggling-ember-agent-a5befd57d0ca4c7c7.md +177 -0
  27. package/templates/default/docs/plans/enchanted-wiggling-ember.md +170 -0
  28. package/templates/default/docs/plans/federated-questing-kahan.md +47 -0
  29. package/templates/default/docs/plans/flickering-pondering-hearth.md +26 -0
  30. package/templates/default/docs/plans/fluttering-snuggling-sprout.md +172 -0
  31. package/templates/default/docs/plans/generic-sleeping-snowglobe-agent-a41d8da.md +179 -0
  32. package/templates/default/docs/plans/generic-sleeping-snowglobe.md +108 -0
  33. package/templates/default/docs/plans/generic-snuggling-pudding.md +57 -0
  34. package/templates/default/docs/plans/glistening-conjuring-cascade.md +42 -0
  35. package/templates/default/docs/plans/idempotent-wiggling-cherny.md +122 -0
  36. package/templates/default/docs/plans/linear-gathering-hejlsberg.md +596 -0
  37. package/templates/default/docs/plans/recursive-fluttering-mitten.md +176 -0
  38. package/templates/default/docs/plans/todo-create-einja-app-ux-fix.md +16 -0
  39. package/templates/default/docs/plans/todo-direnv-hang-fix.md +12 -0
  40. package/templates/default/docs/plans/todo-github-actions-release-workflow.md +34 -0
  41. package/templates/default/docs/plans/todo-glistening-conjuring-cascade.md +20 -0
  42. package/templates/default/docs/plans/todo-issue-spec-rename.md +24 -0
  43. package/templates/default/docs/plans/todo-skill-creator-upgrade.md +18 -0
  44. package/templates/default/docs/plans/todo-unified-crafting-valiant.md +23 -0
  45. package/templates/default/docs/plans/unified-crafting-valiant.md +60 -0
  46. package/templates/default/docs/plans/velvety-chasing-spark.md +28 -0
  47. package/templates/default/docs/plans/wondrous-strolling-crystal-agent-a0615fc.md +215 -0
  48. package/templates/default/docs/plans/wondrous-strolling-crystal.md +182 -0
  49. package/templates/default/docs/plans/zesty-roaming-steele.md +74 -0
  50. package/templates/default/gitignore +6 -2
  51. package/templates/default/package.json +6 -2
  52. package/templates/default/pnpm-lock.yaml +547 -0
  53. package/templates/default/scripts/ensure-serena.sh +28 -9
  54. package/templates/default/scripts/env-rotate-secrets.ts +66 -6
  55. package/templates/default/scripts/init-github.ts +363 -0
  56. package/templates/default/scripts/init.sh +11 -5
  57. package/templates/default/scripts/setup-dev.ts +16 -1
  58. package/templates/default/.claude/hooks/einja/validate-git-commit.sh +0 -239
  59. package/templates/default/.claude/skills/create-einja-app-release/SKILL.md +0 -186
  60. package/templates/default/.claude/skills/dev-cli-release/SKILL.md +0 -173
  61. package/templates/default/.cursor/commands/spec-create.md +0 -227
  62. package/templates/default/.cursor/commands/task-exec.md +0 -287
  63. package/templates/default/.cursor/commands/update-docs-by-task-specs.md +0 -448
  64. package/templates/default/packages/server-core/src/__generated__/fabbrica/index.d.ts +0 -270
  65. package/templates/default/packages/server-core/src/__generated__/fabbrica/index.js +0 -484
package/README.md CHANGED
@@ -331,6 +331,39 @@ Gitがインストールされていません
331
331
  - Gitをインストールしてください: https://git-scm.com/downloads
332
332
  - または `--skip-git` オプションを使用してください
333
333
 
334
+ ### scripts/init.sh が Permission Denied
335
+
336
+ **エラーメッセージ:**
337
+ ```
338
+ Permission denied: ./scripts/init.sh
339
+ ```
340
+
341
+ **解決方法:**
342
+ ```bash
343
+ # 方法1: bashコマンドで実行
344
+ bash scripts/init.sh
345
+
346
+ # 方法2: 実行権限を付与してから実行
347
+ chmod +x scripts/*.sh
348
+ ./scripts/init.sh
349
+ ```
350
+
351
+ ### Volta環境でpnpmが見つからない
352
+
353
+ **エラーメッセージ:**
354
+ ```
355
+ pnpm: command not found
356
+ ```
357
+
358
+ **解決方法:**
359
+ ```bash
360
+ # pnpmを手動でインストール
361
+ npm install -g pnpm@latest-10
362
+
363
+ # またはターミナルを再起動してVoltaのPATHを反映
364
+ exec $SHELL
365
+ ```
366
+
334
367
  ---
335
368
 
336
369
  ## テンプレート更新
package/dist/cli.js CHANGED
@@ -161,6 +161,7 @@ async function promptProjectConfig(defaultProjectName) {
161
161
  // src/generators/template.ts
162
162
  import fsExtra from "fs-extra";
163
163
  import { glob } from "glob";
164
+ import { chmodSync } from "fs";
164
165
  import { dirname as dirname2, join as join2, relative } from "path";
165
166
  import { fileURLToPath } from "url";
166
167
 
@@ -335,48 +336,23 @@ async function generateTemplate(config, targetPath) {
335
336
  for (const file of allFiles) {
336
337
  processFileVariables(file, variables);
337
338
  }
339
+ const shFiles = glob.sync("**/*.sh", {
340
+ cwd: targetPath,
341
+ absolute: true,
342
+ dot: true
343
+ });
344
+ for (const file of shFiles) {
345
+ chmodSync(file, 493);
346
+ }
338
347
  success("\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u5C55\u958B\u5B8C\u4E86");
339
348
  }
340
349
 
341
350
  // src/generators/post-setup.ts
342
- import { execa, execaSync } from "execa";
351
+ import path from "path";
352
+ import os from "os";
353
+ import { execa } from "execa";
343
354
  import chalk2 from "chalk";
344
- import inquirer2 from "inquirer";
345
355
  import ora from "ora";
346
- function isDirenvAvailable() {
347
- try {
348
- execaSync("which", ["direnv"]);
349
- return true;
350
- } catch {
351
- return false;
352
- }
353
- }
354
- async function promptAndExecuteDirenvAllow(targetPath) {
355
- try {
356
- const { shouldAllow } = await inquirer2.prompt([
357
- {
358
- type: "confirm",
359
- name: "shouldAllow",
360
- message: "direnv allow \u3092\u5B9F\u884C\u3057\u307E\u3059\u304B\uFF1F\uFF08\u74B0\u5883\u5909\u6570\u3092\u6709\u52B9\u5316\u3057\u307E\u3059\uFF09",
361
- default: true
362
- }
363
- ]);
364
- if (shouldAllow) {
365
- try {
366
- await execa("direnv", ["allow"], { cwd: targetPath });
367
- success("direnv allow \u3092\u5B9F\u884C\u3057\u307E\u3057\u305F");
368
- } catch (error2) {
369
- warn("direnv allow \u306E\u5B9F\u884C\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
370
- info("\u5F8C\u3067\u624B\u52D5\u3067 'direnv allow' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
371
- }
372
- } else {
373
- info("direnv allow \u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F");
374
- info("\u5F8C\u3067\u624B\u52D5\u3067 'direnv allow' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
375
- }
376
- } catch (error2) {
377
- info("direnv allow \u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F");
378
- }
379
- }
380
356
  function printCompletionMessage(config) {
381
357
  console.log();
382
358
  success("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u4F5C\u6210\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F\uFF01");
@@ -388,10 +364,10 @@ function printCompletionMessage(config) {
388
364
  console.log(chalk2.cyan(" pnpm dev # PostgreSQL\u8D77\u52D5 + \u958B\u767A\u30B5\u30FC\u30D0\u30FC\u8D77\u52D5"));
389
365
  console.log();
390
366
  console.log(
391
- chalk2.yellow("\u26A0 \u30BB\u30AD\u30E5\u30EA\u30C6\u30A3: \u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306E\u79D8\u5BC6\u9375\u3092\u305D\u306E\u307E\u307E\u4F7F\u7528\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044")
367
+ chalk2.green("\u2713 \u30BB\u30AD\u30E5\u30EA\u30C6\u30A3: \u79D8\u5BC6\u9375\u306F\u81EA\u52D5\u30ED\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u6E08\u307F\u3067\u3059")
392
368
  );
393
369
  console.log(
394
- chalk2.gray(" pnpm env:rotate-secrets # \u79D8\u5BC6\u9375\u3092\u81EA\u5206\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u7528\u306B\u518D\u751F\u6210")
370
+ chalk2.gray(" pnpm env:rotate-secrets # \u624B\u52D5\u3067\u518D\u30ED\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u3059\u308B\u5834\u5408")
395
371
  );
396
372
  console.log();
397
373
  console.log(chalk2.gray("\u958B\u767A\u30B5\u30FC\u30D0\u30FC: \u30BF\u30FC\u30DF\u30CA\u30EB\u306B\u8868\u793A\u3055\u308C\u308BURL\u3092\u78BA\u8A8D"));
@@ -401,16 +377,17 @@ function printCompletionMessage(config) {
401
377
  }
402
378
  async function execPostSetup(config, targetPath, options) {
403
379
  const { skipGit, skipInstall } = options;
404
- if (!skipGit) {
405
- const gitSpinner = ora("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u3092\u521D\u671F\u5316\u4E2D...").start();
380
+ if (!skipInstall) {
381
+ info("\u521D\u56DE\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u5B9F\u884C\u4E2D...");
406
382
  try {
407
- await execa("git", ["init"], { cwd: targetPath });
408
- await execa("git", ["add", "."], { cwd: targetPath });
409
- await execa("git", ["commit", "-m", "Initial commit"], { cwd: targetPath });
410
- gitSpinner.succeed("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u3092\u521D\u671F\u5316\u3057\u307E\u3057\u305F");
383
+ await execa("bash", ["scripts/init.sh"], { cwd: targetPath, stdio: "inherit" });
384
+ const voltaBin = path.join(os.homedir(), ".volta", "bin");
385
+ if (!process.env.PATH?.includes(voltaBin)) {
386
+ process.env.PATH = `${voltaBin}:${process.env.PATH}`;
387
+ }
411
388
  } catch (error2) {
412
- gitSpinner.fail("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
413
- warn("\u5F8C\u3067\u624B\u52D5\u3067 'git init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
389
+ warn("\u521D\u56DE\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u306E\u81EA\u52D5\u5B9F\u884C\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
390
+ info("\u5F8C\u3067\u624B\u52D5\u3067 './scripts/init.sh' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
414
391
  }
415
392
  }
416
393
  if (!skipInstall) {
@@ -431,17 +408,36 @@ async function execPostSetup(config, targetPath, options) {
431
408
  warn("\u5F8C\u3067\u624B\u52D5\u3067 'pnpm install' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
432
409
  }
433
410
  }
434
- if (config.tools.direnv && isDirenvAvailable()) {
435
- await promptAndExecuteDirenvAllow(targetPath);
411
+ if (!skipInstall) {
412
+ const rotateSpinner = ora("\u79D8\u5BC6\u9375\u3092\u30ED\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u4E2D...").start();
413
+ try {
414
+ await execa("pnpm", ["env:rotate-secrets", "--all", "--non-interactive"], { cwd: targetPath });
415
+ rotateSpinner.succeed("\u79D8\u5BC6\u9375\u3092\u30ED\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u3057\u307E\u3057\u305F");
416
+ } catch (error2) {
417
+ rotateSpinner.warn("\u79D8\u5BC6\u9375\u306E\u81EA\u52D5\u30ED\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
418
+ info("\u5F8C\u3067\u624B\u52D5\u3067 'pnpm env:rotate-secrets' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
419
+ }
420
+ }
421
+ if (!skipGit) {
422
+ const gitSpinner = ora("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u3092\u521D\u671F\u5316\u4E2D...").start();
423
+ try {
424
+ await execa("git", ["init"], { cwd: targetPath });
425
+ await execa("git", ["add", "."], { cwd: targetPath });
426
+ await execa("git", ["commit", "-m", "Initial commit"], { cwd: targetPath });
427
+ gitSpinner.succeed("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u3092\u521D\u671F\u5316\u3057\u307E\u3057\u305F");
428
+ } catch (error2) {
429
+ gitSpinner.fail("Git\u30EA\u30DD\u30B8\u30C8\u30EA\u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
430
+ warn("\u5F8C\u3067\u624B\u52D5\u3067 'git init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
431
+ }
436
432
  }
437
433
  if (config.setupEinjaCli) {
438
434
  const einjaSpinner = ora("@einja/dev-cli \u3092\u521D\u671F\u5316\u4E2D...").start();
439
435
  try {
440
- await execa("npx", ["@einja/dev-cli", "init", "--force", "--no-backup"], { cwd: targetPath });
436
+ await execa("npx", ["--yes", "@einja/dev-cli@latest", "init", "--force", "--no-backup"], { cwd: targetPath });
441
437
  einjaSpinner.succeed("@einja/dev-cli \u3092\u521D\u671F\u5316\u3057\u307E\u3057\u305F");
442
438
  } catch (error2) {
443
439
  einjaSpinner.fail("@einja/dev-cli \u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
444
- warn("\u5F8C\u3067\u624B\u52D5\u3067 'npx @einja/dev-cli init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
440
+ warn("\u5F8C\u3067\u624B\u52D5\u3067 'npx --yes @einja/dev-cli@latest init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
445
441
  }
446
442
  }
447
443
  printCompletionMessage(config);
@@ -540,7 +536,7 @@ async function createCommand(projectName, options) {
540
536
  import { dirname as dirname5, join as join7 } from "path";
541
537
  import { fileURLToPath as fileURLToPath2 } from "url";
542
538
  import fsExtra3 from "fs-extra";
543
- import inquirer5 from "inquirer";
539
+ import inquirer4 from "inquirer";
544
540
 
545
541
  // src/generators/sync.ts
546
542
  import { glob as glob2 } from "glob";
@@ -679,9 +675,9 @@ async function collectSyncFiles(templateDir, categories, appsDetail, packagesDet
679
675
  }
680
676
 
681
677
  // src/prompts/sync.ts
682
- import inquirer3 from "inquirer";
678
+ import inquirer2 from "inquirer";
683
679
  import * as fs from "fs";
684
- import * as path from "path";
680
+ import * as path2 from "path";
685
681
  var CATEGORY_CONFIGS = {
686
682
  env: {
687
683
  name: "\u74B0\u5883\u8A2D\u5B9A",
@@ -767,7 +763,7 @@ var CATEGORY_CONFIGS = {
767
763
  }
768
764
  };
769
765
  function getAvailableApps(templateDir) {
770
- const appsDir = path.join(templateDir, "apps");
766
+ const appsDir = path2.join(templateDir, "apps");
771
767
  try {
772
768
  if (!fs.existsSync(appsDir)) {
773
769
  return [];
@@ -779,7 +775,7 @@ function getAvailableApps(templateDir) {
779
775
  }
780
776
  }
781
777
  function getAvailablePackages(templateDir) {
782
- const packagesDir = path.join(templateDir, "packages");
778
+ const packagesDir = path2.join(templateDir, "packages");
783
779
  try {
784
780
  if (!fs.existsSync(packagesDir)) {
785
781
  return [];
@@ -791,7 +787,7 @@ function getAvailablePackages(templateDir) {
791
787
  }
792
788
  }
793
789
  async function promptSyncCategories(templateDir, isFirstRun = false) {
794
- const categoryAnswers = await inquirer3.prompt([
790
+ const categoryAnswers = await inquirer2.prompt([
795
791
  {
796
792
  type: "checkbox",
797
793
  name: "categories",
@@ -814,7 +810,7 @@ async function promptSyncCategories(templateDir, isFirstRun = false) {
814
810
  if (hasApps) {
815
811
  const availableApps = getAvailableApps(templateDir);
816
812
  if (availableApps.length > 0) {
817
- const appsAnswers = await inquirer3.prompt([
813
+ const appsAnswers = await inquirer2.prompt([
818
814
  {
819
815
  type: "checkbox",
820
816
  name: "apps",
@@ -841,7 +837,7 @@ async function promptSyncCategories(templateDir, isFirstRun = false) {
841
837
  if (hasPackages) {
842
838
  const availablePackages = getAvailablePackages(templateDir);
843
839
  if (availablePackages.length > 0) {
844
- const packagesAnswers = await inquirer3.prompt([
840
+ const packagesAnswers = await inquirer2.prompt([
845
841
  {
846
842
  type: "checkbox",
847
843
  name: "packages",
@@ -866,7 +862,7 @@ async function promptSyncCategories(templateDir, isFirstRun = false) {
866
862
  }
867
863
  }
868
864
  if (hasRootConfig) {
869
- const packageJsonAnswers = await inquirer3.prompt([
865
+ const packageJsonAnswers = await inquirer2.prompt([
870
866
  {
871
867
  type: "checkbox",
872
868
  name: "sections",
@@ -882,7 +878,7 @@ async function promptSyncCategories(templateDir, isFirstRun = false) {
882
878
  ]);
883
879
  packageJsonSections = packageJsonAnswers.sections;
884
880
  }
885
- const strategyAnswers = await inquirer3.prompt([
881
+ const strategyAnswers = await inquirer2.prompt([
886
882
  {
887
883
  type: "list",
888
884
  name: "conflictStrategy",
@@ -1093,7 +1089,7 @@ import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsS
1093
1089
  import { dirname as dirname4, basename } from "path";
1094
1090
 
1095
1091
  // src/utils/package-json-merger.ts
1096
- import inquirer4 from "inquirer";
1092
+ import inquirer3 from "inquirer";
1097
1093
  function hasVersionConflict(existingVersion, templateVersion) {
1098
1094
  if (existingVersion === templateVersion) {
1099
1095
  return false;
@@ -1132,7 +1128,7 @@ async function resolveVersionConflicts(conflicts) {
1132
1128
  warn(` \u65E2\u5B58: ${conflict.existingVersion}`);
1133
1129
  warn(` \u30C6\u30F3\u30D7\u30EC\u30FC\u30C8: ${conflict.templateVersion}
1134
1130
  `);
1135
- const answer = await inquirer4.prompt([
1131
+ const answer = await inquirer3.prompt([
1136
1132
  {
1137
1133
  type: "list",
1138
1134
  name: "version",
@@ -1666,7 +1662,7 @@ async function handleInterrupt() {
1666
1662
  info("\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u304C\u4F5C\u6210\u3055\u308C\u3066\u3044\u306A\u3044\u305F\u3081\u3001\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306F\u4E0D\u8981\u3067\u3059");
1667
1663
  process.exit(0);
1668
1664
  }
1669
- const answer = await inquirer5.prompt([
1665
+ const answer = await inquirer4.prompt([
1670
1666
  {
1671
1667
  type: "confirm",
1672
1668
  name: "rollback",
@@ -1792,7 +1788,7 @@ async function syncCommand(options) {
1792
1788
  info(` \u2713 \u30D1\u30C3\u30B1\u30FC\u30B8\u30B9\u30B3\u30FC\u30D7: ${detectedConfig.packageScope}`);
1793
1789
  } else {
1794
1790
  warn("\u26A0\uFE0F \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u8A2D\u5B9A\u3092\u81EA\u52D5\u691C\u51FA\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F");
1795
- const inputAnswers = await inquirer5.prompt([
1791
+ const inputAnswers = await inquirer4.prompt([
1796
1792
  {
1797
1793
  type: "input",
1798
1794
  name: "projectName",