kroxt 1.3.3 β†’ 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,116 +1,231 @@
1
- # Kroxt πŸ–€πŸ€
2
-
3
- A framework-agnostic, modular authentication engine for modern TypeScript applications. Built for security, extensibility, and pure developer joy.
4
-
5
- [![npm version](https://img.shields.io/npm/v/kroxt.svg)](https://www.npmjs.com/package/kroxt)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg)](https://opensource.org/licenses/MIT)
7
-
8
- > [!IMPORTANT]
9
- > **What's New in v1.3.0**: The **Kroxt CLI** is here! Bootstrap your entire auth engine in seconds with `npx kroxt init`. Also featuring a premium **Monochrome rebranding** and advanced **IP-Blocking** defense.
10
-
11
- ---
12
-
13
- ## ⚑ Quick Start (The Recommended Way)
14
-
15
- The fastest way to get started with Kroxt is using our interactive initializer:
16
-
17
- ```bash
18
- npx kroxt init
19
- ```
20
-
21
- This will guide you through:
22
- - πŸ—οΈ Choosing your database adapter (**Mongoose**, **Prisma**, **Drizzle**, or **Memory**).
23
- - πŸ›‘οΈ Configuring security layers (**Rate Limiting**, **IP Blocking**, **Peppering**).
24
- - πŸ”‘ Generating secure **JWT_SECRET** and **JWT_PEPPER** in your `.env`.
25
- - βš™οΈ Setting up a modern **tsconfig.json**.
26
-
27
- ---
28
-
29
- ## πŸš€ Why Kroxt?
30
-
31
- Authentication is often either too complex or too restrictive. Kroxt is the **"Headless" Auth Engine** that gives you the best of both worlds:
32
-
33
- - **πŸ—οΈ Database Agnostic**: Native adapters for **Prisma**, **Drizzle**, and **Mongoose**.
34
- - **πŸ› οΈ Modular**: Use only what you need. No forced session managers or UI components.
35
- - **πŸ” Security First**: Argon2 hashing, dual-token rotation, and **IP-based brute force protection** built-in.
36
- - **🧩 TypeScript Native**: Perfectly preserves your user schemas and metadata.
37
-
38
- ---
39
-
40
- ## πŸ—ΊοΈ How it Works
41
-
42
- Kroxt sits between your database and your controller logic. It handles the "heavy lifting" (hashing, JWT signing, token rotation) while you maintain full control over your API.
43
-
44
- ```mermaid
45
- graph LR
46
- A[Client] -- "Credentials" --> B[Express/Fastify/Next.js]
47
- B -- "auth.signup()" --> C[Kroxt Engine]
48
- C -- "Save User" --> D[(Database Adapter)]
49
- D -- "Success" --> C
50
- C -- "Tokens + User" --> B
51
- B -- "Set Cookies/JSON" --> A
52
-
53
- subgraph Adapters
54
- D
55
- E[Mongoose]
56
- F[Drizzle]
57
- G[Prisma]
58
- end
59
- ```
60
-
61
- ---
62
-
63
- ## πŸ›‘οΈ Core Authentication Flows
64
-
65
- ### **Registration**
66
- ```typescript
67
- const { user, accessToken, refreshToken } = await auth.signup({
68
- email,
69
- name,
70
- role: 'user'
71
- }, password);
72
- ```
73
-
74
- ### **Login**
75
- ```typescript
76
- const { user, accessToken, refreshToken } = await auth.loginWithPassword(email, password);
77
- ```
78
-
79
- ### **Token Refresh**
80
- ```typescript
81
- const { accessToken } = await auth.refresh(refreshToken);
82
- ```
83
-
84
- ---
85
-
86
- ## πŸ› οΈ Advanced: Custom JWT Payloads
87
-
88
- Want to share a user's `role` or `plan` with the frontend via the JWT? Use the `payload` hook:
89
-
90
- ```typescript
91
- export const auth = createAuth({
92
- adapter,
93
- jwt: {
94
- payload: (user, type) => {
95
- if (type === "access") {
96
- return {
97
- role: user.role,
98
- schoolId: user.schoolId
99
- };
100
- }
101
- return {};
102
- }
103
- }
104
- });
105
- ```
106
-
107
- ---
108
-
109
- ## πŸ”— Reference Projects
110
-
111
- Complete working implementations for all frameworks:
112
- - [Kroxt Examples (All Frameworks)](https://github.com/adepoju-oluwatobi/kroxt-examples)
113
-
114
- ## πŸ“„ License
115
-
116
- MIT Β© [Adepoju Oluwatobi](https://github.com/adepoju-oluwatobi)
1
+ # Kroxt
2
+
3
+ **The Most Simplified auth library**
4
+
5
+ Kroxt is a premium, framework-agnostic, and security-hardened authentication library for modern TypeScript environments. Designed for 100% schema control and "Zero-Config" onboarding.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/kroxt.svg)](https://www.npmjs.com/package/kroxt)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-black.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ---
11
+
12
+ ## ⚑ 30-Second Onboarding
13
+
14
+ The recommended way to start is the **Kroxt CLI**. It detects your framework (Next.js, Express, Fastify) and scaffolds a professional auth structure automatically.
15
+
16
+ ```bash
17
+ npx kroxt init
18
+ ```
19
+
20
+ ---
21
+
22
+ ## πŸ—οΈ Core Architecture
23
+
24
+ Kroxt is "Headless." It provides the **Brain** (Logic, Hashing, JWTs, Security) while you provide the **Face** (UI/Routes).
25
+
26
+ ### 1. The Configuration Matrix
27
+ Every feature in Kroxt is modular. Toggle security layers with a single boolean.
28
+
29
+ ```typescript
30
+ import { createAuth } from "kroxt";
31
+ import { createMongoAdapter } from "kroxt/adapters/mongoose";
32
+
33
+ export const auth = createAuth({
34
+ adapter: createMongoAdapter(UserModel),
35
+ secret: process.env.JWT_SECRET,
36
+
37
+ // Security Layer 1: Sessions
38
+ session: {
39
+ expires: "15m", // Access Token duration
40
+ refreshExpires: "7d", // Refresh Token duration
41
+ enforceStrictRevocation: true, // DB-lookup on EVERY request (Admin-mode)
42
+ },
43
+
44
+ // Security Layer 2: Defense
45
+ rateLimit: {
46
+ max: 100, // Requests per window
47
+ windowMs: 60 * 1000 // 1 Minute window
48
+ },
49
+
50
+ // Security Layer 3: Brute Force
51
+ ipBlocking: {
52
+ maxStrikes: 5, // Ban after 5 failures
53
+ blockDurationMs: 15 * 60 * 1000 // 15 Min ban
54
+ },
55
+
56
+ // Security Layer 4: Crypto
57
+ passwordPolicy: {
58
+ minLength: 8,
59
+ requireUppercase: true,
60
+ requireSpecialCharacter: true,
61
+ usePepper: true // Requires JWT_PEPPER env variable
62
+ }
63
+ });
64
+ ```
65
+
66
+ ---
67
+
68
+ ## πŸ”Œ Universal Adapters
69
+
70
+ Bring your own schema. Kroxt adapts to you.
71
+
72
+ ### Mongoose (MongoDB)
73
+ ```typescript
74
+ import { createMongoAdapter } from "kroxt/adapters/mongoose";
75
+ const adapter = createMongoAdapter(User);
76
+ ```
77
+
78
+ ### Prisma (SQL)
79
+ ```typescript
80
+ import { createPrismaAdapter } from "kroxt/adapters/prisma";
81
+ const adapter = createPrismaAdapter(prisma.user);
82
+ ```
83
+
84
+ ### Drizzle (SQL)
85
+ ```typescript
86
+ import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
87
+ import { eq } from "drizzle-orm";
88
+ const adapter = createDrizzleAdapter(db, users, eq);
89
+ ```
90
+
91
+ ### Memory (Testing)
92
+ ```typescript
93
+ import { createMemoryAdapter } from "kroxt";
94
+ const adapter = createMemoryAdapter();
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 🧠 API Reference
100
+
101
+ ### `auth.signup(userData, password)`
102
+ Registers a new user. User data is strictly typed to your schema.
103
+ ```typescript
104
+ const { user, accessToken, refreshToken } = await auth.signup({
105
+ email: "dev@kroxt.io",
106
+ role: "admin"
107
+ }, "secure_password");
108
+ ```
109
+
110
+ ### `auth.loginWithPassword(email, password, clientIp?)`
111
+ Authenticates a user and generates tokens. Pass `clientIp` to enable IP-Blocking.
112
+ ```typescript
113
+ const result = await auth.loginWithPassword(email, password, req.ip);
114
+ ```
115
+
116
+ ### `auth.refreshSession(refreshToken, clientIp?)`
117
+ Rotates the session. If `enforceStrictRevocation` is on, it validates the token against the user's current password hash.
118
+ ```typescript
119
+ const { user, accessToken, refreshToken: newRefresh } = await auth.refreshSession(token);
120
+ ```
121
+
122
+ ### `auth.logout(refreshToken)`
123
+ Invalidates a session.
124
+ ```typescript
125
+ await auth.logout(refreshToken);
126
+ ```
127
+
128
+ ### `auth.changePassword(userId, newPassword)`
129
+ Updates password and **instantly invalidates all other active sessions** globally via Hash-Linked revocation.
130
+ ```typescript
131
+ await auth.changePassword(user.id, "new_secure_pass");
132
+ ```
133
+
134
+ ---
135
+
136
+ ## 🧩 Middleware Implementation
137
+
138
+ ### Express / Fastify
139
+ ```typescript
140
+ const protect = async (req, res, next) => {
141
+ const token = req.headers.authorization?.split(" ")[1];
142
+ try {
143
+ const session = await auth.verifyAccessToken(token);
144
+ req.user = session.user;
145
+ next();
146
+ } catch (err) {
147
+ res.status(401).json({ error: "Unauthorized" });
148
+ }
149
+ };
150
+ ```
151
+
152
+ ---
153
+
154
+ ## πŸš€ Advanced Deployment
155
+
156
+ ### Custom JWT Payloads
157
+ Inject metadata into your tokens safely.
158
+ ```typescript
159
+ jwt: {
160
+ payload: (user, type) => {
161
+ return type === "access" ? { role: user.role } : {};
162
+ }
163
+ }
164
+ ```
165
+
166
+ ### Password Peppering
167
+ Kroxt supports server-side peppering to protect against rainbow table attacks even if your database is leaked.
168
+ 1. Set `usePepper: true` in config.
169
+ 2. Add `JWT_PEPPER` to your `.env`.
170
+
171
+ ---
172
+
173
+ ## 🧠 API Reference (Exhaustive)
174
+
175
+ ### `auth.signup()`
176
+ | Argument | Type | Description |
177
+ | --- | --- | --- |
178
+ | `userData` | `Omit<User, "id">` | Your user object without the ID (ID is auto-generated) |
179
+ | `password` | `string` (Optional) | Plain text password. Will be hashed using Argon2 |
180
+
181
+ ### `auth.loginWithPassword()`
182
+ | Argument | Type | Description |
183
+ | --- | --- | --- |
184
+ | `email` | `string` | User email |
185
+ | `password` | `string` | User password |
186
+ | `clientIp` | `string` (Optional) | Required for IP-Blocking defense |
187
+
188
+ ### `auth.changePassword()`
189
+ | Argument | Type | Description |
190
+ | --- | --- | --- |
191
+ | `userId` | `string` | The ID of the user to update |
192
+ | `newPassword` | `string` | The new plain text password |
193
+
194
+ > [!TIP]
195
+ > **Hash-Linked Revocation**: When you call `changePassword`, all existing refresh tokens for that user are immediately invalidated because they contain a fragment of the old password hash.
196
+
197
+ ---
198
+
199
+ ## 🚦 Error Handling
200
+
201
+ Kroxt throws descriptive errors that you can catch in your controller.
202
+
203
+ ```typescript
204
+ try {
205
+ await auth.loginWithPassword(email, password, req.ip);
206
+ } catch (err) {
207
+ if (err.message === "IP is temporarily blocked.") {
208
+ return res.status(403).send("Banned.");
209
+ }
210
+ if (err.message === "Too many requests, please try again later.") {
211
+ return res.status(429).send("Slow down.");
212
+ }
213
+ return res.status(401).send("Invalid Credentials");
214
+ }
215
+ ```
216
+
217
+ ---
218
+
219
+ ## πŸ”’ Security Best Practices
220
+
221
+ 1. **Environmental Pepper**: Always use `JWT_PEPPER`. This adds a server-side secret to every password hash. If your database is stolen, your user passwords are still protected by this environment variable.
222
+ 2. **Strict Revocation**: Set `enforceStrictRevocation: true` for high-security areas (like admin panels). This forces a database lookup on every single request to ensure the user hasn't been banned or changed their password in the last few seconds.
223
+ 3. **Dual Tokens**: Always use the provided `accessToken` for short-term API access and the `refreshToken` (stored in an `HttpOnly` cookie) for session persistence.
224
+
225
+ ---
226
+
227
+ ## πŸ”— Ecosystem
228
+ - [Kroxt Examples Repository](https://github.com/adepoju-oluwatobi/kroxt-examples)
229
+
230
+ ## πŸ“„ License
231
+ MIT Β© [Adepoju Oluwatobi](https://github.com/adepoju-oluwatobi)
@@ -23,13 +23,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  mod
24
24
  ));
25
25
  var import_commander = require("commander");
26
- var import_enquirer = require("enquirer");
26
+ var import_enquirer = __toESM(require("enquirer"), 1);
27
27
  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
31
  var import_child_process = require("child_process");
32
32
  var import_templates = require("./templates.js");
33
+ const { prompt } = import_enquirer.default;
33
34
  const program = new import_commander.Command();
34
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) => {
@@ -48,7 +49,7 @@ program.command("init").description("Initialize Kroxt in your project").option("
48
49
  const projectContext = getProjectContext();
49
50
  const defaultDir = projectContext.isExpress ? projectContext.hasSrc ? "src/config" : "config" : projectContext.hasSrc ? "src/lib/kroxt" : "lib/kroxt";
50
51
  if (!options.yes) {
51
- response = await (0, import_enquirer.prompt)([
52
+ response = await prompt([
52
53
  {
53
54
  type: "select",
54
55
  name: "adapter",
@@ -189,7 +190,7 @@ async function checkAndInstallDeps(adapter, skipPrompts = false) {
189
190
  if (missing.length > 0) {
190
191
  let confirm = true;
191
192
  if (!skipPrompts) {
192
- const result = await (0, import_enquirer.prompt)({
193
+ const result = await prompt({
193
194
  type: "confirm",
194
195
  name: "confirm",
195
196
  message: `Required dependencies are missing: ${import_chalk.default.cyan(missing.join(", "))}. Install them now?`,
@@ -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 { prompt } 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();\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 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 result = await 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": ["chalk", "crypto", "path", "fs"]
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport enquirer from 'enquirer';\nconst { prompt } = 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();\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 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 result = await 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"]
7
7
  }
package/dist/cli/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
- import { prompt } from "enquirer";
3
+ import enquirer from "enquirer";
4
+ const { prompt } = enquirer;
4
5
  import chalk from "chalk";
5
6
  import fs from "fs";
6
7
  import path from "path";
@@ -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 { prompt } 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();\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 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 result = await 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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",
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport enquirer from 'enquirer';\nconst { prompt } = 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();\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 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 result = await 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
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "kroxt",
3
- "version": "1.3.3",
3
+ "version": "1.3.7",
4
4
  "bin": {
5
5
  "kroxt": "./dist/cli/index.js"
6
6
  },
7
+ "homepage": "https://kroxt.vercel.app",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/adepoju-oluwatobi/kroxt.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/adepoju-oluwatobi/kroxt/issues"
14
+ },
15
+ "author": "Adepoju Oluwatobi <https://github.com/adepoju-oluwatobi>",
7
16
  "keywords": [
8
17
  "auth",
9
18
  "authentication",