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.js CHANGED
@@ -825,6 +825,20 @@ var ENV_CONFIGS = {
825
825
  { name: "BETTER_AUTH_URL", schema: "z.string().url()" }
826
826
  ]
827
827
  },
828
+ "auth-jwt": {
829
+ envVars: {
830
+ JWT_ACCESS_SECRET: "your-jwt-access-secret-at-least-32-characters",
831
+ JWT_REFRESH_SECRET: "your-jwt-refresh-secret-at-least-32-characters",
832
+ JWT_ACCESS_EXPIRES_IN: "15m",
833
+ JWT_REFRESH_EXPIRES_IN: "7d"
834
+ },
835
+ schemaFields: [
836
+ { name: "JWT_ACCESS_SECRET", schema: "z.string().min(32)" },
837
+ { name: "JWT_REFRESH_SECRET", schema: "z.string().min(32)" },
838
+ { name: "JWT_ACCESS_EXPIRES_IN", schema: "z.string().min(2)" },
839
+ { name: "JWT_REFRESH_EXPIRES_IN", schema: "z.string().min(2)" }
840
+ ]
841
+ },
828
842
  mailer: {
829
843
  envVars: {
830
844
  SMTP_HOST: "smtp.example.com",
@@ -1309,57 +1323,93 @@ init_code_inject();
1309
1323
  async function isAuthModuleInstalled(projectRoot, srcDir) {
1310
1324
  return await import_fs_extra8.default.pathExists(import_path9.default.join(projectRoot, srcDir, "lib", "auth.ts"));
1311
1325
  }
1312
- async function injectAuthRoutes(projectRoot, srcDir) {
1326
+ async function detectInstalledAuthProvider(projectRoot, srcDir) {
1327
+ const authPath = import_path9.default.join(projectRoot, srcDir, "lib", "auth.ts");
1328
+ if (!await import_fs_extra8.default.pathExists(authPath)) {
1329
+ return null;
1330
+ }
1331
+ const authContent = await import_fs_extra8.default.readFile(authPath, "utf-8");
1332
+ if (authContent.includes("better-auth")) {
1333
+ return "better-auth";
1334
+ }
1335
+ if (authContent.includes("jsonwebtoken") || authContent.includes("JWT_ACCESS_SECRET")) {
1336
+ return "jwt";
1337
+ }
1338
+ return null;
1339
+ }
1340
+ async function injectAuthRoutes(projectRoot, srcDir, provider) {
1313
1341
  const appPath = import_path9.default.join(projectRoot, srcDir, "app.ts");
1314
1342
  if (!await import_fs_extra8.default.pathExists(appPath)) {
1315
1343
  return false;
1316
1344
  }
1317
1345
  let appContent = await import_fs_extra8.default.readFile(appPath, "utf-8");
1318
- const authHandlerImport = `import { toNodeHandler } from "better-auth/node";`;
1319
- const authImport = `import { auth } from "./lib/auth";`;
1320
1346
  const routeIndexUserImport = `import userRoutes from "./user.routes";`;
1347
+ const routeIndexAuthImport = `import authRoutes from "./auth.routes";`;
1321
1348
  const appUserImport = `import userRoutes from "./routes/user.routes";`;
1349
+ const appAuthImport = `import authRoutes from "./routes/auth.routes";`;
1322
1350
  let appModified = false;
1323
- for (const importLine of [authHandlerImport, authImport]) {
1324
- const next = appendImport(appContent, importLine);
1325
- if (!next.inserted) {
1326
- return false;
1351
+ if (provider === "better-auth") {
1352
+ const authHandlerImport = `import { toNodeHandler } from "better-auth/node";`;
1353
+ const authImport = `import { auth } from "./lib/auth";`;
1354
+ for (const importLine of [authHandlerImport, authImport]) {
1355
+ const next = appendImport(appContent, importLine);
1356
+ if (!next.inserted) {
1357
+ return false;
1358
+ }
1359
+ if (next.source !== appContent) {
1360
+ appContent = next.source;
1361
+ appModified = true;
1362
+ }
1327
1363
  }
1328
- if (next.source !== appContent) {
1329
- appContent = next.source;
1364
+ const hasAuthMount = /toNodeHandler\(\s*auth\s*\)/.test(appContent) && /\/api\/auth/.test(appContent);
1365
+ if (!hasAuthMount) {
1366
+ const authMountLine = "app.all(/^\\/api\\/auth(?:\\/.*)?$/, toNodeHandler(auth));\n";
1367
+ const jsonIndex = appContent.search(/^\s*app\.use\(\s*express\.json\(\)\s*\);\s*$/m);
1368
+ let insertionIndex = jsonIndex;
1369
+ if (insertionIndex < 0) {
1370
+ const healthIndex = appContent.search(/^\s*app\.get\(\s*["']\/health["']\s*,/m);
1371
+ insertionIndex = healthIndex;
1372
+ }
1373
+ if (insertionIndex < 0) {
1374
+ const exportMatch = appContent.match(/export default app;?\s*$/m);
1375
+ insertionIndex = exportMatch?.index ?? -1;
1376
+ }
1377
+ if (insertionIndex < 0) {
1378
+ return false;
1379
+ }
1380
+ appContent = appContent.slice(0, insertionIndex) + authMountLine + appContent.slice(insertionIndex);
1330
1381
  appModified = true;
1331
1382
  }
1332
1383
  }
1333
- const hasAuthMount = /toNodeHandler\(\s*auth\s*\)/.test(appContent) && /\/api\/auth/.test(appContent);
1334
- if (!hasAuthMount) {
1335
- const authMountLine = "app.all(/^\\/api\\/auth(?:\\/.*)?$/, toNodeHandler(auth));\n";
1336
- const jsonIndex = appContent.search(/^\s*app\.use\(\s*express\.json\(\)\s*\);\s*$/m);
1337
- let insertionIndex = jsonIndex;
1338
- if (insertionIndex < 0) {
1339
- const healthIndex = appContent.search(/^\s*app\.get\(\s*["']\/health["']\s*,/m);
1340
- insertionIndex = healthIndex;
1341
- }
1342
- if (insertionIndex < 0) {
1343
- const exportMatch = appContent.match(/export default app;?\s*$/m);
1344
- insertionIndex = exportMatch?.index ?? -1;
1345
- }
1346
- if (insertionIndex < 0) {
1347
- return false;
1348
- }
1349
- appContent = appContent.slice(0, insertionIndex) + authMountLine + appContent.slice(insertionIndex);
1350
- appModified = true;
1351
- }
1352
1384
  const routeIndexPath = import_path9.default.join(projectRoot, srcDir, "routes", "index.ts");
1353
1385
  if (await import_fs_extra8.default.pathExists(routeIndexPath)) {
1354
1386
  let routeContent = await import_fs_extra8.default.readFile(routeIndexPath, "utf-8");
1355
1387
  let routeModified = false;
1356
- const userImportResult = appendImport(routeContent, routeIndexUserImport);
1357
- if (!userImportResult.inserted) {
1358
- return false;
1388
+ const routeImports = provider === "jwt" ? [routeIndexAuthImport, routeIndexUserImport] : [routeIndexUserImport];
1389
+ for (const importLine of routeImports) {
1390
+ const next = appendImport(routeContent, importLine);
1391
+ if (!next.inserted) {
1392
+ return false;
1393
+ }
1394
+ if (next.source !== routeContent) {
1395
+ routeContent = next.source;
1396
+ routeModified = true;
1397
+ }
1359
1398
  }
1360
- if (userImportResult.source !== routeContent) {
1361
- routeContent = userImportResult.source;
1362
- routeModified = true;
1399
+ if (provider === "jwt") {
1400
+ const hasAuthRoute = /rootRouter\.use\(\s*["']\/auth["']\s*,\s*authRoutes\s*\)/.test(routeContent);
1401
+ if (!hasAuthRoute) {
1402
+ const routeSetup = `
1403
+ // Auth routes
1404
+ rootRouter.use("/auth", authRoutes);
1405
+ `;
1406
+ const exportMatch = routeContent.match(/export default rootRouter;?\s*$/m);
1407
+ if (!exportMatch || exportMatch.index === void 0) {
1408
+ return false;
1409
+ }
1410
+ routeContent = routeContent.slice(0, exportMatch.index) + routeSetup + "\n" + routeContent.slice(exportMatch.index);
1411
+ routeModified = true;
1412
+ }
1363
1413
  }
1364
1414
  const hasUserRoute = /rootRouter\.use\(\s*["']\/users["']\s*,\s*userRoutes\s*\)/.test(routeContent);
1365
1415
  if (!hasUserRoute) {
@@ -1378,6 +1428,29 @@ rootRouter.use("/users", userRoutes);
1378
1428
  await import_fs_extra8.default.writeFile(routeIndexPath, routeContent);
1379
1429
  }
1380
1430
  } else {
1431
+ if (provider === "jwt") {
1432
+ const authImportResult = appendImport(appContent, appAuthImport);
1433
+ if (!authImportResult.inserted) {
1434
+ return false;
1435
+ }
1436
+ if (authImportResult.source !== appContent) {
1437
+ appContent = authImportResult.source;
1438
+ appModified = true;
1439
+ }
1440
+ const hasAuthRoute = /app\.use\(\s*["']\/api\/auth["']\s*,\s*authRoutes\s*\)/.test(appContent);
1441
+ if (!hasAuthRoute) {
1442
+ const exportMatch = appContent.match(/export default app;?\s*$/m);
1443
+ if (!exportMatch || exportMatch.index === void 0) {
1444
+ return false;
1445
+ }
1446
+ const routeSetup = `
1447
+ // Auth routes
1448
+ app.use("/api/auth", authRoutes);
1449
+ `;
1450
+ appContent = appContent.slice(0, exportMatch.index) + routeSetup + "\n" + appContent.slice(exportMatch.index);
1451
+ appModified = true;
1452
+ }
1453
+ }
1381
1454
  const hasUserRoute = /app\.use\(\s*["']\/api\/users["']\s*,\s*userRoutes\s*\)/.test(appContent);
1382
1455
  if (!hasUserRoute) {
1383
1456
  const exportMatch = appContent.match(/export default app;?\s*$/m);
@@ -1405,21 +1478,179 @@ app.use("/api/users", userRoutes);
1405
1478
  }
1406
1479
  return true;
1407
1480
  }
1408
- async function injectAuthDocs(projectRoot, srcDir) {
1481
+ async function injectAuthDocs(projectRoot, srcDir, provider) {
1409
1482
  const openApiPath = import_path9.default.join(projectRoot, srcDir, "lib", "openapi.ts");
1410
1483
  if (!await import_fs_extra8.default.pathExists(openApiPath)) {
1411
1484
  return false;
1412
1485
  }
1413
- const authMarker = "// ZURO_AUTH_DOCS";
1486
+ const betterAuthMarker = "// ZURO_AUTH_DOCS_BETTER_AUTH";
1487
+ const jwtMarker = "// ZURO_AUTH_DOCS_JWT";
1488
+ const legacyMarker = "// ZURO_AUTH_DOCS";
1414
1489
  let content = await import_fs_extra8.default.readFile(openApiPath, "utf-8");
1415
- if (content.includes(authMarker)) {
1490
+ if (content.includes(betterAuthMarker) || content.includes(jwtMarker) || content.includes(legacyMarker)) {
1416
1491
  return true;
1417
1492
  }
1418
1493
  const moduleDocsEndMarker = "// ZURO_DOCS_MODULES_END";
1419
1494
  if (!content.includes(moduleDocsEndMarker)) {
1420
1495
  return false;
1421
1496
  }
1422
- const authBlock = `
1497
+ const authBlock = provider === "jwt" ? `
1498
+ const authSignUpSchema = z.object({
1499
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1500
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1501
+ name: z.string().min(1).optional().openapi({ example: "Dev User" }),
1502
+ });
1503
+
1504
+ const authSignInSchema = z.object({
1505
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1506
+ password: z.string().min(8).openapi({ example: "strong-password" }),
1507
+ });
1508
+
1509
+ const authRefreshSchema = z.object({
1510
+ refreshToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1511
+ });
1512
+
1513
+ const authTokenSchema = z.object({
1514
+ accessToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1515
+ refreshToken: z.string().openapi({ example: "eyJhbGciOi..." }),
1516
+ tokenType: z.literal("Bearer").openapi({ example: "Bearer" }),
1517
+ });
1518
+
1519
+ const authUserSchema = z.object({
1520
+ id: z.string().openapi({ example: "user_123" }),
1521
+ email: z.string().email().openapi({ example: "dev@company.com" }),
1522
+ name: z.string().nullable().openapi({ example: "Dev User" }),
1523
+ });
1524
+
1525
+ ${jwtMarker}
1526
+ registry.registerPath({
1527
+ method: "post",
1528
+ path: "/api/auth/sign-up/email",
1529
+ tags: ["Auth"],
1530
+ summary: "Register user and issue JWT tokens",
1531
+ request: {
1532
+ body: {
1533
+ content: {
1534
+ "application/json": {
1535
+ schema: authSignUpSchema,
1536
+ },
1537
+ },
1538
+ },
1539
+ },
1540
+ responses: {
1541
+ 200: {
1542
+ description: "Registration successful",
1543
+ content: {
1544
+ "application/json": {
1545
+ schema: z.object({ user: authUserSchema, ...authTokenSchema.shape }),
1546
+ },
1547
+ },
1548
+ },
1549
+ 409: { description: "Email already registered" },
1550
+ },
1551
+ });
1552
+
1553
+ registry.registerPath({
1554
+ method: "post",
1555
+ path: "/api/auth/sign-in/email",
1556
+ tags: ["Auth"],
1557
+ summary: "Sign in and issue JWT tokens",
1558
+ request: {
1559
+ body: {
1560
+ content: {
1561
+ "application/json": {
1562
+ schema: authSignInSchema,
1563
+ },
1564
+ },
1565
+ },
1566
+ },
1567
+ responses: {
1568
+ 200: {
1569
+ description: "Sign in successful",
1570
+ content: {
1571
+ "application/json": {
1572
+ schema: authTokenSchema,
1573
+ },
1574
+ },
1575
+ },
1576
+ 401: { description: "Invalid credentials" },
1577
+ },
1578
+ });
1579
+
1580
+ registry.registerPath({
1581
+ method: "post",
1582
+ path: "/api/auth/refresh",
1583
+ tags: ["Auth"],
1584
+ summary: "Exchange refresh token for new JWT tokens",
1585
+ request: {
1586
+ body: {
1587
+ content: {
1588
+ "application/json": {
1589
+ schema: authRefreshSchema,
1590
+ },
1591
+ },
1592
+ },
1593
+ },
1594
+ responses: {
1595
+ 200: {
1596
+ description: "Tokens refreshed",
1597
+ content: {
1598
+ "application/json": {
1599
+ schema: authTokenSchema,
1600
+ },
1601
+ },
1602
+ },
1603
+ 401: { description: "Invalid refresh token" },
1604
+ },
1605
+ });
1606
+
1607
+ registry.registerPath({
1608
+ method: "post",
1609
+ path: "/api/auth/sign-out",
1610
+ tags: ["Auth"],
1611
+ summary: "Client-side sign out for JWT auth",
1612
+ responses: {
1613
+ 200: { description: "Sign out successful" },
1614
+ },
1615
+ });
1616
+
1617
+ registry.registerPath({
1618
+ method: "get",
1619
+ path: "/api/auth/get-session",
1620
+ tags: ["Auth"],
1621
+ summary: "Get current JWT session user",
1622
+ security: [{ bearerAuth: [] }],
1623
+ responses: {
1624
+ 200: {
1625
+ description: "Current session",
1626
+ content: {
1627
+ "application/json": {
1628
+ schema: z.object({ user: authUserSchema.nullable() }),
1629
+ },
1630
+ },
1631
+ },
1632
+ },
1633
+ });
1634
+
1635
+ registry.registerPath({
1636
+ method: "get",
1637
+ path: "/api/users/me",
1638
+ tags: ["Auth"],
1639
+ summary: "Get current authenticated user",
1640
+ security: [{ bearerAuth: [] }],
1641
+ responses: {
1642
+ 200: {
1643
+ description: "Current user",
1644
+ content: {
1645
+ "application/json": {
1646
+ schema: z.object({ user: authUserSchema }),
1647
+ },
1648
+ },
1649
+ },
1650
+ 401: { description: "Not authenticated" },
1651
+ },
1652
+ });
1653
+ ` : `
1423
1654
  const authSignUpSchema = z.object({
1424
1655
  email: z.string().email().openapi({ example: "dev@company.com" }),
1425
1656
  password: z.string().min(8).openapi({ example: "strong-password" }),
@@ -1437,7 +1668,7 @@ const authUserSchema = z.object({
1437
1668
  name: z.string().nullable().openapi({ example: "Dev User" }),
1438
1669
  });
1439
1670
 
1440
- ${authMarker}
1671
+ ${betterAuthMarker}
1441
1672
  registry.registerPath({
1442
1673
  method: "post",
1443
1674
  path: "/api/auth/sign-up/email",
@@ -1514,7 +1745,27 @@ ${moduleDocsEndMarker}`);
1514
1745
  async function promptAuthConfig(projectRoot, srcDir, options) {
1515
1746
  const { isDocsModuleInstalled: isDocsModuleInstalled2 } = await Promise.resolve().then(() => (init_docs_handler(), docs_handler_exports));
1516
1747
  const docsInstalled = await isDocsModuleInstalled2(projectRoot, srcDir);
1748
+ let authProvider = "better-auth";
1517
1749
  let shouldInstallDocsForAuth = false;
1750
+ if (options.authProvider) {
1751
+ authProvider = options.authProvider;
1752
+ } else if (!options.yes) {
1753
+ const providerResponse = await (0, import_prompts3.default)({
1754
+ type: "select",
1755
+ name: "provider",
1756
+ message: "Choose auth provider:",
1757
+ choices: [
1758
+ { title: "Better Auth (session + plugin ecosystem)", value: "better-auth" },
1759
+ { title: "JWT (access/refresh tokens)", value: "jwt" }
1760
+ ],
1761
+ initial: 0
1762
+ });
1763
+ if (!providerResponse.provider) {
1764
+ console.log(import_chalk5.default.yellow("Operation cancelled."));
1765
+ return null;
1766
+ }
1767
+ authProvider = providerResponse.provider;
1768
+ }
1518
1769
  if (!docsInstalled) {
1519
1770
  if (options.yes) {
1520
1771
  shouldInstallDocsForAuth = true;
@@ -1534,13 +1785,19 @@ async function promptAuthConfig(projectRoot, srcDir, options) {
1534
1785
  }
1535
1786
  const { detectInstalledDatabaseDialect: detectInstalledDatabaseDialect2 } = await Promise.resolve().then(() => (init_database_handler(), database_handler_exports));
1536
1787
  const authDatabaseDialect = await detectInstalledDatabaseDialect2(projectRoot, srcDir);
1537
- return { shouldInstallDocsForAuth, authDatabaseDialect };
1788
+ return { authProvider, shouldInstallDocsForAuth, authDatabaseDialect };
1538
1789
  }
1539
- function printAuthHints(generatedAuthSecret) {
1540
- if (generatedAuthSecret) {
1541
- console.log(import_chalk5.default.yellow("\u2139 BETTER_AUTH_SECRET was generated automatically."));
1790
+ function printAuthHints(generatedAuthSecret, provider) {
1791
+ if (provider === "better-auth") {
1792
+ if (generatedAuthSecret) {
1793
+ console.log(import_chalk5.default.yellow("\u2139 BETTER_AUTH_SECRET was generated automatically."));
1794
+ } else {
1795
+ console.log(import_chalk5.default.yellow("\u2139 Review BETTER_AUTH_SECRET and BETTER_AUTH_URL in .env."));
1796
+ }
1797
+ } else if (generatedAuthSecret) {
1798
+ console.log(import_chalk5.default.yellow("\u2139 JWT_ACCESS_SECRET and JWT_REFRESH_SECRET were generated automatically."));
1542
1799
  } else {
1543
- console.log(import_chalk5.default.yellow("\u2139 Review BETTER_AUTH_SECRET and BETTER_AUTH_URL in .env."));
1800
+ console.log(import_chalk5.default.yellow("\u2139 Review JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, and token TTLs in .env."));
1544
1801
  }
1545
1802
  console.log(import_chalk5.default.yellow("\u2139 Run migrations: npx drizzle-kit generate && npx drizzle-kit migrate"));
1546
1803
  }
@@ -2323,6 +2580,8 @@ var add = async (moduleName, options = {}) => {
2323
2580
  let selectedDatabaseDialect = null;
2324
2581
  let generatedAuthSecret = false;
2325
2582
  let authDatabaseDialect = null;
2583
+ let authProvider = options.authProvider || "better-auth";
2584
+ let uploadAuthProvider = null;
2326
2585
  let customSmtpVars;
2327
2586
  let usedDefaultSmtp = false;
2328
2587
  let mailerProvider = "smtp";
@@ -2349,6 +2608,7 @@ var add = async (moduleName, options = {}) => {
2349
2608
  if (resolvedModuleName === "auth") {
2350
2609
  const result = await promptAuthConfig(projectRoot, srcDir, options);
2351
2610
  if (!result) return;
2611
+ authProvider = result.authProvider;
2352
2612
  shouldInstallDocsForAuth = result.shouldInstallDocsForAuth;
2353
2613
  authDatabaseDialect = result.authDatabaseDialect;
2354
2614
  }
@@ -2389,6 +2649,7 @@ var add = async (moduleName, options = {}) => {
2389
2649
  await add("auth", { yes: true });
2390
2650
  }
2391
2651
  uploadDatabaseDialect = await detectInstalledDatabaseDialect(projectRoot, srcDir);
2652
+ uploadAuthProvider = await detectInstalledAuthProvider(projectRoot, srcDir);
2392
2653
  if (uploadConfig.useDatabaseMetadata) {
2393
2654
  if (uploadDatabaseDialect === "database-prisma-pg" || uploadDatabaseDialect === "database-prisma-mysql") {
2394
2655
  spinner.fail("Uploads metadata currently supports Drizzle-based database setup only.");
@@ -2423,6 +2684,15 @@ var add = async (moduleName, options = {}) => {
2423
2684
  devDeps = ["@types/nodemailer"];
2424
2685
  }
2425
2686
  }
2687
+ if (resolvedModuleName === "auth") {
2688
+ if (authProvider === "jwt") {
2689
+ runtimeDeps = ["jsonwebtoken", "bcryptjs"];
2690
+ devDeps = ["@types/jsonwebtoken", "@types/bcryptjs"];
2691
+ } else {
2692
+ runtimeDeps = ["better-auth"];
2693
+ devDeps = [];
2694
+ }
2695
+ }
2426
2696
  if (resolvedModuleName === "uploads" && uploadConfig) {
2427
2697
  runtimeDeps = ["multer"];
2428
2698
  devDeps = ["@types/multer"];
@@ -2441,11 +2711,46 @@ var add = async (moduleName, options = {}) => {
2441
2711
  let fetchPath = file.path;
2442
2712
  let expectedSha256 = file.sha256;
2443
2713
  let expectedSize = file.size;
2714
+ if (resolvedModuleName === "auth" && authProvider === "better-auth" && (file.target === "routes/auth.routes.ts" || file.target === "controllers/auth.controller.ts")) {
2715
+ continue;
2716
+ }
2444
2717
  if (resolvedModuleName === "auth" && file.target === "db/schema/auth.ts" && authDatabaseDialect === "database-mysql") {
2445
2718
  fetchPath = "express/db/schema/auth.mysql.ts";
2446
2719
  expectedSha256 = void 0;
2447
2720
  expectedSize = void 0;
2448
2721
  }
2722
+ if (resolvedModuleName === "auth" && authProvider === "jwt") {
2723
+ if (file.target === "lib/auth.ts") {
2724
+ fetchPath = "express/lib/auth.jwt.ts";
2725
+ expectedSha256 = void 0;
2726
+ expectedSize = void 0;
2727
+ }
2728
+ if (file.target === "controllers/user.controller.ts") {
2729
+ fetchPath = "express/controllers/user.controller.jwt.ts";
2730
+ expectedSha256 = void 0;
2731
+ expectedSize = void 0;
2732
+ }
2733
+ if (file.target === "routes/user.routes.ts") {
2734
+ fetchPath = "express/routes/user.routes.jwt.ts";
2735
+ expectedSha256 = void 0;
2736
+ expectedSize = void 0;
2737
+ }
2738
+ if (file.target === "controllers/auth.controller.ts") {
2739
+ fetchPath = "express/controllers/auth.controller.jwt.ts";
2740
+ expectedSha256 = void 0;
2741
+ expectedSize = void 0;
2742
+ }
2743
+ if (file.target === "routes/auth.routes.ts") {
2744
+ fetchPath = "express/routes/auth.routes.jwt.ts";
2745
+ expectedSha256 = void 0;
2746
+ expectedSize = void 0;
2747
+ }
2748
+ if (file.target === "db/schema/auth.ts") {
2749
+ fetchPath = authDatabaseDialect === "database-mysql" ? "express/db/schema/auth.mysql.jwt.ts" : "express/db/schema/auth.jwt.ts";
2750
+ expectedSha256 = void 0;
2751
+ expectedSize = void 0;
2752
+ }
2753
+ }
2449
2754
  if (resolvedModuleName === "mailer" && file.target === "lib/mailer.ts" && mailerProvider === "resend") {
2450
2755
  fetchPath = "express/lib/mailer.resend.ts";
2451
2756
  expectedSha256 = void 0;
@@ -2463,7 +2768,12 @@ var add = async (moduleName, options = {}) => {
2463
2768
  expectedSize = void 0;
2464
2769
  }
2465
2770
  if (file.target === "middleware/upload-auth.ts") {
2466
- fetchPath = `express/middleware/upload-auth.${uploadConfig.authMode}.ts`;
2771
+ if (uploadConfig.authMode === "none") {
2772
+ fetchPath = "express/middleware/upload-auth.none.ts";
2773
+ } else {
2774
+ const providerSuffix = uploadAuthProvider === "jwt" ? "jwt" : "better-auth";
2775
+ fetchPath = `express/middleware/upload-auth.required.${providerSuffix}.ts`;
2776
+ }
2467
2777
  expectedSha256 = void 0;
2468
2778
  expectedSize = void 0;
2469
2779
  }
@@ -2499,7 +2809,7 @@ var add = async (moduleName, options = {}) => {
2499
2809
  spinner.succeed("Files generated");
2500
2810
  if (resolvedModuleName === "auth") {
2501
2811
  spinner.start("Configuring routes...");
2502
- const injected = await injectAuthRoutes(projectRoot, srcDir);
2812
+ const injected = await injectAuthRoutes(projectRoot, srcDir, authProvider);
2503
2813
  if (injected) {
2504
2814
  spinner.succeed("Routes configured");
2505
2815
  } else {
@@ -2508,7 +2818,7 @@ var add = async (moduleName, options = {}) => {
2508
2818
  const docsInstalled = await isDocsModuleInstalled(projectRoot, srcDir);
2509
2819
  if (docsInstalled) {
2510
2820
  spinner.start("Adding auth endpoints to API docs...");
2511
- const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
2821
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir, authProvider);
2512
2822
  if (authDocsInjected) {
2513
2823
  spinner.succeed("Auth endpoints added to API docs");
2514
2824
  } else {
@@ -2544,8 +2854,9 @@ var add = async (moduleName, options = {}) => {
2544
2854
  }
2545
2855
  const authInstalled = await isAuthModuleInstalled(projectRoot, srcDir);
2546
2856
  if (authInstalled) {
2857
+ const installedAuthProvider = await detectInstalledAuthProvider(projectRoot, srcDir) || "better-auth";
2547
2858
  spinner.start("Adding auth endpoints to API docs...");
2548
- const authDocsInjected = await injectAuthDocs(projectRoot, srcDir);
2859
+ const authDocsInjected = await injectAuthDocs(projectRoot, srcDir, installedAuthProvider);
2549
2860
  if (authDocsInjected) {
2550
2861
  spinner.succeed("Auth endpoints added to API docs");
2551
2862
  } else {
@@ -2589,6 +2900,9 @@ var add = async (moduleName, options = {}) => {
2589
2900
  if (resolvedModuleName === "mailer" && mailerProvider === "resend") {
2590
2901
  envConfigKey = "mailer-resend";
2591
2902
  }
2903
+ if (resolvedModuleName === "auth" && authProvider === "jwt") {
2904
+ envConfigKey = "auth-jwt";
2905
+ }
2592
2906
  const envConfig = ENV_CONFIGS[envConfigKey];
2593
2907
  if (envConfig) {
2594
2908
  currentStep = "environment configuration";
@@ -2601,10 +2915,23 @@ var add = async (moduleName, options = {}) => {
2601
2915
  Object.assign(envVars, customSmtpVars);
2602
2916
  }
2603
2917
  if (resolvedModuleName === "auth") {
2604
- const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
2605
- if (!hasExistingSecret) {
2606
- envVars.BETTER_AUTH_SECRET = (0, import_node_crypto2.randomBytes)(32).toString("hex");
2607
- generatedAuthSecret = true;
2918
+ if (authProvider === "better-auth") {
2919
+ const hasExistingSecret = await hasEnvVariable(projectRoot, "BETTER_AUTH_SECRET");
2920
+ if (!hasExistingSecret) {
2921
+ envVars.BETTER_AUTH_SECRET = (0, import_node_crypto2.randomBytes)(32).toString("hex");
2922
+ generatedAuthSecret = true;
2923
+ }
2924
+ } else {
2925
+ const hasAccessSecret = await hasEnvVariable(projectRoot, "JWT_ACCESS_SECRET");
2926
+ if (!hasAccessSecret) {
2927
+ envVars.JWT_ACCESS_SECRET = (0, import_node_crypto2.randomBytes)(32).toString("hex");
2928
+ generatedAuthSecret = true;
2929
+ }
2930
+ const hasRefreshSecret = await hasEnvVariable(projectRoot, "JWT_REFRESH_SECRET");
2931
+ if (!hasRefreshSecret) {
2932
+ envVars.JWT_REFRESH_SECRET = (0, import_node_crypto2.randomBytes)(32).toString("hex");
2933
+ generatedAuthSecret = true;
2934
+ }
2608
2935
  }
2609
2936
  }
2610
2937
  await updateEnvFile(projectRoot, envVars, true, {
@@ -2645,7 +2972,7 @@ var add = async (moduleName, options = {}) => {
2645
2972
  printDatabaseHints(resolvedModuleName, customDbUrl, usedDefaultDbUrl, databaseBackupPath);
2646
2973
  }
2647
2974
  if (resolvedModuleName === "auth") {
2648
- printAuthHints(generatedAuthSecret);
2975
+ printAuthHints(generatedAuthSecret, authProvider);
2649
2976
  }
2650
2977
  if (resolvedModuleName === "mailer") {
2651
2978
  printMailerHints(usedDefaultSmtp);
@@ -2674,6 +3001,15 @@ ${import_chalk8.default.bold("Retry:")}`);
2674
3001
  var program = new import_commander.Command();
2675
3002
  program.name("zuro-cli").description("Zuro CLI tool").version("0.0.1");
2676
3003
  program.command("init").description("Initialize a new Zuro project").action(init);
2677
- program.command("add <module>").description("Add a module to your project").action((module2, options) => add(module2, options));
3004
+ program.command("add <module>").description("Add a module to your project").option(
3005
+ "--auth-provider <provider>",
3006
+ "Auth provider for auth module (better-auth|jwt)",
3007
+ (value) => {
3008
+ if (value === "better-auth" || value === "jwt") {
3009
+ return value;
3010
+ }
3011
+ throw new import_commander.InvalidArgumentError("auth-provider must be 'better-auth' or 'jwt'");
3012
+ }
3013
+ ).option("-y, --yes", "Skip prompts and use defaults").action((module2, options) => add(module2, options));
2678
3014
  program.parse(process.argv);
2679
3015
  //# sourceMappingURL=index.js.map