@hyperyai/sdk 1.0.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.
Files changed (102) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +391 -0
  3. package/dist/components/AuthButton.d.ts +51 -0
  4. package/dist/components/AuthButton.js +60 -0
  5. package/dist/components/AuthModal.d.ts +20 -0
  6. package/dist/components/AuthModal.js +62 -0
  7. package/dist/components/BuyButton.d.ts +47 -0
  8. package/dist/components/BuyButton.js +74 -0
  9. package/dist/components/ErrorBoundary.d.ts +13 -0
  10. package/dist/components/ErrorBoundary.js +24 -0
  11. package/dist/components/HyperyModals.d.ts +30 -0
  12. package/dist/components/HyperyModals.js +30 -0
  13. package/dist/components/InsufficientCreditsAlert.d.ts +11 -0
  14. package/dist/components/InsufficientCreditsAlert.js +12 -0
  15. package/dist/components/ModernAuthForm.d.ts +52 -0
  16. package/dist/components/ModernAuthForm.js +83 -0
  17. package/dist/components/RestrictionModal.d.ts +43 -0
  18. package/dist/components/RestrictionModal.js +167 -0
  19. package/dist/components/SignIn.d.ts +26 -0
  20. package/dist/components/SignIn.js +47 -0
  21. package/dist/components/SignInForm.d.ts +41 -0
  22. package/dist/components/SignInForm.js +86 -0
  23. package/dist/components/SignUp.d.ts +26 -0
  24. package/dist/components/SignUp.js +52 -0
  25. package/dist/components/SpendingLimitAlert.d.ts +12 -0
  26. package/dist/components/SpendingLimitAlert.js +14 -0
  27. package/dist/components/UserButton.d.ts +26 -0
  28. package/dist/components/UserButton.js +35 -0
  29. package/dist/components/UserProfile.d.ts +22 -0
  30. package/dist/components/UserProfile.js +26 -0
  31. package/dist/components/WorkspaceSwitcher.d.ts +29 -0
  32. package/dist/components/WorkspaceSwitcher.js +66 -0
  33. package/dist/components/control.d.ts +64 -0
  34. package/dist/components/control.js +89 -0
  35. package/dist/components/ui/dialog.d.ts +19 -0
  36. package/dist/components/ui/dialog.js +53 -0
  37. package/dist/hooks/index.d.ts +22 -0
  38. package/dist/hooks/index.js +23 -0
  39. package/dist/hooks/useBuyerWallet.d.ts +37 -0
  40. package/dist/hooks/useBuyerWallet.js +66 -0
  41. package/dist/hooks/useCheckout.d.ts +27 -0
  42. package/dist/hooks/useCheckout.js +246 -0
  43. package/dist/hooks/useError.d.ts +19 -0
  44. package/dist/hooks/useError.js +36 -0
  45. package/dist/hooks/useMarketplace.d.ts +50 -0
  46. package/dist/hooks/useMarketplace.js +69 -0
  47. package/dist/hooks/useMemberships.d.ts +71 -0
  48. package/dist/hooks/useMemberships.js +138 -0
  49. package/dist/hooks/useWallet.d.ts +62 -0
  50. package/dist/hooks/useWallet.js +123 -0
  51. package/dist/index.d.ts +55 -0
  52. package/dist/index.js +52 -0
  53. package/dist/lib/context.d.ts +50 -0
  54. package/dist/lib/context.js +409 -0
  55. package/dist/lib/oauth.d.ts +49 -0
  56. package/dist/lib/oauth.js +149 -0
  57. package/dist/lib/parse-error.d.ts +45 -0
  58. package/dist/lib/parse-error.js +185 -0
  59. package/dist/lib/parse-stream.d.ts +43 -0
  60. package/dist/lib/parse-stream.js +89 -0
  61. package/dist/lib/popup.d.ts +42 -0
  62. package/dist/lib/popup.js +80 -0
  63. package/dist/lib/storage.d.ts +43 -0
  64. package/dist/lib/storage.js +125 -0
  65. package/dist/lib/utils.d.ts +8 -0
  66. package/dist/lib/utils.js +11 -0
  67. package/dist/types/index.d.ts +191 -0
  68. package/dist/types/index.js +4 -0
  69. package/package.json +78 -0
  70. package/src/components/AuthButton.tsx +123 -0
  71. package/src/components/AuthModal.tsx +240 -0
  72. package/src/components/BuyButton.tsx +150 -0
  73. package/src/components/ErrorBoundary.tsx +97 -0
  74. package/src/components/HyperyModals.tsx +83 -0
  75. package/src/components/InsufficientCreditsAlert.tsx +73 -0
  76. package/src/components/ModernAuthForm.tsx +322 -0
  77. package/src/components/RestrictionModal.tsx +373 -0
  78. package/src/components/SignIn.tsx +84 -0
  79. package/src/components/SignInForm.tsx +256 -0
  80. package/src/components/SignUp.tsx +86 -0
  81. package/src/components/SpendingLimitAlert.tsx +91 -0
  82. package/src/components/UserButton.tsx +106 -0
  83. package/src/components/UserProfile.tsx +106 -0
  84. package/src/components/WorkspaceSwitcher.tsx +199 -0
  85. package/src/components/control.tsx +133 -0
  86. package/src/components/ui/dialog.tsx +151 -0
  87. package/src/hooks/index.ts +65 -0
  88. package/src/hooks/useBuyerWallet.ts +117 -0
  89. package/src/hooks/useCheckout.ts +312 -0
  90. package/src/hooks/useError.ts +60 -0
  91. package/src/hooks/useMarketplace.ts +129 -0
  92. package/src/hooks/useMemberships.ts +203 -0
  93. package/src/hooks/useWallet.ts +170 -0
  94. package/src/index.ts +147 -0
  95. package/src/lib/context.tsx +478 -0
  96. package/src/lib/oauth.ts +215 -0
  97. package/src/lib/parse-error.ts +224 -0
  98. package/src/lib/parse-stream.ts +121 -0
  99. package/src/lib/popup.ts +98 -0
  100. package/src/lib/storage.ts +140 -0
  101. package/src/lib/utils.ts +14 -0
  102. package/src/types/index.ts +216 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Memberships + active-workspace hooks for consumer apps.
3
+ *
4
+ * These power the <WorkspaceSwitcher /> component. They fetch the user's
5
+ * full team → workspace tree from the gateway and let the caller switch
6
+ * the active workspace. The active workspace is stored on the OAuth
7
+ * session server-side so it's persistent across page reloads + devices.
8
+ */
9
+ export interface MembershipWorkspace {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ isDefault: boolean;
14
+ icon: string | null;
15
+ role: 'owner' | 'admin' | 'developer' | 'viewer';
16
+ isActive: boolean;
17
+ }
18
+ export interface MembershipTeam {
19
+ id: string;
20
+ name: string;
21
+ slug: string;
22
+ isPersonal: boolean;
23
+ role: 'owner' | 'admin' | 'developer' | 'viewer';
24
+ }
25
+ export interface MembershipEntry {
26
+ team: MembershipTeam;
27
+ workspaces: MembershipWorkspace[];
28
+ }
29
+ export interface MembershipsResponse {
30
+ activeOrganizationId: string | null;
31
+ activeWorkspaceId: string | null;
32
+ memberships: MembershipEntry[];
33
+ }
34
+ interface MembershipsState {
35
+ data: MembershipsResponse | null;
36
+ isLoading: boolean;
37
+ error: string | null;
38
+ reload: () => Promise<void>;
39
+ }
40
+ /**
41
+ * Hook: list every team + workspace the current user belongs to. Returns a
42
+ * flat memberships array that's easy to render in a switcher dropdown.
43
+ */
44
+ export declare function useMemberships(): MembershipsState;
45
+ export interface ActiveWorkspace {
46
+ teamId: string;
47
+ teamName: string;
48
+ workspaceId: string;
49
+ workspaceName: string;
50
+ role: 'owner' | 'admin' | 'developer' | 'viewer';
51
+ }
52
+ /**
53
+ * Hook: resolves the user's currently-active team + workspace from the
54
+ * server-side OAuth session. Returns null until memberships have loaded.
55
+ */
56
+ export declare function useActiveWorkspace(): {
57
+ active: ActiveWorkspace | null;
58
+ isLoading: boolean;
59
+ };
60
+ /**
61
+ * Mutation: persist a new active team+workspace on the OAuth session. The
62
+ * gateway updates the session record, future requests' Bearer tokens carry
63
+ * the new claims, and consumer apps see the change on their next render.
64
+ */
65
+ export declare function setActiveWorkspace(opts: {
66
+ teamId: string;
67
+ workspaceId: string;
68
+ getAccessToken: () => Promise<string | null>;
69
+ gatewayUrl?: string;
70
+ }): Promise<void>;
71
+ export {};
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Memberships + active-workspace hooks for consumer apps.
3
+ *
4
+ * These power the <WorkspaceSwitcher /> component. They fetch the user's
5
+ * full team → workspace tree from the gateway and let the caller switch
6
+ * the active workspace. The active workspace is stored on the OAuth
7
+ * session server-side so it's persistent across page reloads + devices.
8
+ */
9
+ 'use client';
10
+ import { useCallback, useEffect, useState } from 'react';
11
+ import { useHyperyAuth } from '../lib/context';
12
+ /**
13
+ * Hook: list every team + workspace the current user belongs to. Returns a
14
+ * flat memberships array that's easy to render in a switcher dropdown.
15
+ */
16
+ export function useMemberships() {
17
+ const { isAuthenticated, getAccessToken } = useHyperyAuth();
18
+ const [data, setData] = useState(null);
19
+ const [isLoading, setIsLoading] = useState(true);
20
+ const [error, setError] = useState(null);
21
+ // We can't pull the gatewayUrl off the public context value (intentionally),
22
+ // so we rely on the `Origin` header path: in practice every consumer is
23
+ // configured to point its access-token Bearer at the same gateway, so a
24
+ // simple relative fetch on the gateway's domain works. Consumer apps that
25
+ // run on a different origin override this by setting NEXT_PUBLIC_GATEWAY_URL.
26
+ const gatewayUrl = (typeof process !== 'undefined' &&
27
+ process.env?.NEXT_PUBLIC_GATEWAY_URL) ||
28
+ '';
29
+ const load = useCallback(async () => {
30
+ if (!isAuthenticated) {
31
+ setData(null);
32
+ setIsLoading(false);
33
+ return;
34
+ }
35
+ setIsLoading(true);
36
+ setError(null);
37
+ try {
38
+ const token = await getAccessToken();
39
+ if (!token) {
40
+ setData(null);
41
+ return;
42
+ }
43
+ const url = `${gatewayUrl}/api/auth/list_memberships`;
44
+ const res = await fetch(url, {
45
+ headers: { Authorization: `Bearer ${token}` },
46
+ credentials: 'include',
47
+ });
48
+ if (!res.ok) {
49
+ throw new Error(`Memberships request failed: ${res.status}`);
50
+ }
51
+ const body = (await res.json());
52
+ // Decorate isActive on each workspace from the response's pointers.
53
+ const decorated = {
54
+ ...body,
55
+ memberships: body.memberships.map((m) => ({
56
+ ...m,
57
+ workspaces: m.workspaces.map((w) => ({
58
+ ...w,
59
+ isActive: w.id === body.activeWorkspaceId,
60
+ })),
61
+ })),
62
+ };
63
+ setData(decorated);
64
+ }
65
+ catch (err) {
66
+ setError(err instanceof Error ? err.message : 'Unknown error');
67
+ }
68
+ finally {
69
+ setIsLoading(false);
70
+ }
71
+ }, [isAuthenticated, getAccessToken, gatewayUrl]);
72
+ useEffect(() => {
73
+ void load();
74
+ }, [load]);
75
+ return { data, isLoading, error, reload: load };
76
+ }
77
+ /**
78
+ * Hook: resolves the user's currently-active team + workspace from the
79
+ * server-side OAuth session. Returns null until memberships have loaded.
80
+ */
81
+ export function useActiveWorkspace() {
82
+ const { data, isLoading } = useMemberships();
83
+ if (!data)
84
+ return { active: null, isLoading };
85
+ // Prefer the explicit activeWorkspaceId pointer. Fall back to the personal
86
+ // team's default workspace so first-time users see something sensible.
87
+ const flat = data.memberships.flatMap((m) => m.workspaces.map((w) => ({ membership: m, workspace: w })));
88
+ let entry = flat.find((e) => e.workspace.id === data.activeWorkspaceId) ?? null;
89
+ if (!entry) {
90
+ const personal = data.memberships.find((m) => m.team.isPersonal);
91
+ const personalDefault = personal?.workspaces.find((w) => w.isDefault);
92
+ if (personal && personalDefault) {
93
+ entry = { membership: personal, workspace: personalDefault };
94
+ }
95
+ }
96
+ if (!entry)
97
+ return { active: null, isLoading: false };
98
+ return {
99
+ isLoading: false,
100
+ active: {
101
+ teamId: entry.membership.team.id,
102
+ teamName: entry.membership.team.name,
103
+ workspaceId: entry.workspace.id,
104
+ workspaceName: entry.workspace.name,
105
+ role: entry.workspace.role,
106
+ },
107
+ };
108
+ }
109
+ /**
110
+ * Mutation: persist a new active team+workspace on the OAuth session. The
111
+ * gateway updates the session record, future requests' Bearer tokens carry
112
+ * the new claims, and consumer apps see the change on their next render.
113
+ */
114
+ export async function setActiveWorkspace(opts) {
115
+ const token = await opts.getAccessToken();
116
+ if (!token)
117
+ throw new Error('No access token; user is not signed in');
118
+ const base = opts.gatewayUrl ??
119
+ (typeof process !== 'undefined'
120
+ ? process.env?.NEXT_PUBLIC_GATEWAY_URL ?? ''
121
+ : '');
122
+ const res = await fetch(`${base}/api/oauth/session`, {
123
+ method: 'PATCH',
124
+ headers: {
125
+ Authorization: `Bearer ${token}`,
126
+ 'Content-Type': 'application/json',
127
+ },
128
+ credentials: 'include',
129
+ body: JSON.stringify({
130
+ activeOrganizationId: opts.teamId,
131
+ activeWorkspaceId: opts.workspaceId,
132
+ }),
133
+ });
134
+ if (!res.ok) {
135
+ const detail = await res.text().catch(() => res.statusText);
136
+ throw new Error(`Failed to switch workspace: ${detail}`);
137
+ }
138
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Wallet hook for consumer apps.
3
+ *
4
+ * Reads the mode-aware wallet snapshot from the gateway (GET /api/wallet/state)
5
+ * and exposes the two funding actions the embeddable widget needs:
6
+ * - addFunds(usd) → 1-click off-session charge of the card on file
7
+ * - addPaymentMethod() → Stripe-hosted Checkout (setup) in a popup
8
+ *
9
+ * Works in both billing modes; the widget chooses which action to show from
10
+ * `wallet.mode` and `wallet.paymentMethod.exists`.
11
+ */
12
+ export type BillingMode = 'metered' | 'prepaid';
13
+ export interface WalletTier {
14
+ name: string;
15
+ usdAmount: number;
16
+ credits: number;
17
+ bonus: number;
18
+ popular?: boolean;
19
+ }
20
+ export interface WalletState {
21
+ mode: BillingMode;
22
+ balance: {
23
+ current: number;
24
+ reserved: number;
25
+ monthlySpent: number;
26
+ monthlyLimit: number;
27
+ };
28
+ paymentMethod: {
29
+ exists: boolean;
30
+ last4?: string;
31
+ brand?: string;
32
+ };
33
+ autoTopUp: {
34
+ enabled: boolean;
35
+ threshold?: number;
36
+ amount?: number;
37
+ };
38
+ lowBalance: {
39
+ isLow: boolean;
40
+ threshold: number;
41
+ current: number;
42
+ };
43
+ topupTiers: WalletTier[];
44
+ settingsUrls: {
45
+ billing: string;
46
+ topup: string;
47
+ addPaymentMethod: string;
48
+ };
49
+ }
50
+ export interface UseWalletReturn {
51
+ wallet: WalletState | null;
52
+ isLoading: boolean;
53
+ error: string | null;
54
+ reload: () => Promise<void>;
55
+ /** 1-click: charge the card on file for `usd` dollars and credit the team. */
56
+ addFunds: (usd: number) => Promise<void>;
57
+ /** Open Stripe-hosted Checkout to add a card; resolves true once added. */
58
+ addPaymentMethod: () => Promise<boolean>;
59
+ }
60
+ export declare function useWallet(opts?: {
61
+ gatewayUrl?: string;
62
+ }): UseWalletReturn;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Wallet hook for consumer apps.
3
+ *
4
+ * Reads the mode-aware wallet snapshot from the gateway (GET /api/wallet/state)
5
+ * and exposes the two funding actions the embeddable widget needs:
6
+ * - addFunds(usd) → 1-click off-session charge of the card on file
7
+ * - addPaymentMethod() → Stripe-hosted Checkout (setup) in a popup
8
+ *
9
+ * Works in both billing modes; the widget chooses which action to show from
10
+ * `wallet.mode` and `wallet.paymentMethod.exists`.
11
+ */
12
+ 'use client';
13
+ import { useCallback, useEffect, useState } from 'react';
14
+ import { useHyperyAuth } from '../lib/context';
15
+ function resolveGatewayUrl(explicit) {
16
+ return (explicit ||
17
+ (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_GATEWAY_URL) ||
18
+ '');
19
+ }
20
+ export function useWallet(opts = {}) {
21
+ const { isAuthenticated, getAccessToken } = useHyperyAuth();
22
+ const gatewayUrl = resolveGatewayUrl(opts.gatewayUrl);
23
+ const [wallet, setWallet] = useState(null);
24
+ const [isLoading, setIsLoading] = useState(true);
25
+ const [error, setError] = useState(null);
26
+ const reload = useCallback(async () => {
27
+ if (!isAuthenticated) {
28
+ setWallet(null);
29
+ setIsLoading(false);
30
+ return;
31
+ }
32
+ setIsLoading(true);
33
+ setError(null);
34
+ try {
35
+ const token = await getAccessToken();
36
+ if (!token) {
37
+ setWallet(null);
38
+ return;
39
+ }
40
+ const res = await fetch(`${gatewayUrl}/api/wallet/state`, {
41
+ headers: { Authorization: `Bearer ${token}` },
42
+ });
43
+ if (!res.ok)
44
+ throw new Error(`Wallet state request failed: ${res.status}`);
45
+ const body = (await res.json());
46
+ setWallet(body);
47
+ }
48
+ catch (err) {
49
+ setError(err instanceof Error ? err.message : 'Unknown error');
50
+ }
51
+ finally {
52
+ setIsLoading(false);
53
+ }
54
+ }, [isAuthenticated, getAccessToken, gatewayUrl]);
55
+ useEffect(() => {
56
+ void reload();
57
+ }, [reload]);
58
+ const addFunds = useCallback(async (usd) => {
59
+ const token = await getAccessToken();
60
+ if (!token)
61
+ throw new Error('Not authenticated');
62
+ const res = await fetch(`${gatewayUrl}/api/wallet/topup`, {
63
+ method: 'POST',
64
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({ amount: usd }),
66
+ });
67
+ const body = await res.json().catch(() => ({}));
68
+ if (!res.ok || !body?.success) {
69
+ throw new Error(body?.error || `Top-up failed: ${res.status}`);
70
+ }
71
+ await reload();
72
+ }, [getAccessToken, gatewayUrl, reload]);
73
+ const addPaymentMethod = useCallback(async () => {
74
+ const token = await getAccessToken();
75
+ if (!token)
76
+ throw new Error('Not authenticated');
77
+ const res = await fetch(`${gatewayUrl}/api/payments/stripe/checkout-setup`, {
78
+ method: 'POST',
79
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
80
+ body: JSON.stringify({}),
81
+ });
82
+ const body = await res.json().catch(() => ({}));
83
+ if (!res.ok || !body?.url) {
84
+ throw new Error(body?.error || `Could not start checkout: ${res.status}`);
85
+ }
86
+ const popup = typeof window !== 'undefined'
87
+ ? window.open(body.url, 'hypery-add-card', 'width=480,height=720')
88
+ : null;
89
+ // Resolve when the hosted-Checkout return page messages us, or when the
90
+ // popup closes (fall back to a state reload to detect the new card).
91
+ return new Promise((resolve) => {
92
+ let settled = false;
93
+ const finish = async (added) => {
94
+ if (settled)
95
+ return;
96
+ settled = true;
97
+ window.removeEventListener('message', onMessage);
98
+ clearInterval(poll);
99
+ await reload();
100
+ resolve(added);
101
+ };
102
+ // Only trust the completion message from the gateway's own origin.
103
+ const expectedOrigin = gatewayUrl
104
+ ? new URL(gatewayUrl).origin
105
+ : typeof window !== 'undefined'
106
+ ? window.location.origin
107
+ : '';
108
+ const onMessage = (event) => {
109
+ if (event.origin !== expectedOrigin)
110
+ return;
111
+ if (event?.data?.type === 'hypery:payment-method') {
112
+ void finish(event.data.status === 'added');
113
+ }
114
+ };
115
+ window.addEventListener('message', onMessage);
116
+ const poll = setInterval(() => {
117
+ if (popup && popup.closed)
118
+ void finish(false);
119
+ }, 700);
120
+ });
121
+ }, [getAccessToken, gatewayUrl, reload]);
122
+ return { wallet, isLoading, error, reload, addFunds, addPaymentMethod };
123
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @hyperyai/sdk
3
+ * Drop-in authentication and error handling library for Hypery apps
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * import { HyperyProvider, useUser, SignedIn, SignedOut } from '@hyperyai/sdk';
8
+ *
9
+ * <HyperyProvider config={{ ... }}>
10
+ * <SignedIn>
11
+ * <App />
12
+ * </SignedIn>
13
+ * <SignedOut>
14
+ * <SignIn />
15
+ * </SignedOut>
16
+ * </HyperyProvider>
17
+ * ```
18
+ */
19
+ export { HyperyProvider, useHyperyAuth, useUser } from './lib/context';
20
+ export { useAuth, useMemberships, useActiveWorkspace, setActiveWorkspace, useWallet, useBuyerWallet, useMarketplace, useCheckout, } from './hooks';
21
+ export type { MembershipEntry, MembershipTeam, MembershipWorkspace, MembershipsResponse, ActiveWorkspace, BillingMode, WalletState, WalletTier, UseWalletReturn, BuyerPaymentMethod, AddCardOptions, UseBuyerWalletReturn, BuyInput, BuySuccess, BuyFailure, BuyResult, UseMarketplaceReturn, CheckoutInput, CheckoutStatus, CheckoutResult, UseCheckoutReturn, } from './hooks';
22
+ export { SignIn } from './components/SignIn';
23
+ export { SignUp } from './components/SignUp';
24
+ export { SignInForm } from './components/SignInForm';
25
+ export { UserButton } from './components/UserButton';
26
+ export { UserProfile } from './components/UserProfile';
27
+ export { SignedIn, SignedOut, RedirectToSignIn, Protect } from './components/control';
28
+ export { AuthModal } from './components/AuthModal';
29
+ export type { AuthModalProps } from './components/AuthModal';
30
+ export { AuthButton } from './components/AuthButton';
31
+ export type { AuthButtonProps } from './components/AuthButton';
32
+ export { ModernAuthForm } from './components/ModernAuthForm';
33
+ export type { ModernAuthFormProps } from './components/ModernAuthForm';
34
+ export { WorkspaceSwitcher } from './components/WorkspaceSwitcher';
35
+ export type { WorkspaceSwitcherProps } from './components/WorkspaceSwitcher';
36
+ export { BuyButton } from './components/BuyButton';
37
+ export type { BuyButtonProps } from './components/BuyButton';
38
+ export { RestrictionModal } from './components/RestrictionModal';
39
+ export type { RestrictionError } from './components/RestrictionModal';
40
+ export { HyperyModals } from './components/HyperyModals';
41
+ export type { HyperyModalsProps } from './components/HyperyModals';
42
+ export { SpendingLimitAlert } from './components/SpendingLimitAlert';
43
+ export type { SpendingLimitAlertProps } from './components/SpendingLimitAlert';
44
+ export { InsufficientCreditsAlert } from './components/InsufficientCreditsAlert';
45
+ export type { InsufficientCreditsAlertProps } from './components/InsufficientCreditsAlert';
46
+ export { ErrorBoundary } from './components/ErrorBoundary';
47
+ export type { ErrorBoundaryProps } from './components/ErrorBoundary';
48
+ export { useError } from './hooks/useError';
49
+ export type { UseErrorReturn } from './hooks/useError';
50
+ export type { BrandingConfig, HyperyAuthConfig, InteractionMode, ResolvedMode, PopupAuthResult, User, AuthTokens, AuthState, AuthContextValue, SpendingLimitErrorData, InsufficientCreditsErrorData, PaymentMethodRequiredErrorData, PaymentDeclinedErrorData, AuthenticationErrorData, GenericErrorData, ErrorData, ErrorResponse, ParsedError, } from './types';
51
+ export { TokenStorage } from './lib/storage';
52
+ export { getAuthorizationUrl, exchangeCodeForToken, refreshAccessToken, getUserInfo, } from './lib/oauth';
53
+ export { parseError, isSpendingLimitError, isInsufficientCreditsError, isPaymentMethodRequiredError, isPaymentDeclinedError, isAuthError, isPermissionDeniedError, isRateLimitError, isBillingRestriction, formatTimeUntilReset, } from './lib/parse-error';
54
+ export { parseSSEError, parseSSEFrame, consumeSSEStream } from './lib/parse-stream';
55
+ export type { SSEEvent, SSEStreamHandlers } from './lib/parse-stream';
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @hyperyai/sdk
3
+ * Drop-in authentication and error handling library for Hypery apps
4
+ *
5
+ * @example
6
+ * ```tsx
7
+ * import { HyperyProvider, useUser, SignedIn, SignedOut } from '@hyperyai/sdk';
8
+ *
9
+ * <HyperyProvider config={{ ... }}>
10
+ * <SignedIn>
11
+ * <App />
12
+ * </SignedIn>
13
+ * <SignedOut>
14
+ * <SignIn />
15
+ * </SignedOut>
16
+ * </HyperyProvider>
17
+ * ```
18
+ */
19
+ // Provider & Hooks
20
+ export { HyperyProvider, useHyperyAuth, useUser } from './lib/context';
21
+ export { useAuth, useMemberships, useActiveWorkspace, setActiveWorkspace, useWallet, useBuyerWallet, useMarketplace, useCheckout, } from './hooks';
22
+ // Auth Components
23
+ export { SignIn } from './components/SignIn';
24
+ export { SignUp } from './components/SignUp';
25
+ export { SignInForm } from './components/SignInForm';
26
+ export { UserButton } from './components/UserButton';
27
+ export { UserProfile } from './components/UserProfile';
28
+ export { SignedIn, SignedOut, RedirectToSignIn, Protect } from './components/control';
29
+ export { AuthModal } from './components/AuthModal';
30
+ export { AuthButton } from './components/AuthButton';
31
+ export { ModernAuthForm } from './components/ModernAuthForm';
32
+ export { WorkspaceSwitcher } from './components/WorkspaceSwitcher';
33
+ // "Buy with Hypery" marketplace checkout button.
34
+ export { BuyButton } from './components/BuyButton';
35
+ // Error Components
36
+ export { RestrictionModal } from './components/RestrictionModal';
37
+ // Turnkey modal host — mount once for automatic billing/auth modals driven by
38
+ // authenticatedFetch (issue #42).
39
+ export { HyperyModals } from './components/HyperyModals';
40
+ export { SpendingLimitAlert } from './components/SpendingLimitAlert';
41
+ export { InsufficientCreditsAlert } from './components/InsufficientCreditsAlert';
42
+ export { ErrorBoundary } from './components/ErrorBoundary';
43
+ // Error Hook
44
+ export { useError } from './hooks/useError';
45
+ // Utilities (for advanced usage)
46
+ export { TokenStorage } from './lib/storage';
47
+ export { getAuthorizationUrl, exchangeCodeForToken, refreshAccessToken, getUserInfo, } from './lib/oauth';
48
+ // Error Utilities
49
+ export { parseError, isSpendingLimitError, isInsufficientCreditsError, isPaymentMethodRequiredError, isPaymentDeclinedError, isAuthError, isPermissionDeniedError, isRateLimitError, isBillingRestriction, formatTimeUntilReset, } from './lib/parse-error';
50
+ // Streaming (SSE) error classification — surface a terminal mid-stream error in
51
+ // the same classified shape as a non-streaming failure (issue #44).
52
+ export { parseSSEError, parseSSEFrame, consumeSSEStream } from './lib/parse-stream';
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Hypery Auth Context
3
+ * Similar to Clerk's <ClerkProvider>
4
+ */
5
+ import React, { type ReactNode } from 'react';
6
+ import type { HyperyAuthConfig, AuthContextValue, User } from '../types';
7
+ export interface HyperyProviderProps {
8
+ config: HyperyAuthConfig;
9
+ children: ReactNode;
10
+ }
11
+ /**
12
+ * Hypery Auth Provider
13
+ * Wrap your app with this component to enable authentication
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <HyperyProvider config={{
18
+ * clientId: 'your-client-id',
19
+ * redirectUri: 'http://localhost:3000/callback',
20
+ * gatewayUrl: 'https://api.hypery.ai',
21
+ * scopes: ['read', 'write', 'ai:chat']
22
+ * }}>
23
+ * <App />
24
+ * </HyperyProvider>
25
+ * ```
26
+ */
27
+ export declare function HyperyProvider({ config, children, }: HyperyProviderProps): React.JSX.Element;
28
+ /**
29
+ * Hook to access auth state and methods
30
+ * Similar to Clerk's useAuth()
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const { user, isAuthenticated, login, logout } = useHyperyAuth();
35
+ * ```
36
+ */
37
+ export declare function useHyperyAuth(): AuthContextValue;
38
+ /**
39
+ * Hook to access user data
40
+ * Similar to Clerk's useUser()
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * const { user, isLoading } = useUser();
45
+ * ```
46
+ */
47
+ export declare function useUser(): {
48
+ user: User | null;
49
+ isLoading: boolean;
50
+ };