@atlasauth/nextjs 0.1.2 → 0.1.4

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/matcher.d.ts CHANGED
@@ -21,6 +21,21 @@
21
21
  */
22
22
  export declare function matchesPattern(pathname: string, pattern: string): boolean;
23
23
  export declare function matchesAny(pathname: string, patterns: readonly string[]): boolean;
24
+ /**
25
+ * §10.1 Clerk-parity `createRouteMatcher(patterns)` — the idiom integrators write
26
+ * at the top of `middleware.ts` (`const isProtected = createRouteMatcher(['/dashboard(.*)'])`).
27
+ * Returns a predicate over anything carrying a pathname: a Next `NextRequest`
28
+ * (`req.nextUrl.pathname`), a plain `{ nextUrl }` / `{ url }`, or a bare path
29
+ * string. Uses the SAME `(.*)`-only pattern engine as the middleware, so a
30
+ * matcher written here and the middleware's own routing agree exactly (no second
31
+ * dialect, no customer regex in the auth path).
32
+ */
33
+ export declare function createRouteMatcher(patterns: readonly string[]): (input: string | {
34
+ nextUrl?: {
35
+ pathname?: string;
36
+ };
37
+ url?: string;
38
+ }) => boolean;
24
39
  export declare function isStaticAsset(pathname: string): boolean;
25
40
  export interface MiddlewareConfig {
26
41
  /** Routes reachable without a session. Everything else requires one. */
package/dist/matcher.js CHANGED
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.DEFAULT_SIGN_IN_URL = void 0;
17
17
  exports.matchesPattern = matchesPattern;
18
18
  exports.matchesAny = matchesAny;
19
+ exports.createRouteMatcher = createRouteMatcher;
19
20
  exports.isStaticAsset = isStaticAsset;
20
21
  exports.decideRoute = decideRoute;
21
22
  exports.safeRedirect = safeRedirect;
@@ -40,6 +41,29 @@ function matchesPattern(pathname, pattern) {
40
41
  function matchesAny(pathname, patterns) {
41
42
  return patterns.some((pattern) => matchesPattern(pathname, pattern));
42
43
  }
44
+ /**
45
+ * §10.1 Clerk-parity `createRouteMatcher(patterns)` — the idiom integrators write
46
+ * at the top of `middleware.ts` (`const isProtected = createRouteMatcher(['/dashboard(.*)'])`).
47
+ * Returns a predicate over anything carrying a pathname: a Next `NextRequest`
48
+ * (`req.nextUrl.pathname`), a plain `{ nextUrl }` / `{ url }`, or a bare path
49
+ * string. Uses the SAME `(.*)`-only pattern engine as the middleware, so a
50
+ * matcher written here and the middleware's own routing agree exactly (no second
51
+ * dialect, no customer regex in the auth path).
52
+ */
53
+ function createRouteMatcher(patterns) {
54
+ return (input) => {
55
+ let pathname;
56
+ if (typeof input === 'string') {
57
+ // Accept a full URL or a bare path.
58
+ pathname = input.startsWith('http') ? new URL(input).pathname : input;
59
+ }
60
+ else {
61
+ pathname =
62
+ input.nextUrl?.pathname ?? (input.url ? new URL(input.url, 'http://x').pathname : '');
63
+ }
64
+ return matchesAny(pathname, patterns);
65
+ };
66
+ }
43
67
  /**
44
68
  * Paths that are never auth decisions.
45
69
  *
@@ -1 +1 @@
1
- {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"matcher.js","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAUH,wCASC;AAED,gCAEC;AAWD,gDAcC;AAWD,sCAKC;AA4BD,kCA4BC;AASD,oCAiBC;AAhJD;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAC,QAAgB,EAAE,OAAe;IAC9D,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAElC,0EAA0E;IAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,UAAU,CAAC,QAAgB,EAAE,QAA2B;IACtE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAChC,QAA2B;IAE3B,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,IAAI,QAAgB,CAAC;QACrB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,oCAAoC;YACpC,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QACxE,CAAC;aAAM,CAAC;YACN,QAAQ;gBACN,KAAK,CAAC,OAAO,EAAE,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC;AAEnG,SAAgB,aAAa,CAAC,QAAgB;IAC5C,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,gDAAgD;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAYY,QAAA,mBAAmB,GAAG,UAAU,CAAC;AAQ9C;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,KAM3B;IACC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAElC,IAAI,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE7D,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IACrF,MAAM,QAAQ,GAAG,CAAC,mBAAmB,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAE/F,IAAI,QAAQ,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAE3D;;;;OAIG;IACH,IAAI,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAExD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,2BAAmB,CAAC;IAC1D,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,EAAE,EAAE,GAAG,SAAS,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;KACtE,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAC1B,WAAsC,EACtC,iBAAoC,EAAE,EACtC,QAAQ,GAAG,GAAG;IAEd,IAAI,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAC;IAElC,yEAAyE;IACzE,IAAI,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAClD,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,WAAW,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;QACjC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * `@atlasauth/nextjs/server` — the pre-bound, zero-argument App-Router helpers.
3
+ *
4
+ * §Q7 gap: the base entry ships FACTORIES (`createAuthHelper`,
5
+ * `createCurrentUserHelper`) that the integrator wires once and then feeds an
6
+ * `EdgeRequest` on every call. Clerk instead ships `auth()` / `currentUser()`
7
+ * that read the ambient request from `next/headers` with no argument and read
8
+ * their config from the environment. This subpath adds exactly that ergonomic
9
+ * ON TOP of the existing core — it reuses `resolveAuth` + `AtlasBackend` through
10
+ * the very same factories, so JWT verification is defined in exactly one place.
11
+ *
12
+ * It lives in its own entry precisely because it imports `next/headers`: keeping
13
+ * it out of `index.ts` means `@atlasauth/nextjs` (middleware + matcher) still
14
+ * builds and runs with no `next` installed. `next` is only an OPTIONAL peer.
15
+ */
16
+ import { type AtlasClient, type AtlasClientConfig } from '@atlasauth/backend';
17
+ import { createAuthHelper, type AtlasMiddlewareOptions, type CurrentUser, type EdgeRequest } from './middleware';
18
+ type Env = Record<string, string | undefined>;
19
+ /**
20
+ * Resolve the edge-verification config from the environment, mirroring how Clerk
21
+ * reads `CLERK_*` / `NEXT_PUBLIC_CLERK_*`. Server-only names win over their
22
+ * `NEXT_PUBLIC_` fallbacks. Throws with an actionable message when a required
23
+ * value is absent, because a silently-misconfigured verifier fails every request
24
+ * anyway — better a clear error at the first call than a mystery sign-out loop.
25
+ */
26
+ export declare function configFromEnv(env?: Env): AtlasMiddlewareOptions;
27
+ /**
28
+ * Resolve the Backend-API (secret-key) config from the environment, for
29
+ * {@link atlasClient}. The secret key is server-only by definition — there is no
30
+ * `NEXT_PUBLIC_` fallback for it, and there must never be one.
31
+ */
32
+ export declare function backendConfigFromEnv(env?: Env): AtlasClientConfig;
33
+ /**
34
+ * `clerkClient()`-equivalent: a configured `@atlasauth/backend` management client
35
+ * built from `ATLAS_SECRET_KEY` (+ optional `ATLAS_API_URL`). Overrides win over
36
+ * the environment, for tests and multi-instance setups.
37
+ */
38
+ export declare function atlasClient(overrides?: Partial<AtlasClientConfig>): AtlasClient;
39
+ /** The subset of Next's cookie store {@link buildEdgeRequest} reads. */
40
+ export interface CookieStoreLike {
41
+ getAll(): ReadonlyArray<{
42
+ name: string;
43
+ value: string;
44
+ }>;
45
+ get?(name: string): {
46
+ value: string;
47
+ } | undefined;
48
+ }
49
+ /** The subset of Next's header store {@link buildEdgeRequest} reads. */
50
+ export interface HeaderStoreLike {
51
+ get(name: string): string | null | undefined;
52
+ }
53
+ /**
54
+ * Build an `EdgeRequest`-shaped object from a cookie store + a header store, the
55
+ * bridge between `next/headers` and the existing `resolveAuth` core. Pure and
56
+ * injectable: the ambient `auth()` feeds it the real Next stores, and tests feed
57
+ * it fakes — no request context required. `resolveAuth` reads only the
58
+ * `authorization` and `cookie` headers, so those are what we synthesize; the
59
+ * cookie header is reconstructed from the cookie store (which reflects any
60
+ * in-request mutations), falling back to the raw `cookie` header.
61
+ */
62
+ export declare function buildEdgeRequest(cookieStore: CookieStoreLike, headerStore: HeaderStoreLike): EdgeRequest;
63
+ /** What the pre-bound `auth()` resolves to — the same state + `has`/`protect` the
64
+ * factory helper returns. */
65
+ export type ServerAuth = Awaited<ReturnType<ReturnType<typeof createAuthHelper>>>;
66
+ /**
67
+ * Clerk-parity `auth()` — no arguments. Reads cookies/headers from the ambient
68
+ * `next/headers` request, verifies the session at the edge via the shared core,
69
+ * and returns the same `AuthState & { has, protect }`. Config comes from the
70
+ * environment (see {@link configFromEnv}). Signed-out is a plain state, not a
71
+ * throw — call `.protect()` where anonymous access is a bug.
72
+ */
73
+ export declare function auth(): Promise<ServerAuth>;
74
+ /**
75
+ * Clerk-parity `currentUser()` — no arguments. The signed-in user's profile from
76
+ * the verified session claims (no round-trip), or `null` when signed out.
77
+ */
78
+ export declare function currentUser(): Promise<CurrentUser | null>;
79
+ export type { AtlasClient, AtlasClientConfig } from '@atlasauth/backend';
80
+ export type { AuthState, CurrentUser, EdgeRequest } from './middleware';
package/dist/server.js ADDED
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.configFromEnv = configFromEnv;
37
+ exports.backendConfigFromEnv = backendConfigFromEnv;
38
+ exports.atlasClient = atlasClient;
39
+ exports.buildEdgeRequest = buildEdgeRequest;
40
+ exports.auth = auth;
41
+ exports.currentUser = currentUser;
42
+ /**
43
+ * `@atlasauth/nextjs/server` — the pre-bound, zero-argument App-Router helpers.
44
+ *
45
+ * §Q7 gap: the base entry ships FACTORIES (`createAuthHelper`,
46
+ * `createCurrentUserHelper`) that the integrator wires once and then feeds an
47
+ * `EdgeRequest` on every call. Clerk instead ships `auth()` / `currentUser()`
48
+ * that read the ambient request from `next/headers` with no argument and read
49
+ * their config from the environment. This subpath adds exactly that ergonomic
50
+ * ON TOP of the existing core — it reuses `resolveAuth` + `AtlasBackend` through
51
+ * the very same factories, so JWT verification is defined in exactly one place.
52
+ *
53
+ * It lives in its own entry precisely because it imports `next/headers`: keeping
54
+ * it out of `index.ts` means `@atlasauth/nextjs` (middleware + matcher) still
55
+ * builds and runs with no `next` installed. `next` is only an OPTIONAL peer.
56
+ */
57
+ const backend_1 = require("@atlasauth/backend");
58
+ const middleware_1 = require("./middleware");
59
+ /** Read `process.env` without requiring `process` to be typed (no @types/node). */
60
+ function readEnv() {
61
+ return globalThis.process?.env ?? {};
62
+ }
63
+ /** First non-empty env var among `names`. */
64
+ function pick(env, ...names) {
65
+ for (const name of names) {
66
+ const value = env[name];
67
+ if (value !== undefined && value !== '')
68
+ return value;
69
+ }
70
+ return undefined;
71
+ }
72
+ /**
73
+ * Resolve the edge-verification config from the environment, mirroring how Clerk
74
+ * reads `CLERK_*` / `NEXT_PUBLIC_CLERK_*`. Server-only names win over their
75
+ * `NEXT_PUBLIC_` fallbacks. Throws with an actionable message when a required
76
+ * value is absent, because a silently-misconfigured verifier fails every request
77
+ * anyway — better a clear error at the first call than a mystery sign-out loop.
78
+ */
79
+ function configFromEnv(env = readEnv()) {
80
+ const jwksUrl = pick(env, 'ATLAS_JWKS_URL', 'NEXT_PUBLIC_ATLAS_JWKS_URL');
81
+ const issuer = pick(env, 'ATLAS_ISSUER', 'NEXT_PUBLIC_ATLAS_ISSUER');
82
+ if (!jwksUrl) {
83
+ throw new Error('@atlasauth/nextjs/server: missing ATLAS_JWKS_URL (or NEXT_PUBLIC_ATLAS_JWKS_URL).');
84
+ }
85
+ if (!issuer) {
86
+ throw new Error('@atlasauth/nextjs/server: missing ATLAS_ISSUER (or NEXT_PUBLIC_ATLAS_ISSUER).');
87
+ }
88
+ const authorizedPartiesRaw = pick(env, 'ATLAS_AUTHORIZED_PARTIES', 'NEXT_PUBLIC_ATLAS_AUTHORIZED_PARTIES');
89
+ const authorizedParties = authorizedPartiesRaw
90
+ ? authorizedPartiesRaw
91
+ .split(',')
92
+ .map((part) => part.trim())
93
+ .filter(Boolean)
94
+ : undefined;
95
+ const publishableKey = pick(env, 'ATLAS_PUBLISHABLE_KEY', 'NEXT_PUBLIC_ATLAS_PUBLISHABLE_KEY');
96
+ return { jwksUrl, issuer, authorizedParties, publishableKey };
97
+ }
98
+ /**
99
+ * Resolve the Backend-API (secret-key) config from the environment, for
100
+ * {@link atlasClient}. The secret key is server-only by definition — there is no
101
+ * `NEXT_PUBLIC_` fallback for it, and there must never be one.
102
+ */
103
+ function backendConfigFromEnv(env = readEnv()) {
104
+ const secretKey = pick(env, 'ATLAS_SECRET_KEY');
105
+ if (!secretKey) {
106
+ throw new Error('@atlasauth/nextjs/server: missing ATLAS_SECRET_KEY.');
107
+ }
108
+ const apiUrl = pick(env, 'ATLAS_API_URL', 'NEXT_PUBLIC_ATLAS_API_URL');
109
+ return { secretKey, apiUrl };
110
+ }
111
+ /**
112
+ * `clerkClient()`-equivalent: a configured `@atlasauth/backend` management client
113
+ * built from `ATLAS_SECRET_KEY` (+ optional `ATLAS_API_URL`). Overrides win over
114
+ * the environment, for tests and multi-instance setups.
115
+ */
116
+ function atlasClient(overrides = {}) {
117
+ const env = readEnv();
118
+ // Resolve from the environment leniently so an explicit override can supply
119
+ // the secret key on its own; `createAtlasClient` still throws if none is found
120
+ // from either source.
121
+ return (0, backend_1.createAtlasClient)({
122
+ secretKey: overrides.secretKey ?? pick(env, 'ATLAS_SECRET_KEY') ?? '',
123
+ apiUrl: overrides.apiUrl ?? pick(env, 'ATLAS_API_URL', 'NEXT_PUBLIC_ATLAS_API_URL'),
124
+ fetch: overrides.fetch,
125
+ });
126
+ }
127
+ /**
128
+ * Build an `EdgeRequest`-shaped object from a cookie store + a header store, the
129
+ * bridge between `next/headers` and the existing `resolveAuth` core. Pure and
130
+ * injectable: the ambient `auth()` feeds it the real Next stores, and tests feed
131
+ * it fakes — no request context required. `resolveAuth` reads only the
132
+ * `authorization` and `cookie` headers, so those are what we synthesize; the
133
+ * cookie header is reconstructed from the cookie store (which reflects any
134
+ * in-request mutations), falling back to the raw `cookie` header.
135
+ */
136
+ function buildEdgeRequest(cookieStore, headerStore) {
137
+ const reconstructed = cookieStore
138
+ .getAll()
139
+ .map(({ name, value }) => `${name}=${value}`)
140
+ .join('; ');
141
+ const cookieHeader = reconstructed.length > 0 ? reconstructed : (headerStore.get('cookie') ?? null);
142
+ const authorization = headerStore.get('authorization') ?? null;
143
+ return {
144
+ nextUrl: { pathname: '' },
145
+ headers: {
146
+ get(name) {
147
+ const key = name.toLowerCase();
148
+ if (key === 'cookie')
149
+ return cookieHeader;
150
+ if (key === 'authorization')
151
+ return authorization;
152
+ return headerStore.get(name) ?? null;
153
+ },
154
+ },
155
+ };
156
+ }
157
+ /**
158
+ * Read the ambient request from `next/headers` and shape it for the core.
159
+ * Imported dynamically so merely importing this module never touches
160
+ * `next/headers` (which throws outside a request scope) — the module loads only
161
+ * when `auth()`/`currentUser()` actually run inside a server component, route
162
+ * handler, or Server Action.
163
+ */
164
+ async function edgeRequestFromContext() {
165
+ const { cookies, headers } = await Promise.resolve().then(() => __importStar(require('next/headers')));
166
+ const cookieStore = await cookies();
167
+ const headerStore = await headers();
168
+ return buildEdgeRequest(cookieStore, headerStore);
169
+ }
170
+ /**
171
+ * Memoize the factory-built helpers by their resolved config so the in-process
172
+ * JWKS cache inside `AtlasBackend` stays warm across calls — rebuilding a fresh
173
+ * backend per `auth()` would throw that cache away and re-fetch the JWKS on
174
+ * every render, defeating the whole point of edge-local verification.
175
+ */
176
+ function cacheKey(options) {
177
+ return [options.jwksUrl, options.issuer, (options.authorizedParties ?? []).join(',')].join('\n');
178
+ }
179
+ let authHelperCache;
180
+ function getAuthHelper() {
181
+ const options = configFromEnv();
182
+ const key = cacheKey(options);
183
+ if (!authHelperCache || authHelperCache.key !== key) {
184
+ authHelperCache = { key, fn: (0, middleware_1.createAuthHelper)(options) };
185
+ }
186
+ return authHelperCache.fn;
187
+ }
188
+ let currentUserHelperCache;
189
+ function getCurrentUserHelper() {
190
+ const options = configFromEnv();
191
+ const key = cacheKey(options);
192
+ if (!currentUserHelperCache || currentUserHelperCache.key !== key) {
193
+ currentUserHelperCache = { key, fn: (0, middleware_1.createCurrentUserHelper)(options) };
194
+ }
195
+ return currentUserHelperCache.fn;
196
+ }
197
+ /**
198
+ * Clerk-parity `auth()` — no arguments. Reads cookies/headers from the ambient
199
+ * `next/headers` request, verifies the session at the edge via the shared core,
200
+ * and returns the same `AuthState & { has, protect }`. Config comes from the
201
+ * environment (see {@link configFromEnv}). Signed-out is a plain state, not a
202
+ * throw — call `.protect()` where anonymous access is a bug.
203
+ */
204
+ async function auth() {
205
+ const helper = getAuthHelper();
206
+ return helper(await edgeRequestFromContext());
207
+ }
208
+ /**
209
+ * Clerk-parity `currentUser()` — no arguments. The signed-in user's profile from
210
+ * the verified session claims (no round-trip), or `null` when signed out.
211
+ */
212
+ async function currentUser() {
213
+ const helper = getCurrentUserHelper();
214
+ return helper(await edgeRequestFromContext());
215
+ }
216
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,35 @@
1
1
  {
2
2
  "name": "@atlasauth/nextjs",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/index.js"
10
+ },
11
+ "./server": {
12
+ "types": "./dist/server.d.ts",
13
+ "default": "./dist/server.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
6
17
  "dependencies": {
7
- "@atlasauth/backend": "0.1.1"
18
+ "@atlasauth/backend": "0.1.2"
19
+ },
20
+ "peerDependencies": {
21
+ "next": ">=13.4"
22
+ },
23
+ "peerDependenciesMeta": {
24
+ "next": {
25
+ "optional": true
26
+ }
8
27
  },
9
28
  "devDependencies": {
10
29
  "typescript": "^5.6.3",
11
30
  "vitest": "^2.1.4",
12
- "jose": "^5.9.6"
31
+ "jose": "^5.9.6",
32
+ "next": "^15.0.0"
13
33
  },
14
34
  "publishConfig": {
15
35
  "access": "public"