zuro-cli 0.0.2-beta.10 → 0.0.2-beta.12

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.mjs CHANGED
@@ -334,6 +334,32 @@ var ENV_CONFIGS = {
334
334
  { name: "BETTER_AUTH_SECRET", schema: "z.string().min(32)" },
335
335
  { name: "BETTER_AUTH_URL", schema: "z.string().url()" }
336
336
  ]
337
+ },
338
+ mailer: {
339
+ envVars: {
340
+ SMTP_HOST: "smtp.example.com",
341
+ SMTP_PORT: "587",
342
+ SMTP_USER: "your-email@example.com",
343
+ SMTP_PASS: "your-password",
344
+ MAIL_FROM: "noreply@example.com"
345
+ },
346
+ schemaFields: [
347
+ { name: "SMTP_HOST", schema: "z.string().min(1)" },
348
+ { name: "SMTP_PORT", schema: "z.coerce.number().default(587)" },
349
+ { name: "SMTP_USER", schema: "z.string().min(1)" },
350
+ { name: "SMTP_PASS", schema: "z.string().min(1)" },
351
+ { name: "MAIL_FROM", schema: "z.string().email()" }
352
+ ]
353
+ },
354
+ "mailer-resend": {
355
+ envVars: {
356
+ RESEND_API_KEY: "re_your_api_key",
357
+ MAIL_FROM: "onboarding@resend.dev"
358
+ },
359
+ schemaFields: [
360
+ { name: "RESEND_API_KEY", schema: "z.string().min(1)" },
361
+ { name: "MAIL_FROM", schema: "z.string().min(1)" }
362
+ ]
337
363
  }
338
364
  };
339
365
 
@@ -640,7 +666,8 @@ var BLOCK_SIGNATURES = {
640
666
  validator: "middleware/validate.ts",
641
667
  "error-handler": "lib/errors.ts",
642
668
  logger: "lib/logger.ts",
643
- auth: "lib/auth.ts"
669
+ auth: "lib/auth.ts",
670
+ mailer: "lib/mailer.ts"
644
671
  };
645
672
  var resolveDependencies = async (moduleDependencies, cwd) => {
646
673
  if (!moduleDependencies || moduleDependencies.length === 0) {
@@ -1016,6 +1043,9 @@ var add = async (moduleName) => {
1016
1043
  let databaseBackupPath = null;
1017
1044
  let generatedAuthSecret = false;
1018
1045
  let authDatabaseDialect = null;
1046
+ let customSmtpVars;
1047
+ let usedDefaultSmtp = false;
1048
+ let mailerProvider = "smtp";
1019
1049
  if (resolvedModuleName === "database") {
1020
1050
  const variantResponse = await prompts2({
1021
1051
  type: "select",
@@ -1076,6 +1106,103 @@ var add = async (moduleName) => {
1076
1106
  usedDefaultDbUrl = enteredUrl.length === 0;
1077
1107
  customDbUrl = validateDatabaseUrl(enteredUrl || defaultUrl, resolvedModuleName);
1078
1108
  }
1109
+ if (resolvedModuleName === "mailer") {
1110
+ const providerResponse = await prompts2({
1111
+ type: "select",
1112
+ name: "provider",
1113
+ message: "Which email provider?",
1114
+ choices: [
1115
+ { title: "SMTP (Nodemailer)", description: "Gmail, Mailtrap, any SMTP server", value: "smtp" },
1116
+ { title: "Resend", description: "API-based, easiest setup", value: "resend" }
1117
+ ]
1118
+ });
1119
+ if (providerResponse.provider === void 0) {
1120
+ console.log(chalk4.yellow("Operation cancelled."));
1121
+ return;
1122
+ }
1123
+ mailerProvider = providerResponse.provider;
1124
+ console.log(chalk4.dim(" Tip: Leave fields blank to use placeholder values and configure later\n"));
1125
+ if (mailerProvider === "smtp") {
1126
+ const smtpResponse = await prompts2([
1127
+ {
1128
+ type: "text",
1129
+ name: "host",
1130
+ message: "SMTP Host",
1131
+ initial: ""
1132
+ },
1133
+ {
1134
+ type: "text",
1135
+ name: "port",
1136
+ message: "SMTP Port",
1137
+ initial: "587"
1138
+ },
1139
+ {
1140
+ type: "text",
1141
+ name: "user",
1142
+ message: "SMTP User",
1143
+ initial: ""
1144
+ },
1145
+ {
1146
+ type: "password",
1147
+ name: "pass",
1148
+ message: "SMTP Password"
1149
+ },
1150
+ {
1151
+ type: "text",
1152
+ name: "from",
1153
+ message: "Mail From address",
1154
+ initial: ""
1155
+ }
1156
+ ]);
1157
+ if (smtpResponse.host === void 0) {
1158
+ console.log(chalk4.yellow("Operation cancelled."));
1159
+ return;
1160
+ }
1161
+ const host = smtpResponse.host?.trim() || "";
1162
+ const user = smtpResponse.user?.trim() || "";
1163
+ const pass = smtpResponse.pass?.trim() || "";
1164
+ const from = smtpResponse.from?.trim() || "";
1165
+ const port = smtpResponse.port?.trim() || "587";
1166
+ usedDefaultSmtp = !host && !user;
1167
+ if (!usedDefaultSmtp) {
1168
+ customSmtpVars = {
1169
+ SMTP_HOST: host || "smtp.example.com",
1170
+ SMTP_PORT: port,
1171
+ SMTP_USER: user || "your-email@example.com",
1172
+ SMTP_PASS: pass || "your-password",
1173
+ MAIL_FROM: from || "noreply@example.com"
1174
+ };
1175
+ }
1176
+ } else {
1177
+ const resendResponse = await prompts2([
1178
+ {
1179
+ type: "text",
1180
+ name: "apiKey",
1181
+ message: "Resend API Key",
1182
+ initial: ""
1183
+ },
1184
+ {
1185
+ type: "text",
1186
+ name: "from",
1187
+ message: "Mail From address",
1188
+ initial: ""
1189
+ }
1190
+ ]);
1191
+ if (resendResponse.apiKey === void 0) {
1192
+ console.log(chalk4.yellow("Operation cancelled."));
1193
+ return;
1194
+ }
1195
+ const apiKey = resendResponse.apiKey?.trim() || "";
1196
+ const from = resendResponse.from?.trim() || "";
1197
+ usedDefaultSmtp = !apiKey;
1198
+ if (!usedDefaultSmtp) {
1199
+ customSmtpVars = {
1200
+ RESEND_API_KEY: apiKey || "re_your_api_key",
1201
+ MAIL_FROM: from || "onboarding@resend.dev"
1202
+ };
1203
+ }
1204
+ }
1205
+ }
1079
1206
  const pm = resolvePackageManager(projectRoot);
1080
1207
  const spinner = ora2(`Checking registry for ${resolvedModuleName}...`).start();
1081
1208
  let currentStep = "package manager preflight";
@@ -1096,8 +1223,19 @@ var add = async (moduleName) => {
1096
1223
  await resolveDependencies(moduleDeps, projectRoot);
1097
1224
  currentStep = "dependency installation";
1098
1225
  spinner.start("Installing dependencies...");
1099
- await installDependencies(pm, module.dependencies || [], projectRoot);
1100
- await installDependencies(pm, module.devDependencies || [], projectRoot, { dev: true });
1226
+ let runtimeDeps = module.dependencies || [];
1227
+ let devDeps = module.devDependencies || [];
1228
+ if (resolvedModuleName === "mailer") {
1229
+ if (mailerProvider === "resend") {
1230
+ runtimeDeps = ["resend"];
1231
+ devDeps = [];
1232
+ } else {
1233
+ runtimeDeps = ["nodemailer"];
1234
+ devDeps = ["@types/nodemailer"];
1235
+ }
1236
+ }
1237
+ await installDependencies(pm, runtimeDeps, projectRoot);
1238
+ await installDependencies(pm, devDeps, projectRoot, { dev: true });
1101
1239
  spinner.succeed("Dependencies installed");
1102
1240
  currentStep = "module scaffolding";
1103
1241
  spinner.start("Scaffolding files...");
@@ -1113,6 +1251,11 @@ var add = async (moduleName) => {
1113
1251
  expectedSha256 = void 0;
1114
1252
  expectedSize = void 0;
1115
1253
  }
1254
+ if (resolvedModuleName === "mailer" && file.target === "lib/mailer.ts" && mailerProvider === "resend") {
1255
+ fetchPath = "express/lib/mailer.resend.ts";
1256
+ expectedSha256 = void 0;
1257
+ expectedSize = void 0;
1258
+ }
1116
1259
  let content = await fetchFile(fetchPath, {
1117
1260
  baseUrl: registryContext.fileBaseUrl,
1118
1261
  expectedSha256,
@@ -1152,7 +1295,11 @@ var add = async (moduleName) => {
1152
1295
  spinner.warn("Could not find app.ts - error handler needs manual setup");
1153
1296
  }
1154
1297
  }
1155
- const envConfig = ENV_CONFIGS[resolvedModuleName];
1298
+ let envConfigKey = resolvedModuleName;
1299
+ if (resolvedModuleName === "mailer" && mailerProvider === "resend") {
1300
+ envConfigKey = "mailer-resend";
1301
+ }
1302
+ const envConfig = ENV_CONFIGS[envConfigKey];
1156
1303
  if (envConfig) {
1157
1304
  currentStep = "environment configuration";
1158
1305
  spinner.start("Updating environment configuration...");
@@ -1160,6 +1307,9 @@ var add = async (moduleName) => {
1160
1307
  if (customDbUrl && isDatabaseModule(resolvedModuleName)) {
1161
1308
  envVars.DATABASE_URL = customDbUrl;
1162
1309
  }
1310
+ if (resolvedModuleName === "mailer" && customSmtpVars) {
1311
+ Object.assign(envVars, customSmtpVars);
1312
+ }
1163
1313
  if (resolvedModuleName === "auth") {
1164
1314
  const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
1165
1315
  if (!hasExistingSecret) {
@@ -1202,6 +1352,13 @@ var add = async (moduleName) => {
1202
1352
  }
1203
1353
  console.log(chalk4.yellow("\u2139 Run migrations: npx drizzle-kit generate && npx drizzle-kit migrate"));
1204
1354
  }
1355
+ if (resolvedModuleName === "mailer") {
1356
+ if (usedDefaultSmtp) {
1357
+ console.log(chalk4.yellow("\u2139 Placeholder SMTP values added to .env \u2014 update them before sending emails."));
1358
+ } else {
1359
+ console.log(chalk4.yellow("\u2139 Review SMTP configuration in .env to ensure values are correct."));
1360
+ }
1361
+ }
1205
1362
  } catch (error) {
1206
1363
  spinner.fail(chalk4.red(`Failed during ${currentStep}.`));
1207
1364
  const errorMessage = error instanceof Error ? error.message : String(error);