zuro-cli 0.0.2-beta.11 → 0.0.2-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -357,6 +357,32 @@ var ENV_CONFIGS = {
357
357
  { name: "BETTER_AUTH_SECRET", schema: "z.string().min(32)" },
358
358
  { name: "BETTER_AUTH_URL", schema: "z.string().url()" }
359
359
  ]
360
+ },
361
+ mailer: {
362
+ envVars: {
363
+ SMTP_HOST: "smtp.example.com",
364
+ SMTP_PORT: "587",
365
+ SMTP_USER: "your-email@example.com",
366
+ SMTP_PASS: "your-password",
367
+ MAIL_FROM: "noreply@example.com"
368
+ },
369
+ schemaFields: [
370
+ { name: "SMTP_HOST", schema: "z.string().min(1)" },
371
+ { name: "SMTP_PORT", schema: "z.coerce.number().default(587)" },
372
+ { name: "SMTP_USER", schema: "z.string().min(1)" },
373
+ { name: "SMTP_PASS", schema: "z.string().min(1)" },
374
+ { name: "MAIL_FROM", schema: "z.string().email()" }
375
+ ]
376
+ },
377
+ "mailer-resend": {
378
+ envVars: {
379
+ RESEND_API_KEY: "re_your_api_key",
380
+ MAIL_FROM: "onboarding@resend.dev"
381
+ },
382
+ schemaFields: [
383
+ { name: "RESEND_API_KEY", schema: "z.string().min(1)" },
384
+ { name: "MAIL_FROM", schema: "z.string().min(1)" }
385
+ ]
360
386
  }
361
387
  };
362
388
 
@@ -663,7 +689,9 @@ var BLOCK_SIGNATURES = {
663
689
  validator: "middleware/validate.ts",
664
690
  "error-handler": "lib/errors.ts",
665
691
  logger: "lib/logger.ts",
666
- auth: "lib/auth.ts"
692
+ auth: "lib/auth.ts",
693
+ mailer: "lib/mailer.ts",
694
+ docs: "lib/openapi.ts"
667
695
  };
668
696
  var resolveDependencies = async (moduleDependencies, cwd) => {
669
697
  if (!moduleDependencies || moduleDependencies.length === 0) {
@@ -814,6 +842,25 @@ function getModuleDocsPath(moduleName) {
814
842
  function escapeRegex(value) {
815
843
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
816
844
  }
845
+ function appendImport(source, line) {
846
+ if (source.includes(line)) {
847
+ return { source, inserted: true };
848
+ }
849
+ const importRegex = /^import .+ from .+;?\s*$/gm;
850
+ let lastImportIndex = 0;
851
+ let match;
852
+ while ((match = importRegex.exec(source)) !== null) {
853
+ lastImportIndex = match.index + match[0].length;
854
+ }
855
+ if (lastImportIndex <= 0) {
856
+ return { source, inserted: false };
857
+ }
858
+ return {
859
+ source: source.slice(0, lastImportIndex) + `
860
+ ${line}` + source.slice(lastImportIndex),
861
+ inserted: true
862
+ };
863
+ }
817
864
  async function hasEnvVariable(projectRoot, key) {
818
865
  const envPath = import_path6.default.join(projectRoot, ".env");
819
866
  if (!await import_fs_extra6.default.pathExists(envPath)) {
@@ -851,6 +898,12 @@ async function ensureSchemaExport(projectRoot, srcDir, schemaFileName) {
851
898
  `;
852
899
  await import_fs_extra6.default.writeFile(schemaIndexPath, next);
853
900
  }
901
+ async function isDocsModuleInstalled(projectRoot, srcDir) {
902
+ return await import_fs_extra6.default.pathExists(import_path6.default.join(projectRoot, srcDir, "lib", "openapi.ts"));
903
+ }
904
+ async function isAuthModuleInstalled(projectRoot, srcDir) {
905
+ return await import_fs_extra6.default.pathExists(import_path6.default.join(projectRoot, srcDir, "lib", "auth.ts"));
906
+ }
854
907
  async function injectErrorHandler(projectRoot, srcDir) {
855
908
  const appPath = import_path6.default.join(projectRoot, srcDir, "app.ts");
856
909
  if (!import_fs_extra6.default.existsSync(appPath)) {
@@ -913,25 +966,6 @@ async function injectAuthRoutes(projectRoot, srcDir) {
913
966
  const routeIndexUserImport = `import userRoutes from "./user.routes";`;
914
967
  const appUserImport = `import userRoutes from "./routes/user.routes";`;
915
968
  let appModified = false;
916
- const appendImport = (source, line) => {
917
- if (source.includes(line)) {
918
- return { source, inserted: true };
919
- }
920
- const importRegex = /^import .+ from .+;?\s*$/gm;
921
- let lastImportIndex = 0;
922
- let match;
923
- while ((match = importRegex.exec(source)) !== null) {
924
- lastImportIndex = match.index + match[0].length;
925
- }
926
- if (lastImportIndex <= 0) {
927
- return { source, inserted: false };
928
- }
929
- return {
930
- source: source.slice(0, lastImportIndex) + `
931
- ${line}` + source.slice(lastImportIndex),
932
- inserted: true
933
- };
934
- };
935
969
  for (const importLine of [authHandlerImport, authImport]) {
936
970
  const next = appendImport(appContent, importLine);
937
971
  if (!next.inserted) {
@@ -1017,7 +1051,177 @@ app.use("/api/users", userRoutes);
1017
1051
  }
1018
1052
  return true;
1019
1053
  }
1020
- var add = async (moduleName) => {
1054
+ async function injectDocsRoutes(projectRoot, srcDir) {
1055
+ const routeIndexPath = import_path6.default.join(projectRoot, srcDir, "routes", "index.ts");
1056
+ const routeImport = `import docsRoutes from "./docs.routes";`;
1057
+ const routeMountPattern = /rootRouter\.use\(\s*["']\/docs["']\s*,\s*docsRoutes\s*\)/;
1058
+ if (await import_fs_extra6.default.pathExists(routeIndexPath)) {
1059
+ let routeContent = await import_fs_extra6.default.readFile(routeIndexPath, "utf-8");
1060
+ let routeModified = false;
1061
+ const importResult = appendImport(routeContent, routeImport);
1062
+ if (!importResult.inserted) {
1063
+ return false;
1064
+ }
1065
+ if (importResult.source !== routeContent) {
1066
+ routeContent = importResult.source;
1067
+ routeModified = true;
1068
+ }
1069
+ if (!routeMountPattern.test(routeContent)) {
1070
+ const routeSetup = `
1071
+ // API docs
1072
+ rootRouter.use("/docs", docsRoutes);
1073
+ `;
1074
+ const exportMatch = routeContent.match(/export default rootRouter;?\s*$/m);
1075
+ if (!exportMatch || exportMatch.index === void 0) {
1076
+ return false;
1077
+ }
1078
+ routeContent = routeContent.slice(0, exportMatch.index) + routeSetup + "\n" + routeContent.slice(exportMatch.index);
1079
+ routeModified = true;
1080
+ }
1081
+ if (routeModified) {
1082
+ await import_fs_extra6.default.writeFile(routeIndexPath, routeContent);
1083
+ }
1084
+ return true;
1085
+ }
1086
+ const appPath = import_path6.default.join(projectRoot, srcDir, "app.ts");
1087
+ if (!await import_fs_extra6.default.pathExists(appPath)) {
1088
+ return false;
1089
+ }
1090
+ let appContent = await import_fs_extra6.default.readFile(appPath, "utf-8");
1091
+ let appModified = false;
1092
+ const appImportResult = appendImport(appContent, `import docsRoutes from "./routes/docs.routes";`);
1093
+ if (!appImportResult.inserted) {
1094
+ return false;
1095
+ }
1096
+ if (appImportResult.source !== appContent) {
1097
+ appContent = appImportResult.source;
1098
+ appModified = true;
1099
+ }
1100
+ const hasMount = /app\.use\(\s*["']\/api\/docs["']\s*,\s*docsRoutes\s*\)/.test(appContent);
1101
+ if (!hasMount) {
1102
+ const setup = `
1103
+ // API docs
1104
+ app.use("/api/docs", docsRoutes);
1105
+ `;
1106
+ const exportMatch = appContent.match(/export default app;?\s*$/m);
1107
+ if (!exportMatch || exportMatch.index === void 0) {
1108
+ return false;
1109
+ }
1110
+ appContent = appContent.slice(0, exportMatch.index) + setup + "\n" + appContent.slice(exportMatch.index);
1111
+ appModified = true;
1112
+ }
1113
+ if (appModified) {
1114
+ await import_fs_extra6.default.writeFile(appPath, appContent);
1115
+ }
1116
+ return true;
1117
+ }
1118
+ async function injectAuthDocs(projectRoot, srcDir) {
1119
+ const openApiPath = import_path6.default.join(projectRoot, srcDir, "lib", "openapi.ts");
1120
+ if (!await import_fs_extra6.default.pathExists(openApiPath)) {
1121
+ return false;
1122
+ }
1123
+ const authMarker = "// ZURO_AUTH_DOCS";
1124
+ let content = await import_fs_extra6.default.readFile(openApiPath, "utf-8");
1125
+ if (content.includes(authMarker)) {
1126
+ return true;
1127
+ }
1128
+ const moduleDocsEndMarker = "// ZURO_DOCS_MODULES_END";
1129
+ if (!content.includes(moduleDocsEndMarker)) {
1130
+ return false;
1131
+ }
1132
+ const authBlock = `
1133
+ const authSignUpSchema = z.object({
1134
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1135
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1136
+ name: z.string().min(1).optional().openapi({ example: "Dev User" }),
1137
+ });
1138
+
1139
+ const authSignInSchema = z.object({
1140
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1141
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1142
+ });
1143
+
1144
+ const authUserSchema = z.object({
1145
+ id: z.string().openapi({ example: "user_123" }),
1146
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1147
+ name: z.string().nullable().openapi({ example: "Dev User" }),
1148
+ });
1149
+
1150
+ ${authMarker}
1151
+ registry.registerPath({
1152
+ method: "post",
1153
+ path: "/api/auth/sign-up/email",
1154
+ tags: ["Auth"],
1155
+ summary: "Register using email and password",
1156
+ request: {
1157
+ body: {
1158
+ content: {
1159
+ "application/json": {
1160
+ schema: authSignUpSchema,
1161
+ },
1162
+ },
1163
+ },
1164
+ },
1165
+ responses: {
1166
+ 200: { description: "Registration successful" },
1167
+ },
1168
+ });
1169
+
1170
+ registry.registerPath({
1171
+ method: "post",
1172
+ path: "/api/auth/sign-in/email",
1173
+ tags: ["Auth"],
1174
+ summary: "Sign in using email and password",
1175
+ request: {
1176
+ body: {
1177
+ content: {
1178
+ "application/json": {
1179
+ schema: authSignInSchema,
1180
+ },
1181
+ },
1182
+ },
1183
+ },
1184
+ responses: {
1185
+ 200: { description: "Sign in successful" },
1186
+ 401: { description: "Invalid credentials" },
1187
+ },
1188
+ });
1189
+
1190
+ registry.registerPath({
1191
+ method: "post",
1192
+ path: "/api/auth/sign-out",
1193
+ tags: ["Auth"],
1194
+ summary: "Sign out current user",
1195
+ responses: {
1196
+ 200: { description: "Sign out successful" },
1197
+ },
1198
+ });
1199
+
1200
+ registry.registerPath({
1201
+ method: "get",
1202
+ path: "/api/users/me",
1203
+ tags: ["Auth"],
1204
+ summary: "Get current authenticated user",
1205
+ security: [{ bearerAuth: [] }],
1206
+ responses: {
1207
+ 200: {
1208
+ description: "Current user",
1209
+ content: {
1210
+ "application/json": {
1211
+ schema: z.object({ user: authUserSchema }),
1212
+ },
1213
+ },
1214
+ },
1215
+ 401: { description: "Not authenticated" },
1216
+ },
1217
+ });
1218
+ `;
1219
+ content = content.replace(moduleDocsEndMarker, `${authBlock}
1220
+ ${moduleDocsEndMarker}`);
1221
+ await import_fs_extra6.default.writeFile(openApiPath, content);
1222
+ return true;
1223
+ }
1224
+ var add = async (moduleName, options = {}) => {
1021
1225
  const projectRoot = process.cwd();
1022
1226
  const projectConfig = await readZuroConfig(projectRoot);
1023
1227
  if (!projectConfig) {
@@ -1039,6 +1243,10 @@ var add = async (moduleName) => {
1039
1243
  let databaseBackupPath = null;
1040
1244
  let generatedAuthSecret = false;
1041
1245
  let authDatabaseDialect = null;
1246
+ let customSmtpVars;
1247
+ let usedDefaultSmtp = false;
1248
+ let mailerProvider = "smtp";
1249
+ let shouldInstallDocsForAuth = false;
1042
1250
  if (resolvedModuleName === "database") {
1043
1251
  const variantResponse = await (0, import_prompts2.default)({
1044
1252
  type: "select",
@@ -1099,6 +1307,123 @@ var add = async (moduleName) => {
1099
1307
  usedDefaultDbUrl = enteredUrl.length === 0;
1100
1308
  customDbUrl = validateDatabaseUrl(enteredUrl || defaultUrl, resolvedModuleName);
1101
1309
  }
1310
+ if (resolvedModuleName === "mailer") {
1311
+ const providerResponse = await (0, import_prompts2.default)({
1312
+ type: "select",
1313
+ name: "provider",
1314
+ message: "Which email provider?",
1315
+ choices: [
1316
+ { title: "SMTP (Nodemailer)", description: "Gmail, Mailtrap, any SMTP server", value: "smtp" },
1317
+ { title: "Resend", description: "API-based, easiest setup", value: "resend" }
1318
+ ]
1319
+ });
1320
+ if (providerResponse.provider === void 0) {
1321
+ console.log(import_chalk4.default.yellow("Operation cancelled."));
1322
+ return;
1323
+ }
1324
+ mailerProvider = providerResponse.provider;
1325
+ console.log(import_chalk4.default.dim(" Tip: Leave fields blank to use placeholder values and configure later\n"));
1326
+ if (mailerProvider === "smtp") {
1327
+ const smtpResponse = await (0, import_prompts2.default)([
1328
+ {
1329
+ type: "text",
1330
+ name: "host",
1331
+ message: "SMTP Host",
1332
+ initial: ""
1333
+ },
1334
+ {
1335
+ type: "text",
1336
+ name: "port",
1337
+ message: "SMTP Port",
1338
+ initial: "587"
1339
+ },
1340
+ {
1341
+ type: "text",
1342
+ name: "user",
1343
+ message: "SMTP User",
1344
+ initial: ""
1345
+ },
1346
+ {
1347
+ type: "password",
1348
+ name: "pass",
1349
+ message: "SMTP Password"
1350
+ },
1351
+ {
1352
+ type: "text",
1353
+ name: "from",
1354
+ message: "Mail From address",
1355
+ initial: ""
1356
+ }
1357
+ ]);
1358
+ if (smtpResponse.host === void 0) {
1359
+ console.log(import_chalk4.default.yellow("Operation cancelled."));
1360
+ return;
1361
+ }
1362
+ const host = smtpResponse.host?.trim() || "";
1363
+ const user = smtpResponse.user?.trim() || "";
1364
+ const pass = smtpResponse.pass?.trim() || "";
1365
+ const from = smtpResponse.from?.trim() || "";
1366
+ const port = smtpResponse.port?.trim() || "587";
1367
+ usedDefaultSmtp = !host && !user;
1368
+ if (!usedDefaultSmtp) {
1369
+ customSmtpVars = {
1370
+ SMTP_HOST: host || "smtp.example.com",
1371
+ SMTP_PORT: port,
1372
+ SMTP_USER: user || "your-email@example.com",
1373
+ SMTP_PASS: pass || "your-password",
1374
+ MAIL_FROM: from || "noreply@example.com"
1375
+ };
1376
+ }
1377
+ } else {
1378
+ const resendResponse = await (0, import_prompts2.default)([
1379
+ {
1380
+ type: "text",
1381
+ name: "apiKey",
1382
+ message: "Resend API Key",
1383
+ initial: ""
1384
+ },
1385
+ {
1386
+ type: "text",
1387
+ name: "from",
1388
+ message: "Mail From address",
1389
+ initial: ""
1390
+ }
1391
+ ]);
1392
+ if (resendResponse.apiKey === void 0) {
1393
+ console.log(import_chalk4.default.yellow("Operation cancelled."));
1394
+ return;
1395
+ }
1396
+ const apiKey = resendResponse.apiKey?.trim() || "";
1397
+ const from = resendResponse.from?.trim() || "";
1398
+ usedDefaultSmtp = !apiKey;
1399
+ if (!usedDefaultSmtp) {
1400
+ customSmtpVars = {
1401
+ RESEND_API_KEY: apiKey || "re_your_api_key",
1402
+ MAIL_FROM: from || "onboarding@resend.dev"
1403
+ };
1404
+ }
1405
+ }
1406
+ }
1407
+ if (resolvedModuleName === "auth") {
1408
+ const docsInstalled = await isDocsModuleInstalled(projectRoot, srcDir);
1409
+ if (!docsInstalled) {
1410
+ if (options.yes) {
1411
+ shouldInstallDocsForAuth = true;
1412
+ } else {
1413
+ const docsResponse = await (0, import_prompts2.default)({
1414
+ type: "confirm",
1415
+ name: "installDocs",
1416
+ message: "Install API docs module (Scalar + OpenAPI) too?",
1417
+ initial: true
1418
+ });
1419
+ if (docsResponse.installDocs === void 0) {
1420
+ console.log(import_chalk4.default.yellow("Operation cancelled."));
1421
+ return;
1422
+ }
1423
+ shouldInstallDocsForAuth = docsResponse.installDocs;
1424
+ }
1425
+ }
1426
+ }
1102
1427
  const pm = resolvePackageManager(projectRoot);
1103
1428
  const spinner = (0, import_ora2.default)(`Checking registry for ${resolvedModuleName}...`).start();
1104
1429
  let currentStep = "package manager preflight";
@@ -1119,8 +1444,19 @@ var add = async (moduleName) => {
1119
1444
  await resolveDependencies(moduleDeps, projectRoot);
1120
1445
  currentStep = "dependency installation";
1121
1446
  spinner.start("Installing dependencies...");
1122
- await installDependencies(pm, module2.dependencies || [], projectRoot);
1123
- await installDependencies(pm, module2.devDependencies || [], projectRoot, { dev: true });
1447
+ let runtimeDeps = module2.dependencies || [];
1448
+ let devDeps = module2.devDependencies || [];
1449
+ if (resolvedModuleName === "mailer") {
1450
+ if (mailerProvider === "resend") {
1451
+ runtimeDeps = ["resend"];
1452
+ devDeps = [];
1453
+ } else {
1454
+ runtimeDeps = ["nodemailer"];
1455
+ devDeps = ["@types/nodemailer"];
1456
+ }
1457
+ }
1458
+ await installDependencies(pm, runtimeDeps, projectRoot);
1459
+ await installDependencies(pm, devDeps, projectRoot, { dev: true });
1124
1460
  spinner.succeed("Dependencies installed");
1125
1461
  currentStep = "module scaffolding";
1126
1462
  spinner.start("Scaffolding files...");
@@ -1136,6 +1472,11 @@ var add = async (moduleName) => {
1136
1472
  expectedSha256 = void 0;
1137
1473
  expectedSize = void 0;
1138
1474
  }
1475
+ if (resolvedModuleName === "mailer" && file.target === "lib/mailer.ts" && mailerProvider === "resend") {
1476
+ fetchPath = "express/lib/mailer.resend.ts";
1477
+ expectedSha256 = void 0;
1478
+ expectedSize = void 0;
1479
+ }
1139
1480
  let content = await fetchFile(fetchPath, {
1140
1481
  baseUrl: registryContext.fileBaseUrl,
1141
1482
  expectedSha256,
@@ -1165,6 +1506,16 @@ var add = async (moduleName) => {
1165
1506
  } else {
1166
1507
  spinner.warn("Could not configure routes automatically");
1167
1508
  }
1509
+ const docsInstalled = await isDocsModuleInstalled(projectRoot, srcDir);
1510
+ if (docsInstalled) {
1511
+ spinner.start("Adding auth endpoints to API docs...");
1512
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
1513
+ if (authDocsInjected) {
1514
+ spinner.succeed("Auth endpoints added to API docs");
1515
+ } else {
1516
+ spinner.warn("Could not update API docs automatically");
1517
+ }
1518
+ }
1168
1519
  }
1169
1520
  if (resolvedModuleName === "error-handler") {
1170
1521
  spinner.start("Configuring error handler in app.ts...");
@@ -1175,7 +1526,30 @@ var add = async (moduleName) => {
1175
1526
  spinner.warn("Could not find app.ts - error handler needs manual setup");
1176
1527
  }
1177
1528
  }
1178
- const envConfig = ENV_CONFIGS[resolvedModuleName];
1529
+ if (resolvedModuleName === "docs") {
1530
+ spinner.start("Configuring docs routes...");
1531
+ const injected = await injectDocsRoutes(projectRoot, srcDir);
1532
+ if (injected) {
1533
+ spinner.succeed("Docs routes configured");
1534
+ } else {
1535
+ spinner.warn("Could not configure docs routes automatically");
1536
+ }
1537
+ const authInstalled = await isAuthModuleInstalled(projectRoot, srcDir);
1538
+ if (authInstalled) {
1539
+ spinner.start("Adding auth endpoints to API docs...");
1540
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
1541
+ if (authDocsInjected) {
1542
+ spinner.succeed("Auth endpoints added to API docs");
1543
+ } else {
1544
+ spinner.warn("Could not update API docs automatically");
1545
+ }
1546
+ }
1547
+ }
1548
+ let envConfigKey = resolvedModuleName;
1549
+ if (resolvedModuleName === "mailer" && mailerProvider === "resend") {
1550
+ envConfigKey = "mailer-resend";
1551
+ }
1552
+ const envConfig = ENV_CONFIGS[envConfigKey];
1179
1553
  if (envConfig) {
1180
1554
  currentStep = "environment configuration";
1181
1555
  spinner.start("Updating environment configuration...");
@@ -1183,6 +1557,9 @@ var add = async (moduleName) => {
1183
1557
  if (customDbUrl && isDatabaseModule(resolvedModuleName)) {
1184
1558
  envVars.DATABASE_URL = customDbUrl;
1185
1559
  }
1560
+ if (resolvedModuleName === "mailer" && customSmtpVars) {
1561
+ Object.assign(envVars, customSmtpVars);
1562
+ }
1186
1563
  if (resolvedModuleName === "auth") {
1187
1564
  const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
1188
1565
  if (!hasExistingSecret) {
@@ -1225,6 +1602,21 @@ var add = async (moduleName) => {
1225
1602
  }
1226
1603
  console.log(import_chalk4.default.yellow("\u2139 Run migrations: npx drizzle-kit generate && npx drizzle-kit migrate"));
1227
1604
  }
1605
+ if (resolvedModuleName === "mailer") {
1606
+ if (usedDefaultSmtp) {
1607
+ console.log(import_chalk4.default.yellow("\u2139 Placeholder SMTP values added to .env \u2014 update them before sending emails."));
1608
+ } else {
1609
+ console.log(import_chalk4.default.yellow("\u2139 Review SMTP configuration in .env to ensure values are correct."));
1610
+ }
1611
+ }
1612
+ if (resolvedModuleName === "docs") {
1613
+ console.log(import_chalk4.default.yellow("\u2139 API docs available at: /api/docs"));
1614
+ console.log(import_chalk4.default.yellow("\u2139 OpenAPI spec available at: /api/docs/openapi.json"));
1615
+ }
1616
+ if (resolvedModuleName === "auth" && shouldInstallDocsForAuth) {
1617
+ console.log(import_chalk4.default.blue("\n\u2139 Installing API docs module..."));
1618
+ await add("docs", { yes: true });
1619
+ }
1228
1620
  } catch (error) {
1229
1621
  spinner.fail(import_chalk4.default.red(`Failed during ${currentStep}.`));
1230
1622
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1239,6 +1631,6 @@ ${import_chalk4.default.bold("Retry:")}`);
1239
1631
  var program = new import_commander.Command();
1240
1632
  program.name("zuro-cli").description("Zuro CLI tool").version("0.0.1");
1241
1633
  program.command("init").description("Initialize a new Zuro project").action(init);
1242
- program.command("add <module>").description("Add a module to your project").action(add);
1634
+ program.command("add <module>").description("Add a module to your project").action((module2, options) => add(module2, options));
1243
1635
  program.parse(process.argv);
1244
1636
  //# sourceMappingURL=index.js.map