limen-auth 0.0.0 → 0.0.2-beta.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/README.md +18 -41
- package/dist/broadcast-channel.mjs +51 -0
- package/dist/build-tree.mjs +73 -0
- package/dist/client.d.mts +7 -0
- package/dist/client.mjs +71 -0
- package/dist/{constants-CsR2pQ_9.mjs → constants.mjs} +1 -3
- package/dist/context.d.mts +32 -0
- package/dist/define-plugin.d.mts +40 -0
- package/dist/{define-plugin-C7WOGU4b.mjs → define-plugin.mjs} +1 -3
- package/dist/envelope.mjs +39 -0
- package/dist/errors.d.mts +18 -0
- package/dist/{errors-4YJYt6f0.mjs → errors.mjs} +2 -5
- package/dist/fetcher.d.mts +17 -0
- package/dist/fetcher.mjs +112 -0
- package/dist/{helpers-CvmKjWi2.d.mts → helpers.d.mts} +1 -2
- package/dist/{helpers-Cs3VtXdv.mjs → helpers.mjs} +1 -3
- package/dist/hooks.d.mts +1 -0
- package/dist/hooks.mjs +34 -0
- package/dist/index.d.mts +14 -30
- package/dist/index.mjs +9 -11
- package/dist/infer.d.mts +42 -0
- package/dist/json-deep-equal.mjs +27 -0
- package/dist/normalize.d.mts +12 -0
- package/dist/normalize.mjs +19 -0
- package/dist/package.mjs +4 -0
- package/dist/path.mjs +41 -0
- package/dist/pipeline.mjs +65 -0
- package/dist/plugin.d.mts +71 -0
- package/dist/plugins/bearer/index.d.mts +13 -1
- package/dist/plugins/bearer/index.mjs +43 -1
- package/dist/plugins/bearer/storage.d.mts +8 -0
- package/dist/plugins/bearer/storage.mjs +41 -0
- package/dist/{index-B8SpHkSd.d.mts → plugins/bearer/types.d.mts} +1 -18
- package/dist/plugins/credential/index.d.mts +54 -1
- package/dist/plugins/credential/index.mjs +2 -4
- package/dist/plugins/credential/types.d.mts +35 -0
- package/dist/plugins/index.d.mts +13 -6
- package/dist/plugins/index.mjs +3 -2
- package/dist/plugins/magic-link/index.d.mts +17 -1
- package/dist/plugins/magic-link/index.mjs +2 -4
- package/dist/plugins/magic-link/types.d.mts +13 -0
- package/dist/plugins/oauth/index.d.mts +47 -1
- package/dist/plugins/oauth/index.mjs +3 -5
- package/dist/plugins/oauth/types.d.mts +35 -0
- package/dist/plugins/session-jwt/index.d.mts +24 -1
- package/dist/plugins/session-jwt/index.mjs +95 -1
- package/dist/plugins/session-jwt/jwt.mjs +34 -0
- package/dist/plugins/session-jwt/types.d.mts +11 -0
- package/dist/plugins/two-factor/index.d.mts +41 -1
- package/dist/plugins/two-factor/index.mjs +2 -4
- package/dist/plugins/two-factor/types.d.mts +26 -0
- package/dist/react/index.d.mts +6 -7
- package/dist/react/index.mjs +2 -20
- package/dist/react/react-store.d.mts +6 -0
- package/dist/react/react-store.mjs +18 -0
- package/dist/route.d.mts +80 -0
- package/dist/{route-DGxvFqWl.mjs → route.mjs} +1 -3
- package/dist/routes.d.mts +53 -0
- package/dist/routes.mjs +58 -0
- package/dist/serialize.d.mts +11 -0
- package/dist/serialize.mjs +23 -0
- package/dist/session-store.d.mts +29 -0
- package/dist/session-store.mjs +79 -0
- package/dist/session-sync.mjs +47 -0
- package/dist/solid/index.d.mts +6 -7
- package/dist/solid/index.mjs +2 -17
- package/dist/solid/solid-store.d.mts +7 -0
- package/dist/solid/solid-store.mjs +15 -0
- package/dist/svelte/index.d.mts +5 -3
- package/dist/svelte/index.mjs +1 -3
- package/dist/type-utils.d.mts +15 -0
- package/dist/types.d.mts +97 -0
- package/dist/version.d.mts +4 -0
- package/dist/version.mjs +5 -0
- package/dist/vue/index.d.mts +6 -19
- package/dist/vue/index.mjs +2 -25
- package/dist/vue/vue-store.d.mts +18 -0
- package/dist/vue/vue-store.mjs +23 -0
- package/package.json +4 -3
- package/dist/bearer-Cqmrmjjf.mjs +0 -84
- package/dist/bearer-Cqmrmjjf.mjs.map +0 -1
- package/dist/client-Er91De-z.mjs +0 -705
- package/dist/client-Er91De-z.mjs.map +0 -1
- package/dist/constants-CsR2pQ_9.mjs.map +0 -1
- package/dist/define-plugin-C7WOGU4b.mjs.map +0 -1
- package/dist/define-plugin-Dv0xXIaH.d.mts +0 -450
- package/dist/define-plugin-Dv0xXIaH.d.mts.map +0 -1
- package/dist/errors-4YJYt6f0.mjs.map +0 -1
- package/dist/helpers-Cs3VtXdv.mjs.map +0 -1
- package/dist/helpers-CvmKjWi2.d.mts.map +0 -1
- package/dist/index-B8SpHkSd.d.mts.map +0 -1
- package/dist/index-C6atwjEq.d.mts +0 -65
- package/dist/index-C6atwjEq.d.mts.map +0 -1
- package/dist/index-C9EuA9UZ.d.mts +0 -32
- package/dist/index-C9EuA9UZ.d.mts.map +0 -1
- package/dist/index-Cgr2wHmM.d.mts +0 -87
- package/dist/index-Cgr2wHmM.d.mts.map +0 -1
- package/dist/index-DV6YcNSu.d.mts +0 -81
- package/dist/index-DV6YcNSu.d.mts.map +0 -1
- package/dist/index-dEksIImj.d.mts +0 -28
- package/dist/index-dEksIImj.d.mts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/plugins/credential/index.mjs.map +0 -1
- package/dist/plugins/magic-link/index.mjs.map +0 -1
- package/dist/plugins/oauth/index.mjs.map +0 -1
- package/dist/plugins/two-factor/index.mjs.map +0 -1
- package/dist/react/index.d.mts.map +0 -1
- package/dist/react/index.mjs.map +0 -1
- package/dist/route-DGxvFqWl.mjs.map +0 -1
- package/dist/session-jwt-DgLdMQxP.mjs +0 -129
- package/dist/session-jwt-DgLdMQxP.mjs.map +0 -1
- package/dist/solid/index.d.mts.map +0 -1
- package/dist/solid/index.mjs.map +0 -1
- package/dist/svelte/index.d.mts.map +0 -1
- package/dist/svelte/index.mjs.map +0 -1
- package/dist/vue/index.d.mts.map +0 -1
- package/dist/vue/index.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
declare function normalizeUser<F = unknown>(raw: Record<string, unknown>): User<F>;
|
|
17
|
-
declare function defaultSessionParse<F = unknown>(raw: unknown): Session<F>;
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/serialize.d.ts
|
|
20
|
-
/**
|
|
21
|
-
* Default request serializer: shallow camelCase → snake_case, drops `undefined`,
|
|
22
|
-
* leaves non-objects unchanged.
|
|
23
|
-
*
|
|
24
|
-
* `additionalFields` entries are merged into the top-level body verbatim.
|
|
25
|
-
* Known route fields win on key collisions.
|
|
26
|
-
*/
|
|
27
|
-
declare function defaultSerialize(input: unknown): unknown;
|
|
28
|
-
//#endregion
|
|
29
|
-
export { type ActiveSession, type AfterResponseHook, type AnyRouteContext, type AuthClient, type BeforeRequestHook, type ClientFetchOptions, type CoreContribution, type CreateAuthClientOptions, type EnvelopeConfig, type EnvelopeFields, type EnvelopeMode, type FetchInit, type HTTPMethod, LimenError, type LimenErrorCode, type ParseSession, type PluginClientOverride, type PluginIdOf, type PluginOverrides, type RedirectFn, type RequestContext, type ResponseContext, type RouteCallOptions, type RouteContext, type RouteHandler, type RouteMatcher, type RunRoute, type Session, type SessionState, type SessionStore, type User, VERSION, type VerifyEmailInput, camelizeEach, camelizeKeys, coreClientPlugin, createAuthClient, defaultSerialize, defaultSessionParse, defineClientPlugin, defineRoutes, deriveErrorCode, normalizeUser, route };
|
|
30
|
-
//# sourceMappingURL=index.d.mts.map
|
|
1
|
+
import { VERSION } from "./version.mjs";
|
|
2
|
+
import { LimenError, LimenErrorCode, deriveErrorCode } from "./errors.mjs";
|
|
3
|
+
import { RouteCallOptions, RouteHandler, route } from "./route.mjs";
|
|
4
|
+
import { ActiveSession, CoreContribution, VerifyEmailInput, coreClientPlugin } from "./routes.mjs";
|
|
5
|
+
import { SessionState, SessionStore } from "./session-store.mjs";
|
|
6
|
+
import { AuthClient, ClientFetchOptions, CreateAuthClientOptions, EnvelopeConfig, EnvelopeFields, EnvelopeMode, HTTPMethod, ParseSession, RedirectFn, Session, User } from "./types.mjs";
|
|
7
|
+
import { AfterResponseHook, BeforeRequestHook, FetchInit, PluginClientOverride, PluginIdOf, PluginOverrides, RequestContext, ResponseContext, RouteMatcher } from "./plugin.mjs";
|
|
8
|
+
import { AnyRouteContext, RouteContext } from "./context.mjs";
|
|
9
|
+
import { RunRoute, defineClientPlugin, defineRoutes } from "./define-plugin.mjs";
|
|
10
|
+
import { createAuthClient } from "./client.mjs";
|
|
11
|
+
import { camelizeEach, camelizeKeys } from "./helpers.mjs";
|
|
12
|
+
import { defaultSessionParse, normalizeUser } from "./normalize.mjs";
|
|
13
|
+
import { defaultSerialize } from "./serialize.mjs";
|
|
14
|
+
export { type ActiveSession, type AfterResponseHook, type AnyRouteContext, type AuthClient, type BeforeRequestHook, type ClientFetchOptions, type CoreContribution, type CreateAuthClientOptions, type EnvelopeConfig, type EnvelopeFields, type EnvelopeMode, type FetchInit, type HTTPMethod, LimenError, type LimenErrorCode, type ParseSession, type PluginClientOverride, type PluginIdOf, type PluginOverrides, type RedirectFn, type RequestContext, type ResponseContext, type RouteCallOptions, type RouteContext, type RouteHandler, type RouteMatcher, type RunRoute, type Session, type SessionState, type SessionStore, type User, VERSION, type VerifyEmailInput, camelizeEach, camelizeKeys, coreClientPlugin, createAuthClient, defaultSerialize, defaultSessionParse, defineClientPlugin, defineRoutes, deriveErrorCode, normalizeUser, route };
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { VERSION } from "./version.mjs";
|
|
2
|
+
import { camelizeEach, camelizeKeys } from "./helpers.mjs";
|
|
3
|
+
import { defaultSerialize } from "./serialize.mjs";
|
|
4
|
+
import { LimenError, deriveErrorCode } from "./errors.mjs";
|
|
5
|
+
import { defaultSessionParse, normalizeUser } from "./normalize.mjs";
|
|
6
|
+
import { defineClientPlugin, defineRoutes } from "./define-plugin.mjs";
|
|
7
|
+
import { route } from "./route.mjs";
|
|
8
|
+
import { coreClientPlugin } from "./routes.mjs";
|
|
9
|
+
import { createAuthClient } from "./client.mjs";
|
|
10
10
|
export { LimenError, VERSION, camelizeEach, camelizeKeys, coreClientPlugin, createAuthClient, defaultSerialize, defaultSessionParse, defineClientPlugin, defineRoutes, deriveErrorCode, normalizeUser, route };
|
|
11
|
-
|
|
12
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/infer.d.mts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { KebabToCamel, Split, UnionToIntersection } from "./type-utils.mjs";
|
|
2
|
+
import { InputOf, OutputOf, RouteCallOptions } from "./route.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/infer.d.ts
|
|
5
|
+
type IsParam<S extends string> = S extends `:${string}` ? true : false;
|
|
6
|
+
/**
|
|
7
|
+
* Turn a route path literal into its camelCased client-chain segments, dropping
|
|
8
|
+
* leading slashes and `:param` segments. `"/otp/send"` -> `["otp", "send"]`.
|
|
9
|
+
*/
|
|
10
|
+
type PathSegments<P extends string> = P extends `/${infer Rest}` ? PathSegments<Rest> : P extends `${infer Head}/${infer Tail}` ? Head extends "" ? PathSegments<Tail> : IsParam<Head> extends true ? PathSegments<Tail> : [KebabToCamel<Head>, ...PathSegments<Tail>] : P extends "" ? [] : IsParam<P> extends true ? [] : [KebabToCamel<P>];
|
|
11
|
+
type PathOf<R> = R extends {
|
|
12
|
+
path: infer P extends string;
|
|
13
|
+
} ? P : never;
|
|
14
|
+
/**
|
|
15
|
+
* The resolved chain for one route: an absolute `as` wins, otherwise it is the
|
|
16
|
+
* plugin's base-path segments followed by the route-path segments.
|
|
17
|
+
*/
|
|
18
|
+
type ChainSegments<R, BasePrefix extends readonly string[]> = R extends {
|
|
19
|
+
as: infer A extends string;
|
|
20
|
+
} ? Split<A, "."> : [...BasePrefix, ...PathSegments<PathOf<R>>];
|
|
21
|
+
type Nest<Segs extends readonly string[], Fn> = Segs extends readonly [infer Head extends string, ...infer Rest extends readonly string[]] ? string extends Head ? unknown : { [K in Head]: Nest<Rest, Fn> } : Fn;
|
|
22
|
+
/**
|
|
23
|
+
* A no-input route (`I` is `void`) takes no input — only the optional, trailing
|
|
24
|
+
* call options; everything else takes `input` followed by the call options.
|
|
25
|
+
* Options are always the trailing argument so the runtime can place them
|
|
26
|
+
* unambiguously (a lone argument is always the route input).
|
|
27
|
+
*/
|
|
28
|
+
type InferRouteFn<I, O> = [I] extends [void] ? (input?: void, opts?: RouteCallOptions<O>) => Promise<O> : (input: I, opts?: RouteCallOptions<O>) => Promise<O>;
|
|
29
|
+
type IsExposed<R> = R extends {
|
|
30
|
+
expose: false;
|
|
31
|
+
} ? false : true;
|
|
32
|
+
type RouteFn<R> = InferRouteFn<InputOf<R>, OutputOf<R>>;
|
|
33
|
+
type InferOneRoute<R, BasePrefix extends readonly string[]> = IsExposed<R> extends false ? unknown : Nest<ChainSegments<R, BasePrefix>, RouteFn<R>>;
|
|
34
|
+
/**
|
|
35
|
+
* Infer the public API tree for a list of route descriptors, given the owning
|
|
36
|
+
* plugin's base-path segments. Each route mounts a callable at its resolved
|
|
37
|
+
* chain; sibling keys merge via intersection, so `signin.credential` and
|
|
38
|
+
* `signup.credential` coexist and both autocomplete.
|
|
39
|
+
*/
|
|
40
|
+
type InferRoutes<Routes extends readonly unknown[], BasePrefix extends readonly string[]> = UnionToIntersection<{ [K in keyof Routes]: InferOneRoute<Routes[K], BasePrefix> }[number]>;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { InferRoutes, PathSegments };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/json-deep-equal.ts
|
|
2
|
+
function isPlainObject(value) {
|
|
3
|
+
if (typeof value !== "object" || value === null) return false;
|
|
4
|
+
const proto = Object.getPrototypeOf(value);
|
|
5
|
+
return proto === Object.prototype || proto === null;
|
|
6
|
+
}
|
|
7
|
+
function equalArrays(a, b) {
|
|
8
|
+
if (a.length !== b.length) return false;
|
|
9
|
+
for (let i = 0; i < a.length; i += 1) if (!deepJsonEqual(a[i], b[i])) return false;
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
function equalObjects(a, b) {
|
|
13
|
+
const aKeys = Object.keys(a);
|
|
14
|
+
const bKeys = Object.keys(b);
|
|
15
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
16
|
+
for (const key of aKeys) if (!Object.hasOwn(b, key) || !deepJsonEqual(a[key], b[key])) return false;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/** Structural equality for JSON-shaped values. */
|
|
20
|
+
function deepJsonEqual(a, b) {
|
|
21
|
+
if (Object.is(a, b)) return true;
|
|
22
|
+
if (Array.isArray(a) && Array.isArray(b)) return equalArrays(a, b);
|
|
23
|
+
if (!isPlainObject(a) || !isPlainObject(b)) return false;
|
|
24
|
+
return equalObjects(a, b);
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { deepJsonEqual };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Session, User } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/normalize.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Convert snake_case User keys from server payloads to camelCase. Unknown
|
|
6
|
+
* extension fields are converted with the same rule so consumers consistently
|
|
7
|
+
* read camelCase in SDK responses.
|
|
8
|
+
*/
|
|
9
|
+
declare function normalizeUser<F = unknown>(raw: Record<string, unknown>): User<F>;
|
|
10
|
+
declare function defaultSessionParse<F = unknown>(raw: unknown): Session<F>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { defaultSessionParse, normalizeUser };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { toCamelCaseKey } from "./helpers.mjs";
|
|
2
|
+
//#region src/normalize.ts
|
|
3
|
+
/**
|
|
4
|
+
* Convert snake_case User keys from server payloads to camelCase. Unknown
|
|
5
|
+
* extension fields are converted with the same rule so consumers consistently
|
|
6
|
+
* read camelCase in SDK responses.
|
|
7
|
+
*/
|
|
8
|
+
function normalizeUser(raw) {
|
|
9
|
+
const out = {};
|
|
10
|
+
for (const [key, value] of Object.entries(raw)) out[toCamelCaseKey(key)] = value;
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
function defaultSessionParse(raw) {
|
|
14
|
+
if (!raw || typeof raw !== "object") throw new TypeError(`Expected session response to be an object, got ${raw === null ? "null" : typeof raw}`);
|
|
15
|
+
const obj = raw;
|
|
16
|
+
return { user: normalizeUser(obj["user"] ?? obj) };
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { defaultSessionParse, normalizeUser };
|
package/dist/package.mjs
ADDED
package/dist/path.mjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { kebabToCamel } from "./helpers.mjs";
|
|
2
|
+
//#region src/path.ts
|
|
3
|
+
/**
|
|
4
|
+
* Derive the public client chain from a route path. Mirrors the type-level
|
|
5
|
+
* `PathSegments` in `infer.ts` exactly, so runtime materialization and compile
|
|
6
|
+
* time inference can never drift.
|
|
7
|
+
*
|
|
8
|
+
* "/otp/send" -> ["otp", "send"]
|
|
9
|
+
* "/revoke-sessions" -> ["revokeSessions"]
|
|
10
|
+
* "/:provider/authorize" -> ["authorize"] (param segments are dropped)
|
|
11
|
+
*/
|
|
12
|
+
function pathToChain(path) {
|
|
13
|
+
return path.split("/").filter((seg) => seg.length > 0 && !seg.startsWith(":")).map(kebabToCamel);
|
|
14
|
+
}
|
|
15
|
+
function chainFromDotted(chain) {
|
|
16
|
+
return chain.split(".").filter((seg) => seg.length > 0);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Substitute declared path params from `input` into `path` and strip them from
|
|
20
|
+
* the payload.
|
|
21
|
+
*/
|
|
22
|
+
function resolvePath(path, params, input) {
|
|
23
|
+
if (!params || params.length === 0) return {
|
|
24
|
+
path,
|
|
25
|
+
rest: input
|
|
26
|
+
};
|
|
27
|
+
const rest = { ...input ?? {} };
|
|
28
|
+
let resolved = path;
|
|
29
|
+
for (const param of params) {
|
|
30
|
+
const value = rest[param];
|
|
31
|
+
if (value === void 0) throw new Error(`Missing required path param "${param}" for route "${path}"`);
|
|
32
|
+
resolved = resolved.replace(`:${param}`, encodeURIComponent(value));
|
|
33
|
+
delete rest[param];
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
path: resolved,
|
|
37
|
+
rest
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { chainFromDotted, pathToChain, resolvePath };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { camelizeEach } from "./helpers.mjs";
|
|
2
|
+
import { resolvePath } from "./path.mjs";
|
|
3
|
+
import { defaultSerialize } from "./serialize.mjs";
|
|
4
|
+
//#region src/pipeline.ts
|
|
5
|
+
/**
|
|
6
|
+
* Run the default HTTP steps for a route — merge defaults, resolve path params,
|
|
7
|
+
* serialize, dispatch, parse — without applying session effects.
|
|
8
|
+
*/
|
|
9
|
+
async function runHttp(ctx, def, input) {
|
|
10
|
+
let merged = input;
|
|
11
|
+
if (def.defaults !== void 0) merged = {
|
|
12
|
+
...def.defaults,
|
|
13
|
+
...input ?? {}
|
|
14
|
+
};
|
|
15
|
+
const { path, rest } = resolvePath(def.path, def.params, merged);
|
|
16
|
+
const payload = def.serialize !== void 0 ? def.serialize(rest) : defaultSerialize(rest);
|
|
17
|
+
const init = {
|
|
18
|
+
method: def.method,
|
|
19
|
+
absolute: def.absolute ?? false
|
|
20
|
+
};
|
|
21
|
+
if (def.method === "GET" && payload !== void 0) init.query = payload;
|
|
22
|
+
else init.body = payload;
|
|
23
|
+
const raw = await ctx.fetch(path, init);
|
|
24
|
+
if (def.parseSession === true) return ctx.parseSession(raw);
|
|
25
|
+
if (def.parse !== void 0) return def.parse(raw);
|
|
26
|
+
return Array.isArray(raw) ? camelizeEach(raw) : raw;
|
|
27
|
+
}
|
|
28
|
+
async function applyEffects(ctx, def, result) {
|
|
29
|
+
if (def.clearSession === true) ctx.store.setData(null);
|
|
30
|
+
if (def.parseSession === true && def.skipStore !== true) {
|
|
31
|
+
if (result !== null && typeof result === "object" && "user" in result) ctx.store.setData(result);
|
|
32
|
+
}
|
|
33
|
+
if (def.refetchSession === true) await ctx.store.refetch();
|
|
34
|
+
}
|
|
35
|
+
function makeHttpRunner(ctx, def, boundInput) {
|
|
36
|
+
const run = (override) => runHttp(ctx, def, override === void 0 ? boundInput : override);
|
|
37
|
+
return run;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Execute a route's behaviour: delegate to its `handler` when present (handler
|
|
41
|
+
* owns all behaviour, including any effects), otherwise run the default
|
|
42
|
+
* pipeline and apply declarative effects once at the top level.
|
|
43
|
+
*/
|
|
44
|
+
async function dispatchRoute(ctx, def, input) {
|
|
45
|
+
if (def.handler !== void 0) return def.handler(ctx, input, makeHttpRunner(ctx, def, input));
|
|
46
|
+
const result = await runHttp(ctx, def, input);
|
|
47
|
+
await applyEffects(ctx, def, result);
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run a route as a public client call, firing the per-call `onSuccess` /
|
|
52
|
+
* `onError` hooks around the resolved value or thrown error.
|
|
53
|
+
*/
|
|
54
|
+
async function runRoute(ctx, def, input, opts) {
|
|
55
|
+
try {
|
|
56
|
+
const result = await dispatchRoute(ctx, def, input);
|
|
57
|
+
opts?.onSuccess?.(result);
|
|
58
|
+
return result;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
opts?.onError?.(error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { runRoute };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { KebabToCamel } from "./type-utils.mjs";
|
|
2
|
+
import { HTTPMethod } from "./types.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/plugin.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Route filter for hooks. Matches the stable route path, so client overrides do
|
|
7
|
+
* not change which hooks run.
|
|
8
|
+
*/
|
|
9
|
+
type RouteMatcher = string | readonly string[] | ((ctx: {
|
|
10
|
+
path: string;
|
|
11
|
+
}) => boolean);
|
|
12
|
+
/**
|
|
13
|
+
* Mutable request context passed to `beforeRequest` hooks. Return the updated
|
|
14
|
+
* context, or throw to abort the request.
|
|
15
|
+
*/
|
|
16
|
+
type RequestContext = {
|
|
17
|
+
method: HTTPMethod; /** Path relative to `baseURL` (already includes the configured `basePath`). */
|
|
18
|
+
fullPath: string; /** Path relative to the client `basePath`. */
|
|
19
|
+
path: string; /** Stable route identifier, unaffected by client overrides. */
|
|
20
|
+
routePath: string; /** Full request URL. */
|
|
21
|
+
url: string;
|
|
22
|
+
headers: Headers;
|
|
23
|
+
body: unknown;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Mutable response context passed to `afterResponse` hooks. The body has
|
|
27
|
+
* already been envelope-unwrapped.
|
|
28
|
+
*/
|
|
29
|
+
type ResponseContext = Omit<RequestContext, "url"> & {
|
|
30
|
+
/** Status code. */status: number; /** Whether the response is successful. */
|
|
31
|
+
ok: boolean;
|
|
32
|
+
};
|
|
33
|
+
type BeforeRequestHook = {
|
|
34
|
+
/** Optional route filter. Omit to run for every request. */match?: RouteMatcher;
|
|
35
|
+
run: (req: RequestContext) => RequestContext | Promise<RequestContext>;
|
|
36
|
+
};
|
|
37
|
+
type AfterResponseHook = {
|
|
38
|
+
match?: RouteMatcher; /** Run even for failed responses. */
|
|
39
|
+
allowOnFailure?: boolean;
|
|
40
|
+
run: (res: ResponseContext) => ResponseContext | Promise<ResponseContext>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Request and response hooks contributed by a plugin.
|
|
44
|
+
*/
|
|
45
|
+
type PluginHooks = {
|
|
46
|
+
beforeRequest?: BeforeRequestHook[];
|
|
47
|
+
afterResponse?: AfterResponseHook[];
|
|
48
|
+
};
|
|
49
|
+
/** Options accepted by `ctx.fetch(path, init)`. */
|
|
50
|
+
type FetchInit = {
|
|
51
|
+
method?: HTTPMethod; /** JSON body. The fetcher stringifies. */
|
|
52
|
+
body?: unknown; /** Appended as `?k=v` query string. */
|
|
53
|
+
query?: Record<string, string>; /** Extra headers to merge with the defaults (`Content-Type`, `Accept`). */
|
|
54
|
+
headers?: HeadersInit;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve `path` from the client base path instead of the plugin base path.
|
|
57
|
+
*/
|
|
58
|
+
absolute?: boolean;
|
|
59
|
+
};
|
|
60
|
+
type PluginIdOf<P> = P extends {
|
|
61
|
+
readonly id: infer Id extends string;
|
|
62
|
+
} ? Id : never;
|
|
63
|
+
type PluginClientOverride = {
|
|
64
|
+
/** Replace the plugin's default base path (relative to the client `basePath`). */basePath?: string;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Per-plugin client overrides, keyed by camelCased plugin id.
|
|
68
|
+
*/
|
|
69
|
+
type PluginOverrides<Plugins extends readonly unknown[]> = Partial<Record<KebabToCamel<PluginIdOf<Plugins[number]>>, PluginClientOverride>>;
|
|
70
|
+
//#endregion
|
|
71
|
+
export { AfterResponseHook, BeforeRequestHook, FetchInit, PluginClientOverride, PluginHooks, PluginIdOf, PluginOverrides, RequestContext, ResponseContext, RouteMatcher };
|
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ClientPlugin } from "../../define-plugin.mjs";
|
|
2
|
+
import { BearerPlugin, BearerPluginConfig, BearerStorage, BearerTokens } from "./types.mjs";
|
|
3
|
+
import { localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage } from "./storage.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/bearer/index.d.ts
|
|
6
|
+
declare function bearerPlugin(config?: BearerPluginConfig): ClientPlugin<"bearer", "", [], {
|
|
7
|
+
bearer: {
|
|
8
|
+
getTokens: () => BearerTokens | null;
|
|
9
|
+
setTokens: (tokens: BearerTokens) => void;
|
|
10
|
+
clear: () => void;
|
|
11
|
+
};
|
|
12
|
+
}>;
|
|
13
|
+
//#endregion
|
|
2
14
|
export { type BearerPluginConfig, type BearerPlugin as BearerPublic, type BearerStorage, type BearerTokens, bearerPlugin, localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage };
|
|
@@ -1,2 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SET_AUTH_TOKEN_HEADER, SET_REFRESH_TOKEN_HEADER } from "../../constants.mjs";
|
|
2
|
+
import { defineClientPlugin, defineRoutes } from "../../define-plugin.mjs";
|
|
3
|
+
import { localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage } from "./storage.mjs";
|
|
4
|
+
//#region src/plugins/bearer/index.ts
|
|
5
|
+
function bearerPlugin(config = {}) {
|
|
6
|
+
const store = config.storage ?? resolveDefaultStorage(config.storageKey ?? "limen.tokens");
|
|
7
|
+
return defineClientPlugin({
|
|
8
|
+
id: "bearer",
|
|
9
|
+
routes: defineRoutes(),
|
|
10
|
+
actions: () => ({ bearer: {
|
|
11
|
+
getTokens: () => store.get(),
|
|
12
|
+
setTokens: (tokens) => store.set(tokens),
|
|
13
|
+
clear: () => store.clear()
|
|
14
|
+
} }),
|
|
15
|
+
hooks: {
|
|
16
|
+
beforeRequest: [{ run: (req) => {
|
|
17
|
+
const tokens = store.get();
|
|
18
|
+
if (tokens?.accessToken && !req.headers.has("Authorization")) req.headers.set("Authorization", `Bearer ${tokens.accessToken}`);
|
|
19
|
+
return req;
|
|
20
|
+
} }],
|
|
21
|
+
afterResponse: [{
|
|
22
|
+
allowOnFailure: true,
|
|
23
|
+
run: (res) => {
|
|
24
|
+
const accessToken = res.headers.get(SET_AUTH_TOKEN_HEADER);
|
|
25
|
+
if (accessToken) {
|
|
26
|
+
const tokens = { accessToken };
|
|
27
|
+
const refreshToken = res.headers.get(SET_REFRESH_TOKEN_HEADER);
|
|
28
|
+
if (refreshToken) tokens.refreshToken = refreshToken;
|
|
29
|
+
store.set(tokens);
|
|
30
|
+
}
|
|
31
|
+
return res;
|
|
32
|
+
}
|
|
33
|
+
}, {
|
|
34
|
+
match: ["/signout", "/revoke-sessions"],
|
|
35
|
+
run: (res) => {
|
|
36
|
+
store.clear();
|
|
37
|
+
return res;
|
|
38
|
+
}
|
|
39
|
+
}]
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
2
44
|
export { bearerPlugin, localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BearerStorage } from "./types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/bearer/storage.d.ts
|
|
4
|
+
declare function memoryBearerStorage(): BearerStorage;
|
|
5
|
+
declare function localStorageBearerStorage(key?: string): BearerStorage;
|
|
6
|
+
declare function resolveDefaultStorage(key: string): BearerStorage;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { DEFAULT_TOKEN_STORAGE_KEY } from "../../constants.mjs";
|
|
2
|
+
//#region src/plugins/bearer/storage.ts
|
|
3
|
+
function memoryBearerStorage() {
|
|
4
|
+
let tokens = null;
|
|
5
|
+
return {
|
|
6
|
+
get: () => tokens,
|
|
7
|
+
set: (next) => {
|
|
8
|
+
tokens = next;
|
|
9
|
+
},
|
|
10
|
+
clear: () => {
|
|
11
|
+
tokens = null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function localStorageBearerStorage(key = DEFAULT_TOKEN_STORAGE_KEY) {
|
|
16
|
+
return {
|
|
17
|
+
get: () => {
|
|
18
|
+
try {
|
|
19
|
+
const raw = globalThis.localStorage.getItem(key);
|
|
20
|
+
if (!raw) return null;
|
|
21
|
+
const parsed = JSON.parse(raw);
|
|
22
|
+
if (typeof parsed?.accessToken !== "string") return null;
|
|
23
|
+
return parsed;
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
set: (tokens) => {
|
|
29
|
+
globalThis.localStorage.setItem(key, JSON.stringify(tokens));
|
|
30
|
+
},
|
|
31
|
+
clear: () => {
|
|
32
|
+
globalThis.localStorage.removeItem(key);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function resolveDefaultStorage(key) {
|
|
37
|
+
if (typeof globalThis.localStorage !== "undefined") return localStorageBearerStorage(key);
|
|
38
|
+
return memoryBearerStorage();
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { n as ClientPlugin } from "./define-plugin-Dv0xXIaH.mjs";
|
|
2
|
-
|
|
3
1
|
//#region src/plugins/bearer/types.d.ts
|
|
4
2
|
type BearerPlugin = {
|
|
5
3
|
bearer: {
|
|
@@ -30,19 +28,4 @@ type BearerPluginConfig = {
|
|
|
30
28
|
storageKey?: string;
|
|
31
29
|
};
|
|
32
30
|
//#endregion
|
|
33
|
-
|
|
34
|
-
declare function memoryBearerStorage(): BearerStorage;
|
|
35
|
-
declare function localStorageBearerStorage(key?: string): BearerStorage;
|
|
36
|
-
declare function resolveDefaultStorage(key: string): BearerStorage;
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/plugins/bearer/index.d.ts
|
|
39
|
-
declare function bearerPlugin(config?: BearerPluginConfig): ClientPlugin<"bearer", "", [], {
|
|
40
|
-
bearer: {
|
|
41
|
-
getTokens: () => BearerTokens | null;
|
|
42
|
-
setTokens: (tokens: BearerTokens) => void;
|
|
43
|
-
clear: () => void;
|
|
44
|
-
};
|
|
45
|
-
}>;
|
|
46
|
-
//#endregion
|
|
47
|
-
export { BearerPlugin as a, BearerTokens as c, resolveDefaultStorage as i, localStorageBearerStorage as n, BearerPluginConfig as o, memoryBearerStorage as r, BearerStorage as s, bearerPlugin as t };
|
|
48
|
-
//# sourceMappingURL=index-B8SpHkSd.d.mts.map
|
|
31
|
+
export { BearerPlugin, BearerPluginConfig, BearerStorage, BearerTokens };
|
|
@@ -1,2 +1,55 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RouteDescriptor } from "../../route.mjs";
|
|
2
|
+
import { Session } from "../../types.mjs";
|
|
3
|
+
import { ClientPlugin } from "../../define-plugin.mjs";
|
|
4
|
+
import { ChangePasswordInput, CheckUsernameInput, RequestPasswordResetInput, ResetPasswordInput, SetPasswordInput, SignInCredentialInput, SignUpCredentialInput } from "./types.mjs";
|
|
5
|
+
|
|
6
|
+
//#region src/plugins/credential/index.d.ts
|
|
7
|
+
declare function credentialPasswordPlugin<TFields = unknown>(): ClientPlugin<"credential-password", "/", [RouteDescriptor<SignInCredentialInput, Session<TFields>, {
|
|
8
|
+
readonly method: "POST";
|
|
9
|
+
readonly path: "/signin/credential";
|
|
10
|
+
readonly parseSession: true;
|
|
11
|
+
readonly as: "signIn.credential";
|
|
12
|
+
readonly defaults: {
|
|
13
|
+
readonly rememberMe: true;
|
|
14
|
+
};
|
|
15
|
+
}>, RouteDescriptor<SignUpCredentialInput, Session<TFields>, {
|
|
16
|
+
readonly method: "POST";
|
|
17
|
+
readonly path: "/signup/credential";
|
|
18
|
+
readonly parseSession: true;
|
|
19
|
+
readonly as: "signUp.credential";
|
|
20
|
+
}>, RouteDescriptor<RequestPasswordResetInput, {
|
|
21
|
+
message: string;
|
|
22
|
+
}, {
|
|
23
|
+
readonly method: "POST";
|
|
24
|
+
readonly path: "/passwords/request-reset";
|
|
25
|
+
readonly as: "password.requestReset";
|
|
26
|
+
}>, RouteDescriptor<ResetPasswordInput, {
|
|
27
|
+
message: string;
|
|
28
|
+
}, {
|
|
29
|
+
readonly method: "POST";
|
|
30
|
+
readonly path: "/passwords/reset";
|
|
31
|
+
readonly as: "password.reset";
|
|
32
|
+
}>, RouteDescriptor<ChangePasswordInput, Session<TFields>, {
|
|
33
|
+
readonly method: "POST";
|
|
34
|
+
readonly path: "/passwords/change";
|
|
35
|
+
readonly parseSession: true;
|
|
36
|
+
readonly defaults: {
|
|
37
|
+
readonly revokeOtherSessions: true;
|
|
38
|
+
};
|
|
39
|
+
readonly as: "password.change";
|
|
40
|
+
}>, RouteDescriptor<SetPasswordInput, Session<TFields>, {
|
|
41
|
+
readonly method: "PUT";
|
|
42
|
+
readonly path: "/passwords";
|
|
43
|
+
readonly as: "password.set";
|
|
44
|
+
readonly parseSession: true;
|
|
45
|
+
readonly defaults: {
|
|
46
|
+
readonly revokeOtherSessions: true;
|
|
47
|
+
};
|
|
48
|
+
}>, RouteDescriptor<CheckUsernameInput, boolean, {
|
|
49
|
+
readonly method: "POST";
|
|
50
|
+
readonly path: "/usernames/check";
|
|
51
|
+
readonly parse: (raw: unknown) => boolean;
|
|
52
|
+
readonly as: "username.checkAvailability";
|
|
53
|
+
}>], Record<never, never>>;
|
|
54
|
+
//#endregion
|
|
2
55
|
export { type ChangePasswordInput, type CheckUsernameInput, type RequestPasswordResetInput, type ResetPasswordInput, type SetPasswordInput, type SignInCredentialInput, type SignUpCredentialInput, credentialPasswordPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { defineClientPlugin, defineRoutes } from "../../define-plugin.mjs";
|
|
2
|
+
import { route } from "../../route.mjs";
|
|
3
3
|
//#region src/plugins/credential/index.ts
|
|
4
4
|
function credentialPasswordPlugin() {
|
|
5
5
|
return defineClientPlugin({
|
|
@@ -46,5 +46,3 @@ function credentialPasswordPlugin() {
|
|
|
46
46
|
}
|
|
47
47
|
//#endregion
|
|
48
48
|
export { credentialPasswordPlugin };
|
|
49
|
-
|
|
50
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/plugins/credential/types.d.ts
|
|
2
|
+
type SignInCredentialInput = {
|
|
3
|
+
/** Email or username, depending on what the server enables. */credential: string;
|
|
4
|
+
password: string; /** When true (default), issues a long-lived session. */
|
|
5
|
+
rememberMe?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type SignUpCredentialInput = {
|
|
8
|
+
email: string;
|
|
9
|
+
password: string; /** Required when username-on-signup is enabled. */
|
|
10
|
+
username?: string; /** Optional profile fields the server records on the user. */
|
|
11
|
+
firstname?: string;
|
|
12
|
+
lastname?: string; /** Extra fields recorded on the user at registration. */
|
|
13
|
+
additionalFields?: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
type ChangePasswordInput = {
|
|
16
|
+
currentPassword: string;
|
|
17
|
+
newPassword: string; /** Invalidate other sessions on success. Defaults to true. */
|
|
18
|
+
revokeOtherSessions?: boolean;
|
|
19
|
+
};
|
|
20
|
+
type SetPasswordInput = {
|
|
21
|
+
newPassword: string;
|
|
22
|
+
revokeOtherSessions?: boolean;
|
|
23
|
+
};
|
|
24
|
+
type RequestPasswordResetInput = {
|
|
25
|
+
email: string;
|
|
26
|
+
};
|
|
27
|
+
type ResetPasswordInput = {
|
|
28
|
+
token: string;
|
|
29
|
+
newPassword: string;
|
|
30
|
+
};
|
|
31
|
+
type CheckUsernameInput = {
|
|
32
|
+
username: string;
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { ChangePasswordInput, CheckUsernameInput, RequestPasswordResetInput, ResetPasswordInput, SetPasswordInput, SignInCredentialInput, SignUpCredentialInput };
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { BearerPlugin, BearerPluginConfig, BearerStorage, BearerTokens } from "./bearer/types.mjs";
|
|
2
|
+
import { localStorageBearerStorage, memoryBearerStorage, resolveDefaultStorage } from "./bearer/storage.mjs";
|
|
3
|
+
import { bearerPlugin } from "./bearer/index.mjs";
|
|
4
|
+
import { ChangePasswordInput, CheckUsernameInput, RequestPasswordResetInput, ResetPasswordInput, SetPasswordInput, SignInCredentialInput, SignUpCredentialInput } from "./credential/types.mjs";
|
|
5
|
+
import { credentialPasswordPlugin } from "./credential/index.mjs";
|
|
6
|
+
import { RequestMagicLinkInput, VerifyMagicLinkInput } from "./magic-link/types.mjs";
|
|
7
|
+
import { magicLinkPlugin } from "./magic-link/index.mjs";
|
|
8
|
+
import { LinkOAuthInput, OAuthAccount, OAuthAuthorizeQuery, OAuthAuthorizeResult, OAuthTokens, SignInOAuthInput } from "./oauth/types.mjs";
|
|
9
|
+
import { oauthClientPlugin } from "./oauth/index.mjs";
|
|
10
|
+
import { SessionJwtPluginConfig, SessionJwtTokens } from "./session-jwt/types.mjs";
|
|
11
|
+
import { sessionJwtPlugin } from "./session-jwt/index.mjs";
|
|
12
|
+
import { DisableTwoFactorInput, FinalizeSetupInput, InitiateSetupInput, SendOTPInput, TwoFactorConfig, TwoFactorMethod, TwoFactorSetupURI, VerifyInput } from "./two-factor/types.mjs";
|
|
13
|
+
import { twoFactorPlugin } from "./two-factor/index.mjs";
|
|
7
14
|
export { type BearerPluginConfig, type BearerPlugin as BearerPublic, type BearerStorage, type BearerTokens, type ChangePasswordInput, type CheckUsernameInput, type DisableTwoFactorInput, type FinalizeSetupInput, type InitiateSetupInput, type LinkOAuthInput, type OAuthAccount, type OAuthAuthorizeQuery, type OAuthAuthorizeResult, type OAuthTokens, type RequestMagicLinkInput, type RequestPasswordResetInput, type ResetPasswordInput, type SendOTPInput, type SessionJwtPluginConfig, type SessionJwtTokens, type SetPasswordInput, type SignInCredentialInput, type SignInOAuthInput, type SignUpCredentialInput, type TwoFactorConfig, type TwoFactorMethod, type TwoFactorSetupURI, type VerifyInput, type VerifyMagicLinkInput, bearerPlugin, credentialPasswordPlugin, localStorageBearerStorage, magicLinkPlugin, memoryBearerStorage, oauthClientPlugin, resolveDefaultStorage, sessionJwtPlugin, twoFactorPlugin };
|