@mostajs/auth-lite 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/dist/index.js +16 -20
  2. package/package.json +1 -4
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { createHash, randomBytes, timingSafeEqual } from 'crypto';
2
- import { baseFromHeaders } from '@mostajs/url';
3
2
  /**
4
- * Base PUBLIQUE (`proto://host`) pour les redirects. En WebContainer
5
- * (StackBlitz/Bolt) ou derrière un reverse proxy, `req.url` côté Node pointe
6
- * sur le bind interne (`http://localhost:3000`) l'utilisateur serait redirigé
7
- * vers localhost. `baseFromHeaders` lit l'hôte public réel depuis
8
- * `X-Forwarded-Host`/`Host` ; fallback sur l'origine de `req.url`.
3
+ * Réponse 303 avec un `Location` **relatif** (ex. `/dashboard`). Le navigateur
4
+ * le résout contre l'URL PUBLIQUE de la requête courante → fonctionne en
5
+ * WebContainer (StackBlitz/Bolt qui ne transmettent pas l'hôte public au
6
+ * serveur), derrière un reverse proxy, et en localhost, **sans que le serveur
7
+ * ait besoin de connaître son hôte**. Plus robuste qu'une URL absolue.
9
8
  */
10
- function reqBase(req) {
11
- return baseFromHeaders(req.headers) ?? new URL(req.url).origin;
9
+ async function see(location) {
10
+ const { NextResponse } = await import('next/server');
11
+ return new NextResponse(null, { status: 303, headers: { Location: location } });
12
12
  }
13
13
  // ---------------------------------------------------------------------------
14
14
  // Password hashing — salted, iterated SHA-256 (no native addon, boots anywhere)
@@ -59,48 +59,44 @@ export function createAuthHandlers(config) {
59
59
  const afterLogout = config.afterLogout ?? '/';
60
60
  const loginError = config.loginErrorPath ?? '/login?error=invalid';
61
61
  const signupError = config.signupErrorPath ?? ((k) => `/signup?error=${k}`);
62
- async function startSession(req, sessions, userId) {
63
- const { NextResponse } = await import('next/server');
62
+ async function startSession(sessions, userId) {
64
63
  const token = randomBytes(32).toString('hex');
65
64
  const expiresAt = new Date(Date.now() + ttlMs);
66
65
  await sessions.create({ token, user: userId, expiresAt });
67
- const res = NextResponse.redirect(new URL(afterAuth, reqBase(req)), 303);
66
+ const res = await see(afterAuth);
68
67
  res.cookies.set(cookie, token, { httpOnly: true, sameSite: 'lax', path: '/', expires: expiresAt });
69
68
  return res;
70
69
  }
71
70
  /** POST handler — verify credentials, start a session. */
72
71
  async function login(req) {
73
- const { NextResponse } = await import('next/server');
74
72
  const form = await req.formData();
75
73
  const email = String(form.get('email') ?? '').toLowerCase().trim();
76
74
  const password = String(form.get('password') ?? '');
77
75
  const { users, sessions } = await config.getRepos();
78
76
  const user = await users.findOne({ email });
79
77
  if (!user || !verifyPassword(password, user.passwordHash)) {
80
- return NextResponse.redirect(new URL(loginError, reqBase(req)), 303);
78
+ return see(loginError);
81
79
  }
82
- return startSession(req, sessions, user.id);
80
+ return startSession(sessions, user.id);
83
81
  }
84
82
  /** POST handler — create the account, start a session. */
85
83
  async function signup(req) {
86
- const { NextResponse } = await import('next/server');
87
84
  const form = await req.formData();
88
85
  const email = String(form.get('email') ?? '').toLowerCase().trim();
89
86
  const name = String(form.get('name') ?? '').trim();
90
87
  const password = String(form.get('password') ?? '');
91
88
  if (!email || !name || password.length < 6) {
92
- return NextResponse.redirect(new URL(signupError('invalid'), reqBase(req)), 303);
89
+ return see(signupError('invalid'));
93
90
  }
94
91
  const { users, sessions } = await config.getRepos();
95
92
  if (await users.findOne({ email })) {
96
- return NextResponse.redirect(new URL(signupError('exists'), reqBase(req)), 303);
93
+ return see(signupError('exists'));
97
94
  }
98
95
  const user = await users.create({ email, name, passwordHash: hashPassword(password) });
99
- return startSession(req, sessions, user.id);
96
+ return startSession(sessions, user.id);
100
97
  }
101
98
  /** POST handler — destroy the session (DB + cookie). */
102
99
  async function logout(req) {
103
- const { NextResponse } = await import('next/server');
104
100
  const token = req.cookies.get(cookie)?.value;
105
101
  if (token) {
106
102
  const { sessions } = await config.getRepos();
@@ -108,7 +104,7 @@ export function createAuthHandlers(config) {
108
104
  if (session)
109
105
  await sessions.delete(session.id);
110
106
  }
111
- const res = NextResponse.redirect(new URL(afterLogout, reqBase(req)), 303);
107
+ const res = await see(afterLogout);
112
108
  res.cookies.delete(cookie);
113
109
  return res;
114
110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mostajs/auth-lite",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Minimal email/password + session auth for Next.js on @mostajs/orm. No native addon — boots in Bolt.new / StackBlitz / edge.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Dr Hamid MADANI <drmdh@msn.com>",
@@ -57,8 +57,5 @@
57
57
  "funding": {
58
58
  "type": "github",
59
59
  "url": "https://github.com/sponsors/apolocine"
60
- },
61
- "dependencies": {
62
- "@mostajs/url": "^0.5.0"
63
60
  }
64
61
  }