limen-auth 0.0.0 → 0.0.1

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.
Files changed (118) hide show
  1. package/README.md +16 -41
  2. package/dist/broadcast-channel.mjs +51 -0
  3. package/dist/build-tree.mjs +73 -0
  4. package/dist/client.d.mts +7 -0
  5. package/dist/client.mjs +71 -0
  6. package/dist/{constants-CsR2pQ_9.mjs → constants.mjs} +1 -3
  7. package/dist/context.d.mts +32 -0
  8. package/dist/define-plugin.d.mts +40 -0
  9. package/dist/{define-plugin-C7WOGU4b.mjs → define-plugin.mjs} +1 -3
  10. package/dist/envelope.mjs +39 -0
  11. package/dist/errors.d.mts +19 -0
  12. package/dist/{errors-4YJYt6f0.mjs → errors.mjs} +1 -3
  13. package/dist/fetcher.d.mts +17 -0
  14. package/dist/fetcher.mjs +112 -0
  15. package/dist/{helpers-CvmKjWi2.d.mts → helpers.d.mts} +1 -2
  16. package/dist/{helpers-Cs3VtXdv.mjs → helpers.mjs} +1 -3
  17. package/dist/hooks.d.mts +1 -0
  18. package/dist/hooks.mjs +34 -0
  19. package/dist/index.d.mts +14 -30
  20. package/dist/index.mjs +9 -11
  21. package/dist/infer.d.mts +42 -0
  22. package/dist/json-deep-equal.mjs +27 -0
  23. package/dist/normalize.d.mts +12 -0
  24. package/dist/normalize.mjs +19 -0
  25. package/dist/package.mjs +4 -0
  26. package/dist/path.mjs +41 -0
  27. package/dist/pipeline.mjs +65 -0
  28. package/dist/plugin.d.mts +71 -0
  29. package/dist/plugins/bearer/index.d.mts +13 -1
  30. package/dist/plugins/bearer/index.mjs +43 -1
  31. package/dist/plugins/bearer/storage.d.mts +8 -0
  32. package/dist/plugins/bearer/storage.mjs +41 -0
  33. package/dist/{index-B8SpHkSd.d.mts → plugins/bearer/types.d.mts} +1 -18
  34. package/dist/plugins/credential/index.d.mts +54 -1
  35. package/dist/plugins/credential/index.mjs +2 -4
  36. package/dist/plugins/credential/types.d.mts +35 -0
  37. package/dist/plugins/index.d.mts +13 -6
  38. package/dist/plugins/index.mjs +3 -2
  39. package/dist/plugins/magic-link/index.d.mts +17 -1
  40. package/dist/plugins/magic-link/index.mjs +2 -4
  41. package/dist/plugins/magic-link/types.d.mts +13 -0
  42. package/dist/plugins/oauth/index.d.mts +47 -1
  43. package/dist/plugins/oauth/index.mjs +3 -5
  44. package/dist/plugins/oauth/types.d.mts +35 -0
  45. package/dist/plugins/session-jwt/index.d.mts +24 -1
  46. package/dist/plugins/session-jwt/index.mjs +95 -1
  47. package/dist/plugins/session-jwt/jwt.mjs +34 -0
  48. package/dist/plugins/session-jwt/types.d.mts +11 -0
  49. package/dist/plugins/two-factor/index.d.mts +41 -1
  50. package/dist/plugins/two-factor/index.mjs +2 -4
  51. package/dist/plugins/two-factor/types.d.mts +26 -0
  52. package/dist/react/index.d.mts +6 -7
  53. package/dist/react/index.mjs +2 -20
  54. package/dist/react/react-store.d.mts +6 -0
  55. package/dist/react/react-store.mjs +18 -0
  56. package/dist/route.d.mts +80 -0
  57. package/dist/{route-DGxvFqWl.mjs → route.mjs} +1 -3
  58. package/dist/routes.d.mts +53 -0
  59. package/dist/routes.mjs +58 -0
  60. package/dist/serialize.d.mts +11 -0
  61. package/dist/serialize.mjs +23 -0
  62. package/dist/session-store.d.mts +29 -0
  63. package/dist/session-store.mjs +79 -0
  64. package/dist/session-sync.mjs +47 -0
  65. package/dist/solid/index.d.mts +6 -7
  66. package/dist/solid/index.mjs +2 -17
  67. package/dist/solid/solid-store.d.mts +7 -0
  68. package/dist/solid/solid-store.mjs +15 -0
  69. package/dist/svelte/index.d.mts +5 -3
  70. package/dist/svelte/index.mjs +1 -3
  71. package/dist/type-utils.d.mts +15 -0
  72. package/dist/types.d.mts +97 -0
  73. package/dist/version.d.mts +4 -0
  74. package/dist/version.mjs +5 -0
  75. package/dist/vue/index.d.mts +6 -19
  76. package/dist/vue/index.mjs +2 -25
  77. package/dist/vue/vue-store.d.mts +18 -0
  78. package/dist/vue/vue-store.mjs +23 -0
  79. package/package.json +4 -3
  80. package/dist/bearer-Cqmrmjjf.mjs +0 -84
  81. package/dist/bearer-Cqmrmjjf.mjs.map +0 -1
  82. package/dist/client-Er91De-z.mjs +0 -705
  83. package/dist/client-Er91De-z.mjs.map +0 -1
  84. package/dist/constants-CsR2pQ_9.mjs.map +0 -1
  85. package/dist/define-plugin-C7WOGU4b.mjs.map +0 -1
  86. package/dist/define-plugin-Dv0xXIaH.d.mts +0 -450
  87. package/dist/define-plugin-Dv0xXIaH.d.mts.map +0 -1
  88. package/dist/errors-4YJYt6f0.mjs.map +0 -1
  89. package/dist/helpers-Cs3VtXdv.mjs.map +0 -1
  90. package/dist/helpers-CvmKjWi2.d.mts.map +0 -1
  91. package/dist/index-B8SpHkSd.d.mts.map +0 -1
  92. package/dist/index-C6atwjEq.d.mts +0 -65
  93. package/dist/index-C6atwjEq.d.mts.map +0 -1
  94. package/dist/index-C9EuA9UZ.d.mts +0 -32
  95. package/dist/index-C9EuA9UZ.d.mts.map +0 -1
  96. package/dist/index-Cgr2wHmM.d.mts +0 -87
  97. package/dist/index-Cgr2wHmM.d.mts.map +0 -1
  98. package/dist/index-DV6YcNSu.d.mts +0 -81
  99. package/dist/index-DV6YcNSu.d.mts.map +0 -1
  100. package/dist/index-dEksIImj.d.mts +0 -28
  101. package/dist/index-dEksIImj.d.mts.map +0 -1
  102. package/dist/index.d.mts.map +0 -1
  103. package/dist/index.mjs.map +0 -1
  104. package/dist/plugins/credential/index.mjs.map +0 -1
  105. package/dist/plugins/magic-link/index.mjs.map +0 -1
  106. package/dist/plugins/oauth/index.mjs.map +0 -1
  107. package/dist/plugins/two-factor/index.mjs.map +0 -1
  108. package/dist/react/index.d.mts.map +0 -1
  109. package/dist/react/index.mjs.map +0 -1
  110. package/dist/route-DGxvFqWl.mjs.map +0 -1
  111. package/dist/session-jwt-DgLdMQxP.mjs +0 -129
  112. package/dist/session-jwt-DgLdMQxP.mjs.map +0 -1
  113. package/dist/solid/index.d.mts.map +0 -1
  114. package/dist/solid/index.mjs.map +0 -1
  115. package/dist/svelte/index.d.mts.map +0 -1
  116. package/dist/svelte/index.mjs.map +0 -1
  117. package/dist/vue/index.d.mts.map +0 -1
  118. package/dist/vue/index.mjs.map +0 -1
@@ -0,0 +1,58 @@
1
+ import { defineClientPlugin, defineRoutes } from "./define-plugin.mjs";
2
+ import { route } from "./route.mjs";
3
+ //#region src/routes.ts
4
+ /**
5
+ * Core routes available on every client.
6
+ */
7
+ function coreClientPlugin() {
8
+ return defineClientPlugin({
9
+ id: "core",
10
+ basePath: "/",
11
+ routes: defineRoutes(route()({
12
+ method: "GET",
13
+ path: "/sessions"
14
+ }), route()({
15
+ method: "POST",
16
+ path: "/signout",
17
+ clearSession: true
18
+ }), route()({
19
+ method: "POST",
20
+ path: "/revoke-sessions",
21
+ clearSession: true
22
+ }), route()({
23
+ method: "POST",
24
+ path: "/verify-email",
25
+ refetchSession: true
26
+ }), route()({
27
+ method: "POST",
28
+ path: "/email-verifications",
29
+ as: "requestEmailVerification"
30
+ })),
31
+ actions: (ctx) => ({
32
+ /**
33
+ * Revalidate session state with `GET /me`, update `$session`, and return the
34
+ * resolved value (`null` when signed out).
35
+ *
36
+ * Prefer subscribing to `$session` for reactive UI state (`data`, `isPending`,
37
+ * `error`). Use `getSession()` when you need an awaited server re-check, such
38
+ * as route guards or SSR revalidation after `initialSession`.
39
+ */
40
+ getSession: async () => {
41
+ await ctx.refetchSession();
42
+ const state = ctx.store.$session.get();
43
+ if (state.error) throw state.error;
44
+ return state.data;
45
+ } })
46
+ });
47
+ }
48
+ /**
49
+ * Fetch and parse the current session for the reactive store.
50
+ */
51
+ function createSessionHydrator(ctx) {
52
+ return async () => {
53
+ const raw = await ctx.fetch("/me", { method: "GET" });
54
+ return ctx.parseSession(raw);
55
+ };
56
+ }
57
+ //#endregion
58
+ export { coreClientPlugin, createSessionHydrator };
@@ -0,0 +1,11 @@
1
+ //#region src/serialize.d.ts
2
+ /**
3
+ * Default request serializer: shallow camelCase → snake_case, drops `undefined`,
4
+ * leaves non-objects unchanged.
5
+ *
6
+ * `additionalFields` entries are merged into the top-level body verbatim.
7
+ * Known route fields win on key collisions.
8
+ */
9
+ declare function defaultSerialize(input: unknown): unknown;
10
+ //#endregion
11
+ export { defaultSerialize };
@@ -0,0 +1,23 @@
1
+ import { camelToSnake } from "./helpers.mjs";
2
+ //#region src/serialize.ts
3
+ /**
4
+ * Default request serializer: shallow camelCase → snake_case, drops `undefined`,
5
+ * leaves non-objects unchanged.
6
+ *
7
+ * `additionalFields` entries are merged into the top-level body verbatim.
8
+ * Known route fields win on key collisions.
9
+ */
10
+ function defaultSerialize(input) {
11
+ if (input === null || input === void 0) return input;
12
+ if (typeof input !== "object" || Array.isArray(input)) return input;
13
+ const { additionalFields, ...rest } = input;
14
+ const out = {};
15
+ if (additionalFields && typeof additionalFields === "object" && !Array.isArray(additionalFields)) Object.assign(out, additionalFields);
16
+ for (const [key, value] of Object.entries(rest)) {
17
+ if (value === void 0) continue;
18
+ out[camelToSnake(key)] = value;
19
+ }
20
+ return out;
21
+ }
22
+ //#endregion
23
+ export { defaultSerialize };
@@ -0,0 +1,29 @@
1
+ import { LimenError } from "./errors.mjs";
2
+ import { Session } from "./types.mjs";
3
+ import { ReadableAtom } from "nanostores";
4
+
5
+ //#region src/session-store.d.ts
6
+ type SessionState<TFields = unknown> = {
7
+ /** The current session, or `null` when signed out. */data: Session<TFields> | null; /** True while a `/me` fetch is in flight. */
8
+ isPending: boolean;
9
+ /**
10
+ * The last non-401 failure (network error, 5xx, etc.). A 401 is not an error
11
+ * — it resolves to `data: null`. `error` is cleared on the next successful or
12
+ * 401 outcome.
13
+ */
14
+ error: LimenError | null;
15
+ };
16
+ type RefetchOptions = {
17
+ /** Skip the fetch when the last hydration ran within this many milliseconds. */maxAgeMs?: number; /** Skip the fetch when the session is signed out. */
18
+ skipSignedOut?: boolean;
19
+ };
20
+ type SessionStore<TFields = unknown> = {
21
+ readonly $session: ReadableAtom<SessionState<TFields>>;
22
+ setData(session: Session<TFields> | null): void;
23
+ /**
24
+ * Re-validate the session from the server.
25
+ */
26
+ refetch(options?: RefetchOptions): Promise<void>;
27
+ };
28
+ //#endregion
29
+ export { SessionState, SessionStore };
@@ -0,0 +1,79 @@
1
+ import { LimenError } from "./errors.mjs";
2
+ import { createSessionSync } from "./session-sync.mjs";
3
+ import { atom, onMount } from "nanostores";
4
+ //#region src/session-store.ts
5
+ function createSessionStore(options) {
6
+ const $session = atom({
7
+ data: options.initialSession ?? null,
8
+ isPending: false,
9
+ error: null
10
+ });
11
+ let inFlightHydration = null;
12
+ let writeVersion = 0;
13
+ let lastRefreshedAt = 0;
14
+ const isStale = (requestVersion) => requestVersion !== writeVersion;
15
+ const fetchSessionFromServer = async () => {
16
+ const requestVersion = ++writeVersion;
17
+ $session.set({
18
+ data: $session.get().data,
19
+ isPending: true,
20
+ error: null
21
+ });
22
+ try {
23
+ const session = await options.hydrator();
24
+ if (isStale(requestVersion)) return;
25
+ $session.set({
26
+ data: session,
27
+ isPending: false,
28
+ error: null
29
+ });
30
+ } catch (err) {
31
+ if (isStale(requestVersion)) return;
32
+ if (err instanceof LimenError && err.isUnauthorized) {
33
+ $session.set({
34
+ data: null,
35
+ isPending: false,
36
+ error: null
37
+ });
38
+ return;
39
+ }
40
+ const error = err instanceof LimenError ? err : new LimenError(err instanceof Error ? err.message : "Failed to load session", 0, "unknown");
41
+ $session.set({
42
+ data: $session.get().data,
43
+ isPending: false,
44
+ error
45
+ });
46
+ }
47
+ };
48
+ const refetch = (options) => {
49
+ const { skipSignedOut, maxAgeMs } = options ?? {};
50
+ if (skipSignedOut && $session.get().data === null) return Promise.resolve();
51
+ if (maxAgeMs !== void 0 && Date.now() - lastRefreshedAt < maxAgeMs) return Promise.resolve();
52
+ if (!inFlightHydration) inFlightHydration = fetchSessionFromServer().finally(() => {
53
+ inFlightHydration = null;
54
+ lastRefreshedAt = Date.now();
55
+ });
56
+ return inFlightHydration;
57
+ };
58
+ const setData = (session) => {
59
+ writeVersion++;
60
+ $session.set({
61
+ data: session,
62
+ isPending: false,
63
+ error: null
64
+ });
65
+ };
66
+ const store = {
67
+ $session,
68
+ setData,
69
+ refetch
70
+ };
71
+ onMount($session, () => createSessionSync(store, {
72
+ fetchOnMount: options.initialSession === void 0,
73
+ crossTabSync: options.crossTabSync ?? false,
74
+ refetchOnWindowFocus: options.refetchOnWindowFocus ?? false
75
+ }));
76
+ return store;
77
+ }
78
+ //#endregion
79
+ export { createSessionStore };
@@ -0,0 +1,47 @@
1
+ import { createBroadcastChannel } from "./broadcast-channel.mjs";
2
+ import { deepJsonEqual } from "./json-deep-equal.mjs";
3
+ import { onNotify } from "nanostores";
4
+ //#region src/session-sync.ts
5
+ const CHANNEL_NAME = "limen.session";
6
+ const FOCUS_REFETCH_THROTTLE_MS = 5e3;
7
+ function createSessionSync(store, options) {
8
+ if (options.fetchOnMount) store.refetch();
9
+ const teardowns = [];
10
+ if (options.crossTabSync) teardowns.push(syncAcrossTabs(store));
11
+ if (options.refetchOnWindowFocus) teardowns.push(refetchOnFocus(store));
12
+ return () => {
13
+ for (const teardown of teardowns) teardown();
14
+ };
15
+ }
16
+ function syncAcrossTabs(store) {
17
+ const port = createBroadcastChannel(CHANNEL_NAME);
18
+ let lastData = store.$session.get().data;
19
+ const unsubscribe = port.subscribe((message) => {
20
+ lastData = message.data;
21
+ store.setData(message.data);
22
+ });
23
+ const unbindNotify = onNotify(store.$session, () => {
24
+ const data = store.$session.get().data;
25
+ if (deepJsonEqual(data, lastData)) return;
26
+ lastData = data;
27
+ port.post({ data });
28
+ });
29
+ return () => {
30
+ unbindNotify();
31
+ unsubscribe();
32
+ port.close();
33
+ };
34
+ }
35
+ function refetchOnFocus(store) {
36
+ if (typeof document === "undefined") return () => {};
37
+ const onVisibilityChange = () => {
38
+ if (document.visibilityState === "visible") store.refetch({
39
+ maxAgeMs: FOCUS_REFETCH_THROTTLE_MS,
40
+ skipSignedOut: true
41
+ });
42
+ };
43
+ document.addEventListener("visibilitychange", onVisibilityChange);
44
+ return () => document.removeEventListener("visibilitychange", onVisibilityChange);
45
+ }
46
+ //#endregion
47
+ export { createSessionSync };
@@ -1,10 +1,10 @@
1
- import { D as User, E as Session, O as SessionState, V as Prettify, _ as AuthClient, k as SessionStore, t as AnyClientPlugin, y as CreateAuthClientOptions } from "../define-plugin-Dv0xXIaH.mjs";
2
- import { Store, StoreValue } from "nanostores";
1
+ import { Prettify } from "../type-utils.mjs";
2
+ import { SessionState, SessionStore } from "../session-store.mjs";
3
+ import { AuthClient, CreateAuthClientOptions, Session, User } from "../types.mjs";
4
+ import { AnyClientPlugin } from "../define-plugin.mjs";
5
+ import { useStore } from "./solid-store.mjs";
3
6
  import { Accessor } from "solid-js";
4
7
 
5
- //#region src/solid/solid-store.d.ts
6
- declare function useStore<SomeStore extends Store, Value extends StoreValue<SomeStore>>(store: SomeStore): Accessor<Value>;
7
- //#endregion
8
8
  //#region src/solid/index.d.ts
9
9
  /**
10
10
  * An {@link AuthClient} augmented with Solid primitives.
@@ -21,5 +21,4 @@ type SolidAuthClient<Plugins extends readonly AnyClientPlugin[], TFields = unkno
21
21
  */
22
22
  declare function createAuthClient<const Plugins extends readonly AnyClientPlugin[] = readonly [], TFields = unknown>(opts: CreateAuthClientOptions<Plugins, TFields>): SolidAuthClient<Plugins, TFields>;
23
23
  //#endregion
24
- export { type AuthClient, type CreateAuthClientOptions, type Session, type SessionState, type SessionStore, SolidAuthClient, type User, createAuthClient, useStore };
25
- //# sourceMappingURL=index.d.mts.map
24
+ export { type AuthClient, type CreateAuthClientOptions, type Session, type SessionState, type SessionStore, SolidAuthClient, type User, createAuthClient, useStore };
@@ -1,18 +1,5 @@
1
- import { t as createAuthClient$1 } from "../client-Er91De-z.mjs";
2
- import { onCleanup } from "solid-js";
3
- import { createStore, reconcile } from "solid-js/store";
4
- //#region src/solid/solid-store.ts
5
- function useStore(store) {
6
- const unbindActivation = store.listen(() => {});
7
- const [state, setState] = createStore({ value: store.get() });
8
- const unsubscribe = store.subscribe((value) => {
9
- setState("value", reconcile(value));
10
- });
11
- onCleanup(() => unsubscribe());
12
- unbindActivation();
13
- return () => state.value;
14
- }
15
- //#endregion
1
+ import { createAuthClient as createAuthClient$1 } from "../client.mjs";
2
+ import { useStore } from "./solid-store.mjs";
16
3
  //#region src/solid/index.ts
17
4
  /**
18
5
  * Create a Limen auth client with Solid primitives attached.
@@ -24,5 +11,3 @@ function createAuthClient(opts) {
24
11
  }
25
12
  //#endregion
26
13
  export { createAuthClient, useStore };
27
-
28
- //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,7 @@
1
+ import { Store, StoreValue } from "nanostores";
2
+ import { Accessor } from "solid-js";
3
+
4
+ //#region src/solid/solid-store.d.ts
5
+ declare function useStore<SomeStore extends Store, Value extends StoreValue<SomeStore>>(store: SomeStore): Accessor<Value>;
6
+ //#endregion
7
+ export { useStore };
@@ -0,0 +1,15 @@
1
+ import { onCleanup } from "solid-js";
2
+ import { createStore, reconcile } from "solid-js/store";
3
+ //#region src/solid/solid-store.ts
4
+ function useStore(store) {
5
+ const unbindActivation = store.listen(() => {});
6
+ const [state, setState] = createStore({ value: store.get() });
7
+ const unsubscribe = store.subscribe((value) => {
8
+ setState("value", reconcile(value));
9
+ });
10
+ onCleanup(() => unsubscribe());
11
+ unbindActivation();
12
+ return () => state.value;
13
+ }
14
+ //#endregion
15
+ export { useStore };
@@ -1,4 +1,7 @@
1
- import { D as User, E as Session, O as SessionState, V as Prettify, _ as AuthClient, k as SessionStore, t as AnyClientPlugin, y as CreateAuthClientOptions } from "../define-plugin-Dv0xXIaH.mjs";
1
+ import { Prettify } from "../type-utils.mjs";
2
+ import { SessionState, SessionStore } from "../session-store.mjs";
3
+ import { AuthClient, CreateAuthClientOptions, Session, User } from "../types.mjs";
4
+ import { AnyClientPlugin } from "../define-plugin.mjs";
2
5
  import { Readable } from "svelte/store";
3
6
 
4
7
  //#region src/svelte/index.d.ts
@@ -21,5 +24,4 @@ type SvelteAuthClient<Plugins extends readonly AnyClientPlugin[], TFields = unkn
21
24
  */
22
25
  declare function createAuthClient<const Plugins extends readonly AnyClientPlugin[] = readonly [], TFields = unknown>(opts: CreateAuthClientOptions<Plugins, TFields>): SvelteAuthClient<Plugins, TFields>;
23
26
  //#endregion
24
- export { type AuthClient, type CreateAuthClientOptions, type Session, type SessionState, type SessionStore, SvelteAuthClient, type User, createAuthClient };
25
- //# sourceMappingURL=index.d.mts.map
27
+ export { type AuthClient, type CreateAuthClientOptions, type Session, type SessionState, type SessionStore, SvelteAuthClient, type User, createAuthClient };
@@ -1,4 +1,4 @@
1
- import { t as createAuthClient$1 } from "../client-Er91De-z.mjs";
1
+ import { createAuthClient as createAuthClient$1 } from "../client.mjs";
2
2
  //#region src/svelte/index.ts
3
3
  /**
4
4
  * Create a Limen auth client with Svelte stores attached.
@@ -14,5 +14,3 @@ function createAuthClient(opts) {
14
14
  }
15
15
  //#endregion
16
16
  export { createAuthClient };
17
-
18
- //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,15 @@
1
+ //#region src/type-utils.d.ts
2
+ /** Collapse an intersection into a single readable object type on hover. */
3
+ type Prettify<T> = { [K in keyof T]: T[K] } & {};
4
+ /** Turn a union `A | B | C` into the intersection `A & B & C`. */
5
+ type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
6
+ /**
7
+ * Convert a kebab-case literal to camelCase: `"magic-link"` -> `"magicLink"`.
8
+ */
9
+ type KebabToCamel<S extends string> = S extends `${infer Head}-${infer Tail}` ? `${Head}${Capitalize<KebabToCamel<Tail>>}` : S;
10
+ /** Split a string literal into a tuple on a delimiter, dropping empty segments. */
11
+ type Split<S extends string, D extends string> = S extends `${infer Head}${D}${infer Tail}` ? Head extends "" ? Split<Tail, D> : [Head, ...Split<Tail, D>] : S extends "" ? [] : [S];
12
+ /** Check if a type is `any`. */
13
+ type IsAny<T> = 0 extends 1 & T ? true : false;
14
+ //#endregion
15
+ export { IsAny, KebabToCamel, Prettify, Split, UnionToIntersection };
@@ -0,0 +1,97 @@
1
+ import { Prettify } from "./type-utils.mjs";
2
+ import { FetcherFetchOptions } from "./fetcher.mjs";
3
+ import { CoreContribution } from "./routes.mjs";
4
+ import { SessionState } from "./session-store.mjs";
5
+ import { PluginOverrides } from "./plugin.mjs";
6
+ import { AnyClientPlugin, CombinedClientContributions } from "./define-plugin.mjs";
7
+ import { ReadableAtom } from "nanostores";
8
+
9
+ //#region src/types.d.ts
10
+ type ClientFetchOptions = Partial<FetcherFetchOptions>;
11
+ type CreateAuthClientOptions<Plugins extends readonly AnyClientPlugin[], TFields = unknown> = {
12
+ /** Server origin, e.g. `"http://localhost:8080"`. Trailing slash is stripped. */baseURL: string; /** Path where the Limen handler is mounted. Defaults to `"/auth"`. */
13
+ basePath?: string; /** Options that modify how the SDK performs HTTP requests. */
14
+ fetchOptions?: ClientFetchOptions;
15
+ /**
16
+ * Optional transformer for non-default session payloads.
17
+ *
18
+ * Provide this when your server returns custom user/session fields. It must
19
+ * map the raw response into `Session<TFields>`.
20
+ */
21
+ parseSession?: ParseSession<TFields>;
22
+ /**
23
+ * How the SDK navigates the browser when a flow hands control to an external
24
+ * page (e.g. an OAuth provider's authorization URL). Defaults to
25
+ * `window.location.href = url` when a `window` is available; a no-op in
26
+ * non-browser environments. Provide a custom function to integrate with a
27
+ * client-side router.
28
+ */
29
+ redirectFn?: RedirectFn; /** Plugins to register. */
30
+ plugins?: Plugins;
31
+ /**
32
+ * Response-envelope config. Set this when the server wraps successful or all
33
+ * responses.
34
+ */
35
+ envelope?: EnvelopeConfig;
36
+ /**
37
+ * Per-plugin route overrides. Keys are camelCased plugin ids, e.g.
38
+ * `{ magicLink: { basePath: "/passwordless" } }`.
39
+ */
40
+ overrides?: PluginOverrides<Plugins>;
41
+ /**
42
+ * SSR seed for the session store. Provide the session resolved server-side to
43
+ * avoid a hydration flash. When provided, lazy hydration is skipped until you
44
+ * call `getSession()` or the store revalidates.
45
+ */
46
+ initialSession?: Session<TFields> | null;
47
+ /**
48
+ * Keep session state in sync across browser tabs.
49
+ * Enabled by default in browsers. Set `false` to disable.
50
+ */
51
+ crossTabSync?: boolean;
52
+ /**
53
+ * Refresh session state when the tab becomes active again.
54
+ * Enabled by default in browsers. Set `false` to disable.
55
+ */
56
+ refetchOnWindowFocus?: boolean;
57
+ };
58
+ type AuthClient<Plugins extends readonly AnyClientPlugin[], TFields = unknown> = Prettify<{
59
+ readonly baseURL: string;
60
+ readonly basePath: string;
61
+ /**
62
+ * Reactive session store holding `{ data, isPending, error }`. Read it with
63
+ * `.get()` / `.listen()` or a framework `useStore`.
64
+ */
65
+ readonly $session: ReadableAtom<SessionState<TFields>>;
66
+ } & CoreContribution<TFields> & CombinedClientContributions<Plugins>>;
67
+ /**
68
+ * The user object returned from `/me` and any session-bearing response.
69
+ *
70
+ * `TFields` lets consumers extend the shape with custom user fields. The
71
+ * fields listed here are always present.
72
+ *
73
+ * @example
74
+ * type AppUser = User<{ firstName: string; orgId: string }>;
75
+ */
76
+ type User<TFields = unknown> = {
77
+ id: string;
78
+ email: string;
79
+ emailVerifiedAt: string | null;
80
+ } & TFields;
81
+ type Session<TFields = unknown> = {
82
+ user: User<TFields>;
83
+ };
84
+ type EnvelopeMode = "off" | "wrap-success" | "always";
85
+ type EnvelopeFields = {
86
+ data: string;
87
+ message: string;
88
+ };
89
+ type EnvelopeConfig = {
90
+ mode: EnvelopeMode;
91
+ fields?: EnvelopeFields;
92
+ };
93
+ type ParseSession<TFields = unknown> = (raw: unknown) => Session<TFields>;
94
+ type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
95
+ type RedirectFn = (url: string) => boolean;
96
+ //#endregion
97
+ export { AuthClient, ClientFetchOptions, CreateAuthClientOptions, EnvelopeConfig, EnvelopeFields, EnvelopeMode, HTTPMethod, ParseSession, RedirectFn, Session, User };
@@ -0,0 +1,4 @@
1
+ //#region src/version.d.ts
2
+ declare const VERSION: string;
3
+ //#endregion
4
+ export { VERSION };
@@ -0,0 +1,5 @@
1
+ import { version } from "./package.mjs";
2
+ //#region src/version.ts
3
+ const VERSION = version;
4
+ //#endregion
5
+ export { VERSION };
@@ -1,21 +1,9 @@
1
- import { D as User, E as Session, O as SessionState, V as Prettify, _ as AuthClient, k as SessionStore, t as AnyClientPlugin, y as CreateAuthClientOptions } from "../define-plugin-Dv0xXIaH.mjs";
2
- import { Store, StoreValue } from "nanostores";
3
- import { DeepReadonly, ShallowRef, UnwrapNestedRefs } from "vue";
1
+ import { Prettify } from "../type-utils.mjs";
2
+ import { SessionState, SessionStore } from "../session-store.mjs";
3
+ import { AuthClient, CreateAuthClientOptions, Session, User } from "../types.mjs";
4
+ import { AnyClientPlugin } from "../define-plugin.mjs";
5
+ import { ReactiveValue, useStore } from "./vue-store.mjs";
4
6
 
5
- //#region src/vue/vue-store.d.ts
6
- /** What {@link useStore} returns: a readonly reactive ref of the store value. */
7
- type ReactiveValue<Value> = DeepReadonly<UnwrapNestedRefs<ShallowRef<Value>>>;
8
- /**
9
- * Subscribe a Vue component to a nanostores store.
10
- *
11
- * Modeled on `@nanostores/vue`'s `useStore`: a `shallowRef` mirrors the store
12
- * value, `subscribe` keeps it in sync (firing once immediately), and the
13
- * listener is torn down on scope dispose. On the server (no `window`) it reads
14
- * once without subscribing, so a store seeded with `initialSession` renders
15
- * without leaving a subscription behind.
16
- */
17
- declare function useStore<SomeStore extends Store>(store: SomeStore): ReactiveValue<StoreValue<SomeStore>>;
18
- //#endregion
19
7
  //#region src/vue/index.d.ts
20
8
  /**
21
9
  * An {@link AuthClient} augmented with Vue composables.
@@ -32,5 +20,4 @@ type VueAuthClient<Plugins extends readonly AnyClientPlugin[], TFields = unknown
32
20
  */
33
21
  declare function createAuthClient<const Plugins extends readonly AnyClientPlugin[] = readonly [], TFields = unknown>(opts: CreateAuthClientOptions<Plugins, TFields>): VueAuthClient<Plugins, TFields>;
34
22
  //#endregion
35
- export { type AuthClient, type CreateAuthClientOptions, type ReactiveValue, type Session, type SessionState, type SessionStore, type User, VueAuthClient, createAuthClient, useStore };
36
- //# sourceMappingURL=index.d.mts.map
23
+ export { type AuthClient, type CreateAuthClientOptions, type ReactiveValue, type Session, type SessionState, type SessionStore, type User, VueAuthClient, createAuthClient, useStore };
@@ -1,26 +1,5 @@
1
- import { t as createAuthClient$1 } from "../client-Er91De-z.mjs";
2
- import { getCurrentScope, onScopeDispose, readonly, shallowRef } from "vue";
3
- //#region src/vue/vue-store.ts
4
- /**
5
- * Subscribe a Vue component to a nanostores store.
6
- *
7
- * Modeled on `@nanostores/vue`'s `useStore`: a `shallowRef` mirrors the store
8
- * value, `subscribe` keeps it in sync (firing once immediately), and the
9
- * listener is torn down on scope dispose. On the server (no `window`) it reads
10
- * once without subscribing, so a store seeded with `initialSession` renders
11
- * without leaving a subscription behind.
12
- */
13
- function useStore(store) {
14
- const state = shallowRef(store.get());
15
- if (typeof window !== "undefined") {
16
- const unsubscribe = store.subscribe((value) => {
17
- state.value = value;
18
- });
19
- if (getCurrentScope()) onScopeDispose(unsubscribe);
20
- }
21
- return readonly(state);
22
- }
23
- //#endregion
1
+ import { createAuthClient as createAuthClient$1 } from "../client.mjs";
2
+ import { useStore } from "./vue-store.mjs";
24
3
  //#region src/vue/index.ts
25
4
  /**
26
5
  * Create a Limen auth client with Vue composables attached.
@@ -32,5 +11,3 @@ function createAuthClient(opts) {
32
11
  }
33
12
  //#endregion
34
13
  export { createAuthClient, useStore };
35
-
36
- //# sourceMappingURL=index.mjs.map
@@ -0,0 +1,18 @@
1
+ import { Store, StoreValue } from "nanostores";
2
+ import { DeepReadonly, ShallowRef, UnwrapNestedRefs } from "vue";
3
+
4
+ //#region src/vue/vue-store.d.ts
5
+ /** What {@link useStore} returns: a readonly reactive ref of the store value. */
6
+ type ReactiveValue<Value> = DeepReadonly<UnwrapNestedRefs<ShallowRef<Value>>>;
7
+ /**
8
+ * Subscribe a Vue component to a nanostores store.
9
+ *
10
+ * Modeled on `@nanostores/vue`'s `useStore`: a `shallowRef` mirrors the store
11
+ * value, `subscribe` keeps it in sync (firing once immediately), and the
12
+ * listener is torn down on scope dispose. On the server (no `window`) it reads
13
+ * once without subscribing, so a store seeded with `initialSession` renders
14
+ * without leaving a subscription behind.
15
+ */
16
+ declare function useStore<SomeStore extends Store>(store: SomeStore): ReactiveValue<StoreValue<SomeStore>>;
17
+ //#endregion
18
+ export { ReactiveValue, useStore };
@@ -0,0 +1,23 @@
1
+ import { getCurrentScope, onScopeDispose, readonly, shallowRef } from "vue";
2
+ //#region src/vue/vue-store.ts
3
+ /**
4
+ * Subscribe a Vue component to a nanostores store.
5
+ *
6
+ * Modeled on `@nanostores/vue`'s `useStore`: a `shallowRef` mirrors the store
7
+ * value, `subscribe` keeps it in sync (firing once immediately), and the
8
+ * listener is torn down on scope dispose. On the server (no `window`) it reads
9
+ * once without subscribing, so a store seeded with `initialSession` renders
10
+ * without leaving a subscription behind.
11
+ */
12
+ function useStore(store) {
13
+ const state = shallowRef(store.get());
14
+ if (typeof window !== "undefined") {
15
+ const unsubscribe = store.subscribe((value) => {
16
+ state.value = value;
17
+ });
18
+ if (getCurrentScope()) onScopeDispose(unsubscribe);
19
+ }
20
+ return readonly(state);
21
+ }
22
+ //#endregion
23
+ export { useStore };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "limen-auth",
3
- "version": "0.0.0",
4
- "description": "TypeScript authentication client for Limen framework-agnostic core with React, Vue, Svelte, and Solid adapters.",
3
+ "version": "0.0.1",
4
+ "description": "Official TypeScript SDK for Limen, a composable Go auth library. Framework-agnostic core with React, Vue, Svelte, and Solid adapters.",
5
5
  "keywords": [
6
6
  "limen",
7
7
  "auth",
@@ -18,7 +18,7 @@
18
18
  "typescript",
19
19
  "sdk"
20
20
  ],
21
- "homepage": "https://github.com/thecodearcher/limen#readme",
21
+ "homepage": "https://limenauth.dev",
22
22
  "bugs": "https://github.com/thecodearcher/limen/issues",
23
23
  "repository": {
24
24
  "type": "git",
@@ -29,6 +29,7 @@
29
29
  "author": "Brian Iyoha <brian.iyoha@gmail.com>",
30
30
  "type": "module",
31
31
  "module": "./dist/index.mjs",
32
+ "types": "./dist/index.d.mts",
32
33
  "publishConfig": {
33
34
  "access": "public"
34
35
  },