zuro-cli 0.0.2-beta.16 → 0.0.2-beta.17

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
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-VMOTWTER.mjs";
21
21
 
22
22
  // src/index.ts
23
- import { Command } from "commander";
23
+ import { Command, InvalidArgumentError } from "commander";
24
24
 
25
25
  // src/commands/init.ts
26
26
  import ora from "ora";
@@ -371,6 +371,20 @@ var ENV_CONFIGS = {
371
371
  { name: "BETTER_AUTH_URL", schema: "z.string().url()" }
372
372
  ]
373
373
  },
374
+ "auth-jwt": {
375
+ envVars: {
376
+ JWT_ACCESS_SECRET: "your-jwt-access-secret-at-least-32-characters",
377
+ JWT_REFRESH_SECRET: "your-jwt-refresh-secret-at-least-32-characters",
378
+ JWT_ACCESS_EXPIRES_IN: "15m",
379
+ JWT_REFRESH_EXPIRES_IN: "7d"
380
+ },
381
+ schemaFields: [
382
+ { name: "JWT_ACCESS_SECRET", schema: "z.string().min(32)" },
383
+ { name: "JWT_REFRESH_SECRET", schema: "z.string().min(32)" },
384
+ { name: "JWT_ACCESS_EXPIRES_IN", schema: "z.string().min(2)" },
385
+ { name: "JWT_REFRESH_EXPIRES_IN", schema: "z.string().min(2)" }
386
+ ]
387
+ },
374
388
  mailer: {
375
389
  envVars: {
376
390
  SMTP_HOST: "smtp.example.com",
@@ -852,57 +866,93 @@ import chalk4 from "chalk";
852
866
  async function isAuthModuleInstalled(projectRoot, srcDir) {
853
867
  return await fs6.pathExists(path7.join(projectRoot, srcDir, "lib", "auth.ts"));
854
868
  }
855
- async function injectAuthRoutes(projectRoot, srcDir) {
869
+ async function detectInstalledAuthProvider(projectRoot, srcDir) {
870
+ const authPath = path7.join(projectRoot, srcDir, "lib", "auth.ts");
871
+ if (!await fs6.pathExists(authPath)) {
872
+ return null;
873
+ }
874
+ const authContent = await fs6.readFile(authPath, "utf-8");
875
+ if (authContent.includes("better-auth")) {
876
+ return "better-auth";
877
+ }
878
+ if (authContent.includes("jsonwebtoken") || authContent.includes("JWT_ACCESS_SECRET")) {
879
+ return "jwt";
880
+ }
881
+ return null;
882
+ }
883
+ async function injectAuthRoutes(projectRoot, srcDir, provider) {
856
884
  const appPath = path7.join(projectRoot, srcDir, "app.ts");
857
885
  if (!await fs6.pathExists(appPath)) {
858
886
  return false;
859
887
  }
860
888
  let appContent = await fs6.readFile(appPath, "utf-8");
861
- const authHandlerImport = `import { toNodeHandler } from "better-auth/node";`;
862
- const authImport = `import { auth } from "./lib/auth";`;
863
889
  const routeIndexUserImport = `import userRoutes from "./user.routes";`;
890
+ const routeIndexAuthImport = `import authRoutes from "./auth.routes";`;
864
891
  const appUserImport = `import userRoutes from "./routes/user.routes";`;
892
+ const appAuthImport = `import authRoutes from "./routes/auth.routes";`;
865
893
  let appModified = false;
866
- for (const importLine of [authHandlerImport, authImport]) {
867
- const next = appendImport(appContent, importLine);
868
- if (!next.inserted) {
869
- return false;
894
+ if (provider === "better-auth") {
895
+ const authHandlerImport = `import { toNodeHandler } from "better-auth/node";`;
896
+ const authImport = `import { auth } from "./lib/auth";`;
897
+ for (const importLine of [authHandlerImport, authImport]) {
898
+ const next = appendImport(appContent, importLine);
899
+ if (!next.inserted) {
900
+ return false;
901
+ }
902
+ if (next.source !== appContent) {
903
+ appContent = next.source;
904
+ appModified = true;
905
+ }
870
906
  }
871
- if (next.source !== appContent) {
872
- appContent = next.source;
907
+ const hasAuthMount = /toNodeHandler\(\s*auth\s*\)/.test(appContent) && /\/api\/auth/.test(appContent);
908
+ if (!hasAuthMount) {
909
+ const authMountLine = "app.all(/^\\/api\\/auth(?:\\/.*)?$/, toNodeHandler(auth));\n";
910
+ const jsonIndex = appContent.search(/^\s*app\.use\(\s*express\.json\(\)\s*\);\s*$/m);
911
+ let insertionIndex = jsonIndex;
912
+ if (insertionIndex < 0) {
913
+ const healthIndex = appContent.search(/^\s*app\.get\(\s*["']\/health["']\s*,/m);
914
+ insertionIndex = healthIndex;
915
+ }
916
+ if (insertionIndex < 0) {
917
+ const exportMatch = appContent.match(/export default app;?\s*$/m);
918
+ insertionIndex = exportMatch?.index ?? -1;
919
+ }
920
+ if (insertionIndex < 0) {
921
+ return false;
922
+ }
923
+ appContent = appContent.slice(0, insertionIndex) + authMountLine + appContent.slice(insertionIndex);
873
924
  appModified = true;
874
925
  }
875
926
  }
876
- const hasAuthMount = /toNodeHandler\(\s*auth\s*\)/.test(appContent) && /\/api\/auth/.test(appContent);
877
- if (!hasAuthMount) {
878
- const authMountLine = "app.all(/^\\/api\\/auth(?:\\/.*)?$/, toNodeHandler(auth));\n";
879
- const jsonIndex = appContent.search(/^\s*app\.use\(\s*express\.json\(\)\s*\);\s*$/m);
880
- let insertionIndex = jsonIndex;
881
- if (insertionIndex < 0) {
882
- const healthIndex = appContent.search(/^\s*app\.get\(\s*["']\/health["']\s*,/m);
883
- insertionIndex = healthIndex;
884
- }
885
- if (insertionIndex < 0) {
886
- const exportMatch = appContent.match(/export default app;?\s*$/m);
887
- insertionIndex = exportMatch?.index ?? -1;
888
- }
889
- if (insertionIndex < 0) {
890
- return false;
891
- }
892
- appContent = appContent.slice(0, insertionIndex) + authMountLine + appContent.slice(insertionIndex);
893
- appModified = true;
894
- }
895
927
  const routeIndexPath = path7.join(projectRoot, srcDir, "routes", "index.ts");
896
928
  if (await fs6.pathExists(routeIndexPath)) {
897
929
  let routeContent = await fs6.readFile(routeIndexPath, "utf-8");
898
930
  let routeModified = false;
899
- const userImportResult = appendImport(routeContent, routeIndexUserImport);
900
- if (!userImportResult.inserted) {
901
- return false;
931
+ const routeImports = provider === "jwt" ? [routeIndexAuthImport, routeIndexUserImport] : [routeIndexUserImport];
932
+ for (const importLine of routeImports) {
933
+ const next = appendImport(routeContent, importLine);
934
+ if (!next.inserted) {
935
+ return false;
936
+ }
937
+ if (next.source !== routeContent) {
938
+ routeContent = next.source;
939
+ routeModified = true;
940
+ }
902
941
  }
903
- if (userImportResult.source !== routeContent) {
904
- routeContent = userImportResult.source;
905
- routeModified = true;
942
+ if (provider === "jwt") {
943
+ const hasAuthRoute = /rootRouter\.use\(\s*["']\/auth["']\s*,\s*authRoutes\s*\)/.test(routeContent);
944
+ if (!hasAuthRoute) {
945
+ const routeSetup = `
946
+ // Auth routes
947
+ rootRouter.use("/auth", authRoutes);
948
+ `;
949
+ const exportMatch = routeContent.match(/export default rootRouter;?\s*$/m);
950
+ if (!exportMatch || exportMatch.index === void 0) {
951
+ return false;
952
+ }
953
+ routeContent = routeContent.slice(0, exportMatch.index) + routeSetup + "\n" + routeContent.slice(exportMatch.index);
954
+ routeModified = true;
955
+ }
906
956
  }
907
957
  const hasUserRoute = /rootRouter\.use\(\s*["']\/users["']\s*,\s*userRoutes\s*\)/.test(routeContent);
908
958
  if (!hasUserRoute) {
@@ -921,6 +971,29 @@ rootRouter.use("/users", userRoutes);
921
971
  await fs6.writeFile(routeIndexPath, routeContent);
922
972
  }
923
973
  } else {
974
+ if (provider === "jwt") {
975
+ const authImportResult = appendImport(appContent, appAuthImport);
976
+ if (!authImportResult.inserted) {
977
+ return false;
978
+ }
979
+ if (authImportResult.source !== appContent) {
980
+ appContent = authImportResult.source;
981
+ appModified = true;
982
+ }
983
+ const hasAuthRoute = /app\.use\(\s*["']\/api\/auth["']\s*,\s*authRoutes\s*\)/.test(appContent);
984
+ if (!hasAuthRoute) {
985
+ const exportMatch = appContent.match(/export default app;?\s*$/m);
986
+ if (!exportMatch || exportMatch.index === void 0) {
987
+ return false;
988
+ }
989
+ const routeSetup = `
990
+ // Auth routes
991
+ app.use("/api/auth", authRoutes);
992
+ `;
993
+ appContent = appContent.slice(0, exportMatch.index) + routeSetup + "\n" + appContent.slice(exportMatch.index);
994
+ appModified = true;
995
+ }
996
+ }
924
997
  const hasUserRoute = /app\.use\(\s*["']\/api\/users["']\s*,\s*userRoutes\s*\)/.test(appContent);
925
998
  if (!hasUserRoute) {
926
999
  const exportMatch = appContent.match(/export default app;?\s*$/m);
@@ -948,21 +1021,23 @@ app.use("/api/users", userRoutes);
948
1021
  }
949
1022
  return true;
950
1023
  }
951
- async function injectAuthDocs(projectRoot, srcDir) {
1024
+ async function injectAuthDocs(projectRoot, srcDir, provider) {
952
1025
  const openApiPath = path7.join(projectRoot, srcDir, "lib", "openapi.ts");
953
1026
  if (!await fs6.pathExists(openApiPath)) {
954
1027
  return false;
955
1028
  }
956
- const authMarker = "// ZURO_AUTH_DOCS";
1029
+ const betterAuthMarker = "// ZURO_AUTH_DOCS_BETTER_AUTH";
1030
+ const jwtMarker = "// ZURO_AUTH_DOCS_JWT";
1031
+ const legacyMarker = "// ZURO_AUTH_DOCS";
957
1032
  let content = await fs6.readFile(openApiPath, "utf-8");
958
- if (content.includes(authMarker)) {
1033
+ if (content.includes(betterAuthMarker) || content.includes(jwtMarker) || content.includes(legacyMarker)) {
959
1034
  return true;
960
1035
  }
961
1036
  const moduleDocsEndMarker = "// ZURO_DOCS_MODULES_END";
962
1037
  if (!content.includes(moduleDocsEndMarker)) {
963
1038
  return false;
964
1039
  }
965
- const authBlock = `
1040
+ const authBlock = provider === "jwt" ? `
966
1041
  const authSignUpSchema = z.object({
967
1042
  email: z.string().email().openapi({ example: "dev@company.com" }),
968
1043
  password: z.string().min(8).openapi({ example: "strong-password" }),
@@ -974,13 +1049,169 @@ const authSignInSchema = z.object({
974
1049
  password: z.string().min(8).openapi({ example: "strong-password" }),
975
1050
  });
976
1051
 
1052
+ const authRefreshSchema = z.object({
1053
+ refreshToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1054
+ });
1055
+
1056
+ const authTokenSchema = z.object({
1057
+ accessToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1058
+ refreshToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1059
+ tokenType: z.literal("Bearer").openapi({ example: "Bearer" }),
1060
+ });
1061
+
977
1062
  const authUserSchema = z.object({
978
1063
  id: z.string().openapi({ example: "user_123" }),
979
1064
  email: z.string().email().openapi({ example: "dev@company.com" }),
980
1065
  name: z.string().nullable().openapi({ example: "Dev User" }),
981
1066
  });
982
1067
 
983
- ${authMarker}
1068
+ ${jwtMarker}
1069
+ registry.registerPath({
1070
+ method: "post",
1071
+ path: "/api/auth/sign-up/email",
1072
+ tags: ["Auth"],
1073
+ summary: "Register user and issue JWT tokens",
1074
+ request: {
1075
+ body: {
1076
+ content: {
1077
+ "application/json": {
1078
+ schema: authSignUpSchema,
1079
+ },
1080
+ },
1081
+ },
1082
+ },
1083
+ responses: {
1084
+ 200: {
1085
+ description: "Registration successful",
1086
+ content: {
1087
+ "application/json": {
1088
+ schema: z.object({ user: authUserSchema, ...authTokenSchema.shape }),
1089
+ },
1090
+ },
1091
+ },
1092
+ 409: { description: "Email already registered" },
1093
+ },
1094
+ });
1095
+
1096
+ registry.registerPath({
1097
+ method: "post",
1098
+ path: "/api/auth/sign-in/email",
1099
+ tags: ["Auth"],
1100
+ summary: "Sign in and issue JWT tokens",
1101
+ request: {
1102
+ body: {
1103
+ content: {
1104
+ "application/json": {
1105
+ schema: authSignInSchema,
1106
+ },
1107
+ },
1108
+ },
1109
+ },
1110
+ responses: {
1111
+ 200: {
1112
+ description: "Sign in successful",
1113
+ content: {
1114
+ "application/json": {
1115
+ schema: authTokenSchema,
1116
+ },
1117
+ },
1118
+ },
1119
+ 401: { description: "Invalid credentials" },
1120
+ },
1121
+ });
1122
+
1123
+ registry.registerPath({
1124
+ method: "post",
1125
+ path: "/api/auth/refresh",
1126
+ tags: ["Auth"],
1127
+ summary: "Exchange refresh token for new JWT tokens",
1128
+ request: {
1129
+ body: {
1130
+ content: {
1131
+ "application/json": {
1132
+ schema: authRefreshSchema,
1133
+ },
1134
+ },
1135
+ },
1136
+ },
1137
+ responses: {
1138
+ 200: {
1139
+ description: "Tokens refreshed",
1140
+ content: {
1141
+ "application/json": {
1142
+ schema: authTokenSchema,
1143
+ },
1144
+ },
1145
+ },
1146
+ 401: { description: "Invalid refresh token" },
1147
+ },
1148
+ });
1149
+
1150
+ registry.registerPath({
1151
+ method: "post",
1152
+ path: "/api/auth/sign-out",
1153
+ tags: ["Auth"],
1154
+ summary: "Client-side sign out for JWT auth",
1155
+ responses: {
1156
+ 200: { description: "Sign out successful" },
1157
+ },
1158
+ });
1159
+
1160
+ registry.registerPath({
1161
+ method: "get",
1162
+ path: "/api/auth/get-session",
1163
+ tags: ["Auth"],
1164
+ summary: "Get current JWT session user",
1165
+ security: [{ bearerAuth: [] }],
1166
+ responses: {
1167
+ 200: {
1168
+ description: "Current session",
1169
+ content: {
1170
+ "application/json": {
1171
+ schema: z.object({ user: authUserSchema.nullable() }),
1172
+ },
1173
+ },
1174
+ },
1175
+ },
1176
+ });
1177
+
1178
+ registry.registerPath({
1179
+ method: "get",
1180
+ path: "/api/users/me",
1181
+ tags: ["Auth"],
1182
+ summary: "Get current authenticated user",
1183
+ security: [{ bearerAuth: [] }],
1184
+ responses: {
1185
+ 200: {
1186
+ description: "Current user",
1187
+ content: {
1188
+ "application/json": {
1189
+ schema: z.object({ user: authUserSchema }),
1190
+ },
1191
+ },
1192
+ },
1193
+ 401: { description: "Not authenticated" },
1194
+ },
1195
+ });
1196
+ ` : `
1197
+ const authSignUpSchema = z.object({
1198
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1199
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1200
+ name: z.string().min(1).optional().openapi({ example: "Dev User" }),
1201
+ });
1202
+
1203
+ const authSignInSchema = z.object({
1204
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1205
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1206
+ });
1207
+
1208
+ const authUserSchema = z.object({
1209
+ id: z.string().openapi({ example: "user_123" }),
1210
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1211
+ name: z.string().nullable().openapi({ example: "Dev User" }),
1212
+ });
1213
+
1214
+ ${betterAuthMarker}
984
1215
  registry.registerPath({
985
1216
  method: "post",
986
1217
  path: "/api/auth/sign-up/email",
@@ -1057,7 +1288,27 @@ ${moduleDocsEndMarker}`);
1057
1288
  async function promptAuthConfig(projectRoot, srcDir, options) {
1058
1289
  const { isDocsModuleInstalled: isDocsModuleInstalled2 } = await import("./docs.handler-JL3ZIVJQ.mjs");
1059
1290
  const docsInstalled = await isDocsModuleInstalled2(projectRoot, srcDir);
1291
+ let authProvider = "better-auth";
1060
1292
  let shouldInstallDocsForAuth = false;
1293
+ if (options.authProvider) {
1294
+ authProvider = options.authProvider;
1295
+ } else if (!options.yes) {
1296
+ const providerResponse = await prompts2({
1297
+ type: "select",
1298
+ name: "provider",
1299
+ message: "Choose auth provider:",
1300
+ choices: [
1301
+ { title: "Better Auth (session + plugin ecosystem)", value: "better-auth" },
1302
+ { title: "JWT (access/refresh tokens)", value: "jwt" }
1303
+ ],
1304
+ initial: 0
1305
+ });
1306
+ if (!providerResponse.provider) {
1307
+ console.log(chalk4.yellow("Operation cancelled."));
1308
+ return null;
1309
+ }
1310
+ authProvider = providerResponse.provider;
1311
+ }
1061
1312
  if (!docsInstalled) {
1062
1313
  if (options.yes) {
1063
1314
  shouldInstallDocsForAuth = true;
@@ -1077,13 +1328,19 @@ async function promptAuthConfig(projectRoot, srcDir, options) {
1077
1328
  }
1078
1329
  const { detectInstalledDatabaseDialect: detectInstalledDatabaseDialect2 } = await import("./database.handler-5OUD6XJZ.mjs");
1079
1330
  const authDatabaseDialect = await detectInstalledDatabaseDialect2(projectRoot, srcDir);
1080
- return { shouldInstallDocsForAuth, authDatabaseDialect };
1331
+ return { authProvider, shouldInstallDocsForAuth, authDatabaseDialect };
1081
1332
  }
1082
- function printAuthHints(generatedAuthSecret) {
1083
- if (generatedAuthSecret) {
1084
- console.log(chalk4.yellow("\u2139 BETTER_AUTH_SECRET was generated automatically."));
1333
+ function printAuthHints(generatedAuthSecret, provider) {
1334
+ if (provider === "better-auth") {
1335
+ if (generatedAuthSecret) {
1336
+ console.log(chalk4.yellow("\u2139 BETTER_AUTH_SECRET was generated automatically."));
1337
+ } else {
1338
+ console.log(chalk4.yellow("\u2139 Review BETTER_AUTH_SECRET and BETTER_AUTH_URL in .env."));
1339
+ }
1340
+ } else if (generatedAuthSecret) {
1341
+ console.log(chalk4.yellow("\u2139 JWT_ACCESS_SECRET and JWT_REFRESH_SECRET were generated automatically."));
1085
1342
  } else {
1086
- console.log(chalk4.yellow("\u2139 Review BETTER_AUTH_SECRET and BETTER_AUTH_URL in .env."));
1343
+ console.log(chalk4.yellow("\u2139 Review JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, and token TTLs in .env."));
1087
1344
  }
1088
1345
  console.log(chalk4.yellow("\u2139 Run migrations: npx drizzle-kit generate && npx drizzle-kit migrate"));
1089
1346
  }
@@ -1862,6 +2119,8 @@ var add = async (moduleName, options = {}) => {
1862
2119
  let selectedDatabaseDialect = null;
1863
2120
  let generatedAuthSecret = false;
1864
2121
  let authDatabaseDialect = null;
2122
+ let authProvider = options.authProvider || "better-auth";
2123
+ let uploadAuthProvider = null;
1865
2124
  let customSmtpVars;
1866
2125
  let usedDefaultSmtp = false;
1867
2126
  let mailerProvider = "smtp";
@@ -1888,6 +2147,7 @@ var add = async (moduleName, options = {}) => {
1888
2147
  if (resolvedModuleName === "auth") {
1889
2148
  const result = await promptAuthConfig(projectRoot, srcDir, options);
1890
2149
  if (!result) return;
2150
+ authProvider = result.authProvider;
1891
2151
  shouldInstallDocsForAuth = result.shouldInstallDocsForAuth;
1892
2152
  authDatabaseDialect = result.authDatabaseDialect;
1893
2153
  }
@@ -1928,6 +2188,7 @@ var add = async (moduleName, options = {}) => {
1928
2188
  await add("auth", { yes: true });
1929
2189
  }
1930
2190
  uploadDatabaseDialect = await detectInstalledDatabaseDialect(projectRoot, srcDir);
2191
+ uploadAuthProvider = await detectInstalledAuthProvider(projectRoot, srcDir);
1931
2192
  if (uploadConfig.useDatabaseMetadata) {
1932
2193
  if (uploadDatabaseDialect === "database-prisma-pg" || uploadDatabaseDialect === "database-prisma-mysql") {
1933
2194
  spinner.fail("Uploads metadata currently supports Drizzle-based database setup only.");
@@ -1962,6 +2223,15 @@ var add = async (moduleName, options = {}) => {
1962
2223
  devDeps = ["@types/nodemailer"];
1963
2224
  }
1964
2225
  }
2226
+ if (resolvedModuleName === "auth") {
2227
+ if (authProvider === "jwt") {
2228
+ runtimeDeps = ["jsonwebtoken", "bcryptjs"];
2229
+ devDeps = ["@types/jsonwebtoken", "@types/bcryptjs"];
2230
+ } else {
2231
+ runtimeDeps = ["better-auth"];
2232
+ devDeps = [];
2233
+ }
2234
+ }
1965
2235
  if (resolvedModuleName === "uploads" && uploadConfig) {
1966
2236
  runtimeDeps = ["multer"];
1967
2237
  devDeps = ["@types/multer"];
@@ -1980,11 +2250,46 @@ var add = async (moduleName, options = {}) => {
1980
2250
  let fetchPath = file.path;
1981
2251
  let expectedSha256 = file.sha256;
1982
2252
  let expectedSize = file.size;
2253
+ if (resolvedModuleName === "auth" && authProvider === "better-auth" && (file.target === "routes/auth.routes.ts" || file.target === "controllers/auth.controller.ts")) {
2254
+ continue;
2255
+ }
1983
2256
  if (resolvedModuleName === "auth" && file.target === "db/schema/auth.ts" && authDatabaseDialect === "database-mysql") {
1984
2257
  fetchPath = "express/db/schema/auth.mysql.ts";
1985
2258
  expectedSha256 = void 0;
1986
2259
  expectedSize = void 0;
1987
2260
  }
2261
+ if (resolvedModuleName === "auth" && authProvider === "jwt") {
2262
+ if (file.target === "lib/auth.ts") {
2263
+ fetchPath = "express/lib/auth.jwt.ts";
2264
+ expectedSha256 = void 0;
2265
+ expectedSize = void 0;
2266
+ }
2267
+ if (file.target === "controllers/user.controller.ts") {
2268
+ fetchPath = "express/controllers/user.controller.jwt.ts";
2269
+ expectedSha256 = void 0;
2270
+ expectedSize = void 0;
2271
+ }
2272
+ if (file.target === "routes/user.routes.ts") {
2273
+ fetchPath = "express/routes/user.routes.jwt.ts";
2274
+ expectedSha256 = void 0;
2275
+ expectedSize = void 0;
2276
+ }
2277
+ if (file.target === "controllers/auth.controller.ts") {
2278
+ fetchPath = "express/controllers/auth.controller.jwt.ts";
2279
+ expectedSha256 = void 0;
2280
+ expectedSize = void 0;
2281
+ }
2282
+ if (file.target === "routes/auth.routes.ts") {
2283
+ fetchPath = "express/routes/auth.routes.jwt.ts";
2284
+ expectedSha256 = void 0;
2285
+ expectedSize = void 0;
2286
+ }
2287
+ if (file.target === "db/schema/auth.ts") {
2288
+ fetchPath = authDatabaseDialect === "database-mysql" ? "express/db/schema/auth.mysql.jwt.ts" : "express/db/schema/auth.jwt.ts";
2289
+ expectedSha256 = void 0;
2290
+ expectedSize = void 0;
2291
+ }
2292
+ }
1988
2293
  if (resolvedModuleName === "mailer" && file.target === "lib/mailer.ts" && mailerProvider === "resend") {
1989
2294
  fetchPath = "express/lib/mailer.resend.ts";
1990
2295
  expectedSha256 = void 0;
@@ -2002,7 +2307,12 @@ var add = async (moduleName, options = {}) => {
2002
2307
  expectedSize = void 0;
2003
2308
  }
2004
2309
  if (file.target === "middleware/upload-auth.ts") {
2005
- fetchPath = `express/middleware/upload-auth.${uploadConfig.authMode}.ts`;
2310
+ if (uploadConfig.authMode === "none") {
2311
+ fetchPath = "express/middleware/upload-auth.none.ts";
2312
+ } else {
2313
+ const providerSuffix = uploadAuthProvider === "jwt" ? "jwt" : "better-auth";
2314
+ fetchPath = `express/middleware/upload-auth.required.${providerSuffix}.ts`;
2315
+ }
2006
2316
  expectedSha256 = void 0;
2007
2317
  expectedSize = void 0;
2008
2318
  }
@@ -2038,7 +2348,7 @@ var add = async (moduleName, options = {}) => {
2038
2348
  spinner.succeed("Files generated");
2039
2349
  if (resolvedModuleName === "auth") {
2040
2350
  spinner.start("Configuring routes...");
2041
- const injected = await injectAuthRoutes(projectRoot, srcDir);
2351
+ const injected = await injectAuthRoutes(projectRoot, srcDir, authProvider);
2042
2352
  if (injected) {
2043
2353
  spinner.succeed("Routes configured");
2044
2354
  } else {
@@ -2047,7 +2357,7 @@ var add = async (moduleName, options = {}) => {
2047
2357
  const docsInstalled = await isDocsModuleInstalled(projectRoot, srcDir);
2048
2358
  if (docsInstalled) {
2049
2359
  spinner.start("Adding auth endpoints to API docs...");
2050
- const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
2360
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir, authProvider);
2051
2361
  if (authDocsInjected) {
2052
2362
  spinner.succeed("Auth endpoints added to API docs");
2053
2363
  } else {
@@ -2083,8 +2393,9 @@ var add = async (moduleName, options = {}) => {
2083
2393
  }
2084
2394
  const authInstalled = await isAuthModuleInstalled(projectRoot, srcDir);
2085
2395
  if (authInstalled) {
2396
+ const installedAuthProvider = await detectInstalledAuthProvider(projectRoot, srcDir) || "better-auth";
2086
2397
  spinner.start("Adding auth endpoints to API docs...");
2087
- const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
2398
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir, installedAuthProvider);
2088
2399
  if (authDocsInjected) {
2089
2400
  spinner.succeed("Auth endpoints added to API docs");
2090
2401
  } else {
@@ -2128,6 +2439,9 @@ var add = async (moduleName, options = {}) => {
2128
2439
  if (resolvedModuleName === "mailer" && mailerProvider === "resend") {
2129
2440
  envConfigKey = "mailer-resend";
2130
2441
  }
2442
+ if (resolvedModuleName === "auth" && authProvider === "jwt") {
2443
+ envConfigKey = "auth-jwt";
2444
+ }
2131
2445
  const envConfig = ENV_CONFIGS[envConfigKey];
2132
2446
  if (envConfig) {
2133
2447
  currentStep = "environment configuration";
@@ -2140,10 +2454,23 @@ var add = async (moduleName, options = {}) => {
2140
2454
  Object.assign(envVars, customSmtpVars);
2141
2455
  }
2142
2456
  if (resolvedModuleName === "auth") {
2143
- const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
2144
- if (!hasExistingSecret) {
2145
- envVars.BETTER_AUTH_SECRET = randomBytes(32).toString("hex");
2146
- generatedAuthSecret = true;
2457
+ if (authProvider === "better-auth") {
2458
+ const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
2459
+ if (!hasExistingSecret) {
2460
+ envVars.BETTER_AUTH_SECRET = randomBytes(32).toString("hex");
2461
+ generatedAuthSecret = true;
2462
+ }
2463
+ } else {
2464
+ const hasAccessSecret = await hasEnvVariable(projectRoot, "JWT_ACCESS_SECRET");
2465
+ if (!hasAccessSecret) {
2466
+ envVars.JWT_ACCESS_SECRET = randomBytes(32).toString("hex");
2467
+ generatedAuthSecret = true;
2468
+ }
2469
+ const hasRefreshSecret = await hasEnvVariable(projectRoot, "JWT_REFRESH_SECRET");
2470
+ if (!hasRefreshSecret) {
2471
+ envVars.JWT_REFRESH_SECRET = randomBytes(32).toString("hex");
2472
+ generatedAuthSecret = true;
2473
+ }
2147
2474
  }
2148
2475
  }
2149
2476
  await updateEnvFile(projectRoot, envVars, true, {
@@ -2184,7 +2511,7 @@ var add = async (moduleName, options = {}) => {
2184
2511
  printDatabaseHints(resolvedModuleName, customDbUrl, usedDefaultDbUrl, databaseBackupPath);
2185
2512
  }
2186
2513
  if (resolvedModuleName === "auth") {
2187
- printAuthHints(generatedAuthSecret);
2514
+ printAuthHints(generatedAuthSecret, authProvider);
2188
2515
  }
2189
2516
  if (resolvedModuleName === "mailer") {
2190
2517
  printMailerHints(usedDefaultSmtp);
@@ -2213,6 +2540,15 @@ ${chalk7.bold("Retry:")}`);
2213
2540
  var program = new Command();
2214
2541
  program.name("zuro-cli").description("Zuro CLI tool").version("0.0.1");
2215
2542
  program.command("init").description("Initialize a new Zuro project").action(init);
2216
- program.command("add <module>").description("Add a module to your project").action((module, options) => add(module, options));
2543
+ program.command("add <module>").description("Add a module to your project").option(
2544
+ "--auth-provider <provider>",
2545
+ "Auth provider for auth module (better-auth|jwt)",
2546
+ (value) => {
2547
+ if (value === "better-auth" || value === "jwt") {
2548
+ return value;
2549
+ }
2550
+ throw new InvalidArgumentError("auth-provider must be 'better-auth' or 'jwt'");
2551
+ }
2552
+ ).option("-y, --yes", "Skip prompts and use defaults").action((module, options) => add(module, options));
2217
2553
  program.parse(process.argv);
2218
2554
  //# sourceMappingURL=index.mjs.map