@iaurelius/accounts-nextjs 0.1.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 +133 -0
- package/dist/client.d.ts +68 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +211 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/cookies.d.ts +18 -0
- package/dist/cookies.d.ts.map +1 -0
- package/dist/cookies.js +94 -0
- package/dist/cookies.js.map +1 -0
- package/dist/handlers.d.ts +8 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +157 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/index.server.d.ts +3 -0
- package/dist/index.server.d.ts.map +1 -0
- package/dist/index.server.js +5 -0
- package/dist/index.server.js.map +1 -0
- package/dist/provider.server.d.ts +10 -0
- package/dist/provider.server.d.ts.map +1 -0
- package/dist/provider.server.js +19 -0
- package/dist/provider.server.js.map +1 -0
- package/dist/proxy.d.ts +17 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +61 -0
- package/dist/proxy.js.map +1 -0
- package/dist/server.d.ts +47 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +72 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +48 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +89 -0
- package/dist/session.js.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 iAurelius
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# @iaurelius/accounts-nextjs
|
|
2
|
+
|
|
3
|
+
Accounts by iAurelius for Next.js (App Router, Next 15.3+ and 16).
|
|
4
|
+
|
|
5
|
+
People sign in on your application's hosted page, on your domain with passkeys, email codes and Google, and come back signed in. In your app you get:
|
|
6
|
+
- `auth()` and `currentUser()` on the server;
|
|
7
|
+
- `useAuth()` and `useUser()` in the browser;
|
|
8
|
+
- ready-made `<SignInButton />`, `<UserButton />`, `<SignedIn>` and `<SignedOut>`.
|
|
9
|
+
|
|
10
|
+
The tokens stay on the server, in an encrypted HttpOnly cookie. The SDK refreshes them before they expire.
|
|
11
|
+
|
|
12
|
+
## Quick start
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npx @iaurelius/accounts init
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
It installs the package, registers your development app, and writes `.env.local` and `proxy.ts`. To do it by hand, follow the three steps below.
|
|
19
|
+
|
|
20
|
+
### 1. Settings (`.env.local`)
|
|
21
|
+
|
|
22
|
+
Copy them from your application in the console, under Apps and APIs:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
NEXT_PUBLIC_ACCOUNTS_PUBLISHABLE_KEY=pk_live_…
|
|
26
|
+
ACCOUNTS_CLIENT_ID=…
|
|
27
|
+
# Production (a web app, https): its secret.
|
|
28
|
+
ACCOUNTS_CLIENT_SECRET=…
|
|
29
|
+
# Development (the localhost app, public, PKCE only): a random secret for the cookie instead.
|
|
30
|
+
# ACCOUNTS_COOKIE_SECRET=$(openssl rand -base64 32)
|
|
31
|
+
# Optional: your API's identifier, for getToken().
|
|
32
|
+
# ACCOUNTS_AUDIENCE=https://api.example.com
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The development app is a public app, with no secret and PKCE only. It allows `http://localhost` redirects, which a web app cannot have. Register it with this callback, and use your real port:
|
|
36
|
+
- `http://localhost:3000/api/accounts/callback` as the redirect URI;
|
|
37
|
+
- `http://localhost:3000/` as the sign-out URI.
|
|
38
|
+
|
|
39
|
+
In production, a web app (confidential, https) uses the same two URLs on your domain.
|
|
40
|
+
|
|
41
|
+
### 2. `proxy.ts`
|
|
42
|
+
|
|
43
|
+
Use `middleware.ts` before Next 16.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { accountsMiddleware } from "@iaurelius/accounts-nextjs/server";
|
|
47
|
+
|
|
48
|
+
export default accountsMiddleware({ protect: ["/dashboard(.*)"] });
|
|
49
|
+
|
|
50
|
+
export const config = {
|
|
51
|
+
matcher: ["/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", "/(api|trpc)(.*)"],
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The proxy does four things:
|
|
56
|
+
- It answers `/api/accounts/{sign-in,sign-up,callback,sign-out,session,token}`, so you write no route files.
|
|
57
|
+
- It keeps the session fresh.
|
|
58
|
+
- It sends people who are signed out of a protected page to the sign-in, and back to that page afterwards. Protected API routes answer `401` instead.
|
|
59
|
+
- It hands the session to the rest of the request.
|
|
60
|
+
|
|
61
|
+
### 3. `app/layout.tsx`
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { AccountsProvider, SignInButton, SignedIn, SignedOut, UserButton } from "@iaurelius/accounts-nextjs";
|
|
65
|
+
|
|
66
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
67
|
+
return (
|
|
68
|
+
<html lang="en">
|
|
69
|
+
<body>
|
|
70
|
+
<AccountsProvider>
|
|
71
|
+
<header>
|
|
72
|
+
<SignedOut><SignInButton /></SignedOut>
|
|
73
|
+
<SignedIn><UserButton /></SignedIn>
|
|
74
|
+
</header>
|
|
75
|
+
{children}
|
|
76
|
+
</AccountsProvider>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`<UserButton />` is the avatar menu. It shows who is signed in and has "Manage account" and "Sign out":
|
|
84
|
+
- "Manage account" opens the hosted account page, which has a way back to where the person was. For that way back, allow your app's origin in the console under Emails and paths → Allowed origins.
|
|
85
|
+
- "Sign out" also ends the session on the hosted pages.
|
|
86
|
+
|
|
87
|
+
The buttons speak English or Spanish: `<AccountsProvider locale="es">`.
|
|
88
|
+
|
|
89
|
+
## On the server
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { auth, currentUser } from "@iaurelius/accounts-nextjs/server";
|
|
93
|
+
|
|
94
|
+
export default async function Page() {
|
|
95
|
+
const { userId, user } = await auth.protect(); // signed out: to the sign-in and back
|
|
96
|
+
const me = await currentUser(); // the latest profile, from the application
|
|
97
|
+
return <p>Hello {user.name ?? user.email}</p>;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`auth()` returns:
|
|
102
|
+
- `isAuthenticated`, `userId`, `sessionId`, `orgId` and `user`;
|
|
103
|
+
- `getToken()`, the access token for your API;
|
|
104
|
+
- `protect()` and `redirectToSignIn()`.
|
|
105
|
+
|
|
106
|
+
It works in server components, route handlers and server actions.
|
|
107
|
+
|
|
108
|
+
## In the browser
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
"use client";
|
|
112
|
+
import { useAuth, useUser } from "@iaurelius/accounts-nextjs";
|
|
113
|
+
|
|
114
|
+
const { isSignedIn, getToken, signOut } = useAuth();
|
|
115
|
+
const { user } = useUser();
|
|
116
|
+
const res = await fetch("https://api.example.com/me", { headers: { authorization: `Bearer ${await getToken()}` } });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Your API checks that token with [`@iaurelius/accounts`](https://www.npmjs.com/package/@iaurelius/accounts), for example with `accountsMiddleware()` for Hono.
|
|
120
|
+
|
|
121
|
+
## Security
|
|
122
|
+
|
|
123
|
+
- **Sign-in:**
|
|
124
|
+
- Authorization code with PKCE (S256), `state` and `nonce`, and RFC 9207's `iss` checked.
|
|
125
|
+
- The ID token is verified: signature, audience and nonce.
|
|
126
|
+
- **Session cookie:** encrypted (A256GCM) with a key derived from your app's secret, `HttpOnly`, `SameSite=Lax`, and `Secure` on https.
|
|
127
|
+
- **Redirects:** after sign-in the person only ever goes back to a path of your app.
|
|
128
|
+
- **Sign-out:** only from your app's own pages (Origin checked). The refresh token is revoked and the hosted session ends.
|
|
129
|
+
- **Revocation:** a person who is banned or signed out everywhere is out at the next refresh.
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type SessionUser = {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string | null;
|
|
5
|
+
emailVerified: boolean;
|
|
6
|
+
name: string | null;
|
|
7
|
+
imageUrl: string | null;
|
|
8
|
+
};
|
|
9
|
+
export type Locale = "en" | "es";
|
|
10
|
+
export type AuthState = {
|
|
11
|
+
isLoaded: boolean;
|
|
12
|
+
isSignedIn: boolean;
|
|
13
|
+
user: SessionUser | null;
|
|
14
|
+
sessionId: string | null;
|
|
15
|
+
orgId: string | null;
|
|
16
|
+
};
|
|
17
|
+
export type AccountsProviderProps = {
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/** Language of the buttons. Default: the page's <html lang>, else English. */
|
|
20
|
+
locale?: Locale;
|
|
21
|
+
/** Set by the server provider; a client-only app leaves them out. */
|
|
22
|
+
initialState?: AuthState;
|
|
23
|
+
issuer?: string;
|
|
24
|
+
basePath?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function AccountsClientProvider({ children, initialState, issuer, basePath, locale }: AccountsProviderProps): import("react").JSX.Element;
|
|
27
|
+
export declare function useAuth(): {
|
|
28
|
+
isLoaded: boolean;
|
|
29
|
+
isSignedIn: boolean;
|
|
30
|
+
userId: string | null;
|
|
31
|
+
sessionId: string | null;
|
|
32
|
+
orgId: string | null;
|
|
33
|
+
getToken: () => Promise<string | null>;
|
|
34
|
+
signOut: () => void;
|
|
35
|
+
};
|
|
36
|
+
export declare function useUser(): {
|
|
37
|
+
isLoaded: boolean;
|
|
38
|
+
isSignedIn: boolean;
|
|
39
|
+
user: SessionUser | null;
|
|
40
|
+
};
|
|
41
|
+
/** Renders its children only once it is known that someone is signed in. */
|
|
42
|
+
export declare function SignedIn({ children }: {
|
|
43
|
+
children?: ReactNode;
|
|
44
|
+
}): import("react").JSX.Element | null;
|
|
45
|
+
/** Renders its children only once it is known that nobody is signed in. */
|
|
46
|
+
export declare function SignedOut({ children }: {
|
|
47
|
+
children?: ReactNode;
|
|
48
|
+
}): import("react").JSX.Element | null;
|
|
49
|
+
type ButtonProps = {
|
|
50
|
+
children?: ReactNode;
|
|
51
|
+
className?: string; /** Where to come back after it. Default: this page. */
|
|
52
|
+
redirectUrl?: string;
|
|
53
|
+
};
|
|
54
|
+
/** Goes to the hosted sign-in and back to this page. Wraps your own button if you give it one. */
|
|
55
|
+
export declare const SignInButton: (p: ButtonProps) => import("react").JSX.Element;
|
|
56
|
+
/** The same, opening the hosted page on "create an account". */
|
|
57
|
+
export declare const SignUpButton: (p: ButtonProps) => import("react").JSX.Element;
|
|
58
|
+
/** Signs out here and on the hosted pages (a POST from this app's own page). */
|
|
59
|
+
export declare function SignOutButton({ children, className }: {
|
|
60
|
+
children?: ReactNode;
|
|
61
|
+
className?: string;
|
|
62
|
+
}): import("react").JSX.Element;
|
|
63
|
+
/** The avatar menu: who is signed in, "Manage account" (the hosted page, and back) and "Sign out". */
|
|
64
|
+
export declare function UserButton({ showName }: {
|
|
65
|
+
showName?: boolean;
|
|
66
|
+
}): import("react").JSX.Element | null;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"AAIA,OAAO,EAcL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AACrI,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AACjC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAoBF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,QAA0B,EAAE,MAAM,EAAE,EAAE,qBAAqB,+BA6BnI;AAUD,wBAAgB,OAAO;;;;;;oBAEkB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;;EAmB9D;AAED,wBAAgB,OAAO;IAEZ,QAAQ;IAAc,UAAU;IAAgB,IAAI;EAC9D;AAED,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,sCAG9D;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,sCAG/D;AAoCD,KAAK,WAAW,GAAG;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,uDAAuD;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAyB9I,kGAAkG;AAClG,eAAO,MAAM,YAAY,MAAO,WAAW,gCAAuC,CAAC;AACnF,gEAAgE;AAChE,eAAO,MAAM,YAAY,MAAO,WAAW,gCAAuC,CAAC;AAEnF,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAclG;AAUD,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,EAAE,QAAgB,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sCAoFtE"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// In the browser: the provider, useAuth()/useUser(), <SignedIn>/<SignedOut> and the buttons. The session
|
|
4
|
+
// stays in its HttpOnly cookie: the browser only learns who is signed in (GET /api/accounts/session) and,
|
|
5
|
+
// when it asks, an access token for your API (GET /api/accounts/token).
|
|
6
|
+
import { cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useId, useMemo, useRef, useState, } from "react";
|
|
7
|
+
const AccountsContext = createContext(null);
|
|
8
|
+
const LOADING = { isLoaded: false, isSignedIn: false, user: null, sessionId: null, orgId: null };
|
|
9
|
+
const SIGNED_OUT = { isLoaded: true, isSignedIn: false, user: null, sessionId: null, orgId: null };
|
|
10
|
+
/** The issuer from a publishable key (pk_live_ + base64 of the host and "$"), without the server package. */
|
|
11
|
+
function issuerOf(pk) {
|
|
12
|
+
const m = /^pk_(?:live|test)_([A-Za-z0-9+/]+={0,2})$/.exec(pk ?? "");
|
|
13
|
+
if (!m)
|
|
14
|
+
return null;
|
|
15
|
+
try {
|
|
16
|
+
const host = atob(m[1]).replace(/\$$/, "");
|
|
17
|
+
return `${/^(?:[^:]+\.)?localhost(?::\d+)?$|^127\.0\.0\.1(?::\d+)?$/.test(host) ? "http" : "https"}://${host}`;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function AccountsClientProvider({ children, initialState, issuer, basePath = "/api/accounts", locale }) {
|
|
24
|
+
const [state, setState] = useState(initialState ?? LOADING);
|
|
25
|
+
const [lang, setLang] = useState(locale ?? "en");
|
|
26
|
+
const last = useRef(0);
|
|
27
|
+
const refresh = useCallback(async () => {
|
|
28
|
+
last.current = Date.now();
|
|
29
|
+
try {
|
|
30
|
+
const r = await fetch(`${basePath}/session`, { credentials: "same-origin", cache: "no-store" });
|
|
31
|
+
const s = (await r.json());
|
|
32
|
+
setState(s.isSignedIn && s.user ? { isLoaded: true, isSignedIn: true, user: s.user, sessionId: s.sessionId ?? null, orgId: s.orgId ?? null } : SIGNED_OUT);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
setState((prev) => (prev.isLoaded ? prev : SIGNED_OUT));
|
|
36
|
+
}
|
|
37
|
+
}, [basePath]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!locale)
|
|
40
|
+
setLang(document.documentElement.lang.toLowerCase().startsWith("es") ? "es" : "en");
|
|
41
|
+
if (!initialState)
|
|
42
|
+
void refresh();
|
|
43
|
+
// Signed out in another tab, or the session ended: noticed when the person comes back.
|
|
44
|
+
const onFocus = () => {
|
|
45
|
+
if (Date.now() - last.current > 10_000)
|
|
46
|
+
void refresh();
|
|
47
|
+
};
|
|
48
|
+
window.addEventListener("focus", onFocus);
|
|
49
|
+
return () => window.removeEventListener("focus", onFocus);
|
|
50
|
+
}, [refresh, initialState, locale]);
|
|
51
|
+
const value = useMemo(() => ({ ...state, issuer: issuer ?? issuerOf(typeof process === "undefined" ? undefined : process.env.NEXT_PUBLIC_ACCOUNTS_PUBLISHABLE_KEY), basePath, locale: lang, refresh }), [state, issuer, basePath, lang, refresh]);
|
|
52
|
+
return _jsx(AccountsContext.Provider, { value: value, children: children });
|
|
53
|
+
}
|
|
54
|
+
function useAccounts() {
|
|
55
|
+
const c = useContext(AccountsContext);
|
|
56
|
+
if (!c)
|
|
57
|
+
throw new Error("Wrap your app in <AccountsProvider> (app/layout.tsx) to use Accounts' components and hooks.");
|
|
58
|
+
return c;
|
|
59
|
+
}
|
|
60
|
+
let cachedToken = null;
|
|
61
|
+
export function useAuth() {
|
|
62
|
+
const c = useAccounts();
|
|
63
|
+
const getToken = useCallback(async () => {
|
|
64
|
+
if (cachedToken && cachedToken.expiresAt - Date.now() / 1000 > 30)
|
|
65
|
+
return cachedToken.token;
|
|
66
|
+
const r = await fetch(`${c.basePath}/token`, { credentials: "same-origin", cache: "no-store" });
|
|
67
|
+
if (!r.ok) {
|
|
68
|
+
cachedToken = null;
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
cachedToken = (await r.json());
|
|
72
|
+
return cachedToken.token;
|
|
73
|
+
}, [c.basePath]);
|
|
74
|
+
const signOut = useCallback(() => {
|
|
75
|
+
cachedToken = null;
|
|
76
|
+
const f = document.createElement("form");
|
|
77
|
+
f.method = "post";
|
|
78
|
+
f.action = `${c.basePath}/sign-out`;
|
|
79
|
+
document.body.appendChild(f);
|
|
80
|
+
f.submit();
|
|
81
|
+
}, [c.basePath]);
|
|
82
|
+
return { isLoaded: c.isLoaded, isSignedIn: c.isSignedIn, userId: c.user?.id ?? null, sessionId: c.sessionId, orgId: c.orgId, getToken, signOut };
|
|
83
|
+
}
|
|
84
|
+
export function useUser() {
|
|
85
|
+
const c = useAccounts();
|
|
86
|
+
return { isLoaded: c.isLoaded, isSignedIn: c.isSignedIn, user: c.user };
|
|
87
|
+
}
|
|
88
|
+
/** Renders its children only once it is known that someone is signed in. */
|
|
89
|
+
export function SignedIn({ children }) {
|
|
90
|
+
const c = useAccounts();
|
|
91
|
+
return c.isLoaded && c.isSignedIn ? _jsx(_Fragment, { children: children }) : null;
|
|
92
|
+
}
|
|
93
|
+
/** Renders its children only once it is known that nobody is signed in. */
|
|
94
|
+
export function SignedOut({ children }) {
|
|
95
|
+
const c = useAccounts();
|
|
96
|
+
return c.isLoaded && !c.isSignedIn ? _jsx(_Fragment, { children: children }) : null;
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------- buttons
|
|
99
|
+
const LABELS = {
|
|
100
|
+
en: { signIn: "Sign in", signUp: "Sign up", signOut: "Sign out", manage: "Manage account", open: "Open account menu", menu: "Account" },
|
|
101
|
+
es: { signIn: "Entrar", signUp: "Crear cuenta", signOut: "Cerrar sesión", manage: "Gestionar cuenta", open: "Abrir el menú de la cuenta", menu: "Cuenta" },
|
|
102
|
+
};
|
|
103
|
+
const CSS = `
|
|
104
|
+
.iaa-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5em;min-height:40px;padding:0 16px;border-radius:8px;border:1px solid transparent;background:var(--accounts-accent,#3f4b5a);color:var(--accounts-on-accent,#fff);font:inherit;font-weight:600;text-decoration:none;cursor:pointer}
|
|
105
|
+
.iaa-btn:focus-visible,.iaa-ub-trigger:focus-visible,.iaa-ub-item:focus-visible{outline:2px solid var(--accounts-accent,#3f4b5a);outline-offset:2px}
|
|
106
|
+
.iaa-ub{position:relative;display:inline-block;font:inherit}
|
|
107
|
+
.iaa-ub-trigger{display:inline-flex;align-items:center;gap:8px;min-height:40px;min-width:40px;padding:0;border:0;border-radius:999px;background:none;color:inherit;font:inherit;cursor:pointer}
|
|
108
|
+
.iaa-ub-avatar{display:inline-grid;place-items:center;width:36px;height:36px;border-radius:999px;overflow:hidden;background:var(--accounts-accent,#3f4b5a);color:var(--accounts-on-accent,#fff);font-weight:600;font-size:14px;letter-spacing:.02em}
|
|
109
|
+
.iaa-ub-avatar img{width:100%;height:100%;object-fit:cover}
|
|
110
|
+
.iaa-ub-menu{position:absolute;right:0;top:calc(100% + 8px);z-index:50;min-width:240px;max-width:min(320px,calc(100vw - 32px));padding:6px;border-radius:12px;border:1px solid var(--accounts-border,rgba(0,0,0,.12));background:var(--accounts-surface,#fff);color:var(--accounts-text,#1f2328);box-shadow:0 12px 32px rgba(0,0,0,.14)}
|
|
111
|
+
.iaa-ub-who{display:grid;gap:2px;padding:10px 10px 12px;border-bottom:1px solid var(--accounts-border,rgba(0,0,0,.12));margin-bottom:6px;overflow-wrap:anywhere}
|
|
112
|
+
.iaa-ub-who strong{font-weight:600}
|
|
113
|
+
.iaa-ub-who span{font-size:.875em;opacity:.72}
|
|
114
|
+
.iaa-ub-item{display:flex;width:100%;align-items:center;min-height:40px;padding:0 10px;border:0;border-radius:8px;background:none;color:inherit;font:inherit;text-align:left;text-decoration:none;cursor:pointer}
|
|
115
|
+
.iaa-ub-item:hover,.iaa-ub-item:focus-visible{background:var(--accounts-hover,rgba(0,0,0,.06))}
|
|
116
|
+
.iaa-ub form{margin:0}
|
|
117
|
+
@media (prefers-color-scheme:dark){.iaa-ub-menu{--accounts-surface:#24262b;--accounts-text:#f2f2f0;--accounts-border:rgba(255,255,255,.14);--accounts-hover:rgba(255,255,255,.08)}}
|
|
118
|
+
`;
|
|
119
|
+
const Styles = () => (_jsx("style", { href: "iaurelius-accounts", precedence: "default", children: CSS }));
|
|
120
|
+
function useHere() {
|
|
121
|
+
const [here, setHere] = useState(null);
|
|
122
|
+
useEffect(() => setHere(location.pathname + location.search), []);
|
|
123
|
+
return here;
|
|
124
|
+
}
|
|
125
|
+
function AuthLink({ mode, children, className, redirectUrl }) {
|
|
126
|
+
const c = useAccounts();
|
|
127
|
+
const here = useHere();
|
|
128
|
+
const href = `${c.basePath}/${mode}?redirect_url=${encodeURIComponent(redirectUrl ?? here ?? "/")}`;
|
|
129
|
+
if (isValidElement(children)) {
|
|
130
|
+
const el = children;
|
|
131
|
+
return cloneElement(el, {
|
|
132
|
+
onClick: (e) => {
|
|
133
|
+
el.props.onClick?.(e);
|
|
134
|
+
if (!e.defaultPrevented)
|
|
135
|
+
location.assign(href);
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return (_jsxs(_Fragment, { children: [_jsx(Styles, {}), _jsx("a", { href: href, className: className ?? "iaa-btn", children: children ?? LABELS[c.locale][mode === "sign-in" ? "signIn" : "signUp"] })] }));
|
|
140
|
+
}
|
|
141
|
+
/** Goes to the hosted sign-in and back to this page. Wraps your own button if you give it one. */
|
|
142
|
+
export const SignInButton = (p) => _jsx(AuthLink, { mode: "sign-in", ...p });
|
|
143
|
+
/** The same, opening the hosted page on "create an account". */
|
|
144
|
+
export const SignUpButton = (p) => _jsx(AuthLink, { mode: "sign-up", ...p });
|
|
145
|
+
/** Signs out here and on the hosted pages (a POST from this app's own page). */
|
|
146
|
+
export function SignOutButton({ children, className }) {
|
|
147
|
+
const c = useAccounts();
|
|
148
|
+
return (_jsxs("form", { method: "post", action: `${c.basePath}/sign-out`, style: { display: "inline", margin: 0 }, children: [_jsx(Styles, {}), isValidElement(children) ? (cloneElement(children, { type: "submit" })) : (_jsx("button", { type: "submit", className: className ?? "iaa-btn", children: children ?? LABELS[c.locale].signOut }))] }));
|
|
149
|
+
}
|
|
150
|
+
const initialsOf = (u) => (u.name ?? u.email ?? "?")
|
|
151
|
+
.split(/[\s@._-]+/)
|
|
152
|
+
.filter(Boolean)
|
|
153
|
+
.slice(0, 2)
|
|
154
|
+
.map((w) => w[0].toUpperCase())
|
|
155
|
+
.join("");
|
|
156
|
+
/** The avatar menu: who is signed in, "Manage account" (the hosted page, and back) and "Sign out". */
|
|
157
|
+
export function UserButton({ showName = false }) {
|
|
158
|
+
const c = useAccounts();
|
|
159
|
+
const [open, setOpen] = useState(false);
|
|
160
|
+
const here = useRef(null);
|
|
161
|
+
const root = useRef(null);
|
|
162
|
+
const trigger = useRef(null);
|
|
163
|
+
const menu = useRef(null);
|
|
164
|
+
const id = useId();
|
|
165
|
+
const L = LABELS[c.locale];
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
here.current = location.href;
|
|
168
|
+
});
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
if (!open)
|
|
171
|
+
return;
|
|
172
|
+
menu.current?.querySelector("[role=menuitem]")?.focus();
|
|
173
|
+
const onDown = (e) => {
|
|
174
|
+
if (!root.current?.contains(e.target))
|
|
175
|
+
setOpen(false);
|
|
176
|
+
};
|
|
177
|
+
document.addEventListener("pointerdown", onDown);
|
|
178
|
+
return () => document.removeEventListener("pointerdown", onDown);
|
|
179
|
+
}, [open]);
|
|
180
|
+
if (!c.isLoaded || !c.isSignedIn || !c.user)
|
|
181
|
+
return null;
|
|
182
|
+
const u = c.user;
|
|
183
|
+
// The hosted account page (the application's root), with the way back to this page.
|
|
184
|
+
const account = c.issuer ? `${c.issuer}/?redirect_url=${encodeURIComponent(here.current ?? "")}` : null;
|
|
185
|
+
const onKey = (e) => {
|
|
186
|
+
const items = [...(menu.current?.querySelectorAll("[role=menuitem]") ?? [])];
|
|
187
|
+
const i = items.indexOf(document.activeElement);
|
|
188
|
+
if (e.key === "Escape") {
|
|
189
|
+
e.preventDefault();
|
|
190
|
+
setOpen(false);
|
|
191
|
+
trigger.current?.focus();
|
|
192
|
+
}
|
|
193
|
+
else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
items[(i + (e.key === "ArrowDown" ? 1 : items.length - 1)) % items.length]?.focus();
|
|
196
|
+
}
|
|
197
|
+
else if (e.key === "Home" || e.key === "End") {
|
|
198
|
+
e.preventDefault();
|
|
199
|
+
items[e.key === "Home" ? 0 : items.length - 1]?.focus();
|
|
200
|
+
}
|
|
201
|
+
else if (e.key === "Tab")
|
|
202
|
+
setOpen(false);
|
|
203
|
+
};
|
|
204
|
+
return (_jsxs("div", { className: "iaa-ub", ref: root, children: [_jsx(Styles, {}), _jsxs("button", { ref: trigger, type: "button", className: "iaa-ub-trigger", "aria-haspopup": "menu", "aria-expanded": open, "aria-controls": open ? `${id}-menu` : undefined, "aria-label": showName ? undefined : L.open, onClick: () => setOpen((o) => !o), onKeyDown: (e) => {
|
|
205
|
+
if (e.key === "ArrowDown" && !open) {
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
setOpen(true);
|
|
208
|
+
}
|
|
209
|
+
}, children: [_jsx("span", { className: "iaa-ub-avatar", "aria-hidden": "true", children: u.imageUrl ? _jsx("img", { src: u.imageUrl, alt: "" }) : initialsOf(u) }), showName && _jsx("span", { children: u.name ?? u.email })] }), open && (_jsxs("div", { ref: menu, id: `${id}-menu`, role: "menu", "aria-label": L.menu, className: "iaa-ub-menu", onKeyDown: onKey, children: [_jsxs("div", { className: "iaa-ub-who", role: "none", children: [u.name && _jsx("strong", { children: u.name }), u.email && _jsx("span", { children: u.email })] }), account && (_jsx("a", { role: "menuitem", className: "iaa-ub-item", href: account, children: L.manage })), _jsx("form", { method: "post", action: `${c.basePath}/sign-out`, role: "none", children: _jsx("button", { role: "menuitem", type: "submit", className: "iaa-ub-item", children: L.signOut }) })] }))] }));
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.tsx"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { FetchLike } from "@iaurelius/accounts";
|
|
2
|
+
export type AccountsOptions = {
|
|
3
|
+
/** pk_live_… Default: NEXT_PUBLIC_ACCOUNTS_PUBLISHABLE_KEY. */
|
|
4
|
+
publishableKey?: string;
|
|
5
|
+
/** Your web app in the console (Apps and APIs). Default: ACCOUNTS_CLIENT_ID. */
|
|
6
|
+
clientId?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Default: ACCOUNTS_CLIENT_SECRET. A production web app has one; the development app (localhost) is a
|
|
9
|
+
* public app without it, with PKCE. It also encrypts the session cookie, unless ACCOUNTS_COOKIE_SECRET is set.
|
|
10
|
+
*/
|
|
11
|
+
clientSecret?: string;
|
|
12
|
+
/** Your API's identifier: the access token (getToken()) is issued for it. Default: ACCOUNTS_AUDIENCE. */
|
|
13
|
+
audience?: string | string[];
|
|
14
|
+
/** Where the SDK answers: sign-in, sign-up, callback, sign-out, session, token. Default /api/accounts. */
|
|
15
|
+
basePath?: string;
|
|
16
|
+
/** Where people land after signing out. Default "/". */
|
|
17
|
+
afterSignOutPath?: string;
|
|
18
|
+
/** Your app's public URL, if requests do not carry it (some proxies). Default: ACCOUNTS_APP_URL, else the request's origin. */
|
|
19
|
+
appUrl?: string;
|
|
20
|
+
/** Refresh the access token when it has less than this left. Default 60 s. */
|
|
21
|
+
refreshBeforeSeconds?: number;
|
|
22
|
+
/** How long a session cookie lives without being refreshed. Default 30 days. */
|
|
23
|
+
sessionMaxAgeDays?: number;
|
|
24
|
+
fetch?: FetchLike;
|
|
25
|
+
};
|
|
26
|
+
export type AccountsConfig = Required<Pick<AccountsOptions, "basePath" | "afterSignOutPath" | "refreshBeforeSeconds" | "sessionMaxAgeDays">> & {
|
|
27
|
+
issuer: string;
|
|
28
|
+
clientId: string;
|
|
29
|
+
clientSecret: string | undefined;
|
|
30
|
+
cookieSecret: string;
|
|
31
|
+
audience: string[] | undefined;
|
|
32
|
+
appUrl: string | undefined;
|
|
33
|
+
fetch: FetchLike | undefined;
|
|
34
|
+
};
|
|
35
|
+
/** The settings from the options, else the environment; says exactly which ones are missing. */
|
|
36
|
+
export declare function configOf(o?: AccountsOptions): AccountsConfig;
|
|
37
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG;IAC5B,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+HAA+H;IAC/H,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,kBAAkB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC,CAAC,GAAG;IAC7I,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;CAC9B,CAAC;AAMF,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,CAAC,GAAE,eAAoB,GAAG,cAAc,CAsChE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AccountsError, issuerFromPublishableKey } from "@iaurelius/accounts";
|
|
2
|
+
const envOf = () => globalThis.process?.env ?? {};
|
|
3
|
+
const clean = (v) => (v && v.trim() ? v.trim() : undefined);
|
|
4
|
+
/** The settings from the options, else the environment; says exactly which ones are missing. */
|
|
5
|
+
export function configOf(o = {}) {
|
|
6
|
+
const env = envOf();
|
|
7
|
+
const publishableKey = clean(o.publishableKey) ?? clean(env.NEXT_PUBLIC_ACCOUNTS_PUBLISHABLE_KEY) ?? clean(env.ACCOUNTS_PUBLISHABLE_KEY);
|
|
8
|
+
const clientId = clean(o.clientId) ?? clean(env.ACCOUNTS_CLIENT_ID);
|
|
9
|
+
const clientSecret = clean(o.clientSecret) ?? clean(env.ACCOUNTS_CLIENT_SECRET);
|
|
10
|
+
const cookieSecretEnv = clean(env.ACCOUNTS_COOKIE_SECRET);
|
|
11
|
+
const missing = [
|
|
12
|
+
!publishableKey && "NEXT_PUBLIC_ACCOUNTS_PUBLISHABLE_KEY",
|
|
13
|
+
!clientId && "ACCOUNTS_CLIENT_ID",
|
|
14
|
+
// A public app (the development one) has no secret: the cookie needs its own.
|
|
15
|
+
!clientSecret && !cookieSecretEnv && "ACCOUNTS_CLIENT_SECRET (or, for the development app, ACCOUNTS_COOKIE_SECRET)",
|
|
16
|
+
].filter(Boolean);
|
|
17
|
+
if (missing.length)
|
|
18
|
+
throw new AccountsError("missing_configuration", `Accounts needs ${missing.join(", ")}. Run \`npx @iaurelius/accounts init\`, or copy them from the console (Apps and APIs → your web app) into .env.local.`);
|
|
19
|
+
const audience = o.audience ?? clean(env.ACCOUNTS_AUDIENCE)?.split(/[\s,]+/).filter(Boolean);
|
|
20
|
+
const basePath = (o.basePath ?? "/api/accounts").replace(/\/+$/, "");
|
|
21
|
+
if (!/^\/[A-Za-z0-9/_-]*$/.test(basePath))
|
|
22
|
+
throw new AccountsError("invalid_configuration", "basePath is a path such as /api/accounts.");
|
|
23
|
+
const afterSignOutPath = o.afterSignOutPath ?? "/";
|
|
24
|
+
if (!afterSignOutPath.startsWith("/") || afterSignOutPath.startsWith("//"))
|
|
25
|
+
throw new AccountsError("invalid_configuration", "afterSignOutPath is a path of your app, such as /.");
|
|
26
|
+
const appUrl = clean(o.appUrl) ?? clean(env.ACCOUNTS_APP_URL);
|
|
27
|
+
const cookieSecret = cookieSecretEnv ?? clientSecret;
|
|
28
|
+
if (cookieSecret.length < 32)
|
|
29
|
+
throw new AccountsError("invalid_configuration", "ACCOUNTS_COOKIE_SECRET must be at least 32 characters.");
|
|
30
|
+
return {
|
|
31
|
+
issuer: issuerFromPublishableKey(publishableKey),
|
|
32
|
+
clientId: clientId,
|
|
33
|
+
clientSecret,
|
|
34
|
+
cookieSecret,
|
|
35
|
+
audience: audience === undefined ? undefined : Array.isArray(audience) ? audience : [audience],
|
|
36
|
+
basePath,
|
|
37
|
+
afterSignOutPath,
|
|
38
|
+
appUrl: appUrl ? new URL(appUrl).origin : undefined,
|
|
39
|
+
refreshBeforeSeconds: o.refreshBeforeSeconds ?? 60,
|
|
40
|
+
sessionMaxAgeDays: o.sessionMaxAgeDays ?? 30,
|
|
41
|
+
fetch: o.fetch,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAuC9E,MAAM,KAAK,GAAG,GAAQ,EAAE,CAAE,UAA0C,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;AACxF,MAAM,KAAK,GAAG,CAAC,CAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAEhF,gGAAgG;AAChG,MAAM,UAAU,QAAQ,CAAC,CAAC,GAAoB,EAAE;IAC9C,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;IACpB,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACzI,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACpE,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAChF,MAAM,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG;QACd,CAAC,cAAc,IAAI,sCAAsC;QACzD,CAAC,QAAQ,IAAI,oBAAoB;QACjC,8EAA8E;QAC9E,CAAC,YAAY,IAAI,CAAC,eAAe,IAAI,8EAA8E;KACpH,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,IAAI,OAAO,CAAC,MAAM;QAChB,MAAM,IAAI,aAAa,CACrB,uBAAuB,EACvB,kBAAkB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,uHAAuH,CAC5J,CAAC;IACJ,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,eAAe,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,uBAAuB,EAAE,2CAA2C,CAAC,CAAC;IACzI,MAAM,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACnD,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,uBAAuB,EAAE,oDAAoD,CAAC,CAAC;IACnL,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,eAAe,IAAI,YAAa,CAAC;IACtD,IAAI,YAAY,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,aAAa,CAAC,uBAAuB,EAAE,wDAAwD,CAAC,CAAC;IACzI,OAAO;QACL,MAAM,EAAE,wBAAwB,CAAC,cAAe,CAAC;QACjD,QAAQ,EAAE,QAAS;QACnB,YAAY;QACZ,YAAY;QACZ,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC9F,QAAQ;QACR,gBAAgB;QAChB,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QACnD,oBAAoB,EAAE,CAAC,CAAC,oBAAoB,IAAI,EAAE;QAClD,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,IAAI,EAAE;QAC5C,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type JWTPayload } from "jose";
|
|
2
|
+
export declare function seal(payload: JWTPayload, secret: string, purpose: string, maxAgeSeconds: number): Promise<string>;
|
|
3
|
+
/** The payload, or null for anything not sealed by us for this purpose, or expired. */
|
|
4
|
+
export declare function unseal<T extends JWTPayload>(value: string | undefined, secret: string, purpose: string): Promise<T | null>;
|
|
5
|
+
export type CookieOptions = {
|
|
6
|
+
maxAge?: number;
|
|
7
|
+
path?: string;
|
|
8
|
+
secure: boolean;
|
|
9
|
+
httpOnly?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseCookies(header: string | null | undefined): Map<string, string>;
|
|
12
|
+
export declare function serialize(name: string, value: string, o: CookieOptions): string;
|
|
13
|
+
/** The Set-Cookie headers that store `value` under `name` (chunked if needed) and drop the chunks it no longer uses. */
|
|
14
|
+
export declare function writeChunked(name: string, value: string, existing: Map<string, string>, o: CookieOptions): string[];
|
|
15
|
+
export declare function readChunked(name: string, cookies: Map<string, string>): string | undefined;
|
|
16
|
+
/** Set-Cookie headers that remove `name` and every chunk of it. */
|
|
17
|
+
export declare function clearChunked(name: string, existing: Map<string, string>, o: CookieOptions): string[];
|
|
18
|
+
//# sourceMappingURL=cookies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../src/cookies.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAoB/D,wBAAsB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAMrG;AAED,uFAAuF;AACvF,wBAAsB,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAOhI;AAGD,MAAM,MAAM,aAAa,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpG,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASnF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,aAAa,UAMtE;AAKD,wHAAwH;AACxH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAcnH;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAM1F;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM,EAAE,CAEpG"}
|