@sigma-auth/better-auth-plugin 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.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # sigma-auth-better-auth-plugin
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.3.0. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,59 @@
1
+ import type { BetterFetchOption } from "@better-fetch/fetch";
2
+ import type { OAuthCallbackResult, SubscriptionStatus } from "../types/index.js";
3
+ export type { OAuthCallbackError, OAuthCallbackResult, SubscriptionStatus, } from "../types/index.js";
4
+ /**
5
+ * Options for Sigma sign-in
6
+ */
7
+ export interface SigmaSignInOptions {
8
+ authToken?: string;
9
+ bapId?: string;
10
+ callbackURL?: string;
11
+ errorCallbackURL?: string;
12
+ provider?: string;
13
+ clientId?: string;
14
+ disableRedirect?: boolean;
15
+ }
16
+ /**
17
+ * Sigma Auth client plugin for Better Auth
18
+ * Provides browser-side OAuth flow with PKCE
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import { createAuthClient } from "better-auth/client";
23
+ * import { sigmaClient } from "@sigma-auth/better-auth-plugin/client";
24
+ *
25
+ * export const authClient = createAuthClient({
26
+ * baseURL: "https://auth.sigmaidentity.com",
27
+ * plugins: [sigmaClient()],
28
+ * });
29
+ *
30
+ * // Sign in with Sigma
31
+ * authClient.signIn.sigma({
32
+ * clientId: "your-app",
33
+ * callbackURL: "/callback",
34
+ * });
35
+ * ```
36
+ */
37
+ export declare const sigmaClient: () => {
38
+ id: "sigma";
39
+ getActions: ($fetch: import("@better-fetch/fetch").BetterFetch) => {
40
+ subscription: {
41
+ getStatus: () => Promise<SubscriptionStatus>;
42
+ };
43
+ signIn: {
44
+ sigma: (options?: SigmaSignInOptions, fetchOptions?: BetterFetchOption) => Promise<unknown>;
45
+ };
46
+ sigma: {
47
+ /**
48
+ * Handle OAuth callback after redirect from auth server
49
+ * Verifies state, exchanges code for tokens, and returns user data
50
+ *
51
+ * @param searchParams - URL search params from callback (code, state, error)
52
+ * @returns Promise resolving to user data and tokens
53
+ * @throws OAuthCallbackError if callback fails
54
+ */
55
+ handleCallback: (searchParams: URLSearchParams) => Promise<OAuthCallbackResult>;
56
+ };
57
+ };
58
+ };
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAEX,mBAAmB,EACnB,kBAAkB,EAClB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EACX,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAsBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,WAAW;;;;6BAOE,OAAO,CAAC,kBAAkB,CAAC;;;8BAiBrC,kBAAkB,iBACb,iBAAiB;;;YAwEjC;;;;;;;eAOG;2CAEY,eAAe,KAC3B,OAAO,CAAC,mBAAmB,CAAC;;;CAsJnC,CAAC"}
@@ -0,0 +1,246 @@
1
+ // PKCE helper functions
2
+ const generateCodeVerifier = () => {
3
+ const array = new Uint8Array(32);
4
+ crypto.getRandomValues(array);
5
+ return btoa(String.fromCharCode(...array))
6
+ .replace(/\+/g, "-")
7
+ .replace(/\//g, "_")
8
+ .replace(/=/g, "");
9
+ };
10
+ const generateCodeChallenge = async (verifier) => {
11
+ const encoder = new TextEncoder();
12
+ const data = encoder.encode(verifier);
13
+ const hash = await crypto.subtle.digest("SHA-256", data);
14
+ return btoa(String.fromCharCode(...new Uint8Array(hash)))
15
+ .replace(/\+/g, "-")
16
+ .replace(/\//g, "_")
17
+ .replace(/=/g, "");
18
+ };
19
+ /**
20
+ * Sigma Auth client plugin for Better Auth
21
+ * Provides browser-side OAuth flow with PKCE
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { createAuthClient } from "better-auth/client";
26
+ * import { sigmaClient } from "@sigma-auth/better-auth-plugin/client";
27
+ *
28
+ * export const authClient = createAuthClient({
29
+ * baseURL: "https://auth.sigmaidentity.com",
30
+ * plugins: [sigmaClient()],
31
+ * });
32
+ *
33
+ * // Sign in with Sigma
34
+ * authClient.signIn.sigma({
35
+ * clientId: "your-app",
36
+ * callbackURL: "/callback",
37
+ * });
38
+ * ```
39
+ */
40
+ export const sigmaClient = () => {
41
+ return {
42
+ id: "sigma",
43
+ getActions: ($fetch) => {
44
+ return {
45
+ subscription: {
46
+ getStatus: async () => {
47
+ const res = await $fetch("/subscription/status", {
48
+ method: "GET",
49
+ });
50
+ if (res.error) {
51
+ throw new Error(res.error.message || "Failed to fetch subscription status");
52
+ }
53
+ return res.data;
54
+ },
55
+ },
56
+ signIn: {
57
+ sigma: async (options, fetchOptions) => {
58
+ // Two modes:
59
+ // 1. With authToken: Call local endpoint (for auth server login)
60
+ // 2. Without authToken: OAuth redirect (for external clients)
61
+ if (options?.authToken) {
62
+ // Auth server local sign-in - call endpoint with authToken
63
+ const res = await $fetch("/sign-in/sigma", {
64
+ method: "POST",
65
+ body: {},
66
+ headers: {
67
+ "X-Auth-Token": options.authToken,
68
+ },
69
+ ...fetchOptions,
70
+ });
71
+ return res;
72
+ }
73
+ // External OAuth client - redirect to auth server
74
+ const state = Math.random().toString(36).substring(7);
75
+ // Generate PKCE parameters for public clients
76
+ const codeVerifier = generateCodeVerifier();
77
+ const codeChallenge = await generateCodeChallenge(codeVerifier);
78
+ if (typeof window !== "undefined") {
79
+ sessionStorage.setItem("sigma_oauth_state", state);
80
+ sessionStorage.setItem("sigma_code_verifier", codeVerifier);
81
+ }
82
+ const authUrl = typeof process !== "undefined"
83
+ ? process.env.NEXT_PUBLIC_SIGMA_AUTH_URL ||
84
+ "https://auth.sigmaidentity.com"
85
+ : "https://auth.sigmaidentity.com";
86
+ // Ensure redirect_uri is always absolute (OAuth requires absolute URLs)
87
+ const origin = typeof window !== "undefined" ? window.location.origin : "";
88
+ const callbackPath = options?.callbackURL || "/callback";
89
+ const redirectUri = callbackPath.startsWith("http")
90
+ ? callbackPath
91
+ : `${origin}${callbackPath.startsWith("/") ? callbackPath : `/${callbackPath}`}`;
92
+ const params = new URLSearchParams({
93
+ redirect_uri: redirectUri,
94
+ response_type: "code",
95
+ state,
96
+ scope: "openid profile bsv:tools",
97
+ code_challenge: codeChallenge,
98
+ code_challenge_method: "S256",
99
+ });
100
+ if (options?.clientId) {
101
+ params.append("client_id", options.clientId);
102
+ }
103
+ if (options?.provider) {
104
+ params.append("provider", options.provider);
105
+ }
106
+ // Use custom authorize endpoint that checks wallet unlock before proceeding
107
+ const fullAuthUrl = `${authUrl}/oauth2/authorize?${params.toString()}`;
108
+ if (typeof window !== "undefined") {
109
+ window.location.href = fullAuthUrl;
110
+ }
111
+ return new Promise(() => { });
112
+ },
113
+ },
114
+ sigma: {
115
+ /**
116
+ * Handle OAuth callback after redirect from auth server
117
+ * Verifies state, exchanges code for tokens, and returns user data
118
+ *
119
+ * @param searchParams - URL search params from callback (code, state, error)
120
+ * @returns Promise resolving to user data and tokens
121
+ * @throws OAuthCallbackError if callback fails
122
+ */
123
+ handleCallback: async (searchParams) => {
124
+ // Check for OAuth error
125
+ const error = searchParams.get("error");
126
+ if (error) {
127
+ const errorDescription = searchParams.get("error_description");
128
+ throw {
129
+ title: "Authentication Error",
130
+ message: errorDescription ||
131
+ error ||
132
+ "An unknown error occurred during authentication.",
133
+ };
134
+ }
135
+ // Check for authorization code
136
+ const code = searchParams.get("code");
137
+ const state = searchParams.get("state");
138
+ if (!code) {
139
+ throw {
140
+ title: "Missing Authorization Code",
141
+ message: "The authorization code was not received from the authentication server.",
142
+ };
143
+ }
144
+ // Verify state for CSRF protection
145
+ const savedState = typeof window !== "undefined"
146
+ ? sessionStorage.getItem("sigma_oauth_state")
147
+ : null;
148
+ if (state !== savedState) {
149
+ // Clear invalid state
150
+ if (typeof window !== "undefined") {
151
+ sessionStorage.removeItem("sigma_oauth_state");
152
+ }
153
+ throw {
154
+ title: "Security Error",
155
+ message: "Invalid state parameter. Please try signing in again.",
156
+ };
157
+ }
158
+ // Clear state after successful verification
159
+ if (typeof window !== "undefined") {
160
+ sessionStorage.removeItem("sigma_oauth_state");
161
+ }
162
+ // Get PKCE verifier
163
+ const codeVerifier = typeof window !== "undefined"
164
+ ? sessionStorage.getItem("sigma_code_verifier") || undefined
165
+ : undefined;
166
+ // Exchange code for tokens via backend API
167
+ // This must be done server-side because it requires bitcoin-auth signature
168
+ try {
169
+ const response = await fetch("/api/auth/callback", {
170
+ method: "POST",
171
+ headers: {
172
+ "Content-Type": "application/json",
173
+ },
174
+ body: JSON.stringify({
175
+ code,
176
+ state,
177
+ code_verifier: codeVerifier,
178
+ }),
179
+ });
180
+ if (!response.ok) {
181
+ let errorMessage = "Failed to exchange authorization code for access token.";
182
+ let errorTitle = "Token Exchange Failed";
183
+ try {
184
+ const errorData = (await response.json());
185
+ const endpoint = errorData.endpoint || "unknown";
186
+ const status = errorData.status || response.status;
187
+ // Parse nested error details if present
188
+ if (errorData.details) {
189
+ try {
190
+ const nestedError = JSON.parse(errorData.details);
191
+ if (nestedError.error_description) {
192
+ errorMessage = nestedError.error_description;
193
+ }
194
+ if (nestedError.error === "invalid_client") {
195
+ errorTitle = "Platform Not Registered";
196
+ errorMessage =
197
+ "This platform is not registered with the authentication server.";
198
+ }
199
+ }
200
+ catch {
201
+ errorMessage = errorData.details;
202
+ }
203
+ }
204
+ else if (errorData.error) {
205
+ errorMessage = errorData.error;
206
+ }
207
+ errorMessage += `\n\nBackend: ${status} (${endpoint})`;
208
+ }
209
+ catch {
210
+ // Use default error message
211
+ }
212
+ throw {
213
+ title: errorTitle,
214
+ message: errorMessage,
215
+ };
216
+ }
217
+ const data = (await response.json());
218
+ return {
219
+ user: data.user,
220
+ access_token: data.access_token,
221
+ refresh_token: data.refresh_token,
222
+ };
223
+ }
224
+ catch (err) {
225
+ // If already an OAuthCallbackError, rethrow
226
+ if (typeof err === "object" &&
227
+ err !== null &&
228
+ "title" in err &&
229
+ "message" in err) {
230
+ throw err;
231
+ }
232
+ // Otherwise wrap in error object
233
+ throw {
234
+ title: "Authentication Failed",
235
+ message: err instanceof Error
236
+ ? err.message
237
+ : "An unknown error occurred.",
238
+ };
239
+ }
240
+ },
241
+ },
242
+ };
243
+ },
244
+ };
245
+ };
246
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Next.js App Router integration for Sigma Auth
3
+ * Provides ready-to-use route handlers for OAuth callback
4
+ */
5
+ interface NextRequest {
6
+ json(): Promise<unknown>;
7
+ nextUrl: {
8
+ origin: string;
9
+ };
10
+ }
11
+ /**
12
+ * Configuration for the callback route handler
13
+ * All values can be set via environment variables
14
+ */
15
+ export interface CallbackRouteConfig {
16
+ /** Sigma Auth server URL (default: NEXT_PUBLIC_SIGMA_AUTH_URL or https://auth.sigmaidentity.com) */
17
+ issuerUrl?: string;
18
+ /** OAuth client ID (default: NEXT_PUBLIC_SIGMA_CLIENT_ID) */
19
+ clientId?: string;
20
+ /** Member private key for signing (default: SIGMA_MEMBER_PRIVATE_KEY env) */
21
+ memberPrivateKey?: string;
22
+ /** Callback path (default: /callback) */
23
+ callbackPath?: string;
24
+ }
25
+ /**
26
+ * Creates a Next.js POST route handler for OAuth callback
27
+ * This handler exchanges the authorization code for tokens using bitcoin-auth signature
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // app/api/auth/callback/route.ts
32
+ * import { createCallbackHandler } from "@sigma-auth/better-auth-plugin/next";
33
+ *
34
+ * export const runtime = "nodejs";
35
+ * export const POST = createCallbackHandler();
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // With custom config
41
+ * import { createCallbackHandler } from "@sigma-auth/better-auth-plugin/next";
42
+ *
43
+ * export const runtime = "nodejs";
44
+ * export const POST = createCallbackHandler({
45
+ * callbackPath: "/auth/callback"
46
+ * });
47
+ * ```
48
+ */
49
+ export declare function createCallbackHandler(config?: CallbackRouteConfig): (request: NextRequest) => Promise<Response>;
50
+ /**
51
+ * Runtime configuration for Next.js route
52
+ * Set to nodejs to support bitcoin-auth cryptography
53
+ */
54
+ export declare const runtime = "nodejs";
55
+ export {};
56
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,UAAU,WAAW;IACpB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;KACf,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,mBAAmB,IACnD,SAAS,WAAW,uBA4GlC;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,WAAW,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Next.js App Router integration for Sigma Auth
3
+ * Provides ready-to-use route handlers for OAuth callback
4
+ */
5
+ import { exchangeCodeForTokens, } from "../server/index.js";
6
+ /**
7
+ * Creates a Next.js POST route handler for OAuth callback
8
+ * This handler exchanges the authorization code for tokens using bitcoin-auth signature
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // app/api/auth/callback/route.ts
13
+ * import { createCallbackHandler } from "@sigma-auth/better-auth-plugin/next";
14
+ *
15
+ * export const runtime = "nodejs";
16
+ * export const POST = createCallbackHandler();
17
+ * ```
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // With custom config
22
+ * import { createCallbackHandler } from "@sigma-auth/better-auth-plugin/next";
23
+ *
24
+ * export const runtime = "nodejs";
25
+ * export const POST = createCallbackHandler({
26
+ * callbackPath: "/auth/callback"
27
+ * });
28
+ * ```
29
+ */
30
+ export function createCallbackHandler(config) {
31
+ return async (request) => {
32
+ try {
33
+ const body = (await request.json());
34
+ const { code, code_verifier } = body;
35
+ if (!code) {
36
+ return Response.json({ error: "Missing authorization code" }, { status: 400 });
37
+ }
38
+ // Get configuration from env or config
39
+ const memberPrivateKey = config?.memberPrivateKey || process.env.SIGMA_MEMBER_PRIVATE_KEY;
40
+ if (!memberPrivateKey) {
41
+ console.error("[Sigma OAuth Callback] SIGMA_MEMBER_PRIVATE_KEY not configured");
42
+ return Response.json({
43
+ error: "Server configuration error",
44
+ details: "Missing SIGMA_MEMBER_PRIVATE_KEY",
45
+ }, { status: 500 });
46
+ }
47
+ const issuerUrl = config?.issuerUrl ||
48
+ process.env.NEXT_PUBLIC_SIGMA_AUTH_URL ||
49
+ "https://auth.sigmaidentity.com";
50
+ const clientId = config?.clientId || process.env.NEXT_PUBLIC_SIGMA_CLIENT_ID;
51
+ if (!clientId) {
52
+ console.error("[Sigma OAuth Callback] NEXT_PUBLIC_SIGMA_CLIENT_ID not configured");
53
+ return Response.json({ error: "Server configuration error", details: "Missing client ID" }, { status: 500 });
54
+ }
55
+ const callbackPath = config?.callbackPath || "/callback";
56
+ const redirectUri = `${request.nextUrl.origin}${callbackPath}`;
57
+ console.log("[Sigma OAuth Callback] Exchanging code for tokens:", {
58
+ issuerUrl,
59
+ clientId,
60
+ redirectUri,
61
+ });
62
+ const result = await exchangeCodeForTokens({
63
+ code,
64
+ redirectUri,
65
+ clientId,
66
+ memberPrivateKey,
67
+ codeVerifier: code_verifier,
68
+ issuerUrl,
69
+ });
70
+ console.log("[Sigma OAuth Callback] Success:", {
71
+ hasBap: !!result.user.bap,
72
+ name: result.user.name,
73
+ bapId: result.user.bap?.idKey?.substring(0, 20) || "none",
74
+ });
75
+ return Response.json({
76
+ user: result.user,
77
+ access_token: result.access_token,
78
+ refresh_token: result.refresh_token,
79
+ });
80
+ }
81
+ catch (error) {
82
+ console.error("[Sigma OAuth Callback] Error:", error);
83
+ // Check if it's a TokenExchangeError
84
+ if (error &&
85
+ typeof error === "object" &&
86
+ "error" in error &&
87
+ "endpoint" in error) {
88
+ const tokenError = error;
89
+ return Response.json({
90
+ error: tokenError.error,
91
+ details: tokenError.details,
92
+ status: tokenError.status,
93
+ endpoint: tokenError.endpoint,
94
+ }, { status: tokenError.status || 500 });
95
+ }
96
+ return Response.json({
97
+ error: "Internal server error",
98
+ details: error instanceof Error ? error.message : "Unknown error",
99
+ }, { status: 500 });
100
+ }
101
+ };
102
+ }
103
+ /**
104
+ * Runtime configuration for Next.js route
105
+ * Set to nodejs to support bitcoin-auth cryptography
106
+ */
107
+ export const runtime = "nodejs";
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { Pool } from "@neondatabase/serverless";
2
+ import type { BetterAuthPlugin } from "better-auth";
3
+ /**
4
+ * Configuration options for the Sigma Auth provider plugin
5
+ */
6
+ export interface SigmaProviderOptions {
7
+ /**
8
+ * Optional BAP (Bitcoin Attestation Protocol) ID resolver
9
+ * Resolves a Bitcoin pubkey to a BAP ID and registers it
10
+ * @param pool Database connection pool (implementation-specific)
11
+ * @param userId User ID in your database
12
+ * @param pubkey Bitcoin public key
13
+ * @param register Whether to register the BAP ID
14
+ * @returns BAP ID or null if not found
15
+ */
16
+ resolveBAPId?: (pool: Pool, userId: string, pubkey: string, register: boolean) => Promise<string | null>;
17
+ /**
18
+ * Optional database pool getter
19
+ * Returns a database connection pool for BAP ID resolution
20
+ */
21
+ getPool?: () => Pool;
22
+ /**
23
+ * Optional cache implementation for BAP ID caching and OAuth consent state
24
+ * Should provide get/set/delete methods for key-value storage
25
+ * The set method should accept an optional options object for TTL configuration
26
+ */
27
+ cache?: {
28
+ get: <T = unknown>(key: string) => Promise<T | null>;
29
+ set: (key: string, value: unknown, options?: {
30
+ ex?: number;
31
+ }) => Promise<void>;
32
+ delete?: (key: string) => Promise<void>;
33
+ };
34
+ /**
35
+ * Enable subscription tier support
36
+ * Adds subscriptionTier field to user and session
37
+ * @default false
38
+ */
39
+ enableSubscription?: boolean;
40
+ }
41
+ /**
42
+ * Sigma Auth provider plugin for Better Auth
43
+ * This is the OAuth provider that runs on auth.sigmaidentity.com
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * import { betterAuth } from "better-auth";
48
+ * import { sigmaProvider } from "@sigma-auth/better-auth-plugin/provider";
49
+ *
50
+ * export const auth = betterAuth({
51
+ * plugins: [
52
+ * sigmaProvider({
53
+ * getPool: () => dbPool,
54
+ * cache: redisCache,
55
+ * resolveBAPId: async (pool, userId, pubkey, register) => {
56
+ * // Custom BAP ID resolution logic
57
+ * },
58
+ * }),
59
+ * ],
60
+ * });
61
+ * ```
62
+ */
63
+ export declare const sigmaProvider: (options?: SigmaProviderOptions) => BetterAuthPlugin;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/provider/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAQ,MAAM,aAAa,CAAC;AAoB1D;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,KACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QACP,GAAG,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACrD,GAAG,EAAE,CACJ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAA;SAAE,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACxC,CAAC;IAEF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,aAAa,GACzB,UAAU,oBAAoB,KAC5B,gBA25BD,CAAC"}