@poly-x/next 0.1.0-alpha.6 → 0.1.0-alpha.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/dist/server.cjs +44 -0
- package/dist/server.d.cts +31 -1
- package/dist/server.d.mts +31 -1
- package/dist/server.mjs +44 -0
- package/dist/styles.css +71 -0
- package/package.json +3 -3
package/dist/server.cjs
CHANGED
|
@@ -165,6 +165,50 @@ function createAuthHandlers(handlersConfig = {}) {
|
|
|
165
165
|
});
|
|
166
166
|
return attempt(newPassword);
|
|
167
167
|
},
|
|
168
|
+
async forgotPassword(request) {
|
|
169
|
+
const config = resolveNextConfig(handlersConfig);
|
|
170
|
+
let payload;
|
|
171
|
+
try {
|
|
172
|
+
payload = await request.json();
|
|
173
|
+
} catch {
|
|
174
|
+
return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
175
|
+
}
|
|
176
|
+
const email = typeof payload.email === "string" ? payload.email.trim() : "";
|
|
177
|
+
if (!email) return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
178
|
+
try {
|
|
179
|
+
await buildServerAuthClient(config).requestPasswordReset({ email });
|
|
180
|
+
} catch {}
|
|
181
|
+
return Response.json({ status: "accepted" });
|
|
182
|
+
},
|
|
183
|
+
async resetPassword(request) {
|
|
184
|
+
const config = resolveNextConfig(handlersConfig);
|
|
185
|
+
let payload;
|
|
186
|
+
try {
|
|
187
|
+
payload = await request.json();
|
|
188
|
+
} catch {
|
|
189
|
+
return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
190
|
+
}
|
|
191
|
+
const token = typeof payload.token === "string" ? payload.token : "";
|
|
192
|
+
const newPassword = typeof payload.newPassword === "string" ? payload.newPassword : "";
|
|
193
|
+
const confirmPassword = typeof payload.confirmPassword === "string" ? payload.confirmPassword : void 0;
|
|
194
|
+
if (!token) return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
195
|
+
if (newPassword.length < MIN_PASSWORD_LENGTH) return Response.json({
|
|
196
|
+
status: "weak_password",
|
|
197
|
+
minLength: MIN_PASSWORD_LENGTH
|
|
198
|
+
}, { status: 400 });
|
|
199
|
+
if (confirmPassword !== void 0 && newPassword !== confirmPassword) return Response.json({ status: "password_mismatch" }, { status: 400 });
|
|
200
|
+
switch (await buildServerAuthClient(config).resetPassword({
|
|
201
|
+
token,
|
|
202
|
+
newPassword
|
|
203
|
+
})) {
|
|
204
|
+
case "ok": return Response.json({ status: "success" });
|
|
205
|
+
case "weak_password": return Response.json({
|
|
206
|
+
status: "weak_password",
|
|
207
|
+
minLength: MIN_PASSWORD_LENGTH
|
|
208
|
+
}, { status: 400 });
|
|
209
|
+
default: return Response.json({ status: "invalid_or_expired" }, { status: 400 });
|
|
210
|
+
}
|
|
211
|
+
},
|
|
168
212
|
async callback(request) {
|
|
169
213
|
const config = resolveNextConfig(handlersConfig);
|
|
170
214
|
const url = new URL(request.url);
|
package/dist/server.d.cts
CHANGED
|
@@ -80,10 +80,40 @@ interface AuthHandlers {
|
|
|
80
80
|
* The browser never sees the code, the tokens, or the credentials after POST.
|
|
81
81
|
*/
|
|
82
82
|
authenticate(request: Request): Promise<Response>;
|
|
83
|
+
/**
|
|
84
|
+
* The `<ForgotPassword/>` BFF endpoint: reads `{email}`, adds this app's publishable
|
|
85
|
+
* key, and asks poly-auth to email a reset link server-side. Always relays a uniform
|
|
86
|
+
* `accepted` — it never reveals whether the account exists.
|
|
87
|
+
*/
|
|
88
|
+
forgotPassword(request: Request): Promise<Response>;
|
|
89
|
+
/**
|
|
90
|
+
* The `<ResetPassword/>` BFF endpoint: reads `{token, newPassword}` and redeems the
|
|
91
|
+
* opaque single-use token. `success` on completion; `invalid_or_expired` otherwise.
|
|
92
|
+
*/
|
|
93
|
+
resetPassword(request: Request): Promise<Response>;
|
|
83
94
|
callback(request: Request): Promise<Response>;
|
|
84
95
|
refresh(request: Request): Promise<Response>;
|
|
85
96
|
signout(request: Request): Promise<Response>;
|
|
86
97
|
}
|
|
98
|
+
/** The JSON the `forgotPassword` handler returns — always uniform (no enumeration). */
|
|
99
|
+
type ForgotPasswordResult = {
|
|
100
|
+
status: "accepted";
|
|
101
|
+
} | {
|
|
102
|
+
status: "invalid_request";
|
|
103
|
+
};
|
|
104
|
+
/** The JSON the `resetPassword` handler returns — the `<ResetPassword/>` form branches on `status`. */
|
|
105
|
+
type ResetPasswordResult = {
|
|
106
|
+
status: "success";
|
|
107
|
+
} | {
|
|
108
|
+
status: "weak_password";
|
|
109
|
+
minLength: number;
|
|
110
|
+
} | {
|
|
111
|
+
status: "password_mismatch";
|
|
112
|
+
} | {
|
|
113
|
+
status: "invalid_or_expired";
|
|
114
|
+
} | {
|
|
115
|
+
status: "invalid_request";
|
|
116
|
+
};
|
|
87
117
|
/** The JSON the `authenticate` handler returns — the `<SignIn/>` form branches on `status`. */
|
|
88
118
|
type AuthenticateResult = {
|
|
89
119
|
status: "success";
|
|
@@ -109,4 +139,4 @@ type AuthenticateResult = {
|
|
|
109
139
|
};
|
|
110
140
|
declare function createAuthHandlers(handlersConfig?: AuthHandlersConfig): AuthHandlers;
|
|
111
141
|
//#endregion
|
|
112
|
-
export { type AuthContext, AuthHandlers, AuthHandlersConfig, AuthenticateResult, type CookieAdapter, type CookieSetOptions, DEFAULT_SESSION_COOKIE, type NextServerConfig, ServerSession, auth, createAuthHandlers, openSession, resolveNextConfig, sealSession };
|
|
142
|
+
export { type AuthContext, AuthHandlers, AuthHandlersConfig, AuthenticateResult, type CookieAdapter, type CookieSetOptions, DEFAULT_SESSION_COOKIE, ForgotPasswordResult, type NextServerConfig, ResetPasswordResult, ServerSession, auth, createAuthHandlers, openSession, resolveNextConfig, sealSession };
|
package/dist/server.d.mts
CHANGED
|
@@ -80,10 +80,40 @@ interface AuthHandlers {
|
|
|
80
80
|
* The browser never sees the code, the tokens, or the credentials after POST.
|
|
81
81
|
*/
|
|
82
82
|
authenticate(request: Request): Promise<Response>;
|
|
83
|
+
/**
|
|
84
|
+
* The `<ForgotPassword/>` BFF endpoint: reads `{email}`, adds this app's publishable
|
|
85
|
+
* key, and asks poly-auth to email a reset link server-side. Always relays a uniform
|
|
86
|
+
* `accepted` — it never reveals whether the account exists.
|
|
87
|
+
*/
|
|
88
|
+
forgotPassword(request: Request): Promise<Response>;
|
|
89
|
+
/**
|
|
90
|
+
* The `<ResetPassword/>` BFF endpoint: reads `{token, newPassword}` and redeems the
|
|
91
|
+
* opaque single-use token. `success` on completion; `invalid_or_expired` otherwise.
|
|
92
|
+
*/
|
|
93
|
+
resetPassword(request: Request): Promise<Response>;
|
|
83
94
|
callback(request: Request): Promise<Response>;
|
|
84
95
|
refresh(request: Request): Promise<Response>;
|
|
85
96
|
signout(request: Request): Promise<Response>;
|
|
86
97
|
}
|
|
98
|
+
/** The JSON the `forgotPassword` handler returns — always uniform (no enumeration). */
|
|
99
|
+
type ForgotPasswordResult = {
|
|
100
|
+
status: "accepted";
|
|
101
|
+
} | {
|
|
102
|
+
status: "invalid_request";
|
|
103
|
+
};
|
|
104
|
+
/** The JSON the `resetPassword` handler returns — the `<ResetPassword/>` form branches on `status`. */
|
|
105
|
+
type ResetPasswordResult = {
|
|
106
|
+
status: "success";
|
|
107
|
+
} | {
|
|
108
|
+
status: "weak_password";
|
|
109
|
+
minLength: number;
|
|
110
|
+
} | {
|
|
111
|
+
status: "password_mismatch";
|
|
112
|
+
} | {
|
|
113
|
+
status: "invalid_or_expired";
|
|
114
|
+
} | {
|
|
115
|
+
status: "invalid_request";
|
|
116
|
+
};
|
|
87
117
|
/** The JSON the `authenticate` handler returns — the `<SignIn/>` form branches on `status`. */
|
|
88
118
|
type AuthenticateResult = {
|
|
89
119
|
status: "success";
|
|
@@ -109,4 +139,4 @@ type AuthenticateResult = {
|
|
|
109
139
|
};
|
|
110
140
|
declare function createAuthHandlers(handlersConfig?: AuthHandlersConfig): AuthHandlers;
|
|
111
141
|
//#endregion
|
|
112
|
-
export { type AuthContext, AuthHandlers, AuthHandlersConfig, AuthenticateResult, type CookieAdapter, type CookieSetOptions, DEFAULT_SESSION_COOKIE, type NextServerConfig, ServerSession, auth, createAuthHandlers, openSession, resolveNextConfig, sealSession };
|
|
142
|
+
export { type AuthContext, AuthHandlers, AuthHandlersConfig, AuthenticateResult, type CookieAdapter, type CookieSetOptions, DEFAULT_SESSION_COOKIE, ForgotPasswordResult, type NextServerConfig, ResetPasswordResult, ServerSession, auth, createAuthHandlers, openSession, resolveNextConfig, sealSession };
|
package/dist/server.mjs
CHANGED
|
@@ -164,6 +164,50 @@ function createAuthHandlers(handlersConfig = {}) {
|
|
|
164
164
|
});
|
|
165
165
|
return attempt(newPassword);
|
|
166
166
|
},
|
|
167
|
+
async forgotPassword(request) {
|
|
168
|
+
const config = resolveNextConfig(handlersConfig);
|
|
169
|
+
let payload;
|
|
170
|
+
try {
|
|
171
|
+
payload = await request.json();
|
|
172
|
+
} catch {
|
|
173
|
+
return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
174
|
+
}
|
|
175
|
+
const email = typeof payload.email === "string" ? payload.email.trim() : "";
|
|
176
|
+
if (!email) return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
177
|
+
try {
|
|
178
|
+
await buildServerAuthClient(config).requestPasswordReset({ email });
|
|
179
|
+
} catch {}
|
|
180
|
+
return Response.json({ status: "accepted" });
|
|
181
|
+
},
|
|
182
|
+
async resetPassword(request) {
|
|
183
|
+
const config = resolveNextConfig(handlersConfig);
|
|
184
|
+
let payload;
|
|
185
|
+
try {
|
|
186
|
+
payload = await request.json();
|
|
187
|
+
} catch {
|
|
188
|
+
return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
189
|
+
}
|
|
190
|
+
const token = typeof payload.token === "string" ? payload.token : "";
|
|
191
|
+
const newPassword = typeof payload.newPassword === "string" ? payload.newPassword : "";
|
|
192
|
+
const confirmPassword = typeof payload.confirmPassword === "string" ? payload.confirmPassword : void 0;
|
|
193
|
+
if (!token) return Response.json({ status: "invalid_request" }, { status: 400 });
|
|
194
|
+
if (newPassword.length < MIN_PASSWORD_LENGTH) return Response.json({
|
|
195
|
+
status: "weak_password",
|
|
196
|
+
minLength: MIN_PASSWORD_LENGTH
|
|
197
|
+
}, { status: 400 });
|
|
198
|
+
if (confirmPassword !== void 0 && newPassword !== confirmPassword) return Response.json({ status: "password_mismatch" }, { status: 400 });
|
|
199
|
+
switch (await buildServerAuthClient(config).resetPassword({
|
|
200
|
+
token,
|
|
201
|
+
newPassword
|
|
202
|
+
})) {
|
|
203
|
+
case "ok": return Response.json({ status: "success" });
|
|
204
|
+
case "weak_password": return Response.json({
|
|
205
|
+
status: "weak_password",
|
|
206
|
+
minLength: MIN_PASSWORD_LENGTH
|
|
207
|
+
}, { status: 400 });
|
|
208
|
+
default: return Response.json({ status: "invalid_or_expired" }, { status: 400 });
|
|
209
|
+
}
|
|
210
|
+
},
|
|
167
211
|
async callback(request) {
|
|
168
212
|
const config = resolveNextConfig(handlersConfig);
|
|
169
213
|
const url = new URL(request.url);
|
package/dist/styles.css
CHANGED
|
@@ -339,6 +339,77 @@
|
|
|
339
339
|
opacity: 0.85;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
/* --- Recovery confirmation states (ForgotPassword / ResetPassword) ------- */
|
|
343
|
+
|
|
344
|
+
.polyx-signin__header--center {
|
|
345
|
+
align-items: center;
|
|
346
|
+
text-align: center;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.polyx-signin__status-icon {
|
|
350
|
+
display: inline-flex;
|
|
351
|
+
align-items: center;
|
|
352
|
+
justify-content: center;
|
|
353
|
+
width: 3rem;
|
|
354
|
+
height: 3rem;
|
|
355
|
+
margin-bottom: 0.25rem;
|
|
356
|
+
border-radius: 999px;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.polyx-signin__status-icon svg {
|
|
360
|
+
width: 1.5rem;
|
|
361
|
+
height: 1.5rem;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.polyx-signin__status-icon--brand {
|
|
365
|
+
color: var(--polyx-brand);
|
|
366
|
+
background: color-mix(in srgb, var(--polyx-brand) 12%, transparent);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.polyx-signin__status-icon--danger {
|
|
370
|
+
color: var(--polyx-danger);
|
|
371
|
+
background: var(--polyx-danger-bg);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* The entered email, emphasized inside the confirmation copy. */
|
|
375
|
+
.polyx-signin__email {
|
|
376
|
+
color: var(--polyx-fg);
|
|
377
|
+
font-weight: 600;
|
|
378
|
+
word-break: break-all;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Secondary text-link actions under a confirmation screen — quieter than the CTA. */
|
|
382
|
+
.polyx-signin__actions {
|
|
383
|
+
display: flex;
|
|
384
|
+
flex-direction: column;
|
|
385
|
+
align-items: center;
|
|
386
|
+
gap: 0.75rem;
|
|
387
|
+
margin-top: 1.5rem;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.polyx-signin__link {
|
|
391
|
+
padding: 0;
|
|
392
|
+
font: inherit;
|
|
393
|
+
font-size: 0.875rem;
|
|
394
|
+
font-weight: 500;
|
|
395
|
+
color: var(--polyx-brand);
|
|
396
|
+
background: none;
|
|
397
|
+
border: none;
|
|
398
|
+
cursor: pointer;
|
|
399
|
+
text-decoration: none;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.polyx-signin__link:hover {
|
|
403
|
+
color: var(--polyx-brand-hover);
|
|
404
|
+
text-decoration: underline;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.polyx-signin__link:focus-visible {
|
|
408
|
+
outline: none;
|
|
409
|
+
border-radius: 2px;
|
|
410
|
+
box-shadow: 0 0 0 3px var(--polyx-ring);
|
|
411
|
+
}
|
|
412
|
+
|
|
342
413
|
/* --- Workspace picker ---------------------------------------------------- */
|
|
343
414
|
|
|
344
415
|
.polyx-signin__tenants {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poly-x/next",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "PolyX SDK for Next.js App Router - components plus server helpers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"module": "./dist/index.mjs",
|
|
48
48
|
"types": "./dist/index.d.cts",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@poly-x/core": "0.1.0-alpha.
|
|
51
|
-
"@poly-x/react": "0.1.0-alpha.
|
|
50
|
+
"@poly-x/core": "0.1.0-alpha.7",
|
|
51
|
+
"@poly-x/react": "0.1.0-alpha.7"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"next": ">=14",
|