@synqauth/nextjs 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +117 -2
- package/dist/client.d.ts +13 -0
- package/dist/client.js +24 -0
- package/dist/config-CpEbAGEs.d.ts +215 -0
- package/dist/define.d.ts +6 -0
- package/dist/define.js +7 -0
- package/dist/index.d.ts +125 -0
- package/dist/index.js +106 -0
- package/dist/proxy.d.ts +28 -0
- package/dist/proxy.js +59 -0
- package/dist/sign-in-error-kd56GHt_.js +1349 -0
- package/package.json +59 -3
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { t as SynqAuthOptions } from "./config-CpEbAGEs.js";
|
|
2
|
+
//#region src/proxy.d.ts
|
|
3
|
+
/** What `synqProxy()` takes: which paths need a session. */
|
|
4
|
+
export interface SynqProxyOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Paths that need someone signed in: path prefixes, or a test. There is no
|
|
7
|
+
* default: everything would send the app's images, `robots.txt` and
|
|
8
|
+
* `/.well-known/` files to sign in. Narrow what the proxy runs on with
|
|
9
|
+
* `export const config = { matcher }` as well.
|
|
10
|
+
*/
|
|
11
|
+
readonly protect: readonly string[] | ((pathname: string) => boolean);
|
|
12
|
+
/**
|
|
13
|
+
* The app's own page saying why a sign-in didn't finish: a protected
|
|
14
|
+
* request without a session that came back with `synq_error` is
|
|
15
|
+
* rewritten to it, with `synq_error` and `returnTo` in its query (read
|
|
16
|
+
* them with `synqAuth().signInError()`), and it is never protected
|
|
17
|
+
* itself. Without it, the proxy answers such a request with a plain page
|
|
18
|
+
* of its own. Either way, it never sends that request to sign in again.
|
|
19
|
+
*/
|
|
20
|
+
readonly signInError?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Next's proxy for Synq: refreshes a session that is due, and sends a
|
|
24
|
+
* request to a protected path without one to sign in, or, when a sign-in
|
|
25
|
+
* just failed, to the page that says why.
|
|
26
|
+
*/
|
|
27
|
+
export declare function synqProxy(config: SynqAuthOptions, options: SynqProxyOptions): (request: Request) => Promise<Response | undefined>;
|
|
28
|
+
//#endregion
|
package/dist/proxy.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { a as withoutSignInError, f as resolveConfig, i as signInErrorPage, o as createSynqCore, r as signInErrorOf, t as SIGN_IN_ERROR_PARAM, u as requestJar } from "./sign-in-error-kd56GHt_.js";
|
|
2
|
+
import { NextResponse } from "next/server.js";
|
|
3
|
+
//#region src/proxy.ts
|
|
4
|
+
/**
|
|
5
|
+
* Next's proxy for Synq: refreshes a session that is due, and sends a
|
|
6
|
+
* request to a protected path without one to sign in, or, when a sign-in
|
|
7
|
+
* just failed, to the page that says why.
|
|
8
|
+
*/
|
|
9
|
+
function synqProxy(config, options) {
|
|
10
|
+
const { protect, signInError } = options;
|
|
11
|
+
if (signInError !== void 0 && !/^\/(?![/\\])/.test(signInError)) throw new TypeError("synqProxy: signInError is a path on the app, such as /sign-in-error");
|
|
12
|
+
const protectsPath = typeof protect === "function" ? protect : (path) => protect.some((prefix) => under(path, prefix));
|
|
13
|
+
const protects = (path) => !(signInError !== void 0 && under(path, signInError)) && protectsPath(path);
|
|
14
|
+
let core;
|
|
15
|
+
return async function proxy(request) {
|
|
16
|
+
core ??= createSynqCore(resolveConfig(config));
|
|
17
|
+
const url = new URL(request.url);
|
|
18
|
+
if (under(url.pathname, core.config.basePath)) return void 0;
|
|
19
|
+
const jar = requestJar(request);
|
|
20
|
+
const signedIn = await core.refreshIfDue(jar);
|
|
21
|
+
const changes = jar.headers();
|
|
22
|
+
if (!signedIn && protects(url.pathname)) {
|
|
23
|
+
const returnTo = withoutSignInError(`${url.pathname}${url.search}`);
|
|
24
|
+
const failed = signInErrorOf(url.searchParams.get(SIGN_IN_ERROR_PARAM), core.config.basePath, returnTo);
|
|
25
|
+
if (failed) {
|
|
26
|
+
const response = signInError ? NextResponse.rewrite(errorPageUrl(signInError, url, failed.code, returnTo)) : signInErrorPage(failed);
|
|
27
|
+
for (const cookie of changes) response.headers.append("set-cookie", cookie);
|
|
28
|
+
return response;
|
|
29
|
+
}
|
|
30
|
+
const signIn = new URL(`${core.config.basePath}/sign-in`, core.config.appUrl);
|
|
31
|
+
signIn.searchParams.set("returnTo", returnTo);
|
|
32
|
+
const response = new Response(null, {
|
|
33
|
+
status: 307,
|
|
34
|
+
headers: { location: signIn.href }
|
|
35
|
+
});
|
|
36
|
+
for (const cookie of changes) response.headers.append("set-cookie", cookie);
|
|
37
|
+
return response;
|
|
38
|
+
}
|
|
39
|
+
if (changes.length === 0) return void 0;
|
|
40
|
+
const headers = new Headers(request.headers);
|
|
41
|
+
headers.set("cookie", jar.cookieHeader());
|
|
42
|
+
const response = NextResponse.next({ request: { headers } });
|
|
43
|
+
for (const cookie of changes) response.headers.append("set-cookie", cookie);
|
|
44
|
+
return response;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** The app's page for a sign-in error, with the error and where its ways on come back to. */
|
|
48
|
+
function errorPageUrl(path, url, code, returnTo) {
|
|
49
|
+
const page = new URL(path, url);
|
|
50
|
+
page.searchParams.set(SIGN_IN_ERROR_PARAM, code);
|
|
51
|
+
page.searchParams.set("returnTo", returnTo);
|
|
52
|
+
return page;
|
|
53
|
+
}
|
|
54
|
+
function under(path, prefix) {
|
|
55
|
+
const base = prefix.replace(/\/+$/, "");
|
|
56
|
+
return base === "" || path === base || path.startsWith(`${base}/`);
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
export { synqProxy };
|