kroxt 1.3.0 → 1.3.2

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.
@@ -28,10 +28,11 @@ var import_chalk = __toESM(require("chalk"), 1);
28
28
  var import_fs = __toESM(require("fs"), 1);
29
29
  var import_path = __toESM(require("path"), 1);
30
30
  var import_crypto = __toESM(require("crypto"), 1);
31
+ var import_child_process = require("child_process");
31
32
  var import_templates = require("./templates.js");
32
33
  const program = new import_commander.Command();
33
34
  const enquirer = new import_enquirer.default();
34
- program.name("kroxt").description("Kroxt CLI for bootstrapping auth engines").version("1.0.0");
35
+ program.name("kroxt").description("Kroxt CLI for bootstrapping auth engines").version("1.3.1");
35
36
  program.command("init").description("Initialize Kroxt in your project").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
36
37
  console.log(import_chalk.default.bold.white("\n\u2B22 KROXT AUTH INITIALIZER\n"));
37
38
  try {
@@ -41,8 +42,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
41
42
  useRateLimit: true,
42
43
  useIPBlocking: true,
43
44
  useStrictRevocation: true,
44
- usePepper: true
45
+ usePepper: true,
46
+ createModel: true,
47
+ targetDir: ""
45
48
  };
49
+ const projectContext = getProjectContext();
50
+ const defaultDir = projectContext.isExpress ? projectContext.hasSrc ? "src/config" : "config" : projectContext.hasSrc ? "src/lib/kroxt" : "lib/kroxt";
46
51
  if (!options.yes) {
47
52
  response = await enquirer.prompt([
48
53
  {
@@ -57,6 +62,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
57
62
  { name: "none", message: "None (Manual Setup)" }
58
63
  ]
59
64
  },
65
+ {
66
+ type: "input",
67
+ name: "targetDir",
68
+ message: "Where should I put the Kroxt files?",
69
+ initial: defaultDir
70
+ },
60
71
  {
61
72
  type: "confirm",
62
73
  name: "useRateLimit",
@@ -81,6 +92,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
81
92
  message: "Use server-side password peppering?",
82
93
  initial: true
83
94
  },
95
+ {
96
+ type: "confirm",
97
+ name: "createModel",
98
+ message: "Create a boilerplate User model for you?",
99
+ initial: true
100
+ },
84
101
  {
85
102
  type: "confirm",
86
103
  name: "generateEnv",
@@ -95,24 +112,49 @@ program.command("init").description("Initialize Kroxt in your project").option("
95
112
  useRateLimit: true,
96
113
  useIPBlocking: true,
97
114
  useStrictRevocation: true,
98
- usePepper: true
115
+ usePepper: true,
116
+ createModel: true,
117
+ targetDir: defaultDir
99
118
  };
100
119
  }
101
120
  const secret = import_crypto.default.randomBytes(32).toString("hex");
102
121
  const authContent = (0, import_templates.authTemplate)(response.adapter, secret, response);
103
- const authPath = import_path.default.join(process.cwd(), "src", "lib", "auth.ts");
122
+ const authPath = import_path.default.join(process.cwd(), response.targetDir, "auth.ts");
104
123
  const dirPath = import_path.default.dirname(authPath);
105
124
  if (!import_fs.default.existsSync(dirPath)) {
106
125
  import_fs.default.mkdirSync(dirPath, { recursive: true });
107
126
  }
108
127
  import_fs.default.writeFileSync(authPath, authContent);
109
128
  console.log(import_chalk.default.green(`
110
- \u2714 Created: ${import_chalk.default.white("src/lib/auth.ts")}`));
129
+ \u2714 Created: ${import_chalk.default.white(import_path.default.relative(process.cwd(), authPath))}`));
111
130
  const tsConfigPath = import_path.default.join(process.cwd(), "tsconfig.json");
112
131
  if (!import_fs.default.existsSync(tsConfigPath)) {
113
132
  import_fs.default.writeFileSync(tsConfigPath, import_templates.tsConfigTemplate);
114
133
  console.log(import_chalk.default.green(`\u2714 Created: ${import_chalk.default.white("tsconfig.json")}`));
115
134
  }
135
+ if (response.createModel && response.adapter !== "memory" && response.adapter !== "none") {
136
+ let modelPath = "";
137
+ switch (response.adapter) {
138
+ case "mongoose":
139
+ modelPath = import_path.default.join(process.cwd(), response.targetDir, "user.model.ts");
140
+ break;
141
+ case "drizzle":
142
+ modelPath = import_path.default.join(process.cwd(), response.targetDir, "schema.ts");
143
+ break;
144
+ case "prisma":
145
+ modelPath = import_path.default.join(process.cwd(), response.targetDir, "user.prisma");
146
+ break;
147
+ }
148
+ if (modelPath) {
149
+ const modelDirPath = import_path.default.dirname(modelPath);
150
+ if (!import_fs.default.existsSync(modelDirPath)) {
151
+ import_fs.default.mkdirSync(modelDirPath, { recursive: true });
152
+ }
153
+ const { userModelTemplate } = await import("./templates.js");
154
+ import_fs.default.writeFileSync(modelPath, userModelTemplate(response.adapter));
155
+ console.log(import_chalk.default.green(`\u2714 Created: ${import_chalk.default.white(import_path.default.relative(process.cwd(), modelPath))}`));
156
+ }
157
+ }
116
158
  if (response.generateEnv) {
117
159
  const envPath = import_path.default.join(process.cwd(), ".env");
118
160
  const envContent = (0, import_templates.envTemplate)(secret, response.usePepper);
@@ -125,10 +167,63 @@ program.command("init").description("Initialize Kroxt in your project").option("
125
167
  }
126
168
  }
127
169
  console.log(import_chalk.default.bold.white("\nKroxt is ready. Happy coding! \u{1F680}\n"));
170
+ await checkAndInstallDeps(response.adapter, !!options.yes);
128
171
  } catch (err) {
129
172
  console.error(import_chalk.default.red("\n\u2716 Initialization cancelled."));
130
173
  process.exit(1);
131
174
  }
132
175
  });
176
+ async function checkAndInstallDeps(adapter, skipPrompts = false) {
177
+ const pkgPath = import_path.default.join(process.cwd(), "package.json");
178
+ if (!import_fs.default.existsSync(pkgPath)) return;
179
+ const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf8"));
180
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
181
+ const required = {
182
+ memory: ["kroxt", "dotenv"],
183
+ mongoose: ["kroxt", "mongoose", "dotenv"],
184
+ prisma: ["kroxt", "@prisma/client", "dotenv"],
185
+ drizzle: ["kroxt", "drizzle-orm", "dotenv"],
186
+ none: ["kroxt"]
187
+ };
188
+ const packages = required[adapter] || [];
189
+ const missing = packages.filter((dep) => !deps[dep]);
190
+ if (missing.length > 0) {
191
+ let confirm = true;
192
+ if (!skipPrompts) {
193
+ const enquirer2 = new import_enquirer.default();
194
+ const result = await enquirer2.prompt({
195
+ type: "confirm",
196
+ name: "confirm",
197
+ message: `Required dependencies are missing: ${import_chalk.default.cyan(missing.join(", "))}. Install them now?`,
198
+ initial: true
199
+ });
200
+ confirm = result.confirm;
201
+ }
202
+ if (confirm) {
203
+ console.log(import_chalk.default.gray(`
204
+ Installing ${missing.join(", ")}...`));
205
+ return new Promise((resolve) => {
206
+ const child = (0, import_child_process.spawn)("npm", ["install", ...missing], {
207
+ stdio: "inherit",
208
+ shell: true
209
+ });
210
+ child.on("close", resolve);
211
+ });
212
+ }
213
+ }
214
+ }
215
+ function getProjectContext() {
216
+ const hasSrc = import_fs.default.existsSync(import_path.default.join(process.cwd(), "src"));
217
+ const pkgPath = import_path.default.join(process.cwd(), "package.json");
218
+ let isExpress = false;
219
+ let isNext = false;
220
+ if (import_fs.default.existsSync(pkgPath)) {
221
+ const pkg = JSON.parse(import_fs.default.readFileSync(pkgPath, "utf8"));
222
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
223
+ isExpress = !!(deps.express || deps.fastify);
224
+ isNext = !!deps.next;
225
+ }
226
+ return { hasSrc, isExpress, isNext };
227
+ }
133
228
  program.parse(process.argv);
134
229
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/index.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { authTemplate, envTemplate, tsConfigTemplate } from './templates.js';\n\nconst program = new Command();\nconst enquirer = new Enquirer();\n\nprogram\n .name('kroxt')\n .description('Kroxt CLI for bootstrapping auth engines')\n .version('1.0.0');\n\nprogram\n .command('init')\n .description('Initialize Kroxt in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n console.log(chalk.bold.white('\\n\u2B22 KROXT AUTH INITIALIZER\\n'));\n\n try {\n let response = {\n adapter: 'memory',\n generateEnv: true,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true\n };\n\n if (!options.yes) {\n response = await enquirer.prompt([\n {\n type: 'select',\n name: 'adapter',\n message: 'Choose your database adapter:',\n choices: [\n { name: 'memory', message: 'In-Memory (Testing)' },\n { name: 'mongoose', message: 'Mongoose (MongoDB)' },\n { name: 'prisma', message: 'Prisma (PostgreSQL/MySQL)' },\n { name: 'drizzle', message: 'Drizzle (SQLite/PostgreSQL)' },\n { name: 'none', message: 'None (Manual Setup)' }\n ]\n },\n {\n type: 'confirm',\n name: 'useRateLimit',\n message: 'Enable rate limiting defensive layer?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useIPBlocking',\n message: 'Enable automatic IP blocking?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useStrictRevocation',\n message: 'Enforce strict session revocation?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'usePepper',\n message: 'Use server-side password peppering?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'generateEnv',\n message: 'Generate secure secrets in .env?',\n initial: true\n }\n ]) as any;\n } else {\n console.log(chalk.gray('Using default settings (--yes)...'));\n response = {\n ...response,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true\n } as any;\n }\n\n const secret = crypto.randomBytes(32).toString('hex');\n const authContent = authTemplate(response.adapter, secret, response);\n\n // Write auth.ts\n const authPath = path.join(process.cwd(), 'src', 'lib', 'auth.ts');\n const dirPath = path.dirname(authPath);\n\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n\n fs.writeFileSync(authPath, authContent);\n console.log(chalk.green(`\\n\u2714 Created: ${chalk.white('src/lib/auth.ts')}`));\n\n // Write tsconfig.json if not present\n const tsConfigPath = path.join(process.cwd(), 'tsconfig.json');\n if (!fs.existsSync(tsConfigPath)) {\n fs.writeFileSync(tsConfigPath, tsConfigTemplate);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('tsconfig.json')}`));\n }\n\n // Write .env\n if (response.generateEnv) {\n const envPath = path.join(process.cwd(), '.env');\n const envContent = envTemplate(secret, response.usePepper);\n \n if (fs.existsSync(envPath)) {\n fs.appendFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Updated: ${chalk.white('.env')} (Appended JWT_SECRET)`));\n } else {\n fs.writeFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('.env')}`));\n }\n }\n\n console.log(chalk.bold.white('\\nKroxt is ready. Happy coding! \uD83D\uDE80\\n'));\n\n } catch (err) {\n console.error(chalk.red('\\n\u2716 Initialization cancelled.'));\n process.exit(1);\n }\n });\n\nprogram.parse(process.argv);\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AACA,uBAAwB;AACxB,sBAAqB;AACrB,mBAAkB;AAClB,gBAAe;AACf,kBAAiB;AACjB,oBAAmB;AACnB,uBAA4D;AAE5D,MAAM,UAAU,IAAI,yBAAQ;AAC5B,MAAM,WAAW,IAAI,gBAAAA,QAAS;AAE9B,QACG,KAAK,OAAO,EACZ,YAAY,0CAA0C,EACtD,QAAQ,OAAO;AAElB,QACG,QAAQ,MAAM,EACd,YAAY,kCAAkC,EAC9C,OAAO,aAAa,+BAA+B,EACnD,OAAO,OAAO,YAAY;AACzB,UAAQ,IAAI,aAAAC,QAAM,KAAK,MAAM,mCAA8B,CAAC;AAE5D,MAAI;AACF,QAAI,WAAW;AAAA,MACb,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAc;AAAA,MACd,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,WAAW;AAAA,IACb;AAEA,QAAI,CAAC,QAAQ,KAAK;AAChB,iBAAW,MAAM,SAAS,OAAO;AAAA,QAC/B;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,YACP,EAAE,MAAM,UAAU,SAAS,sBAAsB;AAAA,YACjD,EAAE,MAAM,YAAY,SAAS,qBAAqB;AAAA,YAClD,EAAE,MAAM,UAAU,SAAS,4BAA4B;AAAA,YACvD,EAAE,MAAM,WAAW,SAAS,8BAA8B;AAAA,YAC1D,EAAE,MAAM,QAAQ,SAAS,sBAAsB;AAAA,UACjD;AAAA,QACF;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,IAAI,aAAAA,QAAM,KAAK,mCAAmC,CAAC;AAC3D,iBAAW;AAAA,QACT,GAAG;AAAA,QACH,cAAc;AAAA,QACd,eAAe;AAAA,QACf,qBAAqB;AAAA,QACrB,WAAW;AAAA,MACb;AAAA,IACF;AAEA,UAAM,SAAS,cAAAC,QAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AACpD,UAAM,kBAAc,+BAAa,SAAS,SAAS,QAAQ,QAAQ;AAGnE,UAAM,WAAW,YAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,OAAO,SAAS;AACjE,UAAM,UAAU,YAAAA,QAAK,QAAQ,QAAQ;AAErC,QAAI,CAAC,UAAAC,QAAG,WAAW,OAAO,GAAG;AAC3B,gBAAAA,QAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3C;AAEA,cAAAA,QAAG,cAAc,UAAU,WAAW;AACtC,YAAQ,IAAI,aAAAH,QAAM,MAAM;AAAA,kBAAgB,aAAAA,QAAM,MAAM,iBAAiB,CAAC,EAAE,CAAC;AAGzE,UAAM,eAAe,YAAAE,QAAK,KAAK,QAAQ,IAAI,GAAG,eAAe;AAC7D,QAAI,CAAC,UAAAC,QAAG,WAAW,YAAY,GAAG;AAChC,gBAAAA,QAAG,cAAc,cAAc,iCAAgB;AAC/C,cAAQ,IAAI,aAAAH,QAAM,MAAM,mBAAc,aAAAA,QAAM,MAAM,eAAe,CAAC,EAAE,CAAC;AAAA,IACvE;AAGA,QAAI,SAAS,aAAa;AACxB,YAAM,UAAU,YAAAE,QAAK,KAAK,QAAQ,IAAI,GAAG,MAAM;AAC/C,YAAM,iBAAa,8BAAY,QAAQ,SAAS,SAAS;AAEzD,UAAI,UAAAC,QAAG,WAAW,OAAO,GAAG;AAC1B,kBAAAA,QAAG,eAAe,SAAS,UAAU;AACrC,gBAAQ,IAAI,aAAAH,QAAM,MAAM,mBAAc,aAAAA,QAAM,MAAM,MAAM,CAAC,wBAAwB,CAAC;AAAA,MACpF,OAAO;AACL,kBAAAG,QAAG,cAAc,SAAS,UAAU;AACpC,gBAAQ,IAAI,aAAAH,QAAM,MAAM,mBAAc,aAAAA,QAAM,MAAM,MAAM,CAAC,EAAE,CAAC;AAAA,MAC9D;AAAA,IACF;AAEA,YAAQ,IAAI,aAAAA,QAAM,KAAK,MAAM,6CAAsC,CAAC;AAAA,EAEtE,SAAS,KAAK;AACZ,YAAQ,MAAM,aAAAA,QAAM,IAAI,oCAA+B,CAAC;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QAAQ,MAAM,QAAQ,IAAI;",
6
- "names": ["Enquirer", "chalk", "crypto", "path", "fs"]
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { spawn } from 'child_process';\nimport { authTemplate, envTemplate, tsConfigTemplate } from './templates.js';\n\nconst program = new Command();\nconst enquirer = new Enquirer();\n\nprogram\n .name('kroxt')\n .description('Kroxt CLI for bootstrapping auth engines')\n .version('1.3.1');\n\nprogram\n .command('init')\n .description('Initialize Kroxt in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n console.log(chalk.bold.white('\\n\u2B22 KROXT AUTH INITIALIZER\\n'));\n\n try {\n let response = {\n adapter: 'memory',\n generateEnv: true,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true,\n createModel: true,\n targetDir: ''\n };\n\n const projectContext = getProjectContext();\n const defaultDir = projectContext.isExpress ? (projectContext.hasSrc ? 'src/config' : 'config') : (projectContext.hasSrc ? 'src/lib/kroxt' : 'lib/kroxt');\n\n if (!options.yes) {\n response = await enquirer.prompt([\n {\n type: 'select',\n name: 'adapter',\n message: 'Choose your database adapter:',\n choices: [\n { name: 'memory', message: 'In-Memory (Testing)' },\n { name: 'mongoose', message: 'Mongoose (MongoDB)' },\n { name: 'prisma', message: 'Prisma (PostgreSQL/MySQL)' },\n { name: 'drizzle', message: 'Drizzle (SQLite/PostgreSQL)' },\n { name: 'none', message: 'None (Manual Setup)' }\n ]\n },\n {\n type: 'input',\n name: 'targetDir',\n message: 'Where should I put the Kroxt files?',\n initial: defaultDir\n },\n {\n type: 'confirm',\n name: 'useRateLimit',\n message: 'Enable rate limiting defensive layer?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useIPBlocking',\n message: 'Enable automatic IP blocking?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useStrictRevocation',\n message: 'Enforce strict session revocation?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'usePepper',\n message: 'Use server-side password peppering?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'createModel',\n message: 'Create a boilerplate User model for you?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'generateEnv',\n message: 'Generate secure secrets in .env?',\n initial: true\n }\n ]) as any;\n } else {\n console.log(chalk.gray('Using default settings (--yes)...'));\n response = {\n ...response,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true,\n createModel: true,\n targetDir: defaultDir\n } as any;\n }\n\n const secret = crypto.randomBytes(32).toString('hex');\n const authContent = authTemplate(response.adapter, secret, response);\n\n // Write auth.ts\n const authPath = path.join(process.cwd(), response.targetDir, 'auth.ts');\n const dirPath = path.dirname(authPath);\n\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n\n fs.writeFileSync(authPath, authContent);\n console.log(chalk.green(`\\n\u2714 Created: ${chalk.white(path.relative(process.cwd(), authPath))}`));\n\n // Write tsconfig.json if not present\n const tsConfigPath = path.join(process.cwd(), 'tsconfig.json');\n if (!fs.existsSync(tsConfigPath)) {\n fs.writeFileSync(tsConfigPath, tsConfigTemplate);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('tsconfig.json')}`));\n }\n\n // Write User Model if requested\n if (response.createModel && response.adapter !== 'memory' && response.adapter !== 'none') {\n let modelPath = '';\n switch (response.adapter) {\n case 'mongoose':\n modelPath = path.join(process.cwd(), response.targetDir, 'user.model.ts');\n break;\n case 'drizzle':\n modelPath = path.join(process.cwd(), response.targetDir, 'schema.ts');\n break;\n case 'prisma':\n modelPath = path.join(process.cwd(), response.targetDir, 'user.prisma');\n break;\n }\n\n if (modelPath) {\n const modelDirPath = path.dirname(modelPath);\n if (!fs.existsSync(modelDirPath)) {\n fs.mkdirSync(modelDirPath, { recursive: true });\n }\n \n const { userModelTemplate } = await import('./templates.js');\n fs.writeFileSync(modelPath, userModelTemplate(response.adapter));\n console.log(chalk.green(`\u2714 Created: ${chalk.white(path.relative(process.cwd(), modelPath))}`));\n }\n }\n\n // Write .env\n if (response.generateEnv) {\n const envPath = path.join(process.cwd(), '.env');\n const envContent = envTemplate(secret, response.usePepper);\n \n if (fs.existsSync(envPath)) {\n fs.appendFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Updated: ${chalk.white('.env')} (Appended JWT_SECRET)`));\n } else {\n fs.writeFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('.env')}`));\n }\n }\n\n console.log(chalk.bold.white('\\nKroxt is ready. Happy coding! \uD83D\uDE80\\n'));\n\n // --- DEPENDENCY AUTO-INSTALLATION ---\n await checkAndInstallDeps(response.adapter, !!options.yes);\n\n } catch (err) {\n console.error(chalk.red('\\n\u2716 Initialization cancelled.'));\n process.exit(1);\n }\n });\n\nasync function checkAndInstallDeps(adapter: string, skipPrompts: boolean = false) {\n const pkgPath = path.join(process.cwd(), 'package.json');\n if (!fs.existsSync(pkgPath)) return;\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n const required: Record<string, string[]> = {\n memory: ['kroxt', 'dotenv'],\n mongoose: ['kroxt', 'mongoose', 'dotenv'],\n prisma: ['kroxt', '@prisma/client', 'dotenv'],\n drizzle: ['kroxt', 'drizzle-orm', 'dotenv'],\n none: ['kroxt']\n };\n\n const packages = required[adapter] || [];\n const missing = packages.filter(dep => !deps[dep]);\n\n if (missing.length > 0) {\n let confirm = true;\n\n if (!skipPrompts) {\n const enquirer = new Enquirer();\n const result = await enquirer.prompt({\n type: 'confirm',\n name: 'confirm',\n message: `Required dependencies are missing: ${chalk.cyan(missing.join(', '))}. Install them now?`,\n initial: true\n }) as any;\n confirm = result.confirm;\n }\n\n if (confirm) {\n console.log(chalk.gray(`\\nInstalling ${missing.join(', ')}...`));\n return new Promise((resolve) => {\n const child = spawn('npm', ['install', ...missing], { \n stdio: 'inherit',\n shell: true \n });\n child.on('close', resolve);\n });\n }\n }\n}\n\nfunction getProjectContext() {\n const hasSrc = fs.existsSync(path.join(process.cwd(), 'src'));\n const pkgPath = path.join(process.cwd(), 'package.json');\n let isExpress = false;\n let isNext = false;\n\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n isExpress = !!(deps.express || deps.fastify);\n isNext = !!deps.next;\n }\n\n return { hasSrc, isExpress, isNext };\n}\n\nprogram.parse(process.argv);\n"],
5
+ "mappings": "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",
6
+ "names": ["Enquirer", "chalk", "crypto", "path", "fs", "enquirer"]
7
7
  }
package/dist/cli/index.js CHANGED
@@ -5,10 +5,11 @@ import chalk from "chalk";
5
5
  import fs from "fs";
6
6
  import path from "path";
7
7
  import crypto from "crypto";
8
+ import { spawn } from "child_process";
8
9
  import { authTemplate, envTemplate, tsConfigTemplate } from "./templates.js";
9
10
  const program = new Command();
10
11
  const enquirer = new Enquirer();
11
- program.name("kroxt").description("Kroxt CLI for bootstrapping auth engines").version("1.0.0");
12
+ program.name("kroxt").description("Kroxt CLI for bootstrapping auth engines").version("1.3.1");
12
13
  program.command("init").description("Initialize Kroxt in your project").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
13
14
  console.log(chalk.bold.white("\n\u2B22 KROXT AUTH INITIALIZER\n"));
14
15
  try {
@@ -18,8 +19,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
18
19
  useRateLimit: true,
19
20
  useIPBlocking: true,
20
21
  useStrictRevocation: true,
21
- usePepper: true
22
+ usePepper: true,
23
+ createModel: true,
24
+ targetDir: ""
22
25
  };
26
+ const projectContext = getProjectContext();
27
+ const defaultDir = projectContext.isExpress ? projectContext.hasSrc ? "src/config" : "config" : projectContext.hasSrc ? "src/lib/kroxt" : "lib/kroxt";
23
28
  if (!options.yes) {
24
29
  response = await enquirer.prompt([
25
30
  {
@@ -34,6 +39,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
34
39
  { name: "none", message: "None (Manual Setup)" }
35
40
  ]
36
41
  },
42
+ {
43
+ type: "input",
44
+ name: "targetDir",
45
+ message: "Where should I put the Kroxt files?",
46
+ initial: defaultDir
47
+ },
37
48
  {
38
49
  type: "confirm",
39
50
  name: "useRateLimit",
@@ -58,6 +69,12 @@ program.command("init").description("Initialize Kroxt in your project").option("
58
69
  message: "Use server-side password peppering?",
59
70
  initial: true
60
71
  },
72
+ {
73
+ type: "confirm",
74
+ name: "createModel",
75
+ message: "Create a boilerplate User model for you?",
76
+ initial: true
77
+ },
61
78
  {
62
79
  type: "confirm",
63
80
  name: "generateEnv",
@@ -72,24 +89,49 @@ program.command("init").description("Initialize Kroxt in your project").option("
72
89
  useRateLimit: true,
73
90
  useIPBlocking: true,
74
91
  useStrictRevocation: true,
75
- usePepper: true
92
+ usePepper: true,
93
+ createModel: true,
94
+ targetDir: defaultDir
76
95
  };
77
96
  }
78
97
  const secret = crypto.randomBytes(32).toString("hex");
79
98
  const authContent = authTemplate(response.adapter, secret, response);
80
- const authPath = path.join(process.cwd(), "src", "lib", "auth.ts");
99
+ const authPath = path.join(process.cwd(), response.targetDir, "auth.ts");
81
100
  const dirPath = path.dirname(authPath);
82
101
  if (!fs.existsSync(dirPath)) {
83
102
  fs.mkdirSync(dirPath, { recursive: true });
84
103
  }
85
104
  fs.writeFileSync(authPath, authContent);
86
105
  console.log(chalk.green(`
87
- \u2714 Created: ${chalk.white("src/lib/auth.ts")}`));
106
+ \u2714 Created: ${chalk.white(path.relative(process.cwd(), authPath))}`));
88
107
  const tsConfigPath = path.join(process.cwd(), "tsconfig.json");
89
108
  if (!fs.existsSync(tsConfigPath)) {
90
109
  fs.writeFileSync(tsConfigPath, tsConfigTemplate);
91
110
  console.log(chalk.green(`\u2714 Created: ${chalk.white("tsconfig.json")}`));
92
111
  }
112
+ if (response.createModel && response.adapter !== "memory" && response.adapter !== "none") {
113
+ let modelPath = "";
114
+ switch (response.adapter) {
115
+ case "mongoose":
116
+ modelPath = path.join(process.cwd(), response.targetDir, "user.model.ts");
117
+ break;
118
+ case "drizzle":
119
+ modelPath = path.join(process.cwd(), response.targetDir, "schema.ts");
120
+ break;
121
+ case "prisma":
122
+ modelPath = path.join(process.cwd(), response.targetDir, "user.prisma");
123
+ break;
124
+ }
125
+ if (modelPath) {
126
+ const modelDirPath = path.dirname(modelPath);
127
+ if (!fs.existsSync(modelDirPath)) {
128
+ fs.mkdirSync(modelDirPath, { recursive: true });
129
+ }
130
+ const { userModelTemplate } = await import("./templates.js");
131
+ fs.writeFileSync(modelPath, userModelTemplate(response.adapter));
132
+ console.log(chalk.green(`\u2714 Created: ${chalk.white(path.relative(process.cwd(), modelPath))}`));
133
+ }
134
+ }
93
135
  if (response.generateEnv) {
94
136
  const envPath = path.join(process.cwd(), ".env");
95
137
  const envContent = envTemplate(secret, response.usePepper);
@@ -102,10 +144,63 @@ program.command("init").description("Initialize Kroxt in your project").option("
102
144
  }
103
145
  }
104
146
  console.log(chalk.bold.white("\nKroxt is ready. Happy coding! \u{1F680}\n"));
147
+ await checkAndInstallDeps(response.adapter, !!options.yes);
105
148
  } catch (err) {
106
149
  console.error(chalk.red("\n\u2716 Initialization cancelled."));
107
150
  process.exit(1);
108
151
  }
109
152
  });
153
+ async function checkAndInstallDeps(adapter, skipPrompts = false) {
154
+ const pkgPath = path.join(process.cwd(), "package.json");
155
+ if (!fs.existsSync(pkgPath)) return;
156
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
157
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
158
+ const required = {
159
+ memory: ["kroxt", "dotenv"],
160
+ mongoose: ["kroxt", "mongoose", "dotenv"],
161
+ prisma: ["kroxt", "@prisma/client", "dotenv"],
162
+ drizzle: ["kroxt", "drizzle-orm", "dotenv"],
163
+ none: ["kroxt"]
164
+ };
165
+ const packages = required[adapter] || [];
166
+ const missing = packages.filter((dep) => !deps[dep]);
167
+ if (missing.length > 0) {
168
+ let confirm = true;
169
+ if (!skipPrompts) {
170
+ const enquirer2 = new Enquirer();
171
+ const result = await enquirer2.prompt({
172
+ type: "confirm",
173
+ name: "confirm",
174
+ message: `Required dependencies are missing: ${chalk.cyan(missing.join(", "))}. Install them now?`,
175
+ initial: true
176
+ });
177
+ confirm = result.confirm;
178
+ }
179
+ if (confirm) {
180
+ console.log(chalk.gray(`
181
+ Installing ${missing.join(", ")}...`));
182
+ return new Promise((resolve) => {
183
+ const child = spawn("npm", ["install", ...missing], {
184
+ stdio: "inherit",
185
+ shell: true
186
+ });
187
+ child.on("close", resolve);
188
+ });
189
+ }
190
+ }
191
+ }
192
+ function getProjectContext() {
193
+ const hasSrc = fs.existsSync(path.join(process.cwd(), "src"));
194
+ const pkgPath = path.join(process.cwd(), "package.json");
195
+ let isExpress = false;
196
+ let isNext = false;
197
+ if (fs.existsSync(pkgPath)) {
198
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
199
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
200
+ isExpress = !!(deps.express || deps.fastify);
201
+ isNext = !!deps.next;
202
+ }
203
+ return { hasSrc, isExpress, isNext };
204
+ }
110
205
  program.parse(process.argv);
111
206
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/index.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { authTemplate, envTemplate, tsConfigTemplate } from './templates.js';\n\nconst program = new Command();\nconst enquirer = new Enquirer();\n\nprogram\n .name('kroxt')\n .description('Kroxt CLI for bootstrapping auth engines')\n .version('1.0.0');\n\nprogram\n .command('init')\n .description('Initialize Kroxt in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n console.log(chalk.bold.white('\\n\u2B22 KROXT AUTH INITIALIZER\\n'));\n\n try {\n let response = {\n adapter: 'memory',\n generateEnv: true,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true\n };\n\n if (!options.yes) {\n response = await enquirer.prompt([\n {\n type: 'select',\n name: 'adapter',\n message: 'Choose your database adapter:',\n choices: [\n { name: 'memory', message: 'In-Memory (Testing)' },\n { name: 'mongoose', message: 'Mongoose (MongoDB)' },\n { name: 'prisma', message: 'Prisma (PostgreSQL/MySQL)' },\n { name: 'drizzle', message: 'Drizzle (SQLite/PostgreSQL)' },\n { name: 'none', message: 'None (Manual Setup)' }\n ]\n },\n {\n type: 'confirm',\n name: 'useRateLimit',\n message: 'Enable rate limiting defensive layer?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useIPBlocking',\n message: 'Enable automatic IP blocking?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useStrictRevocation',\n message: 'Enforce strict session revocation?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'usePepper',\n message: 'Use server-side password peppering?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'generateEnv',\n message: 'Generate secure secrets in .env?',\n initial: true\n }\n ]) as any;\n } else {\n console.log(chalk.gray('Using default settings (--yes)...'));\n response = {\n ...response,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true\n } as any;\n }\n\n const secret = crypto.randomBytes(32).toString('hex');\n const authContent = authTemplate(response.adapter, secret, response);\n\n // Write auth.ts\n const authPath = path.join(process.cwd(), 'src', 'lib', 'auth.ts');\n const dirPath = path.dirname(authPath);\n\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n\n fs.writeFileSync(authPath, authContent);\n console.log(chalk.green(`\\n\u2714 Created: ${chalk.white('src/lib/auth.ts')}`));\n\n // Write tsconfig.json if not present\n const tsConfigPath = path.join(process.cwd(), 'tsconfig.json');\n if (!fs.existsSync(tsConfigPath)) {\n fs.writeFileSync(tsConfigPath, tsConfigTemplate);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('tsconfig.json')}`));\n }\n\n // Write .env\n if (response.generateEnv) {\n const envPath = path.join(process.cwd(), '.env');\n const envContent = envTemplate(secret, response.usePepper);\n \n if (fs.existsSync(envPath)) {\n fs.appendFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Updated: ${chalk.white('.env')} (Appended JWT_SECRET)`));\n } else {\n fs.writeFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('.env')}`));\n }\n }\n\n console.log(chalk.bold.white('\\nKroxt is ready. Happy coding! \uD83D\uDE80\\n'));\n\n } catch (err) {\n console.error(chalk.red('\\n\u2716 Initialization cancelled.'));\n process.exit(1);\n }\n });\n\nprogram.parse(process.argv);\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport Enquirer from 'enquirer';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { spawn } from 'child_process';\nimport { authTemplate, envTemplate, tsConfigTemplate } from './templates.js';\n\nconst program = new Command();\nconst enquirer = new Enquirer();\n\nprogram\n .name('kroxt')\n .description('Kroxt CLI for bootstrapping auth engines')\n .version('1.3.1');\n\nprogram\n .command('init')\n .description('Initialize Kroxt in your project')\n .option('-y, --yes', 'Skip prompts and use defaults')\n .action(async (options) => {\n console.log(chalk.bold.white('\\n\u2B22 KROXT AUTH INITIALIZER\\n'));\n\n try {\n let response = {\n adapter: 'memory',\n generateEnv: true,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true,\n createModel: true,\n targetDir: ''\n };\n\n const projectContext = getProjectContext();\n const defaultDir = projectContext.isExpress ? (projectContext.hasSrc ? 'src/config' : 'config') : (projectContext.hasSrc ? 'src/lib/kroxt' : 'lib/kroxt');\n\n if (!options.yes) {\n response = await enquirer.prompt([\n {\n type: 'select',\n name: 'adapter',\n message: 'Choose your database adapter:',\n choices: [\n { name: 'memory', message: 'In-Memory (Testing)' },\n { name: 'mongoose', message: 'Mongoose (MongoDB)' },\n { name: 'prisma', message: 'Prisma (PostgreSQL/MySQL)' },\n { name: 'drizzle', message: 'Drizzle (SQLite/PostgreSQL)' },\n { name: 'none', message: 'None (Manual Setup)' }\n ]\n },\n {\n type: 'input',\n name: 'targetDir',\n message: 'Where should I put the Kroxt files?',\n initial: defaultDir\n },\n {\n type: 'confirm',\n name: 'useRateLimit',\n message: 'Enable rate limiting defensive layer?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useIPBlocking',\n message: 'Enable automatic IP blocking?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'useStrictRevocation',\n message: 'Enforce strict session revocation?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'usePepper',\n message: 'Use server-side password peppering?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'createModel',\n message: 'Create a boilerplate User model for you?',\n initial: true\n },\n {\n type: 'confirm',\n name: 'generateEnv',\n message: 'Generate secure secrets in .env?',\n initial: true\n }\n ]) as any;\n } else {\n console.log(chalk.gray('Using default settings (--yes)...'));\n response = {\n ...response,\n useRateLimit: true,\n useIPBlocking: true,\n useStrictRevocation: true,\n usePepper: true,\n createModel: true,\n targetDir: defaultDir\n } as any;\n }\n\n const secret = crypto.randomBytes(32).toString('hex');\n const authContent = authTemplate(response.adapter, secret, response);\n\n // Write auth.ts\n const authPath = path.join(process.cwd(), response.targetDir, 'auth.ts');\n const dirPath = path.dirname(authPath);\n\n if (!fs.existsSync(dirPath)) {\n fs.mkdirSync(dirPath, { recursive: true });\n }\n\n fs.writeFileSync(authPath, authContent);\n console.log(chalk.green(`\\n\u2714 Created: ${chalk.white(path.relative(process.cwd(), authPath))}`));\n\n // Write tsconfig.json if not present\n const tsConfigPath = path.join(process.cwd(), 'tsconfig.json');\n if (!fs.existsSync(tsConfigPath)) {\n fs.writeFileSync(tsConfigPath, tsConfigTemplate);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('tsconfig.json')}`));\n }\n\n // Write User Model if requested\n if (response.createModel && response.adapter !== 'memory' && response.adapter !== 'none') {\n let modelPath = '';\n switch (response.adapter) {\n case 'mongoose':\n modelPath = path.join(process.cwd(), response.targetDir, 'user.model.ts');\n break;\n case 'drizzle':\n modelPath = path.join(process.cwd(), response.targetDir, 'schema.ts');\n break;\n case 'prisma':\n modelPath = path.join(process.cwd(), response.targetDir, 'user.prisma');\n break;\n }\n\n if (modelPath) {\n const modelDirPath = path.dirname(modelPath);\n if (!fs.existsSync(modelDirPath)) {\n fs.mkdirSync(modelDirPath, { recursive: true });\n }\n \n const { userModelTemplate } = await import('./templates.js');\n fs.writeFileSync(modelPath, userModelTemplate(response.adapter));\n console.log(chalk.green(`\u2714 Created: ${chalk.white(path.relative(process.cwd(), modelPath))}`));\n }\n }\n\n // Write .env\n if (response.generateEnv) {\n const envPath = path.join(process.cwd(), '.env');\n const envContent = envTemplate(secret, response.usePepper);\n \n if (fs.existsSync(envPath)) {\n fs.appendFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Updated: ${chalk.white('.env')} (Appended JWT_SECRET)`));\n } else {\n fs.writeFileSync(envPath, envContent);\n console.log(chalk.green(`\u2714 Created: ${chalk.white('.env')}`));\n }\n }\n\n console.log(chalk.bold.white('\\nKroxt is ready. Happy coding! \uD83D\uDE80\\n'));\n\n // --- DEPENDENCY AUTO-INSTALLATION ---\n await checkAndInstallDeps(response.adapter, !!options.yes);\n\n } catch (err) {\n console.error(chalk.red('\\n\u2716 Initialization cancelled.'));\n process.exit(1);\n }\n });\n\nasync function checkAndInstallDeps(adapter: string, skipPrompts: boolean = false) {\n const pkgPath = path.join(process.cwd(), 'package.json');\n if (!fs.existsSync(pkgPath)) return;\n\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n const required: Record<string, string[]> = {\n memory: ['kroxt', 'dotenv'],\n mongoose: ['kroxt', 'mongoose', 'dotenv'],\n prisma: ['kroxt', '@prisma/client', 'dotenv'],\n drizzle: ['kroxt', 'drizzle-orm', 'dotenv'],\n none: ['kroxt']\n };\n\n const packages = required[adapter] || [];\n const missing = packages.filter(dep => !deps[dep]);\n\n if (missing.length > 0) {\n let confirm = true;\n\n if (!skipPrompts) {\n const enquirer = new Enquirer();\n const result = await enquirer.prompt({\n type: 'confirm',\n name: 'confirm',\n message: `Required dependencies are missing: ${chalk.cyan(missing.join(', '))}. Install them now?`,\n initial: true\n }) as any;\n confirm = result.confirm;\n }\n\n if (confirm) {\n console.log(chalk.gray(`\\nInstalling ${missing.join(', ')}...`));\n return new Promise((resolve) => {\n const child = spawn('npm', ['install', ...missing], { \n stdio: 'inherit',\n shell: true \n });\n child.on('close', resolve);\n });\n }\n }\n}\n\nfunction getProjectContext() {\n const hasSrc = fs.existsSync(path.join(process.cwd(), 'src'));\n const pkgPath = path.join(process.cwd(), 'package.json');\n let isExpress = false;\n let isNext = false;\n\n if (fs.existsSync(pkgPath)) {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n isExpress = !!(deps.express || deps.fastify);\n isNext = !!deps.next;\n }\n\n return { hasSrc, isExpress, isNext };\n}\n\nprogram.parse(process.argv);\n"],
5
+ "mappings": "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",
6
+ "names": ["enquirer"]
7
7
  }
@@ -30,7 +30,8 @@ var templates_exports = {};
30
30
  __export(templates_exports, {
31
31
  authTemplate: () => authTemplate,
32
32
  envTemplate: () => envTemplate,
33
- tsConfigTemplate: () => tsConfigTemplate
33
+ tsConfigTemplate: () => tsConfigTemplate,
34
+ userModelTemplate: () => userModelTemplate
34
35
  });
35
36
  module.exports = __toCommonJS(templates_exports);
36
37
  var import_crypto = __toESM(require("crypto"), 1);
@@ -40,7 +41,7 @@ import dotenv from "dotenv";
40
41
 
41
42
  dotenv.config();
42
43
 
43
- ${getAdapterInitialization(adapter)}
44
+ ${getAdapterInitialization(adapter, options)}
44
45
 
45
46
  export const auth = createAuth({
46
47
  adapter: authAdapter,
@@ -98,19 +99,20 @@ import { eq } from "drizzle-orm";`;
98
99
  return "";
99
100
  }
100
101
  }
101
- function getAdapterInitialization(adapter) {
102
+ function getAdapterInitialization(adapter, options) {
103
+ const modelImported = options.createModel;
102
104
  switch (adapter) {
103
105
  case "mongoose":
104
- return `// import { User } from "../models/user.model.js";
106
+ return `${modelImported ? 'import { User } from "./user.model.js";' : '// import { User } from "./user.model.js";'}
107
+
105
108
  // The rate limit model is optional but recommended
106
109
  const authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;
107
110
  case "prisma":
108
111
  return `// import { prisma } from "./lib/prisma";
109
112
  const authAdapter = createPrismaAdapter(prisma.user);`;
110
113
  case "drizzle":
111
- return `// import { db } from "./db";
112
- // import { users } from "./db/schema";
113
- // import { eq } from "drizzle-orm";
114
+ return `${modelImported ? 'import { db } from "./index.js";\nimport { users } from "./schema.js";' : '// import { db } from "./index";\n// import { users } from "./schema";'}
115
+
114
116
  const authAdapter = createDrizzleAdapter(db, users, eq);`;
115
117
  case "memory":
116
118
  return `const authAdapter = createMemoryAdapter();`;
@@ -118,6 +120,58 @@ const authAdapter = createDrizzleAdapter(db, users, eq);`;
118
120
  return `// const authAdapter = ...;`;
119
121
  }
120
122
  }
123
+ const userModelTemplate = (adapter) => {
124
+ switch (adapter) {
125
+ case "mongoose":
126
+ return `import mongoose, { Schema, Document } from "mongoose";
127
+
128
+ export interface IUser extends Document {
129
+ email: string;
130
+ passwordHash?: string;
131
+ role?: string;
132
+ createdAt: Date;
133
+ updatedAt: Date;
134
+ }
135
+
136
+ const UserSchema: Schema = new Schema(
137
+ {
138
+ email: { type: String, required: true, unique: true },
139
+ passwordHash: { type: String },
140
+ role: { type: String, default: "user" },
141
+ },
142
+ { timestamps: true }
143
+ );
144
+
145
+ export const User = mongoose.models.User || mongoose.model<IUser>("User", UserSchema);
146
+ `;
147
+ case "drizzle":
148
+ return `import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
149
+
150
+ export const users = pgTable("users", {
151
+ id: text("id").primaryKey(),
152
+ email: text("email").unique().notNull(),
153
+ passwordHash: text("password_hash"),
154
+ role: text("role").default("user"),
155
+ createdAt: timestamp("created_at").defaultNow().notNull(),
156
+ updatedAt: timestamp("updated_at").defaultNow().notNull(),
157
+ });
158
+ `;
159
+ case "prisma":
160
+ return `// Add this to your schema.prisma file:
161
+
162
+ model User {
163
+ id String @id @default(cuid())
164
+ email String @unique
165
+ passwordHash String?
166
+ role String @default("user")
167
+ createdAt DateTime @default(now())
168
+ updatedAt DateTime @updatedAt
169
+ }
170
+ `;
171
+ default:
172
+ return "";
173
+ }
174
+ };
121
175
  const envTemplate = (secret, usePepper) => `
122
176
  # Kroxt Auth Secrets
123
177
  JWT_SECRET="${secret}"
@@ -142,6 +196,7 @@ const tsConfigTemplate = `{
142
196
  0 && (module.exports = {
143
197
  authTemplate,
144
198
  envTemplate,
145
- tsConfigTemplate
199
+ tsConfigTemplate,
200
+ userModelTemplate
146
201
  });
147
202
  //# sourceMappingURL=templates.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/templates.ts"],
4
- "sourcesContent": ["import crypto from 'crypto';\n\nexport const authTemplate = (adapter: string, secret: string, options: any) => `import { createAuth } from \"kroxt\";\n${getAdapterImportBlock(adapter)}\nimport dotenv from \"dotenv\";\n\ndotenv.config();\n\n${getAdapterInitialization(adapter)}\n\nexport const auth = createAuth({\n adapter: authAdapter,\n secret: process.env.JWT_SECRET || \"${secret}\",\n ${options.usePepper ? 'pepper: process.env.JWT_PEPPER || \"\",' : ''}\n \n // Global Security Configurations\n session: {\n expires: \"15m\",\n refreshExpires: \"7d\",\n enforceStrictRevocation: ${options.useStrictRevocation ? 'true' : 'false'}\n },\n \n // Custom JWT Payload logic\n jwt: {\n payload: (user: any, type: \"access\" | \"refresh\") => {\n if (type === \"access\") {\n return {\n role: user.role,\n // schoolId: user.schoolId \n };\n }\n return {};\n }\n },\n\n ${options.useRateLimit ? `rateLimit: {\n max: 100, // Requests per minute\n windowMs: 60 * 1000\n },` : ''}\n ${options.useIPBlocking ? `ipBlocking: {\n maxStrikes: 5,\n blockDurationMs: 15 * 60 * 1000\n },` : ''}\n passwordPolicy: {\n minLength: 6,\n requireUppercase: true,\n requireSpecialCharacter: true\n }\n});\n`;\n\nfunction getAdapterImportBlock(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `import { createMongoAdapter, createRateLimitModel } from \"kroxt/adapters/mongoose\";\\nimport mongoose from \"mongoose\";`;\n case 'prisma':\n return `import { createPrismaAdapter } from \"kroxt/adapters/prisma\";`;\n case 'drizzle':\n return `import { createDrizzleAdapter } from \"kroxt/adapters/drizzle\";\\nimport { eq } from \"drizzle-orm\";`;\n case 'memory':\n return `import { createMemoryAdapter } from \"kroxt/adapters/memory\";`;\n default:\n return '';\n }\n}\n\nfunction getAdapterInitialization(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `// import { User } from \"../models/user.model.js\";\\n// The rate limit model is optional but recommended\\nconst authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;\n case 'prisma':\n return `// import { prisma } from \"./lib/prisma\";\\nconst authAdapter = createPrismaAdapter(prisma.user);`;\n case 'drizzle':\n return `// import { db } from \"./db\";\\n// import { users } from \"./db/schema\";\\n// import { eq } from \"drizzle-orm\";\\nconst authAdapter = createDrizzleAdapter(db, users, eq);`;\n case 'memory':\n return `const authAdapter = createMemoryAdapter();`;\n default:\n return `// const authAdapter = ...;`;\n }\n}\n\nexport const envTemplate = (secret: string, usePepper: boolean) => `\n# Kroxt Auth Secrets\nJWT_SECRET=\"${secret}\"\n${usePepper ? `JWT_PEPPER=\"${crypto.randomBytes(16).toString('hex')}\"` : ''}\n`;\n\nexport const tsConfigTemplate = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"esModuleInterop\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"strict\": true,\n \"skipLibCheck\": true,\n \"types\": [\"node\"]\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\"]\n}\n`;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AAEZ,MAAM,eAAe,CAAC,SAAiB,QAAgB,YAAiB;AAAA,EAC7E,sBAAsB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,uCAII,MAAM;AAAA,IACzC,QAAQ,YAAY,0CAA0C,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAMrC,QAAQ,sBAAsB,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBzE,QAAQ,eAAe;AAAA;AAAA;AAAA,QAGnB,EAAE;AAAA,IACN,QAAQ,gBAAgB;AAAA;AAAA;AAAA,QAGpB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASV,SAAS,sBAAsB,SAAiB;AAC9C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,yBAAyB,SAAiB;AACjD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,cAAc,CAAC,QAAgB,cAAuB;AAAA;AAAA,cAErD,MAAM;AAAA,EAClB,YAAY,eAAe,cAAAA,QAAO,YAAY,EAAE,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE;AAAA;AAGpE,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["import crypto from 'crypto';\n\nexport const authTemplate = (adapter: string, secret: string, options: any) => `import { createAuth } from \"kroxt\";\n${getAdapterImportBlock(adapter)}\nimport dotenv from \"dotenv\";\n\ndotenv.config();\n\n${getAdapterInitialization(adapter, options)}\n\nexport const auth = createAuth({\n adapter: authAdapter,\n secret: process.env.JWT_SECRET || \"${secret}\",\n ${options.usePepper ? 'pepper: process.env.JWT_PEPPER || \"\",' : ''}\n \n // Global Security Configurations\n session: {\n expires: \"15m\",\n refreshExpires: \"7d\",\n enforceStrictRevocation: ${options.useStrictRevocation ? 'true' : 'false'}\n },\n \n // Custom JWT Payload logic\n jwt: {\n payload: (user: any, type: \"access\" | \"refresh\") => {\n if (type === \"access\") {\n return {\n role: user.role,\n // schoolId: user.schoolId \n };\n }\n return {};\n }\n },\n\n ${options.useRateLimit ? `rateLimit: {\n max: 100, // Requests per minute\n windowMs: 60 * 1000\n },` : ''}\n ${options.useIPBlocking ? `ipBlocking: {\n maxStrikes: 5,\n blockDurationMs: 15 * 60 * 1000\n },` : ''}\n passwordPolicy: {\n minLength: 6,\n requireUppercase: true,\n requireSpecialCharacter: true\n }\n});\n`;\n\nfunction getAdapterImportBlock(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `import { createMongoAdapter, createRateLimitModel } from \"kroxt/adapters/mongoose\";\\nimport mongoose from \"mongoose\";`;\n case 'prisma':\n return `import { createPrismaAdapter } from \"kroxt/adapters/prisma\";`;\n case 'drizzle':\n return `import { createDrizzleAdapter } from \"kroxt/adapters/drizzle\";\\nimport { eq } from \"drizzle-orm\";`;\n case 'memory':\n return `import { createMemoryAdapter } from \"kroxt/adapters/memory\";`;\n default:\n return '';\n }\n}\n\nfunction getAdapterInitialization(adapter: string, options: any) {\n const modelImported = options.createModel;\n switch (adapter) {\n case 'mongoose':\n return `${modelImported ? 'import { User } from \"./user.model.js\";' : '// import { User } from \"./user.model.js\";'}\\n\\n// The rate limit model is optional but recommended\\nconst authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;\n case 'prisma':\n return `// import { prisma } from \"./lib/prisma\";\\nconst authAdapter = createPrismaAdapter(prisma.user);`;\n case 'drizzle':\n return `${modelImported ? 'import { db } from \"./index.js\";\\nimport { users } from \"./schema.js\";' : '// import { db } from \"./index\";\\n// import { users } from \"./schema\";'}\\n\\nconst authAdapter = createDrizzleAdapter(db, users, eq);`;\n case 'memory':\n return `const authAdapter = createMemoryAdapter();`;\n default:\n return `// const authAdapter = ...;`;\n }\n}\n\nexport const userModelTemplate = (adapter: string) => {\n switch (adapter) {\n case 'mongoose':\n return `import mongoose, { Schema, Document } from \"mongoose\";\n\nexport interface IUser extends Document {\n email: string;\n passwordHash?: string;\n role?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst UserSchema: Schema = new Schema(\n {\n email: { type: String, required: true, unique: true },\n passwordHash: { type: String },\n role: { type: String, default: \"user\" },\n },\n { timestamps: true }\n);\n\nexport const User = mongoose.models.User || mongoose.model<IUser>(\"User\", UserSchema);\n`;\n case 'drizzle':\n return `import { pgTable, text, timestamp } from \"drizzle-orm/pg-core\";\n\nexport const users = pgTable(\"users\", {\n id: text(\"id\").primaryKey(),\n email: text(\"email\").unique().notNull(),\n passwordHash: text(\"password_hash\"),\n role: text(\"role\").default(\"user\"),\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\n});\n`;\n case 'prisma':\n return `// Add this to your schema.prisma file:\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n passwordHash String?\n role String @default(\"user\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n`;\n default:\n return '';\n }\n};\n\nexport const envTemplate = (secret: string, usePepper: boolean) => `\n# Kroxt Auth Secrets\nJWT_SECRET=\"${secret}\"\n${usePepper ? `JWT_PEPPER=\"${crypto.randomBytes(16).toString('hex')}\"` : ''}\n`;\n\nexport const tsConfigTemplate = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"esModuleInterop\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"strict\": true,\n \"skipLibCheck\": true,\n \"types\": [\"node\"]\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\"]\n}\n`;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AAEZ,MAAM,eAAe,CAAC,SAAiB,QAAgB,YAAiB;AAAA,EAC7E,sBAAsB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,yBAAyB,SAAS,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,uCAIL,MAAM;AAAA,IACzC,QAAQ,YAAY,0CAA0C,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAMrC,QAAQ,sBAAsB,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBzE,QAAQ,eAAe;AAAA;AAAA;AAAA,QAGnB,EAAE;AAAA,IACN,QAAQ,gBAAgB;AAAA;AAAA;AAAA,QAGpB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASV,SAAS,sBAAsB,SAAiB;AAC9C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,yBAAyB,SAAiB,SAAc;AAC/D,QAAM,gBAAgB,QAAQ;AAC9B,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,GAAG,gBAAgB,4CAA4C,4CAA4C;AAAA;AAAA;AAAA;AAAA,IACpH,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO,GAAG,gBAAgB,2EAA2E,wEAAwE;AAAA;AAAA;AAAA,IAC/K,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,oBAAoB,CAAC,YAAoB;AACpD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,cAAc,CAAC,QAAgB,cAAuB;AAAA;AAAA,cAErD,MAAM;AAAA,EAClB,YAAY,eAAe,cAAAA,QAAO,YAAY,EAAE,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE;AAAA;AAGpE,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": ["crypto"]
7
7
  }
@@ -5,7 +5,7 @@ import dotenv from "dotenv";
5
5
 
6
6
  dotenv.config();
7
7
 
8
- ${getAdapterInitialization(adapter)}
8
+ ${getAdapterInitialization(adapter, options)}
9
9
 
10
10
  export const auth = createAuth({
11
11
  adapter: authAdapter,
@@ -63,19 +63,20 @@ import { eq } from "drizzle-orm";`;
63
63
  return "";
64
64
  }
65
65
  }
66
- function getAdapterInitialization(adapter) {
66
+ function getAdapterInitialization(adapter, options) {
67
+ const modelImported = options.createModel;
67
68
  switch (adapter) {
68
69
  case "mongoose":
69
- return `// import { User } from "../models/user.model.js";
70
+ return `${modelImported ? 'import { User } from "./user.model.js";' : '// import { User } from "./user.model.js";'}
71
+
70
72
  // The rate limit model is optional but recommended
71
73
  const authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;
72
74
  case "prisma":
73
75
  return `// import { prisma } from "./lib/prisma";
74
76
  const authAdapter = createPrismaAdapter(prisma.user);`;
75
77
  case "drizzle":
76
- return `// import { db } from "./db";
77
- // import { users } from "./db/schema";
78
- // import { eq } from "drizzle-orm";
78
+ return `${modelImported ? 'import { db } from "./index.js";\nimport { users } from "./schema.js";' : '// import { db } from "./index";\n// import { users } from "./schema";'}
79
+
79
80
  const authAdapter = createDrizzleAdapter(db, users, eq);`;
80
81
  case "memory":
81
82
  return `const authAdapter = createMemoryAdapter();`;
@@ -83,6 +84,58 @@ const authAdapter = createDrizzleAdapter(db, users, eq);`;
83
84
  return `// const authAdapter = ...;`;
84
85
  }
85
86
  }
87
+ const userModelTemplate = (adapter) => {
88
+ switch (adapter) {
89
+ case "mongoose":
90
+ return `import mongoose, { Schema, Document } from "mongoose";
91
+
92
+ export interface IUser extends Document {
93
+ email: string;
94
+ passwordHash?: string;
95
+ role?: string;
96
+ createdAt: Date;
97
+ updatedAt: Date;
98
+ }
99
+
100
+ const UserSchema: Schema = new Schema(
101
+ {
102
+ email: { type: String, required: true, unique: true },
103
+ passwordHash: { type: String },
104
+ role: { type: String, default: "user" },
105
+ },
106
+ { timestamps: true }
107
+ );
108
+
109
+ export const User = mongoose.models.User || mongoose.model<IUser>("User", UserSchema);
110
+ `;
111
+ case "drizzle":
112
+ return `import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
113
+
114
+ export const users = pgTable("users", {
115
+ id: text("id").primaryKey(),
116
+ email: text("email").unique().notNull(),
117
+ passwordHash: text("password_hash"),
118
+ role: text("role").default("user"),
119
+ createdAt: timestamp("created_at").defaultNow().notNull(),
120
+ updatedAt: timestamp("updated_at").defaultNow().notNull(),
121
+ });
122
+ `;
123
+ case "prisma":
124
+ return `// Add this to your schema.prisma file:
125
+
126
+ model User {
127
+ id String @id @default(cuid())
128
+ email String @unique
129
+ passwordHash String?
130
+ role String @default("user")
131
+ createdAt DateTime @default(now())
132
+ updatedAt DateTime @updatedAt
133
+ }
134
+ `;
135
+ default:
136
+ return "";
137
+ }
138
+ };
86
139
  const envTemplate = (secret, usePepper) => `
87
140
  # Kroxt Auth Secrets
88
141
  JWT_SECRET="${secret}"
@@ -106,6 +159,7 @@ const tsConfigTemplate = `{
106
159
  export {
107
160
  authTemplate,
108
161
  envTemplate,
109
- tsConfigTemplate
162
+ tsConfigTemplate,
163
+ userModelTemplate
110
164
  };
111
165
  //# sourceMappingURL=templates.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/cli/templates.ts"],
4
- "sourcesContent": ["import crypto from 'crypto';\n\nexport const authTemplate = (adapter: string, secret: string, options: any) => `import { createAuth } from \"kroxt\";\n${getAdapterImportBlock(adapter)}\nimport dotenv from \"dotenv\";\n\ndotenv.config();\n\n${getAdapterInitialization(adapter)}\n\nexport const auth = createAuth({\n adapter: authAdapter,\n secret: process.env.JWT_SECRET || \"${secret}\",\n ${options.usePepper ? 'pepper: process.env.JWT_PEPPER || \"\",' : ''}\n \n // Global Security Configurations\n session: {\n expires: \"15m\",\n refreshExpires: \"7d\",\n enforceStrictRevocation: ${options.useStrictRevocation ? 'true' : 'false'}\n },\n \n // Custom JWT Payload logic\n jwt: {\n payload: (user: any, type: \"access\" | \"refresh\") => {\n if (type === \"access\") {\n return {\n role: user.role,\n // schoolId: user.schoolId \n };\n }\n return {};\n }\n },\n\n ${options.useRateLimit ? `rateLimit: {\n max: 100, // Requests per minute\n windowMs: 60 * 1000\n },` : ''}\n ${options.useIPBlocking ? `ipBlocking: {\n maxStrikes: 5,\n blockDurationMs: 15 * 60 * 1000\n },` : ''}\n passwordPolicy: {\n minLength: 6,\n requireUppercase: true,\n requireSpecialCharacter: true\n }\n});\n`;\n\nfunction getAdapterImportBlock(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `import { createMongoAdapter, createRateLimitModel } from \"kroxt/adapters/mongoose\";\\nimport mongoose from \"mongoose\";`;\n case 'prisma':\n return `import { createPrismaAdapter } from \"kroxt/adapters/prisma\";`;\n case 'drizzle':\n return `import { createDrizzleAdapter } from \"kroxt/adapters/drizzle\";\\nimport { eq } from \"drizzle-orm\";`;\n case 'memory':\n return `import { createMemoryAdapter } from \"kroxt/adapters/memory\";`;\n default:\n return '';\n }\n}\n\nfunction getAdapterInitialization(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `// import { User } from \"../models/user.model.js\";\\n// The rate limit model is optional but recommended\\nconst authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;\n case 'prisma':\n return `// import { prisma } from \"./lib/prisma\";\\nconst authAdapter = createPrismaAdapter(prisma.user);`;\n case 'drizzle':\n return `// import { db } from \"./db\";\\n// import { users } from \"./db/schema\";\\n// import { eq } from \"drizzle-orm\";\\nconst authAdapter = createDrizzleAdapter(db, users, eq);`;\n case 'memory':\n return `const authAdapter = createMemoryAdapter();`;\n default:\n return `// const authAdapter = ...;`;\n }\n}\n\nexport const envTemplate = (secret: string, usePepper: boolean) => `\n# Kroxt Auth Secrets\nJWT_SECRET=\"${secret}\"\n${usePepper ? `JWT_PEPPER=\"${crypto.randomBytes(16).toString('hex')}\"` : ''}\n`;\n\nexport const tsConfigTemplate = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"esModuleInterop\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"strict\": true,\n \"skipLibCheck\": true,\n \"types\": [\"node\"]\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\"]\n}\n`;\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AAEZ,MAAM,eAAe,CAAC,SAAiB,QAAgB,YAAiB;AAAA,EAC7E,sBAAsB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,yBAAyB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,uCAII,MAAM;AAAA,IACzC,QAAQ,YAAY,0CAA0C,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAMrC,QAAQ,sBAAsB,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBzE,QAAQ,eAAe;AAAA;AAAA;AAAA,QAGnB,EAAE;AAAA,IACN,QAAQ,gBAAgB;AAAA;AAAA;AAAA,QAGpB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASV,SAAS,sBAAsB,SAAiB;AAC9C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,yBAAyB,SAAiB;AACjD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,cAAc,CAAC,QAAgB,cAAuB;AAAA;AAAA,cAErD,MAAM;AAAA,EAClB,YAAY,eAAe,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE;AAAA;AAGpE,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
4
+ "sourcesContent": ["import crypto from 'crypto';\n\nexport const authTemplate = (adapter: string, secret: string, options: any) => `import { createAuth } from \"kroxt\";\n${getAdapterImportBlock(adapter)}\nimport dotenv from \"dotenv\";\n\ndotenv.config();\n\n${getAdapterInitialization(adapter, options)}\n\nexport const auth = createAuth({\n adapter: authAdapter,\n secret: process.env.JWT_SECRET || \"${secret}\",\n ${options.usePepper ? 'pepper: process.env.JWT_PEPPER || \"\",' : ''}\n \n // Global Security Configurations\n session: {\n expires: \"15m\",\n refreshExpires: \"7d\",\n enforceStrictRevocation: ${options.useStrictRevocation ? 'true' : 'false'}\n },\n \n // Custom JWT Payload logic\n jwt: {\n payload: (user: any, type: \"access\" | \"refresh\") => {\n if (type === \"access\") {\n return {\n role: user.role,\n // schoolId: user.schoolId \n };\n }\n return {};\n }\n },\n\n ${options.useRateLimit ? `rateLimit: {\n max: 100, // Requests per minute\n windowMs: 60 * 1000\n },` : ''}\n ${options.useIPBlocking ? `ipBlocking: {\n maxStrikes: 5,\n blockDurationMs: 15 * 60 * 1000\n },` : ''}\n passwordPolicy: {\n minLength: 6,\n requireUppercase: true,\n requireSpecialCharacter: true\n }\n});\n`;\n\nfunction getAdapterImportBlock(adapter: string) {\n switch (adapter) {\n case 'mongoose':\n return `import { createMongoAdapter, createRateLimitModel } from \"kroxt/adapters/mongoose\";\\nimport mongoose from \"mongoose\";`;\n case 'prisma':\n return `import { createPrismaAdapter } from \"kroxt/adapters/prisma\";`;\n case 'drizzle':\n return `import { createDrizzleAdapter } from \"kroxt/adapters/drizzle\";\\nimport { eq } from \"drizzle-orm\";`;\n case 'memory':\n return `import { createMemoryAdapter } from \"kroxt/adapters/memory\";`;\n default:\n return '';\n }\n}\n\nfunction getAdapterInitialization(adapter: string, options: any) {\n const modelImported = options.createModel;\n switch (adapter) {\n case 'mongoose':\n return `${modelImported ? 'import { User } from \"./user.model.js\";' : '// import { User } from \"./user.model.js\";'}\\n\\n// The rate limit model is optional but recommended\\nconst authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;\n case 'prisma':\n return `// import { prisma } from \"./lib/prisma\";\\nconst authAdapter = createPrismaAdapter(prisma.user);`;\n case 'drizzle':\n return `${modelImported ? 'import { db } from \"./index.js\";\\nimport { users } from \"./schema.js\";' : '// import { db } from \"./index\";\\n// import { users } from \"./schema\";'}\\n\\nconst authAdapter = createDrizzleAdapter(db, users, eq);`;\n case 'memory':\n return `const authAdapter = createMemoryAdapter();`;\n default:\n return `// const authAdapter = ...;`;\n }\n}\n\nexport const userModelTemplate = (adapter: string) => {\n switch (adapter) {\n case 'mongoose':\n return `import mongoose, { Schema, Document } from \"mongoose\";\n\nexport interface IUser extends Document {\n email: string;\n passwordHash?: string;\n role?: string;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst UserSchema: Schema = new Schema(\n {\n email: { type: String, required: true, unique: true },\n passwordHash: { type: String },\n role: { type: String, default: \"user\" },\n },\n { timestamps: true }\n);\n\nexport const User = mongoose.models.User || mongoose.model<IUser>(\"User\", UserSchema);\n`;\n case 'drizzle':\n return `import { pgTable, text, timestamp } from \"drizzle-orm/pg-core\";\n\nexport const users = pgTable(\"users\", {\n id: text(\"id\").primaryKey(),\n email: text(\"email\").unique().notNull(),\n passwordHash: text(\"password_hash\"),\n role: text(\"role\").default(\"user\"),\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\n});\n`;\n case 'prisma':\n return `// Add this to your schema.prisma file:\n\nmodel User {\n id String @id @default(cuid())\n email String @unique\n passwordHash String?\n role String @default(\"user\")\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n`;\n default:\n return '';\n }\n};\n\nexport const envTemplate = (secret: string, usePepper: boolean) => `\n# Kroxt Auth Secrets\nJWT_SECRET=\"${secret}\"\n${usePepper ? `JWT_PEPPER=\"${crypto.randomBytes(16).toString('hex')}\"` : ''}\n`;\n\nexport const tsConfigTemplate = `{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"esModuleInterop\": true,\n \"forceConsistentCasingInFileNames\": true,\n \"strict\": true,\n \"skipLibCheck\": true,\n \"types\": [\"node\"]\n },\n \"include\": [\"src/**/*\"],\n \"exclude\": [\"node_modules\"]\n}\n`;\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AAEZ,MAAM,eAAe,CAAC,SAAiB,QAAgB,YAAiB;AAAA,EAC7E,sBAAsB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,yBAAyB,SAAS,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,uCAIL,MAAM;AAAA,IACzC,QAAQ,YAAY,0CAA0C,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAMrC,QAAQ,sBAAsB,SAAS,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBzE,QAAQ,eAAe;AAAA;AAAA;AAAA,QAGnB,EAAE;AAAA,IACN,QAAQ,gBAAgB;AAAA;AAAA;AAAA,QAGpB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASV,SAAS,sBAAsB,SAAiB;AAC9C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,yBAAyB,SAAiB,SAAc;AAC/D,QAAM,gBAAgB,QAAQ;AAC9B,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,GAAG,gBAAgB,4CAA4C,4CAA4C;AAAA;AAAA;AAAA;AAAA,IACpH,KAAK;AACH,aAAO;AAAA;AAAA,IACT,KAAK;AACH,aAAO,GAAG,gBAAgB,2EAA2E,wEAAwE;AAAA;AAAA;AAAA,IAC/K,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,oBAAoB,CAAC,YAAoB;AACpD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAqBT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWT,KAAK;AACH,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWT;AACE,aAAO;AAAA,EACX;AACF;AAEO,MAAM,cAAc,CAAC,QAAgB,cAAuB;AAAA;AAAA,cAErD,MAAM;AAAA,EAClB,YAAY,eAAe,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK,CAAC,MAAM,EAAE;AAAA;AAGpE,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kroxt",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "bin": {
5
5
  "kroxt": "./dist/cli/index.js"
6
6
  },