@binary1702/auth 0.2.5 → 0.3.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/AGENTS.md +139 -0
- package/CHANGELOG.md +31 -0
- package/INSTALL.md +27 -16
- package/PROMPT.md +324 -36
- package/README.md +279 -51
- package/dist/cli.js +232 -17
- package/dist/core/admin-html.d.ts +26 -0
- package/dist/core/admin-html.js +252 -0
- package/dist/core/admin.d.ts +26 -0
- package/dist/core/admin.js +48 -0
- package/dist/core/config.d.ts +8 -1
- package/dist/core/config.js +20 -6
- package/dist/core/db.d.ts +131 -10
- package/dist/core/db.js +388 -69
- package/dist/core/email.d.ts +49 -0
- package/dist/core/email.js +213 -0
- package/dist/core/guard.d.ts +49 -0
- package/dist/core/guard.js +103 -0
- package/dist/core/html.d.ts +36 -0
- package/dist/core/html.js +106 -25
- package/dist/core/options.d.ts +76 -0
- package/dist/core/options.js +310 -0
- package/dist/core/org.d.ts +34 -0
- package/dist/core/org.js +55 -0
- package/dist/core/password.d.ts +16 -0
- package/dist/core/password.js +41 -12
- package/dist/core/rate.d.ts +26 -0
- package/dist/core/rate.js +70 -0
- package/dist/core/reset.d.ts +9 -0
- package/dist/core/reset.js +31 -0
- package/dist/core/session.d.ts +11 -1
- package/dist/core/session.js +27 -7
- package/dist/core/signup.d.ts +9 -6
- package/dist/core/signup.js +26 -15
- package/dist/core/tokens.d.ts +29 -0
- package/dist/core/tokens.js +64 -0
- package/dist/core/verify.d.ts +8 -0
- package/dist/core/verify.js +33 -0
- package/dist/core/yaml.d.ts +10 -0
- package/dist/core/yaml.js +85 -0
- package/dist/index.d.ts +17 -6
- package/dist/index.js +17 -6
- package/dist/next/index.d.ts +10 -3
- package/dist/next/index.js +444 -52
- package/dist/next/proxy.d.ts +2 -1
- package/dist/next/proxy.js +11 -7
- package/dist/react/index.d.ts +18 -0
- package/dist/react/index.js +55 -0
- package/package.json +16 -3
package/dist/next/proxy.js
CHANGED
|
@@ -13,20 +13,24 @@
|
|
|
13
13
|
//
|
|
14
14
|
// The CLI writes proxy.ts with an inline `config.matcher`, because
|
|
15
15
|
// Next reads the matcher statically and ignores a re-exported one.
|
|
16
|
-
//
|
|
17
|
-
//
|
|
16
|
+
// The matcher only skips Next's build output; isPublic() (core/guard.ts)
|
|
17
|
+
// makes every other decision, so the rule lives in one tested place.
|
|
18
18
|
// ─────────────────────────────────────────────────────────────
|
|
19
19
|
import { NextResponse } from "next/server.js";
|
|
20
|
-
import { COOKIE_NAME, SIGN_IN_PATH, getSecret } from "../core/config.js";
|
|
20
|
+
import { COOKIE_NAME, SIGN_IN_PATH, cookieName, getSecret } from "../core/config.js";
|
|
21
21
|
import { verifySession } from "../core/session.js";
|
|
22
|
+
import { MATCHER, isPublic } from "../core/guard.js";
|
|
23
|
+
import { options } from "../core/options.js";
|
|
22
24
|
/** Paste this into proxy.ts as `export const config = { matcher: MATCHER }` */
|
|
23
|
-
export
|
|
24
|
-
const PUBLIC = /^\/(auth(\/|$)|_next\/|favicon\.ico$)|\.[a-z0-9]+$/i;
|
|
25
|
+
export { MATCHER };
|
|
25
26
|
export async function proxy(request) {
|
|
26
27
|
const { pathname, search } = request.nextUrl;
|
|
27
|
-
|
|
28
|
+
// `protected:` or `public:` from b17_auth.yaml, on top of the built-in rules (auth pages, Next internals)
|
|
29
|
+
const o = options();
|
|
30
|
+
if (isPublic(pathname, { public: o.public, protected: o.protected }))
|
|
28
31
|
return NextResponse.next();
|
|
29
|
-
|
|
32
|
+
// The current cookie name, then the pre-0.3.0 one: upgrading signs nobody out
|
|
33
|
+
const token = request.cookies.get(cookieName(o.production))?.value ?? request.cookies.get(COOKIE_NAME)?.value;
|
|
30
34
|
if (token && (await verifySession(token, getSecret())))
|
|
31
35
|
return NextResponse.next();
|
|
32
36
|
if (pathname.startsWith("/api/")) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type Authorization, type Organization, type Session } from "../core/org.ts";
|
|
3
|
+
export type { Session, Organization, Authorization };
|
|
4
|
+
export type AuthState = {
|
|
5
|
+
user: Session["user"] | null;
|
|
6
|
+
organization: Organization | null;
|
|
7
|
+
authorization: Authorization;
|
|
8
|
+
/** True only while the provider is fetching the session itself */
|
|
9
|
+
loading: boolean;
|
|
10
|
+
/** Re-fetch GET /auth/session (after switching organization, for instance) */
|
|
11
|
+
refresh: () => Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
export declare function fetchSession(): Promise<Session | null>;
|
|
14
|
+
export declare function AuthProvider(props: {
|
|
15
|
+
session?: Session | null;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}): import("react").FunctionComponentElement<import("react").ProviderProps<AuthState | null>>;
|
|
18
|
+
export declare function useAuth(): AuthState;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// ─────────────────────────────────────────────────────────────
|
|
3
|
+
// React side of the session contract. For rendering only: every
|
|
4
|
+
// protected operation is still checked on the server.
|
|
5
|
+
//
|
|
6
|
+
// <AuthProvider session={await getSession()}> in a server layout,
|
|
7
|
+
// no request from the client
|
|
8
|
+
// <AuthProvider> anywhere else: fetches
|
|
9
|
+
// GET /auth/session once
|
|
10
|
+
// const { user, organization, authorization } = useAuth()
|
|
11
|
+
//
|
|
12
|
+
// Signed out: user and organization are null, permissions are empty.
|
|
13
|
+
// ─────────────────────────────────────────────────────────────
|
|
14
|
+
import { createContext, createElement, useCallback, useContext, useEffect, useState } from "react";
|
|
15
|
+
import { NO_SESSION } from "../core/org.js";
|
|
16
|
+
const SESSION_URL = "/auth/session";
|
|
17
|
+
const Ctx = createContext(null);
|
|
18
|
+
export async function fetchSession() {
|
|
19
|
+
const res = await fetch(SESSION_URL, { credentials: "same-origin", cache: "no-store" });
|
|
20
|
+
return res.ok ? (await res.json()) : null;
|
|
21
|
+
}
|
|
22
|
+
export function AuthProvider(props) {
|
|
23
|
+
const provided = props.session !== undefined;
|
|
24
|
+
const [session, setSession] = useState(props.session ?? null);
|
|
25
|
+
const [loading, setLoading] = useState(!provided);
|
|
26
|
+
const refresh = useCallback(async () => {
|
|
27
|
+
setLoading(true);
|
|
28
|
+
try {
|
|
29
|
+
setSession(await fetchSession());
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
setLoading(false);
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (provided)
|
|
37
|
+
setSession(props.session ?? null);
|
|
38
|
+
else
|
|
39
|
+
void refresh();
|
|
40
|
+
}, [provided, props.session, refresh]);
|
|
41
|
+
const value = {
|
|
42
|
+
user: session?.user ?? NO_SESSION.user,
|
|
43
|
+
organization: session?.organization ?? NO_SESSION.organization,
|
|
44
|
+
authorization: session?.authorization ?? NO_SESSION.authorization,
|
|
45
|
+
loading,
|
|
46
|
+
refresh,
|
|
47
|
+
};
|
|
48
|
+
return createElement(Ctx.Provider, { value }, props.children);
|
|
49
|
+
}
|
|
50
|
+
export function useAuth() {
|
|
51
|
+
const ctx = useContext(Ctx);
|
|
52
|
+
if (!ctx)
|
|
53
|
+
throw new Error("useAuth() needs an <AuthProvider> above it");
|
|
54
|
+
return ctx;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@binary1702/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Email + password auth for Next.js. One command: npx @binary1702/auth",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -26,12 +26,18 @@
|
|
|
26
26
|
"./next/proxy": {
|
|
27
27
|
"types": "./dist/next/proxy.d.ts",
|
|
28
28
|
"import": "./dist/next/proxy.js"
|
|
29
|
+
},
|
|
30
|
+
"./react": {
|
|
31
|
+
"types": "./dist/react/index.d.ts",
|
|
32
|
+
"import": "./dist/react/index.js"
|
|
29
33
|
}
|
|
30
34
|
},
|
|
31
35
|
"files": [
|
|
32
36
|
"dist",
|
|
33
37
|
"INSTALL.md",
|
|
34
|
-
"PROMPT.md"
|
|
38
|
+
"PROMPT.md",
|
|
39
|
+
"AGENTS.md",
|
|
40
|
+
"CHANGELOG.md"
|
|
35
41
|
],
|
|
36
42
|
"scripts": {
|
|
37
43
|
"build": "tsc",
|
|
@@ -43,10 +49,17 @@
|
|
|
43
49
|
"jose": "^6.2.5"
|
|
44
50
|
},
|
|
45
51
|
"peerDependencies": {
|
|
46
|
-
"next": ">=15.0.0"
|
|
52
|
+
"next": ">=15.0.0",
|
|
53
|
+
"react": ">=18"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"react": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
47
59
|
},
|
|
48
60
|
"devDependencies": {
|
|
49
61
|
"@types/node": "^20",
|
|
62
|
+
"@types/react": "19.3.0",
|
|
50
63
|
"next": "^16.3.2",
|
|
51
64
|
"typescript": "^5.9.3"
|
|
52
65
|
},
|