kroxt 1.2.2 → 1.3.1
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 +116 -183
- package/dist/adapters/drizzle.d.ts +2 -1
- package/dist/adapters/drizzle.d.ts.map +1 -1
- package/dist/adapters/index.d.ts +9 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/memory.d.ts.map +1 -1
- package/dist/adapters/mongoose.d.ts +7 -1
- package/dist/adapters/mongoose.d.ts.map +1 -1
- package/dist/adapters/prisma.d.ts +2 -1
- package/dist/adapters/prisma.d.ts.map +1 -1
- package/dist/{adapters → auth/adapters}/drizzle.cjs +33 -2
- package/dist/auth/adapters/drizzle.cjs.map +7 -0
- package/dist/auth/adapters/drizzle.js +58 -0
- package/dist/auth/adapters/drizzle.js.map +7 -0
- package/dist/{adapters → auth/adapters}/index.cjs.map +2 -2
- package/dist/{adapters → auth/adapters}/memory.cjs +28 -0
- package/dist/auth/adapters/memory.cjs.map +7 -0
- package/dist/auth/adapters/memory.js +59 -0
- package/dist/auth/adapters/memory.js.map +7 -0
- package/dist/auth/adapters/mongoose.cjs +99 -0
- package/dist/auth/adapters/mongoose.cjs.map +7 -0
- package/dist/auth/adapters/mongoose.js +74 -0
- package/dist/auth/adapters/mongoose.js.map +7 -0
- package/dist/{adapters → auth/adapters}/prisma.cjs +36 -2
- package/dist/auth/adapters/prisma.cjs.map +7 -0
- package/dist/auth/adapters/prisma.js +68 -0
- package/dist/auth/adapters/prisma.js.map +7 -0
- package/dist/{core → auth/core}/index.cjs +67 -2
- package/dist/auth/core/index.cjs.map +7 -0
- package/dist/auth/core/index.js +143 -0
- package/dist/auth/core/index.js.map +7 -0
- package/dist/{index.cjs → auth/index.cjs} +12 -4
- package/dist/{index.cjs.map → auth/index.cjs.map} +3 -3
- package/dist/{index.js → auth/index.js} +6 -1
- package/dist/{index.js.map → auth/index.js.map} +3 -3
- package/dist/{providers → auth/providers}/index.cjs.map +1 -1
- package/dist/{providers → auth/providers}/index.js.map +1 -1
- package/dist/{security → auth/security}/index.cjs +4 -1
- package/dist/{security → auth/security}/index.cjs.map +3 -3
- package/dist/{security → auth/security}/index.js +1 -0
- package/dist/{security → auth/security}/index.js.map +3 -3
- package/dist/auth/security/rate-limit.cjs +82 -0
- package/dist/auth/security/rate-limit.cjs.map +7 -0
- package/dist/auth/security/rate-limit.js +57 -0
- package/dist/auth/security/rate-limit.js.map +7 -0
- package/dist/cli/index.cjs +229 -0
- package/dist/cli/index.cjs.map +7 -0
- package/dist/cli/index.js +206 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/templates.cjs +202 -0
- package/dist/cli/templates.cjs.map +7 -0
- package/dist/cli/templates.js +165 -0
- package/dist/cli/templates.js.map +7 -0
- package/dist/core/index.d.ts +16 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/rate-limit.d.ts +39 -0
- package/dist/security/rate-limit.d.ts.map +1 -0
- package/package.json +7 -1
- package/dist/adapters/drizzle.cjs.map +0 -7
- package/dist/adapters/drizzle.js +0 -27
- package/dist/adapters/drizzle.js.map +0 -7
- package/dist/adapters/memory.cjs.map +0 -7
- package/dist/adapters/memory.js +0 -31
- package/dist/adapters/memory.js.map +0 -7
- package/dist/adapters/mongoose.cjs +0 -55
- package/dist/adapters/mongoose.cjs.map +0 -7
- package/dist/adapters/mongoose.js +0 -31
- package/dist/adapters/mongoose.js.map +0 -7
- package/dist/adapters/prisma.cjs.map +0 -7
- package/dist/adapters/prisma.js +0 -34
- package/dist/adapters/prisma.js.map +0 -7
- package/dist/core/index.cjs.map +0 -7
- package/dist/core/index.js +0 -78
- package/dist/core/index.js.map +0 -7
- /package/dist/{adapters → auth/adapters}/index.cjs +0 -0
- /package/dist/{adapters → auth/adapters}/index.js +0 -0
- /package/dist/{adapters → auth/adapters}/index.js.map +0 -0
- /package/dist/{providers → auth/providers}/index.cjs +0 -0
- /package/dist/{providers → auth/providers}/index.js +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var templates_exports = {};
|
|
30
|
+
__export(templates_exports, {
|
|
31
|
+
authTemplate: () => authTemplate,
|
|
32
|
+
envTemplate: () => envTemplate,
|
|
33
|
+
tsConfigTemplate: () => tsConfigTemplate,
|
|
34
|
+
userModelTemplate: () => userModelTemplate
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(templates_exports);
|
|
37
|
+
var import_crypto = __toESM(require("crypto"), 1);
|
|
38
|
+
const authTemplate = (adapter, secret, options) => `import { createAuth } from "kroxt";
|
|
39
|
+
${getAdapterImportBlock(adapter)}
|
|
40
|
+
import dotenv from "dotenv";
|
|
41
|
+
|
|
42
|
+
dotenv.config();
|
|
43
|
+
|
|
44
|
+
${getAdapterInitialization(adapter, options)}
|
|
45
|
+
|
|
46
|
+
export const auth = createAuth({
|
|
47
|
+
adapter: authAdapter,
|
|
48
|
+
secret: process.env.JWT_SECRET || "${secret}",
|
|
49
|
+
${options.usePepper ? 'pepper: process.env.JWT_PEPPER || "",' : ""}
|
|
50
|
+
|
|
51
|
+
// Global Security Configurations
|
|
52
|
+
session: {
|
|
53
|
+
expires: "15m",
|
|
54
|
+
refreshExpires: "7d",
|
|
55
|
+
enforceStrictRevocation: ${options.useStrictRevocation ? "true" : "false"}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Custom JWT Payload logic
|
|
59
|
+
jwt: {
|
|
60
|
+
payload: (user: any, type: "access" | "refresh") => {
|
|
61
|
+
if (type === "access") {
|
|
62
|
+
return {
|
|
63
|
+
role: user.role,
|
|
64
|
+
// schoolId: user.schoolId
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
${options.useRateLimit ? `rateLimit: {
|
|
72
|
+
max: 100, // Requests per minute
|
|
73
|
+
windowMs: 60 * 1000
|
|
74
|
+
},` : ""}
|
|
75
|
+
${options.useIPBlocking ? `ipBlocking: {
|
|
76
|
+
maxStrikes: 5,
|
|
77
|
+
blockDurationMs: 15 * 60 * 1000
|
|
78
|
+
},` : ""}
|
|
79
|
+
passwordPolicy: {
|
|
80
|
+
minLength: 6,
|
|
81
|
+
requireUppercase: true,
|
|
82
|
+
requireSpecialCharacter: true
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
`;
|
|
86
|
+
function getAdapterImportBlock(adapter) {
|
|
87
|
+
switch (adapter) {
|
|
88
|
+
case "mongoose":
|
|
89
|
+
return `import { createMongoAdapter, createRateLimitModel } from "kroxt/adapters/mongoose";
|
|
90
|
+
import mongoose from "mongoose";`;
|
|
91
|
+
case "prisma":
|
|
92
|
+
return `import { createPrismaAdapter } from "kroxt/adapters/prisma";`;
|
|
93
|
+
case "drizzle":
|
|
94
|
+
return `import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
|
|
95
|
+
import { eq } from "drizzle-orm";`;
|
|
96
|
+
case "memory":
|
|
97
|
+
return `import { createMemoryAdapter } from "kroxt/adapters/memory";`;
|
|
98
|
+
default:
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function getAdapterInitialization(adapter, options) {
|
|
103
|
+
const modelImported = options.createModel;
|
|
104
|
+
switch (adapter) {
|
|
105
|
+
case "mongoose":
|
|
106
|
+
return `${modelImported ? 'import { User } from "./user.model.js";' : '// import { User } from "./user.model.js";'}
|
|
107
|
+
|
|
108
|
+
// The rate limit model is optional but recommended
|
|
109
|
+
const authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;
|
|
110
|
+
case "prisma":
|
|
111
|
+
return `// import { prisma } from "./lib/prisma";
|
|
112
|
+
const authAdapter = createPrismaAdapter(prisma.user);`;
|
|
113
|
+
case "drizzle":
|
|
114
|
+
return `${modelImported ? 'import { db } from "./index.js";\nimport { users } from "./schema.js";' : '// import { db } from "./index";\n// import { users } from "./schema";'}
|
|
115
|
+
|
|
116
|
+
const authAdapter = createDrizzleAdapter(db, users, eq);`;
|
|
117
|
+
case "memory":
|
|
118
|
+
return `const authAdapter = createMemoryAdapter();`;
|
|
119
|
+
default:
|
|
120
|
+
return `// const authAdapter = ...;`;
|
|
121
|
+
}
|
|
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
|
+
};
|
|
175
|
+
const envTemplate = (secret, usePepper) => `
|
|
176
|
+
# Kroxt Auth Secrets
|
|
177
|
+
JWT_SECRET="${secret}"
|
|
178
|
+
${usePepper ? `JWT_PEPPER="${import_crypto.default.randomBytes(16).toString("hex")}"` : ""}
|
|
179
|
+
`;
|
|
180
|
+
const tsConfigTemplate = `{
|
|
181
|
+
"compilerOptions": {
|
|
182
|
+
"target": "ESNext",
|
|
183
|
+
"module": "ESNext",
|
|
184
|
+
"moduleResolution": "bundler",
|
|
185
|
+
"esModuleInterop": true,
|
|
186
|
+
"forceConsistentCasingInFileNames": true,
|
|
187
|
+
"strict": true,
|
|
188
|
+
"skipLibCheck": true,
|
|
189
|
+
"types": ["node"]
|
|
190
|
+
},
|
|
191
|
+
"include": ["src/**/*"],
|
|
192
|
+
"exclude": ["node_modules"]
|
|
193
|
+
}
|
|
194
|
+
`;
|
|
195
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
196
|
+
0 && (module.exports = {
|
|
197
|
+
authTemplate,
|
|
198
|
+
envTemplate,
|
|
199
|
+
tsConfigTemplate,
|
|
200
|
+
userModelTemplate
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=templates.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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, 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
|
+
"names": ["crypto"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
const authTemplate = (adapter, secret, options) => `import { createAuth } from "kroxt";
|
|
3
|
+
${getAdapterImportBlock(adapter)}
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
|
|
6
|
+
dotenv.config();
|
|
7
|
+
|
|
8
|
+
${getAdapterInitialization(adapter, options)}
|
|
9
|
+
|
|
10
|
+
export const auth = createAuth({
|
|
11
|
+
adapter: authAdapter,
|
|
12
|
+
secret: process.env.JWT_SECRET || "${secret}",
|
|
13
|
+
${options.usePepper ? 'pepper: process.env.JWT_PEPPER || "",' : ""}
|
|
14
|
+
|
|
15
|
+
// Global Security Configurations
|
|
16
|
+
session: {
|
|
17
|
+
expires: "15m",
|
|
18
|
+
refreshExpires: "7d",
|
|
19
|
+
enforceStrictRevocation: ${options.useStrictRevocation ? "true" : "false"}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Custom JWT Payload logic
|
|
23
|
+
jwt: {
|
|
24
|
+
payload: (user: any, type: "access" | "refresh") => {
|
|
25
|
+
if (type === "access") {
|
|
26
|
+
return {
|
|
27
|
+
role: user.role,
|
|
28
|
+
// schoolId: user.schoolId
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
${options.useRateLimit ? `rateLimit: {
|
|
36
|
+
max: 100, // Requests per minute
|
|
37
|
+
windowMs: 60 * 1000
|
|
38
|
+
},` : ""}
|
|
39
|
+
${options.useIPBlocking ? `ipBlocking: {
|
|
40
|
+
maxStrikes: 5,
|
|
41
|
+
blockDurationMs: 15 * 60 * 1000
|
|
42
|
+
},` : ""}
|
|
43
|
+
passwordPolicy: {
|
|
44
|
+
minLength: 6,
|
|
45
|
+
requireUppercase: true,
|
|
46
|
+
requireSpecialCharacter: true
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
`;
|
|
50
|
+
function getAdapterImportBlock(adapter) {
|
|
51
|
+
switch (adapter) {
|
|
52
|
+
case "mongoose":
|
|
53
|
+
return `import { createMongoAdapter, createRateLimitModel } from "kroxt/adapters/mongoose";
|
|
54
|
+
import mongoose from "mongoose";`;
|
|
55
|
+
case "prisma":
|
|
56
|
+
return `import { createPrismaAdapter } from "kroxt/adapters/prisma";`;
|
|
57
|
+
case "drizzle":
|
|
58
|
+
return `import { createDrizzleAdapter } from "kroxt/adapters/drizzle";
|
|
59
|
+
import { eq } from "drizzle-orm";`;
|
|
60
|
+
case "memory":
|
|
61
|
+
return `import { createMemoryAdapter } from "kroxt/adapters/memory";`;
|
|
62
|
+
default:
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function getAdapterInitialization(adapter, options) {
|
|
67
|
+
const modelImported = options.createModel;
|
|
68
|
+
switch (adapter) {
|
|
69
|
+
case "mongoose":
|
|
70
|
+
return `${modelImported ? 'import { User } from "./user.model.js";' : '// import { User } from "./user.model.js";'}
|
|
71
|
+
|
|
72
|
+
// The rate limit model is optional but recommended
|
|
73
|
+
const authAdapter = createMongoAdapter(User, createRateLimitModel(mongoose));`;
|
|
74
|
+
case "prisma":
|
|
75
|
+
return `// import { prisma } from "./lib/prisma";
|
|
76
|
+
const authAdapter = createPrismaAdapter(prisma.user);`;
|
|
77
|
+
case "drizzle":
|
|
78
|
+
return `${modelImported ? 'import { db } from "./index.js";\nimport { users } from "./schema.js";' : '// import { db } from "./index";\n// import { users } from "./schema";'}
|
|
79
|
+
|
|
80
|
+
const authAdapter = createDrizzleAdapter(db, users, eq);`;
|
|
81
|
+
case "memory":
|
|
82
|
+
return `const authAdapter = createMemoryAdapter();`;
|
|
83
|
+
default:
|
|
84
|
+
return `// const authAdapter = ...;`;
|
|
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
|
+
};
|
|
139
|
+
const envTemplate = (secret, usePepper) => `
|
|
140
|
+
# Kroxt Auth Secrets
|
|
141
|
+
JWT_SECRET="${secret}"
|
|
142
|
+
${usePepper ? `JWT_PEPPER="${crypto.randomBytes(16).toString("hex")}"` : ""}
|
|
143
|
+
`;
|
|
144
|
+
const tsConfigTemplate = `{
|
|
145
|
+
"compilerOptions": {
|
|
146
|
+
"target": "ESNext",
|
|
147
|
+
"module": "ESNext",
|
|
148
|
+
"moduleResolution": "bundler",
|
|
149
|
+
"esModuleInterop": true,
|
|
150
|
+
"forceConsistentCasingInFileNames": true,
|
|
151
|
+
"strict": true,
|
|
152
|
+
"skipLibCheck": true,
|
|
153
|
+
"types": ["node"]
|
|
154
|
+
},
|
|
155
|
+
"include": ["src/**/*"],
|
|
156
|
+
"exclude": ["node_modules"]
|
|
157
|
+
}
|
|
158
|
+
`;
|
|
159
|
+
export {
|
|
160
|
+
authTemplate,
|
|
161
|
+
envTemplate,
|
|
162
|
+
tsConfigTemplate,
|
|
163
|
+
userModelTemplate
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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, 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
|
+
"names": []
|
|
7
|
+
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AuthAdapter, User } from "../adapters/index.js";
|
|
2
2
|
import type { Provider } from "../providers/index.js";
|
|
3
|
+
import { type RateLimitOptions } from "../security/rate-limit.js";
|
|
3
4
|
export interface CreateAuthOptions {
|
|
4
5
|
adapter: AuthAdapter<any>;
|
|
5
6
|
secret: string | Uint8Array;
|
|
@@ -7,6 +8,7 @@ export interface CreateAuthOptions {
|
|
|
7
8
|
session?: {
|
|
8
9
|
expires?: string | number;
|
|
9
10
|
refreshExpires?: string | number;
|
|
11
|
+
enforceStrictRevocation?: boolean;
|
|
10
12
|
};
|
|
11
13
|
providers?: Provider[];
|
|
12
14
|
jwt?: {
|
|
@@ -18,6 +20,18 @@ export interface CreateAuthOptions {
|
|
|
18
20
|
*/
|
|
19
21
|
payload?: (user: User<any>, type: "access" | "refresh") => Record<string, any>;
|
|
20
22
|
};
|
|
23
|
+
rateLimit?: RateLimitOptions;
|
|
24
|
+
ipBlocking?: {
|
|
25
|
+
maxStrikes: number;
|
|
26
|
+
blockDurationMs: number;
|
|
27
|
+
};
|
|
28
|
+
passwordPolicy?: {
|
|
29
|
+
minLength?: number;
|
|
30
|
+
requireUppercase?: boolean;
|
|
31
|
+
requireLowercase?: boolean;
|
|
32
|
+
requireNumber?: boolean;
|
|
33
|
+
requireSpecialCharacter?: boolean;
|
|
34
|
+
};
|
|
21
35
|
}
|
|
22
36
|
export declare function createAuth(options: CreateAuthOptions): {
|
|
23
37
|
signup: (userData: Omit<User<any>, "id">, password?: string) => Promise<{
|
|
@@ -25,11 +39,12 @@ export declare function createAuth(options: CreateAuthOptions): {
|
|
|
25
39
|
accessToken: string;
|
|
26
40
|
refreshToken: string;
|
|
27
41
|
}>;
|
|
28
|
-
loginWithPassword: (email: string, password: string) => Promise<{
|
|
42
|
+
loginWithPassword: (email: string, password: string, clientIp?: string) => Promise<{
|
|
29
43
|
user: any;
|
|
30
44
|
accessToken: string;
|
|
31
45
|
refreshToken: string;
|
|
32
46
|
}>;
|
|
47
|
+
changePassword: (userId: string, newPassword: string) => Promise<any>;
|
|
33
48
|
refresh: (refreshToken: string) => Promise<{
|
|
34
49
|
accessToken: string;
|
|
35
50
|
}>;
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/core/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/core/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,UAAU,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,uBAAuB,CAAC,EAAE,OAAO,CAAC;KACrC,CAAC;IACF,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE;QACF;;;;;WAKG;QACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAClF,CAAC;IACF,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,UAAU,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,cAAc,CAAC,EAAE;QACb,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;KACrC,CAAC;CACL;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB;uBAuGjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,aAAa,MAAM;;;;;+BAoBhC,MAAM,YAAY,MAAM,aAAa,MAAM;;;;;6BA0C7C,MAAM,eAAe,MAAM;4BA7G5B,MAAM;;;yBArBT,MAAM,iBAAgB,QAAQ,GAAG,SAAS;0BAxBzC,IAAI,CAAC,GAAG,CAAC,SAAQ,QAAQ,GAAG,SAAS;;EAoL3E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,MAAW,GAAG,UAAU,CAE9D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export type { Provider, ProviderConfig } from "./providers/index.js";
|
|
|
4
4
|
export { createAuth, generateSecret } from "./core/index.js";
|
|
5
5
|
export type { CreateAuthOptions } from "./core/index.js";
|
|
6
6
|
export { createMemoryAdapter } from "./adapters/memory.js";
|
|
7
|
-
export { createMongoAdapter } from "./adapters/mongoose.js";
|
|
7
|
+
export { createMongoAdapter, createRateLimitModel } from "./adapters/mongoose.js";
|
|
8
|
+
export { createPrismaAdapter } from "./adapters/prisma.js";
|
|
9
|
+
export { createDrizzleAdapter } from "./adapters/drizzle.js";
|
|
8
10
|
export * from "./security/index.js";
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,cAAc,qBAAqB,CAAC"}
|
package/dist/security/index.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export declare function verifyCsrf(tokenInRequest: string, tokenInCookie: string
|
|
|
14
14
|
* 2. Use a 'pepper' in createAuth to protect hashes.
|
|
15
15
|
* 3. Implement rate limiting on /login and /register endpoints.
|
|
16
16
|
*/
|
|
17
|
+
export * from "./rate-limit.js";
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/security/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAejF;AAED;;;;;GAKG"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/security/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAejF;AAED;;;;;GAKG;AAEH,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AuthAdapter } from "../adapters/index.js";
|
|
2
|
+
export interface RateLimitOptions {
|
|
3
|
+
windowMs: number;
|
|
4
|
+
max: number;
|
|
5
|
+
}
|
|
6
|
+
export interface RateLimitResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
limit: number;
|
|
9
|
+
remaining: number;
|
|
10
|
+
reset: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A zero-dependency in-memory store for rate limiting.
|
|
14
|
+
* Used as a fallback if the provided AuthAdapter does not
|
|
15
|
+
* implement `incrementRateLimit`.
|
|
16
|
+
*/
|
|
17
|
+
export declare class MemoryRateLimitStore {
|
|
18
|
+
private hits;
|
|
19
|
+
increment(key: string, windowMs: number): Promise<{
|
|
20
|
+
count: number;
|
|
21
|
+
resetTime: number;
|
|
22
|
+
}>;
|
|
23
|
+
getRateLimit(key: string): Promise<{
|
|
24
|
+
count: number;
|
|
25
|
+
resetTime: number;
|
|
26
|
+
} | null>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a rate limiter function that uses the Database Adapter
|
|
30
|
+
* for state tracking (if supported), or falls back to Memory.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createRateLimiter(adapter: AuthAdapter<any>, options?: RateLimitOptions): {
|
|
33
|
+
increment(key: string, overrideWindowMs?: number): Promise<RateLimitResult>;
|
|
34
|
+
check(key: string): Promise<{
|
|
35
|
+
count: number;
|
|
36
|
+
resetTime: number;
|
|
37
|
+
} | null>;
|
|
38
|
+
} | null;
|
|
39
|
+
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/auth/security/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,IAAI,CAA2D;IAEjE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAcvF,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAMxF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB;mBAO1D,MAAM,qBAAqB,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;eAsBhE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;SAOrF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kroxt",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"bin": {
|
|
5
|
+
"kroxt": "./dist/cli/index.js"
|
|
6
|
+
},
|
|
4
7
|
"keywords": [
|
|
5
8
|
"auth",
|
|
6
9
|
"authentication",
|
|
@@ -82,6 +85,9 @@
|
|
|
82
85
|
"dependencies": {
|
|
83
86
|
"arctic": "^3.7.0",
|
|
84
87
|
"argon2": "^0.44.0",
|
|
88
|
+
"chalk": "^5.6.2",
|
|
89
|
+
"commander": "^14.0.3",
|
|
90
|
+
"enquirer": "^2.4.1",
|
|
85
91
|
"jose": "^6.2.1",
|
|
86
92
|
"zod": "^3.23.8"
|
|
87
93
|
},
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/auth/adapters/drizzle.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any\r\n): AuthAdapter<TUser> {\r\n return {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n}\r\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,qBACd,IACA,OACA,IACoB;AACpB,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/adapters/drizzle.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
function createDrizzleAdapter(db, table, eq) {
|
|
2
|
-
return {
|
|
3
|
-
async createUser(data) {
|
|
4
|
-
const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };
|
|
5
|
-
const results = await db.insert(table).values(dataToSave).returning();
|
|
6
|
-
return results[0];
|
|
7
|
-
},
|
|
8
|
-
async findUserByEmail(email) {
|
|
9
|
-
const results = await db.select().from(table).where(eq(table.email, email)).limit(1);
|
|
10
|
-
return results[0] || null;
|
|
11
|
-
},
|
|
12
|
-
async findUserById(id) {
|
|
13
|
-
const results = await db.select().from(table).where(eq(table.id, id)).limit(1);
|
|
14
|
-
return results[0] || null;
|
|
15
|
-
},
|
|
16
|
-
async linkOAuthAccount(userId, provider, providerId) {
|
|
17
|
-
await db.update(table).set({
|
|
18
|
-
oauthProvider: provider,
|
|
19
|
-
oauthId: providerId
|
|
20
|
-
}).where(eq(table.id, userId));
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export {
|
|
25
|
-
createDrizzleAdapter
|
|
26
|
-
};
|
|
27
|
-
//# sourceMappingURL=drizzle.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/auth/adapters/drizzle.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates a Drizzle ORM adapter.\r\n * \r\n * Works with any Drizzle-supported database (PostgreSQL, MySQL, SQLite)\r\n * by using the standard drizzle-orm `db` instance and table definition.\r\n * \r\n * @param db - The Drizzle database instance.\r\n * @param table - The Drizzle table representing users.\r\n * @param eq - The Drizzle `eq` operator (imported from `drizzle-orm`).\r\n * @returns An AuthAdapter compliant object.\r\n */\r\nexport function createDrizzleAdapter<TUser extends User = User>(\r\n db: any,\r\n table: any,\r\n eq: any\r\n): AuthAdapter<TUser> {\r\n return {\r\n async createUser(data: any) {\r\n const dataToSave = { id: data.id || globalThis.crypto.randomUUID(), ...data };\r\n const results = await db.insert(table).values(dataToSave).returning();\r\n return results[0] as TUser;\r\n },\r\n\r\n async findUserByEmail(email: string) {\r\n const results = await db.select().from(table).where(eq(table.email, email)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async findUserById(id: string) {\r\n const results = await db.select().from(table).where(eq(table.id, id)).limit(1);\r\n return (results[0] || null) as TUser | null;\r\n },\r\n\r\n async linkOAuthAccount(userId: string, provider: string, providerId: string) {\r\n await db.update(table)\r\n .set({\r\n oauthProvider: provider,\r\n oauthId: providerId,\r\n })\r\n .where(eq(table.id, userId));\r\n },\r\n };\r\n}\r\n"],
|
|
5
|
-
"mappings": "AAaO,SAAS,qBACd,IACA,OACA,IACoB;AACpB,SAAO;AAAA,IACL,MAAM,WAAW,MAAW;AAC1B,YAAM,aAAa,EAAE,IAAI,KAAK,MAAM,WAAW,OAAO,WAAW,GAAG,GAAG,KAAK;AAC5E,YAAM,UAAU,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU;AACpE,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IAEA,MAAM,gBAAgB,OAAe;AACnC,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,CAAC;AACnF,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,aAAa,IAAY;AAC7B,YAAM,UAAU,MAAM,GAAG,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC;AAC7E,aAAQ,QAAQ,CAAC,KAAK;AAAA,IACxB;AAAA,IAEA,MAAM,iBAAiB,QAAgB,UAAkB,YAAoB;AAC3E,YAAM,GAAG,OAAO,KAAK,EAClB,IAAI;AAAA,QACH,eAAe;AAAA,QACf,SAAS;AAAA,MACX,CAAC,EACA,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/auth/adapters/memory.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AuthAdapter, User } from \"./index.js\";\r\n\r\n/**\r\n * Creates an in-memory database adapter for the auth engine.\r\n * This is useful for testing, prototyping, or when you don't need persistent storage.\r\n * All data is kept in memory and is lost when the server restarts.\r\n */\r\nexport function createMemoryAdapter<TUser extends User = User>(): AuthAdapter<TUser> {\r\n const users = new Map<string, TUser>();\r\n const accounts = new Map<string, { userId: string; provider: string; providerId: string }>();\r\n\r\n return {\r\n createUser: async (data: any) => {\r\n // Auto-generate ID if not provided\r\n const id = data.id || Date.now().toString();\r\n const newUser = { ...data, id } as TUser;\r\n\r\n // Store using email as the primary lookup key\r\n users.set(newUser.email, newUser);\r\n return newUser;\r\n },\r\n\r\n findUserByEmail: async (email: string) => {\r\n return users.get(email) || null;\r\n },\r\n\r\n findUserById: async (id: string) => {\r\n for (const user of users.values()) {\r\n if (user.id === id) {\r\n return user;\r\n }\r\n }\r\n return null;\r\n },\r\n\r\n linkOAuthAccount: async (userId: string, provider: string, providerId: string) => {\r\n const accountId = `${provider}_${providerId}`;\r\n accounts.set(accountId, { userId, provider, providerId });\r\n }\r\n };\r\n}\r\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,sBAAqE;AACjF,QAAM,QAAQ,oBAAI,IAAmB;AACrC,QAAM,WAAW,oBAAI,IAAsE;AAE3F,SAAO;AAAA,IACH,YAAY,OAAO,SAAc;AAE7B,YAAM,KAAK,KAAK,MAAM,KAAK,IAAI,EAAE,SAAS;AAC1C,YAAM,UAAU,EAAE,GAAG,MAAM,GAAG;AAG9B,YAAM,IAAI,QAAQ,OAAO,OAAO;AAChC,aAAO;AAAA,IACX;AAAA,IAEA,iBAAiB,OAAO,UAAkB;AACtC,aAAO,MAAM,IAAI,KAAK,KAAK;AAAA,IAC/B;AAAA,IAEA,cAAc,OAAO,OAAe;AAChC,iBAAW,QAAQ,MAAM,OAAO,GAAG;AAC/B,YAAI,KAAK,OAAO,IAAI;AAChB,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,aAAO;AAAA,IACX;AAAA,IAEA,kBAAkB,OAAO,QAAgB,UAAkB,eAAuB;AAC9E,YAAM,YAAY,GAAG,QAAQ,IAAI,UAAU;AAC3C,eAAS,IAAI,WAAW,EAAE,QAAQ,UAAU,WAAW,CAAC;AAAA,IAC5D;AAAA,EACJ;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/adapters/memory.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
function createMemoryAdapter() {
|
|
2
|
-
const users = /* @__PURE__ */ new Map();
|
|
3
|
-
const accounts = /* @__PURE__ */ new Map();
|
|
4
|
-
return {
|
|
5
|
-
createUser: async (data) => {
|
|
6
|
-
const id = data.id || Date.now().toString();
|
|
7
|
-
const newUser = { ...data, id };
|
|
8
|
-
users.set(newUser.email, newUser);
|
|
9
|
-
return newUser;
|
|
10
|
-
},
|
|
11
|
-
findUserByEmail: async (email) => {
|
|
12
|
-
return users.get(email) || null;
|
|
13
|
-
},
|
|
14
|
-
findUserById: async (id) => {
|
|
15
|
-
for (const user of users.values()) {
|
|
16
|
-
if (user.id === id) {
|
|
17
|
-
return user;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return null;
|
|
21
|
-
},
|
|
22
|
-
linkOAuthAccount: async (userId, provider, providerId) => {
|
|
23
|
-
const accountId = `${provider}_${providerId}`;
|
|
24
|
-
accounts.set(accountId, { userId, provider, providerId });
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
export {
|
|
29
|
-
createMemoryAdapter
|
|
30
|
-
};
|
|
31
|
-
//# sourceMappingURL=memory.js.map
|