@buildspacestudio/sdk 0.3.0 → 0.4.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 (54) hide show
  1. package/README.md +126 -0
  2. package/dist/auth/index.cjs.map +1 -1
  3. package/dist/auth/index.d.cts +3 -118
  4. package/dist/auth/index.d.ts +3 -118
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/billing/index.cjs +226 -0
  7. package/dist/billing/index.cjs.map +1 -0
  8. package/dist/billing/index.d.cts +60 -0
  9. package/dist/billing/index.d.ts +60 -0
  10. package/dist/billing/index.js +222 -0
  11. package/dist/billing/index.js.map +1 -0
  12. package/dist/client/index.cjs +130 -0
  13. package/dist/client/index.cjs.map +1 -1
  14. package/dist/client/index.d.cts +7 -3
  15. package/dist/client/index.d.ts +7 -3
  16. package/dist/client/index.js +130 -0
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client-BYUWUiGZ.d.cts +143 -0
  19. package/dist/{client-BH7LbrKM.d.ts → client-ByNR5EZz.d.ts} +1 -1
  20. package/dist/{client-C67hy1kt.d.cts → client-D0vypxWb.d.cts} +1 -1
  21. package/dist/{client-DqWXAwCr.d.cts → client-D7bqvGJv.d.cts} +1 -1
  22. package/dist/{client-Dlif1JBf.d.ts → client-DbGRRMt7.d.ts} +1 -1
  23. package/dist/client-d7kX5WfR.d.ts +143 -0
  24. package/dist/events/index.d.cts +2 -2
  25. package/dist/events/index.d.ts +2 -2
  26. package/dist/{http-U-zzKmFF.d.cts → http-D2gXpNpr.d.cts} +2 -2
  27. package/dist/{http-U-zzKmFF.d.ts → http-D2gXpNpr.d.ts} +2 -2
  28. package/dist/index.cjs +228 -0
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +13 -8
  31. package/dist/index.d.ts +13 -8
  32. package/dist/index.js +226 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/next/index.cjs +183 -0
  35. package/dist/next/index.cjs.map +1 -0
  36. package/dist/next/index.d.cts +164 -0
  37. package/dist/next/index.d.ts +164 -0
  38. package/dist/next/index.js +172 -0
  39. package/dist/next/index.js.map +1 -0
  40. package/dist/notifications/index.d.cts +1 -1
  41. package/dist/notifications/index.d.ts +1 -1
  42. package/dist/react/index.cjs +120 -0
  43. package/dist/react/index.cjs.map +1 -0
  44. package/dist/react/index.d.cts +567 -0
  45. package/dist/react/index.d.ts +567 -0
  46. package/dist/react/index.js +92 -0
  47. package/dist/react/index.js.map +1 -0
  48. package/dist/server-CoPDzSUP.d.cts +117 -0
  49. package/dist/server-Suq3tZZC.d.ts +117 -0
  50. package/dist/storage/index.cjs.map +1 -1
  51. package/dist/storage/index.d.cts +1 -1
  52. package/dist/storage/index.d.ts +1 -1
  53. package/dist/storage/index.js.map +1 -1
  54. package/package.json +51 -2
package/README.md CHANGED
@@ -69,6 +69,75 @@ const signUpUrl = buildspace.auth.getSignUpUrl({
69
69
  });
70
70
  ```
71
71
 
72
+ ### Next.js adapter (`@buildspacestudio/sdk/next`)
73
+
74
+ Skip the hand-rolled auth routes — the adapter standardizes the `bs_session` cookie and ships route-handler factories for the whole flow. Works with any framework using web-standard `Request`/`Response` handlers.
75
+
76
+ ```ts
77
+ // app/api/auth/callback/route.ts
78
+ import { createAuthCallback } from "@buildspacestudio/sdk/next";
79
+ import { buildspace } from "@/lib/buildspace";
80
+
81
+ export const GET = createAuthCallback(buildspace, {
82
+ redirectTo: "/dashboard",
83
+ onSignIn: async ({ user }) => {
84
+ // first-class place for signup side effects (upsert user, welcome email)
85
+ },
86
+ });
87
+
88
+ // app/api/auth/logout/route.ts
89
+ import { createLogoutRoute } from "@buildspacestudio/sdk/next";
90
+ export const POST = createLogoutRoute(buildspace);
91
+
92
+ // app/api/auth/session/route.ts
93
+ import { createSessionRoute } from "@buildspacestudio/sdk/next";
94
+ export const GET = createSessionRoute(buildspace);
95
+ ```
96
+
97
+ Read the session anywhere on the server:
98
+
99
+ ```ts
100
+ import { cookies } from "next/headers";
101
+ import { getSession, requireSession } from "@buildspacestudio/sdk/next";
102
+
103
+ const session = await getSession(buildspace, await cookies()); // null when signed out
104
+ const { user, token } = await requireSession(buildspace, request); // throws 401 BuildspaceError
105
+ ```
106
+
107
+ Protect routes in middleware with a fast cookie-presence check:
108
+
109
+ ```ts
110
+ // middleware.ts
111
+ import { createSessionCookieGuard } from "@buildspacestudio/sdk/next";
112
+
113
+ export const middleware = createSessionCookieGuard({ redirectTo: "/" });
114
+ export const config = { matcher: ["/dashboard/:path*"] };
115
+ ```
116
+
117
+ ### React bindings (`@buildspacestudio/sdk/react`)
118
+
119
+ ```tsx
120
+ "use client";
121
+ import { createClient } from "@buildspacestudio/sdk/client";
122
+ import { BuildspaceProvider, useAuth, useTrack } from "@buildspacestudio/sdk/react";
123
+
124
+ const client = createClient(process.env.NEXT_PUBLIC_BUILDSPACE_PUBLISHABLE_KEY!);
125
+
126
+ // Wrap your app (pass the server-resolved user for a flash-free first paint)
127
+ <BuildspaceProvider client={client} initialUser={initialUser}>
128
+ {children}
129
+ </BuildspaceProvider>;
130
+
131
+ // Anywhere below the provider:
132
+ function UserMenu() {
133
+ const { user, signIn, signOut } = useAuth();
134
+ const track = useTrack(); // fire-and-forget analytics, never throws
135
+ // ...
136
+ }
137
+ ```
138
+
139
+ `react >= 19` is an optional peer dependency — only needed if you import `/react`.
140
+
72
141
  ---
73
142
 
74
143
  ## Events
@@ -154,6 +223,63 @@ const { key, url } = await buildspace.storage.upload(file, {
154
223
 
155
224
  ---
156
225
 
226
+ ## Billing
227
+
228
+ Stripe-backed subscriptions on the creator's connected account: Checkout, the customer portal, and entitlement checks.
229
+
230
+ ### Server
231
+
232
+ ```ts
233
+ // Is billing configured for this app environment?
234
+ const status = await buildspace.billing.getStatus();
235
+ // status.enabled, status.status ("disabled" | "setup_required" | "active" | "paused"),
236
+ // status.testMode — render a "Test mode" banner when true
237
+
238
+ // Catalog
239
+ const { products } = await buildspace.billing.listProducts();
240
+ const { prices } = await buildspace.billing.listPrices();
241
+
242
+ // Send a user to Stripe Checkout
243
+ const { url } = await buildspace.billing.createCheckout({
244
+ userId, // or appUserId for your own auth system
245
+ priceId: price.id, // or lookupKey
246
+ successUrl: "https://yourapp.com/billing?status=success",
247
+ cancelUrl: "https://yourapp.com/billing",
248
+ });
249
+
250
+ // Stripe-hosted customer portal (manage/cancel subscription)
251
+ const portal = await buildspace.billing.createPortalSession({
252
+ userId,
253
+ returnUrl: "https://yourapp.com/billing",
254
+ });
255
+
256
+ // Subscription + entitlement state
257
+ const { subscription } = await buildspace.billing.getSubscription({ userId });
258
+ const { active } = await buildspace.billing.getEntitlements({ userId });
259
+ if (active) {
260
+ // gate paid features here
261
+ }
262
+ ```
263
+
264
+ ### Client
265
+
266
+ ```ts
267
+ // List prices, then send the signed-in user to Checkout or the portal
268
+ const { prices } = await buildspace.billing.listPrices();
269
+
270
+ await buildspace.billing.redirectToCheckout({
271
+ priceId,
272
+ successUrl: `${location.origin}/billing?status=success`,
273
+ cancelUrl: `${location.origin}/billing`,
274
+ });
275
+
276
+ await buildspace.billing.manageSubscription({
277
+ returnUrl: `${location.origin}/billing`,
278
+ });
279
+ ```
280
+
281
+ ---
282
+
157
283
  ## Notifications
158
284
 
159
285
  Send transactional emails. **Server only.**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/client.ts","../../src/errors.ts","../../src/auth/server.ts"],"names":["forwardedHost","forwardedProto"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { HttpTransport } from \"../http\";\n\n/** Options for generating a sign-in URL. */\nexport interface SignInUrlOptions {\n /** App slug to scope the login to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after authentication completes. */\n redirectUri: string;\n}\n\n/** Options for generating a sign-up URL. */\nexport interface SignUpUrlOptions {\n /** App slug to scope the registration to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after registration completes. */\n redirectUri: string;\n}\n\n/**\n * Client-side authentication methods for generating login URLs.\n *\n * Access via `buildspace.auth` on the client SDK, or `buildspace.authClient`\n * on the server SDK when you need to generate URLs from server-side code.\n *\n * @example\n * ```ts\n * import { createClient } from \"@buildspacestudio/sdk/client\";\n *\n * const buildspace = createClient(process.env.NEXT_PUBLIC_BUILDSPACE_KEY!);\n *\n * const signInUrl = buildspace.auth.getSignInUrl({\n * redirectUri: \"https://yourapp.com/auth/callback\",\n * });\n *\n * // Use in a link or redirect\n * window.location.href = signInUrl;\n * ```\n */\nexport class AuthClientNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-in page.\n *\n * After the user authenticates, they are redirected back to `redirectUri`\n * with a `?code=` parameter that can be exchanged for tokens via\n * `buildspace.auth.handleCallback()` on the server.\n *\n * @param opts - Sign-in URL options.\n * @returns The full sign-in URL as a string.\n */\n getSignInUrl(opts: SignInUrlOptions): string {\n const url = new URL(\"/sign-in\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-up page.\n *\n * Works identically to {@link getSignInUrl} but directs the user to the\n * registration flow instead.\n *\n * @param opts - Sign-up URL options.\n * @returns The full sign-up URL as a string.\n */\n getSignUpUrl(opts: SignUpUrlOptions): string {\n const url = new URL(\"/sign-up\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n}\n","/** Services available in the Buildspace platform. */\nexport type BuildspaceService = \"auth\" | \"events\" | \"notifications\" | \"storage\";\n\n/**\n * Error thrown by all Buildspace SDK methods on failure.\n *\n * @example\n * ```ts\n * try {\n * await buildspace.auth.getSession(token);\n * } catch (err) {\n * if (err instanceof BuildspaceError) {\n * console.error(err.service, err.code, err.status, err.message);\n * }\n * }\n * ```\n */\nexport class BuildspaceError extends Error {\n /** Machine-readable error code, e.g. `\"auth/invalid-token\"`. */\n readonly code: string;\n /** Which service produced the error. */\n readonly service: BuildspaceService;\n /** HTTP status code from the API. */\n readonly status: number;\n\n constructor({\n code,\n message,\n service,\n status,\n }: {\n code: string;\n message: string;\n service: BuildspaceService;\n status: number;\n }) {\n super(message);\n this.name = \"BuildspaceError\";\n this.code = code;\n this.service = service;\n this.status = status;\n }\n}\n","import { BuildspaceError } from \"../errors\";\nimport type { HttpTransport } from \"../http\";\n\n/** A Buildspace user returned from auth endpoints. */\nexport interface AuthUser {\n /** The user's email address. */\n email: string;\n /** Unique user identifier. */\n id: string;\n /** The user's display name, or `null` if not set. */\n name: string | null;\n}\n\n/**\n * An active session for an authenticated user.\n *\n * Returned by {@link AuthServerNamespace.getSession}.\n */\nexport interface AuthSession {\n /** The app this session belongs to, or `null` for platform-level sessions. */\n appId: string | null;\n /** The authenticated user. */\n user: AuthUser;\n}\n\n/**\n * Token response returned after a successful OAuth callback exchange.\n *\n * Returned by {@link AuthServerNamespace.handleCallback}.\n */\nexport interface TokenResponse {\n /** The access token to use for authenticated requests. */\n access_token: string;\n /** Token lifetime in seconds. */\n expires_in: number;\n /** Always `\"bearer\"`. */\n token_type: \"bearer\";\n /** The authenticated user. */\n user: AuthUser;\n}\n\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"localhost\", \"::1\", \"0.0.0.0\"]);\nconst FORWARDED_HOST_RE = /host=\"?([^;\"]+)\"?/i;\nconst FORWARDED_PROTO_RE = /proto=\"?([^;\"]+)\"?/i;\n\nfunction getFirstForwardedValue(value: string | null): string | null {\n if (!value) {\n return null;\n }\n\n return (\n value\n .split(\",\")\n .map((part) => part.trim())\n .find(Boolean) ?? null\n );\n}\n\nfunction stripPort(host: string): string {\n if (host.startsWith(\"[\") && host.includes(\"]\")) {\n return host.slice(1, host.indexOf(\"]\"));\n }\n\n const colonIndex = host.indexOf(\":\");\n return colonIndex >= 0 ? host.slice(0, colonIndex) : host;\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\").map((part) => Number(part));\n if (parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)) {\n return false;\n }\n\n return (\n parts[0] === 10 ||\n (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||\n (parts[0] === 192 && parts[1] === 168)\n );\n}\n\nfunction isInternalHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n\n return (\n LOOPBACK_HOSTS.has(normalized) ||\n normalized.endsWith(\".local\") ||\n normalized.endsWith(\".internal\") ||\n isPrivateIpv4(normalized)\n );\n}\n\nfunction getForwardedOrigin(request: Request): string | null {\n const forwarded = getFirstForwardedValue(request.headers.get(\"forwarded\"));\n if (forwarded) {\n const forwardedHost = forwarded.match(FORWARDED_HOST_RE)?.[1]?.trim();\n const forwardedProto = forwarded.match(FORWARDED_PROTO_RE)?.[1]?.trim();\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n }\n\n const forwardedHost = getFirstForwardedValue(request.headers.get(\"x-forwarded-host\"));\n const forwardedProto = getFirstForwardedValue(request.headers.get(\"x-forwarded-proto\"));\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return null;\n}\n\nfunction resolveDefaultRedirectUri(request: Request | URL | string, url: URL): string {\n if (!(request instanceof Request)) {\n return `${url.origin}${url.pathname}`;\n }\n\n const forwardedOrigin = getForwardedOrigin(request);\n if (forwardedOrigin) {\n return `${forwardedOrigin}${url.pathname}`;\n }\n\n const hostHeader = request.headers.get(\"host\")?.trim();\n if (hostHeader && !isInternalHostname(stripPort(hostHeader))) {\n return `${url.protocol}//${hostHeader}${url.pathname}`;\n }\n\n if (!isInternalHostname(url.hostname)) {\n return `${url.origin}${url.pathname}`;\n }\n\n return `${url.origin}${url.pathname}`;\n}\n\n/**\n * Server-side authentication methods.\n *\n * Access via `buildspace.auth` on the server SDK.\n *\n * @example\n * ```ts\n * import Buildspace from \"@buildspacestudio/sdk\";\n *\n * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);\n *\n * // Handle OAuth callback\n * const tokens = await buildspace.auth.handleCallback(request);\n *\n * // Verify a session\n * const session = await buildspace.auth.getSession(sessionToken);\n *\n * // Sign out\n * await buildspace.auth.signOut(sessionToken);\n * ```\n */\nexport class AuthServerNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Retrieve the session associated with a token.\n *\n * Returns the {@link AuthSession} if valid, or `null` if the token is\n * expired, revoked, or invalid (401/404).\n *\n * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).\n */\n async getSession(sessionToken: string): Promise<AuthSession | null> {\n try {\n return await this.transport.request<AuthSession>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n } catch (error) {\n if (error instanceof BuildspaceError && (error.status === 401 || error.status === 404)) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Exchange an OAuth authorization code for tokens.\n *\n * Extracts the `code` query parameter from the callback URL and exchanges\n * it with the Buildspace API for an access token and user info.\n *\n * @param request - The incoming callback request. Accepts a `Request` object,\n * a `URL`, or a raw URL string containing the `?code=` parameter.\n * @param opts - Optional settings.\n * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.\n * Defaults to the origin + pathname of the callback URL.\n * @returns The token response containing `access_token`, `expires_in`, and `user`.\n *\n * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).\n *\n * @example\n * ```ts\n * // Next.js Route Handler\n * export async function GET(request: Request) {\n * const { access_token, user } = await buildspace.auth.handleCallback(request);\n * // Store access_token as a session cookie\n * }\n * ```\n */\n handleCallback(\n request: Request | URL | string,\n opts?: { redirectUri?: string }\n ): Promise<TokenResponse> {\n let url: URL;\n if (typeof request === \"string\") {\n url = new URL(request);\n } else if (request instanceof URL) {\n url = request;\n } else {\n url = new URL(request.url);\n }\n\n const code = url.searchParams.get(\"code\");\n if (!code) {\n throw new BuildspaceError({\n service: \"auth\",\n status: 400,\n code: \"auth/missing-code\",\n message: \"No auth code found in callback URL. Expected ?code= parameter.\",\n });\n }\n\n const redirectUri = opts?.redirectUri ?? resolveDefaultRedirectUri(request, url);\n\n return this.transport.request<TokenResponse>({\n service: \"auth\",\n path: \"/v1/auth/token\",\n method: \"POST\",\n body: {\n code,\n redirect_uri: redirectUri,\n },\n });\n }\n\n /**\n * Revoke a specific session token.\n *\n * @param sessionToken - The token to revoke.\n * @throws {BuildspaceError} If the revocation fails.\n */\n async revokeSession(sessionToken: string): Promise<void> {\n await this.transport.request<void>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n method: \"DELETE\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n }\n\n /**\n * Sign the user out by revoking the session and clearing the SDK's stored token.\n *\n * If the session is already expired or not found, the error is silently\n * ignored and the local session is still cleared.\n *\n * @param sessionToken - Token to revoke. If omitted, uses the token\n * previously set via `buildspace.setSession()`.\n */\n async signOut(sessionToken?: string): Promise<void> {\n const token = sessionToken ?? this.transport.getSessionToken();\n\n try {\n if (token) {\n await this.revokeSession(token);\n }\n } catch (error) {\n if (\n !(\n error instanceof BuildspaceError &&\n error.service === \"auth\" &&\n (error.status === 401 || error.status === 404)\n )\n ) {\n throw error;\n }\n } finally {\n this.transport.clearSession();\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/auth/client.ts","../../src/errors.ts","../../src/auth/server.ts"],"names":["forwardedHost","forwardedProto"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { HttpTransport } from \"../http\";\n\n/** Options for generating a sign-in URL. */\nexport interface SignInUrlOptions {\n /** App slug to scope the login to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after authentication completes. */\n redirectUri: string;\n}\n\n/** Options for generating a sign-up URL. */\nexport interface SignUpUrlOptions {\n /** App slug to scope the registration to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after registration completes. */\n redirectUri: string;\n}\n\n/**\n * Client-side authentication methods for generating login URLs.\n *\n * Access via `buildspace.auth` on the client SDK, or `buildspace.authClient`\n * on the server SDK when you need to generate URLs from server-side code.\n *\n * @example\n * ```ts\n * import { createClient } from \"@buildspacestudio/sdk/client\";\n *\n * const buildspace = createClient(process.env.NEXT_PUBLIC_BUILDSPACE_KEY!);\n *\n * const signInUrl = buildspace.auth.getSignInUrl({\n * redirectUri: \"https://yourapp.com/auth/callback\",\n * });\n *\n * // Use in a link or redirect\n * window.location.href = signInUrl;\n * ```\n */\nexport class AuthClientNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-in page.\n *\n * After the user authenticates, they are redirected back to `redirectUri`\n * with a `?code=` parameter that can be exchanged for tokens via\n * `buildspace.auth.handleCallback()` on the server.\n *\n * @param opts - Sign-in URL options.\n * @returns The full sign-in URL as a string.\n */\n getSignInUrl(opts: SignInUrlOptions): string {\n const url = new URL(\"/sign-in\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-up page.\n *\n * Works identically to {@link getSignInUrl} but directs the user to the\n * registration flow instead.\n *\n * @param opts - Sign-up URL options.\n * @returns The full sign-up URL as a string.\n */\n getSignUpUrl(opts: SignUpUrlOptions): string {\n const url = new URL(\"/sign-up\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n}\n","/** Services available in the Buildspace platform. */\nexport type BuildspaceService = \"auth\" | \"billing\" | \"events\" | \"notifications\" | \"storage\";\n\n/**\n * Error thrown by all Buildspace SDK methods on failure.\n *\n * @example\n * ```ts\n * try {\n * await buildspace.auth.getSession(token);\n * } catch (err) {\n * if (err instanceof BuildspaceError) {\n * console.error(err.service, err.code, err.status, err.message);\n * }\n * }\n * ```\n */\nexport class BuildspaceError extends Error {\n /** Machine-readable error code, e.g. `\"auth/invalid-token\"`. */\n readonly code: string;\n /** Which service produced the error. */\n readonly service: BuildspaceService;\n /** HTTP status code from the API. */\n readonly status: number;\n\n constructor({\n code,\n message,\n service,\n status,\n }: {\n code: string;\n message: string;\n service: BuildspaceService;\n status: number;\n }) {\n super(message);\n this.name = \"BuildspaceError\";\n this.code = code;\n this.service = service;\n this.status = status;\n }\n}\n","import { BuildspaceError } from \"../errors\";\nimport type { HttpTransport } from \"../http\";\n\n/** A Buildspace user returned from auth endpoints. */\nexport interface AuthUser {\n /** The user's email address. */\n email: string;\n /** Unique user identifier. */\n id: string;\n /** The user's display name, or `null` if not set. */\n name: string | null;\n}\n\n/**\n * An active session for an authenticated user.\n *\n * Returned by {@link AuthServerNamespace.getSession}.\n */\nexport interface AuthSession {\n /** The app this session belongs to, or `null` for platform-level sessions. */\n appId: string | null;\n /** The authenticated user. */\n user: AuthUser;\n}\n\n/**\n * Token response returned after a successful OAuth callback exchange.\n *\n * Returned by {@link AuthServerNamespace.handleCallback}.\n */\nexport interface TokenResponse {\n /** The access token to use for authenticated requests. */\n access_token: string;\n /** Token lifetime in seconds. */\n expires_in: number;\n /** Always `\"bearer\"`. */\n token_type: \"bearer\";\n /** The authenticated user. */\n user: AuthUser;\n}\n\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"localhost\", \"::1\", \"0.0.0.0\"]);\nconst FORWARDED_HOST_RE = /host=\"?([^;\"]+)\"?/i;\nconst FORWARDED_PROTO_RE = /proto=\"?([^;\"]+)\"?/i;\n\nfunction getFirstForwardedValue(value: string | null): string | null {\n if (!value) {\n return null;\n }\n\n return (\n value\n .split(\",\")\n .map((part) => part.trim())\n .find(Boolean) ?? null\n );\n}\n\nfunction stripPort(host: string): string {\n if (host.startsWith(\"[\") && host.includes(\"]\")) {\n return host.slice(1, host.indexOf(\"]\"));\n }\n\n const colonIndex = host.indexOf(\":\");\n return colonIndex >= 0 ? host.slice(0, colonIndex) : host;\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\").map((part) => Number(part));\n if (parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)) {\n return false;\n }\n\n return (\n parts[0] === 10 ||\n (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||\n (parts[0] === 192 && parts[1] === 168)\n );\n}\n\nfunction isInternalHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n\n return (\n LOOPBACK_HOSTS.has(normalized) ||\n normalized.endsWith(\".local\") ||\n normalized.endsWith(\".internal\") ||\n isPrivateIpv4(normalized)\n );\n}\n\nfunction getForwardedOrigin(request: Request): string | null {\n const forwarded = getFirstForwardedValue(request.headers.get(\"forwarded\"));\n if (forwarded) {\n const forwardedHost = forwarded.match(FORWARDED_HOST_RE)?.[1]?.trim();\n const forwardedProto = forwarded.match(FORWARDED_PROTO_RE)?.[1]?.trim();\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n }\n\n const forwardedHost = getFirstForwardedValue(request.headers.get(\"x-forwarded-host\"));\n const forwardedProto = getFirstForwardedValue(request.headers.get(\"x-forwarded-proto\"));\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return null;\n}\n\nfunction resolveDefaultRedirectUri(request: Request | URL | string, url: URL): string {\n if (!(request instanceof Request)) {\n return `${url.origin}${url.pathname}`;\n }\n\n const forwardedOrigin = getForwardedOrigin(request);\n if (forwardedOrigin) {\n return `${forwardedOrigin}${url.pathname}`;\n }\n\n const hostHeader = request.headers.get(\"host\")?.trim();\n if (hostHeader && !isInternalHostname(stripPort(hostHeader))) {\n return `${url.protocol}//${hostHeader}${url.pathname}`;\n }\n\n if (!isInternalHostname(url.hostname)) {\n return `${url.origin}${url.pathname}`;\n }\n\n return `${url.origin}${url.pathname}`;\n}\n\n/**\n * Server-side authentication methods.\n *\n * Access via `buildspace.auth` on the server SDK.\n *\n * @example\n * ```ts\n * import Buildspace from \"@buildspacestudio/sdk\";\n *\n * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);\n *\n * // Handle OAuth callback\n * const tokens = await buildspace.auth.handleCallback(request);\n *\n * // Verify a session\n * const session = await buildspace.auth.getSession(sessionToken);\n *\n * // Sign out\n * await buildspace.auth.signOut(sessionToken);\n * ```\n */\nexport class AuthServerNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Retrieve the session associated with a token.\n *\n * Returns the {@link AuthSession} if valid, or `null` if the token is\n * expired, revoked, or invalid (401/404).\n *\n * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).\n */\n async getSession(sessionToken: string): Promise<AuthSession | null> {\n try {\n return await this.transport.request<AuthSession>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n } catch (error) {\n if (error instanceof BuildspaceError && (error.status === 401 || error.status === 404)) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Exchange an OAuth authorization code for tokens.\n *\n * Extracts the `code` query parameter from the callback URL and exchanges\n * it with the Buildspace API for an access token and user info.\n *\n * @param request - The incoming callback request. Accepts a `Request` object,\n * a `URL`, or a raw URL string containing the `?code=` parameter.\n * @param opts - Optional settings.\n * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.\n * Defaults to the origin + pathname of the callback URL.\n * @returns The token response containing `access_token`, `expires_in`, and `user`.\n *\n * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).\n *\n * @example\n * ```ts\n * // Next.js Route Handler\n * export async function GET(request: Request) {\n * const { access_token, user } = await buildspace.auth.handleCallback(request);\n * // Store access_token as a session cookie\n * }\n * ```\n */\n handleCallback(\n request: Request | URL | string,\n opts?: { redirectUri?: string }\n ): Promise<TokenResponse> {\n let url: URL;\n if (typeof request === \"string\") {\n url = new URL(request);\n } else if (request instanceof URL) {\n url = request;\n } else {\n url = new URL(request.url);\n }\n\n const code = url.searchParams.get(\"code\");\n if (!code) {\n throw new BuildspaceError({\n service: \"auth\",\n status: 400,\n code: \"auth/missing-code\",\n message: \"No auth code found in callback URL. Expected ?code= parameter.\",\n });\n }\n\n const redirectUri = opts?.redirectUri ?? resolveDefaultRedirectUri(request, url);\n\n return this.transport.request<TokenResponse>({\n service: \"auth\",\n path: \"/v1/auth/token\",\n method: \"POST\",\n body: {\n code,\n redirect_uri: redirectUri,\n },\n });\n }\n\n /**\n * Revoke a specific session token.\n *\n * @param sessionToken - The token to revoke.\n * @throws {BuildspaceError} If the revocation fails.\n */\n async revokeSession(sessionToken: string): Promise<void> {\n await this.transport.request<void>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n method: \"DELETE\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n }\n\n /**\n * Sign the user out by revoking the session and clearing the SDK's stored token.\n *\n * If the session is already expired or not found, the error is silently\n * ignored and the local session is still cleared.\n *\n * @param sessionToken - Token to revoke. If omitted, uses the token\n * previously set via `buildspace.setSession()`.\n */\n async signOut(sessionToken?: string): Promise<void> {\n const token = sessionToken ?? this.transport.getSessionToken();\n\n try {\n if (token) {\n await this.revokeSession(token);\n }\n } catch (error) {\n if (\n !(\n error instanceof BuildspaceError &&\n error.service === \"auth\" &&\n (error.status === 401 || error.status === 404)\n )\n ) {\n throw error;\n }\n } finally {\n this.transport.clearSession();\n }\n }\n}\n"]}
@@ -1,118 +1,3 @@
1
- export { A as AuthClientNamespace, S as SignInUrlOptions, a as SignUpUrlOptions } from '../client-DqWXAwCr.cjs';
2
- import { H as HttpTransport } from '../http-U-zzKmFF.cjs';
3
-
4
- /** A Buildspace user returned from auth endpoints. */
5
- interface AuthUser {
6
- /** The user's email address. */
7
- email: string;
8
- /** Unique user identifier. */
9
- id: string;
10
- /** The user's display name, or `null` if not set. */
11
- name: string | null;
12
- }
13
- /**
14
- * An active session for an authenticated user.
15
- *
16
- * Returned by {@link AuthServerNamespace.getSession}.
17
- */
18
- interface AuthSession {
19
- /** The app this session belongs to, or `null` for platform-level sessions. */
20
- appId: string | null;
21
- /** The authenticated user. */
22
- user: AuthUser;
23
- }
24
- /**
25
- * Token response returned after a successful OAuth callback exchange.
26
- *
27
- * Returned by {@link AuthServerNamespace.handleCallback}.
28
- */
29
- interface TokenResponse {
30
- /** The access token to use for authenticated requests. */
31
- access_token: string;
32
- /** Token lifetime in seconds. */
33
- expires_in: number;
34
- /** Always `"bearer"`. */
35
- token_type: "bearer";
36
- /** The authenticated user. */
37
- user: AuthUser;
38
- }
39
- /**
40
- * Server-side authentication methods.
41
- *
42
- * Access via `buildspace.auth` on the server SDK.
43
- *
44
- * @example
45
- * ```ts
46
- * import Buildspace from "@buildspacestudio/sdk";
47
- *
48
- * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);
49
- *
50
- * // Handle OAuth callback
51
- * const tokens = await buildspace.auth.handleCallback(request);
52
- *
53
- * // Verify a session
54
- * const session = await buildspace.auth.getSession(sessionToken);
55
- *
56
- * // Sign out
57
- * await buildspace.auth.signOut(sessionToken);
58
- * ```
59
- */
60
- declare class AuthServerNamespace {
61
- private readonly transport;
62
- constructor(transport: HttpTransport);
63
- /**
64
- * Retrieve the session associated with a token.
65
- *
66
- * Returns the {@link AuthSession} if valid, or `null` if the token is
67
- * expired, revoked, or invalid (401/404).
68
- *
69
- * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).
70
- */
71
- getSession(sessionToken: string): Promise<AuthSession | null>;
72
- /**
73
- * Exchange an OAuth authorization code for tokens.
74
- *
75
- * Extracts the `code` query parameter from the callback URL and exchanges
76
- * it with the Buildspace API for an access token and user info.
77
- *
78
- * @param request - The incoming callback request. Accepts a `Request` object,
79
- * a `URL`, or a raw URL string containing the `?code=` parameter.
80
- * @param opts - Optional settings.
81
- * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.
82
- * Defaults to the origin + pathname of the callback URL.
83
- * @returns The token response containing `access_token`, `expires_in`, and `user`.
84
- *
85
- * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).
86
- *
87
- * @example
88
- * ```ts
89
- * // Next.js Route Handler
90
- * export async function GET(request: Request) {
91
- * const { access_token, user } = await buildspace.auth.handleCallback(request);
92
- * // Store access_token as a session cookie
93
- * }
94
- * ```
95
- */
96
- handleCallback(request: Request | URL | string, opts?: {
97
- redirectUri?: string;
98
- }): Promise<TokenResponse>;
99
- /**
100
- * Revoke a specific session token.
101
- *
102
- * @param sessionToken - The token to revoke.
103
- * @throws {BuildspaceError} If the revocation fails.
104
- */
105
- revokeSession(sessionToken: string): Promise<void>;
106
- /**
107
- * Sign the user out by revoking the session and clearing the SDK's stored token.
108
- *
109
- * If the session is already expired or not found, the error is silently
110
- * ignored and the local session is still cleared.
111
- *
112
- * @param sessionToken - Token to revoke. If omitted, uses the token
113
- * previously set via `buildspace.setSession()`.
114
- */
115
- signOut(sessionToken?: string): Promise<void>;
116
- }
117
-
118
- export { AuthServerNamespace, type AuthSession, type AuthUser, type TokenResponse };
1
+ export { A as AuthClientNamespace, S as SignInUrlOptions, a as SignUpUrlOptions } from '../client-D7bqvGJv.cjs';
2
+ export { A as AuthServerNamespace, a as AuthSession, b as AuthUser, T as TokenResponse } from '../server-CoPDzSUP.cjs';
3
+ import '../http-D2gXpNpr.cjs';
@@ -1,118 +1,3 @@
1
- export { A as AuthClientNamespace, S as SignInUrlOptions, a as SignUpUrlOptions } from '../client-BH7LbrKM.js';
2
- import { H as HttpTransport } from '../http-U-zzKmFF.js';
3
-
4
- /** A Buildspace user returned from auth endpoints. */
5
- interface AuthUser {
6
- /** The user's email address. */
7
- email: string;
8
- /** Unique user identifier. */
9
- id: string;
10
- /** The user's display name, or `null` if not set. */
11
- name: string | null;
12
- }
13
- /**
14
- * An active session for an authenticated user.
15
- *
16
- * Returned by {@link AuthServerNamespace.getSession}.
17
- */
18
- interface AuthSession {
19
- /** The app this session belongs to, or `null` for platform-level sessions. */
20
- appId: string | null;
21
- /** The authenticated user. */
22
- user: AuthUser;
23
- }
24
- /**
25
- * Token response returned after a successful OAuth callback exchange.
26
- *
27
- * Returned by {@link AuthServerNamespace.handleCallback}.
28
- */
29
- interface TokenResponse {
30
- /** The access token to use for authenticated requests. */
31
- access_token: string;
32
- /** Token lifetime in seconds. */
33
- expires_in: number;
34
- /** Always `"bearer"`. */
35
- token_type: "bearer";
36
- /** The authenticated user. */
37
- user: AuthUser;
38
- }
39
- /**
40
- * Server-side authentication methods.
41
- *
42
- * Access via `buildspace.auth` on the server SDK.
43
- *
44
- * @example
45
- * ```ts
46
- * import Buildspace from "@buildspacestudio/sdk";
47
- *
48
- * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);
49
- *
50
- * // Handle OAuth callback
51
- * const tokens = await buildspace.auth.handleCallback(request);
52
- *
53
- * // Verify a session
54
- * const session = await buildspace.auth.getSession(sessionToken);
55
- *
56
- * // Sign out
57
- * await buildspace.auth.signOut(sessionToken);
58
- * ```
59
- */
60
- declare class AuthServerNamespace {
61
- private readonly transport;
62
- constructor(transport: HttpTransport);
63
- /**
64
- * Retrieve the session associated with a token.
65
- *
66
- * Returns the {@link AuthSession} if valid, or `null` if the token is
67
- * expired, revoked, or invalid (401/404).
68
- *
69
- * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).
70
- */
71
- getSession(sessionToken: string): Promise<AuthSession | null>;
72
- /**
73
- * Exchange an OAuth authorization code for tokens.
74
- *
75
- * Extracts the `code` query parameter from the callback URL and exchanges
76
- * it with the Buildspace API for an access token and user info.
77
- *
78
- * @param request - The incoming callback request. Accepts a `Request` object,
79
- * a `URL`, or a raw URL string containing the `?code=` parameter.
80
- * @param opts - Optional settings.
81
- * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.
82
- * Defaults to the origin + pathname of the callback URL.
83
- * @returns The token response containing `access_token`, `expires_in`, and `user`.
84
- *
85
- * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).
86
- *
87
- * @example
88
- * ```ts
89
- * // Next.js Route Handler
90
- * export async function GET(request: Request) {
91
- * const { access_token, user } = await buildspace.auth.handleCallback(request);
92
- * // Store access_token as a session cookie
93
- * }
94
- * ```
95
- */
96
- handleCallback(request: Request | URL | string, opts?: {
97
- redirectUri?: string;
98
- }): Promise<TokenResponse>;
99
- /**
100
- * Revoke a specific session token.
101
- *
102
- * @param sessionToken - The token to revoke.
103
- * @throws {BuildspaceError} If the revocation fails.
104
- */
105
- revokeSession(sessionToken: string): Promise<void>;
106
- /**
107
- * Sign the user out by revoking the session and clearing the SDK's stored token.
108
- *
109
- * If the session is already expired or not found, the error is silently
110
- * ignored and the local session is still cleared.
111
- *
112
- * @param sessionToken - Token to revoke. If omitted, uses the token
113
- * previously set via `buildspace.setSession()`.
114
- */
115
- signOut(sessionToken?: string): Promise<void>;
116
- }
117
-
118
- export { AuthServerNamespace, type AuthSession, type AuthUser, type TokenResponse };
1
+ export { A as AuthClientNamespace, S as SignInUrlOptions, a as SignUpUrlOptions } from '../client-ByNR5EZz.js';
2
+ export { A as AuthServerNamespace, a as AuthSession, b as AuthUser, T as TokenResponse } from '../server-Suq3tZZC.js';
3
+ import '../http-D2gXpNpr.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/client.ts","../../src/errors.ts","../../src/auth/server.ts"],"names":["forwardedHost","forwardedProto"],"mappings":"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","file":"index.js","sourcesContent":["import type { HttpTransport } from \"../http\";\n\n/** Options for generating a sign-in URL. */\nexport interface SignInUrlOptions {\n /** App slug to scope the login to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after authentication completes. */\n redirectUri: string;\n}\n\n/** Options for generating a sign-up URL. */\nexport interface SignUpUrlOptions {\n /** App slug to scope the registration to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after registration completes. */\n redirectUri: string;\n}\n\n/**\n * Client-side authentication methods for generating login URLs.\n *\n * Access via `buildspace.auth` on the client SDK, or `buildspace.authClient`\n * on the server SDK when you need to generate URLs from server-side code.\n *\n * @example\n * ```ts\n * import { createClient } from \"@buildspacestudio/sdk/client\";\n *\n * const buildspace = createClient(process.env.NEXT_PUBLIC_BUILDSPACE_KEY!);\n *\n * const signInUrl = buildspace.auth.getSignInUrl({\n * redirectUri: \"https://yourapp.com/auth/callback\",\n * });\n *\n * // Use in a link or redirect\n * window.location.href = signInUrl;\n * ```\n */\nexport class AuthClientNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-in page.\n *\n * After the user authenticates, they are redirected back to `redirectUri`\n * with a `?code=` parameter that can be exchanged for tokens via\n * `buildspace.auth.handleCallback()` on the server.\n *\n * @param opts - Sign-in URL options.\n * @returns The full sign-in URL as a string.\n */\n getSignInUrl(opts: SignInUrlOptions): string {\n const url = new URL(\"/sign-in\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-up page.\n *\n * Works identically to {@link getSignInUrl} but directs the user to the\n * registration flow instead.\n *\n * @param opts - Sign-up URL options.\n * @returns The full sign-up URL as a string.\n */\n getSignUpUrl(opts: SignUpUrlOptions): string {\n const url = new URL(\"/sign-up\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n}\n","/** Services available in the Buildspace platform. */\nexport type BuildspaceService = \"auth\" | \"events\" | \"notifications\" | \"storage\";\n\n/**\n * Error thrown by all Buildspace SDK methods on failure.\n *\n * @example\n * ```ts\n * try {\n * await buildspace.auth.getSession(token);\n * } catch (err) {\n * if (err instanceof BuildspaceError) {\n * console.error(err.service, err.code, err.status, err.message);\n * }\n * }\n * ```\n */\nexport class BuildspaceError extends Error {\n /** Machine-readable error code, e.g. `\"auth/invalid-token\"`. */\n readonly code: string;\n /** Which service produced the error. */\n readonly service: BuildspaceService;\n /** HTTP status code from the API. */\n readonly status: number;\n\n constructor({\n code,\n message,\n service,\n status,\n }: {\n code: string;\n message: string;\n service: BuildspaceService;\n status: number;\n }) {\n super(message);\n this.name = \"BuildspaceError\";\n this.code = code;\n this.service = service;\n this.status = status;\n }\n}\n","import { BuildspaceError } from \"../errors\";\nimport type { HttpTransport } from \"../http\";\n\n/** A Buildspace user returned from auth endpoints. */\nexport interface AuthUser {\n /** The user's email address. */\n email: string;\n /** Unique user identifier. */\n id: string;\n /** The user's display name, or `null` if not set. */\n name: string | null;\n}\n\n/**\n * An active session for an authenticated user.\n *\n * Returned by {@link AuthServerNamespace.getSession}.\n */\nexport interface AuthSession {\n /** The app this session belongs to, or `null` for platform-level sessions. */\n appId: string | null;\n /** The authenticated user. */\n user: AuthUser;\n}\n\n/**\n * Token response returned after a successful OAuth callback exchange.\n *\n * Returned by {@link AuthServerNamespace.handleCallback}.\n */\nexport interface TokenResponse {\n /** The access token to use for authenticated requests. */\n access_token: string;\n /** Token lifetime in seconds. */\n expires_in: number;\n /** Always `\"bearer\"`. */\n token_type: \"bearer\";\n /** The authenticated user. */\n user: AuthUser;\n}\n\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"localhost\", \"::1\", \"0.0.0.0\"]);\nconst FORWARDED_HOST_RE = /host=\"?([^;\"]+)\"?/i;\nconst FORWARDED_PROTO_RE = /proto=\"?([^;\"]+)\"?/i;\n\nfunction getFirstForwardedValue(value: string | null): string | null {\n if (!value) {\n return null;\n }\n\n return (\n value\n .split(\",\")\n .map((part) => part.trim())\n .find(Boolean) ?? null\n );\n}\n\nfunction stripPort(host: string): string {\n if (host.startsWith(\"[\") && host.includes(\"]\")) {\n return host.slice(1, host.indexOf(\"]\"));\n }\n\n const colonIndex = host.indexOf(\":\");\n return colonIndex >= 0 ? host.slice(0, colonIndex) : host;\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\").map((part) => Number(part));\n if (parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)) {\n return false;\n }\n\n return (\n parts[0] === 10 ||\n (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||\n (parts[0] === 192 && parts[1] === 168)\n );\n}\n\nfunction isInternalHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n\n return (\n LOOPBACK_HOSTS.has(normalized) ||\n normalized.endsWith(\".local\") ||\n normalized.endsWith(\".internal\") ||\n isPrivateIpv4(normalized)\n );\n}\n\nfunction getForwardedOrigin(request: Request): string | null {\n const forwarded = getFirstForwardedValue(request.headers.get(\"forwarded\"));\n if (forwarded) {\n const forwardedHost = forwarded.match(FORWARDED_HOST_RE)?.[1]?.trim();\n const forwardedProto = forwarded.match(FORWARDED_PROTO_RE)?.[1]?.trim();\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n }\n\n const forwardedHost = getFirstForwardedValue(request.headers.get(\"x-forwarded-host\"));\n const forwardedProto = getFirstForwardedValue(request.headers.get(\"x-forwarded-proto\"));\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return null;\n}\n\nfunction resolveDefaultRedirectUri(request: Request | URL | string, url: URL): string {\n if (!(request instanceof Request)) {\n return `${url.origin}${url.pathname}`;\n }\n\n const forwardedOrigin = getForwardedOrigin(request);\n if (forwardedOrigin) {\n return `${forwardedOrigin}${url.pathname}`;\n }\n\n const hostHeader = request.headers.get(\"host\")?.trim();\n if (hostHeader && !isInternalHostname(stripPort(hostHeader))) {\n return `${url.protocol}//${hostHeader}${url.pathname}`;\n }\n\n if (!isInternalHostname(url.hostname)) {\n return `${url.origin}${url.pathname}`;\n }\n\n return `${url.origin}${url.pathname}`;\n}\n\n/**\n * Server-side authentication methods.\n *\n * Access via `buildspace.auth` on the server SDK.\n *\n * @example\n * ```ts\n * import Buildspace from \"@buildspacestudio/sdk\";\n *\n * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);\n *\n * // Handle OAuth callback\n * const tokens = await buildspace.auth.handleCallback(request);\n *\n * // Verify a session\n * const session = await buildspace.auth.getSession(sessionToken);\n *\n * // Sign out\n * await buildspace.auth.signOut(sessionToken);\n * ```\n */\nexport class AuthServerNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Retrieve the session associated with a token.\n *\n * Returns the {@link AuthSession} if valid, or `null` if the token is\n * expired, revoked, or invalid (401/404).\n *\n * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).\n */\n async getSession(sessionToken: string): Promise<AuthSession | null> {\n try {\n return await this.transport.request<AuthSession>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n } catch (error) {\n if (error instanceof BuildspaceError && (error.status === 401 || error.status === 404)) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Exchange an OAuth authorization code for tokens.\n *\n * Extracts the `code` query parameter from the callback URL and exchanges\n * it with the Buildspace API for an access token and user info.\n *\n * @param request - The incoming callback request. Accepts a `Request` object,\n * a `URL`, or a raw URL string containing the `?code=` parameter.\n * @param opts - Optional settings.\n * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.\n * Defaults to the origin + pathname of the callback URL.\n * @returns The token response containing `access_token`, `expires_in`, and `user`.\n *\n * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).\n *\n * @example\n * ```ts\n * // Next.js Route Handler\n * export async function GET(request: Request) {\n * const { access_token, user } = await buildspace.auth.handleCallback(request);\n * // Store access_token as a session cookie\n * }\n * ```\n */\n handleCallback(\n request: Request | URL | string,\n opts?: { redirectUri?: string }\n ): Promise<TokenResponse> {\n let url: URL;\n if (typeof request === \"string\") {\n url = new URL(request);\n } else if (request instanceof URL) {\n url = request;\n } else {\n url = new URL(request.url);\n }\n\n const code = url.searchParams.get(\"code\");\n if (!code) {\n throw new BuildspaceError({\n service: \"auth\",\n status: 400,\n code: \"auth/missing-code\",\n message: \"No auth code found in callback URL. Expected ?code= parameter.\",\n });\n }\n\n const redirectUri = opts?.redirectUri ?? resolveDefaultRedirectUri(request, url);\n\n return this.transport.request<TokenResponse>({\n service: \"auth\",\n path: \"/v1/auth/token\",\n method: \"POST\",\n body: {\n code,\n redirect_uri: redirectUri,\n },\n });\n }\n\n /**\n * Revoke a specific session token.\n *\n * @param sessionToken - The token to revoke.\n * @throws {BuildspaceError} If the revocation fails.\n */\n async revokeSession(sessionToken: string): Promise<void> {\n await this.transport.request<void>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n method: \"DELETE\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n }\n\n /**\n * Sign the user out by revoking the session and clearing the SDK's stored token.\n *\n * If the session is already expired or not found, the error is silently\n * ignored and the local session is still cleared.\n *\n * @param sessionToken - Token to revoke. If omitted, uses the token\n * previously set via `buildspace.setSession()`.\n */\n async signOut(sessionToken?: string): Promise<void> {\n const token = sessionToken ?? this.transport.getSessionToken();\n\n try {\n if (token) {\n await this.revokeSession(token);\n }\n } catch (error) {\n if (\n !(\n error instanceof BuildspaceError &&\n error.service === \"auth\" &&\n (error.status === 401 || error.status === 404)\n )\n ) {\n throw error;\n }\n } finally {\n this.transport.clearSession();\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/auth/client.ts","../../src/errors.ts","../../src/auth/server.ts"],"names":["forwardedHost","forwardedProto"],"mappings":"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","file":"index.js","sourcesContent":["import type { HttpTransport } from \"../http\";\n\n/** Options for generating a sign-in URL. */\nexport interface SignInUrlOptions {\n /** App slug to scope the login to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after authentication completes. */\n redirectUri: string;\n}\n\n/** Options for generating a sign-up URL. */\nexport interface SignUpUrlOptions {\n /** App slug to scope the registration to a specific creator app. */\n appSlug?: string;\n /** Environment to authenticate against. */\n env?: \"dev\" | \"prod\";\n /** URL to redirect the user to after registration completes. */\n redirectUri: string;\n}\n\n/**\n * Client-side authentication methods for generating login URLs.\n *\n * Access via `buildspace.auth` on the client SDK, or `buildspace.authClient`\n * on the server SDK when you need to generate URLs from server-side code.\n *\n * @example\n * ```ts\n * import { createClient } from \"@buildspacestudio/sdk/client\";\n *\n * const buildspace = createClient(process.env.NEXT_PUBLIC_BUILDSPACE_KEY!);\n *\n * const signInUrl = buildspace.auth.getSignInUrl({\n * redirectUri: \"https://yourapp.com/auth/callback\",\n * });\n *\n * // Use in a link or redirect\n * window.location.href = signInUrl;\n * ```\n */\nexport class AuthClientNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-in page.\n *\n * After the user authenticates, they are redirected back to `redirectUri`\n * with a `?code=` parameter that can be exchanged for tokens via\n * `buildspace.auth.handleCallback()` on the server.\n *\n * @param opts - Sign-in URL options.\n * @returns The full sign-in URL as a string.\n */\n getSignInUrl(opts: SignInUrlOptions): string {\n const url = new URL(\"/sign-in\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n\n /**\n * Build a URL that redirects the user to the Buildspace sign-up page.\n *\n * Works identically to {@link getSignInUrl} but directs the user to the\n * registration flow instead.\n *\n * @param opts - Sign-up URL options.\n * @returns The full sign-up URL as a string.\n */\n getSignUpUrl(opts: SignUpUrlOptions): string {\n const url = new URL(\"/sign-up\", this.transport.loginUrl);\n\n if (opts.appSlug) {\n url.searchParams.set(\"app\", opts.appSlug);\n }\n\n url.searchParams.set(\"redirect_uri\", opts.redirectUri);\n url.searchParams.set(\"client_id\", this.transport.key);\n\n if (opts.env) {\n url.searchParams.set(\"env\", opts.env);\n }\n\n return url.toString();\n }\n}\n","/** Services available in the Buildspace platform. */\nexport type BuildspaceService = \"auth\" | \"billing\" | \"events\" | \"notifications\" | \"storage\";\n\n/**\n * Error thrown by all Buildspace SDK methods on failure.\n *\n * @example\n * ```ts\n * try {\n * await buildspace.auth.getSession(token);\n * } catch (err) {\n * if (err instanceof BuildspaceError) {\n * console.error(err.service, err.code, err.status, err.message);\n * }\n * }\n * ```\n */\nexport class BuildspaceError extends Error {\n /** Machine-readable error code, e.g. `\"auth/invalid-token\"`. */\n readonly code: string;\n /** Which service produced the error. */\n readonly service: BuildspaceService;\n /** HTTP status code from the API. */\n readonly status: number;\n\n constructor({\n code,\n message,\n service,\n status,\n }: {\n code: string;\n message: string;\n service: BuildspaceService;\n status: number;\n }) {\n super(message);\n this.name = \"BuildspaceError\";\n this.code = code;\n this.service = service;\n this.status = status;\n }\n}\n","import { BuildspaceError } from \"../errors\";\nimport type { HttpTransport } from \"../http\";\n\n/** A Buildspace user returned from auth endpoints. */\nexport interface AuthUser {\n /** The user's email address. */\n email: string;\n /** Unique user identifier. */\n id: string;\n /** The user's display name, or `null` if not set. */\n name: string | null;\n}\n\n/**\n * An active session for an authenticated user.\n *\n * Returned by {@link AuthServerNamespace.getSession}.\n */\nexport interface AuthSession {\n /** The app this session belongs to, or `null` for platform-level sessions. */\n appId: string | null;\n /** The authenticated user. */\n user: AuthUser;\n}\n\n/**\n * Token response returned after a successful OAuth callback exchange.\n *\n * Returned by {@link AuthServerNamespace.handleCallback}.\n */\nexport interface TokenResponse {\n /** The access token to use for authenticated requests. */\n access_token: string;\n /** Token lifetime in seconds. */\n expires_in: number;\n /** Always `\"bearer\"`. */\n token_type: \"bearer\";\n /** The authenticated user. */\n user: AuthUser;\n}\n\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"localhost\", \"::1\", \"0.0.0.0\"]);\nconst FORWARDED_HOST_RE = /host=\"?([^;\"]+)\"?/i;\nconst FORWARDED_PROTO_RE = /proto=\"?([^;\"]+)\"?/i;\n\nfunction getFirstForwardedValue(value: string | null): string | null {\n if (!value) {\n return null;\n }\n\n return (\n value\n .split(\",\")\n .map((part) => part.trim())\n .find(Boolean) ?? null\n );\n}\n\nfunction stripPort(host: string): string {\n if (host.startsWith(\"[\") && host.includes(\"]\")) {\n return host.slice(1, host.indexOf(\"]\"));\n }\n\n const colonIndex = host.indexOf(\":\");\n return colonIndex >= 0 ? host.slice(0, colonIndex) : host;\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\").map((part) => Number(part));\n if (parts.length !== 4 || parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)) {\n return false;\n }\n\n return (\n parts[0] === 10 ||\n (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||\n (parts[0] === 192 && parts[1] === 168)\n );\n}\n\nfunction isInternalHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase();\n\n return (\n LOOPBACK_HOSTS.has(normalized) ||\n normalized.endsWith(\".local\") ||\n normalized.endsWith(\".internal\") ||\n isPrivateIpv4(normalized)\n );\n}\n\nfunction getForwardedOrigin(request: Request): string | null {\n const forwarded = getFirstForwardedValue(request.headers.get(\"forwarded\"));\n if (forwarded) {\n const forwardedHost = forwarded.match(FORWARDED_HOST_RE)?.[1]?.trim();\n const forwardedProto = forwarded.match(FORWARDED_PROTO_RE)?.[1]?.trim();\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n }\n\n const forwardedHost = getFirstForwardedValue(request.headers.get(\"x-forwarded-host\"));\n const forwardedProto = getFirstForwardedValue(request.headers.get(\"x-forwarded-proto\"));\n\n if (forwardedHost && forwardedProto) {\n return `${forwardedProto}://${forwardedHost}`;\n }\n\n return null;\n}\n\nfunction resolveDefaultRedirectUri(request: Request | URL | string, url: URL): string {\n if (!(request instanceof Request)) {\n return `${url.origin}${url.pathname}`;\n }\n\n const forwardedOrigin = getForwardedOrigin(request);\n if (forwardedOrigin) {\n return `${forwardedOrigin}${url.pathname}`;\n }\n\n const hostHeader = request.headers.get(\"host\")?.trim();\n if (hostHeader && !isInternalHostname(stripPort(hostHeader))) {\n return `${url.protocol}//${hostHeader}${url.pathname}`;\n }\n\n if (!isInternalHostname(url.hostname)) {\n return `${url.origin}${url.pathname}`;\n }\n\n return `${url.origin}${url.pathname}`;\n}\n\n/**\n * Server-side authentication methods.\n *\n * Access via `buildspace.auth` on the server SDK.\n *\n * @example\n * ```ts\n * import Buildspace from \"@buildspacestudio/sdk\";\n *\n * const buildspace = new Buildspace(process.env.BUILDSPACE_SECRET_KEY!);\n *\n * // Handle OAuth callback\n * const tokens = await buildspace.auth.handleCallback(request);\n *\n * // Verify a session\n * const session = await buildspace.auth.getSession(sessionToken);\n *\n * // Sign out\n * await buildspace.auth.signOut(sessionToken);\n * ```\n */\nexport class AuthServerNamespace {\n private readonly transport: HttpTransport;\n\n constructor(transport: HttpTransport) {\n this.transport = transport;\n }\n\n /**\n * Retrieve the session associated with a token.\n *\n * Returns the {@link AuthSession} if valid, or `null` if the token is\n * expired, revoked, or invalid (401/404).\n *\n * @throws {BuildspaceError} On unexpected server errors (5xx, network issues).\n */\n async getSession(sessionToken: string): Promise<AuthSession | null> {\n try {\n return await this.transport.request<AuthSession>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n } catch (error) {\n if (error instanceof BuildspaceError && (error.status === 401 || error.status === 404)) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Exchange an OAuth authorization code for tokens.\n *\n * Extracts the `code` query parameter from the callback URL and exchanges\n * it with the Buildspace API for an access token and user info.\n *\n * @param request - The incoming callback request. Accepts a `Request` object,\n * a `URL`, or a raw URL string containing the `?code=` parameter.\n * @param opts - Optional settings.\n * @param opts.redirectUri - Override the redirect URI sent to the token endpoint.\n * Defaults to the origin + pathname of the callback URL.\n * @returns The token response containing `access_token`, `expires_in`, and `user`.\n *\n * @throws {BuildspaceError} If the code exchange fails (invalid code, expired, etc.).\n *\n * @example\n * ```ts\n * // Next.js Route Handler\n * export async function GET(request: Request) {\n * const { access_token, user } = await buildspace.auth.handleCallback(request);\n * // Store access_token as a session cookie\n * }\n * ```\n */\n handleCallback(\n request: Request | URL | string,\n opts?: { redirectUri?: string }\n ): Promise<TokenResponse> {\n let url: URL;\n if (typeof request === \"string\") {\n url = new URL(request);\n } else if (request instanceof URL) {\n url = request;\n } else {\n url = new URL(request.url);\n }\n\n const code = url.searchParams.get(\"code\");\n if (!code) {\n throw new BuildspaceError({\n service: \"auth\",\n status: 400,\n code: \"auth/missing-code\",\n message: \"No auth code found in callback URL. Expected ?code= parameter.\",\n });\n }\n\n const redirectUri = opts?.redirectUri ?? resolveDefaultRedirectUri(request, url);\n\n return this.transport.request<TokenResponse>({\n service: \"auth\",\n path: \"/v1/auth/token\",\n method: \"POST\",\n body: {\n code,\n redirect_uri: redirectUri,\n },\n });\n }\n\n /**\n * Revoke a specific session token.\n *\n * @param sessionToken - The token to revoke.\n * @throws {BuildspaceError} If the revocation fails.\n */\n async revokeSession(sessionToken: string): Promise<void> {\n await this.transport.request<void>({\n service: \"auth\",\n path: \"/v1/auth/session\",\n method: \"DELETE\",\n headers: { \"X-Session-Token\": sessionToken },\n });\n }\n\n /**\n * Sign the user out by revoking the session and clearing the SDK's stored token.\n *\n * If the session is already expired or not found, the error is silently\n * ignored and the local session is still cleared.\n *\n * @param sessionToken - Token to revoke. If omitted, uses the token\n * previously set via `buildspace.setSession()`.\n */\n async signOut(sessionToken?: string): Promise<void> {\n const token = sessionToken ?? this.transport.getSessionToken();\n\n try {\n if (token) {\n await this.revokeSession(token);\n }\n } catch (error) {\n if (\n !(\n error instanceof BuildspaceError &&\n error.service === \"auth\" &&\n (error.status === 401 || error.status === 404)\n )\n ) {\n throw error;\n }\n } finally {\n this.transport.clearSession();\n }\n }\n}\n"]}