create-einja-app 0.1.2 → 0.2.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.
- package/README.md +72 -0
- package/dist/cli.js +852 -21
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/CLAUDE.md +27 -0
- package/templates/default/README.md +150 -45
- package/templates/default/apps/web/server/presentation/routes/userRoutes.ts +2 -5
- package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTable.tsx +110 -113
- package/templates/default/apps/web/src/app/(authenticated)/data/_components/UserTableContainer.tsx +5 -17
- package/templates/default/apps/web/src/app/(authenticated)/data/page.tsx +9 -7
- package/templates/default/apps/web/src/app/api/rpc/[[...route]]/route.ts +1 -1
- package/templates/default/apps/web/src/hooks/api/prefetch-users.ts +63 -0
- package/templates/default/apps/web/src/hooks/{use-users.ts → api/use-users.ts} +11 -46
- package/templates/default/apps/web/src/lib/api/parse-response.ts +114 -0
- package/templates/default/apps/web/src/shared/schemas/user.ts +36 -0
- package/templates/default/middleware.ts +0 -32
- package/templates/default/apps/web/src/lib/{api-client.ts → api/client.ts} +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { readFileSync as
|
|
6
|
-
import { fileURLToPath as
|
|
7
|
-
import { dirname as
|
|
5
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
6
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7
|
+
import { dirname as dirname5, join as join14 } from "path";
|
|
8
8
|
|
|
9
9
|
// src/commands/create.ts
|
|
10
|
-
import { existsSync as existsSync3 } from "fs";
|
|
10
|
+
import { existsSync as existsSync3, readdirSync } from "fs";
|
|
11
11
|
import { resolve } from "path";
|
|
12
12
|
import ora2 from "ora";
|
|
13
13
|
|
|
@@ -28,6 +28,12 @@ async function promptProjectConfig(defaultProjectName) {
|
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
+
{
|
|
32
|
+
type: "confirm",
|
|
33
|
+
name: "useCurrentDir",
|
|
34
|
+
message: "\u4ECA\u3044\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u76F4\u63A5\u4F5C\u6210\u3057\u307E\u3059\u304B\uFF1F\uFF08No\u306A\u3089\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u4F5C\u6210\uFF09",
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
31
37
|
{
|
|
32
38
|
type: "input",
|
|
33
39
|
name: "packageScope",
|
|
@@ -54,7 +60,7 @@ async function promptProjectConfig(defaultProjectName) {
|
|
|
54
60
|
{
|
|
55
61
|
type: "confirm",
|
|
56
62
|
name: "setupEinjaCli",
|
|
57
|
-
message: "@einja/cli \u3092\u81EA\u52D5\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u307E\u3059\u304B\uFF1F",
|
|
63
|
+
message: "@einja/dev-cli \u3092\u81EA\u52D5\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u307E\u3059\u304B\uFF1F",
|
|
58
64
|
default: true
|
|
59
65
|
},
|
|
60
66
|
{
|
|
@@ -147,7 +153,8 @@ async function promptProjectConfig(defaultProjectName) {
|
|
|
147
153
|
authMethod: answers.authMethod,
|
|
148
154
|
tools,
|
|
149
155
|
setupEinjaCli: answers.setupEinjaCli,
|
|
150
|
-
worktreeConfig
|
|
156
|
+
worktreeConfig,
|
|
157
|
+
useCurrentDir: answers.useCurrentDir
|
|
151
158
|
};
|
|
152
159
|
}
|
|
153
160
|
|
|
@@ -457,19 +464,29 @@ async function execPostSetup(config, targetPath, options) {
|
|
|
457
464
|
await promptAndExecuteDirenvAllow(targetPath);
|
|
458
465
|
}
|
|
459
466
|
if (config.setupEinjaCli) {
|
|
460
|
-
const einjaSpinner = ora("@einja/cli \u3092\u521D\u671F\u5316\u4E2D...").start();
|
|
467
|
+
const einjaSpinner = ora("@einja/dev-cli \u3092\u521D\u671F\u5316\u4E2D...").start();
|
|
461
468
|
try {
|
|
462
|
-
await execa("npx", ["@einja/cli", "init"], { cwd: targetPath });
|
|
463
|
-
einjaSpinner.succeed("@einja/cli \u3092\u521D\u671F\u5316\u3057\u307E\u3057\u305F");
|
|
469
|
+
await execa("npx", ["@einja/dev-cli", "init", "--force"], { cwd: targetPath });
|
|
470
|
+
einjaSpinner.succeed("@einja/dev-cli \u3092\u521D\u671F\u5316\u3057\u307E\u3057\u305F");
|
|
464
471
|
} catch (error2) {
|
|
465
|
-
einjaSpinner.fail("@einja/cli \u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
466
|
-
warn("\u5F8C\u3067\u624B\u52D5\u3067 'npx @einja/cli init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
472
|
+
einjaSpinner.fail("@einja/dev-cli \u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
473
|
+
warn("\u5F8C\u3067\u624B\u52D5\u3067 'npx @einja/dev-cli init' \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
467
474
|
}
|
|
468
475
|
}
|
|
469
476
|
printCompletionMessage(config);
|
|
470
477
|
}
|
|
471
478
|
|
|
472
479
|
// src/commands/create.ts
|
|
480
|
+
function isDirectoryEmpty(dirPath) {
|
|
481
|
+
if (!existsSync3(dirPath)) {
|
|
482
|
+
return true;
|
|
483
|
+
}
|
|
484
|
+
const files = readdirSync(dirPath);
|
|
485
|
+
const significantFiles = files.filter(
|
|
486
|
+
(f) => !f.startsWith(".")
|
|
487
|
+
);
|
|
488
|
+
return significantFiles.length === 0;
|
|
489
|
+
}
|
|
473
490
|
function validateProjectName(projectName) {
|
|
474
491
|
const regex = /^[a-zA-Z][a-zA-Z0-9_-]{0,49}$/;
|
|
475
492
|
if (!regex.test(projectName)) {
|
|
@@ -502,7 +519,8 @@ async function createCommand(projectName, options) {
|
|
|
502
519
|
husky: true
|
|
503
520
|
},
|
|
504
521
|
setupEinjaCli: true,
|
|
505
|
-
worktreeConfig: void 0
|
|
522
|
+
worktreeConfig: void 0,
|
|
523
|
+
useCurrentDir: false
|
|
506
524
|
};
|
|
507
525
|
info(`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D: ${config.projectName}`);
|
|
508
526
|
info(`\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8: ${config.template}`);
|
|
@@ -510,11 +528,19 @@ async function createCommand(projectName, options) {
|
|
|
510
528
|
} else {
|
|
511
529
|
config = await promptProjectConfig(projectName);
|
|
512
530
|
}
|
|
513
|
-
const targetPath = resolve(process.cwd(), config.projectName);
|
|
514
|
-
if (
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
531
|
+
const targetPath = config.useCurrentDir ? process.cwd() : resolve(process.cwd(), config.projectName);
|
|
532
|
+
if (config.useCurrentDir) {
|
|
533
|
+
if (!isDirectoryEmpty(targetPath)) {
|
|
534
|
+
error("\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u3059");
|
|
535
|
+
info("\u7A7A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u5B9F\u884C\u3059\u308B\u304B\u3001\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
536
|
+
process.exit(1);
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
if (checkProjectExists(targetPath)) {
|
|
540
|
+
error(`\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA '${config.projectName}' \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059`);
|
|
541
|
+
info("\u5225\u306E\u540D\u524D\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001\u65E2\u5B58\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u524A\u9664\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
542
|
+
process.exit(1);
|
|
543
|
+
}
|
|
518
544
|
}
|
|
519
545
|
const spinner = ora2("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4F5C\u6210\u4E2D...").start();
|
|
520
546
|
try {
|
|
@@ -984,11 +1010,808 @@ async function setupCommand() {
|
|
|
984
1010
|
success("\u958B\u767A\u3092\u958B\u59CB\u3067\u304D\u307E\u3059\uFF01");
|
|
985
1011
|
}
|
|
986
1012
|
|
|
1013
|
+
// src/commands/add.ts
|
|
1014
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1015
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
1016
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
1017
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1018
|
+
import ora4 from "ora";
|
|
1019
|
+
|
|
1020
|
+
// src/prompts/add.ts
|
|
1021
|
+
import inquirer5 from "inquirer";
|
|
1022
|
+
function getDefaultAddConfig() {
|
|
1023
|
+
return {
|
|
1024
|
+
components: {
|
|
1025
|
+
packages: true,
|
|
1026
|
+
apps: true,
|
|
1027
|
+
config: true
|
|
1028
|
+
},
|
|
1029
|
+
packageComponents: ["front-core", "server-core", "config", "ui"],
|
|
1030
|
+
appComponents: ["web"],
|
|
1031
|
+
dryRun: false
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
async function promptAddConfig(dryRun) {
|
|
1035
|
+
const componentAnswers = await inquirer5.prompt([
|
|
1036
|
+
{
|
|
1037
|
+
type: "checkbox",
|
|
1038
|
+
name: "components",
|
|
1039
|
+
message: "\u8FFD\u52A0\u3059\u308B\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u3092\u9078\u629E\uFF08Space\u3067\u9078\u629E\u3001Enter\u3067\u78BA\u5B9A\uFF09:",
|
|
1040
|
+
choices: [
|
|
1041
|
+
{
|
|
1042
|
+
name: "packages/ - \u5171\u901A\u30D1\u30C3\u30B1\u30FC\u30B8\uFF08front-core, server-core, config, ui\uFF09",
|
|
1043
|
+
value: "packages",
|
|
1044
|
+
checked: true
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
name: "apps/ - \u30A2\u30D7\u30EA\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8",
|
|
1048
|
+
value: "apps",
|
|
1049
|
+
checked: true
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
name: "\u76F4\u4E0B\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB - turbo.json, pnpm-workspace.yaml \u7B49",
|
|
1053
|
+
value: "config",
|
|
1054
|
+
checked: true
|
|
1055
|
+
}
|
|
1056
|
+
]
|
|
1057
|
+
}
|
|
1058
|
+
]);
|
|
1059
|
+
const selectedComponents = componentAnswers.components;
|
|
1060
|
+
const hasPackages = selectedComponents.includes("packages");
|
|
1061
|
+
const hasApps = selectedComponents.includes("apps");
|
|
1062
|
+
const hasConfig = selectedComponents.includes("config");
|
|
1063
|
+
let packageComponents = [];
|
|
1064
|
+
if (hasPackages) {
|
|
1065
|
+
const packageAnswers = await inquirer5.prompt([
|
|
1066
|
+
{
|
|
1067
|
+
type: "checkbox",
|
|
1068
|
+
name: "packages",
|
|
1069
|
+
message: "\u8FFD\u52A0\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u9078\u629E:",
|
|
1070
|
+
choices: [
|
|
1071
|
+
{
|
|
1072
|
+
name: "front-core - \u30D5\u30ED\u30F3\u30C8\u30A8\u30F3\u30C9\u5171\u901A\u5C64\uFF08\u8A8D\u8A3C\u8A2D\u5B9A\u3001hooks\u3001utils\uFF09",
|
|
1073
|
+
value: "front-core",
|
|
1074
|
+
checked: true
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
name: "server-core - \u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u5171\u901A\u5C64\uFF08Prisma\u3001\u30C9\u30E1\u30A4\u30F3\u30ED\u30B8\u30C3\u30AF\uFF09",
|
|
1078
|
+
value: "server-core",
|
|
1079
|
+
checked: true
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
name: "config - \u5171\u901A\u8A2D\u5B9A\uFF08Biome, TypeScript, Panda CSS\uFF09",
|
|
1083
|
+
value: "config",
|
|
1084
|
+
checked: true
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
name: "ui - \u5171\u901AUI\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\uFF08shadcn/ui\uFF09",
|
|
1088
|
+
value: "ui",
|
|
1089
|
+
checked: true
|
|
1090
|
+
}
|
|
1091
|
+
],
|
|
1092
|
+
validate: (input) => {
|
|
1093
|
+
if (input.length === 0) {
|
|
1094
|
+
return "\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044";
|
|
1095
|
+
}
|
|
1096
|
+
return true;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
]);
|
|
1100
|
+
packageComponents = packageAnswers.packages;
|
|
1101
|
+
}
|
|
1102
|
+
let appComponents = [];
|
|
1103
|
+
if (hasApps) {
|
|
1104
|
+
const appAnswers = await inquirer5.prompt([
|
|
1105
|
+
{
|
|
1106
|
+
type: "checkbox",
|
|
1107
|
+
name: "apps",
|
|
1108
|
+
message: "\u8FFD\u52A0\u3059\u308B\u30A2\u30D7\u30EA\u3092\u9078\u629E:",
|
|
1109
|
+
choices: [
|
|
1110
|
+
{
|
|
1111
|
+
name: "web - \u30E1\u30A4\u30F3\u7BA1\u7406\u753B\u9762\u30A2\u30D7\u30EA\uFF08Next.js + App Router\uFF09",
|
|
1112
|
+
value: "web",
|
|
1113
|
+
checked: true
|
|
1114
|
+
}
|
|
1115
|
+
],
|
|
1116
|
+
validate: (input) => {
|
|
1117
|
+
if (input.length === 0) {
|
|
1118
|
+
return "\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u30A2\u30D7\u30EA\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044";
|
|
1119
|
+
}
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
]);
|
|
1124
|
+
appComponents = appAnswers.apps;
|
|
1125
|
+
}
|
|
1126
|
+
return {
|
|
1127
|
+
components: {
|
|
1128
|
+
packages: hasPackages,
|
|
1129
|
+
apps: hasApps,
|
|
1130
|
+
config: hasConfig
|
|
1131
|
+
},
|
|
1132
|
+
packageComponents,
|
|
1133
|
+
appComponents,
|
|
1134
|
+
dryRun
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// src/generators/partials/packages.ts
|
|
1139
|
+
import { readdir } from "fs/promises";
|
|
1140
|
+
import { join as join10 } from "path";
|
|
1141
|
+
|
|
1142
|
+
// src/utils/merger.ts
|
|
1143
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync5, existsSync as existsSync5 } from "fs";
|
|
1144
|
+
import { dirname as dirname3 } from "path";
|
|
1145
|
+
function mergeTextWithMarkers(templateContent, existingContent) {
|
|
1146
|
+
if (existingContent === null) {
|
|
1147
|
+
return templateContent;
|
|
1148
|
+
}
|
|
1149
|
+
const templateSections = parseMarkers(templateContent);
|
|
1150
|
+
const localSections = parseMarkers(existingContent);
|
|
1151
|
+
const hasMarkers = templateSections.some(
|
|
1152
|
+
(s) => s.type === "managed" || s.type === "seed"
|
|
1153
|
+
);
|
|
1154
|
+
if (!hasMarkers) {
|
|
1155
|
+
return existingContent;
|
|
1156
|
+
}
|
|
1157
|
+
const templateManagedById = /* @__PURE__ */ new Map();
|
|
1158
|
+
const templateSeedById = /* @__PURE__ */ new Map();
|
|
1159
|
+
const processedTemplateIds = /* @__PURE__ */ new Set();
|
|
1160
|
+
for (const section of templateSections) {
|
|
1161
|
+
if (section.type === "managed" && section.id) {
|
|
1162
|
+
templateManagedById.set(section.id, section);
|
|
1163
|
+
} else if (section.type === "seed" && section.id) {
|
|
1164
|
+
templateSeedById.set(section.id, section);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
const result = [];
|
|
1168
|
+
for (const localSection of localSections) {
|
|
1169
|
+
if (localSection.type === "managed") {
|
|
1170
|
+
const match = localSection.id ? templateManagedById.get(localSection.id) : void 0;
|
|
1171
|
+
if (localSection.id && match) {
|
|
1172
|
+
processedTemplateIds.add(localSection.id);
|
|
1173
|
+
result.push(match.content);
|
|
1174
|
+
} else if (!localSection.id) {
|
|
1175
|
+
result.push(localSection.content);
|
|
1176
|
+
}
|
|
1177
|
+
} else if (localSection.type === "seed") {
|
|
1178
|
+
if (localSection.id) {
|
|
1179
|
+
processedTemplateIds.add(localSection.id);
|
|
1180
|
+
}
|
|
1181
|
+
result.push(localSection.content);
|
|
1182
|
+
} else {
|
|
1183
|
+
result.push(localSection.content);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
for (const [id, section] of templateManagedById) {
|
|
1187
|
+
if (!processedTemplateIds.has(id)) {
|
|
1188
|
+
result.push(section.content);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
for (const [id, section] of templateSeedById) {
|
|
1192
|
+
if (!processedTemplateIds.has(id)) {
|
|
1193
|
+
result.push(section.content);
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
const firstElement = result[0];
|
|
1197
|
+
if (result.length > 0 && firstElement !== void 0 && firstElement.length === 0) {
|
|
1198
|
+
result.shift();
|
|
1199
|
+
}
|
|
1200
|
+
return result.join("\n");
|
|
1201
|
+
}
|
|
1202
|
+
function mergeJson(templateJson, existingJson, jsonPaths, filePath = "package.json") {
|
|
1203
|
+
if (existingJson === null) {
|
|
1204
|
+
return JSON.parse(JSON.stringify(templateJson));
|
|
1205
|
+
}
|
|
1206
|
+
return deepMergeWithPaths(
|
|
1207
|
+
templateJson,
|
|
1208
|
+
existingJson,
|
|
1209
|
+
jsonPaths,
|
|
1210
|
+
filePath,
|
|
1211
|
+
""
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1214
|
+
function deepMergeWithPaths(template, existing, jsonPaths, filePath, currentPath) {
|
|
1215
|
+
const result = JSON.parse(JSON.stringify(existing));
|
|
1216
|
+
for (const [key, templateValue] of Object.entries(template)) {
|
|
1217
|
+
const keyPath = currentPath ? `${currentPath}.${key}` : key;
|
|
1218
|
+
const existingValue = existing[key];
|
|
1219
|
+
if (isPathManaged(filePath, keyPath, jsonPaths)) {
|
|
1220
|
+
result[key] = deepClone(templateValue);
|
|
1221
|
+
} else if (isPathSeed(filePath, keyPath, jsonPaths)) {
|
|
1222
|
+
if (typeof templateValue === "object" && templateValue !== null && !Array.isArray(templateValue) && typeof existingValue === "object" && existingValue !== null && !Array.isArray(existingValue)) {
|
|
1223
|
+
result[key] = deepMergeWithPaths(
|
|
1224
|
+
templateValue,
|
|
1225
|
+
existingValue,
|
|
1226
|
+
jsonPaths,
|
|
1227
|
+
filePath,
|
|
1228
|
+
keyPath
|
|
1229
|
+
);
|
|
1230
|
+
} else if (!(key in existing)) {
|
|
1231
|
+
result[key] = deepClone(templateValue);
|
|
1232
|
+
}
|
|
1233
|
+
} else if (typeof templateValue === "object" && templateValue !== null && !Array.isArray(templateValue) && typeof existingValue === "object" && existingValue !== null && !Array.isArray(existingValue)) {
|
|
1234
|
+
result[key] = deepMergeWithPaths(
|
|
1235
|
+
templateValue,
|
|
1236
|
+
existingValue,
|
|
1237
|
+
jsonPaths,
|
|
1238
|
+
filePath,
|
|
1239
|
+
keyPath
|
|
1240
|
+
);
|
|
1241
|
+
} else if (!(key in existing)) {
|
|
1242
|
+
result[key] = deepClone(templateValue);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return result;
|
|
1246
|
+
}
|
|
1247
|
+
function deepClone(value) {
|
|
1248
|
+
if (value === void 0) {
|
|
1249
|
+
return void 0;
|
|
1250
|
+
}
|
|
1251
|
+
return JSON.parse(JSON.stringify(value));
|
|
1252
|
+
}
|
|
1253
|
+
async function loadSyncMetadata(targetDir) {
|
|
1254
|
+
const metadataPath = `${targetDir}/.einja-sync.json`;
|
|
1255
|
+
if (!existsSync5(metadataPath)) {
|
|
1256
|
+
return null;
|
|
1257
|
+
}
|
|
1258
|
+
try {
|
|
1259
|
+
const content = readFileSync4(metadataPath, "utf-8");
|
|
1260
|
+
return JSON.parse(content);
|
|
1261
|
+
} catch {
|
|
1262
|
+
return null;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
async function saveSyncMetadata(targetDir, metadata) {
|
|
1266
|
+
const metadataPath = `${targetDir}/.einja-sync.json`;
|
|
1267
|
+
ensureDir(dirname3(metadataPath));
|
|
1268
|
+
writeFileSync5(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
1269
|
+
}
|
|
1270
|
+
async function mergeAndWriteFile(templatePath, targetPath, syncMetadata) {
|
|
1271
|
+
const templateContent = readFileSync4(templatePath, "utf-8");
|
|
1272
|
+
const targetExists = existsSync5(targetPath);
|
|
1273
|
+
const existingContent = targetExists ? readFileSync4(targetPath, "utf-8") : null;
|
|
1274
|
+
const isJsonFile = targetPath.endsWith(".json");
|
|
1275
|
+
let mergedContent;
|
|
1276
|
+
let action;
|
|
1277
|
+
if (!targetExists) {
|
|
1278
|
+
mergedContent = templateContent;
|
|
1279
|
+
action = "created";
|
|
1280
|
+
} else if (isJsonFile) {
|
|
1281
|
+
try {
|
|
1282
|
+
const templateJson = JSON.parse(templateContent);
|
|
1283
|
+
const existingJson = existingContent ? JSON.parse(existingContent) : null;
|
|
1284
|
+
const jsonPaths = syncMetadata.jsonPaths || { managed: {}, seed: {} };
|
|
1285
|
+
const fileName = targetPath.split("/").pop() || "package.json";
|
|
1286
|
+
const mergedJson = mergeJson(templateJson, existingJson, jsonPaths, fileName);
|
|
1287
|
+
mergedContent = JSON.stringify(mergedJson, null, 2);
|
|
1288
|
+
action = "merged";
|
|
1289
|
+
} catch {
|
|
1290
|
+
mergedContent = templateContent;
|
|
1291
|
+
action = "overwritten";
|
|
1292
|
+
}
|
|
1293
|
+
} else {
|
|
1294
|
+
mergedContent = mergeTextWithMarkers(templateContent, existingContent);
|
|
1295
|
+
if (mergedContent === existingContent) {
|
|
1296
|
+
action = "skipped";
|
|
1297
|
+
} else {
|
|
1298
|
+
action = "merged";
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
if (action !== "skipped") {
|
|
1302
|
+
ensureDir(dirname3(targetPath));
|
|
1303
|
+
writeFileSync5(targetPath, mergedContent, "utf-8");
|
|
1304
|
+
}
|
|
1305
|
+
return { action, path: targetPath };
|
|
1306
|
+
}
|
|
1307
|
+
function parseMarkers(content) {
|
|
1308
|
+
const lines = content.split("\n");
|
|
1309
|
+
const sections = [];
|
|
1310
|
+
let currentType = "unmanaged";
|
|
1311
|
+
let currentStartLine = 1;
|
|
1312
|
+
let currentContent = [];
|
|
1313
|
+
let currentId;
|
|
1314
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1315
|
+
const line = lines[i];
|
|
1316
|
+
const lineNumber = i + 1;
|
|
1317
|
+
const startMarker = parseStartMarker(line);
|
|
1318
|
+
if (startMarker) {
|
|
1319
|
+
if (currentType !== "unmanaged") {
|
|
1320
|
+
currentContent.push(line);
|
|
1321
|
+
continue;
|
|
1322
|
+
}
|
|
1323
|
+
if (currentContent.length > 0 || sections.length === 0) {
|
|
1324
|
+
sections.push({
|
|
1325
|
+
type: "unmanaged",
|
|
1326
|
+
startLine: currentStartLine,
|
|
1327
|
+
endLine: lineNumber - 1,
|
|
1328
|
+
content: currentContent.join("\n")
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
currentType = startMarker.type;
|
|
1332
|
+
currentId = startMarker.id;
|
|
1333
|
+
currentStartLine = lineNumber;
|
|
1334
|
+
currentContent = [line];
|
|
1335
|
+
} else if (parseEndMarker(line)) {
|
|
1336
|
+
if (currentType === "unmanaged") {
|
|
1337
|
+
currentContent.push(line);
|
|
1338
|
+
continue;
|
|
1339
|
+
}
|
|
1340
|
+
currentContent.push(line);
|
|
1341
|
+
sections.push({
|
|
1342
|
+
type: currentType,
|
|
1343
|
+
startLine: currentStartLine,
|
|
1344
|
+
endLine: lineNumber,
|
|
1345
|
+
content: currentContent.join("\n"),
|
|
1346
|
+
id: currentId
|
|
1347
|
+
});
|
|
1348
|
+
currentType = "unmanaged";
|
|
1349
|
+
currentId = void 0;
|
|
1350
|
+
currentStartLine = lineNumber + 1;
|
|
1351
|
+
currentContent = [];
|
|
1352
|
+
} else {
|
|
1353
|
+
currentContent.push(line);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
if (currentContent.length > 0 || sections.length === 0) {
|
|
1357
|
+
sections.push({
|
|
1358
|
+
type: currentType,
|
|
1359
|
+
startLine: currentStartLine,
|
|
1360
|
+
endLine: lines.length,
|
|
1361
|
+
content: currentContent.join("\n"),
|
|
1362
|
+
id: currentId
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
return sections;
|
|
1366
|
+
}
|
|
1367
|
+
function parseStartMarker(line) {
|
|
1368
|
+
const markdownManagedPattern = /^<!--\s*@einja:managed:start(?:\s+id="([^"]+)")?\s*-->$/;
|
|
1369
|
+
let match = line.match(markdownManagedPattern);
|
|
1370
|
+
if (match) {
|
|
1371
|
+
return { type: "managed", id: match[1] || void 0 };
|
|
1372
|
+
}
|
|
1373
|
+
const markdownSeedPattern = /^<!--\s*@einja:seed:start(?:\s+id="([^"]+)")?\s*-->$/;
|
|
1374
|
+
match = line.match(markdownSeedPattern);
|
|
1375
|
+
if (match) {
|
|
1376
|
+
return { type: "seed", id: match[1] || void 0 };
|
|
1377
|
+
}
|
|
1378
|
+
const yamlManagedPattern = /^\s*#\s*@einja:managed:start(?:\s+id="([^"]+)")?\s*$/;
|
|
1379
|
+
match = line.match(yamlManagedPattern);
|
|
1380
|
+
if (match) {
|
|
1381
|
+
return { type: "managed", id: match[1] || void 0 };
|
|
1382
|
+
}
|
|
1383
|
+
const yamlSeedPattern = /^\s*#\s*@einja:seed:start(?:\s+id="([^"]+)")?\s*$/;
|
|
1384
|
+
match = line.match(yamlSeedPattern);
|
|
1385
|
+
if (match) {
|
|
1386
|
+
return { type: "seed", id: match[1] || void 0 };
|
|
1387
|
+
}
|
|
1388
|
+
return null;
|
|
1389
|
+
}
|
|
1390
|
+
function parseEndMarker(line) {
|
|
1391
|
+
if (/^<!--\s*@einja:managed:end\s*-->$/.test(line)) {
|
|
1392
|
+
return "managed";
|
|
1393
|
+
}
|
|
1394
|
+
if (/^<!--\s*@einja:seed:end\s*-->$/.test(line)) {
|
|
1395
|
+
return "seed";
|
|
1396
|
+
}
|
|
1397
|
+
if (/^\s*#\s*@einja:managed:end\s*$/.test(line)) {
|
|
1398
|
+
return "managed";
|
|
1399
|
+
}
|
|
1400
|
+
if (/^\s*#\s*@einja:seed:end\s*$/.test(line)) {
|
|
1401
|
+
return "seed";
|
|
1402
|
+
}
|
|
1403
|
+
return null;
|
|
1404
|
+
}
|
|
1405
|
+
function isPathManaged(filePath, keyPath, jsonPaths) {
|
|
1406
|
+
const managedPaths = jsonPaths.managed[filePath] || [];
|
|
1407
|
+
return managedPaths.some(
|
|
1408
|
+
(p) => keyPath === p || keyPath.startsWith(`${p}.`)
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
function isPathSeed(filePath, keyPath, jsonPaths) {
|
|
1412
|
+
const seedPaths = jsonPaths.seed[filePath] || [];
|
|
1413
|
+
return seedPaths.some((p) => keyPath === p || keyPath.startsWith(`${p}.`));
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// src/generators/partials/packages.ts
|
|
1417
|
+
async function addPackages(options, components, syncMetadata) {
|
|
1418
|
+
const added = [];
|
|
1419
|
+
const skipped = [];
|
|
1420
|
+
const merged = [];
|
|
1421
|
+
const { targetDir, templateDir, config } = options;
|
|
1422
|
+
for (const component of components) {
|
|
1423
|
+
const componentName = component === "front-core" ? "front-core" : component === "server-core" ? "server-core" : component === "config" ? "config" : "ui";
|
|
1424
|
+
const srcDir = join10(templateDir, "packages", componentName);
|
|
1425
|
+
const destDir = join10(targetDir, "packages", componentName);
|
|
1426
|
+
info(`Adding package component: ${componentName}`);
|
|
1427
|
+
await copyDirectory(
|
|
1428
|
+
srcDir,
|
|
1429
|
+
destDir,
|
|
1430
|
+
{ added, skipped, merged },
|
|
1431
|
+
config.dryRun,
|
|
1432
|
+
syncMetadata
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
return { added, skipped, merged };
|
|
1436
|
+
}
|
|
1437
|
+
async function copyDirectory(srcDir, destDir, result, dryRun, syncMetadata) {
|
|
1438
|
+
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
1439
|
+
for (const entry of entries) {
|
|
1440
|
+
const srcPath = join10(srcDir, entry.name);
|
|
1441
|
+
const destPath = join10(destDir, entry.name);
|
|
1442
|
+
if (entry.isDirectory()) {
|
|
1443
|
+
await copyDirectory(srcPath, destPath, result, dryRun, syncMetadata);
|
|
1444
|
+
} else {
|
|
1445
|
+
if (!dryRun) {
|
|
1446
|
+
const mergeResult = await mergeAndWriteFile(
|
|
1447
|
+
srcPath,
|
|
1448
|
+
destPath,
|
|
1449
|
+
syncMetadata
|
|
1450
|
+
);
|
|
1451
|
+
if (mergeResult.action === "created") {
|
|
1452
|
+
result.added.push(destPath);
|
|
1453
|
+
} else if (mergeResult.action === "skipped") {
|
|
1454
|
+
result.skipped.push(destPath);
|
|
1455
|
+
} else if (mergeResult.action === "merged") {
|
|
1456
|
+
result.merged.push(destPath);
|
|
1457
|
+
}
|
|
1458
|
+
} else {
|
|
1459
|
+
result.skipped.push(destPath);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
// src/generators/partials/apps.ts
|
|
1466
|
+
import { readdir as readdir2 } from "fs/promises";
|
|
1467
|
+
import { join as join11 } from "path";
|
|
1468
|
+
async function addApps(options, components, syncMetadata) {
|
|
1469
|
+
const added = [];
|
|
1470
|
+
const skipped = [];
|
|
1471
|
+
const merged = [];
|
|
1472
|
+
const { targetDir, templateDir, config } = options;
|
|
1473
|
+
for (const component of components) {
|
|
1474
|
+
const componentName = component === "web" ? "web" : component;
|
|
1475
|
+
const srcDir = join11(templateDir, "apps", componentName);
|
|
1476
|
+
const destDir = join11(targetDir, "apps", componentName);
|
|
1477
|
+
info(`Adding app component: ${componentName}`);
|
|
1478
|
+
await copyDirectory2(
|
|
1479
|
+
srcDir,
|
|
1480
|
+
destDir,
|
|
1481
|
+
{ added, skipped, merged },
|
|
1482
|
+
config.dryRun,
|
|
1483
|
+
syncMetadata
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
return { added, skipped, merged };
|
|
1487
|
+
}
|
|
1488
|
+
async function copyDirectory2(srcDir, destDir, result, dryRun, syncMetadata) {
|
|
1489
|
+
const entries = await readdir2(srcDir, { withFileTypes: true });
|
|
1490
|
+
for (const entry of entries) {
|
|
1491
|
+
const srcPath = join11(srcDir, entry.name);
|
|
1492
|
+
const destPath = join11(destDir, entry.name);
|
|
1493
|
+
if (entry.isDirectory()) {
|
|
1494
|
+
await copyDirectory2(srcPath, destPath, result, dryRun, syncMetadata);
|
|
1495
|
+
} else {
|
|
1496
|
+
if (!dryRun) {
|
|
1497
|
+
const mergeResult = await mergeAndWriteFile(
|
|
1498
|
+
srcPath,
|
|
1499
|
+
destPath,
|
|
1500
|
+
syncMetadata
|
|
1501
|
+
);
|
|
1502
|
+
if (mergeResult.action === "created") {
|
|
1503
|
+
result.added.push(destPath);
|
|
1504
|
+
} else if (mergeResult.action === "skipped") {
|
|
1505
|
+
result.skipped.push(destPath);
|
|
1506
|
+
} else if (mergeResult.action === "merged") {
|
|
1507
|
+
result.merged.push(destPath);
|
|
1508
|
+
}
|
|
1509
|
+
} else {
|
|
1510
|
+
result.skipped.push(destPath);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// src/generators/partials/config.ts
|
|
1517
|
+
import { readdir as readdir3, readFile } from "fs/promises";
|
|
1518
|
+
import { join as join12, relative as relative2, sep } from "path";
|
|
1519
|
+
async function addConfigFiles(options, syncMetadata) {
|
|
1520
|
+
const added = [];
|
|
1521
|
+
const skipped = [];
|
|
1522
|
+
const merged = [];
|
|
1523
|
+
const { targetDir, templateDir, config } = options;
|
|
1524
|
+
info("Adding config files from template root");
|
|
1525
|
+
const excludedPaths = /* @__PURE__ */ new Set([
|
|
1526
|
+
".claude",
|
|
1527
|
+
"docs/einja",
|
|
1528
|
+
"CLAUDE.md",
|
|
1529
|
+
".mcp.json",
|
|
1530
|
+
"node_modules",
|
|
1531
|
+
".turbo",
|
|
1532
|
+
"next-env.d.ts",
|
|
1533
|
+
"styled-system",
|
|
1534
|
+
"pnpm-lock.yaml",
|
|
1535
|
+
"package-lock.json",
|
|
1536
|
+
"packages",
|
|
1537
|
+
"apps"
|
|
1538
|
+
]);
|
|
1539
|
+
const gitignorePatterns = await loadGitignorePatterns(templateDir);
|
|
1540
|
+
await copyConfigDirectory(
|
|
1541
|
+
templateDir,
|
|
1542
|
+
targetDir,
|
|
1543
|
+
templateDir,
|
|
1544
|
+
// rootDir として templateDir を渡す
|
|
1545
|
+
{ added, skipped, merged },
|
|
1546
|
+
config.dryRun,
|
|
1547
|
+
excludedPaths,
|
|
1548
|
+
gitignorePatterns,
|
|
1549
|
+
syncMetadata
|
|
1550
|
+
);
|
|
1551
|
+
return { added, skipped, merged };
|
|
1552
|
+
}
|
|
1553
|
+
async function loadGitignorePatterns(templateDir) {
|
|
1554
|
+
const patterns = /* @__PURE__ */ new Set();
|
|
1555
|
+
const gitignorePath = join12(templateDir, ".gitignore");
|
|
1556
|
+
try {
|
|
1557
|
+
const content = await readFile(gitignorePath, "utf-8");
|
|
1558
|
+
const lines = content.split("\n");
|
|
1559
|
+
for (const line of lines) {
|
|
1560
|
+
const trimmed = line.trim();
|
|
1561
|
+
if (trimmed && !trimmed.startsWith("#")) {
|
|
1562
|
+
const pattern = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
|
|
1563
|
+
patterns.add(pattern);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
} catch {
|
|
1567
|
+
}
|
|
1568
|
+
return patterns;
|
|
1569
|
+
}
|
|
1570
|
+
async function copyConfigDirectory(srcDir, destDir, rootDir, result, dryRun, excludedPaths, gitignorePatterns, syncMetadata) {
|
|
1571
|
+
const entries = await readdir3(srcDir, { withFileTypes: true });
|
|
1572
|
+
for (const entry of entries) {
|
|
1573
|
+
const srcPath = join12(srcDir, entry.name);
|
|
1574
|
+
const destPath = join12(destDir, entry.name);
|
|
1575
|
+
const rawRelativePath = relative2(rootDir, srcPath);
|
|
1576
|
+
const relativePath = rawRelativePath.split(sep).join("/");
|
|
1577
|
+
if (shouldExclude(relativePath, excludedPaths, gitignorePatterns)) {
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
if (entry.isDirectory()) {
|
|
1581
|
+
await copyConfigDirectory(
|
|
1582
|
+
srcPath,
|
|
1583
|
+
destPath,
|
|
1584
|
+
rootDir,
|
|
1585
|
+
// rootDir を引き継ぐ
|
|
1586
|
+
result,
|
|
1587
|
+
dryRun,
|
|
1588
|
+
excludedPaths,
|
|
1589
|
+
gitignorePatterns,
|
|
1590
|
+
syncMetadata
|
|
1591
|
+
);
|
|
1592
|
+
} else {
|
|
1593
|
+
if (!dryRun) {
|
|
1594
|
+
const mergeResult = await mergeAndWriteFile(
|
|
1595
|
+
srcPath,
|
|
1596
|
+
destPath,
|
|
1597
|
+
syncMetadata
|
|
1598
|
+
);
|
|
1599
|
+
if (mergeResult.action === "created") {
|
|
1600
|
+
result.added.push(destPath);
|
|
1601
|
+
} else if (mergeResult.action === "skipped") {
|
|
1602
|
+
result.skipped.push(destPath);
|
|
1603
|
+
} else if (mergeResult.action === "merged") {
|
|
1604
|
+
result.merged.push(destPath);
|
|
1605
|
+
}
|
|
1606
|
+
} else {
|
|
1607
|
+
result.skipped.push(destPath);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
function shouldExclude(relativePath, excludedPaths, gitignorePatterns) {
|
|
1613
|
+
for (const excluded of excludedPaths) {
|
|
1614
|
+
if (relativePath === excluded || relativePath.startsWith(`${excluded}/`)) {
|
|
1615
|
+
return true;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
for (const pattern of gitignorePatterns) {
|
|
1619
|
+
if (matchPattern(relativePath, pattern)) {
|
|
1620
|
+
return true;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
return false;
|
|
1624
|
+
}
|
|
1625
|
+
function matchPattern(path, pattern) {
|
|
1626
|
+
if (pattern.endsWith("/")) {
|
|
1627
|
+
const dirPattern = pattern.slice(0, -1);
|
|
1628
|
+
return path === dirPattern || path.startsWith(`${dirPattern}/`);
|
|
1629
|
+
}
|
|
1630
|
+
if (pattern.includes("*")) {
|
|
1631
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
1632
|
+
return new RegExp(`^${regexPattern}$`).test(path);
|
|
1633
|
+
}
|
|
1634
|
+
return path === pattern || path.startsWith(`${pattern}/`);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
// src/commands/add.ts
|
|
1638
|
+
function getTemplatePath2(templateName) {
|
|
1639
|
+
const __filename3 = fileURLToPath2(import.meta.url);
|
|
1640
|
+
const __dirname3 = dirname4(__filename3);
|
|
1641
|
+
const distPath = join13(__dirname3, "../templates", templateName);
|
|
1642
|
+
const srcPath = join13(__dirname3, "../../templates", templateName);
|
|
1643
|
+
if (existsSync6(distPath)) {
|
|
1644
|
+
return distPath;
|
|
1645
|
+
}
|
|
1646
|
+
if (existsSync6(srcPath)) {
|
|
1647
|
+
return srcPath;
|
|
1648
|
+
}
|
|
1649
|
+
return distPath;
|
|
1650
|
+
}
|
|
1651
|
+
async function loadTemplateSyncMetadata(templateDir) {
|
|
1652
|
+
const syncFilePath = join13(templateDir, ".einja-sync.json");
|
|
1653
|
+
try {
|
|
1654
|
+
const content = await readFile2(syncFilePath, "utf-8");
|
|
1655
|
+
return JSON.parse(content);
|
|
1656
|
+
} catch {
|
|
1657
|
+
return null;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
function mergeSyncMetadata(template, existing) {
|
|
1661
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1662
|
+
const jsonPaths = template?.jsonPaths ?? existing?.jsonPaths ?? { managed: {}, seed: {} };
|
|
1663
|
+
return {
|
|
1664
|
+
version: template?.version ?? existing?.version ?? "1.0.0",
|
|
1665
|
+
lastSync: now,
|
|
1666
|
+
templateVersion: template?.templateVersion ?? "1.0.0",
|
|
1667
|
+
files: { ...existing?.files ?? {}, ...template?.files ?? {} },
|
|
1668
|
+
jsonPaths
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
async function addCommand(options) {
|
|
1672
|
+
try {
|
|
1673
|
+
const targetDir = process.cwd();
|
|
1674
|
+
let config;
|
|
1675
|
+
if (options.skipPrompts) {
|
|
1676
|
+
config = getDefaultAddConfig();
|
|
1677
|
+
info("\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u307E\u3059\uFF08\u3059\u3079\u3066\u306E\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u3092\u9078\u629E\uFF09");
|
|
1678
|
+
} else {
|
|
1679
|
+
config = await promptAddConfig(options.dryRun);
|
|
1680
|
+
}
|
|
1681
|
+
config.dryRun = options.dryRun;
|
|
1682
|
+
if (config.dryRun) {
|
|
1683
|
+
warn("dry-run\u30E2\u30FC\u30C9: \u5B9F\u969B\u306E\u30D5\u30A1\u30A4\u30EB\u64CD\u4F5C\u306F\u884C\u3044\u307E\u305B\u3093");
|
|
1684
|
+
info("\n--- \u8FFD\u52A0\u4E88\u5B9A\u306E\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8 ---");
|
|
1685
|
+
if (config.components.packages) {
|
|
1686
|
+
info(
|
|
1687
|
+
`- packages/: ${config.packageComponents.join(", ")}`
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
if (config.components.apps) {
|
|
1691
|
+
info(`- apps/: ${config.appComponents.join(", ")}`);
|
|
1692
|
+
}
|
|
1693
|
+
if (config.components.config) {
|
|
1694
|
+
info("- \u76F4\u4E0B\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB: turbo.json, pnpm-workspace.yaml \u7B49");
|
|
1695
|
+
}
|
|
1696
|
+
info("---\n");
|
|
1697
|
+
}
|
|
1698
|
+
const templateDir = getTemplatePath2("default");
|
|
1699
|
+
if (!existsSync6(templateDir)) {
|
|
1700
|
+
throw new Error("\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: default");
|
|
1701
|
+
}
|
|
1702
|
+
const templateMetadata = await loadTemplateSyncMetadata(templateDir);
|
|
1703
|
+
const existingMetadata = await loadSyncMetadata(targetDir);
|
|
1704
|
+
const syncMetadata = mergeSyncMetadata(templateMetadata, existingMetadata);
|
|
1705
|
+
const addOptions = {
|
|
1706
|
+
targetDir,
|
|
1707
|
+
templateDir,
|
|
1708
|
+
config
|
|
1709
|
+
};
|
|
1710
|
+
let totalAdded = 0;
|
|
1711
|
+
let totalMerged = 0;
|
|
1712
|
+
let totalSkipped = 0;
|
|
1713
|
+
if (config.components.packages && config.packageComponents.length > 0) {
|
|
1714
|
+
const spinner = ora4("\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u8FFD\u52A0\u4E2D...").start();
|
|
1715
|
+
try {
|
|
1716
|
+
const result = await addPackages(
|
|
1717
|
+
addOptions,
|
|
1718
|
+
config.packageComponents,
|
|
1719
|
+
syncMetadata
|
|
1720
|
+
);
|
|
1721
|
+
totalAdded += result.added.length;
|
|
1722
|
+
totalMerged += result.merged.length;
|
|
1723
|
+
totalSkipped += result.skipped.length;
|
|
1724
|
+
spinner.succeed(
|
|
1725
|
+
`\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\uFF08\u8FFD\u52A0: ${result.added.length}, \u30DE\u30FC\u30B8: ${result.merged.length}, \u30B9\u30AD\u30C3\u30D7: ${result.skipped.length}\uFF09`
|
|
1726
|
+
);
|
|
1727
|
+
} catch (error2) {
|
|
1728
|
+
spinner.fail("\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u8FFD\u52A0\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1729
|
+
throw error2;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
if (config.components.apps && config.appComponents.length > 0) {
|
|
1733
|
+
const spinner = ora4("\u30A2\u30D7\u30EA\u3092\u8FFD\u52A0\u4E2D...").start();
|
|
1734
|
+
try {
|
|
1735
|
+
const result = await addApps(
|
|
1736
|
+
addOptions,
|
|
1737
|
+
config.appComponents,
|
|
1738
|
+
syncMetadata
|
|
1739
|
+
);
|
|
1740
|
+
totalAdded += result.added.length;
|
|
1741
|
+
totalMerged += result.merged.length;
|
|
1742
|
+
totalSkipped += result.skipped.length;
|
|
1743
|
+
spinner.succeed(
|
|
1744
|
+
`\u30A2\u30D7\u30EA\u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\uFF08\u8FFD\u52A0: ${result.added.length}, \u30DE\u30FC\u30B8: ${result.merged.length}, \u30B9\u30AD\u30C3\u30D7: ${result.skipped.length}\uFF09`
|
|
1745
|
+
);
|
|
1746
|
+
} catch (error2) {
|
|
1747
|
+
spinner.fail("\u30A2\u30D7\u30EA\u306E\u8FFD\u52A0\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1748
|
+
throw error2;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
if (config.components.config) {
|
|
1752
|
+
const spinner = ora4("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0\u4E2D...").start();
|
|
1753
|
+
try {
|
|
1754
|
+
const result = await addConfigFiles(addOptions, syncMetadata);
|
|
1755
|
+
totalAdded += result.added.length;
|
|
1756
|
+
totalMerged += result.merged.length;
|
|
1757
|
+
totalSkipped += result.skipped.length;
|
|
1758
|
+
spinner.succeed(
|
|
1759
|
+
`\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0\u3057\u307E\u3057\u305F\uFF08\u8FFD\u52A0: ${result.added.length}, \u30DE\u30FC\u30B8: ${result.merged.length}, \u30B9\u30AD\u30C3\u30D7: ${result.skipped.length}\uFF09`
|
|
1760
|
+
);
|
|
1761
|
+
} catch (error2) {
|
|
1762
|
+
spinner.fail("\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u306E\u8FFD\u52A0\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
1763
|
+
throw error2;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
if (!config.dryRun) {
|
|
1767
|
+
syncMetadata.lastSync = (/* @__PURE__ */ new Date()).toISOString();
|
|
1768
|
+
await saveSyncMetadata(targetDir, syncMetadata);
|
|
1769
|
+
}
|
|
1770
|
+
success("\n\u2713 \u8FFD\u52A0\u5B8C\u4E86\uFF01\n");
|
|
1771
|
+
if (config.dryRun) {
|
|
1772
|
+
info("\uFF08dry-run\u30E2\u30FC\u30C9\u306E\u305F\u3081\u3001\u5B9F\u969B\u306E\u5909\u66F4\u306F\u884C\u308F\u308C\u3066\u3044\u307E\u305B\u3093\uFF09\n");
|
|
1773
|
+
}
|
|
1774
|
+
info(`\u8FFD\u52A0\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB: ${totalAdded}\u500B`);
|
|
1775
|
+
info(`\u30DE\u30FC\u30B8\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB: ${totalMerged}\u500B`);
|
|
1776
|
+
info(`\u30B9\u30AD\u30C3\u30D7\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB: ${totalSkipped}\u500B
|
|
1777
|
+
`);
|
|
1778
|
+
const packageJsonPath2 = join13(targetDir, "package.json");
|
|
1779
|
+
if (existsSync6(packageJsonPath2)) {
|
|
1780
|
+
const packageJson2 = await import(packageJsonPath2);
|
|
1781
|
+
const hasEinjaCli = packageJson2.default?.devDependencies?.["@einja/dev-cli"] || packageJson2.default?.dependencies?.["@einja/dev-cli"];
|
|
1782
|
+
if (!hasEinjaCli) {
|
|
1783
|
+
info("\u6B21\u306E\u30B9\u30C6\u30C3\u30D7:");
|
|
1784
|
+
info("1. pnpm install");
|
|
1785
|
+
info("2. pnpm dev:setup");
|
|
1786
|
+
info("\n\u63A8\u5968:");
|
|
1787
|
+
info(" einja\u958B\u767A\u652F\u63F4CLI (@einja/dev-cli) \u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB:");
|
|
1788
|
+
info(" pnpm add -D @einja/dev-cli\n");
|
|
1789
|
+
} else {
|
|
1790
|
+
info("\u6B21\u306E\u30B9\u30C6\u30C3\u30D7:");
|
|
1791
|
+
info("1. pnpm install");
|
|
1792
|
+
info("2. pnpm dev:setup\n");
|
|
1793
|
+
}
|
|
1794
|
+
} else {
|
|
1795
|
+
info("\u6B21\u306E\u30B9\u30C6\u30C3\u30D7:");
|
|
1796
|
+
info("1. pnpm install");
|
|
1797
|
+
info("2. pnpm dev:setup\n");
|
|
1798
|
+
}
|
|
1799
|
+
} catch (error2) {
|
|
1800
|
+
error("\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:");
|
|
1801
|
+
if (error2 instanceof Error) {
|
|
1802
|
+
error(error2.message);
|
|
1803
|
+
} else {
|
|
1804
|
+
error(String(error2));
|
|
1805
|
+
}
|
|
1806
|
+
process.exit(1);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
|
|
987
1810
|
// src/cli.ts
|
|
988
|
-
var __filename2 =
|
|
989
|
-
var __dirname2 =
|
|
990
|
-
var packageJsonPath =
|
|
991
|
-
var packageJson = JSON.parse(
|
|
1811
|
+
var __filename2 = fileURLToPath3(import.meta.url);
|
|
1812
|
+
var __dirname2 = dirname5(__filename2);
|
|
1813
|
+
var packageJsonPath = join14(__dirname2, "../package.json");
|
|
1814
|
+
var packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
|
|
992
1815
|
var program = new Command();
|
|
993
1816
|
program.name("create-einja-app").description("CLI tool to create new projects with Einja Management Template").version(packageJson.version);
|
|
994
1817
|
program.argument("[project-name]", "Project name").option("--skip-git", "Skip git initialization").option("--skip-install", "Skip package installation").option("-y, --yes", "Skip interactive prompts").action(
|
|
@@ -999,5 +1822,13 @@ program.argument("[project-name]", "Project name").option("--skip-git", "Skip gi
|
|
|
999
1822
|
program.command("setup").description("Setup tools for existing project").action(async () => {
|
|
1000
1823
|
await setupCommand();
|
|
1001
1824
|
});
|
|
1825
|
+
program.command("add").description("Add einja components to existing monorepo").option("-y, --yes", "Skip prompts and use defaults (select all)").option("--all", "Select all components (same as -y)").option("--dry-run", "Preview changes without making them").action(
|
|
1826
|
+
async (options) => {
|
|
1827
|
+
await addCommand({
|
|
1828
|
+
skipPrompts: options.yes || options.all || false,
|
|
1829
|
+
dryRun: options.dryRun || false
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
);
|
|
1002
1833
|
program.parse();
|
|
1003
1834
|
//# sourceMappingURL=cli.js.map
|