@alinsafawi/aegis-auth 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +137 -37
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23443,6 +23443,60 @@ export default config
|
|
|
23443
23443
|
}
|
|
23444
23444
|
|
|
23445
23445
|
// src/generators/env.ts
|
|
23446
|
+
function generateEnvFile(cookiePrefix, infra, features) {
|
|
23447
|
+
const lines = [
|
|
23448
|
+
`# \u2500\u2500\u2500 Aegis Auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
23449
|
+
`# Fill in every value before running: npx prisma migrate dev --name init`,
|
|
23450
|
+
``,
|
|
23451
|
+
`# Generate with (PowerShell): [Convert]::ToBase64String((1..32|%{[byte](Get-Random -Max 256)}))`,
|
|
23452
|
+
`# Generate with (Unix): openssl rand -base64 32`,
|
|
23453
|
+
`AEGIS_JWT_SECRET=`,
|
|
23454
|
+
``,
|
|
23455
|
+
`# Set to the previous secret when rotating \u2014 gives active sessions a grace period`,
|
|
23456
|
+
`# AEGIS_JWT_SECRET_PREVIOUS=`,
|
|
23457
|
+
``,
|
|
23458
|
+
`# \u2500\u2500\u2500 Database \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
23459
|
+
`# Neon: postgresql://user:pass@host/db?sslmode=require`,
|
|
23460
|
+
`# Supabase: postgresql://postgres:pass@db.xxx.supabase.co:5432/postgres`,
|
|
23461
|
+
`# Local: postgresql://postgres:password@localhost:5432/mydb`,
|
|
23462
|
+
`DATABASE_URL=`,
|
|
23463
|
+
``
|
|
23464
|
+
];
|
|
23465
|
+
if (features.emailVerification || features.passwordReset || features.accountLockout) {
|
|
23466
|
+
lines.push(
|
|
23467
|
+
`# \u2500\u2500\u2500 Email (SMTP) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
23468
|
+
`# Works with Resend, Sendgrid, Postmark, Gmail, etc.`
|
|
23469
|
+
);
|
|
23470
|
+
if (infra.setupSmtp && infra.smtpHost) {
|
|
23471
|
+
lines.push(
|
|
23472
|
+
`AEGIS_SMTP_HOST=${infra.smtpHost}`,
|
|
23473
|
+
`AEGIS_SMTP_PORT=${infra.smtpPort ?? 587}`,
|
|
23474
|
+
`AEGIS_SMTP_USER=${infra.smtpUser ?? ""}`,
|
|
23475
|
+
`AEGIS_SMTP_PASS=`,
|
|
23476
|
+
`AEGIS_SMTP_FROM=${infra.smtpFrom ?? ""}`
|
|
23477
|
+
);
|
|
23478
|
+
} else {
|
|
23479
|
+
lines.push(
|
|
23480
|
+
`AEGIS_SMTP_HOST=`,
|
|
23481
|
+
`AEGIS_SMTP_PORT=587`,
|
|
23482
|
+
`AEGIS_SMTP_USER=`,
|
|
23483
|
+
`AEGIS_SMTP_PASS=`,
|
|
23484
|
+
`AEGIS_SMTP_FROM=`
|
|
23485
|
+
);
|
|
23486
|
+
}
|
|
23487
|
+
lines.push(``);
|
|
23488
|
+
}
|
|
23489
|
+
if (infra.rateLimitProvider === "upstash") {
|
|
23490
|
+
lines.push(
|
|
23491
|
+
`# \u2500\u2500\u2500 Upstash Redis (rate limiting) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
23492
|
+
`# Get these from upstash.com \u2014 free tier available`,
|
|
23493
|
+
`UPSTASH_REDIS_REST_URL=`,
|
|
23494
|
+
`UPSTASH_REDIS_REST_TOKEN=`,
|
|
23495
|
+
``
|
|
23496
|
+
);
|
|
23497
|
+
}
|
|
23498
|
+
return lines.join("\n");
|
|
23499
|
+
}
|
|
23446
23500
|
function generateEnvExample(cookiePrefix, infra, features) {
|
|
23447
23501
|
const lines = [
|
|
23448
23502
|
`# \u2500\u2500\u2500 Aegis Auth \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
@@ -23553,11 +23607,12 @@ export default function RootPage() {
|
|
|
23553
23607
|
}
|
|
23554
23608
|
function generateMiddleware(cookiePrefix, language) {
|
|
23555
23609
|
return `import { createAuthMiddleware } from '@alinsafawi/aegis-auth-next'
|
|
23556
|
-
import
|
|
23610
|
+
import authConfig from './auth.config'
|
|
23557
23611
|
|
|
23558
|
-
export default createAuthMiddleware(
|
|
23612
|
+
export default createAuthMiddleware(authConfig)
|
|
23559
23613
|
|
|
23560
23614
|
export const config = {
|
|
23615
|
+
runtime: 'nodejs',
|
|
23561
23616
|
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
|
|
23562
23617
|
}
|
|
23563
23618
|
`;
|
|
@@ -23672,7 +23727,11 @@ export default function LoginPage() {
|
|
|
23672
23727
|
function generateNextConfig() {
|
|
23673
23728
|
return `import type { NextConfig } from 'next'
|
|
23674
23729
|
|
|
23675
|
-
const nextConfig: NextConfig = {
|
|
23730
|
+
const nextConfig: NextConfig = {
|
|
23731
|
+
experimental: {
|
|
23732
|
+
nodeMiddleware: true,
|
|
23733
|
+
},
|
|
23734
|
+
}
|
|
23676
23735
|
|
|
23677
23736
|
export default nextConfig
|
|
23678
23737
|
`;
|
|
@@ -23710,6 +23769,7 @@ function generatePackageJson(name, packageManager) {
|
|
|
23710
23769
|
"react-dom": "^19.0.0"
|
|
23711
23770
|
},
|
|
23712
23771
|
devDependencies: {
|
|
23772
|
+
"@alinsafawi/aegis-auth": "latest",
|
|
23713
23773
|
"@types/node": "^20.0.0",
|
|
23714
23774
|
"@types/react": "^19.0.0",
|
|
23715
23775
|
"@types/react-dom": "^19.0.0",
|
|
@@ -23939,7 +23999,8 @@ dist
|
|
|
23939
23999
|
const e = language === "typescript" ? "tsx" : "jsx";
|
|
23940
24000
|
await writeFile(`src/app/(auth)/login/page.${e}`, generateLoginPage(app.appName, style.primaryColor, language));
|
|
23941
24001
|
});
|
|
23942
|
-
await step("
|
|
24002
|
+
await step("Creating .env and .env.example", async () => {
|
|
24003
|
+
await writeFile(".env", generateEnvFile(app.cookiePrefix, infra, features));
|
|
23943
24004
|
await writeFile(".env.example", generateEnvExample(app.cookiePrefix, infra, features));
|
|
23944
24005
|
});
|
|
23945
24006
|
if (!isDry && mode === "new") {
|
|
@@ -23957,13 +24018,13 @@ dist
|
|
|
23957
24018
|
}] : [],
|
|
23958
24019
|
{
|
|
23959
24020
|
n: 1,
|
|
23960
|
-
title:
|
|
24021
|
+
title: `Fill in ${import_chalk8.default.yellow(".env")} ${import_chalk8.default.dim("(created for you \u2014 open it and add your values)")}`,
|
|
23961
24022
|
lines: [
|
|
23962
|
-
`${import_chalk8.default.cyan("
|
|
23963
|
-
`${import_chalk8.default.cyan("
|
|
23964
|
-
features.emailVerification || features.passwordReset ? `${import_chalk8.default.cyan("AEGIS_SMTP_HOST=")}` :
|
|
23965
|
-
infra.rateLimitProvider === "upstash" ? `${import_chalk8.default.cyan("UPSTASH_REDIS_REST_URL=")}` :
|
|
23966
|
-
]
|
|
24023
|
+
`${import_chalk8.default.cyan("DATABASE_URL=")} ${import_chalk8.default.dim("\u2190 your Postgres connection string (Neon, Supabase, local)")}`,
|
|
24024
|
+
`${import_chalk8.default.cyan("AEGIS_JWT_SECRET=")} ${import_chalk8.default.dim(process.platform === "win32" ? "\u2190 [Convert]::ToBase64String((1..32|%{[byte](Get-Random -Max 256)}))" : "\u2190 openssl rand -base64 32")}`,
|
|
24025
|
+
...features.emailVerification || features.passwordReset ? [`${import_chalk8.default.cyan("AEGIS_SMTP_HOST=")} ${import_chalk8.default.dim("\u2190 and SMTP_PORT, SMTP_USER, SMTP_PASS, SMTP_FROM")}`] : [],
|
|
24026
|
+
...infra.rateLimitProvider === "upstash" ? [`${import_chalk8.default.cyan("UPSTASH_REDIS_REST_URL=")} ${import_chalk8.default.dim("\u2190 and UPSTASH_REDIS_REST_TOKEN")}`] : []
|
|
24027
|
+
]
|
|
23967
24028
|
},
|
|
23968
24029
|
{
|
|
23969
24030
|
n: 2,
|
|
@@ -24151,20 +24212,34 @@ async function runSeed() {
|
|
|
24151
24212
|
p9.cancel("No auth.config.ts found. Run: npx aegis-auth init first.");
|
|
24152
24213
|
process.exit(1);
|
|
24153
24214
|
}
|
|
24154
|
-
|
|
24155
|
-
|
|
24156
|
-
|
|
24157
|
-
|
|
24158
|
-
|
|
24215
|
+
const hasPrisma = import_fs_extra5.default.existsSync(import_path5.default.join(cwd, "node_modules", ".prisma", "client"));
|
|
24216
|
+
if (!hasPrisma) {
|
|
24217
|
+
p9.cancel("Prisma client not generated. Run: npx prisma generate first.");
|
|
24218
|
+
process.exit(1);
|
|
24219
|
+
}
|
|
24220
|
+
console.log(`
|
|
24221
|
+
${import_chalk12.default.dim("Creates the first user account in your database.")}
|
|
24222
|
+
`);
|
|
24159
24223
|
const role = await p9.text({
|
|
24160
|
-
message: "Role ID
|
|
24224
|
+
message: "Role ID",
|
|
24161
24225
|
placeholder: "admin",
|
|
24162
24226
|
validate: (v) => !v ? "Required" : void 0
|
|
24163
24227
|
});
|
|
24164
24228
|
if (p9.isCancel(role)) process.exit(0);
|
|
24229
|
+
const loginField = await p9.select({
|
|
24230
|
+
message: "Login field for this role",
|
|
24231
|
+
options: [
|
|
24232
|
+
{ value: "email", label: "email" },
|
|
24233
|
+
{ value: "username", label: "username" }
|
|
24234
|
+
]
|
|
24235
|
+
});
|
|
24236
|
+
if (p9.isCancel(loginField)) process.exit(0);
|
|
24165
24237
|
const identifier = await p9.text({
|
|
24166
|
-
message: "Email
|
|
24167
|
-
validate: (v) =>
|
|
24238
|
+
message: loginField === "email" ? "Email address" : "Username",
|
|
24239
|
+
validate: (v) => {
|
|
24240
|
+
if (!v) return "Required";
|
|
24241
|
+
if (loginField === "email" && !v.includes("@")) return "Enter a valid email address";
|
|
24242
|
+
}
|
|
24168
24243
|
});
|
|
24169
24244
|
if (p9.isCancel(identifier)) process.exit(0);
|
|
24170
24245
|
const password3 = await p9.password({
|
|
@@ -24172,25 +24247,50 @@ async function runSeed() {
|
|
|
24172
24247
|
validate: (v) => v.length < 8 ? "At least 8 characters" : void 0
|
|
24173
24248
|
});
|
|
24174
24249
|
if (p9.isCancel(password3)) process.exit(0);
|
|
24175
|
-
|
|
24176
|
-
|
|
24177
|
-
|
|
24178
|
-
|
|
24179
|
-
|
|
24180
|
-
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
|
|
24186
|
-
|
|
24187
|
-
|
|
24188
|
-
|
|
24189
|
-
|
|
24190
|
-
|
|
24191
|
-
)
|
|
24192
|
-
|
|
24193
|
-
|
|
24250
|
+
const spin = p9.spinner();
|
|
24251
|
+
spin.start("Creating user\u2026");
|
|
24252
|
+
try {
|
|
24253
|
+
const envPath = import_path5.default.join(cwd, ".env");
|
|
24254
|
+
if (import_fs_extra5.default.existsSync(envPath)) {
|
|
24255
|
+
const raw = import_fs_extra5.default.readFileSync(envPath, "utf8");
|
|
24256
|
+
for (const line of raw.split("\n")) {
|
|
24257
|
+
const trimmed = line.trim();
|
|
24258
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
24259
|
+
const eq = trimmed.indexOf("=");
|
|
24260
|
+
if (eq === -1) continue;
|
|
24261
|
+
const key = trimmed.slice(0, eq).trim();
|
|
24262
|
+
const val = trimmed.slice(eq + 1).trim().replace(/^["']|["']$/g, "");
|
|
24263
|
+
if (!process.env[key]) process.env[key] = val;
|
|
24264
|
+
}
|
|
24265
|
+
}
|
|
24266
|
+
const { PrismaClient } = require(import_path5.default.join(cwd, "node_modules", ".prisma", "client"));
|
|
24267
|
+
const { hashPassword } = require(import_path5.default.join(cwd, "node_modules", "@alinsafawi", "aegis-auth-core", "dist", "index.js"));
|
|
24268
|
+
const prisma = new PrismaClient();
|
|
24269
|
+
const modelKey = role.charAt(0).toLowerCase() + role.slice(1);
|
|
24270
|
+
const passwordHash = await hashPassword(password3);
|
|
24271
|
+
await prisma[modelKey].create({
|
|
24272
|
+
data: {
|
|
24273
|
+
[loginField]: identifier,
|
|
24274
|
+
passwordHash
|
|
24275
|
+
}
|
|
24276
|
+
});
|
|
24277
|
+
await prisma.$disconnect();
|
|
24278
|
+
spin.stop(`${import_chalk12.default.green("\u2713")} User created`);
|
|
24279
|
+
console.log();
|
|
24280
|
+
console.log(` ${import_chalk12.default.bold("Role")} ${import_chalk12.default.magentaBright(role)}`);
|
|
24281
|
+
console.log(` ${import_chalk12.default.bold(loginField)} ${import_chalk12.default.cyan(identifier)}`);
|
|
24282
|
+
console.log();
|
|
24283
|
+
} catch (err) {
|
|
24284
|
+
spin.stop(`${import_chalk12.default.red("\u2717")} Failed`);
|
|
24285
|
+
console.log();
|
|
24286
|
+
if (err?.code === "P2002") {
|
|
24287
|
+
console.log(` ${import_chalk12.default.red("A user with that ${loginField} already exists.")}`);
|
|
24288
|
+
} else {
|
|
24289
|
+
console.log(` ${import_chalk12.default.red(err?.message ?? String(err))}`);
|
|
24290
|
+
}
|
|
24291
|
+
console.log();
|
|
24292
|
+
process.exit(1);
|
|
24293
|
+
}
|
|
24194
24294
|
}
|
|
24195
24295
|
|
|
24196
24296
|
// src/index.ts
|