wlmaker 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.mjs +1082 -333
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/cli.ts
4
4
  import { createRequire } from "module";
5
5
  import { Command } from "commander";
6
- import chalk10 from "chalk";
6
+ import chalk12 from "chalk";
7
7
 
8
8
  // src/core/create-bloc.ts
9
9
  import * as fs3 from "fs";
@@ -106,17 +106,17 @@ function hasBuildRunner(projectRoot) {
106
106
  return /build_runner/.test(pubspec);
107
107
  }
108
108
  function runBuildRunner(projectRoot) {
109
- return new Promise((resolve4) => {
109
+ return new Promise((resolve5) => {
110
110
  const child = spawn(
111
111
  "dart",
112
112
  ["run", "build_runner", "build", "--delete-conflicting-outputs"],
113
113
  { cwd: projectRoot, stdio: "inherit" }
114
114
  );
115
115
  child.on("close", (code) => {
116
- resolve4();
116
+ resolve5();
117
117
  });
118
118
  child.on("error", () => {
119
- resolve4();
119
+ resolve5();
120
120
  });
121
121
  });
122
122
  }
@@ -955,19 +955,154 @@ async function createUseCase(name, tierInput, options) {
955
955
  }
956
956
  }
957
957
 
958
+ // src/core/create-page.ts
959
+ import * as fs8 from "fs";
960
+ import * as path8 from "path";
961
+ import chalk4 from "chalk";
962
+
963
+ // src/core/page-templates.ts
964
+ import { pascalCase as pascalCase4 } from "change-case";
965
+ function pageTemplate(name, packageName) {
966
+ const pascal = pascalCase4(name);
967
+ const routePath = "/" + name;
968
+ const imports = [
969
+ `package:flutter/material.dart`,
970
+ `package:go_router/go_router.dart`,
971
+ `package:${packageName}/pages/views/${name}_view.dart`
972
+ ].sort();
973
+ return `${imports.map((i) => `import '${i}';`).join("\n")}
974
+
975
+ class ${pascal}Page extends GoRoute {
976
+ ${pascal}Page({super.name, super.routes})
977
+ : super(
978
+ path: fullPath,
979
+ pageBuilder: (context, state) =>
980
+ const MaterialPage(child: ${pascal}View()),
981
+ );
982
+
983
+ static const fullPath = '${routePath}';
984
+
985
+ static void open(BuildContext context) => context.go(fullPath);
986
+ }
987
+ `;
988
+ }
989
+ function viewTemplate(name) {
990
+ const pascal = pascalCase4(name);
991
+ return `import 'package:flutter/material.dart';
992
+
993
+ class ${pascal}View extends StatelessWidget {
994
+ const ${pascal}View({super.key});
995
+
996
+ @override
997
+ Widget build(BuildContext context) {
998
+ return Scaffold(
999
+ appBar: AppBar(title: const Text('${pascal}')),
1000
+ body: const Center(child: Text('${pascal}')),
1001
+ );
1002
+ }
1003
+ }
1004
+ `;
1005
+ }
1006
+
1007
+ // src/core/create-page.ts
1008
+ var SNAKE_CASE_REGEX4 = /^[a-z][a-z0-9_]*$/;
1009
+ async function createPage(name, options) {
1010
+ const pagesPath = path8.resolve(options.pagesPath);
1011
+ if (!name || name.trim().length === 0) {
1012
+ throw new Error("Page name is required.");
1013
+ }
1014
+ if (!SNAKE_CASE_REGEX4.test(name)) {
1015
+ throw new Error("Page name must be snake_case (lowercase letters, digits, underscores).");
1016
+ }
1017
+ if (!fs8.existsSync(pagesPath)) {
1018
+ throw new Error(`Path does not exist: ${pagesPath}`);
1019
+ }
1020
+ const packageName = extractPackageName(pagesPath);
1021
+ const pageFile = path8.join(pagesPath, `${name}_page.dart`);
1022
+ const viewsDir = path8.join(pagesPath, "views");
1023
+ const viewFile = path8.join(viewsDir, `${name}_view.dart`);
1024
+ if (fs8.existsSync(pageFile)) {
1025
+ throw new Error(`Page "${name}" already exists at ${pageFile}`);
1026
+ }
1027
+ if (fs8.existsSync(viewFile)) {
1028
+ throw new Error(`View "${name}" already exists at ${viewFile}`);
1029
+ }
1030
+ fs8.mkdirSync(viewsDir, { recursive: true });
1031
+ if (!packageName) {
1032
+ throw new Error(
1033
+ `Could not determine package name from path: ${pagesPath}
1034
+ Expected path pattern: .../packages/<name>/lib/pages`
1035
+ );
1036
+ }
1037
+ fs8.writeFileSync(pageFile, pageTemplate(name, packageName));
1038
+ console.log(chalk4.green(` \u2713 Page file created: ${pageFile}`));
1039
+ fs8.writeFileSync(viewFile, viewTemplate(name));
1040
+ console.log(chalk4.green(` \u2713 View file created: ${viewFile}`));
1041
+ updateViewsBarrel(viewsDir, name);
1042
+ updatePagesBarrel(pagesPath, name);
1043
+ }
1044
+ function updateViewsBarrel(viewsDir, name) {
1045
+ const barrelPath = path8.join(viewsDir, "views.dart");
1046
+ const exportLine = `export '${name}_view.dart';`;
1047
+ let lines = [];
1048
+ if (fs8.existsSync(barrelPath)) {
1049
+ const content = fs8.readFileSync(barrelPath, "utf8");
1050
+ lines = content.split("\n").filter((l) => l.trim().length > 0);
1051
+ }
1052
+ if (lines.includes(exportLine)) {
1053
+ console.log(chalk4.blue(" \xB7 Export already in views.dart"));
1054
+ return;
1055
+ }
1056
+ lines.push(exportLine);
1057
+ lines.sort();
1058
+ fs8.writeFileSync(barrelPath, lines.join("\n") + "\n");
1059
+ console.log(chalk4.green(" \u2713 views.dart updated"));
1060
+ }
1061
+ function updatePagesBarrel(pagesPath, name) {
1062
+ const barrelPath = path8.join(pagesPath, "pages.dart");
1063
+ const pageExport = `export '${name}_page.dart';`;
1064
+ const viewsExport = `export 'views/views.dart';`;
1065
+ let lines = [];
1066
+ if (fs8.existsSync(barrelPath)) {
1067
+ const content = fs8.readFileSync(barrelPath, "utf8");
1068
+ lines = content.split("\n").filter((l) => l.trim().length > 0);
1069
+ }
1070
+ let modified = false;
1071
+ if (!lines.includes(pageExport)) {
1072
+ lines.push(pageExport);
1073
+ modified = true;
1074
+ }
1075
+ if (!lines.includes(viewsExport)) {
1076
+ lines.push(viewsExport);
1077
+ modified = true;
1078
+ }
1079
+ if (modified) {
1080
+ lines.sort();
1081
+ fs8.writeFileSync(barrelPath, lines.join("\n") + "\n");
1082
+ console.log(chalk4.green(" \u2713 pages.dart updated"));
1083
+ } else {
1084
+ console.log(chalk4.blue(" \xB7 pages.dart already up to date"));
1085
+ }
1086
+ }
1087
+ function extractPackageName(pagesPath) {
1088
+ const normalized = pagesPath.replace(/\\/g, "/");
1089
+ const match = normalized.match(/\/([^/]+)\/lib\/pages\/?$/);
1090
+ return match ? match[1] : null;
1091
+ }
1092
+
958
1093
  // src/interactive.ts
959
- import * as fs14 from "fs";
1094
+ import * as fs16 from "fs";
960
1095
  import * as os from "os";
961
- import * as path13 from "path";
962
- import { execSync as execSync2 } from "child_process";
1096
+ import * as path15 from "path";
1097
+ import { execSync as execSync3 } from "child_process";
963
1098
  import * as clack from "@clack/prompts";
964
- import chalk9 from "chalk";
1099
+ import chalk11 from "chalk";
965
1100
 
966
1101
  // src/core/create-endpoint.ts
967
- import * as fs9 from "fs";
968
- import * as path8 from "path";
969
- import chalk4 from "chalk";
970
- import { pascalCase as pascalCase4, camelCase as camelCase2 } from "change-case";
1102
+ import * as fs10 from "fs";
1103
+ import * as path9 from "path";
1104
+ import chalk5 from "chalk";
1105
+ import { pascalCase as pascalCase5, camelCase as camelCase2 } from "change-case";
971
1106
 
972
1107
  // src/core/endpoint-templates.ts
973
1108
  import { camelCase } from "change-case";
@@ -1050,8 +1185,8 @@ ${paramsClass}
1050
1185
  }
1051
1186
  `;
1052
1187
  }
1053
- function retrofitMethod(methodName, path14, httpMethod, params, returnType) {
1054
- const httpAnnotation = `@${httpMethod.toUpperCase()}('${path14}')`;
1188
+ function retrofitMethod(methodName, path16, httpMethod, params, returnType) {
1189
+ const httpAnnotation = `@${httpMethod.toUpperCase()}('${path16}')`;
1055
1190
  const paramList = params.map((p) => {
1056
1191
  if (p.isPath) return `@Path('${p.name}') ${p.type} ${p.name}`;
1057
1192
  if (p.isBody) return `@Body() ${p.type} ${p.name}`;
@@ -1117,9 +1252,9 @@ ${annotation}${useCaseClass} ${useCaseCamel}(${repoInterface} repository) =>
1117
1252
  }
1118
1253
 
1119
1254
  // src/core/dart-injector.ts
1120
- import * as fs8 from "fs";
1255
+ import * as fs9 from "fs";
1121
1256
  function injectMethod(filePath, className, methodCode, dedupKey) {
1122
- const content = fs8.readFileSync(filePath, "utf8");
1257
+ const content = fs9.readFileSync(filePath, "utf8");
1123
1258
  const dedup = dedupKey ?? findSignature(methodCode);
1124
1259
  if (dedup && content.includes(dedup)) {
1125
1260
  return;
@@ -1150,10 +1285,10 @@ function injectMethod(filePath, className, methodCode, dedupKey) {
1150
1285
  }
1151
1286
  const indentedMethod = methodCode.split("\n").map((line) => line.trim() ? ` ${line}` : "").join("\n");
1152
1287
  const newContent = content.slice(0, classEnd) + "\n" + indentedMethod + "\n" + content.slice(classEnd);
1153
- fs8.writeFileSync(filePath, newContent);
1288
+ fs9.writeFileSync(filePath, newContent);
1154
1289
  }
1155
1290
  function injectImport(filePath, importLine) {
1156
- const content = fs8.readFileSync(filePath, "utf8");
1291
+ const content = fs9.readFileSync(filePath, "utf8");
1157
1292
  if (content.includes(importLine.trim())) {
1158
1293
  return;
1159
1294
  }
@@ -1163,15 +1298,15 @@ function injectImport(filePath, importLine) {
1163
1298
  const lastImport = imports[imports.length - 1];
1164
1299
  const insertPos = lastImport.index + lastImport[0].length;
1165
1300
  const newContent = content.slice(0, insertPos) + "\n" + importLine + content.slice(insertPos);
1166
- fs8.writeFileSync(filePath, newContent);
1301
+ fs9.writeFileSync(filePath, newContent);
1167
1302
  } else {
1168
- fs8.writeFileSync(filePath, importLine + "\n\n" + content);
1303
+ fs9.writeFileSync(filePath, importLine + "\n\n" + content);
1169
1304
  }
1170
1305
  }
1171
1306
  function injectExport(filePath, exportLine) {
1172
1307
  let content = "";
1173
- if (fs8.existsSync(filePath)) {
1174
- content = fs8.readFileSync(filePath, "utf8");
1308
+ if (fs9.existsSync(filePath)) {
1309
+ content = fs9.readFileSync(filePath, "utf8");
1175
1310
  }
1176
1311
  if (content.includes(exportLine)) {
1177
1312
  return;
@@ -1179,7 +1314,7 @@ function injectExport(filePath, exportLine) {
1179
1314
  const lines = content.split("\n").filter((l) => l.trim().length > 0);
1180
1315
  lines.push(exportLine);
1181
1316
  lines.sort();
1182
- fs8.writeFileSync(filePath, lines.join("\n") + "\n");
1317
+ fs9.writeFileSync(filePath, lines.join("\n") + "\n");
1183
1318
  }
1184
1319
  function findSignature(methodCode) {
1185
1320
  const lines = methodCode.trim().split("\n");
@@ -1194,51 +1329,51 @@ function findSignature(methodCode) {
1194
1329
 
1195
1330
  // src/core/create-endpoint.ts
1196
1331
  async function createEndpoint(options) {
1197
- const lib = path8.join(options.projectRoot, "lib");
1198
- const pascal = pascalCase4(options.useCaseName);
1199
- const useCasePascal = pascalCase4(options.useCaseName);
1332
+ const lib = path9.join(options.projectRoot, "lib");
1333
+ const pascal = pascalCase5(options.useCaseName);
1334
+ const useCasePascal = pascalCase5(options.useCaseName);
1200
1335
  const useCaseSnake = options.useCaseName;
1201
1336
  const needsBody = ["POST", "PUT", "PATCH"].includes(options.httpMethod);
1202
1337
  const domain = extractDomain(options.bffApiFile);
1203
- const datasourceFile = path8.join(lib, "data", "datasources", `${domain}_rest_datasource.dart`);
1204
- const datasourceClassName = `${pascalCase4(domain)}RestDataSource`;
1205
- const repositoryInterfaceFile = path8.join(lib, "domain", "repositories", `${domain}_repository.dart`);
1206
- const repositoryInterfaceName = `${pascalCase4(domain)}Repository`;
1207
- const repositoryImplFile = path8.join(lib, "data", "repositories", `${domain}_repository_data.dart`);
1208
- const repositoryImplClassName = `${pascalCase4(domain)}RepositoryData`;
1338
+ const datasourceFile = path9.join(lib, "data", "datasources", `${domain}_rest_datasource.dart`);
1339
+ const datasourceClassName = `${pascalCase5(domain)}RestDataSource`;
1340
+ const repositoryInterfaceFile = path9.join(lib, "domain", "repositories", `${domain}_repository.dart`);
1341
+ const repositoryInterfaceName = `${pascalCase5(domain)}Repository`;
1342
+ const repositoryImplFile = path9.join(lib, "data", "repositories", `${domain}_repository_data.dart`);
1343
+ const repositoryImplClassName = `${pascalCase5(domain)}RepositoryData`;
1209
1344
  const feature = domain;
1210
1345
  const pathParams = extractPathParams(options.endpointPath);
1211
1346
  const methodParams = buildMethodParams(options, pathParams, needsBody);
1212
1347
  const methodParamsForSignature = methodParams.map((p) => ({ name: p.name, type: p.type }));
1213
1348
  const modelType = `${pascal}Model`;
1214
1349
  const entityType = `${pascal}Entity`;
1215
- const spinner3 = (msg) => console.log(chalk4.cyan(` \u2192 ${msg}`));
1350
+ const spinner3 = (msg) => console.log(chalk5.cyan(` \u2192 ${msg}`));
1216
1351
  spinner3("Generating entity");
1217
- const entityDir = path8.join(lib, "domain", "entities", feature);
1218
- fs9.mkdirSync(entityDir, { recursive: true });
1219
- fs9.writeFileSync(
1220
- path8.join(entityDir, `${useCaseSnake}_entity.dart`),
1352
+ const entityDir = path9.join(lib, "domain", "entities", feature);
1353
+ fs10.mkdirSync(entityDir, { recursive: true });
1354
+ fs10.writeFileSync(
1355
+ path9.join(entityDir, `${useCaseSnake}_entity.dart`),
1221
1356
  entityBoilerplate(pascal)
1222
1357
  );
1223
1358
  spinner3("Generating model");
1224
- const modelDir = path8.join(lib, "data", "models", feature);
1225
- fs9.mkdirSync(modelDir, { recursive: true });
1226
- fs9.writeFileSync(
1227
- path8.join(modelDir, `${useCaseSnake}_model.dart`),
1359
+ const modelDir = path9.join(lib, "data", "models", feature);
1360
+ fs10.mkdirSync(modelDir, { recursive: true });
1361
+ fs10.writeFileSync(
1362
+ path9.join(modelDir, `${useCaseSnake}_model.dart`),
1228
1363
  modelBoilerplate(useCaseSnake, pascal, options.projectName)
1229
1364
  );
1230
1365
  if (needsBody) {
1231
1366
  spinner3("Generating request model");
1232
- const reqModelDir = path8.join(lib, "data", "models", feature);
1233
- fs9.mkdirSync(reqModelDir, { recursive: true });
1234
- fs9.writeFileSync(
1235
- path8.join(reqModelDir, `${useCaseSnake}_request_model.dart`),
1367
+ const reqModelDir = path9.join(lib, "data", "models", feature);
1368
+ fs10.mkdirSync(reqModelDir, { recursive: true });
1369
+ fs10.writeFileSync(
1370
+ path9.join(reqModelDir, `${useCaseSnake}_request_model.dart`),
1236
1371
  requestModelBoilerplate(useCaseSnake, pascal)
1237
1372
  );
1238
1373
  }
1239
1374
  spinner3("Injecting Retrofit method");
1240
- const bffPath = path8.resolve(options.bffApiFile);
1241
- if (fs9.existsSync(bffPath)) {
1375
+ const bffPath = path9.resolve(options.bffApiFile);
1376
+ if (fs10.existsSync(bffPath)) {
1242
1377
  const retrofitParams = buildRetrofitParams(options, pathParams, needsBody);
1243
1378
  const method = retrofitMethod(
1244
1379
  camelCase2(options.useCaseName),
@@ -1249,11 +1384,11 @@ async function createEndpoint(options) {
1249
1384
  );
1250
1385
  injectMethod(bffPath, extractClassName(bffPath), method);
1251
1386
  } else {
1252
- console.log(chalk4.yellow(` \u26A0 BFF API file not found: ${bffPath}`));
1387
+ console.log(chalk5.yellow(` \u26A0 BFF API file not found: ${bffPath}`));
1253
1388
  }
1254
1389
  spinner3("Injecting datasource method");
1255
- const dsPath = path8.resolve(datasourceFile);
1256
- if (fs9.existsSync(dsPath)) {
1390
+ const dsPath = path9.resolve(datasourceFile);
1391
+ if (fs10.existsSync(dsPath)) {
1257
1392
  const dsMethod = datasourceMethod(
1258
1393
  camelCase2(options.useCaseName),
1259
1394
  modelType,
@@ -1261,11 +1396,11 @@ async function createEndpoint(options) {
1261
1396
  );
1262
1397
  injectMethod(dsPath, datasourceClassName, dsMethod);
1263
1398
  } else {
1264
- console.log(chalk4.yellow(` \u26A0 Datasource file not found: ${dsPath}`));
1399
+ console.log(chalk5.yellow(` \u26A0 Datasource file not found: ${dsPath}`));
1265
1400
  }
1266
1401
  spinner3("Injecting repository interface method");
1267
- const repoIfacePath = path8.resolve(repositoryInterfaceFile);
1268
- if (fs9.existsSync(repoIfacePath)) {
1402
+ const repoIfacePath = path9.resolve(repositoryInterfaceFile);
1403
+ if (fs10.existsSync(repoIfacePath)) {
1269
1404
  const ifaceMethod = repositoryInterfaceMethod(
1270
1405
  camelCase2(options.useCaseName),
1271
1406
  entityType,
@@ -1273,11 +1408,11 @@ async function createEndpoint(options) {
1273
1408
  );
1274
1409
  injectMethod(repoIfacePath, repositoryInterfaceName, ifaceMethod);
1275
1410
  } else {
1276
- console.log(chalk4.yellow(` \u26A0 Repository interface not found: ${repoIfacePath}`));
1411
+ console.log(chalk5.yellow(` \u26A0 Repository interface not found: ${repoIfacePath}`));
1277
1412
  }
1278
1413
  spinner3("Injecting repository implementation method");
1279
- const repoImplPath = path8.resolve(repositoryImplFile);
1280
- if (fs9.existsSync(repoImplPath)) {
1414
+ const repoImplPath = path9.resolve(repositoryImplFile);
1415
+ if (fs10.existsSync(repoImplPath)) {
1281
1416
  const dsVarName = camelCase2(datasourceClassName);
1282
1417
  const implMethod = repositoryImplMethod(
1283
1418
  camelCase2(options.useCaseName),
@@ -1288,13 +1423,13 @@ async function createEndpoint(options) {
1288
1423
  );
1289
1424
  injectMethod(repoImplPath, repositoryImplClassName, implMethod);
1290
1425
  } else {
1291
- console.log(chalk4.yellow(` \u26A0 Repository implementation not found: ${repoImplPath}`));
1426
+ console.log(chalk5.yellow(` \u26A0 Repository implementation not found: ${repoImplPath}`));
1292
1427
  }
1293
1428
  spinner3("Generating UseCase");
1294
- const useCaseDir = path8.join(lib, "domain", "usecases", feature);
1295
- fs9.mkdirSync(useCaseDir, { recursive: true });
1296
- fs9.writeFileSync(
1297
- path8.join(useCaseDir, `${useCaseSnake}_usecase.dart`),
1429
+ const useCaseDir = path9.join(lib, "domain", "usecases", feature);
1430
+ fs10.mkdirSync(useCaseDir, { recursive: true });
1431
+ fs10.writeFileSync(
1432
+ path9.join(useCaseDir, `${useCaseSnake}_usecase.dart`),
1298
1433
  useCaseTemplate2(
1299
1434
  useCasePascal,
1300
1435
  camelCase2(options.useCaseName),
@@ -1305,39 +1440,39 @@ async function createEndpoint(options) {
1305
1440
  )
1306
1441
  );
1307
1442
  spinner3("Updating barrel files");
1308
- const dsFileName = path8.basename(datasourceFile);
1443
+ const dsFileName = path9.basename(datasourceFile);
1309
1444
  injectExport(
1310
- path8.join(lib, "data", "datasources", "datasources.dart"),
1445
+ path9.join(lib, "data", "datasources", "datasources.dart"),
1311
1446
  `export '${dsFileName}';`
1312
1447
  );
1313
- const entityBarrel = path8.join(lib, "domain", "entities", feature, `${feature}.dart`);
1448
+ const entityBarrel = path9.join(lib, "domain", "entities", feature, `${feature}.dart`);
1314
1449
  injectExport(entityBarrel, `export '${useCaseSnake}_entity.dart';`);
1315
1450
  injectExport(
1316
- path8.join(lib, "domain", "entities", "entities.dart"),
1451
+ path9.join(lib, "domain", "entities", "entities.dart"),
1317
1452
  `export '${feature}/${feature}.dart';`
1318
1453
  );
1319
- const modelBarrel = path8.join(lib, "data", "models", feature, `${feature}.dart`);
1454
+ const modelBarrel = path9.join(lib, "data", "models", feature, `${feature}.dart`);
1320
1455
  injectExport(modelBarrel, `export '${useCaseSnake}_model.dart';`);
1321
1456
  if (needsBody) {
1322
1457
  injectExport(modelBarrel, `export '${useCaseSnake}_request_model.dart';`);
1323
1458
  }
1324
1459
  injectExport(
1325
- path8.join(lib, "data", "models", "models.dart"),
1460
+ path9.join(lib, "data", "models", "models.dart"),
1326
1461
  `export '${feature}/${feature}.dart';`
1327
1462
  );
1328
- const useCaseBarrel = path8.join(useCaseDir, `${feature}.dart`);
1463
+ const useCaseBarrel = path9.join(useCaseDir, `${feature}.dart`);
1329
1464
  injectExport(useCaseBarrel, `export '${useCaseSnake}_usecase.dart';`);
1330
1465
  injectExport(
1331
- path8.join(lib, "domain", "usecases", "usecases.dart"),
1466
+ path9.join(lib, "domain", "usecases", "usecases.dart"),
1332
1467
  `export '${feature}/${feature}.dart';`
1333
1468
  );
1334
1469
  if (options.diTarget && options.diTarget !== "none") {
1335
1470
  spinner3("Registering in DI modules");
1336
1471
  const appBaseDir = findAppBasePackageDir(options.projectRoot, options.diTarget);
1337
1472
  if (appBaseDir) {
1338
- const domainPascal = pascalCase4(domain);
1473
+ const domainPascal = pascalCase5(domain);
1339
1474
  const lazy = options.diLazySingleton !== false;
1340
- const dsModuleFile = path8.join(appBaseDir, "datasources_module.dart");
1475
+ const dsModuleFile = path9.join(appBaseDir, "datasources_module.dart");
1341
1476
  const dsRegistration = datasourceModuleRegistration(domainPascal, lazy);
1342
1477
  injectModuleRegistration(
1343
1478
  dsModuleFile,
@@ -1345,7 +1480,7 @@ async function createEndpoint(options) {
1345
1480
  dsRegistration,
1346
1481
  `${domainPascal}RestDataSource`
1347
1482
  );
1348
- const repoModuleFile = path8.join(appBaseDir, "repositories_module.dart");
1483
+ const repoModuleFile = path9.join(appBaseDir, "repositories_module.dart");
1349
1484
  const repoRegistration = repositoryModuleRegistration(domainPascal, lazy);
1350
1485
  injectModuleRegistration(
1351
1486
  repoModuleFile,
@@ -1353,7 +1488,7 @@ async function createEndpoint(options) {
1353
1488
  repoRegistration,
1354
1489
  `${domainPascal}RepositoryData`
1355
1490
  );
1356
- const ucModuleFile = path8.join(appBaseDir, "usecases_module.dart");
1491
+ const ucModuleFile = path9.join(appBaseDir, "usecases_module.dart");
1357
1492
  const ucRegistration = useCaseModuleRegistration(useCasePascal, domainPascal, lazy);
1358
1493
  injectModuleRegistration(
1359
1494
  ucModuleFile,
@@ -1366,14 +1501,14 @@ async function createEndpoint(options) {
1366
1501
  injectImport(repoModuleFile, coreImport);
1367
1502
  injectImport(ucModuleFile, coreImport);
1368
1503
  } else {
1369
- console.log(chalk4.yellow(` \u26A0 Package "${options.diTarget}" not found in monorepo`));
1504
+ console.log(chalk5.yellow(` \u26A0 Package "${options.diTarget}" not found in monorepo`));
1370
1505
  }
1371
1506
  }
1372
- console.log(chalk4.green(`
1507
+ console.log(chalk5.green(`
1373
1508
  \u2713 Endpoint "${options.useCaseName}" generated successfully.`));
1374
1509
  }
1375
1510
  function extractDomain(bffApiFile) {
1376
- const baseName = path8.basename(bffApiFile);
1511
+ const baseName = path9.basename(bffApiFile);
1377
1512
  const match = baseName.match(/^bff_(.+)_api\.dart$/);
1378
1513
  if (match) return match[1];
1379
1514
  return baseName.replace(/\.dart$/, "");
@@ -1390,7 +1525,7 @@ function extractPathParams(endpointPath) {
1390
1525
  function buildMethodParams(options, pathParams, hasRequestBody) {
1391
1526
  const params = [...pathParams];
1392
1527
  if (hasRequestBody) {
1393
- const reqPascal = pascalCase4(options.useCaseName);
1528
+ const reqPascal = pascalCase5(options.useCaseName);
1394
1529
  params.push({ name: "body", type: `${reqPascal}RequestModel` });
1395
1530
  }
1396
1531
  return params;
@@ -1401,43 +1536,43 @@ function buildRetrofitParams(options, pathParams, hasRequestBody) {
1401
1536
  params.push({ ...pp, isPath: true });
1402
1537
  }
1403
1538
  if (hasRequestBody) {
1404
- const reqPascal = pascalCase4(options.useCaseName);
1539
+ const reqPascal = pascalCase5(options.useCaseName);
1405
1540
  params.push({ name: "body", type: `${reqPascal}RequestModel`, isBody: true });
1406
1541
  }
1407
1542
  return params;
1408
1543
  }
1409
1544
  function extractClassName(filePath) {
1410
- const content = fs9.readFileSync(filePath, "utf8");
1545
+ const content = fs10.readFileSync(filePath, "utf8");
1411
1546
  const match = content.match(/class\s+(\w+)\s+/);
1412
1547
  if (!match) throw new Error(`No class found in ${filePath}`);
1413
1548
  return match[1];
1414
1549
  }
1415
1550
  function findAppBasePackageDir(projectRoot, packageName) {
1416
- let dir = path8.resolve(projectRoot);
1551
+ let dir = path9.resolve(projectRoot);
1417
1552
  for (let i = 0; i < 10; i++) {
1418
- const candidate = path8.join(dir, "packages", packageName, "lib", "dependencies");
1419
- if (fs9.existsSync(candidate)) {
1553
+ const candidate = path9.join(dir, "packages", packageName, "lib", "dependencies");
1554
+ if (fs10.existsSync(candidate)) {
1420
1555
  return candidate;
1421
1556
  }
1422
- const parent = path8.dirname(dir);
1557
+ const parent = path9.dirname(dir);
1423
1558
  if (parent === dir) break;
1424
1559
  dir = parent;
1425
1560
  }
1426
1561
  return null;
1427
1562
  }
1428
1563
  function injectModuleRegistration(filePath, className, registrationCode, dedupKey) {
1429
- if (!fs9.existsSync(filePath)) {
1430
- console.log(chalk4.yellow(` \u26A0 Module file not found: ${filePath}`));
1564
+ if (!fs10.existsSync(filePath)) {
1565
+ console.log(chalk5.yellow(` \u26A0 Module file not found: ${filePath}`));
1431
1566
  return;
1432
1567
  }
1433
- const content = fs9.readFileSync(filePath, "utf8");
1568
+ const content = fs10.readFileSync(filePath, "utf8");
1434
1569
  if (content.includes(dedupKey)) {
1435
1570
  return;
1436
1571
  }
1437
1572
  const classRegex = new RegExp(`class\\s+${className}\\s*[^{]*\\{`);
1438
1573
  const classMatch = content.match(classRegex);
1439
1574
  if (!classMatch) {
1440
- console.log(chalk4.yellow(` \u26A0 Class "${className}" not found in ${filePath}`));
1575
+ console.log(chalk5.yellow(` \u26A0 Class "${className}" not found in ${filePath}`));
1441
1576
  return;
1442
1577
  }
1443
1578
  const classStart = content.indexOf(classMatch[0]);
@@ -1457,19 +1592,19 @@ function injectModuleRegistration(filePath, className, registrationCode, dedupKe
1457
1592
  }
1458
1593
  }
1459
1594
  if (classEnd === -1) {
1460
- console.log(chalk4.yellow(` \u26A0 Could not find closing brace for "${className}" in ${filePath}`));
1595
+ console.log(chalk5.yellow(` \u26A0 Could not find closing brace for "${className}" in ${filePath}`));
1461
1596
  return;
1462
1597
  }
1463
1598
  const indentedCode = registrationCode.split("\n").map((line) => line.trim() ? ` ${line}` : "").join("\n");
1464
1599
  const newContent = content.slice(0, classEnd) + "\n" + indentedCode + "\n" + content.slice(classEnd);
1465
- fs9.writeFileSync(filePath, newContent);
1600
+ fs10.writeFileSync(filePath, newContent);
1466
1601
  }
1467
1602
 
1468
1603
  // src/core/create-env-var.ts
1469
- import * as fs10 from "fs";
1470
- import * as path9 from "path";
1604
+ import * as fs11 from "fs";
1605
+ import * as path10 from "path";
1471
1606
  import { execSync } from "child_process";
1472
- import chalk5 from "chalk";
1607
+ import chalk6 from "chalk";
1473
1608
  import { camelCase as camelCase3 } from "change-case";
1474
1609
  function screamingSnakeToCamel(name) {
1475
1610
  return camelCase3(name.toLowerCase());
@@ -1557,38 +1692,39 @@ function appConfigModelJsonKey(camelName, dartType) {
1557
1692
  }
1558
1693
  }
1559
1694
  function discoverAppsWithEnv(monorepoRoot) {
1560
- const appsDir = path9.join(monorepoRoot, "apps");
1561
- if (!fs10.existsSync(appsDir)) return [];
1562
- return fs10.readdirSync(appsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).filter((d) => fs10.existsSync(path9.join(appsDir, d.name, "env"))).map((d) => d.name).sort();
1695
+ const appsDir = path10.join(monorepoRoot, "apps");
1696
+ if (!fs11.existsSync(appsDir)) return [];
1697
+ return fs11.readdirSync(appsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).filter((d) => fs11.existsSync(path10.join(appsDir, d.name, "env"))).map((d) => d.name).sort();
1563
1698
  }
1564
1699
  function injectIntoJsonFile(filePath, key, value, isTemplate) {
1565
- if (!fs10.existsSync(filePath)) {
1566
- console.log(chalk5.yellow(` Skipping ${filePath} (not found)`));
1567
- return;
1700
+ if (!fs11.existsSync(filePath)) {
1701
+ console.log(chalk6.yellow(` Skipping ${filePath} (not found)`));
1702
+ return null;
1568
1703
  }
1569
- const content = fs10.readFileSync(filePath, "utf8");
1704
+ const content = fs11.readFileSync(filePath, "utf8");
1570
1705
  const json = JSON.parse(content);
1571
1706
  if (key in json) {
1572
- console.log(chalk5.yellow(` Key "${key}" already exists in ${path9.basename(filePath)}`));
1573
- return;
1707
+ console.log(chalk6.yellow(` Key "${key}" already exists in ${path10.basename(filePath)}`));
1708
+ return null;
1574
1709
  }
1575
1710
  json[key] = isTemplate ? `\${${key}}` : value;
1576
- fs10.writeFileSync(filePath, JSON.stringify(json, null, 2) + "\n");
1577
- console.log(chalk5.green(` Updated ${path9.basename(filePath)}`));
1711
+ fs11.writeFileSync(filePath, JSON.stringify(json, null, 2) + "\n");
1712
+ console.log(chalk6.green(` Updated ${path10.basename(filePath)}`));
1713
+ return filePath;
1578
1714
  }
1579
1715
  function injectAbstractGetter(monorepoRoot, camelName, dartType) {
1580
- const packagesDir = path9.join(monorepoRoot, "packages");
1581
- if (!fs10.existsSync(packagesDir)) return;
1716
+ const packagesDir = path10.join(monorepoRoot, "packages");
1717
+ if (!fs11.existsSync(packagesDir)) return null;
1582
1718
  const envFile = findFileInPackages(packagesDir, "app_environment.dart");
1583
1719
  if (!envFile) {
1584
- console.log(chalk5.yellow(" app_environment.dart not found in any package"));
1585
- return;
1720
+ console.log(chalk6.yellow(" app_environment.dart not found in any package"));
1721
+ return null;
1586
1722
  }
1587
- const content = fs10.readFileSync(envFile, "utf8");
1723
+ const content = fs11.readFileSync(envFile, "utf8");
1588
1724
  const dedup = `get ${camelName}`;
1589
1725
  if (content.includes(dedup)) {
1590
- console.log(chalk5.yellow(` '${camelName}' already in AppEnvironment`));
1591
- return;
1726
+ console.log(chalk6.yellow(` '${camelName}' already in AppEnvironment`));
1727
+ return null;
1592
1728
  }
1593
1729
  const getterRegex = /\n\s+\w+(?:<[^>]+>)?\s+get\s+\w+;/g;
1594
1730
  let lastGetterMatch = null;
@@ -1597,43 +1733,46 @@ function injectAbstractGetter(monorepoRoot, camelName, dartType) {
1597
1733
  lastGetterMatch = match;
1598
1734
  }
1599
1735
  if (!lastGetterMatch) {
1600
- console.log(chalk5.yellow(" No getters found in AppEnvironment"));
1601
- return;
1736
+ console.log(chalk6.yellow(" No getters found in AppEnvironment"));
1737
+ return null;
1602
1738
  }
1603
1739
  const insertPos = lastGetterMatch.index + lastGetterMatch[0].length;
1604
1740
  const getterLine = `
1605
1741
  ${abstractGetterCode(camelName, dartType)}`;
1606
1742
  const newContent = content.slice(0, insertPos) + getterLine + content.slice(insertPos);
1607
- fs10.writeFileSync(envFile, newContent);
1608
- console.log(chalk5.green(` Injected abstract getter in ${formatPkgPath(monorepoRoot, envFile)}`));
1743
+ fs11.writeFileSync(envFile, newContent);
1744
+ console.log(chalk6.green(` Injected abstract getter in ${formatPkgPath(monorepoRoot, envFile)}`));
1745
+ return envFile;
1609
1746
  }
1610
1747
  function injectBuildEnvGetter(monorepoRoot, variableName, camelName, dartType) {
1611
- const packagesDir = path9.join(monorepoRoot, "packages");
1612
- if (!fs10.existsSync(packagesDir)) return;
1748
+ const packagesDir = path10.join(monorepoRoot, "packages");
1749
+ if (!fs11.existsSync(packagesDir)) return null;
1613
1750
  const buildEnvFile = findFileInPackages(packagesDir, "app_build_environment.dart");
1614
1751
  if (!buildEnvFile) {
1615
- console.log(chalk5.yellow(" app_build_environment.dart not found in any package"));
1616
- return;
1752
+ console.log(chalk6.yellow(" app_build_environment.dart not found in any package"));
1753
+ return null;
1617
1754
  }
1618
1755
  const code = buildEnvGetterCode(camelName, variableName, dartType);
1619
1756
  try {
1620
1757
  injectMethod(buildEnvFile, "AppBuildEnvironment", code, `get ${camelName}`);
1621
- console.log(chalk5.green(` Injected build env getter in ${formatPkgPath(monorepoRoot, buildEnvFile)}`));
1758
+ console.log(chalk6.green(` Injected build env getter in ${formatPkgPath(monorepoRoot, buildEnvFile)}`));
1759
+ return buildEnvFile;
1622
1760
  } catch (e) {
1623
- console.log(chalk5.yellow(` Skipped: ${e.message}`));
1761
+ console.log(chalk6.yellow(` Skipped: ${e.message}`));
1762
+ return null;
1624
1763
  }
1625
1764
  }
1626
1765
  function injectIntoRemoteConfigDefaults(vendorsPath, camelName, dartType) {
1627
- const content = fs10.readFileSync(vendorsPath, "utf8");
1766
+ const content = fs11.readFileSync(vendorsPath, "utf8");
1628
1767
  if (content.includes(`'${camelName}'`) || content.includes(`"${camelName}"`)) {
1629
- console.log(chalk5.yellow(` '${camelName}' already in ${path9.basename(vendorsPath)}`));
1630
- return;
1768
+ console.log(chalk6.yellow(` '${camelName}' already in ${path10.basename(vendorsPath)}`));
1769
+ return null;
1631
1770
  }
1632
1771
  const defaultValuesRegex = /final\s+defaultValues\s*=\s*(?:<String,\s*dynamic>\s*)?\{/;
1633
1772
  const match = content.match(defaultValuesRegex);
1634
1773
  if (!match) {
1635
- console.log(chalk5.yellow(` Could not find defaultValues map in ${path9.basename(vendorsPath)}`));
1636
- return;
1774
+ console.log(chalk6.yellow(` Could not find defaultValues map in ${path10.basename(vendorsPath)}`));
1775
+ return null;
1637
1776
  }
1638
1777
  const mapStart = content.indexOf(match[0]) + match[0].length;
1639
1778
  let braceCount = 1;
@@ -1649,8 +1788,8 @@ function injectIntoRemoteConfigDefaults(vendorsPath, camelName, dartType) {
1649
1788
  }
1650
1789
  }
1651
1790
  if (mapEnd === -1) {
1652
- console.log(chalk5.yellow(` Could not find end of defaultValues map`));
1653
- return;
1791
+ console.log(chalk6.yellow(` Could not find end of defaultValues map`));
1792
+ return null;
1654
1793
  }
1655
1794
  const valueExpr = dartType === "List<String>" ? `jsonEncode(env.${camelName})` : `env.${camelName}`;
1656
1795
  const beforeClose = content.slice(0, mapEnd);
@@ -1667,48 +1806,49 @@ function injectIntoRemoteConfigDefaults(vendorsPath, camelName, dartType) {
1667
1806
  const insertion = `${lastEntryIndent}'${camelName}': ${valueExpr},
1668
1807
  `;
1669
1808
  const newContent = content.slice(0, mapEnd) + insertion + content.slice(mapEnd);
1670
- fs10.writeFileSync(vendorsPath, newContent);
1671
- console.log(chalk5.green(` Injected into VendorsModule defaultValues`));
1809
+ fs11.writeFileSync(vendorsPath, newContent);
1810
+ console.log(chalk6.green(` Injected into VendorsModule defaultValues`));
1811
+ return vendorsPath;
1672
1812
  }
1673
1813
  function injectAppConfigProperty(configPath, camelName, dartType) {
1674
- const content = fs10.readFileSync(configPath, "utf8");
1814
+ const content = fs11.readFileSync(configPath, "utf8");
1675
1815
  if (content.includes(`final ${dartTypeForGetter(dartType)} ${camelName}`)) {
1676
- console.log(chalk5.yellow(` '${camelName}' already in AppConfig`));
1677
- return;
1816
+ console.log(chalk6.yellow(` '${camelName}' already in AppConfig`));
1817
+ return null;
1678
1818
  }
1679
1819
  const fieldLine = ` final ${dartTypeForGetter(dartType)} ${camelName};
1680
1820
  `;
1681
1821
  let newContent = content;
1682
- const propsMatch = newContent.match(/@override\n\s+List<Object\?>/);
1683
- if (propsMatch) {
1684
- const propsPos = newContent.indexOf(propsMatch[0]);
1685
- newContent = newContent.slice(0, propsPos) + fieldLine + newContent.slice(propsPos);
1822
+ const propsSeparator = newContent.search(/\n\n(\s*)@override\n\s+List<Object\?>/);
1823
+ if (propsSeparator !== -1) {
1824
+ newContent = newContent.slice(0, propsSeparator + 1) + fieldLine + newContent.slice(propsSeparator + 1);
1686
1825
  } else {
1687
1826
  newContent = injectBeforeClassClose(newContent, "AppConfig", ` final ${dartTypeForGetter(dartType)} ${camelName};`);
1688
1827
  }
1689
1828
  newContent = injectConstructorParam(newContent, "AppConfig", camelName, dartType);
1690
1829
  newContent = injectIntoPropsList(newContent, camelName);
1691
- fs10.writeFileSync(configPath, newContent);
1692
- console.log(chalk5.green(` Injected into AppConfig entity`));
1830
+ fs11.writeFileSync(configPath, newContent);
1831
+ console.log(chalk6.green(` Injected into AppConfig entity`));
1832
+ return configPath;
1693
1833
  }
1694
1834
  function injectAppConfigModelProperty(modelPath, camelName, dartType) {
1695
- const content = fs10.readFileSync(modelPath, "utf8");
1835
+ const content = fs11.readFileSync(modelPath, "utf8");
1696
1836
  if (content.includes(`final ${dartTypeForGetter(dartType)} ${camelName}`)) {
1697
- console.log(chalk5.yellow(` '${camelName}' already in AppConfigModel`));
1698
- return;
1837
+ console.log(chalk6.yellow(` '${camelName}' already in AppConfigModel`));
1838
+ return null;
1699
1839
  }
1700
1840
  const jsonKey = appConfigModelJsonKey(camelName, dartType);
1701
- const fieldLines = jsonKey ? ` ${jsonKey}
1841
+ const fieldLines = jsonKey ? `
1842
+ ${jsonKey}
1843
+ final ${dartTypeForGetter(dartType)} ${camelName};
1844
+ ` : `
1702
1845
  final ${dartTypeForGetter(dartType)} ${camelName};
1703
- ` : ` final ${dartTypeForGetter(dartType)} ${camelName};
1704
1846
  `;
1705
1847
  let newContent = content;
1706
1848
  const staticPos = newContent.search(/\n\s+static\s/);
1707
1849
  const factoryPos = newContent.search(/\n\s+factory\s+AppConfigModel/);
1708
1850
  let insertAnchor = -1;
1709
- if (staticPos !== -1 && factoryPos !== -1) {
1710
- insertAnchor = Math.min(staticPos, factoryPos);
1711
- } else if (staticPos !== -1) {
1851
+ if (staticPos !== -1) {
1712
1852
  insertAnchor = staticPos;
1713
1853
  } else if (factoryPos !== -1) {
1714
1854
  insertAnchor = factoryPos;
@@ -1720,8 +1860,9 @@ function injectAppConfigModelProperty(modelPath, camelName, dartType) {
1720
1860
  }
1721
1861
  newContent = injectConstructorParam(newContent, "AppConfigModel", camelName, dartType);
1722
1862
  newContent = injectIntoSuperCall(newContent, camelName);
1723
- fs10.writeFileSync(modelPath, newContent);
1724
- console.log(chalk5.green(` Injected into AppConfigModel`));
1863
+ fs11.writeFileSync(modelPath, newContent);
1864
+ console.log(chalk6.green(` Injected into AppConfigModel`));
1865
+ return modelPath;
1725
1866
  }
1726
1867
  function injectBeforeClassClose(content, className, line) {
1727
1868
  const classRegex = new RegExp(`class\\s+${className}\\s*[^{]*\\{`);
@@ -1893,9 +2034,9 @@ function injectIntoSuperCall(content, camelName) {
1893
2034
  return content.slice(0, parenEnd) + insertion + content.slice(parenEnd);
1894
2035
  }
1895
2036
  function findFileRecursive(dir, fileName) {
1896
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
2037
+ const entries = fs11.readdirSync(dir, { withFileTypes: true });
1897
2038
  for (const entry of entries) {
1898
- const fullPath = path9.join(dir, entry.name);
2039
+ const fullPath = path10.join(dir, entry.name);
1899
2040
  if (entry.isDirectory()) {
1900
2041
  const result = findFileRecursive(fullPath, fileName);
1901
2042
  if (result) return result;
@@ -1906,29 +2047,29 @@ function findFileRecursive(dir, fileName) {
1906
2047
  return null;
1907
2048
  }
1908
2049
  function discoverVendorsModules(monorepoRoot) {
1909
- const packagesDir = path9.join(monorepoRoot, "packages");
1910
- if (!fs10.existsSync(packagesDir)) return [];
2050
+ const packagesDir = path10.join(monorepoRoot, "packages");
2051
+ if (!fs11.existsSync(packagesDir)) return [];
1911
2052
  const results = [];
1912
- const packages = fs10.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
2053
+ const packages = fs11.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
1913
2054
  for (const pkg2 of packages) {
1914
- const pkgDir = path9.join(packagesDir, pkg2.name);
2055
+ const pkgDir = path10.join(packagesDir, pkg2.name);
1915
2056
  const found = findFileRecursive(pkgDir, "vendors_module.dart");
1916
2057
  if (found) results.push(pkg2.name);
1917
2058
  }
1918
2059
  return results.sort();
1919
2060
  }
1920
2061
  function findAppConfigFile(monorepoRoot) {
1921
- const packagesDir = path9.join(monorepoRoot, "packages");
1922
- if (!fs10.existsSync(packagesDir)) return null;
2062
+ const packagesDir = path10.join(monorepoRoot, "packages");
2063
+ if (!fs11.existsSync(packagesDir)) return null;
1923
2064
  return findClassInPackages(packagesDir, "AppConfig");
1924
2065
  }
1925
2066
  function findAppConfigModelFile(monorepoRoot) {
1926
- const packagesDir = path9.join(monorepoRoot, "packages");
1927
- if (!fs10.existsSync(packagesDir)) return null;
2067
+ const packagesDir = path10.join(monorepoRoot, "packages");
2068
+ if (!fs11.existsSync(packagesDir)) return null;
1928
2069
  return findClassInPackages(packagesDir, "AppConfigModel");
1929
2070
  }
1930
2071
  function findClassInPackages(packagesDir, className) {
1931
- const packages = fs10.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path9.join(packagesDir, d.name));
2072
+ const packages = fs11.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path10.join(packagesDir, d.name));
1932
2073
  for (const pkgDir of packages) {
1933
2074
  const found = findClassFileRecursive(pkgDir, className);
1934
2075
  if (found) return found;
@@ -1937,14 +2078,14 @@ function findClassInPackages(packagesDir, className) {
1937
2078
  }
1938
2079
  function findClassFileRecursive(dir, className) {
1939
2080
  const classRegex = new RegExp(`\\bclass\\s+${className}\\b`);
1940
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
2081
+ const entries = fs11.readdirSync(dir, { withFileTypes: true });
1941
2082
  for (const entry of entries) {
1942
- const fullPath = path9.join(dir, entry.name);
2083
+ const fullPath = path10.join(dir, entry.name);
1943
2084
  if (entry.isDirectory()) {
1944
2085
  const result = findClassFileRecursive(fullPath, className);
1945
2086
  if (result) return result;
1946
2087
  } else if (entry.name.endsWith(".dart") && !entry.name.endsWith(".g.dart")) {
1947
- const content = fs10.readFileSync(fullPath, "utf8");
2088
+ const content = fs11.readFileSync(fullPath, "utf8");
1948
2089
  if (classRegex.test(content)) {
1949
2090
  return fullPath;
1950
2091
  }
@@ -1953,7 +2094,7 @@ function findClassFileRecursive(dir, className) {
1953
2094
  return null;
1954
2095
  }
1955
2096
  function findFileInPackages(packagesDir, fileName) {
1956
- const packages = fs10.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path9.join(packagesDir, d.name));
2097
+ const packages = fs11.readdirSync(packagesDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => path10.join(packagesDir, d.name));
1957
2098
  for (const pkgDir of packages) {
1958
2099
  const found = findFileRecursive(pkgDir, fileName);
1959
2100
  if (found) return found;
@@ -1961,9 +2102,9 @@ function findFileInPackages(packagesDir, fileName) {
1961
2102
  return null;
1962
2103
  }
1963
2104
  function formatPkgPath(monorepoRoot, absPath) {
1964
- return path9.relative(monorepoRoot, absPath);
2105
+ return path10.relative(monorepoRoot, absPath);
1965
2106
  }
1966
- var spinner = (msg) => console.log(chalk5.cyan(` \u2192 ${msg}`));
2107
+ var spinner = (msg) => console.log(chalk6.cyan(` \u2192 ${msg}`));
1967
2108
  async function createEnvVar(options) {
1968
2109
  const {
1969
2110
  monorepoRoot,
@@ -1975,37 +2116,42 @@ async function createEnvVar(options) {
1975
2116
  includeInAppConfig
1976
2117
  } = options;
1977
2118
  const camelName = screamingSnakeToCamel(variableName);
1978
- console.log(chalk5.bold(`
1979
- Adding environment variable: ${chalk5.cyan(variableName)}
2119
+ const modifiedFiles = [];
2120
+ console.log(chalk6.bold(`
2121
+ Adding environment variable: ${chalk6.cyan(variableName)}
1980
2122
  `));
1981
2123
  spinner("PASO 1: Updating env JSON files");
1982
2124
  const jsonValue = typedJsonValue(defaultValue, dartType);
1983
- const appsDir = path9.join(monorepoRoot, "apps");
2125
+ const appsDir = path10.join(monorepoRoot, "apps");
1984
2126
  for (const app of selectedApps) {
1985
- const appEnvDir = path9.join(appsDir, app, "env");
2127
+ const appEnvDir = path10.join(appsDir, app, "env");
1986
2128
  const files = [
1987
2129
  { name: "example.env.json", isTemplate: true },
1988
2130
  { name: "development.env.json", isTemplate: false },
1989
2131
  { name: "production.env.json", isTemplate: false }
1990
2132
  ];
1991
2133
  for (const { name, isTemplate } of files) {
1992
- injectIntoJsonFile(path9.join(appEnvDir, name), variableName, jsonValue, isTemplate);
2134
+ const modified = injectIntoJsonFile(path10.join(appEnvDir, name), variableName, jsonValue, isTemplate);
2135
+ if (modified) modifiedFiles.push(modified);
1993
2136
  }
1994
2137
  }
1995
2138
  spinner("PASO 2: Injecting into AppEnvironment");
1996
- injectAbstractGetter(monorepoRoot, camelName, dartType);
2139
+ const envFile = injectAbstractGetter(monorepoRoot, camelName, dartType);
2140
+ if (envFile) modifiedFiles.push(envFile);
1997
2141
  spinner("PASO 3: Injecting into AppBuildEnvironment");
1998
- injectBuildEnvGetter(monorepoRoot, variableName, camelName, dartType);
2142
+ const buildEnvFile = injectBuildEnvGetter(monorepoRoot, variableName, camelName, dartType);
2143
+ if (buildEnvFile) modifiedFiles.push(buildEnvFile);
1999
2144
  if (includeInRemoteConfig) {
2000
2145
  spinner("PASO 4: Injecting into VendorsModule RemoteConfig");
2001
2146
  for (const pkgName of options.vendorsTargets) {
2002
- const pkgDir = path9.join(monorepoRoot, "packages", pkgName);
2147
+ const pkgDir = path10.join(monorepoRoot, "packages", pkgName);
2003
2148
  const vendorsPath = findFileRecursive(pkgDir, "vendors_module.dart");
2004
2149
  if (vendorsPath) {
2005
- console.log(chalk5.cyan(` \u2192 ${pkgName}/vendors_module.dart`));
2006
- injectIntoRemoteConfigDefaults(vendorsPath, camelName, dartType);
2150
+ console.log(chalk6.cyan(` \u2192 ${pkgName}/vendors_module.dart`));
2151
+ const modified = injectIntoRemoteConfigDefaults(vendorsPath, camelName, dartType);
2152
+ if (modified) modifiedFiles.push(modified);
2007
2153
  } else {
2008
- console.log(chalk5.yellow(` vendors_module.dart not found in ${pkgName}`));
2154
+ console.log(chalk6.yellow(` vendors_module.dart not found in ${pkgName}`));
2009
2155
  }
2010
2156
  }
2011
2157
  }
@@ -2013,46 +2159,476 @@ Adding environment variable: ${chalk5.cyan(variableName)}
2013
2159
  spinner("PASO 5: Injecting into AppConfig entity");
2014
2160
  const configPath = findAppConfigFile(monorepoRoot);
2015
2161
  if (configPath) {
2016
- injectAppConfigProperty(configPath, camelName, dartType);
2162
+ const modified = injectAppConfigProperty(configPath, camelName, dartType);
2163
+ if (modified) modifiedFiles.push(modified);
2017
2164
  } else {
2018
- console.log(chalk5.yellow(" app_config.dart not found, skipping AppConfig"));
2165
+ console.log(chalk6.yellow(" app_config.dart not found, skipping AppConfig"));
2019
2166
  }
2020
2167
  spinner("PASO 6: Injecting into AppConfigModel");
2021
2168
  const modelPath = findAppConfigModelFile(monorepoRoot);
2022
2169
  if (modelPath) {
2023
- injectAppConfigModelProperty(modelPath, camelName, dartType);
2170
+ const modified = injectAppConfigModelProperty(modelPath, camelName, dartType);
2171
+ if (modified) modifiedFiles.push(modified);
2172
+ } else {
2173
+ console.log(chalk6.yellow(" app_config_model.dart not found, skipping AppConfigModel"));
2174
+ }
2175
+ }
2176
+ console.log(chalk6.green("\nEnvironment variable added successfully!"));
2177
+ const dartFiles = modifiedFiles.filter((f) => f.endsWith(".dart"));
2178
+ if (dartFiles.length > 0) {
2179
+ spinner("Running dart format on modified files...");
2180
+ try {
2181
+ const fileList = dartFiles.join(" ");
2182
+ execSync(`dart format ${fileList}`, { cwd: monorepoRoot, stdio: "pipe" });
2183
+ console.log(chalk6.green(` Formatted ${dartFiles.length} file(s)`));
2184
+ } catch {
2185
+ console.log(chalk6.yellow(" dart format failed (you may need to run it manually)"));
2186
+ }
2187
+ }
2188
+ }
2189
+
2190
+ // src/core/create-package.ts
2191
+ import * as fs12 from "fs";
2192
+ import * as path11 from "path";
2193
+ import { execSync as execSync2 } from "child_process";
2194
+ import chalk7 from "chalk";
2195
+ var MAIN_TESTER_CONTENT = `// ignore_for_file: avoid_print
2196
+
2197
+ import 'dart:io';
2198
+
2199
+ void main() {
2200
+ final currentDir = Directory.current;
2201
+ final testDir = Directory('\${currentDir.path}/test');
2202
+
2203
+ try {
2204
+ final entities = testDir.listSync(recursive: true);
2205
+ final testFiles = <String>[];
2206
+
2207
+ print('Finding test files in \${testDir.path}:');
2208
+ print('----------------------------------------');
2209
+
2210
+ for (final entity in entities) {
2211
+ if (entity is File &&
2212
+ entity.path.endsWith('_test.dart') &&
2213
+ !entity.path.endsWith('/main_test.dart')) {
2214
+ final fullPath = entity.path;
2215
+ final relativePath = fullPath.substring(
2216
+ testDir.path.length + 1,
2217
+ );
2218
+
2219
+ print('Found test file: $relativePath');
2220
+ testFiles.add(relativePath);
2221
+ }
2222
+ }
2223
+
2224
+ print('----------------------------------------');
2225
+ print('Total test files found: \${testFiles.length}');
2226
+
2227
+ final mainTestContent = StringBuffer();
2228
+
2229
+ for (final file in testFiles) {
2230
+ final importName = file.replaceAll('/', '_').replaceAll('.dart', '');
2231
+ mainTestContent.writeln("import '$file' as $importName;");
2232
+ }
2233
+
2234
+ mainTestContent.writeln('\\nvoid main() {');
2235
+
2236
+ for (final file in testFiles) {
2237
+ final importName = file.replaceAll('/', '_').replaceAll('.dart', '');
2238
+ mainTestContent.writeln(' $importName.main();');
2239
+ }
2240
+
2241
+ mainTestContent.writeln('}');
2242
+
2243
+ final mainTestFile = File('\${testDir.path}/main_test.dart')
2244
+ ..writeAsStringSync(mainTestContent.toString());
2245
+
2246
+ print('\\nCreated file: \${mainTestFile.path}');
2247
+ print('----------------------------------------');
2248
+ } on Exception catch (e) {
2249
+ print('Error: $e');
2250
+ }
2251
+ }
2252
+ `;
2253
+ function buildPubspecContent(packageName) {
2254
+ const description = `${capitalize(packageName.replace(/_/g, " "))} package`;
2255
+ return `name: ${packageName}
2256
+ description: "${description}"
2257
+ version: 0.0.1
2258
+ publish_to: none
2259
+
2260
+ environment:
2261
+ sdk: ^3.8.1
2262
+ flutter: ">=1.17.0"
2263
+
2264
+ dependencies:
2265
+ core:
2266
+ design_system:
2267
+ flutter:
2268
+ sdk: flutter
2269
+ flutter_bloc: ^9.1.1
2270
+ freezed_annotation: ^3.1.0
2271
+ go_router: ^16.0.0
2272
+ localization:
2273
+
2274
+ dev_dependencies:
2275
+ bloc_test: ^10.0.0
2276
+ build_runner: ^2.5.4
2277
+ flutter_test:
2278
+ sdk: flutter
2279
+ freezed: ^3.2.0
2280
+ mocktail: ^1.0.4
2281
+ very_good_analysis: ^9.0.0
2282
+
2283
+ dependency_overrides:
2284
+ source_gen: ^4.2.0
2285
+
2286
+ flutter:
2287
+ uses-material-design: true
2288
+ `;
2289
+ }
2290
+ function buildGitignoreContent() {
2291
+ return `# Miscellaneous
2292
+ *.class
2293
+ *.log
2294
+ *.pyc
2295
+ *.swp
2296
+ .DS_Store
2297
+ .atom/
2298
+ .buildlog/
2299
+ .history
2300
+ .svn/
2301
+ migrate_working_dir/
2302
+
2303
+ # IntelliJ related
2304
+ *.iml
2305
+ *.ipr
2306
+ *.iws
2307
+ .idea/
2308
+
2309
+ # Flutter/Dart/Pub related
2310
+ /pubspec.lock
2311
+ **/doc/api/
2312
+ .dart_tool/
2313
+ .flutter-plugins
2314
+ .flutter-plugins-dependencies
2315
+ build/
2316
+
2317
+ coverage/
2318
+
2319
+ test/main_test.dart
2320
+ `;
2321
+ }
2322
+ function buildMakefileContent() {
2323
+ return `.PHONY: test
2324
+ test:
2325
+ dart test/main_tester.dart
2326
+ dart format test/main_test.dart
2327
+ dart fix --apply test/main_test.dart
2328
+ flutter test --coverage test/main_test.dart
2329
+ `;
2330
+ }
2331
+ function buildAnalysisOptionsContent() {
2332
+ return `include: ../../analysis_options.yaml
2333
+ `;
2334
+ }
2335
+ function buildBarrelExport(packageName) {
2336
+ return `export 'bloc/bloc.dart';
2337
+ export 'pages/pages.dart';
2338
+ `;
2339
+ }
2340
+ function buildEmptyBarrel() {
2341
+ return "";
2342
+ }
2343
+ function buildGitHubWorkflow(packageName) {
2344
+ return `name: packages/${packageName}
2345
+
2346
+ permissions:
2347
+ contents: read
2348
+ pull-requests: write
2349
+
2350
+ concurrency:
2351
+ group: \${{ github.workflow }}-\${{ github.event.pull_request.number || github.ref }}-${packageName}
2352
+ cancel-in-progress: true
2353
+
2354
+ on:
2355
+ push:
2356
+ branches:
2357
+ - master
2358
+ paths:
2359
+ - "packages/${packageName}/**"
2360
+ - ".github/workflows/${packageName}.yaml"
2361
+ - ".github/workflows/test.yaml"
2362
+ pull_request:
2363
+ branches:
2364
+ - master
2365
+ paths:
2366
+ - "packages/${packageName}/**"
2367
+ - ".github/workflows/${packageName}.yaml"
2368
+ - ".github/workflows/test.yaml"
2369
+
2370
+ jobs:
2371
+ test:
2372
+ uses: ./.github/workflows/test.yaml
2373
+ with:
2374
+ package_name: ${packageName}
2375
+ working_directory: packages/${packageName}
2376
+ `;
2377
+ }
2378
+ function capitalize(s) {
2379
+ return s.replace(/\b\w/g, (c) => c.toUpperCase());
2380
+ }
2381
+ function findWorkspaceFile(monorepoRoot) {
2382
+ const files = fs12.readdirSync(monorepoRoot);
2383
+ return files.find((f) => f.endsWith(".code-workspace")) ?? null;
2384
+ }
2385
+ function updateCodeWorkspace(monorepoRoot, packageName) {
2386
+ const wsFileName = findWorkspaceFile(monorepoRoot);
2387
+ if (!wsFileName) {
2388
+ console.log(chalk7.yellow(" No .code-workspace file found, skipping"));
2389
+ return;
2390
+ }
2391
+ const wsPath = path11.join(monorepoRoot, wsFileName);
2392
+ const content = fs12.readFileSync(wsPath, "utf8");
2393
+ const folderPath = `packages/${packageName}`;
2394
+ if (content.includes(`"path": "${folderPath}"`)) {
2395
+ console.log(chalk7.yellow(` Already in ${wsFileName}`));
2396
+ return;
2397
+ }
2398
+ const folderName = `\u{1F4E6} ${packageName}`;
2399
+ const newBlock = ` {
2400
+ "name": "${folderName}",
2401
+ "path": "${folderPath}"
2402
+ },`;
2403
+ const lines = content.split("\n");
2404
+ const foldersLineIdx = lines.findIndex((l) => l.includes('"folders"'));
2405
+ if (foldersLineIdx === -1) {
2406
+ console.log(chalk7.yellow(' No "folders" key found in workspace, skipping'));
2407
+ return;
2408
+ }
2409
+ let foldersOpenBracket = -1;
2410
+ for (let j = foldersLineIdx; j < lines.length; j++) {
2411
+ if (lines[j].includes("[")) {
2412
+ foldersOpenBracket = j;
2413
+ break;
2414
+ }
2415
+ }
2416
+ if (foldersOpenBracket === -1) {
2417
+ console.log(chalk7.yellow(" Could not find folders array, skipping"));
2418
+ return;
2419
+ }
2420
+ let bracketCount = 0;
2421
+ let foldersCloseBracket = -1;
2422
+ for (let j = foldersOpenBracket; j < lines.length; j++) {
2423
+ for (const ch of lines[j]) {
2424
+ if (ch === "[") bracketCount++;
2425
+ else if (ch === "]") {
2426
+ bracketCount--;
2427
+ if (bracketCount === 0) {
2428
+ foldersCloseBracket = j;
2429
+ break;
2430
+ }
2431
+ }
2432
+ }
2433
+ if (foldersCloseBracket !== -1) break;
2434
+ }
2435
+ if (foldersCloseBracket === -1) {
2436
+ console.log(chalk7.yellow(" Could not find folders array end, skipping"));
2437
+ return;
2438
+ }
2439
+ let widgetbookBlockStart = -1;
2440
+ let idx = foldersOpenBracket + 1;
2441
+ while (idx <= foldersCloseBracket) {
2442
+ const trimmed = lines[idx].trim();
2443
+ if (trimmed === "{" || trimmed.startsWith("{")) {
2444
+ let braceCount = 0;
2445
+ let blockEnd = -1;
2446
+ for (let j = idx; j <= foldersCloseBracket; j++) {
2447
+ for (const ch of lines[j]) {
2448
+ if (ch === "{") braceCount++;
2449
+ else if (ch === "}") {
2450
+ braceCount--;
2451
+ if (braceCount === 0) {
2452
+ blockEnd = j;
2453
+ break;
2454
+ }
2455
+ }
2456
+ }
2457
+ if (blockEnd !== -1) break;
2458
+ }
2459
+ if (blockEnd !== -1) {
2460
+ const blockText = lines.slice(idx, blockEnd + 1).join("\n");
2461
+ if (blockText.includes("widgetbook")) {
2462
+ widgetbookBlockStart = idx;
2463
+ break;
2464
+ }
2465
+ idx = blockEnd + 1;
2466
+ continue;
2467
+ }
2468
+ }
2469
+ idx++;
2470
+ }
2471
+ if (widgetbookBlockStart === -1) {
2472
+ console.log(chalk7.yellow(" No widgetbook entry found in workspace, skipping"));
2473
+ return;
2474
+ }
2475
+ lines.splice(widgetbookBlockStart, 0, newBlock);
2476
+ fs12.writeFileSync(wsPath, lines.join("\n"));
2477
+ console.log(chalk7.green(` Updated ${wsFileName}`));
2478
+ }
2479
+ function updateHelixConfig(monorepoRoot, packageName) {
2480
+ const helixPath = path11.join(monorepoRoot, ".helix", "languages.toml");
2481
+ if (!fs12.existsSync(helixPath)) {
2482
+ console.log(chalk7.yellow(" No .helix/languages.toml found, skipping"));
2483
+ return;
2484
+ }
2485
+ let content = fs12.readFileSync(helixPath, "utf8");
2486
+ const entry = `{ path = "packages/${packageName}" }`;
2487
+ if (content.includes(entry)) {
2488
+ console.log(chalk7.yellow(" Already in .helix/languages.toml"));
2489
+ return;
2490
+ }
2491
+ const workspaceLineRegex = /^\s*\{\s*path\s*=\s*"packages\//;
2492
+ const lines = content.split("\n");
2493
+ let lastPackageLineIdx = -1;
2494
+ for (let i = 0; i < lines.length; i++) {
2495
+ if (workspaceLineRegex.test(lines[i])) {
2496
+ lastPackageLineIdx = i;
2497
+ }
2498
+ }
2499
+ if (lastPackageLineIdx === -1) {
2500
+ const closingBracketIdx = lines.findIndex((l) => l.trim() === "]");
2501
+ if (closingBracketIdx === -1) {
2502
+ console.log(chalk7.yellow(" Could not parse .helix/languages.toml"));
2503
+ return;
2504
+ }
2505
+ lines.splice(closingBracketIdx, 0, ` { path = "packages/${packageName}" },`);
2506
+ } else {
2507
+ const allPackageEntries = [];
2508
+ for (let i = 0; i < lines.length; i++) {
2509
+ const m = lines[i].match(/^\s*\{\s*path\s*=\s*"packages\/([^"]+)"\s*\}/);
2510
+ if (m) {
2511
+ allPackageEntries.push({ lineIdx: i, entry: m[1] });
2512
+ }
2513
+ }
2514
+ allPackageEntries.push({ lineIdx: -1, entry: packageName });
2515
+ allPackageEntries.sort((a, b) => a.entry.localeCompare(b.entry));
2516
+ const insertIdx = allPackageEntries.findIndex((e) => e.entry === packageName);
2517
+ let targetLine;
2518
+ if (insertIdx === 0) {
2519
+ const firstLine = lines.findIndex((l) => workspaceLineRegex.test(l));
2520
+ targetLine = firstLine;
2024
2521
  } else {
2025
- console.log(chalk5.yellow(" app_config_model.dart not found, skipping AppConfigModel"));
2522
+ const prevEntry = allPackageEntries[insertIdx - 1];
2523
+ targetLine = prevEntry.lineIdx + 1;
2026
2524
  }
2525
+ lines.splice(targetLine, 0, ` { path = "packages/${packageName}" },`);
2526
+ }
2527
+ fs12.writeFileSync(helixPath, lines.join("\n"));
2528
+ console.log(chalk7.green(" Updated .helix/languages.toml"));
2529
+ }
2530
+ async function createPackage(options) {
2531
+ const { monorepoRoot, packageName } = options;
2532
+ const pkgDir = path11.join(monorepoRoot, "packages", packageName);
2533
+ if (fs12.existsSync(pkgDir)) {
2534
+ throw new Error(`packages/${packageName} already exists`);
2535
+ }
2536
+ console.log(chalk7.bold(`
2537
+ Creating package: ${chalk7.cyan(packageName)}
2538
+ `));
2539
+ console.log(chalk7.cyan(" \u2192 Running flutter create..."));
2540
+ execSync2(`flutter create -t package packages/${packageName}`, {
2541
+ cwd: monorepoRoot,
2542
+ stdio: "pipe"
2543
+ });
2544
+ const autoTestFile = path11.join(pkgDir, "test", `${packageName}_test.dart`);
2545
+ if (fs12.existsSync(autoTestFile)) {
2546
+ fs12.unlinkSync(autoTestFile);
2547
+ }
2548
+ console.log(chalk7.cyan(" \u2192 Customizing package files..."));
2549
+ fs12.writeFileSync(
2550
+ path11.join(pkgDir, "pubspec.yaml"),
2551
+ buildPubspecContent(packageName)
2552
+ );
2553
+ fs12.writeFileSync(
2554
+ path11.join(pkgDir, ".gitignore"),
2555
+ buildGitignoreContent()
2556
+ );
2557
+ fs12.writeFileSync(
2558
+ path11.join(pkgDir, "analysis_options.yaml"),
2559
+ buildAnalysisOptionsContent()
2560
+ );
2561
+ fs12.writeFileSync(
2562
+ path11.join(pkgDir, "Makefile"),
2563
+ buildMakefileContent()
2564
+ );
2565
+ const libDir = path11.join(pkgDir, "lib");
2566
+ fs12.writeFileSync(
2567
+ path11.join(libDir, `${packageName}.dart`),
2568
+ buildBarrelExport(packageName)
2569
+ );
2570
+ fs12.mkdirSync(path11.join(libDir, "bloc"), { recursive: true });
2571
+ fs12.writeFileSync(
2572
+ path11.join(libDir, "bloc", "bloc.dart"),
2573
+ buildEmptyBarrel()
2574
+ );
2575
+ fs12.mkdirSync(path11.join(libDir, "pages"), { recursive: true });
2576
+ fs12.writeFileSync(
2577
+ path11.join(libDir, "pages", "pages.dart"),
2578
+ buildEmptyBarrel()
2579
+ );
2580
+ const testDir = path11.join(pkgDir, "test");
2581
+ if (!fs12.existsSync(testDir)) {
2582
+ fs12.mkdirSync(testDir, { recursive: true });
2583
+ }
2584
+ fs12.writeFileSync(
2585
+ path11.join(testDir, "main_tester.dart"),
2586
+ MAIN_TESTER_CONTENT
2587
+ );
2588
+ console.log(chalk7.cyan(" \u2192 Updating workspace configuration..."));
2589
+ updateCodeWorkspace(monorepoRoot, packageName);
2590
+ updateHelixConfig(monorepoRoot, packageName);
2591
+ console.log(chalk7.cyan(" \u2192 Creating GitHub Actions workflow..."));
2592
+ const workflowsDir = path11.join(monorepoRoot, ".github", "workflows");
2593
+ if (fs12.existsSync(workflowsDir)) {
2594
+ fs12.writeFileSync(
2595
+ path11.join(workflowsDir, `${packageName}.yaml`),
2596
+ buildGitHubWorkflow(packageName)
2597
+ );
2598
+ console.log(chalk7.green(` Created .github/workflows/${packageName}.yaml`));
2599
+ } else {
2600
+ console.log(chalk7.yellow(" No .github/workflows/ directory found, skipping CI workflow"));
2027
2601
  }
2028
- console.log(chalk5.green("\nEnvironment variable added successfully!"));
2029
- spinner("Running melos format...");
2602
+ console.log(chalk7.cyan(" \u2192 Running melos bootstrap..."));
2030
2603
  try {
2031
- execSync("melos format", { cwd: monorepoRoot, stdio: "pipe" });
2032
- console.log(chalk5.green(" melos format completed"));
2604
+ execSync2("melos bootstrap", { cwd: monorepoRoot, stdio: "pipe" });
2605
+ console.log(chalk7.green(" melos bootstrap completed"));
2033
2606
  } catch {
2034
- console.log(chalk5.yellow(" melos format failed (you may need to run it manually)"));
2607
+ console.log(chalk7.yellow(" melos bootstrap failed (you may need to run it manually)"));
2035
2608
  }
2609
+ console.log(chalk7.green(`
2610
+ Package "${packageName}" created successfully!`));
2611
+ console.log(chalk7.gray(` ${pkgDir}`));
2036
2612
  }
2037
2613
 
2038
2614
  // src/core/docs-serve.ts
2039
2615
  import { spawn as spawn2 } from "child_process";
2040
- import * as fs11 from "fs";
2041
- import * as path10 from "path";
2042
- import chalk6 from "chalk";
2616
+ import * as fs13 from "fs";
2617
+ import * as path12 from "path";
2618
+ import chalk8 from "chalk";
2043
2619
  function detectBookDir(startDir) {
2044
2620
  const root = findMonorepoRoot(startDir) ?? startDir;
2045
- const bookDir = path10.join(root, "book");
2046
- if (fs11.existsSync(bookDir) && (fs11.existsSync(path10.join(bookDir, "docusaurus.config.js")) || fs11.existsSync(path10.join(bookDir, "docusaurus.config.ts")) || fs11.existsSync(path10.join(bookDir, "docusaurus.config.mjs")))) {
2621
+ const bookDir = path12.join(root, "book");
2622
+ if (fs13.existsSync(bookDir) && (fs13.existsSync(path12.join(bookDir, "docusaurus.config")) || fs13.existsSync(path12.join(bookDir, "docusaurus.config.ts")) || fs13.existsSync(path12.join(bookDir, "docusaurus.config.mjs")))) {
2047
2623
  return bookDir;
2048
2624
  }
2049
2625
  return void 0;
2050
2626
  }
2051
2627
  function serveBook(bookDir) {
2052
- return new Promise((resolve4, reject) => {
2053
- const nodeModules = path10.join(bookDir, "node_modules");
2054
- if (!fs11.existsSync(nodeModules)) {
2055
- console.log(chalk6.cyan("Installing book dependencies..."));
2628
+ return new Promise((resolve5, reject) => {
2629
+ const nodeModules = path12.join(bookDir, "node_modules");
2630
+ if (!fs13.existsSync(nodeModules)) {
2631
+ console.log(chalk8.cyan("Installing book dependencies..."));
2056
2632
  const install = spawn2("npm", ["install"], {
2057
2633
  cwd: bookDir,
2058
2634
  stdio: "inherit"
@@ -2062,13 +2638,13 @@ function serveBook(bookDir) {
2062
2638
  reject(new Error(`npm install failed with code ${code}`));
2063
2639
  return;
2064
2640
  }
2065
- startDevServer(bookDir, resolve4);
2641
+ startDevServer(bookDir, resolve5);
2066
2642
  });
2067
2643
  install.on("error", (err) => {
2068
2644
  reject(err);
2069
2645
  });
2070
2646
  } else {
2071
- startDevServer(bookDir, resolve4);
2647
+ startDevServer(bookDir, resolve5);
2072
2648
  }
2073
2649
  });
2074
2650
  }
@@ -2086,16 +2662,16 @@ function startDevServer(bookDir, done) {
2086
2662
  }
2087
2663
 
2088
2664
  // src/core/docs-commands.ts
2089
- import * as fs12 from "fs";
2090
- import * as path11 from "path";
2091
- import chalk7 from "chalk";
2665
+ import * as fs14 from "fs";
2666
+ import * as path13 from "path";
2667
+ import chalk9 from "chalk";
2092
2668
  import YAML2 from "yaml";
2093
2669
  function parseMakefile(filePath) {
2094
- if (!fs12.existsSync(filePath)) return [];
2095
- const content = fs12.readFileSync(filePath, "utf8");
2670
+ if (!fs14.existsSync(filePath)) return [];
2671
+ const content = fs14.readFileSync(filePath, "utf8");
2096
2672
  const lines = content.split("\n");
2097
2673
  const commands = [];
2098
- const source = path11.basename(filePath);
2674
+ const source = path13.basename(filePath);
2099
2675
  let pendingComments = [];
2100
2676
  for (let i = 0; i < lines.length; i++) {
2101
2677
  const line = lines[i];
@@ -2125,13 +2701,13 @@ function parseMakefile(filePath) {
2125
2701
  return commands;
2126
2702
  }
2127
2703
  function parseMelosScripts(filePath) {
2128
- if (!fs12.existsSync(filePath)) return [];
2129
- const content = fs12.readFileSync(filePath, "utf8");
2704
+ if (!fs14.existsSync(filePath)) return [];
2705
+ const content = fs14.readFileSync(filePath, "utf8");
2130
2706
  const parsed = YAML2.parse(content);
2131
2707
  const scripts = parsed?.scripts;
2132
2708
  if (!scripts || typeof scripts !== "object") return [];
2133
2709
  const commands = [];
2134
- const source = path11.basename(filePath);
2710
+ const source = path13.basename(filePath);
2135
2711
  for (const [name, value] of Object.entries(scripts)) {
2136
2712
  let description = "";
2137
2713
  let command = "";
@@ -2153,17 +2729,17 @@ function parseMelosScripts(filePath) {
2153
2729
  function discoverCommands(startDir) {
2154
2730
  const root = findMonorepoRoot(startDir) ?? startDir;
2155
2731
  const commands = [];
2156
- const rootMakefile = path11.join(root, "Makefile");
2732
+ const rootMakefile = path13.join(root, "Makefile");
2157
2733
  commands.push(...parseMakefile(rootMakefile));
2158
- const melosFile = path11.join(root, "melos.yaml");
2734
+ const melosFile = path13.join(root, "melos.yaml");
2159
2735
  commands.push(...parseMelosScripts(melosFile));
2160
- const bookMakefile = path11.join(root, "book", "Makefile");
2736
+ const bookMakefile = path13.join(root, "book", "Makefile");
2161
2737
  commands.push(...parseMakefile(bookMakefile));
2162
2738
  return commands;
2163
2739
  }
2164
2740
  function displayCommands(commands) {
2165
2741
  if (commands.length === 0) {
2166
- console.log(chalk7.yellow("No commands found."));
2742
+ console.log(chalk9.yellow("No commands found."));
2167
2743
  return;
2168
2744
  }
2169
2745
  const groups = /* @__PURE__ */ new Map();
@@ -2173,13 +2749,13 @@ function displayCommands(commands) {
2173
2749
  groups.get(key).push(cmd);
2174
2750
  }
2175
2751
  for (const [group, entries] of groups) {
2176
- console.log(chalk7.bold(chalk7.cyan(`
2752
+ console.log(chalk9.bold(chalk9.cyan(`
2177
2753
  ${group}`)));
2178
- console.log(chalk7.cyan("\u2500".repeat(group.length)));
2754
+ console.log(chalk9.cyan("\u2500".repeat(group.length)));
2179
2755
  const maxNameLen = Math.max(...entries.map((e) => e.name.length));
2180
2756
  for (const entry of entries) {
2181
- const name = chalk7.white(entry.name.padEnd(maxNameLen + 2));
2182
- const desc = entry.description ? chalk7.gray(entry.description) : chalk7.dim("(no description)");
2757
+ const name = chalk9.white(entry.name.padEnd(maxNameLen + 2));
2758
+ const desc = entry.description ? chalk9.gray(entry.description) : chalk9.dim("(no description)");
2183
2759
  console.log(` ${name} ${desc}`);
2184
2760
  }
2185
2761
  }
@@ -2187,9 +2763,9 @@ ${group}`)));
2187
2763
  }
2188
2764
 
2189
2765
  // src/core/docs-architecture.ts
2190
- import * as fs13 from "fs";
2191
- import * as path12 from "path";
2192
- import chalk8 from "chalk";
2766
+ import * as fs15 from "fs";
2767
+ import * as path14 from "path";
2768
+ import chalk10 from "chalk";
2193
2769
  import YAML3 from "yaml";
2194
2770
  var KEY_DEPS = [
2195
2771
  "freezed",
@@ -2207,18 +2783,18 @@ var KEY_DEPS = [
2207
2783
  function discoverArchitecture(startDir) {
2208
2784
  const root = findMonorepoRoot(startDir);
2209
2785
  if (!root) return null;
2210
- const melosPath = path12.join(root, "melos.yaml");
2211
- if (!fs13.existsSync(melosPath)) return null;
2212
- const melosContent = fs13.readFileSync(melosPath, "utf8");
2786
+ const melosPath = path14.join(root, "melos.yaml");
2787
+ if (!fs15.existsSync(melosPath)) return null;
2788
+ const melosContent = fs15.readFileSync(melosPath, "utf8");
2213
2789
  const melos = YAML3.parse(melosContent);
2214
- const projectName = melos?.name ?? path12.basename(root);
2790
+ const projectName = melos?.name ?? path14.basename(root);
2215
2791
  const apps = [];
2216
- const appsDir = path12.join(root, "apps");
2217
- if (fs13.existsSync(appsDir)) {
2218
- for (const entry of fs13.readdirSync(appsDir, { withFileTypes: true })) {
2792
+ const appsDir = path14.join(root, "apps");
2793
+ if (fs15.existsSync(appsDir)) {
2794
+ for (const entry of fs15.readdirSync(appsDir, { withFileTypes: true })) {
2219
2795
  if (!entry.isDirectory()) continue;
2220
- const candidate = path12.join(appsDir, entry.name);
2221
- if (fs13.existsSync(path12.join(candidate, "pubspec.yaml"))) {
2796
+ const candidate = path14.join(appsDir, entry.name);
2797
+ if (fs15.existsSync(path14.join(candidate, "pubspec.yaml"))) {
2222
2798
  apps.push({ name: entry.name, dir: candidate });
2223
2799
  }
2224
2800
  }
@@ -2226,14 +2802,14 @@ function discoverArchitecture(startDir) {
2226
2802
  const packages = [];
2227
2803
  const packageBases = ["packages", "packages/features"];
2228
2804
  for (const base of packageBases) {
2229
- const baseDir = path12.join(root, base);
2230
- if (!fs13.existsSync(baseDir)) continue;
2231
- for (const entry of fs13.readdirSync(baseDir, { withFileTypes: true })) {
2805
+ const baseDir = path14.join(root, base);
2806
+ if (!fs15.existsSync(baseDir)) continue;
2807
+ for (const entry of fs15.readdirSync(baseDir, { withFileTypes: true })) {
2232
2808
  if (!entry.isDirectory()) continue;
2233
- const candidate = path12.join(baseDir, entry.name);
2234
- const pubspecPath = path12.join(candidate, "pubspec.yaml");
2235
- if (!fs13.existsSync(pubspecPath)) continue;
2236
- const content = fs13.readFileSync(pubspecPath, "utf8");
2809
+ const candidate = path14.join(baseDir, entry.name);
2810
+ const pubspecPath = path14.join(candidate, "pubspec.yaml");
2811
+ if (!fs15.existsSync(pubspecPath)) continue;
2812
+ const content = fs15.readFileSync(pubspecPath, "utf8");
2237
2813
  const pubspec = YAML3.parse(content);
2238
2814
  const deps = {
2239
2815
  ...pubspec?.dependencies,
@@ -2268,30 +2844,30 @@ function displayArchitecture(info) {
2268
2844
  const L = "\u2514\u2500\u2500 ";
2269
2845
  const I = "\u2502 ";
2270
2846
  const S = " ";
2271
- console.log(chalk8.bold(chalk8.cyan(info.projectName)) + chalk8.gray(` (${info.root})`));
2847
+ console.log(chalk10.bold(chalk10.cyan(info.projectName)) + chalk10.gray(` (${info.root})`));
2272
2848
  console.log(`${I}`);
2273
2849
  if (info.apps.length > 0) {
2274
- console.log(chalk8.white(`${T}apps/`));
2850
+ console.log(chalk10.white(`${T}apps/`));
2275
2851
  for (let i = 0; i < info.apps.length; i++) {
2276
2852
  const app = info.apps[i];
2277
2853
  const prefix = i === info.apps.length - 1 ? `${I}${S}${L}` : `${I}${S}${T}`;
2278
- console.log(`${prefix}${chalk8.green(app.name)}`);
2854
+ console.log(`${prefix}${chalk10.green(app.name)}`);
2279
2855
  }
2280
2856
  }
2281
2857
  if (info.packages.length > 0) {
2282
2858
  const rootPkgs = info.packages.filter(
2283
- (p) => !p.dir.includes(`${path12.sep}features${path12.sep}`)
2859
+ (p) => !p.dir.includes(`${path14.sep}features${path14.sep}`)
2284
2860
  );
2285
2861
  const featurePkgs = info.packages.filter(
2286
- (p) => p.dir.includes(`${path12.sep}features${path12.sep}`)
2862
+ (p) => p.dir.includes(`${path14.sep}features${path14.sep}`)
2287
2863
  );
2288
- console.log(chalk8.white(`${T}packages/`));
2864
+ console.log(chalk10.white(`${T}packages/`));
2289
2865
  for (let i = 0; i < rootPkgs.length; i++) {
2290
2866
  const pkg2 = rootPkgs[i];
2291
2867
  const isLast = i === rootPkgs.length - 1 && featurePkgs.length === 0;
2292
2868
  const prefix = isLast ? `${I}${S}${L}` : `${I}${S}${T}`;
2293
- const deps = pkg2.keyDeps.length > 0 ? chalk8.dim(` [${pkg2.keyDeps.join(", ")}]`) : "";
2294
- console.log(`${prefix}${chalk8.yellow(pkg2.name)}${deps}`);
2869
+ const deps = pkg2.keyDeps.length > 0 ? chalk10.dim(` [${pkg2.keyDeps.join(", ")}]`) : "";
2870
+ console.log(`${prefix}${chalk10.yellow(pkg2.name)}${deps}`);
2295
2871
  }
2296
2872
  if (featurePkgs.length > 0) {
2297
2873
  console.log(`${I}${S}${T}features/`);
@@ -2299,33 +2875,33 @@ function displayArchitecture(info) {
2299
2875
  const pkg2 = featurePkgs[i];
2300
2876
  const isLast = i === featurePkgs.length - 1;
2301
2877
  const prefix = isLast ? `${I}${S}${S}${L}` : `${I}${S}${S}${T}`;
2302
- const deps = pkg2.keyDeps.length > 0 ? chalk8.dim(` [${pkg2.keyDeps.join(", ")}]`) : "";
2303
- console.log(`${prefix}${chalk8.yellow(pkg2.name)}${deps}`);
2878
+ const deps = pkg2.keyDeps.length > 0 ? chalk10.dim(` [${pkg2.keyDeps.join(", ")}]`) : "";
2879
+ console.log(`${prefix}${chalk10.yellow(pkg2.name)}${deps}`);
2304
2880
  }
2305
2881
  }
2306
2882
  }
2307
2883
  if (info.hasDesignSystem) {
2308
- const tiers = info.designSystemTiers.length > 0 ? chalk8.dim(` (${info.designSystemTiers.join(", ")})`) : "";
2309
- console.log(`${T}${chalk8.magenta("design_system")}${tiers}`);
2884
+ const tiers = info.designSystemTiers.length > 0 ? chalk10.dim(` (${info.designSystemTiers.join(", ")})`) : "";
2885
+ console.log(`${T}${chalk10.magenta("design_system")}${tiers}`);
2310
2886
  }
2311
- const bookDir = path12.join(info.root, "book");
2312
- if (fs13.existsSync(bookDir)) {
2313
- console.log(`${T}${chalk8.blue("book/")}` + chalk8.dim(" (Docusaurus)"));
2887
+ const bookDir = path14.join(info.root, "book");
2888
+ if (fs15.existsSync(bookDir)) {
2889
+ console.log(`${T}${chalk10.blue("book/")}` + chalk10.dim(" (Docusaurus)"));
2314
2890
  }
2315
- if (fs13.existsSync(path12.join(info.root, "melos.yaml"))) {
2316
- console.log(`${L}${chalk8.gray("melos.yaml")}`);
2891
+ if (fs15.existsSync(path14.join(info.root, "melos.yaml"))) {
2892
+ console.log(`${L}${chalk10.gray("melos.yaml")}`);
2317
2893
  }
2318
2894
  console.log();
2319
2895
  }
2320
2896
 
2321
2897
  // src/interactive.ts
2322
- var SNAKE_CASE_REGEX4 = /^[a-z][a-z0-9_]*$/;
2898
+ var SNAKE_CASE_REGEX5 = /^[a-z][a-z0-9_]*$/;
2323
2899
  async function resolveProject() {
2324
2900
  const s = clack.spinner();
2325
2901
  s.start("Analyzing current directory...");
2326
2902
  const cwdProject = analyzeProject(process.cwd());
2327
2903
  if (cwdProject && (cwdProject.hasFreezed || cwdProject.hasBloc)) {
2328
- s.stop(`Found ${chalk9.green(cwdProject.projectName)}`);
2904
+ s.stop(`Found ${chalk11.green(cwdProject.projectName)}`);
2329
2905
  return cwdProject;
2330
2906
  }
2331
2907
  s.message("Looking for Melos monorepo...");
@@ -2338,8 +2914,8 @@ async function resolveProject() {
2338
2914
  }
2339
2915
  }
2340
2916
  s.message("Scanning for Flutter projects...");
2341
- const homeDev = path13.join(os.homedir(), "Development");
2342
- if (fs14.existsSync(homeDev)) {
2917
+ const homeDev = path15.join(os.homedir(), "Development");
2918
+ if (fs16.existsSync(homeDev)) {
2343
2919
  const projects = discoverProjects(homeDev, 2);
2344
2920
  if (projects.length > 0) {
2345
2921
  s.stop(`Found ${projects.length} Flutter project(s)`);
@@ -2347,12 +2923,12 @@ async function resolveProject() {
2347
2923
  }
2348
2924
  }
2349
2925
  s.stop("No Flutter projects found");
2350
- clack.outro(chalk9.red("Could not find any Flutter project with freezed or flutter_bloc."));
2926
+ clack.outro(chalk11.red("Could not find any Flutter project with freezed or flutter_bloc."));
2351
2927
  return null;
2352
2928
  }
2353
2929
  async function selectPackage(projects) {
2354
2930
  if (projects.length === 1) {
2355
- clack.log.info(`Using ${chalk9.green(projects[0].projectName)}`);
2931
+ clack.log.info(`Using ${chalk11.green(projects[0].projectName)}`);
2356
2932
  return projects[0];
2357
2933
  }
2358
2934
  const selected = await clack.select({
@@ -2360,7 +2936,7 @@ async function selectPackage(projects) {
2360
2936
  options: projects.map((p) => ({
2361
2937
  value: p,
2362
2938
  label: p.projectName,
2363
- hint: path13.relative(os.homedir(), p.projectRoot)
2939
+ hint: path15.relative(os.homedir(), p.projectRoot)
2364
2940
  }))
2365
2941
  });
2366
2942
  if (clack.isCancel(selected)) {
@@ -2375,7 +2951,7 @@ async function blocFlow(project) {
2375
2951
  placeholder: "e.g. user_login",
2376
2952
  validate: (value) => {
2377
2953
  if (!value.trim()) return "Name is required";
2378
- if (!SNAKE_CASE_REGEX4.test(value))
2954
+ if (!SNAKE_CASE_REGEX5.test(value))
2379
2955
  return "Must be snake_case (lowercase, digits, underscores)";
2380
2956
  }
2381
2957
  });
@@ -2408,13 +2984,13 @@ async function blocFlow(project) {
2408
2984
  clack.cancel("Cancelled");
2409
2985
  return;
2410
2986
  }
2411
- targetDir = path13.resolve(customPath);
2987
+ targetDir = path15.resolve(customPath);
2412
2988
  } else {
2413
- targetDir = path13.join(project.projectRoot, "lib", "features", feature);
2989
+ targetDir = path15.join(project.projectRoot, "lib", "features", feature);
2414
2990
  }
2415
- } else if (fs14.existsSync(path13.join(project.projectRoot, "lib", "bloc"))) {
2416
- targetDir = path13.join(project.projectRoot, "lib", "bloc");
2417
- clack.log.info(`Target: ${chalk9.cyan("lib/bloc/")}`);
2991
+ } else if (fs16.existsSync(path15.join(project.projectRoot, "lib", "bloc"))) {
2992
+ targetDir = path15.join(project.projectRoot, "lib", "bloc");
2993
+ clack.log.info(`Target: ${chalk11.cyan("lib/bloc/")}`);
2418
2994
  } else {
2419
2995
  clack.note(
2420
2996
  "No lib/features/ directory found. Provide a target path manually.",
@@ -2431,7 +3007,7 @@ async function blocFlow(project) {
2431
3007
  clack.cancel("Cancelled");
2432
3008
  return;
2433
3009
  }
2434
- targetDir = path13.resolve(customPath);
3010
+ targetDir = path15.resolve(customPath);
2435
3011
  }
2436
3012
  const defaultRun = project.hasBuildRunner;
2437
3013
  const runBuildRunner2 = await clack.confirm({
@@ -2450,10 +3026,10 @@ async function blocFlow(project) {
2450
3026
  buildRunner: runBuildRunner2
2451
3027
  });
2452
3028
  genSpinner.stop("BLoC generated");
2453
- clack.outro(chalk9.green("Done!"));
3029
+ clack.outro(chalk11.green("Done!"));
2454
3030
  } catch (error) {
2455
3031
  genSpinner.stop("Failed");
2456
- clack.outro(chalk9.red(`Error: ${error}`));
3032
+ clack.outro(chalk11.red(`Error: ${error}`));
2457
3033
  }
2458
3034
  }
2459
3035
  async function widgetFlow() {
@@ -2461,14 +3037,14 @@ async function widgetFlow() {
2461
3037
  const ds = detectDesignSystem(projectRoot);
2462
3038
  if (!ds) {
2463
3039
  clack.outro(
2464
- chalk9.red(
3040
+ chalk11.red(
2465
3041
  "No design system detected. Run this command from a project with wl_design_system/ directory."
2466
3042
  )
2467
3043
  );
2468
3044
  return;
2469
3045
  }
2470
3046
  clack.log.info(
2471
- `Design system: ${chalk9.cyan(path13.relative(projectRoot, ds.componentsDir))}`
3047
+ `Design system: ${chalk11.cyan(path15.relative(projectRoot, ds.componentsDir))}`
2472
3048
  );
2473
3049
  const name = await clack.text({
2474
3050
  message: "Widget name (snake_case, without wl_ prefix)",
@@ -2476,7 +3052,7 @@ async function widgetFlow() {
2476
3052
  validate: (value) => {
2477
3053
  if (!value.trim()) return "Name is required";
2478
3054
  const clean = value.startsWith("wl_") ? value.slice(3) : value;
2479
- if (!SNAKE_CASE_REGEX4.test(clean))
3055
+ if (!SNAKE_CASE_REGEX5.test(clean))
2480
3056
  return "Must be snake_case (lowercase, digits, underscores)";
2481
3057
  }
2482
3058
  });
@@ -2533,17 +3109,17 @@ async function widgetFlow() {
2533
3109
  genSpinner.stop(`Use-case skipped: ${e}`);
2534
3110
  }
2535
3111
  }
2536
- clack.outro(chalk9.green("Done!"));
3112
+ clack.outro(chalk11.green("Done!"));
2537
3113
  } catch (error) {
2538
3114
  genSpinner.stop("Failed");
2539
- clack.outro(chalk9.red(`Error: ${error}`));
3115
+ clack.outro(chalk11.red(`Error: ${error}`));
2540
3116
  }
2541
3117
  }
2542
3118
  async function useCaseFlow() {
2543
3119
  const ds = detectDesignSystem(process.cwd());
2544
3120
  if (!ds) {
2545
3121
  clack.outro(
2546
- chalk9.red(
3122
+ chalk11.red(
2547
3123
  "No design system detected. Ensure wl_design_system/ directory exists."
2548
3124
  )
2549
3125
  );
@@ -2551,7 +3127,7 @@ async function useCaseFlow() {
2551
3127
  }
2552
3128
  if (!ds.widgetbookDir) {
2553
3129
  clack.outro(
2554
- chalk9.red(
3130
+ chalk11.red(
2555
3131
  "No widgetbook package detected. Ensure apps/widgetbook/ exists."
2556
3132
  )
2557
3133
  );
@@ -2563,7 +3139,7 @@ async function useCaseFlow() {
2563
3139
  validate: (value) => {
2564
3140
  if (!value.trim()) return "Name is required";
2565
3141
  const clean = value.startsWith("wl_") ? value.slice(3) : value;
2566
- if (!SNAKE_CASE_REGEX4.test(clean))
3142
+ if (!SNAKE_CASE_REGEX5.test(clean))
2567
3143
  return "Must be snake_case (lowercase, digits, underscores)";
2568
3144
  }
2569
3145
  });
@@ -2600,18 +3176,123 @@ async function useCaseFlow() {
2600
3176
  buildRunner: runBuildRunner2
2601
3177
  });
2602
3178
  genSpinner.stop("Use-case generated");
2603
- clack.outro(chalk9.green("Done!"));
3179
+ clack.outro(chalk11.green("Done!"));
2604
3180
  } catch (error) {
2605
3181
  genSpinner.stop("Failed");
2606
- clack.outro(chalk9.red(`Error: ${error}`));
3182
+ clack.outro(chalk11.red(`Error: ${error}`));
2607
3183
  }
2608
3184
  }
3185
+ function discoverMonorepoPackages(monorepoRoot) {
3186
+ const results = [];
3187
+ const packageBases = ["packages", "packages/features"];
3188
+ for (const base of packageBases) {
3189
+ const baseDir = path15.join(monorepoRoot, base);
3190
+ if (!fs16.existsSync(baseDir)) continue;
3191
+ const entries = fs16.readdirSync(baseDir, { withFileTypes: true });
3192
+ for (const entry of entries) {
3193
+ if (!entry.isDirectory()) continue;
3194
+ const pkgDir = path15.join(baseDir, entry.name);
3195
+ if (fs16.existsSync(path15.join(pkgDir, "pubspec.yaml"))) {
3196
+ results.push({ name: entry.name, pagesDir: path15.join(pkgDir, "lib", "pages") });
3197
+ }
3198
+ }
3199
+ }
3200
+ return results.sort((a, b) => a.name.localeCompare(b.name));
3201
+ }
3202
+ async function pageFlow(initialName, initialPath) {
3203
+ const name = initialName ?? await clack.text({
3204
+ message: "Page name (snake_case)",
3205
+ placeholder: "e.g. profile, order_detail",
3206
+ validate: (value) => {
3207
+ if (!value.trim()) return "Name is required";
3208
+ if (!SNAKE_CASE_REGEX5.test(value))
3209
+ return "Must be snake_case (lowercase, digits, underscores)";
3210
+ }
3211
+ });
3212
+ if (clack.isCancel(name)) {
3213
+ clack.cancel("Cancelled");
3214
+ return;
3215
+ }
3216
+ let pagesPath = initialPath;
3217
+ if (!pagesPath) {
3218
+ const monorepoRoot = findMonorepoRoot(process.cwd());
3219
+ if (monorepoRoot) {
3220
+ const packages = discoverMonorepoPackages(monorepoRoot);
3221
+ if (packages.length > 0) {
3222
+ const selected = await clack.select({
3223
+ message: "Select package where the page will be created",
3224
+ options: [
3225
+ ...packages.map((p) => ({
3226
+ value: p.pagesDir,
3227
+ label: p.name,
3228
+ hint: path15.relative(monorepoRoot, p.pagesDir)
3229
+ })),
3230
+ { value: "__custom__", label: "Custom path..." }
3231
+ ]
3232
+ });
3233
+ if (clack.isCancel(selected)) {
3234
+ clack.cancel("Cancelled");
3235
+ return;
3236
+ }
3237
+ if (selected === "__custom__") {
3238
+ const customPath = await clack.text({
3239
+ message: "Absolute path to pages directory",
3240
+ placeholder: "/path/to/packages/home/lib/pages",
3241
+ validate: (v) => {
3242
+ if (!v.trim()) return "Path is required";
3243
+ const resolved = path15.resolve(v.trim());
3244
+ if (!fs16.existsSync(resolved)) return "Path does not exist";
3245
+ }
3246
+ });
3247
+ if (clack.isCancel(customPath)) {
3248
+ clack.cancel("Cancelled");
3249
+ return;
3250
+ }
3251
+ pagesPath = path15.resolve(customPath);
3252
+ } else {
3253
+ pagesPath = selected;
3254
+ }
3255
+ } else {
3256
+ pagesPath = await askManualPagesPath();
3257
+ }
3258
+ } else {
3259
+ pagesPath = await askManualPagesPath();
3260
+ }
3261
+ }
3262
+ if (!pagesPath) return;
3263
+ const genSpinner = clack.spinner();
3264
+ genSpinner.start("Creating page...");
3265
+ try {
3266
+ await createPage(name, { pagesPath });
3267
+ genSpinner.stop("Page created");
3268
+ clack.outro(chalk11.green("Done!"));
3269
+ } catch (error) {
3270
+ genSpinner.stop("Failed");
3271
+ clack.outro(chalk11.red(`Error: ${error}`));
3272
+ }
3273
+ }
3274
+ async function askManualPagesPath() {
3275
+ const customPath = await clack.text({
3276
+ message: "Absolute path to pages directory",
3277
+ placeholder: "/path/to/project/lib/pages",
3278
+ validate: (v) => {
3279
+ if (!v.trim()) return "Path is required";
3280
+ const resolved = path15.resolve(v.trim());
3281
+ if (!fs16.existsSync(resolved)) return "Path does not exist";
3282
+ }
3283
+ });
3284
+ if (clack.isCancel(customPath)) {
3285
+ clack.cancel("Cancelled");
3286
+ return void 0;
3287
+ }
3288
+ return path15.resolve(customPath);
3289
+ }
2609
3290
  function findBffFiles(dir) {
2610
3291
  const results = [];
2611
- if (!fs14.existsSync(dir)) return results;
2612
- const entries = fs14.readdirSync(dir, { withFileTypes: true });
3292
+ if (!fs16.existsSync(dir)) return results;
3293
+ const entries = fs16.readdirSync(dir, { withFileTypes: true });
2613
3294
  for (const entry of entries) {
2614
- const fullPath = path13.join(dir, entry.name);
3295
+ const fullPath = path15.join(dir, entry.name);
2615
3296
  if (entry.isDirectory()) {
2616
3297
  results.push(...findBffFiles(fullPath));
2617
3298
  } else if (entry.isFile() && entry.name.endsWith(".dart") && !entry.name.includes(".g.")) {
@@ -2623,8 +3304,8 @@ function findBffFiles(dir) {
2623
3304
  function inferBffFile(bffFiles, endpointPath) {
2624
3305
  const firstSegment = endpointPath.replace(/^\//, "").split("/")[0].toLowerCase();
2625
3306
  if (!firstSegment) return null;
2626
- const withDomains = bffFiles.filter((f) => /^bff_.+_api\.dart$/.test(path13.basename(f))).map((f) => {
2627
- const base = path13.basename(f, ".dart");
3307
+ const withDomains = bffFiles.filter((f) => /^bff_.+_api\.dart$/.test(path15.basename(f))).map((f) => {
3308
+ const base = path15.basename(f, ".dart");
2628
3309
  const domain = base.replace(/^bff_/, "").replace(/_api$/, "");
2629
3310
  return { file: f, domain };
2630
3311
  });
@@ -2651,19 +3332,19 @@ async function resolveEndpointProject() {
2651
3332
  s.message(`Monorepo found at ${monorepoRoot}`);
2652
3333
  const packageBases = ["packages", "packages/features"];
2653
3334
  for (const base of packageBases) {
2654
- const baseDir = path13.join(monorepoRoot, base);
2655
- if (!fs14.existsSync(baseDir)) continue;
2656
- const entries = fs14.readdirSync(baseDir, { withFileTypes: true });
3335
+ const baseDir = path15.join(monorepoRoot, base);
3336
+ if (!fs16.existsSync(baseDir)) continue;
3337
+ const entries = fs16.readdirSync(baseDir, { withFileTypes: true });
2657
3338
  for (const entry of entries) {
2658
3339
  if (!entry.isDirectory()) continue;
2659
- const candidate = path13.join(baseDir, entry.name);
2660
- if (!fs14.existsSync(path13.join(candidate, "pubspec.yaml"))) continue;
2661
- const bffPath = path13.join(candidate, "lib", "data", "api", "bff");
2662
- s.message(`Checking ${candidate} \u2192 bff exists: ${fs14.existsSync(bffPath)}`);
2663
- if (fs14.existsSync(bffPath)) {
3340
+ const candidate = path15.join(baseDir, entry.name);
3341
+ if (!fs16.existsSync(path15.join(candidate, "pubspec.yaml"))) continue;
3342
+ const bffPath = path15.join(candidate, "lib", "data", "api", "bff");
3343
+ s.message(`Checking ${candidate} \u2192 bff exists: ${fs16.existsSync(bffPath)}`);
3344
+ if (fs16.existsSync(bffPath)) {
2664
3345
  const project2 = analyzeProject(candidate);
2665
3346
  if (project2) {
2666
- s.stop(`Using ${chalk9.green(project2.projectName)}`);
3347
+ s.stop(`Using ${chalk11.green(project2.projectName)}`);
2667
3348
  return project2;
2668
3349
  }
2669
3350
  }
@@ -2673,8 +3354,8 @@ async function resolveEndpointProject() {
2673
3354
  s.message("No monorepo root found");
2674
3355
  }
2675
3356
  const cwdProject = analyzeProject(process.cwd());
2676
- if (cwdProject && fs14.existsSync(path13.join(cwdProject.projectRoot, "lib", "data", "api", "bff"))) {
2677
- s.stop(`Using ${chalk9.green(cwdProject.projectName)}`);
3357
+ if (cwdProject && fs16.existsSync(path15.join(cwdProject.projectRoot, "lib", "data", "api", "bff"))) {
3358
+ s.stop(`Using ${chalk11.green(cwdProject.projectName)}`);
2678
3359
  return cwdProject;
2679
3360
  }
2680
3361
  s.stop("No BFF package found");
@@ -2683,33 +3364,33 @@ async function resolveEndpointProject() {
2683
3364
  placeholder: "e.g. /path/to/my-package or ./packages/core",
2684
3365
  validate: (v) => {
2685
3366
  if (!v.trim()) return "Path is required";
2686
- const resolved2 = path13.resolve(v.trim());
2687
- if (!fs14.existsSync(resolved2)) return "Path does not exist";
2688
- if (!fs14.existsSync(path13.join(resolved2, "pubspec.yaml"))) return "No pubspec.yaml found at this path";
2689
- if (!fs14.existsSync(path13.join(resolved2, "lib", "data", "api", "bff"))) return "No lib/data/api/bff/ found at this path";
3367
+ const resolved2 = path15.resolve(v.trim());
3368
+ if (!fs16.existsSync(resolved2)) return "Path does not exist";
3369
+ if (!fs16.existsSync(path15.join(resolved2, "pubspec.yaml"))) return "No pubspec.yaml found at this path";
3370
+ if (!fs16.existsSync(path15.join(resolved2, "lib", "data", "api", "bff"))) return "No lib/data/api/bff/ found at this path";
2690
3371
  }
2691
3372
  });
2692
3373
  if (clack.isCancel(manualPath)) {
2693
3374
  clack.cancel("Cancelled");
2694
3375
  return null;
2695
3376
  }
2696
- const resolved = path13.resolve(manualPath);
3377
+ const resolved = path15.resolve(manualPath);
2697
3378
  const project = analyzeProject(resolved);
2698
3379
  if (!project) {
2699
- clack.outro(chalk9.red(`Could not analyze project at ${resolved}`));
3380
+ clack.outro(chalk11.red(`Could not analyze project at ${resolved}`));
2700
3381
  return null;
2701
3382
  }
2702
- clack.log.info(`Using ${chalk9.green(project.projectName)}`);
3383
+ clack.log.info(`Using ${chalk11.green(project.projectName)}`);
2703
3384
  return project;
2704
3385
  }
2705
3386
  async function endpointFlow() {
2706
3387
  const project = await resolveEndpointProject();
2707
3388
  if (!project) return;
2708
- const lib = path13.join(project.projectRoot, "lib");
2709
- const bffDir = path13.join(lib, "data", "api", "bff");
3389
+ const lib = path15.join(project.projectRoot, "lib");
3390
+ const bffDir = path15.join(lib, "data", "api", "bff");
2710
3391
  const bffFiles = findBffFiles(bffDir);
2711
3392
  if (bffFiles.length === 0) {
2712
- clack.outro(chalk9.red("No BFF API files found. Ensure lib/data/api/bff/ exists with .dart files."));
3393
+ clack.outro(chalk11.red("No BFF API files found. Ensure lib/data/api/bff/ exists with .dart files."));
2713
3394
  return;
2714
3395
  }
2715
3396
  const httpMethod = await clack.select({
@@ -2739,13 +3420,13 @@ async function endpointFlow() {
2739
3420
  }
2740
3421
  let bffApiFile = inferBffFile(bffFiles, endpointPath);
2741
3422
  if (bffApiFile) {
2742
- clack.log.info(`Auto-detected BFF file: ${chalk9.cyan(path13.basename(bffApiFile))}`);
3423
+ clack.log.info(`Auto-detected BFF file: ${chalk11.cyan(path15.basename(bffApiFile))}`);
2743
3424
  } else {
2744
3425
  const selected = await clack.select({
2745
3426
  message: "Could not auto-detect BFF file. Select one:",
2746
3427
  options: bffFiles.map((f) => ({
2747
3428
  value: f,
2748
- label: path13.relative(bffDir, f)
3429
+ label: path15.relative(bffDir, f)
2749
3430
  }))
2750
3431
  });
2751
3432
  if (clack.isCancel(selected)) {
@@ -2763,7 +3444,7 @@ async function endpointFlow() {
2763
3444
  initialValue: inferredName,
2764
3445
  validate: (v) => {
2765
3446
  if (!v.trim()) return "Name is required";
2766
- if (!SNAKE_CASE_REGEX4.test(v)) return "Must be snake_case";
3447
+ if (!SNAKE_CASE_REGEX5.test(v)) return "Must be snake_case";
2767
3448
  }
2768
3449
  });
2769
3450
  if (clack.isCancel(useCaseName)) {
@@ -2809,14 +3490,49 @@ async function endpointFlow() {
2809
3490
  diLazySingleton
2810
3491
  });
2811
3492
  genSpinner.stop("Endpoint generated");
2812
- clack.outro(chalk9.green("Done!"));
3493
+ clack.outro(chalk11.green("Done!"));
3494
+ } catch (error) {
3495
+ genSpinner.stop("Failed");
3496
+ clack.outro(chalk11.red(`Error: ${error}`));
3497
+ }
3498
+ }
3499
+ async function packageFlow() {
3500
+ const monorepoRoot = findMonorepoRoot(process.cwd());
3501
+ if (!monorepoRoot) {
3502
+ clack.outro(chalk11.red("Not inside a monorepo. Run from within a Melos monorepo."));
3503
+ return;
3504
+ }
3505
+ clack.log.info(`Monorepo: ${chalk11.cyan(path15.relative(os.homedir(), monorepoRoot))}`);
3506
+ const name = await clack.text({
3507
+ message: "Package name (snake_case)",
3508
+ placeholder: "e.g. rewards, promotions, notifications",
3509
+ validate: (value) => {
3510
+ if (!value || !value.trim()) return "Name is required";
3511
+ if (!SNAKE_CASE_REGEX5.test(value)) return "Must be snake_case (lowercase, digits, underscores)";
3512
+ const pkgDir = path15.join(monorepoRoot, "packages", value);
3513
+ if (fs16.existsSync(pkgDir)) return `packages/${value} already exists`;
3514
+ }
3515
+ });
3516
+ if (clack.isCancel(name)) {
3517
+ clack.cancel("Cancelled");
3518
+ return;
3519
+ }
3520
+ const genSpinner = clack.spinner();
3521
+ genSpinner.start("Creating package...");
3522
+ try {
3523
+ await createPackage({
3524
+ monorepoRoot,
3525
+ packageName: name
3526
+ });
3527
+ genSpinner.stop("Package created");
3528
+ clack.outro(chalk11.green("Done!"));
2813
3529
  } catch (error) {
2814
3530
  genSpinner.stop("Failed");
2815
- clack.outro(chalk9.red(`Error: ${error}`));
3531
+ clack.outro(chalk11.red(`Error: ${error}`));
2816
3532
  }
2817
3533
  }
2818
3534
  async function docsInteractiveMode() {
2819
- clack.intro(chalk9.bgCyan(chalk9.black(" wlmaker docs ")));
3535
+ clack.intro(chalk11.bgCyan(chalk11.black(" wlmaker docs ")));
2820
3536
  const action = await clack.select({
2821
3537
  message: "What do you want to do?",
2822
3538
  options: [
@@ -2860,46 +3576,46 @@ async function docsInteractiveMode() {
2860
3576
  }
2861
3577
  const remoteUrl = "https://dc-wl-docs.web.app/development_workflow/";
2862
3578
  if (!remoteUrl) {
2863
- clack.outro(chalk9.red("Remote docs URL not configured. Set WL_DOCS_URL in your environment."));
3579
+ clack.outro(chalk11.red("Remote docs URL not configured. Set WL_DOCS_URL in your environment."));
2864
3580
  return;
2865
3581
  }
2866
- clack.log.info(`Opening remote docs: ${chalk9.cyan(remoteUrl)}`);
2867
- execSync2(`open "${remoteUrl}"`, { stdio: "ignore" });
2868
- clack.outro(chalk9.green("Opened remote docs in browser"));
3582
+ clack.log.info(`Opening remote docs: ${chalk11.cyan(remoteUrl)}`);
3583
+ execSync3(`open "${remoteUrl}"`, { stdio: "ignore" });
3584
+ clack.outro(chalk11.green("Opened remote docs in browser"));
2869
3585
  return;
2870
3586
  }
2871
3587
  const bookDir = detectBookDir(process.cwd());
2872
3588
  if (!bookDir) {
2873
3589
  clack.outro(
2874
- chalk9.red("No Docusaurus book/ directory found. Run from a monorepo root.")
3590
+ chalk11.red("No Docusaurus book/ directory found. Run from a monorepo root.")
2875
3591
  );
2876
3592
  return;
2877
3593
  }
2878
- clack.log.info(`Serving docs from ${chalk9.cyan(bookDir)}`);
3594
+ clack.log.info(`Serving docs from ${chalk11.cyan(bookDir)}`);
2879
3595
  await serveBook(bookDir);
2880
3596
  break;
2881
3597
  }
2882
3598
  case "commands": {
2883
3599
  const commands = discoverCommands(process.cwd());
2884
3600
  if (commands.length === 0) {
2885
- clack.outro(chalk9.yellow("No commands found. Run from a monorepo root."));
3601
+ clack.outro(chalk11.yellow("No commands found. Run from a monorepo root."));
2886
3602
  return;
2887
3603
  }
2888
- clack.log.info(`Found ${chalk9.green(commands.length.toString())} command(s)`);
3604
+ clack.log.info(`Found ${chalk11.green(commands.length.toString())} command(s)`);
2889
3605
  displayCommands(commands);
2890
- clack.outro(chalk9.green("Done!"));
3606
+ clack.outro(chalk11.green("Done!"));
2891
3607
  break;
2892
3608
  }
2893
3609
  case "architecture": {
2894
3610
  const info = discoverArchitecture(process.cwd());
2895
3611
  if (!info) {
2896
3612
  clack.outro(
2897
- chalk9.yellow("No monorepo detected. Run from within a Melos monorepo.")
3613
+ chalk11.yellow("No monorepo detected. Run from within a Melos monorepo.")
2898
3614
  );
2899
3615
  return;
2900
3616
  }
2901
3617
  displayArchitecture(info);
2902
- clack.outro(chalk9.green("Done!"));
3618
+ clack.outro(chalk11.green("Done!"));
2903
3619
  break;
2904
3620
  }
2905
3621
  }
@@ -2908,12 +3624,12 @@ var SCREAMING_SNAKE_REGEX = /^[A-Z][A-Z0-9_]*$/;
2908
3624
  async function envVarFlow() {
2909
3625
  const monorepoRoot = findMonorepoRoot(process.cwd());
2910
3626
  if (!monorepoRoot) {
2911
- clack.outro(chalk9.red("Not inside a monorepo. Run from within a Melos monorepo."));
3627
+ clack.outro(chalk11.red("Not inside a monorepo. Run from within a Melos monorepo."));
2912
3628
  return;
2913
3629
  }
2914
3630
  const apps = discoverAppsWithEnv(monorepoRoot);
2915
3631
  if (apps.length === 0) {
2916
- clack.outro(chalk9.red("No apps with env/ directory found in the monorepo."));
3632
+ clack.outro(chalk11.red("No apps with env/ directory found in the monorepo."));
2917
3633
  return;
2918
3634
  }
2919
3635
  const variableName = await clack.text({
@@ -3017,14 +3733,14 @@ async function envVarFlow() {
3017
3733
  includeInAppConfig
3018
3734
  });
3019
3735
  genSpinner.stop("Done");
3020
- clack.outro(chalk9.green("Environment variable added!"));
3736
+ clack.outro(chalk11.green("Environment variable added!"));
3021
3737
  } catch (error) {
3022
3738
  genSpinner.stop("Failed");
3023
- clack.outro(chalk9.red(`Error: ${error}`));
3739
+ clack.outro(chalk11.red(`Error: ${error}`));
3024
3740
  }
3025
3741
  }
3026
3742
  async function interactiveMode() {
3027
- clack.intro(chalk9.bgCyan(chalk9.black(" wlmaker ")));
3743
+ clack.intro(chalk11.bgCyan(chalk11.black(" wlmaker ")));
3028
3744
  const createType = await clack.select({
3029
3745
  message: "What do you want to create?",
3030
3746
  options: [
@@ -3035,11 +3751,21 @@ async function interactiveMode() {
3035
3751
  label: "Widgetbook Use-Case",
3036
3752
  hint: "Component showcase"
3037
3753
  },
3754
+ {
3755
+ value: "page",
3756
+ label: "Page",
3757
+ hint: "GoRoute + View with barrels"
3758
+ },
3038
3759
  {
3039
3760
  value: "endpoint",
3040
3761
  label: "Endpoint",
3041
3762
  hint: "BFF Clean Architecture stack"
3042
3763
  },
3764
+ {
3765
+ value: "package",
3766
+ label: "Package",
3767
+ hint: "Create a new package in the monorepo"
3768
+ },
3043
3769
  {
3044
3770
  value: "env-var",
3045
3771
  label: "Env Var",
@@ -3070,9 +3796,15 @@ async function interactiveMode() {
3070
3796
  case "usecase":
3071
3797
  await useCaseFlow();
3072
3798
  break;
3799
+ case "page":
3800
+ await pageFlow();
3801
+ break;
3073
3802
  case "endpoint":
3074
3803
  await endpointFlow();
3075
3804
  break;
3805
+ case "package":
3806
+ await packageFlow();
3807
+ break;
3076
3808
  case "env-var":
3077
3809
  await envVarFlow();
3078
3810
  break;
@@ -3098,7 +3830,7 @@ program.command("bloc").description("Create a new BLoC with Freezed sealed class
3098
3830
  try {
3099
3831
  await createBloc(name, options);
3100
3832
  } catch (error) {
3101
- console.error(chalk10.red(`Error: ${error}`));
3833
+ console.error(chalk12.red(`Error: ${error}`));
3102
3834
  process.exit(1);
3103
3835
  }
3104
3836
  }
@@ -3115,12 +3847,12 @@ program.command("widget").description("Create a new widget in the design system"
3115
3847
  projectRoot: options.dir,
3116
3848
  buildRunner: false
3117
3849
  });
3118
- console.log(chalk10.green("Widgetbook use-case created"));
3850
+ console.log(chalk12.green("Widgetbook use-case created"));
3119
3851
  } catch {
3120
- console.log(chalk10.yellow("Use-case skipped (may already exist)"));
3852
+ console.log(chalk12.yellow("Use-case skipped (may already exist)"));
3121
3853
  }
3122
3854
  } catch (error) {
3123
- console.error(chalk10.red(`Error: ${error}`));
3855
+ console.error(chalk12.red(`Error: ${error}`));
3124
3856
  process.exit(1);
3125
3857
  }
3126
3858
  }
@@ -3133,7 +3865,21 @@ program.command("usecase").description("Create a Widgetbook use-case for an exis
3133
3865
  buildRunner: options.buildRunner
3134
3866
  });
3135
3867
  } catch (error) {
3136
- console.error(chalk10.red(`Error: ${error}`));
3868
+ console.error(chalk12.red(`Error: ${error}`));
3869
+ process.exit(1);
3870
+ }
3871
+ }
3872
+ );
3873
+ program.command("page").description("Create a new page (GoRoute + View) with barrel updates").argument("[name]", "Page name in snake_case (e.g. profile, order_detail)").option("-p, --path <path>", "absolute path to the pages directory").action(
3874
+ async (name, options) => {
3875
+ if (!name || !options.path) {
3876
+ await pageFlow(name, options.path);
3877
+ return;
3878
+ }
3879
+ try {
3880
+ await createPage(name, { pagesPath: options.path });
3881
+ } catch (error) {
3882
+ console.error(chalk12.red(`Error: ${error}`));
3137
3883
  process.exit(1);
3138
3884
  }
3139
3885
  }
@@ -3143,6 +3889,9 @@ program.command("endpoint").description("Generate Clean Architecture stack for a
3143
3889
  if (!project) return;
3144
3890
  await endpointFlow(project);
3145
3891
  });
3892
+ program.command("package").description("Create a new package in the monorepo").action(async () => {
3893
+ await packageFlow();
3894
+ });
3146
3895
  program.command("env-var").description("Add an environment variable across the Flutter monorepo").action(async () => {
3147
3896
  await envVarFlow();
3148
3897
  });
@@ -3150,26 +3899,26 @@ var docsCmd = program.command("docs").description("Project documentation tools")
3150
3899
  docsCmd.command("serve").description("Start Docusaurus dev server").option("-d, --dir <path>", "project root directory", process.cwd()).action(async (options) => {
3151
3900
  const bookDir = detectBookDir(options.dir);
3152
3901
  if (!bookDir) {
3153
- console.error(chalk10.red("No Docusaurus book/ directory found. Run from a monorepo root."));
3902
+ console.error(chalk12.red("No Docusaurus book/ directory found. Run from a monorepo root."));
3154
3903
  process.exit(1);
3155
3904
  }
3156
- console.log(chalk10.cyan(`Serving docs from ${bookDir}`));
3905
+ console.log(chalk12.cyan(`Serving docs from ${bookDir}`));
3157
3906
  await serveBook(bookDir);
3158
3907
  });
3159
3908
  docsCmd.command("commands").description("Show Makefile & melos commands reference").option("-d, --dir <path>", "project root directory", process.cwd()).action(async (options) => {
3160
3909
  const commands = discoverCommands(options.dir);
3161
3910
  if (commands.length === 0) {
3162
- console.log(chalk10.yellow("No commands found. Run from a monorepo root."));
3911
+ console.log(chalk12.yellow("No commands found. Run from a monorepo root."));
3163
3912
  return;
3164
3913
  }
3165
- console.log(chalk10.green(`Found ${commands.length} command(s)
3914
+ console.log(chalk12.green(`Found ${commands.length} command(s)
3166
3915
  `));
3167
3916
  displayCommands(commands);
3168
3917
  });
3169
3918
  docsCmd.command("architecture").description("Display monorepo architecture tree").option("-d, --dir <path>", "project root directory", process.cwd()).action(async (options) => {
3170
3919
  const info = discoverArchitecture(options.dir);
3171
3920
  if (!info) {
3172
- console.log(chalk10.yellow("No monorepo detected. Run from within a Melos monorepo."));
3921
+ console.log(chalk12.yellow("No monorepo detected. Run from within a Melos monorepo."));
3173
3922
  return;
3174
3923
  }
3175
3924
  displayArchitecture(info);