@alinsafawi/aegis-auth 0.2.2 → 0.2.4

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/index.js +594 -211
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2126,20 +2126,20 @@ var require_range = __commonJS({
2126
2126
  };
2127
2127
  var replaceTilde = (comp, options) => {
2128
2128
  const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
2129
- return comp.replace(r, (_, M, m, p10, pr) => {
2130
- debug("tilde", comp, _, M, m, p10, pr);
2129
+ return comp.replace(r, (_, M, m, p9, pr) => {
2130
+ debug("tilde", comp, _, M, m, p9, pr);
2131
2131
  let ret;
2132
2132
  if (isX(M)) {
2133
2133
  ret = "";
2134
2134
  } else if (isX(m)) {
2135
2135
  ret = `>=${M}.0.0 <${+M + 1}.0.0-0`;
2136
- } else if (isX(p10)) {
2136
+ } else if (isX(p9)) {
2137
2137
  ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`;
2138
2138
  } else if (pr) {
2139
2139
  debug("replaceTilde pr", pr);
2140
- ret = `>=${M}.${m}.${p10}-${pr} <${M}.${+m + 1}.0-0`;
2140
+ ret = `>=${M}.${m}.${p9}-${pr} <${M}.${+m + 1}.0-0`;
2141
2141
  } else {
2142
- ret = `>=${M}.${m}.${p10} <${M}.${+m + 1}.0-0`;
2142
+ ret = `>=${M}.${m}.${p9} <${M}.${+m + 1}.0-0`;
2143
2143
  }
2144
2144
  debug("tilde return", ret);
2145
2145
  return ret;
@@ -2152,14 +2152,14 @@ var require_range = __commonJS({
2152
2152
  debug("caret", comp, options);
2153
2153
  const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
2154
2154
  const z3 = options.includePrerelease ? "-0" : "";
2155
- return comp.replace(r, (_, M, m, p10, pr) => {
2156
- debug("caret", comp, _, M, m, p10, pr);
2155
+ return comp.replace(r, (_, M, m, p9, pr) => {
2156
+ debug("caret", comp, _, M, m, p9, pr);
2157
2157
  let ret;
2158
2158
  if (isX(M)) {
2159
2159
  ret = "";
2160
2160
  } else if (isX(m)) {
2161
2161
  ret = `>=${M}.0.0${z3} <${+M + 1}.0.0-0`;
2162
- } else if (isX(p10)) {
2162
+ } else if (isX(p9)) {
2163
2163
  if (M === "0") {
2164
2164
  ret = `>=${M}.${m}.0${z3} <${M}.${+m + 1}.0-0`;
2165
2165
  } else {
@@ -2169,23 +2169,23 @@ var require_range = __commonJS({
2169
2169
  debug("replaceCaret pr", pr);
2170
2170
  if (M === "0") {
2171
2171
  if (m === "0") {
2172
- ret = `>=${M}.${m}.${p10}-${pr} <${M}.${m}.${+p10 + 1}-0`;
2172
+ ret = `>=${M}.${m}.${p9}-${pr} <${M}.${m}.${+p9 + 1}-0`;
2173
2173
  } else {
2174
- ret = `>=${M}.${m}.${p10}-${pr} <${M}.${+m + 1}.0-0`;
2174
+ ret = `>=${M}.${m}.${p9}-${pr} <${M}.${+m + 1}.0-0`;
2175
2175
  }
2176
2176
  } else {
2177
- ret = `>=${M}.${m}.${p10}-${pr} <${+M + 1}.0.0-0`;
2177
+ ret = `>=${M}.${m}.${p9}-${pr} <${+M + 1}.0.0-0`;
2178
2178
  }
2179
2179
  } else {
2180
2180
  debug("no pr");
2181
2181
  if (M === "0") {
2182
2182
  if (m === "0") {
2183
- ret = `>=${M}.${m}.${p10}${z3} <${M}.${m}.${+p10 + 1}-0`;
2183
+ ret = `>=${M}.${m}.${p9}${z3} <${M}.${m}.${+p9 + 1}-0`;
2184
2184
  } else {
2185
- ret = `>=${M}.${m}.${p10}${z3} <${M}.${+m + 1}.0-0`;
2185
+ ret = `>=${M}.${m}.${p9}${z3} <${M}.${+m + 1}.0-0`;
2186
2186
  }
2187
2187
  } else {
2188
- ret = `>=${M}.${m}.${p10} <${+M + 1}.0.0-0`;
2188
+ ret = `>=${M}.${m}.${p9} <${+M + 1}.0.0-0`;
2189
2189
  }
2190
2190
  }
2191
2191
  debug("caret return", ret);
@@ -2199,11 +2199,11 @@ var require_range = __commonJS({
2199
2199
  var replaceXRange = (comp, options) => {
2200
2200
  comp = comp.trim();
2201
2201
  const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE];
2202
- return comp.replace(r, (ret, gtlt, M, m, p10, pr) => {
2203
- debug("xRange", comp, ret, gtlt, M, m, p10, pr);
2202
+ return comp.replace(r, (ret, gtlt, M, m, p9, pr) => {
2203
+ debug("xRange", comp, ret, gtlt, M, m, p9, pr);
2204
2204
  const xM = isX(M);
2205
2205
  const xm = xM || isX(m);
2206
- const xp = xm || isX(p10);
2206
+ const xp = xm || isX(p9);
2207
2207
  const anyX = xp;
2208
2208
  if (gtlt === "=" && anyX) {
2209
2209
  gtlt = "";
@@ -2219,16 +2219,16 @@ var require_range = __commonJS({
2219
2219
  if (xm) {
2220
2220
  m = 0;
2221
2221
  }
2222
- p10 = 0;
2222
+ p9 = 0;
2223
2223
  if (gtlt === ">") {
2224
2224
  gtlt = ">=";
2225
2225
  if (xm) {
2226
2226
  M = +M + 1;
2227
2227
  m = 0;
2228
- p10 = 0;
2228
+ p9 = 0;
2229
2229
  } else {
2230
2230
  m = +m + 1;
2231
- p10 = 0;
2231
+ p9 = 0;
2232
2232
  }
2233
2233
  } else if (gtlt === "<=") {
2234
2234
  gtlt = "<";
@@ -2241,7 +2241,7 @@ var require_range = __commonJS({
2241
2241
  if (gtlt === "<") {
2242
2242
  pr = "-0";
2243
2243
  }
2244
- ret = `${gtlt + M}.${m}.${p10}${pr}`;
2244
+ ret = `${gtlt + M}.${m}.${p9}${pr}`;
2245
2245
  } else if (xm) {
2246
2246
  ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`;
2247
2247
  } else if (xp) {
@@ -6919,14 +6919,14 @@ var require_mask_pattern = __commonJS({
6919
6919
  const numPatterns = Object.keys(exports2.Patterns).length;
6920
6920
  let bestPattern = 0;
6921
6921
  let lowerPenalty = Infinity;
6922
- for (let p10 = 0; p10 < numPatterns; p10++) {
6923
- setupFormatFunc(p10);
6924
- exports2.applyMask(p10, data);
6922
+ for (let p9 = 0; p9 < numPatterns; p9++) {
6923
+ setupFormatFunc(p9);
6924
+ exports2.applyMask(p9, data);
6925
6925
  const penalty = exports2.getPenaltyN1(data) + exports2.getPenaltyN2(data) + exports2.getPenaltyN3(data) + exports2.getPenaltyN4(data);
6926
- exports2.applyMask(p10, data);
6926
+ exports2.applyMask(p9, data);
6927
6927
  if (penalty < lowerPenalty) {
6928
6928
  lowerPenalty = penalty;
6929
- bestPattern = p10;
6929
+ bestPattern = p9;
6930
6930
  }
6931
6931
  }
6932
6932
  return bestPattern;
@@ -10909,7 +10909,7 @@ var require_browser = __commonJS({
10909
10909
  var QRCode2 = require_qrcode();
10910
10910
  var CanvasRenderer = require_canvas();
10911
10911
  var SvgRenderer = require_svg_tag();
10912
- function renderCanvas(renderFunc, canvas, text8, opts, cb) {
10912
+ function renderCanvas(renderFunc, canvas, text7, opts, cb) {
10913
10913
  const args2 = [].slice.call(arguments, 1);
10914
10914
  const argsNum = args2.length;
10915
10915
  const isLastArgCb = typeof args2[argsNum - 1] === "function";
@@ -10921,8 +10921,8 @@ var require_browser = __commonJS({
10921
10921
  throw new Error("Too few arguments provided");
10922
10922
  }
10923
10923
  if (argsNum === 2) {
10924
- cb = text8;
10925
- text8 = canvas;
10924
+ cb = text7;
10925
+ text7 = canvas;
10926
10926
  canvas = opts = void 0;
10927
10927
  } else if (argsNum === 3) {
10928
10928
  if (canvas.getContext && typeof cb === "undefined") {
@@ -10930,8 +10930,8 @@ var require_browser = __commonJS({
10930
10930
  opts = void 0;
10931
10931
  } else {
10932
10932
  cb = opts;
10933
- opts = text8;
10934
- text8 = canvas;
10933
+ opts = text7;
10934
+ text7 = canvas;
10935
10935
  canvas = void 0;
10936
10936
  }
10937
10937
  }
@@ -10940,16 +10940,16 @@ var require_browser = __commonJS({
10940
10940
  throw new Error("Too few arguments provided");
10941
10941
  }
10942
10942
  if (argsNum === 1) {
10943
- text8 = canvas;
10943
+ text7 = canvas;
10944
10944
  canvas = opts = void 0;
10945
10945
  } else if (argsNum === 2 && !canvas.getContext) {
10946
- opts = text8;
10947
- text8 = canvas;
10946
+ opts = text7;
10947
+ text7 = canvas;
10948
10948
  canvas = void 0;
10949
10949
  }
10950
10950
  return new Promise(function(resolve, reject) {
10951
10951
  try {
10952
- const data = QRCode2.create(text8, opts);
10952
+ const data = QRCode2.create(text7, opts);
10953
10953
  resolve(renderFunc(data, canvas, opts));
10954
10954
  } catch (e) {
10955
10955
  reject(e);
@@ -10957,7 +10957,7 @@ var require_browser = __commonJS({
10957
10957
  });
10958
10958
  }
10959
10959
  try {
10960
- const data = QRCode2.create(text8, opts);
10960
+ const data = QRCode2.create(text7, opts);
10961
10961
  cb(null, renderFunc(data, canvas, opts));
10962
10962
  } catch (e) {
10963
10963
  cb(e);
@@ -10982,8 +10982,8 @@ var require_server = __commonJS({
10982
10982
  var Utf8Renderer = require_utf8();
10983
10983
  var TerminalRenderer = require_terminal2();
10984
10984
  var SvgRenderer = require_svg();
10985
- function checkParams(text8, opts, cb) {
10986
- if (typeof text8 === "undefined") {
10985
+ function checkParams(text7, opts, cb) {
10986
+ if (typeof text7 === "undefined") {
10987
10987
  throw new Error("String required as first argument");
10988
10988
  }
10989
10989
  if (typeof cb === "undefined") {
@@ -11030,11 +11030,11 @@ var require_server = __commonJS({
11030
11030
  return Utf8Renderer;
11031
11031
  }
11032
11032
  }
11033
- function render(renderFunc, text8, params) {
11033
+ function render(renderFunc, text7, params) {
11034
11034
  if (!params.cb) {
11035
11035
  return new Promise(function(resolve, reject) {
11036
11036
  try {
11037
- const data = QRCode2.create(text8, params.opts);
11037
+ const data = QRCode2.create(text7, params.opts);
11038
11038
  return renderFunc(data, params.opts, function(err, data2) {
11039
11039
  return err ? reject(err) : resolve(data2);
11040
11040
  });
@@ -11044,7 +11044,7 @@ var require_server = __commonJS({
11044
11044
  });
11045
11045
  }
11046
11046
  try {
11047
- const data = QRCode2.create(text8, params.opts);
11047
+ const data = QRCode2.create(text7, params.opts);
11048
11048
  return renderFunc(data, params.opts, params.cb);
11049
11049
  } catch (e) {
11050
11050
  params.cb(e);
@@ -11052,43 +11052,43 @@ var require_server = __commonJS({
11052
11052
  }
11053
11053
  exports2.create = QRCode2.create;
11054
11054
  exports2.toCanvas = require_browser().toCanvas;
11055
- exports2.toString = function toString(text8, opts, cb) {
11056
- const params = checkParams(text8, opts, cb);
11055
+ exports2.toString = function toString(text7, opts, cb) {
11056
+ const params = checkParams(text7, opts, cb);
11057
11057
  const type = params.opts ? params.opts.type : void 0;
11058
11058
  const renderer = getStringRendererFromType(type);
11059
- return render(renderer.render, text8, params);
11059
+ return render(renderer.render, text7, params);
11060
11060
  };
11061
- exports2.toDataURL = function toDataURL(text8, opts, cb) {
11062
- const params = checkParams(text8, opts, cb);
11061
+ exports2.toDataURL = function toDataURL(text7, opts, cb) {
11062
+ const params = checkParams(text7, opts, cb);
11063
11063
  const renderer = getRendererFromType(params.opts.type);
11064
- return render(renderer.renderToDataURL, text8, params);
11064
+ return render(renderer.renderToDataURL, text7, params);
11065
11065
  };
11066
- exports2.toBuffer = function toBuffer(text8, opts, cb) {
11067
- const params = checkParams(text8, opts, cb);
11066
+ exports2.toBuffer = function toBuffer(text7, opts, cb) {
11067
+ const params = checkParams(text7, opts, cb);
11068
11068
  const renderer = getRendererFromType(params.opts.type);
11069
- return render(renderer.renderToBuffer, text8, params);
11069
+ return render(renderer.renderToBuffer, text7, params);
11070
11070
  };
11071
- exports2.toFile = function toFile(path6, text8, opts, cb) {
11072
- if (typeof path6 !== "string" || !(typeof text8 === "string" || typeof text8 === "object")) {
11071
+ exports2.toFile = function toFile(path6, text7, opts, cb) {
11072
+ if (typeof path6 !== "string" || !(typeof text7 === "string" || typeof text7 === "object")) {
11073
11073
  throw new Error("Invalid argument");
11074
11074
  }
11075
11075
  if (arguments.length < 3 && !canPromise()) {
11076
11076
  throw new Error("Too few arguments provided");
11077
11077
  }
11078
- const params = checkParams(text8, opts, cb);
11078
+ const params = checkParams(text7, opts, cb);
11079
11079
  const type = params.opts.type || getTypeFromFilename(path6);
11080
11080
  const renderer = getRendererFromType(type);
11081
11081
  const renderToFile = renderer.renderToFile.bind(null, path6);
11082
- return render(renderToFile, text8, params);
11082
+ return render(renderToFile, text7, params);
11083
11083
  };
11084
- exports2.toFileStream = function toFileStream(stream, text8, opts) {
11084
+ exports2.toFileStream = function toFileStream(stream, text7, opts) {
11085
11085
  if (arguments.length < 2) {
11086
11086
  throw new Error("Too few arguments provided");
11087
11087
  }
11088
- const params = checkParams(text8, opts, stream.emit.bind(stream, "error"));
11088
+ const params = checkParams(text7, opts, stream.emit.bind(stream, "error"));
11089
11089
  const renderer = getRendererFromType("png");
11090
11090
  const renderToFileStream = renderer.renderToFileStream.bind(null, stream);
11091
- render(renderToFileStream, text8, params);
11091
+ render(renderToFileStream, text7, params);
11092
11092
  };
11093
11093
  }
11094
11094
  });
@@ -16697,16 +16697,16 @@ var require_mail_composer = __commonJS({
16697
16697
  * @returns {Array} An array of alternative elements. Includes the `text` and `html` values as well
16698
16698
  */
16699
16699
  getAlternatives() {
16700
- let alternatives = [], text8, html, watchHtml, amp, icalEvent, eventObject;
16700
+ let alternatives = [], text7, html, watchHtml, amp, icalEvent, eventObject;
16701
16701
  if (this.mail.text) {
16702
16702
  if (typeof this.mail.text === "object" && (this.mail.text.content || this.mail.text.path || this.mail.text.href || this.mail.text.raw)) {
16703
- text8 = this.mail.text;
16703
+ text7 = this.mail.text;
16704
16704
  } else {
16705
- text8 = {
16705
+ text7 = {
16706
16706
  content: this.mail.text
16707
16707
  };
16708
16708
  }
16709
- text8.contentType = "text/plain; charset=utf-8";
16709
+ text7.contentType = "text/plain; charset=utf-8";
16710
16710
  }
16711
16711
  if (this.mail.watchHtml) {
16712
16712
  if (typeof this.mail.watchHtml === "object" && (this.mail.watchHtml.content || this.mail.watchHtml.path || this.mail.watchHtml.href || this.mail.watchHtml.raw)) {
@@ -16759,7 +16759,7 @@ var require_mail_composer = __commonJS({
16759
16759
  }
16760
16760
  html.contentType = "text/html; charset=utf-8";
16761
16761
  }
16762
- [].concat(text8 || []).concat(watchHtml || []).concat(amp || []).concat(html || []).concat(eventObject || []).concat(this.mail.alternatives || []).forEach((alternative) => {
16762
+ [].concat(text7 || []).concat(watchHtml || []).concat(amp || []).concat(html || []).concat(eventObject || []).concat(this.mail.alternatives || []).forEach((alternative) => {
16763
16763
  let data;
16764
16764
  if (/^data:/i.test(alternative.path || alternative.href)) {
16765
16765
  alternative = this._processDataUrl(alternative);
@@ -22296,8 +22296,8 @@ var require_nodemailer = __commonJS({
22296
22296
  });
22297
22297
 
22298
22298
  // src/commands/init.ts
22299
- var p7 = __toESM(require("@clack/prompts"));
22300
- var import_chalk8 = __toESM(require("chalk"));
22299
+ var p6 = __toESM(require("@clack/prompts"));
22300
+ var import_chalk7 = __toESM(require("chalk"));
22301
22301
  var import_fs_extra = __toESM(require("fs-extra"));
22302
22302
  var import_path = __toESM(require("path"));
22303
22303
  var import_execa = require("execa");
@@ -22933,41 +22933,6 @@ async function promptInfrastructure() {
22933
22933
  };
22934
22934
  }
22935
22935
 
22936
- // src/prompts/style.ts
22937
- var p6 = __toESM(require("@clack/prompts"));
22938
- var import_chalk7 = __toESM(require("chalk"));
22939
- async function promptStyle() {
22940
- console.log(
22941
- `
22942
- ${import_chalk7.default.dim("Used on buttons, links, and focus rings in all scaffolded pages.")}
22943
- ${import_chalk7.default.dim("This becomes a CSS variable \u2014 change it any time in globals.css.")}
22944
- `
22945
- );
22946
- const primaryColor = await p6.text({
22947
- message: "Primary color",
22948
- initialValue: "oklch(0.6 0.2 240)",
22949
- validate: (v) => !v ? "Required" : void 0
22950
- });
22951
- if (p6.isCancel(primaryColor)) process.exit(0);
22952
- console.log(
22953
- `
22954
- ${import_chalk7.default.dim("Accepts any CSS color:")}
22955
- ${import_chalk7.default.dim(" #3b82f6 (hex)")}
22956
- ${import_chalk7.default.dim(" hsl(220 90% 56%) (HSL)")}
22957
- ${import_chalk7.default.dim(" oklch(0.6 0.2 240) (recommended \u2014 perceptually uniform)")}
22958
- `
22959
- );
22960
- const logoUrl = await p6.text({
22961
- message: "Logo path (optional \u2014 leave blank to skip)",
22962
- placeholder: "/logo.svg"
22963
- });
22964
- if (p6.isCancel(logoUrl)) process.exit(0);
22965
- return {
22966
- primaryColor,
22967
- logoUrl: logoUrl || void 0
22968
- };
22969
- }
22970
-
22971
22936
  // ../core/dist/index.js
22972
22937
  var import_zod = require("zod");
22973
22938
  var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
@@ -23342,8 +23307,8 @@ function serializePermissions(role) {
23342
23307
  if (mode === "none") return `'none'`;
23343
23308
  if (mode === "dynamic") return `'dynamic'`;
23344
23309
  const perms = typeof role.permissions === "object" ? role.permissions : {};
23345
- const lines = Object.entries(perms).map(([key, p10]) => {
23346
- const def = p10;
23310
+ const lines = Object.entries(perms).map(([key, p9]) => {
23311
+ const def = p9;
23347
23312
  return [
23348
23313
  ` ${key}: {`,
23349
23314
  ` label: '${def.label}',`,
@@ -23782,8 +23747,406 @@ function generatePackageJson(name, packageManager) {
23782
23747
  2
23783
23748
  );
23784
23749
  }
23750
+ function generatePrismaLib() {
23751
+ return `import { PrismaClient } from '@prisma/client'
23752
+
23753
+ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }
23754
+
23755
+ export const prisma = globalForPrisma.prisma ?? new PrismaClient()
23756
+
23757
+ if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
23758
+ `;
23759
+ }
23760
+ function generateLoginRoute() {
23761
+ return `import { createLoginHandler } from '@alinsafawi/aegis-auth-next'
23762
+ import { prisma } from '@/lib/prisma'
23763
+ import config from '../../../../../auth.config'
23764
+
23765
+ export const POST = createLoginHandler(config, prisma)
23766
+ `;
23767
+ }
23768
+ function generateLogoutRoute() {
23769
+ return `import { createLogoutHandler } from '@alinsafawi/aegis-auth-next'
23770
+ import config from '../../../../../auth.config'
23771
+
23772
+ export const POST = createLogoutHandler(config)
23773
+ `;
23774
+ }
23775
+ function generateTwoFactorRoute() {
23776
+ return `import { createTwoFactorHandler } from '@alinsafawi/aegis-auth-next'
23777
+ import { prisma } from '@/lib/prisma'
23778
+ import config from '../../../../../auth.config'
23779
+
23780
+ export const POST = createTwoFactorHandler(config, prisma)
23781
+ `;
23782
+ }
23783
+ function generateChangePasswordRoute() {
23784
+ return `import { createChangePasswordHandler } from '@alinsafawi/aegis-auth-next'
23785
+ import { prisma } from '@/lib/prisma'
23786
+ import config from '../../../../../auth.config'
23787
+
23788
+ export const POST = createChangePasswordHandler(config, prisma)
23789
+ `;
23790
+ }
23791
+ function generateForgotPasswordPage(language) {
23792
+ const ts = language === "typescript";
23793
+ return `'use client'
23794
+
23795
+ import { useState } from 'react'
23796
+
23797
+ export default function ForgotPasswordPage() {
23798
+ const [email, setEmail] = useState('')
23799
+ const [sent, setSent] = useState(false)
23800
+ const [error, setError] = useState('')
23801
+ const [loading, setLoading] = useState(false)
23802
+
23803
+ async function handleSubmit(e${ts ? ": React.FormEvent" : ""}) {
23804
+ e.preventDefault()
23805
+ setLoading(true)
23806
+ setError('')
23807
+ const res = await fetch('/api/auth/forgot-password', {
23808
+ method: 'POST',
23809
+ headers: { 'Content-Type': 'application/json' },
23810
+ body: JSON.stringify({ email }),
23811
+ })
23812
+ setLoading(false)
23813
+ if (!res.ok) { setError((await res.json()).error ?? 'Something went wrong'); return }
23814
+ setSent(true)
23815
+ }
23816
+
23817
+ if (sent) {
23818
+ return (
23819
+ <main className="min-h-screen flex items-center justify-center p-4">
23820
+ <div className="w-full max-w-sm text-center space-y-3">
23821
+ <h1 className="text-2xl font-bold">Check your email</h1>
23822
+ <p className="text-[var(--muted)] text-sm">
23823
+ If an account exists for <strong>{email}</strong>, a reset link has been sent.
23824
+ </p>
23825
+ <a href="/login" className="block text-sm text-[var(--muted)] hover:underline mt-4">
23826
+ Back to login
23827
+ </a>
23828
+ </div>
23829
+ </main>
23830
+ )
23831
+ }
23832
+
23833
+ return (
23834
+ <main className="min-h-screen flex items-center justify-center p-4">
23835
+ <div className="w-full max-w-sm">
23836
+ <div className="text-center mb-8">
23837
+ <h1 className="text-2xl font-bold">Forgot password</h1>
23838
+ <p className="text-[var(--muted)] text-sm mt-1">We'll send you a reset link.</p>
23839
+ </div>
23840
+ <form onSubmit={handleSubmit} className="space-y-4">
23841
+ {error && <div className="text-sm text-red-500 bg-red-50 border border-red-200 rounded-md p-3">{error}</div>}
23842
+ <div>
23843
+ <label className="block text-sm font-medium mb-1">Email address</label>
23844
+ <input
23845
+ type="email"
23846
+ value={email}
23847
+ onChange={(e) => setEmail(e.target.value)}
23848
+ required
23849
+ autoComplete="email"
23850
+ className="w-full px-3 py-2 rounded-md border bg-[var(--input)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
23851
+ />
23852
+ </div>
23853
+ <button
23854
+ type="submit"
23855
+ disabled={loading}
23856
+ style={{ background: 'var(--primary)', color: 'var(--primary-foreground)' }}
23857
+ className="w-full py-2 px-4 rounded-md font-medium disabled:opacity-50 transition-opacity"
23858
+ >
23859
+ {loading ? 'Sending\u2026' : 'Send reset link'}
23860
+ </button>
23861
+ <div className="text-center">
23862
+ <a href="/login" className="text-sm text-[var(--muted)] hover:underline">Back to login</a>
23863
+ </div>
23864
+ </form>
23865
+ </div>
23866
+ </main>
23867
+ )
23868
+ }
23869
+ `;
23870
+ }
23871
+ function generateResetPasswordPage(language) {
23872
+ const ts = language === "typescript";
23873
+ return `'use client'
23874
+
23875
+ import { useState } from 'react'
23876
+ import { useSearchParams, useRouter } from 'next/navigation'
23877
+
23878
+ export default function ResetPasswordPage() {
23879
+ const params = useSearchParams()
23880
+ const router = useRouter()
23881
+ const token = params.get('token') ?? ''
23882
+ const [password, setPassword] = useState('')
23883
+ const [confirm, setConfirm] = useState('')
23884
+ const [error, setError] = useState('')
23885
+ const [loading, setLoading] = useState(false)
23886
+
23887
+ async function handleSubmit(e${ts ? ": React.FormEvent" : ""}) {
23888
+ e.preventDefault()
23889
+ if (password !== confirm) { setError('Passwords do not match'); return }
23890
+ setLoading(true)
23891
+ setError('')
23892
+ const res = await fetch('/api/auth/reset-password', {
23893
+ method: 'POST',
23894
+ headers: { 'Content-Type': 'application/json' },
23895
+ body: JSON.stringify({ token, newPassword: password }),
23896
+ })
23897
+ setLoading(false)
23898
+ if (!res.ok) { setError((await res.json()).error ?? 'Something went wrong'); return }
23899
+ router.push('/login?reset=1')
23900
+ }
23901
+
23902
+ return (
23903
+ <main className="min-h-screen flex items-center justify-center p-4">
23904
+ <div className="w-full max-w-sm">
23905
+ <div className="text-center mb-8">
23906
+ <h1 className="text-2xl font-bold">Reset password</h1>
23907
+ </div>
23908
+ <form onSubmit={handleSubmit} className="space-y-4">
23909
+ {error && <div className="text-sm text-red-500 bg-red-50 border border-red-200 rounded-md p-3">{error}</div>}
23910
+ <div>
23911
+ <label className="block text-sm font-medium mb-1">New password</label>
23912
+ <input
23913
+ type="password"
23914
+ value={password}
23915
+ onChange={(e) => setPassword(e.target.value)}
23916
+ required
23917
+ autoComplete="new-password"
23918
+ className="w-full px-3 py-2 rounded-md border bg-[var(--input)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
23919
+ />
23920
+ </div>
23921
+ <div>
23922
+ <label className="block text-sm font-medium mb-1">Confirm new password</label>
23923
+ <input
23924
+ type="password"
23925
+ value={confirm}
23926
+ onChange={(e) => setConfirm(e.target.value)}
23927
+ required
23928
+ autoComplete="new-password"
23929
+ className="w-full px-3 py-2 rounded-md border bg-[var(--input)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)]"
23930
+ />
23931
+ </div>
23932
+ <button
23933
+ type="submit"
23934
+ disabled={loading}
23935
+ style={{ background: 'var(--primary)', color: 'var(--primary-foreground)' }}
23936
+ className="w-full py-2 px-4 rounded-md font-medium disabled:opacity-50 transition-opacity"
23937
+ >
23938
+ {loading ? 'Resetting\u2026' : 'Reset password'}
23939
+ </button>
23940
+ </form>
23941
+ </div>
23942
+ </main>
23943
+ )
23944
+ }
23945
+ `;
23946
+ }
23947
+ function generateTwoFactorPage(language) {
23948
+ const ts = language === "typescript";
23949
+ return `'use client'
23950
+
23951
+ import { useState } from 'react'
23952
+ import { useRouter } from 'next/navigation'
23953
+
23954
+ export default function TwoFactorPage() {
23955
+ const [code, setCode] = useState('')
23956
+ const [error, setError] = useState('')
23957
+ const [loading, setLoading] = useState(false)
23958
+ const router = useRouter()
23959
+
23960
+ async function handleSubmit(e${ts ? ": React.FormEvent" : ""}) {
23961
+ e.preventDefault()
23962
+ setLoading(true)
23963
+ setError('')
23964
+ const res = await fetch('/api/auth/two-factor', {
23965
+ method: 'POST',
23966
+ headers: { 'Content-Type': 'application/json' },
23967
+ body: JSON.stringify({ code }),
23968
+ })
23969
+ const data = await res.json()
23970
+ setLoading(false)
23971
+ if (!res.ok) { setError(data.error ?? 'Invalid code'); return }
23972
+ router.push(\`/\${data.role}/dashboard\`)
23973
+ }
23974
+
23975
+ return (
23976
+ <main className="min-h-screen flex items-center justify-center p-4">
23977
+ <div className="w-full max-w-sm">
23978
+ <div className="text-center mb-8">
23979
+ <h1 className="text-2xl font-bold">Two-factor authentication</h1>
23980
+ <p className="text-[var(--muted)] text-sm mt-1">Enter the 6-digit code from your authenticator app.</p>
23981
+ </div>
23982
+ <form onSubmit={handleSubmit} className="space-y-4">
23983
+ {error && <div className="text-sm text-red-500 bg-red-50 border border-red-200 rounded-md p-3">{error}</div>}
23984
+ <div>
23985
+ <label className="block text-sm font-medium mb-1">Authentication code</label>
23986
+ <input
23987
+ type="text"
23988
+ inputMode="numeric"
23989
+ pattern="[0-9]*"
23990
+ maxLength={6}
23991
+ value={code}
23992
+ onChange={(e) => setCode(e.target.value.replace(/D/g, ''))}
23993
+ required
23994
+ autoComplete="one-time-code"
23995
+ placeholder="000000"
23996
+ className="w-full px-3 py-2 rounded-md border bg-[var(--input)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)] text-center tracking-widest text-lg"
23997
+ />
23998
+ </div>
23999
+ <button
24000
+ type="submit"
24001
+ disabled={loading || code.length !== 6}
24002
+ style={{ background: 'var(--primary)', color: 'var(--primary-foreground)' }}
24003
+ className="w-full py-2 px-4 rounded-md font-medium disabled:opacity-50 transition-opacity"
24004
+ >
24005
+ {loading ? 'Verifying\u2026' : 'Verify'}
24006
+ </button>
24007
+ <div className="text-center">
24008
+ <a href="/login" className="text-sm text-[var(--muted)] hover:underline">Back to login</a>
24009
+ </div>
24010
+ </form>
24011
+ </div>
24012
+ </main>
24013
+ )
24014
+ }
24015
+ `;
24016
+ }
24017
+ function generateVerifyEmailNoticePage() {
24018
+ return `export default function VerifyEmailNoticePage() {
24019
+ return (
24020
+ <main className="min-h-screen flex items-center justify-center p-4">
24021
+ <div className="w-full max-w-sm text-center space-y-3">
24022
+ <h1 className="text-2xl font-bold">Verify your email</h1>
24023
+ <p className="text-[var(--muted)] text-sm">
24024
+ We sent a verification code to your email address. Enter it below to activate your account.
24025
+ </p>
24026
+ <a href="/verify-email" className="block mt-4 text-sm underline" style={{ color: 'var(--primary)' }}>
24027
+ Enter verification code \u2192
24028
+ </a>
24029
+ </div>
24030
+ </main>
24031
+ )
24032
+ }
24033
+ `;
24034
+ }
24035
+ function generateVerifyEmailPage(language) {
24036
+ const ts = language === "typescript";
24037
+ return `'use client'
24038
+
24039
+ import { useState } from 'react'
24040
+ import { useRouter } from 'next/navigation'
24041
+
24042
+ export default function VerifyEmailPage() {
24043
+ const [code, setCode] = useState('')
24044
+ const [error, setError] = useState('')
24045
+ const [loading, setLoading] = useState(false)
24046
+ const router = useRouter()
24047
+
24048
+ async function handleSubmit(e${ts ? ": React.FormEvent" : ""}) {
24049
+ e.preventDefault()
24050
+ setLoading(true)
24051
+ setError('')
24052
+ const res = await fetch('/api/auth/verify-email', {
24053
+ method: 'POST',
24054
+ headers: { 'Content-Type': 'application/json' },
24055
+ body: JSON.stringify({ code }),
24056
+ })
24057
+ const data = await res.json()
24058
+ setLoading(false)
24059
+ if (!res.ok) { setError(data.error ?? 'Invalid code'); return }
24060
+ router.push(\`/\${data.role}/dashboard\`)
24061
+ }
24062
+
24063
+ return (
24064
+ <main className="min-h-screen flex items-center justify-center p-4">
24065
+ <div className="w-full max-w-sm">
24066
+ <div className="text-center mb-8">
24067
+ <h1 className="text-2xl font-bold">Enter verification code</h1>
24068
+ <p className="text-[var(--muted)] text-sm mt-1">Check your email for the 6-digit code.</p>
24069
+ </div>
24070
+ <form onSubmit={handleSubmit} className="space-y-4">
24071
+ {error && <div className="text-sm text-red-500 bg-red-50 border border-red-200 rounded-md p-3">{error}</div>}
24072
+ <div>
24073
+ <label className="block text-sm font-medium mb-1">Verification code</label>
24074
+ <input
24075
+ type="text"
24076
+ inputMode="numeric"
24077
+ pattern="[0-9]*"
24078
+ maxLength={6}
24079
+ value={code}
24080
+ onChange={(e) => setCode(e.target.value.replace(/D/g, ''))}
24081
+ required
24082
+ autoComplete="one-time-code"
24083
+ placeholder="000000"
24084
+ className="w-full px-3 py-2 rounded-md border bg-[var(--input)] focus:outline-none focus:ring-2 focus:ring-[var(--primary)] text-center tracking-widest text-lg"
24085
+ />
24086
+ </div>
24087
+ <button
24088
+ type="submit"
24089
+ disabled={loading || code.length !== 6}
24090
+ style={{ background: 'var(--primary)', color: 'var(--primary-foreground)' }}
24091
+ className="w-full py-2 px-4 rounded-md font-medium disabled:opacity-50 transition-opacity"
24092
+ >
24093
+ {loading ? 'Verifying\u2026' : 'Verify email'}
24094
+ </button>
24095
+ <div className="text-center">
24096
+ <a href="/login" className="text-sm text-[var(--muted)] hover:underline">Back to login</a>
24097
+ </div>
24098
+ </form>
24099
+ </div>
24100
+ </main>
24101
+ )
24102
+ }
24103
+ `;
24104
+ }
24105
+ function generateForgotPasswordRoute(language) {
24106
+ const ts = language === "typescript";
24107
+ return `import { NextRequest, NextResponse } from 'next/server'
24108
+ import { prisma } from '@/lib/prisma'
24109
+ import config from '../../../../../auth.config'
24110
+
24111
+ export async function POST(request${ts ? ": NextRequest" : ""}) {
24112
+ // TODO: implement \u2014 find user by email, generate reset token, send email
24113
+ // You can use: import { sendEmail } from '@alinsafawi/aegis-auth-core'
24114
+ const { email } = await request.json()
24115
+ return NextResponse.json({ success: true })
24116
+ }
24117
+ `;
24118
+ }
24119
+ function generateResetPasswordRoute(language) {
24120
+ const ts = language === "typescript";
24121
+ return `import { NextRequest, NextResponse } from 'next/server'
24122
+ import { prisma } from '@/lib/prisma'
24123
+ import { hashPassword } from '@alinsafawi/aegis-auth-core'
24124
+ import config from '../../../../../auth.config'
24125
+
24126
+ export async function POST(request${ts ? ": NextRequest" : ""}) {
24127
+ // TODO: implement \u2014 verify token, update password hash
24128
+ const { token, newPassword } = await request.json()
24129
+ return NextResponse.json({ success: true })
24130
+ }
24131
+ `;
24132
+ }
24133
+ function generateVerifyEmailRoute(language) {
24134
+ const ts = language === "typescript";
24135
+ return `import { NextRequest, NextResponse } from 'next/server'
24136
+ import { prisma } from '@/lib/prisma'
24137
+ import config from '../../../../../auth.config'
24138
+
24139
+ export async function POST(request${ts ? ": NextRequest" : ""}) {
24140
+ // TODO: implement \u2014 verify code, mark emailVerified = true, return role
24141
+ const { code } = await request.json()
24142
+ return NextResponse.json({ success: true, role: 'user' })
24143
+ }
24144
+ `;
24145
+ }
23785
24146
 
23786
24147
  // src/commands/init.ts
24148
+ var DEFAULT_COLOR = "oklch(0.6 0.2 240)";
24149
+ var DEFAULT_STYLE = { primaryColor: DEFAULT_COLOR, logoUrl: void 0 };
23787
24150
  function detectPackageManager() {
23788
24151
  if (process.env.npm_config_user_agent?.includes("pnpm")) return "pnpm";
23789
24152
  if (process.env.npm_config_user_agent?.includes("yarn")) return "yarn";
@@ -23793,10 +24156,10 @@ function detectPackageManager() {
23793
24156
  function isExistingNextProject(dir) {
23794
24157
  return import_fs_extra.default.existsSync(import_path.default.join(dir, "next.config.ts")) || import_fs_extra.default.existsSync(import_path.default.join(dir, "next.config.js")) || import_fs_extra.default.existsSync(import_path.default.join(dir, "next.config.mjs"));
23795
24158
  }
23796
- var STEPS = ["PROJECT", "APP", "ROLES", "FEATURES", "INFRA", "STYLE"];
24159
+ var STEPS = ["PROJECT", "APP", "ROLES", "FEATURES", "INFRA"];
23797
24160
  async function runInit() {
23798
24161
  printBanner();
23799
- const mode = await p7.select({
24162
+ const mode = await p6.select({
23800
24163
  message: "What would you like to do?",
23801
24164
  options: [
23802
24165
  {
@@ -23811,8 +24174,8 @@ async function runInit() {
23811
24174
  }
23812
24175
  ]
23813
24176
  });
23814
- if (p7.isCancel(mode)) {
23815
- p7.cancel("Cancelled.");
24177
+ if (p6.isCancel(mode)) {
24178
+ p6.cancel("Cancelled.");
23816
24179
  process.exit(0);
23817
24180
  }
23818
24181
  let targetDir = process.cwd();
@@ -23829,12 +24192,12 @@ async function runInit() {
23829
24192
  database = project.database;
23830
24193
  targetDir = import_path.default.join(process.cwd(), project.name);
23831
24194
  if (import_fs_extra.default.existsSync(targetDir)) {
23832
- const overwrite = await p7.confirm({
24195
+ const overwrite = await p6.confirm({
23833
24196
  message: `Folder '${project.name}' already exists. Continue anyway?`,
23834
24197
  initialValue: false
23835
24198
  });
23836
- if (p7.isCancel(overwrite) || !overwrite) {
23837
- p7.cancel("Cancelled.");
24199
+ if (p6.isCancel(overwrite) || !overwrite) {
24200
+ p6.cancel("Cancelled.");
23838
24201
  process.exit(0);
23839
24202
  }
23840
24203
  }
@@ -23850,17 +24213,17 @@ async function runInit() {
23850
24213
  printStatusList(checks);
23851
24214
  language = import_fs_extra.default.existsSync(import_path.default.join(targetDir, "tsconfig.json")) ? "typescript" : "javascript";
23852
24215
  if (checks.find((c4) => c4.label === "Next.js")?.status === "error") {
23853
- p7.cancel(`No Next.js project found in ${targetDir}. Run from inside your project folder.`);
24216
+ p6.cancel(`No Next.js project found in ${targetDir}. Run from inside your project folder.`);
23854
24217
  process.exit(1);
23855
24218
  }
23856
24219
  console.log(`
23857
- ${import_chalk8.default.dim("This wizard will:")}
24220
+ ${import_chalk7.default.dim("This wizard will:")}
23858
24221
  `);
23859
- console.log(` ${import_chalk8.default.dim("\xB7")} Generate Prisma models for your roles`);
23860
- console.log(` ${import_chalk8.default.dim("\xB7")} Create API route handlers ${import_chalk8.default.dim("src/app/api/auth/**")}`);
23861
- console.log(` ${import_chalk8.default.dim("\xB7")} Scaffold auth pages ${import_chalk8.default.dim("(login, 2FA, reset password, etc.)")}`);
23862
- console.log(` ${import_chalk8.default.dim("\xB7")} Create auth.config.ts`);
23863
- console.log(` ${import_chalk8.default.dim("\xB7")} Update .env.example
24222
+ console.log(` ${import_chalk7.default.dim("\xB7")} Generate Prisma models for your roles`);
24223
+ console.log(` ${import_chalk7.default.dim("\xB7")} Create API route handlers ${import_chalk7.default.dim("src/app/api/auth/**")}`);
24224
+ console.log(` ${import_chalk7.default.dim("\xB7")} Scaffold auth pages ${import_chalk7.default.dim("(login, 2FA, reset password, etc.)")}`);
24225
+ console.log(` ${import_chalk7.default.dim("\xB7")} Create auth.config.ts`);
24226
+ console.log(` ${import_chalk7.default.dim("\xB7")} Update .env.example
23864
24227
  `);
23865
24228
  }
23866
24229
  printSection(mode === "new" ? `STEP 2 of ${STEPS.length} \u25B8 PROJECT \u2713 \u25B8 APP` : `STEP 1 of ${STEPS.length - 1} \u25B8 APP`);
@@ -23871,31 +24234,29 @@ async function runInit() {
23871
24234
  let features = await promptFeatures(Object.keys(roles));
23872
24235
  printSection(mode === "new" ? `STEP 5 of ${STEPS.length} \u25B8 ... FEATURES \u2713 \u25B8 INFRA` : `STEP 4 \u25B8 FEATURES \u2713 \u25B8 INFRA`);
23873
24236
  let infra = await promptInfrastructure();
23874
- printSection(mode === "new" ? `STEP 6 of ${STEPS.length} \u25B8 ... INFRA \u2713 \u25B8 STYLE` : `STEP 5 \u25B8 INFRA \u2713 \u25B8 STYLE`);
23875
- let style = await promptStyle();
23876
24237
  let isDry = false;
23877
24238
  while (true) {
23878
24239
  printSection("REVIEW \xB7 Everything that's about to happen");
23879
- console.log(` ${import_chalk8.default.bold("Configuration")}
24240
+ console.log(` ${import_chalk7.default.bold("Configuration")}
23880
24241
  `);
23881
- console.log(` App ${import_chalk8.default.cyan(app.appName)}`);
23882
- console.log(` Cookie prefix ${import_chalk8.default.cyan(app.cookiePrefix)}`);
23883
- console.log(` Session ${import_chalk8.default.cyan(app.sessionDuration / 3600 + " hours")}`);
24242
+ console.log(` App ${import_chalk7.default.cyan(app.appName)}`);
24243
+ console.log(` Cookie prefix ${import_chalk7.default.cyan(app.cookiePrefix)}`);
24244
+ console.log(` Session ${import_chalk7.default.cyan(app.sessionDuration / 3600 + " hours")}`);
23884
24245
  if (mode === "new") {
23885
- console.log(` Language ${import_chalk8.default.cyan(language)}`);
23886
- console.log(` Package manager ${import_chalk8.default.cyan(packageManager)}`);
23887
- console.log(` Database ${import_chalk8.default.cyan(database)}`);
24246
+ console.log(` Language ${import_chalk7.default.cyan(language)}`);
24247
+ console.log(` Package manager ${import_chalk7.default.cyan(packageManager)}`);
24248
+ console.log(` Database ${import_chalk7.default.cyan(database)}`);
23888
24249
  }
23889
24250
  console.log();
23890
- console.log(` ${import_chalk8.default.bold("Roles")}`);
24251
+ console.log(` ${import_chalk7.default.bold("Roles")}`);
23891
24252
  for (const [id, role] of Object.entries(roles)) {
23892
- console.log(` ${import_chalk8.default.dim("\xB7")} ${import_chalk8.default.magentaBright(id)} ${import_chalk8.default.dim("\u2192")} ${role.prismaModel} ${import_chalk8.default.dim("(")}${role.loginField}${import_chalk8.default.dim(")")}`);
24253
+ console.log(` ${import_chalk7.default.dim("\xB7")} ${import_chalk7.default.magentaBright(id)} ${import_chalk7.default.dim("\u2192")} ${role.prismaModel} ${import_chalk7.default.dim("(")}${role.loginField}${import_chalk7.default.dim(")")}`);
23893
24254
  }
23894
24255
  console.log();
23895
24256
  const onFeatures = Object.entries(features).filter(([k, v]) => v === true && ["twoFactor", "emailVerification", "passwordReset", "accountLockout", "apiKeys", "auditLog", "sessionTracking"].includes(k)).map(([k]) => k);
23896
- console.log(` ${import_chalk8.default.bold("Features")} ${onFeatures.map((f) => import_chalk8.default.cyan(f)).join(import_chalk8.default.dim(" \xB7 "))}`);
24257
+ console.log(` ${import_chalk7.default.bold("Features")} ${onFeatures.map((f) => import_chalk7.default.cyan(f)).join(import_chalk7.default.dim(" \xB7 "))}`);
23897
24258
  console.log();
23898
- const action = await p7.select({
24259
+ const action = await p6.select({
23899
24260
  message: "Proceed?",
23900
24261
  options: [
23901
24262
  { value: "go", label: mode === "new" ? "Create project" : "Create files" },
@@ -23904,41 +24265,39 @@ async function runInit() {
23904
24265
  { value: "no", label: "Cancel" }
23905
24266
  ]
23906
24267
  });
23907
- if (p7.isCancel(action) || action === "no") {
23908
- p7.cancel("Cancelled.");
24268
+ if (p6.isCancel(action) || action === "no") {
24269
+ p6.cancel("Cancelled.");
23909
24270
  process.exit(0);
23910
24271
  }
23911
24272
  if (action === "edit") {
23912
- const section = await p7.select({
24273
+ const section = await p6.select({
23913
24274
  message: "Which section would you like to change?",
23914
24275
  options: [
23915
24276
  { value: "app", label: "App identity (name, cookie prefix, session duration)" },
23916
24277
  { value: "roles", label: "Roles" },
23917
24278
  { value: "features", label: "Features" },
23918
- { value: "infra", label: "Infrastructure (SMTP, rate limiting)" },
23919
- { value: "style", label: "Style (primary colour, logo)" }
24279
+ { value: "infra", label: "Infrastructure (SMTP, rate limiting)" }
23920
24280
  ]
23921
24281
  });
23922
- if (p7.isCancel(section)) {
23923
- p7.cancel("Cancelled.");
24282
+ if (p6.isCancel(section)) {
24283
+ p6.cancel("Cancelled.");
23924
24284
  process.exit(0);
23925
24285
  }
23926
24286
  if (section === "app") app = await promptApp(projectName);
23927
24287
  if (section === "roles") roles = await promptRoles();
23928
24288
  if (section === "features") features = await promptFeatures(Object.keys(roles));
23929
24289
  if (section === "infra") infra = await promptInfrastructure();
23930
- if (section === "style") style = await promptStyle();
23931
24290
  continue;
23932
24291
  }
23933
24292
  isDry = action === "dry";
23934
24293
  break;
23935
24294
  }
23936
24295
  printSection(mode === "new" ? `BUILDING ${projectName}` : "INSTALLING");
23937
- const spin = p7.spinner();
24296
+ const spin = p6.spinner();
23938
24297
  async function writeFile(relPath, content) {
23939
24298
  const full = import_path.default.join(targetDir, relPath);
23940
24299
  if (isDry) {
23941
- console.log(` ${import_chalk8.default.dim("+")} ${import_chalk8.default.yellow(relPath)}`);
24300
+ console.log(` ${import_chalk7.default.dim("+")} ${import_chalk7.default.yellow(relPath)}`);
23942
24301
  return;
23943
24302
  }
23944
24303
  await import_fs_extra.default.ensureDir(import_path.default.dirname(full));
@@ -23947,7 +24306,7 @@ async function runInit() {
23947
24306
  async function step(label, fn) {
23948
24307
  spin.start(label);
23949
24308
  await fn();
23950
- spin.stop(`${import_chalk8.default.green("\u2713")} ${label}`);
24309
+ spin.stop(`${import_chalk7.default.green("\u2713")} ${label}`);
23951
24310
  }
23952
24311
  if (mode === "new") {
23953
24312
  await step("Scaffolding Next.js project", async () => {
@@ -23963,9 +24322,9 @@ dist
23963
24322
  *.tsbuildinfo
23964
24323
  `);
23965
24324
  await writeFile(".env.local", "");
23966
- await writeFile("src/app/layout.tsx", generateRootLayout(app.appName, style.primaryColor, language));
23967
- await writeFile("src/app/globals.css", generateGlobalsCss(style.primaryColor));
23968
- await writeFile("src/app/page.tsx", generateRootPage(roles[Object.keys(roles)[0]] ? "/login" : "/login"));
24325
+ await writeFile("src/app/layout.tsx", generateRootLayout(app.appName, DEFAULT_COLOR, language));
24326
+ await writeFile("src/app/globals.css", generateGlobalsCss(DEFAULT_COLOR));
24327
+ await writeFile("src/app/page.tsx", generateRootPage("/login"));
23969
24328
  });
23970
24329
  }
23971
24330
  await step("Generating Prisma schema", async () => {
@@ -23986,7 +24345,7 @@ dist
23986
24345
  await writeFile("prisma/schema.prisma", schema);
23987
24346
  });
23988
24347
  await step("Creating auth.config.ts", async () => {
23989
- const config = generateAuthConfig({ appName: app.appName, cookiePrefix: app.cookiePrefix, sessionDuration: app.sessionDuration, roles, features, infra, style, language });
24348
+ const config = generateAuthConfig({ appName: app.appName, cookiePrefix: app.cookiePrefix, sessionDuration: app.sessionDuration, roles, features, infra, style: DEFAULT_STYLE, language });
23990
24349
  await writeFile(`auth.config.${language === "typescript" ? "ts" : "js"}`, config);
23991
24350
  });
23992
24351
  await step("Creating middleware", async () => {
@@ -23995,9 +24354,35 @@ dist
23995
24354
  await step("Creating session helpers", async () => {
23996
24355
  await writeFile(`src/lib/auth.${language === "typescript" ? "ts" : "js"}`, generateAuthLib(language));
23997
24356
  });
23998
- await step("Scaffolding auth pages", async () => {
24357
+ await step("Scaffolding auth pages and API routes", async () => {
23999
24358
  const e = language === "typescript" ? "tsx" : "jsx";
24000
- await writeFile(`src/app/(auth)/login/page.${e}`, generateLoginPage(app.appName, style.primaryColor, language));
24359
+ const r = language === "typescript" ? "ts" : "js";
24360
+ await writeFile(`src/lib/prisma.${r}`, generatePrismaLib());
24361
+ await writeFile(`src/app/api/auth/login/route.${r}`, generateLoginRoute());
24362
+ await writeFile(`src/app/api/auth/logout/route.${r}`, generateLogoutRoute());
24363
+ await writeFile(`src/app/api/auth/change-password/route.${r}`, generateChangePasswordRoute());
24364
+ if (features.twoFactor) {
24365
+ await writeFile(`src/app/api/auth/two-factor/route.${r}`, generateTwoFactorRoute());
24366
+ }
24367
+ if (features.passwordReset) {
24368
+ await writeFile(`src/app/api/auth/forgot-password/route.${r}`, generateForgotPasswordRoute(language));
24369
+ await writeFile(`src/app/api/auth/reset-password/route.${r}`, generateResetPasswordRoute(language));
24370
+ }
24371
+ if (features.emailVerification) {
24372
+ await writeFile(`src/app/api/auth/verify-email/route.${r}`, generateVerifyEmailRoute(language));
24373
+ }
24374
+ await writeFile(`src/app/(auth)/login/page.${e}`, generateLoginPage(app.appName, DEFAULT_COLOR, language));
24375
+ if (features.passwordReset) {
24376
+ await writeFile(`src/app/(auth)/forgot-password/page.${e}`, generateForgotPasswordPage(language));
24377
+ await writeFile(`src/app/(auth)/reset-password/page.${e}`, generateResetPasswordPage(language));
24378
+ }
24379
+ if (features.twoFactor) {
24380
+ await writeFile(`src/app/(auth)/two-factor/page.${e}`, generateTwoFactorPage(language));
24381
+ }
24382
+ if (features.emailVerification) {
24383
+ await writeFile(`src/app/(auth)/verify-email-notice/page.${e}`, generateVerifyEmailNoticePage());
24384
+ await writeFile(`src/app/(auth)/verify-email/page.${e}`, generateVerifyEmailPage(language));
24385
+ }
24001
24386
  });
24002
24387
  await step("Creating .env and .env.example", async () => {
24003
24388
  await writeFile(".env", generateEnvFile(app.cookiePrefix, infra, features));
@@ -24013,55 +24398,53 @@ dist
24013
24398
  printNextSteps([
24014
24399
  ...isNew ? [{
24015
24400
  n: 0,
24016
- title: `Enter your project ${import_chalk8.default.dim("(run every command below from inside here)")}`,
24017
- lines: [`${import_chalk8.default.green(`cd ${projectName}`)}`]
24401
+ title: `Enter your project ${import_chalk7.default.dim("(run every command below from inside here)")}`,
24402
+ lines: [`${import_chalk7.default.green(`cd ${projectName}`)}`]
24018
24403
  }] : [],
24019
24404
  {
24020
24405
  n: 1,
24021
- title: `Fill in ${import_chalk8.default.yellow(".env")} ${import_chalk8.default.dim("(created for you \u2014 open it and add your values)")}`,
24406
+ title: `Fill in ${import_chalk7.default.yellow(".env")} ${import_chalk7.default.dim("(created for you \u2014 open it and add your values)")}`,
24022
24407
  lines: [
24023
- `${import_chalk8.default.cyan("DATABASE_URL=")} ${import_chalk8.default.dim("\u2190 your Postgres connection string (Neon, Supabase, local)")}`,
24024
- `${import_chalk8.default.cyan("AEGIS_JWT_SECRET=")} ${import_chalk8.default.dim(process.platform === "win32" ? "\u2190 [Convert]::ToBase64String((1..32|%{[byte](Get-Random -Max 256)}))" : "\u2190 openssl rand -base64 32")}`,
24025
- ...features.emailVerification || features.passwordReset ? [`${import_chalk8.default.cyan("AEGIS_SMTP_HOST=")} ${import_chalk8.default.dim("\u2190 and SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM")}`] : [],
24026
- ...infra.rateLimitProvider === "upstash" ? [`${import_chalk8.default.cyan("UPSTASH_REDIS_REST_URL=")} ${import_chalk8.default.dim("\u2190 and UPSTASH_REDIS_REST_TOKEN")}`] : []
24408
+ `${import_chalk7.default.cyan("DATABASE_URL=")} ${import_chalk7.default.dim("\u2190 your Postgres connection string (Neon, Supabase, local)")}`,
24409
+ `${import_chalk7.default.cyan("AEGIS_JWT_SECRET=")} ${import_chalk7.default.dim(process.platform === "win32" ? "\u2190 [Convert]::ToBase64String((1..32|%{[byte](Get-Random -Max 256)}))" : "\u2190 openssl rand -base64 32")}`,
24410
+ ...features.emailVerification || features.passwordReset ? [`${import_chalk7.default.cyan("AEGIS_SMTP_HOST=")} ${import_chalk7.default.dim("\u2190 and SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM")}`] : [],
24411
+ ...infra.rateLimitProvider === "upstash" ? [`${import_chalk7.default.cyan("UPSTASH_REDIS_REST_URL=")} ${import_chalk7.default.dim("\u2190 and UPSTASH_REDIS_REST_TOKEN")}`] : []
24027
24412
  ]
24028
24413
  },
24029
24414
  {
24030
24415
  n: 2,
24031
24416
  title: "Apply the database schema",
24032
24417
  lines: [
24033
- ...isNew ? [`${import_chalk8.default.green(`cd ${projectName}`)} ${import_chalk8.default.dim("\u2190 if not already inside")}`] : [],
24034
- `${import_chalk8.default.green("npx prisma migrate dev --name init")}`
24418
+ ...isNew ? [`${import_chalk7.default.green(`cd ${projectName}`)} ${import_chalk7.default.dim("\u2190 if not already inside")}`] : [],
24419
+ `${import_chalk7.default.green("npx prisma migrate dev --name init")}`
24035
24420
  ]
24036
24421
  },
24037
24422
  {
24038
24423
  n: 3,
24039
24424
  title: "Create your first user",
24040
- lines: [`${import_chalk8.default.green("npx aegis-auth seed")}`]
24425
+ lines: [`${import_chalk7.default.green("npx aegis-auth seed")}`]
24041
24426
  },
24042
24427
  {
24043
24428
  n: 4,
24044
24429
  title: mode === "new" ? "Start building" : "Start your dev server",
24045
24430
  lines: [
24046
- `${import_chalk8.default.green(packageManager === "npm" ? "npm run dev" : `${packageManager} dev`)} ${import_chalk8.default.dim("\u2192 http://localhost:3000")}`
24431
+ `${import_chalk7.default.green(packageManager === "npm" ? "npm run dev" : `${packageManager} dev`)} ${import_chalk7.default.dim("\u2192 http://localhost:3000")}`
24047
24432
  ]
24048
24433
  }
24049
24434
  ]);
24050
24435
  console.log();
24051
- console.log(
24052
- ` ${import_chalk8.default.dim("Commands available any time:")}
24053
- `
24054
- );
24055
- console.log(` ${import_chalk8.default.green("aegis-auth add-role")} ${import_chalk8.default.dim("add a new role")}`);
24056
- console.log(` ${import_chalk8.default.green("aegis-auth generate")} ${import_chalk8.default.dim("regenerate TypeScript types")}`);
24057
- console.log(` ${import_chalk8.default.green("aegis-auth validate")} ${import_chalk8.default.dim("check config without hitting DB")}`);
24058
- console.log(` ${import_chalk8.default.green("aegis-auth doctor")} ${import_chalk8.default.dim("check env, DB, SMTP, Redis")}`);
24059
- console.log(` ${import_chalk8.default.green("aegis-auth upgrade")} ${import_chalk8.default.dim("update to a new version")}`);
24436
+ console.log(` ${import_chalk7.default.dim("Commands available any time:")}
24437
+ `);
24438
+ console.log(` ${import_chalk7.default.green("aegis-auth add-role")} ${import_chalk7.default.dim("add a new role")}`);
24439
+ console.log(` ${import_chalk7.default.green("aegis-auth generate")} ${import_chalk7.default.dim("regenerate TypeScript types")}`);
24440
+ console.log(` ${import_chalk7.default.green("aegis-auth validate")} ${import_chalk7.default.dim("check config without hitting DB")}`);
24441
+ console.log(` ${import_chalk7.default.green("aegis-auth doctor")} ${import_chalk7.default.dim("check env, DB, SMTP, Redis")}`);
24442
+ console.log(` ${import_chalk7.default.green("aegis-auth upgrade")} ${import_chalk7.default.dim("update to a new version")}`);
24060
24443
  console.log();
24061
24444
  }
24062
24445
 
24063
24446
  // src/commands/doctor.ts
24064
- var import_chalk9 = __toESM(require("chalk"));
24447
+ var import_chalk8 = __toESM(require("chalk"));
24065
24448
  var import_fs_extra2 = __toESM(require("fs-extra"));
24066
24449
  var import_path2 = __toESM(require("path"));
24067
24450
  async function runDoctor() {
@@ -24089,7 +24472,7 @@ async function runDoctor() {
24089
24472
  "AEGIS_JWT_SECRET_PREVIOUS"
24090
24473
  ];
24091
24474
  console.log(`
24092
- ${import_chalk9.default.dim("\u2500 Environment \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
24475
+ ${import_chalk8.default.dim("\u2500 Environment \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
24093
24476
  `);
24094
24477
  for (const key of requiredEnv) {
24095
24478
  const val = process.env[key];
@@ -24112,20 +24495,20 @@ async function runDoctor() {
24112
24495
  const warns = results.filter((r) => r.status === "warn");
24113
24496
  console.log();
24114
24497
  if (errors.length === 0 && warns.length === 0) {
24115
- console.log(` ${import_chalk9.default.green("\u2713")} ${import_chalk9.default.green("Everything looks good.")}`);
24498
+ console.log(` ${import_chalk8.default.green("\u2713")} ${import_chalk8.default.green("Everything looks good.")}`);
24116
24499
  } else {
24117
24500
  console.log(
24118
- ` ${import_chalk9.default.red(errors.length)} error${errors.length !== 1 ? "s" : ""}` + (warns.length ? ` ${import_chalk9.default.yellow(warns.length)} warning${warns.length !== 1 ? "s" : ""}` : "") + ` found.`
24501
+ ` ${import_chalk8.default.red(errors.length)} error${errors.length !== 1 ? "s" : ""}` + (warns.length ? ` ${import_chalk8.default.yellow(warns.length)} warning${warns.length !== 1 ? "s" : ""}` : "") + ` found.`
24119
24502
  );
24120
24503
  console.log();
24121
- console.log(` Fix the above, then re-run: ${import_chalk9.default.green("npx aegis-auth doctor")}`);
24504
+ console.log(` Fix the above, then re-run: ${import_chalk8.default.green("npx aegis-auth doctor")}`);
24122
24505
  }
24123
24506
  console.log();
24124
24507
  }
24125
24508
 
24126
24509
  // src/commands/add-role.ts
24127
- var p8 = __toESM(require("@clack/prompts"));
24128
- var import_chalk10 = __toESM(require("chalk"));
24510
+ var p7 = __toESM(require("@clack/prompts"));
24511
+ var import_chalk9 = __toESM(require("chalk"));
24129
24512
  var import_fs_extra3 = __toESM(require("fs-extra"));
24130
24513
  var import_path3 = __toESM(require("path"));
24131
24514
  async function runAddRole() {
@@ -24134,25 +24517,25 @@ async function runAddRole() {
24134
24517
  const cwd = process.cwd();
24135
24518
  const configPath = import_fs_extra3.default.existsSync(import_path3.default.join(cwd, "auth.config.ts")) ? import_path3.default.join(cwd, "auth.config.ts") : import_fs_extra3.default.existsSync(import_path3.default.join(cwd, "auth.config.js")) ? import_path3.default.join(cwd, "auth.config.js") : null;
24136
24519
  if (!configPath) {
24137
- p8.cancel("No auth.config.ts found. Run: npx aegis-auth init first.");
24520
+ p7.cancel("No auth.config.ts found. Run: npx aegis-auth init first.");
24138
24521
  process.exit(1);
24139
24522
  }
24140
24523
  console.log(
24141
24524
  `
24142
- ${import_chalk10.default.dim("Adding a new role to your existing setup.")}
24143
- ${import_chalk10.default.dim("You will need to run npx prisma migrate dev after.")}
24525
+ ${import_chalk9.default.dim("Adding a new role to your existing setup.")}
24526
+ ${import_chalk9.default.dim("You will need to run npx prisma migrate dev after.")}
24144
24527
  `
24145
24528
  );
24146
24529
  const { id, config } = await promptRole(1, 1);
24147
24530
  console.log();
24148
- console.log(` ${import_chalk10.default.green("\u2713")} Role ${import_chalk10.default.magentaBright(id)} defined.`);
24531
+ console.log(` ${import_chalk9.default.green("\u2713")} Role ${import_chalk9.default.magentaBright(id)} defined.`);
24149
24532
  console.log();
24150
- console.log(` ${import_chalk10.default.dim("Next steps:")}`);
24533
+ console.log(` ${import_chalk9.default.dim("Next steps:")}`);
24151
24534
  console.log();
24152
24535
  console.log(` 1 Add to auth.config.ts \u2192 roles:`);
24153
24536
  console.log();
24154
24537
  console.log(
24155
- import_chalk10.default.dim(
24538
+ import_chalk9.default.dim(
24156
24539
  ` ${id}: {
24157
24540
  label: '${config.label}',
24158
24541
  prismaModel: '${config.prismaModel}',
@@ -24164,15 +24547,15 @@ async function runAddRole() {
24164
24547
  );
24165
24548
  console.log();
24166
24549
  console.log(` 2 Apply the schema:`);
24167
- console.log(` ${import_chalk10.default.green("npx prisma migrate dev --name add-role-" + id)}`);
24550
+ console.log(` ${import_chalk9.default.green("npx prisma migrate dev --name add-role-" + id)}`);
24168
24551
  console.log();
24169
24552
  console.log(` 3 Regenerate types:`);
24170
- console.log(` ${import_chalk10.default.green("npx aegis-auth generate")}`);
24553
+ console.log(` ${import_chalk9.default.green("npx aegis-auth generate")}`);
24171
24554
  console.log();
24172
24555
  }
24173
24556
 
24174
24557
  // src/commands/generate.ts
24175
- var import_chalk11 = __toESM(require("chalk"));
24558
+ var import_chalk10 = __toESM(require("chalk"));
24176
24559
  var import_fs_extra4 = __toESM(require("fs-extra"));
24177
24560
  var import_path4 = __toESM(require("path"));
24178
24561
  async function runGenerate() {
@@ -24180,7 +24563,7 @@ async function runGenerate() {
24180
24563
  const cwd = process.cwd();
24181
24564
  const outPath = import_path4.default.join(cwd, "src", "lib", "auth-types.generated.ts");
24182
24565
  console.log(`
24183
- ${import_chalk11.default.dim("Regenerating TypeScript types from auth.config.ts...")}
24566
+ ${import_chalk10.default.dim("Regenerating TypeScript types from auth.config.ts...")}
24184
24567
  `);
24185
24568
  const content = `// auto-generated by aegis-auth \u2014 do not edit
24186
24569
  // run: npx aegis-auth generate to update
@@ -24194,13 +24577,13 @@ export type { AegisSession }
24194
24577
  `;
24195
24578
  await import_fs_extra4.default.ensureDir(import_path4.default.dirname(outPath));
24196
24579
  await import_fs_extra4.default.writeFile(outPath, content, "utf8");
24197
- console.log(` ${import_chalk11.default.green("\u2713")} ${import_chalk11.default.yellow("src/lib/auth-types.generated.ts")} updated`);
24580
+ console.log(` ${import_chalk10.default.green("\u2713")} ${import_chalk10.default.yellow("src/lib/auth-types.generated.ts")} updated`);
24198
24581
  console.log();
24199
24582
  }
24200
24583
 
24201
24584
  // src/commands/seed.ts
24202
- var p9 = __toESM(require("@clack/prompts"));
24203
- var import_chalk12 = __toESM(require("chalk"));
24585
+ var p8 = __toESM(require("@clack/prompts"));
24586
+ var import_chalk11 = __toESM(require("chalk"));
24204
24587
  var import_fs_extra5 = __toESM(require("fs-extra"));
24205
24588
  var import_path5 = __toESM(require("path"));
24206
24589
  async function runSeed() {
@@ -24209,45 +24592,45 @@ async function runSeed() {
24209
24592
  const cwd = process.cwd();
24210
24593
  const hasConfig = import_fs_extra5.default.existsSync(import_path5.default.join(cwd, "auth.config.ts")) || import_fs_extra5.default.existsSync(import_path5.default.join(cwd, "auth.config.js"));
24211
24594
  if (!hasConfig) {
24212
- p9.cancel("No auth.config.ts found. Run: npx aegis-auth init first.");
24595
+ p8.cancel("No auth.config.ts found. Run: npx aegis-auth init first.");
24213
24596
  process.exit(1);
24214
24597
  }
24215
24598
  const hasPrisma = import_fs_extra5.default.existsSync(import_path5.default.join(cwd, "node_modules", ".prisma", "client"));
24216
24599
  if (!hasPrisma) {
24217
- p9.cancel("Prisma client not generated. Run: npx prisma generate first.");
24600
+ p8.cancel("Prisma client not generated. Run: npx prisma generate first.");
24218
24601
  process.exit(1);
24219
24602
  }
24220
24603
  console.log(`
24221
- ${import_chalk12.default.dim("Creates the first user account in your database.")}
24604
+ ${import_chalk11.default.dim("Creates the first user account in your database.")}
24222
24605
  `);
24223
- const role = await p9.text({
24606
+ const role = await p8.text({
24224
24607
  message: "Role ID",
24225
24608
  placeholder: "admin",
24226
24609
  validate: (v) => !v ? "Required" : void 0
24227
24610
  });
24228
- if (p9.isCancel(role)) process.exit(0);
24229
- const loginField = await p9.select({
24611
+ if (p8.isCancel(role)) process.exit(0);
24612
+ const loginField = await p8.select({
24230
24613
  message: "Login field for this role",
24231
24614
  options: [
24232
24615
  { value: "email", label: "email" },
24233
24616
  { value: "username", label: "username" }
24234
24617
  ]
24235
24618
  });
24236
- if (p9.isCancel(loginField)) process.exit(0);
24237
- const identifier = await p9.text({
24619
+ if (p8.isCancel(loginField)) process.exit(0);
24620
+ const identifier = await p8.text({
24238
24621
  message: loginField === "email" ? "Email address" : "Username",
24239
24622
  validate: (v) => {
24240
24623
  if (!v) return "Required";
24241
24624
  if (loginField === "email" && !v.includes("@")) return "Enter a valid email address";
24242
24625
  }
24243
24626
  });
24244
- if (p9.isCancel(identifier)) process.exit(0);
24245
- const password3 = await p9.password({
24627
+ if (p8.isCancel(identifier)) process.exit(0);
24628
+ const password3 = await p8.password({
24246
24629
  message: "Password",
24247
24630
  validate: (v) => v.length < 8 ? "At least 8 characters" : void 0
24248
24631
  });
24249
- if (p9.isCancel(password3)) process.exit(0);
24250
- const spin = p9.spinner();
24632
+ if (p8.isCancel(password3)) process.exit(0);
24633
+ const spin = p8.spinner();
24251
24634
  spin.start("Creating user\u2026");
24252
24635
  try {
24253
24636
  const envPath = import_path5.default.join(cwd, ".env");
@@ -24275,18 +24658,18 @@ async function runSeed() {
24275
24658
  }
24276
24659
  });
24277
24660
  await prisma.$disconnect();
24278
- spin.stop(`${import_chalk12.default.green("\u2713")} User created`);
24661
+ spin.stop(`${import_chalk11.default.green("\u2713")} User created`);
24279
24662
  console.log();
24280
- console.log(` ${import_chalk12.default.bold("Role")} ${import_chalk12.default.magentaBright(role)}`);
24281
- console.log(` ${import_chalk12.default.bold(loginField)} ${import_chalk12.default.cyan(identifier)}`);
24663
+ console.log(` ${import_chalk11.default.bold("Role")} ${import_chalk11.default.magentaBright(role)}`);
24664
+ console.log(` ${import_chalk11.default.bold(loginField)} ${import_chalk11.default.cyan(identifier)}`);
24282
24665
  console.log();
24283
24666
  } catch (err) {
24284
- spin.stop(`${import_chalk12.default.red("\u2717")} Failed`);
24667
+ spin.stop(`${import_chalk11.default.red("\u2717")} Failed`);
24285
24668
  console.log();
24286
24669
  if (err?.code === "P2002") {
24287
- console.log(` ${import_chalk12.default.red("A user with that ${loginField} already exists.")}`);
24670
+ console.log(` ${import_chalk11.default.red("A user with that ${loginField} already exists.")}`);
24288
24671
  } else {
24289
- console.log(` ${import_chalk12.default.red(err?.message ?? String(err))}`);
24672
+ console.log(` ${import_chalk11.default.red(err?.message ?? String(err))}`);
24290
24673
  }
24291
24674
  console.log();
24292
24675
  process.exit(1);
@@ -24294,7 +24677,7 @@ async function runSeed() {
24294
24677
  }
24295
24678
 
24296
24679
  // src/index.ts
24297
- var import_chalk13 = __toESM(require("chalk"));
24680
+ var import_chalk12 = __toESM(require("chalk"));
24298
24681
  var [, , command, ...args] = process.argv;
24299
24682
  var COMMANDS = {
24300
24683
  init: runInit,
@@ -24315,23 +24698,23 @@ var DESCRIPTIONS = {
24315
24698
  async function main() {
24316
24699
  if (!command || command === "--help" || command === "-h") {
24317
24700
  printBanner();
24318
- console.log(` ${import_chalk13.default.bold("Usage")} ${import_chalk13.default.cyan("npx aegis-auth")} ${import_chalk13.default.yellow("<command>")}`);
24701
+ console.log(` ${import_chalk12.default.bold("Usage")} ${import_chalk12.default.cyan("npx aegis-auth")} ${import_chalk12.default.yellow("<command>")}`);
24319
24702
  console.log();
24320
- console.log(` ${import_chalk13.default.bold("Commands")}`);
24703
+ console.log(` ${import_chalk12.default.bold("Commands")}`);
24321
24704
  console.log();
24322
24705
  for (const [cmd, desc] of Object.entries(DESCRIPTIONS)) {
24323
- console.log(` ${import_chalk13.default.green(cmd.padEnd(14))} ${import_chalk13.default.dim(desc)}`);
24706
+ console.log(` ${import_chalk12.default.green(cmd.padEnd(14))} ${import_chalk12.default.dim(desc)}`);
24324
24707
  }
24325
24708
  console.log();
24326
- console.log(` ${import_chalk13.default.dim("Run")} ${import_chalk13.default.cyan("npx aegis-auth <command> --help")} ${import_chalk13.default.dim("for more info.")}`);
24709
+ console.log(` ${import_chalk12.default.dim("Run")} ${import_chalk12.default.cyan("npx aegis-auth <command> --help")} ${import_chalk12.default.dim("for more info.")}`);
24327
24710
  console.log();
24328
24711
  return;
24329
24712
  }
24330
24713
  const handler = COMMANDS[command];
24331
24714
  if (!handler) {
24332
24715
  console.error(`
24333
- ${import_chalk13.default.red("Unknown command:")} ${import_chalk13.default.yellow(command)}`);
24334
- console.error(` Run ${import_chalk13.default.cyan("npx aegis-auth --help")} for available commands.
24716
+ ${import_chalk12.default.red("Unknown command:")} ${import_chalk12.default.yellow(command)}`);
24717
+ console.error(` Run ${import_chalk12.default.cyan("npx aegis-auth --help")} for available commands.
24335
24718
  `);
24336
24719
  process.exit(1);
24337
24720
  }
@@ -24339,7 +24722,7 @@ async function main() {
24339
24722
  }
24340
24723
  main().catch((err) => {
24341
24724
  console.error(`
24342
- ${import_chalk13.default.red("Unexpected error:")} ${err.message}
24725
+ ${import_chalk12.default.red("Unexpected error:")} ${err.message}
24343
24726
  `);
24344
24727
  process.exit(1);
24345
24728
  });