@atlasauth/solid 0.0.0-stage → 0.1.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.
package/README.md CHANGED
@@ -1,3 +1,55 @@
1
- # Temporary Holding Version
1
+ # @atlasauth/solid
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ SolidJS bindings for [Atlas](https://atlasauth.net). Wraps the
4
+ framework-agnostic `@atlasauth/js` client in Solid's fine-grained reactivity:
5
+ drop in `<AtlasProvider>`, read auth state through accessors, and gate UI with
6
+ control components — the Solid peer of `@atlasauth/react` and `@atlasauth/vue`.
7
+
8
+ ```tsx
9
+ import {
10
+ AtlasProvider,
11
+ SignedIn,
12
+ SignedOut,
13
+ SignIn,
14
+ UserButton,
15
+ useAuth,
16
+ } from '@atlasauth/solid';
17
+
18
+ function App() {
19
+ return (
20
+ <AtlasProvider publishableKey="pk_test_...">
21
+ <SignedIn>
22
+ <UserButton />
23
+ </SignedIn>
24
+ <SignedOut>
25
+ <SignIn />
26
+ </SignedOut>
27
+ </AtlasProvider>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## Reactive accessors
33
+
34
+ Each returns Solid accessors (`() => T`), so a component re-runs only when the
35
+ field it reads changes:
36
+
37
+ - `useAtlas()` — the underlying client.
38
+ - `useAuth()` — `{ isLoaded, isSignedIn, userId, sessionId, orgId, orgRole, getToken, getProviderToken, signOut, has }`.
39
+ - `useUser()` — `{ isLoaded, isSignedIn, user, getProviderToken }`.
40
+ - `useSession()` — `{ isLoaded, session }`.
41
+
42
+ ## Control components
43
+
44
+ `<SignedIn>`, `<SignedOut>`, `<AtlasLoading>`, `<AtlasLoaded>`, and
45
+ `<Protect permission="…" fallback={…}>` — all `<Show>`-based. `<Protect>` is a
46
+ rendering helper, never an authorization boundary: the server checking the same
47
+ permission is what actually stops an action.
48
+
49
+ ## Widgets
50
+
51
+ `<SignIn>`, `<SignUp>`, and `<UserButton>` mount Atlas's server-driven flow into
52
+ a host element on mount and tear it down on cleanup.
53
+
54
+ > SSR-safe: the provider boots only in the browser; on the server it renders a
55
+ > `loading` state and hydrates into the real status on the client.
@@ -0,0 +1,45 @@
1
+ import { type ProtectCondition, type ProviderToken } from '@atlasauth/js';
2
+ import type { AuthStatus } from './provider';
3
+ import type { AtlasSession, AtlasUser } from './types';
4
+ /**
5
+ * The Solid peer of React's hooks and Vue's composables.
6
+ *
7
+ * Every one returns `isLoaded` alongside its data, and that is not ceremony:
8
+ * without it a component cannot tell "still booting" from "signed out", so it
9
+ * flashes a sign-in form for a frame on every load — the flash of
10
+ * unauthenticated content that makes an app feel broken. Each returned value is
11
+ * an ACCESSOR (a `() => T` function), the idiomatic Solid shape: call it inside
12
+ * JSX or an effect and that spot re-runs when just that field changes.
13
+ */
14
+ export declare function useUser(): {
15
+ isLoaded: () => boolean;
16
+ isSignedIn: () => boolean;
17
+ user: () => AtlasUser | null;
18
+ /**
19
+ * The signed-in user's own live token at a connected provider — always the
20
+ * caller's (the server keys off the session), refreshed on read if stale, and
21
+ * never the refresh token.
22
+ */
23
+ getProviderToken: (provider: string) => Promise<ProviderToken | null>;
24
+ };
25
+ export declare function useSession(): {
26
+ isLoaded: () => boolean;
27
+ session: () => AtlasSession | null;
28
+ };
29
+ export declare function useAuth(): {
30
+ isLoaded: () => boolean;
31
+ isSignedIn: () => boolean;
32
+ /** Three-state auth status (`loading` | `signed_in` | `signed_out`); same source as isLoaded/isSignedIn. */
33
+ status: () => AuthStatus;
34
+ /** The active session, or null while loading or signed out. */
35
+ session: () => AtlasSession | null;
36
+ userId: () => string | null;
37
+ sessionId: () => string | null;
38
+ orgId: () => string | null;
39
+ orgRole: () => string | null;
40
+ getToken: () => Promise<string | null>;
41
+ getProviderToken: (provider: string) => Promise<ProviderToken | null>;
42
+ signOut: () => Promise<void>;
43
+ /** Mirrors `<Protect>`, for logic that is not a render decision. */
44
+ has: (condition: ProtectCondition) => boolean;
45
+ };
@@ -0,0 +1,46 @@
1
+ import { evaluate } from '@atlasauth/js';
2
+ import { useAtlas } from './context';
3
+ /**
4
+ * The Solid peer of React's hooks and Vue's composables.
5
+ *
6
+ * Every one returns `isLoaded` alongside its data, and that is not ceremony:
7
+ * without it a component cannot tell "still booting" from "signed out", so it
8
+ * flashes a sign-in form for a frame on every load — the flash of
9
+ * unauthenticated content that makes an app feel broken. Each returned value is
10
+ * an ACCESSOR (a `() => T` function), the idiomatic Solid shape: call it inside
11
+ * JSX or an effect and that spot re-runs when just that field changes.
12
+ */
13
+ export function useUser() {
14
+ const client = useAtlas();
15
+ return {
16
+ isLoaded: () => client.state.status !== 'loading',
17
+ isSignedIn: () => client.state.status === 'signed_in',
18
+ user: () => client.state.user,
19
+ getProviderToken: client.getProviderToken,
20
+ };
21
+ }
22
+ export function useSession() {
23
+ const client = useAtlas();
24
+ return {
25
+ isLoaded: () => client.state.status !== 'loading',
26
+ session: () => client.state.session,
27
+ };
28
+ }
29
+ export function useAuth() {
30
+ const client = useAtlas();
31
+ return {
32
+ isLoaded: () => client.state.status !== 'loading',
33
+ isSignedIn: () => client.state.status === 'signed_in',
34
+ status: () => client.state.status,
35
+ session: () => client.state.session,
36
+ userId: () => client.state.claims?.sub ?? null,
37
+ sessionId: () => client.state.claims?.sid ?? null,
38
+ orgId: () => client.state.claims?.org_id ?? null,
39
+ orgRole: () => client.state.claims?.org_role ?? null,
40
+ getToken: client.getToken,
41
+ getProviderToken: client.getProviderToken,
42
+ signOut: client.signOut,
43
+ has: (condition) => evaluate(client.state.claims, condition).allowed,
44
+ };
45
+ }
46
+ //# sourceMappingURL=accessors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessors.js","sourceRoot":"","sources":["../src/accessors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA6C,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAIrC;;;;;;;;;GASG;AAEH,MAAM,UAAU,OAAO;IAWrB,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;QACjD,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW;QACrD,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;QAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU;IAIxB,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;QACjD,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO;IAiBrB,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;QACjD,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW;QACrD,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM;QACjC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO;QACnC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI;QAC9C,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI;QACjD,KAAK,EAAE,GAAG,EAAE,CAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAA6B,IAAI,IAAI;QACxE,OAAO,EAAE,GAAG,EAAE,CAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,QAA+B,IAAI,IAAI;QAC5E,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,OAAO;KACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { AtlasClient } from './provider';
2
+ /**
3
+ * The injected Atlas client — the Solid peer of React's `AtlasContext` and Vue's
4
+ * `ATLAS_INJECTION_KEY`.
5
+ *
6
+ * `<AtlasProvider>` puts exactly one `AtlasClient` here, so every accessor and
7
+ * component reaches a single reactive source of auth truth per provider — never
8
+ * a module-level singleton that would leak one request's session into another
9
+ * on an SSR server sharing a process.
10
+ */
11
+ export declare const AtlasContext: import("solid-js").Context<AtlasClient | undefined>;
12
+ /**
13
+ * Reach the Atlas client from inside the provider tree.
14
+ *
15
+ * Throws rather than handing back a null-ish default. An accessor that returned
16
+ * `{ user: null }` outside the provider is indistinguishable from a signed-out
17
+ * user, and the developer loses an afternoon to it.
18
+ */
19
+ export declare function useAtlas(): AtlasClient;
@@ -0,0 +1,26 @@
1
+ import { createContext, useContext } from 'solid-js';
2
+ /**
3
+ * The injected Atlas client — the Solid peer of React's `AtlasContext` and Vue's
4
+ * `ATLAS_INJECTION_KEY`.
5
+ *
6
+ * `<AtlasProvider>` puts exactly one `AtlasClient` here, so every accessor and
7
+ * component reaches a single reactive source of auth truth per provider — never
8
+ * a module-level singleton that would leak one request's session into another
9
+ * on an SSR server sharing a process.
10
+ */
11
+ export const AtlasContext = createContext();
12
+ /**
13
+ * Reach the Atlas client from inside the provider tree.
14
+ *
15
+ * Throws rather than handing back a null-ish default. An accessor that returned
16
+ * `{ user: null }` outside the provider is indistinguishable from a signed-out
17
+ * user, and the developer loses an afternoon to it.
18
+ */
19
+ export function useAtlas() {
20
+ const client = useContext(AtlasContext);
21
+ if (!client) {
22
+ throw new Error('Atlas accessors and components must be used inside <AtlasProvider publishableKey="...">.');
23
+ }
24
+ return client;
25
+ }
26
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGrD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,EAAe,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { type JSX } from 'solid-js';
2
+ import { type ProtectCondition } from '@atlasauth/js';
3
+ /**
4
+ * Control / conditional-rendering components — the Solid peers of React's
5
+ * `control-components.tsx` and Vue's `<SignedIn>` / `<Protect>`.
6
+ *
7
+ * All three are thin `<Show>` wrappers. `when` is passed as a zero-arg FUNCTION
8
+ * (an accessor), which `solid-js/h` converts to a reactive component prop — so
9
+ * the branch flips when auth state changes without re-rendering anything above
10
+ * it. (A plain getter would NOT be made reactive by `h`; only a function value
11
+ * is.) Children are a function so `<Show>` realises them only on the winning
12
+ * branch.
13
+ */
14
+ export declare function SignedIn(props: {
15
+ children?: JSX.Element;
16
+ }): JSX.Element;
17
+ export declare function SignedOut(props: {
18
+ children?: JSX.Element;
19
+ }): JSX.Element;
20
+ /** Render children only while the SDK is still loading. */
21
+ export declare function AtlasLoading(props: {
22
+ children?: JSX.Element;
23
+ }): JSX.Element;
24
+ /** Render children only once the SDK has finished loading — the symmetric
25
+ * partner of {@link AtlasLoading}. */
26
+ export declare function AtlasLoaded(props: {
27
+ children?: JSX.Element;
28
+ }): JSX.Element;
29
+ export type ProtectProps = ProtectCondition & {
30
+ children?: JSX.Element;
31
+ fallback?: JSX.Element;
32
+ };
33
+ /**
34
+ * `<Protect permission="…">` — conditional rendering.
35
+ *
36
+ * A rendering helper, NEVER an authorization boundary — anyone can flip the
37
+ * condition in devtools, and seeing is not doing. The server checking the same
38
+ * permission is the only thing that actually stops an action; this component's
39
+ * job is just to avoid showing a button that would fail. The evaluation lives in
40
+ * `@atlasauth/authz` (re-exported by `@atlasauth/js`), the one primitive every
41
+ * SDK shares, so this `<Protect>` and the server's `has()` judge a condition
42
+ * identically.
43
+ *
44
+ * Implemented as a `createMemo` whose value IS the content to render, returned
45
+ * straight from the component (not wrapped in `<Show>`). A component that
46
+ * returns another component — `<Protect>` returning `<Show>` — breaks under
47
+ * `solid-js/h`: the returned component's reactive scope stops updating, so the
48
+ * gate never reopened once the token's claims landed after boot. Returning a
49
+ * reactive accessor is how a function child behaves, and that tracks correctly.
50
+ */
51
+ export declare function Protect(props: ProtectProps): JSX.Element;
@@ -0,0 +1,80 @@
1
+ import { Show, createMemo } from 'solid-js';
2
+ import { h } from './h';
3
+ import { evaluate } from '@atlasauth/js';
4
+ import { useAtlas } from './context';
5
+ import { useUser } from './accessors';
6
+ /**
7
+ * Control / conditional-rendering components — the Solid peers of React's
8
+ * `control-components.tsx` and Vue's `<SignedIn>` / `<Protect>`.
9
+ *
10
+ * All three are thin `<Show>` wrappers. `when` is passed as a zero-arg FUNCTION
11
+ * (an accessor), which `solid-js/h` converts to a reactive component prop — so
12
+ * the branch flips when auth state changes without re-rendering anything above
13
+ * it. (A plain getter would NOT be made reactive by `h`; only a function value
14
+ * is.) Children are a function so `<Show>` realises them only on the winning
15
+ * branch.
16
+ */
17
+ export function SignedIn(props) {
18
+ const { isLoaded, isSignedIn } = useUser();
19
+ // Renders nothing while loading rather than flashing the signed-out branch.
20
+ return h(Show, { when: () => isLoaded() && isSignedIn() }, () => props.children);
21
+ }
22
+ export function SignedOut(props) {
23
+ const { isLoaded, isSignedIn } = useUser();
24
+ return h(Show, { when: () => isLoaded() && !isSignedIn() }, () => props.children);
25
+ }
26
+ /** Render children only while the SDK is still loading. */
27
+ export function AtlasLoading(props) {
28
+ const { isLoaded } = useUser();
29
+ return h(Show, { when: () => !isLoaded() }, () => props.children);
30
+ }
31
+ /** Render children only once the SDK has finished loading — the symmetric
32
+ * partner of {@link AtlasLoading}. */
33
+ export function AtlasLoaded(props) {
34
+ const { isLoaded } = useUser();
35
+ return h(Show, { when: () => isLoaded() }, () => props.children);
36
+ }
37
+ /**
38
+ * `<Protect permission="…">` — conditional rendering.
39
+ *
40
+ * A rendering helper, NEVER an authorization boundary — anyone can flip the
41
+ * condition in devtools, and seeing is not doing. The server checking the same
42
+ * permission is the only thing that actually stops an action; this component's
43
+ * job is just to avoid showing a button that would fail. The evaluation lives in
44
+ * `@atlasauth/authz` (re-exported by `@atlasauth/js`), the one primitive every
45
+ * SDK shares, so this `<Protect>` and the server's `has()` judge a condition
46
+ * identically.
47
+ *
48
+ * Implemented as a `createMemo` whose value IS the content to render, returned
49
+ * straight from the component (not wrapped in `<Show>`). A component that
50
+ * returns another component — `<Protect>` returning `<Show>` — breaks under
51
+ * `solid-js/h`: the returned component's reactive scope stops updating, so the
52
+ * gate never reopened once the token's claims landed after boot. Returning a
53
+ * reactive accessor is how a function child behaves, and that tracks correctly.
54
+ */
55
+ export function Protect(props) {
56
+ const client = useAtlas();
57
+ const loaded = () => client.state.status !== 'loading';
58
+ // Capture the condition ONCE as a plain object; it is fixed for the
59
+ // component's life (the `permission`/`role` props do not change the way auth
60
+ // state does).
61
+ const condition = {
62
+ permission: props.permission,
63
+ role: props.role,
64
+ anyPermission: props.anyPermission,
65
+ allPermissions: props.allPermissions,
66
+ plan: props.plan,
67
+ feature: props.feature,
68
+ };
69
+ // Read status AND claims unconditionally on every run so both are tracked
70
+ // from the first evaluation — while loading, show nothing (not the fallback);
71
+ // once loaded, show children when allowed and the caller's fallback when not.
72
+ const content = createMemo(() => {
73
+ const claims = client.state.claims;
74
+ if (!loaded())
75
+ return null;
76
+ return evaluate(claims, condition).allowed ? props.children : (props.fallback ?? null);
77
+ });
78
+ return content;
79
+ }
80
+ //# sourceMappingURL=control-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-components.js","sourceRoot":"","sources":["../src/control-components.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAY,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAyB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC;;;;;;;;;;GAUG;AAEH,MAAM,UAAU,QAAQ,CAAC,KAAiC;IACxD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAAC;IAC3C,4EAA4E;IAC5E,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAiC;IACzD,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAAC;IAC3C,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACpF,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,YAAY,CAAC,KAAiC;IAC5D,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED;sCACsC;AACtC,MAAM,UAAU,WAAW,CAAC,KAAiC;IAC3D,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;IAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACnE,CAAC;AAOD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,OAAO,CAAC,KAAmB;IACzC,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;IACvD,oEAAoE;IACpE,6EAA6E;IAC7E,eAAe;IACf,MAAM,SAAS,GAAG;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;IAEF,0EAA0E;IAC1E,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;QACnC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,IAAI,CAAC;QAC3B,OAAO,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,OAAO,OAAiC,CAAC;AAC3C,CAAC"}
package/dist/h.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { JSX } from 'solid-js';
2
+ /**
3
+ * `solid-js/h` is the runtime hyperscript — it lets this package author
4
+ * components WITHOUT JSX, so the build is a plain `tsc` (no Babel/vite-plugin-
5
+ * solid transform) exactly like `@atlasauth/vue`'s `h()` render functions.
6
+ *
7
+ * Its published types declare the output as a thunk (`() => Node`), which is how
8
+ * Solid carries a reactive node. At runtime Solid unwraps that function
9
+ * everywhere it accepts children — `insert`, `render`, `createComponent` — so it
10
+ * IS a valid reactive `JSX.Element`. We retype `h` to say so, which keeps every
11
+ * component signature returning an honest `JSX.Element` instead of a thunk.
12
+ */
13
+ export declare const h: (type: unknown, props?: unknown, ...children: unknown[]) => JSX.Element;
package/dist/h.js ADDED
@@ -0,0 +1,14 @@
1
+ import rawH from 'solid-js/h';
2
+ /**
3
+ * `solid-js/h` is the runtime hyperscript — it lets this package author
4
+ * components WITHOUT JSX, so the build is a plain `tsc` (no Babel/vite-plugin-
5
+ * solid transform) exactly like `@atlasauth/vue`'s `h()` render functions.
6
+ *
7
+ * Its published types declare the output as a thunk (`() => Node`), which is how
8
+ * Solid carries a reactive node. At runtime Solid unwraps that function
9
+ * everywhere it accepts children — `insert`, `render`, `createComponent` — so it
10
+ * IS a valid reactive `JSX.Element`. We retype `h` to say so, which keeps every
11
+ * component signature returning an honest `JSX.Element` instead of a thunk.
12
+ */
13
+ export const h = rawH;
14
+ //# sourceMappingURL=h.js.map
package/dist/h.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"h.js","sourceRoot":"","sources":["../src/h.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,YAAY,CAAC;AAG9B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,CAAC,GAAG,IAID,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './types';
2
+ export * from './context';
3
+ export * from './provider';
4
+ export * from './accessors';
5
+ export * from './control-components';
6
+ export * from './widgets';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types';
2
+ export * from './context';
3
+ export * from './provider';
4
+ export * from './accessors';
5
+ export * from './control-components';
6
+ export * from './widgets';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC"}
@@ -0,0 +1,100 @@
1
+ import { type JSX } from 'solid-js';
2
+ import { type ProviderToken } from '@atlasauth/js';
3
+ import type { AtlasOrganizationMembership, AtlasSession, AtlasUser, SessionClaims } from './types';
4
+ /**
5
+ * The Solid peer of React's `<AtlasProvider>` and Vue's `createAtlas()` plugin.
6
+ *
7
+ * It holds exactly one thing that matters in memory: the token. Not
8
+ * localStorage, not a cookie this code writes — the refresh token is HttpOnly so
9
+ * browser script never touches it, and the short-lived JWT lives only as long as
10
+ * the tab. A client that persisted either would outlive the tab and become the
11
+ * first thing an XSS reads.
12
+ */
13
+ export type AuthStatus = 'loading' | 'signed_in' | 'signed_out';
14
+ /**
15
+ * The reactive auth state. A Solid store, so a component that reads
16
+ * `client.state.user` re-runs ONLY when the user changes — the fine-grained
17
+ * peer of Vue's refs, not React's whole-component re-render.
18
+ */
19
+ export interface AtlasState {
20
+ status: AuthStatus;
21
+ user: AtlasUser | null;
22
+ session: AtlasSession | null;
23
+ claims: SessionClaims | null;
24
+ memberships: AtlasOrganizationMembership[];
25
+ }
26
+ /**
27
+ * The client provided to the whole app. Every field React's `AtlasContextValue`
28
+ * exposes, but reactivity is a Solid store (`state`) plus the mount seams the
29
+ * widgets drive, so the public surface stays recognisable across SDKs.
30
+ */
31
+ export interface AtlasClient {
32
+ publishableKey: string;
33
+ /** The instance's FAPI origin. */
34
+ frontendApi: string;
35
+ /** The reactive auth state; read fields off it inside a tracking scope. */
36
+ state: AtlasState;
37
+ /**
38
+ * A sign-in attempt handed back by an OAuth redirect that still owes a second
39
+ * factor (no session was issued). Null in the ordinary case. `<SignIn>` seeds
40
+ * its flow from this so the user resumes at the 2FA step instead of starting
41
+ * over. Captured synchronously at construction — before any component reads
42
+ * it — because such a redirect carries a status but no ticket.
43
+ */
44
+ pendingAttempt: {
45
+ id: string;
46
+ status: string;
47
+ } | null;
48
+ /** Always fresh: refreshes first if the cached token is close to expiry. */
49
+ getToken(): Promise<string | null>;
50
+ /**
51
+ * The signed-in user's OWN live token at a connected provider (Google,
52
+ * GitHub, …), so the app can call that provider's API. Null when there is no
53
+ * usable token. The server refreshes a stale one on read; the refresh token
54
+ * is never exposed.
55
+ */
56
+ getProviderToken(provider: string): Promise<ProviderToken | null>;
57
+ signOut(): Promise<void>;
58
+ setActiveOrganization(organizationId: string | null): Promise<void>;
59
+ reload(): Promise<void>;
60
+ /**
61
+ * Mount the server-driven sign-in / sign-up flow, or the user button, into a
62
+ * host element and return a disposer. These are the seams `<SignIn>`,
63
+ * `<SignUp>` and `<UserButton>` call in `onMount`, and tear down in
64
+ * `onCleanup`. The widgets live on the client (not in `@atlasauth/js`, which
65
+ * ships no DOM widgets) so a mounted flow can reach this same client — its
66
+ * `reload()` after completion, its `signOut()` — without re-threading context.
67
+ */
68
+ mountSignIn(el: HTMLElement): () => void;
69
+ mountSignUp(el: HTMLElement): () => void;
70
+ mountUserButton(el: HTMLElement): () => void;
71
+ }
72
+ export interface AtlasProviderProps {
73
+ publishableKey: string;
74
+ /** The instance's FAPI origin. Empty for same-origin. */
75
+ frontendApi?: string;
76
+ /** Injected in tests to drive the client through a mocked network. */
77
+ fetchImpl?: typeof fetch;
78
+ children?: JSX.Element;
79
+ }
80
+ /**
81
+ * Build the reactive client. Separated from the component so a test can
82
+ * construct it directly and so the mount seams close over one consistent
83
+ * client.
84
+ */
85
+ export declare function createAtlasClient(options: {
86
+ publishableKey: string;
87
+ frontendApi?: string;
88
+ fetchImpl?: typeof fetch;
89
+ }): {
90
+ client: AtlasClient;
91
+ boot: () => Promise<void>;
92
+ dispose: () => void;
93
+ };
94
+ /**
95
+ * The provider component. Builds the client, provides it, and boots the session
96
+ * on mount — guarded to the browser: on the server there is no redirect to
97
+ * complete and no cookie jar to read, so the app renders `loading` and hydrates
98
+ * into the real status on the client. The refresh timer is cleared on unmount.
99
+ */
100
+ export declare function AtlasProvider(props: AtlasProviderProps): JSX.Element;
@@ -0,0 +1,239 @@
1
+ import { onCleanup, onMount } from 'solid-js';
2
+ import { createStore } from 'solid-js/store';
3
+ import { isServer } from 'solid-js/web';
4
+ import { h } from './h';
5
+ import { FapiClient, TokenCache, getProviderToken as fetchProviderToken, msUntilRefresh, readExpiry, readRedirectResult, stripRedirectParams, } from '@atlasauth/js';
6
+ import { AtlasContext } from './context';
7
+ import { mountSignInWidget, mountSignUpWidget, mountUserButtonWidget } from './widgets';
8
+ /**
9
+ * Build the reactive client. Separated from the component so a test can
10
+ * construct it directly and so the mount seams close over one consistent
11
+ * client.
12
+ */
13
+ export function createAtlasClient(options) {
14
+ const publishableKey = options.publishableKey;
15
+ const baseUrl = options.frontendApi ?? '';
16
+ const doFetch = options.fetchImpl ?? fetch;
17
+ const [state, setState] = createStore({
18
+ status: 'loading',
19
+ user: null,
20
+ session: null,
21
+ claims: null,
22
+ memberships: [],
23
+ });
24
+ const cache = new TokenCache();
25
+ let timer = null;
26
+ // A `needs_second_factor` redirect carries a status but no ticket; that is
27
+ // what the 2FA resume seeds from. Read once, synchronously, at construction.
28
+ const pendingAttempt = (() => {
29
+ if (isServer || typeof window === 'undefined')
30
+ return null;
31
+ const result = readRedirectResult(window.location.search);
32
+ return result?.status && !result.ticket
33
+ ? { id: result.attemptId, status: result.status }
34
+ : null;
35
+ })();
36
+ const call = (path, init) => doFetch(`${baseUrl}${path}`, {
37
+ ...init,
38
+ // Cookies carry the session; a fetch without this is indistinguishable
39
+ // from being signed out.
40
+ credentials: 'include',
41
+ headers: {
42
+ 'x-publishable-key': publishableKey,
43
+ ...(init?.body ? { 'content-type': 'application/json' } : {}),
44
+ ...init?.headers,
45
+ },
46
+ });
47
+ const applyToken = (jwt, sessionId) => {
48
+ const expiresAt = readExpiry(jwt);
49
+ if (!expiresAt)
50
+ return;
51
+ cache.set({ jwt, expiresAt, sessionId });
52
+ setState('claims', decodeClaims(jwt));
53
+ };
54
+ // Keep the proactive refresh timer in step with the live token. Called after
55
+ // every status/token change rather than from a reactive effect, so the client
56
+ // behaves identically whether or not it was built inside a Solid root.
57
+ const scheduleRefresh = () => {
58
+ if (timer) {
59
+ clearTimeout(timer);
60
+ timer = null;
61
+ }
62
+ if (state.status !== 'signed_in')
63
+ return;
64
+ const token = cache.peek();
65
+ if (!token)
66
+ return;
67
+ const delay = msUntilRefresh({ token, now: Date.now() });
68
+ timer = setTimeout(() => void refresh(), delay);
69
+ };
70
+ const reload = async () => {
71
+ try {
72
+ const response = await call('/v1/client');
73
+ if (!response.ok)
74
+ throw new Error('boot failed');
75
+ const body = (await response.json());
76
+ if (!body.session || !body.user) {
77
+ cache.clear();
78
+ setState({ status: 'signed_out', user: null, session: null, claims: null, memberships: [] });
79
+ scheduleRefresh();
80
+ return;
81
+ }
82
+ setState({
83
+ status: 'signed_in',
84
+ user: body.user,
85
+ session: body.session,
86
+ memberships: body.organization_memberships ?? [],
87
+ });
88
+ if (body.jwt)
89
+ applyToken(body.jwt, body.session.id);
90
+ scheduleRefresh();
91
+ }
92
+ catch {
93
+ // A failed boot is NOT signed-out. Rendering a sign-in form because the
94
+ // network hiccuped throws away a perfectly good session and forces a
95
+ // needless re-auth.
96
+ if (state.status === 'loading')
97
+ setState('status', 'signed_out');
98
+ }
99
+ };
100
+ const refresh = async () => {
101
+ const current = cache.peek();
102
+ if (!current)
103
+ return;
104
+ try {
105
+ const response = await call(`/v1/client/sessions/${current.sessionId}/tokens`, {
106
+ method: 'POST',
107
+ });
108
+ if (!response.ok)
109
+ throw new Error('refresh failed');
110
+ const body = (await response.json());
111
+ applyToken(body.jwt, body.session_id);
112
+ scheduleRefresh();
113
+ }
114
+ catch {
115
+ // The session may genuinely be gone. Re-boot rather than guess.
116
+ await reload();
117
+ }
118
+ };
119
+ const getToken = async () => {
120
+ // A 5s skew so a token that would die inside the caller's request is
121
+ // refreshed first rather than handed over.
122
+ const usable = cache.get(5_000);
123
+ if (usable)
124
+ return usable.jwt;
125
+ await refresh();
126
+ return cache.get(5_000)?.jwt ?? null;
127
+ };
128
+ // The FAPI client for the token-vault read. Reuses the same publishable key
129
+ // and fetch so `@atlasauth/js` stays the single implementation.
130
+ const fapiClient = new FapiClient({ publishableKey, baseUrl, fetchImpl: doFetch });
131
+ const getProviderToken = (provider) => fetchProviderToken(fapiClient, provider);
132
+ const signOut = async () => {
133
+ const current = cache.peek();
134
+ if (current) {
135
+ await call(`/v1/client/sessions/${current.sessionId}/revoke`, { method: 'POST' }).catch(() => undefined);
136
+ }
137
+ cache.clear();
138
+ setState({ status: 'signed_out', user: null, session: null, claims: null, memberships: [] });
139
+ scheduleRefresh();
140
+ };
141
+ const setActiveOrganization = async (organizationId) => {
142
+ const current = cache.peek();
143
+ if (!current)
144
+ return;
145
+ const response = await call(`/v1/client/sessions/${current.sessionId}/touch`, {
146
+ method: 'POST',
147
+ body: JSON.stringify({ active_organization_id: organizationId }),
148
+ });
149
+ if (!response.ok)
150
+ return;
151
+ const body = (await response.json());
152
+ // The new token carries the new org claims; re-boot would work too but
153
+ // costs a round trip for information already in hand.
154
+ applyToken(body.jwt, current.sessionId);
155
+ await reload();
156
+ };
157
+ /**
158
+ * Complete a redirect-based sign-in. An OAuth or hosted-page flow lands back
159
+ * with a one-time ticket in the URL; exchange it for cookies, scrub the URL so
160
+ * a reload can't replay it, THEN boot. A redirect carrying only a status (a
161
+ * second factor still owed) has no ticket, so nothing is exchanged and the app
162
+ * boots signed-out — exactly as intended.
163
+ */
164
+ const boot = async () => {
165
+ const result = !isServer && typeof window !== 'undefined'
166
+ ? readRedirectResult(window.location.search)
167
+ : null;
168
+ if (result?.ticket) {
169
+ await call('/v1/client/tickets/exchange', {
170
+ method: 'POST',
171
+ body: JSON.stringify({ attempt_id: result.attemptId, ticket: result.ticket }),
172
+ }).catch(() => undefined);
173
+ }
174
+ if (result && typeof window !== 'undefined') {
175
+ window.history.replaceState({}, document.title, stripRedirectParams(window.location.href));
176
+ }
177
+ await reload();
178
+ };
179
+ // `client` is referenced inside the mount seams; the arrows only run once the
180
+ // `const` is initialised, so the self-reference is sound.
181
+ const client = {
182
+ publishableKey,
183
+ frontendApi: baseUrl,
184
+ state,
185
+ pendingAttempt,
186
+ getToken,
187
+ getProviderToken,
188
+ signOut,
189
+ setActiveOrganization,
190
+ reload,
191
+ mountSignIn: (el) => mountSignInWidget(client, el),
192
+ mountSignUp: (el) => mountSignUpWidget(client, el),
193
+ mountUserButton: (el) => mountUserButtonWidget(client, el),
194
+ };
195
+ // Clear the refresh timer WITHOUT revoking the session — the provider calls
196
+ // this on unmount. `signOut()` would log the user out server-side, which is
197
+ // emphatically not what unmounting a React/Vue/Solid tree should do.
198
+ const dispose = () => {
199
+ if (timer) {
200
+ clearTimeout(timer);
201
+ timer = null;
202
+ }
203
+ };
204
+ return { client, boot, dispose };
205
+ }
206
+ /**
207
+ * The provider component. Builds the client, provides it, and boots the session
208
+ * on mount — guarded to the browser: on the server there is no redirect to
209
+ * complete and no cookie jar to read, so the app renders `loading` and hydrates
210
+ * into the real status on the client. The refresh timer is cleared on unmount.
211
+ */
212
+ export function AtlasProvider(props) {
213
+ const { client, boot, dispose } = createAtlasClient({
214
+ publishableKey: props.publishableKey,
215
+ frontendApi: props.frontendApi,
216
+ fetchImpl: props.fetchImpl,
217
+ });
218
+ if (!isServer) {
219
+ onMount(() => {
220
+ void boot();
221
+ });
222
+ // The client's refresh timer is a resource that outlives a render; drop it
223
+ // when the provider unmounts so a torn-down app does not keep polling.
224
+ onCleanup(dispose);
225
+ }
226
+ return h(AtlasContext.Provider, { value: client }, () => props.children);
227
+ }
228
+ function decodeClaims(jwt) {
229
+ const parts = jwt.split('.');
230
+ if (parts.length !== 3)
231
+ return null;
232
+ try {
233
+ return JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
234
+ }
235
+ catch {
236
+ return null;
237
+ }
238
+ }
239
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The public auth shapes the Solid SDK surfaces.
3
+ *
4
+ * Kept identical to `@atlasauth/vue`'s `types.ts` on purpose: a customer moving
5
+ * a component between frameworks should read the same `user.first_name` and the
6
+ * same `claims.org_role`, not relearn the model. These mirror the FAPI
7
+ * `/v1/client` response, so the field names are the server's, not ours.
8
+ */
9
+ export interface SessionClaims {
10
+ sub: string;
11
+ sid: string;
12
+ exp: number;
13
+ org_id?: string;
14
+ org_slug?: string;
15
+ org_role?: string;
16
+ org_permissions?: string[];
17
+ mfa?: boolean;
18
+ [claim: string]: unknown;
19
+ }
20
+ export interface AtlasUser {
21
+ id: string;
22
+ first_name: string | null;
23
+ last_name: string | null;
24
+ username: string | null;
25
+ image_url: string | null;
26
+ public_metadata: Record<string, unknown>;
27
+ unsafe_metadata: Record<string, unknown>;
28
+ mfa_enabled: boolean;
29
+ has_password: boolean;
30
+ email_addresses?: Array<{
31
+ id: string;
32
+ email_address: string;
33
+ verified: boolean;
34
+ primary: boolean;
35
+ }>;
36
+ }
37
+ export interface AtlasOrganizationMembership {
38
+ role: string;
39
+ organization: {
40
+ id: string;
41
+ name: string;
42
+ slug: string;
43
+ image_url: string | null;
44
+ };
45
+ }
46
+ export interface AtlasSession {
47
+ id: string;
48
+ status: string;
49
+ last_active_organization_id: string | null;
50
+ }
package/dist/types.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The public auth shapes the Solid SDK surfaces.
3
+ *
4
+ * Kept identical to `@atlasauth/vue`'s `types.ts` on purpose: a customer moving
5
+ * a component between frameworks should read the same `user.first_name` and the
6
+ * same `claims.org_role`, not relearn the model. These mirror the FAPI
7
+ * `/v1/client` response, so the field names are the server's, not ours.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,8 @@
1
+ import { type JSX } from 'solid-js';
2
+ import type { AtlasClient } from './provider';
3
+ export declare function mountSignInWidget(client: AtlasClient, el: HTMLElement): () => void;
4
+ export declare function mountSignUpWidget(client: AtlasClient, el: HTMLElement): () => void;
5
+ export declare function mountUserButtonWidget(client: AtlasClient, el: HTMLElement): () => void;
6
+ export declare const SignIn: () => JSX.Element;
7
+ export declare const SignUp: () => JSX.Element;
8
+ export declare const UserButton: () => JSX.Element;
@@ -0,0 +1,207 @@
1
+ import { Show, createEffect, createSignal, onCleanup, onMount } from 'solid-js';
2
+ import { isServer, render } from 'solid-js/web';
3
+ import { h } from './h';
4
+ import { FapiClient, advance, flowFromPending, nextStep, pollAttempt, shouldKeepPolling, } from '@atlasauth/js';
5
+ import { useAtlas } from './context';
6
+ /** A labelled, UNCONTROLLED input — its value is read from the form's
7
+ * `FormData` on submit, which sidesteps per-keystroke signal churn for a plain
8
+ * auth form. */
9
+ function field(name, label, type = 'text') {
10
+ return h('label', { class: 'atlas-field' }, [
11
+ h('span', label),
12
+ h('input', { class: 'atlas-input', name, type }),
13
+ ]);
14
+ }
15
+ /** Form-level (non-field) errors, rendered as an alert. */
16
+ function renderErrors(errors) {
17
+ return errors
18
+ .filter((error) => !error.param)
19
+ .map((error) => h('p', { class: 'atlas-error', role: 'alert' }, error.message));
20
+ }
21
+ /** The fields for the current server-driven step. The `unknown`/default branch
22
+ * says so out loud rather than rendering a blank box the user cannot act on. */
23
+ function renderFields(kind) {
24
+ switch (kind) {
25
+ case 'collect_identifier':
26
+ return [field('identifier', 'Email', 'email')];
27
+ case 'collect_first_factor':
28
+ return [field('password', 'Password', 'password')];
29
+ case 'collect_second_factor':
30
+ return [field('code', 'Two-factor code')];
31
+ case 'enroll_second_factor':
32
+ // Two codes, not one: consecutive codes catch a phone with a fast clock
33
+ // here rather than on every sign-in afterwards.
34
+ return [
35
+ field('code', 'Authenticator code'),
36
+ field('secondCode', 'Next authenticator code'),
37
+ ];
38
+ case 'collect_email_code':
39
+ return [field('code', 'Email code')];
40
+ case 'collect_new_password':
41
+ return [field('password', 'New password', 'password')];
42
+ case 'await_oauth':
43
+ return [h('p', 'Continue in the window that opened.')];
44
+ case 'done':
45
+ return [h('p', 'Signed in — you can close this.')];
46
+ default:
47
+ return [h('p', { class: 'atlas-error' }, 'This step needs an updated app. Please reload.')];
48
+ }
49
+ }
50
+ function renderSubmit(kind, busy) {
51
+ if (kind === 'done' || kind === 'await_oauth')
52
+ return null;
53
+ return h('button', { class: 'atlas-button', type: 'submit', disabled: busy }, 'Continue');
54
+ }
55
+ /**
56
+ * The server-driven sign-in / sign-up flow. Never decides what comes next: it
57
+ * drives through `advance` (the driver owns the step→endpoint mapping) and
58
+ * renders whatever `status` the server returned. `<SignIn>` and `<SignUp>` are
59
+ * the same driver — only the title differs, exactly as in React and Vue.
60
+ */
61
+ function Flow(props) {
62
+ const client = props.client;
63
+ const fapi = new FapiClient({ publishableKey: client.publishableKey, baseUrl: client.frontendApi });
64
+ // Seeded from a redirect that returned mid-flow (OAuth owing a second
65
+ // factor), so the user resumes at the demanded step instead of restarting.
66
+ const [state, setState] = createSignal(flowFromPending(client.pendingAttempt));
67
+ const submit = (values) => {
68
+ void (async () => {
69
+ setState((s) => ({ ...s, busy: true, errors: [] }));
70
+ const next = await advance(fapi, state(), values);
71
+ setState(next);
72
+ // A completion response carries a one-time ticket (§7.1). FAPI is
73
+ // cross-origin to the app and cannot set the cookie on its own response,
74
+ // so exchange the ticket over a request THEN re-boot, so the rest of the
75
+ // app sees a signed-in user — and no session token ever rode in a URL.
76
+ if (next.attempt?.status === 'complete') {
77
+ if (next.ticket) {
78
+ await fapi.post('/v1/client/tickets/exchange', {
79
+ attempt_id: next.attempt.id,
80
+ ticket: next.ticket,
81
+ });
82
+ }
83
+ await client.reload();
84
+ }
85
+ })();
86
+ };
87
+ // §5.3 magic-link poll: a sign-in finished on another device. Restart on each
88
+ // state change, run only while the state says to, stop on teardown.
89
+ let poller = null;
90
+ const stopPolling = () => {
91
+ if (poller) {
92
+ clearInterval(poller);
93
+ poller = null;
94
+ }
95
+ };
96
+ createEffect(() => {
97
+ const current = state();
98
+ stopPolling();
99
+ if (!shouldKeepPolling(current))
100
+ return;
101
+ poller = setInterval(() => {
102
+ void (async () => {
103
+ const { state: next, ticket } = await pollAttempt(fapi, state());
104
+ setState(next);
105
+ if (!ticket || !next.attempt)
106
+ return;
107
+ await fapi.post('/v1/client/tickets/exchange', {
108
+ attempt_id: next.attempt.id,
109
+ ticket,
110
+ });
111
+ await client.reload();
112
+ })();
113
+ }, 2_000);
114
+ });
115
+ onCleanup(stopPolling);
116
+ const step = () => {
117
+ const attempt = state().attempt;
118
+ return attempt ? nextStep(attempt) : { kind: 'collect_identifier' };
119
+ };
120
+ return h('form', {
121
+ class: 'atlas-card',
122
+ onSubmit: (event) => {
123
+ event.preventDefault();
124
+ const form = event.currentTarget;
125
+ const values = {};
126
+ new FormData(form).forEach((value, key) => {
127
+ values[key] = String(value);
128
+ });
129
+ submit(values);
130
+ },
131
+ }, [
132
+ h('h1', { class: 'atlas-title' }, props.title),
133
+ () => renderErrors(state().errors),
134
+ () => renderFields(step().kind),
135
+ () => renderSubmit(step().kind, state().busy),
136
+ ]);
137
+ }
138
+ /** The signed-in user's avatar + a menu whose only built-in action is sign-out
139
+ * — the Solid peer of Vue's `<UserButton>`. Renders nothing when signed out. */
140
+ function UserButtonView(client) {
141
+ const [open, setOpen] = createSignal(false);
142
+ const user = () => client.state.user;
143
+ const label = () => {
144
+ const u = user();
145
+ if (!u)
146
+ return '';
147
+ return [u.first_name, u.last_name].filter(Boolean).join(' ') || u.username || '';
148
+ };
149
+ return h(Show, { when: () => Boolean(user()) }, () => h('div', { class: 'atlas-user-button' }, [
150
+ h('button', {
151
+ class: 'atlas-avatar',
152
+ 'aria-expanded': () => open(),
153
+ onClick: () => setOpen(!open()),
154
+ }, () => {
155
+ const u = user();
156
+ return u?.image_url
157
+ ? h('img', { alt: '', src: u.image_url })
158
+ : h('span', () => label().slice(0, 1));
159
+ }),
160
+ () => open()
161
+ ? h('div', { class: 'atlas-menu', role: 'menu' }, [
162
+ h('span', { class: 'atlas-menu-item' }, () => label()),
163
+ h('button', { class: 'atlas-menu-item', onClick: () => void client.signOut() }, 'Sign out'),
164
+ ])
165
+ : null,
166
+ ]));
167
+ }
168
+ // --- Mount seams, called by the client's `mountX` methods. `render` returns the
169
+ // disposer that `onCleanup` later invokes to tear the nested root down. ---
170
+ export function mountSignInWidget(client, el) {
171
+ return render(() => Flow({ client, title: 'Sign in' }), el);
172
+ }
173
+ export function mountSignUpWidget(client, el) {
174
+ return render(() => Flow({ client, title: 'Sign up' }), el);
175
+ }
176
+ export function mountUserButtonWidget(client, el) {
177
+ return render(() => UserButtonView(client), el);
178
+ }
179
+ // --- The public, thin mountable components. ---
180
+ /**
181
+ * Build a component that mounts one widget. It calls the CLIENT's seam
182
+ * (`client.mountSignIn` etc.) rather than the module function directly, so the
183
+ * mounted root reaches the same client the provider built — and so the seam is a
184
+ * real, test-observable boundary. The host element is created imperatively
185
+ * (not via a reactive `ref`) so it is guaranteed present the moment `onMount`
186
+ * fires. SSR renders an empty host and hydrates on the client.
187
+ */
188
+ function mountable(seam, rootClass) {
189
+ return () => {
190
+ const client = useAtlas();
191
+ if (isServer)
192
+ return h('div', { class: rootClass });
193
+ const container = document.createElement('div');
194
+ container.className = rootClass;
195
+ onMount(() => {
196
+ // The seam drives a nested Solid root into `container`; its disposer is
197
+ // the whole teardown, so unmounting the component unmounts the widget.
198
+ const dispose = seam(client)(container);
199
+ onCleanup(dispose);
200
+ });
201
+ return container;
202
+ };
203
+ }
204
+ export const SignIn = mountable((client) => client.mountSignIn, 'atlas-signin-root');
205
+ export const SignUp = mountable((client) => client.mountSignUp, 'atlas-signup-root');
206
+ export const UserButton = mountable((client) => client.mountUserButton, 'atlas-user-button-root');
207
+ //# sourceMappingURL=widgets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgets.js","sourceRoot":"","sources":["../src/widgets.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,47 @@
1
1
  {
2
2
  "name": "@atlasauth/solid",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@atlasauth/js": "0.4.0"
15
+ },
16
+ "peerDependencies": {
17
+ "solid-js": ">=1.8"
18
+ },
19
+ "devDependencies": {
20
+ "@solidjs/testing-library": "^0.8.10",
21
+ "jsdom": "^25.0.1",
22
+ "solid-js": "^1.8.0",
23
+ "typescript": "^5.6.3",
24
+ "vitest": "^2.1.4"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "README.md"
32
+ ],
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/alphajew420/ssoly.git",
36
+ "directory": "packages/solid"
37
+ },
38
+ "homepage": "https://github.com/alphajew420/ssoly/tree/main/packages/solid#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/alphajew420/ssoly/issues"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -p tsconfig.build.json",
44
+ "typecheck": "tsc -p tsconfig.json --noEmit",
45
+ "test": "vitest run"
46
+ }
6
47
  }