@nhost/nhost-js
Version:
Nhost JavaScript SDK
1 lines • 23.3 kB
Source Map (JSON)
{"version":3,"file":"nhost-js.cjs","names":[],"sources":["../src/nhost.ts","../src/index.ts"],"sourcesContent":["import { generateServiceUrl } from './';\nimport {\n type Client as AuthClient,\n createAPIClient as createAuthClient,\n} from './auth';\nimport {\n type AdminSessionOptions,\n attachAccessTokenMiddleware,\n type ChainFunction,\n sessionRefreshMiddleware,\n updateSessionFromResponseMiddleware,\n withAdminSessionMiddleware,\n} from './fetch';\nimport {\n createAPIClient as createFunctionsClient,\n type Client as FunctionsClient,\n} from './functions';\nimport {\n createAPIClient as createGraphQLClient,\n type Client as GraphQLClient,\n} from './graphql';\nimport {\n detectStorage,\n refreshSession,\n SessionStorage,\n type SessionStorageBackend,\n type StoredSession,\n} from './session/';\nimport {\n createAPIClient as createStorageClient,\n type Client as StorageClient,\n} from './storage';\n\n/**\n * Configuration function that receives all clients and can configure them\n * (e.g., by attaching middleware, setting up interceptors, etc.)\n */\nexport type ClientConfigurationFn = (clients: {\n auth: AuthClient;\n storage: StorageClient;\n graphql: GraphQLClient;\n functions: FunctionsClient;\n sessionStorage: SessionStorage;\n}) => void;\n\n/**\n * Built-in configuration for client-side applications.\n * Includes automatic session refresh, token attachment, and session updates.\n */\nexport const withClientSideSessionMiddleware: ClientConfigurationFn = ({\n auth,\n storage,\n graphql,\n functions,\n sessionStorage,\n}) => {\n const mwChain: ChainFunction[] = [\n sessionRefreshMiddleware(auth, sessionStorage),\n updateSessionFromResponseMiddleware(sessionStorage),\n attachAccessTokenMiddleware(sessionStorage),\n ];\n\n for (const mw of mwChain) {\n auth.pushChainFunction(mw);\n storage.pushChainFunction(mw);\n graphql.pushChainFunction(mw);\n functions.pushChainFunction(mw);\n }\n};\n\n/**\n * Built-in configuration for server-side applications.\n * Includes token attachment and session updates, but NOT automatic session refresh\n * to prevent race conditions in server contexts.\n */\nexport const withServerSideSessionMiddleware: ClientConfigurationFn = ({\n auth,\n storage,\n graphql,\n functions,\n sessionStorage,\n}) => {\n const mwChain: ChainFunction[] = [\n updateSessionFromResponseMiddleware(sessionStorage),\n attachAccessTokenMiddleware(sessionStorage),\n ];\n\n for (const mw of mwChain) {\n auth.pushChainFunction(mw);\n storage.pushChainFunction(mw);\n graphql.pushChainFunction(mw);\n functions.pushChainFunction(mw);\n }\n};\n\n/**\n * Configuration for admin clients with elevated privileges.\n * Applies admin session middleware to storage, graphql, and functions clients only.\n *\n * **Security Warning**: Never use this in client-side code. Admin secrets grant\n * unrestricted access to your entire database.\n *\n * @param adminSession - Admin session options including admin secret, role, and session variables\n * @returns Configuration function that sets up admin middleware\n */\nexport function withAdminSession(\n adminSession: AdminSessionOptions,\n): ClientConfigurationFn {\n return ({ storage, graphql, functions }) => {\n const adminMiddleware = withAdminSessionMiddleware(adminSession);\n\n storage.pushChainFunction(adminMiddleware);\n graphql.pushChainFunction(adminMiddleware);\n functions.pushChainFunction(adminMiddleware);\n };\n}\n\n/**\n * Configuration for adding custom chain functions to all clients.\n * Useful for adding custom middleware like logging, caching, or custom headers.\n *\n * @param chainFunctions - Array of chain functions to apply to all clients\n * @returns Configuration function that sets up custom middleware\n */\nexport function withChainFunctions(\n chainFunctions: ChainFunction[],\n): ClientConfigurationFn {\n return ({ auth, storage, graphql, functions }) => {\n for (const mw of chainFunctions) {\n auth.pushChainFunction(mw);\n storage.pushChainFunction(mw);\n graphql.pushChainFunction(mw);\n functions.pushChainFunction(mw);\n }\n };\n}\n\n/**\n * Main client class that provides unified access to all Nhost services.\n * This class serves as the central interface for interacting with Nhost's\n * authentication, storage, GraphQL, and serverless functions capabilities.\n */\nexport class NhostClient {\n /**\n * Authentication client providing methods for user sign-in, sign-up, and session management.\n * Use this client to handle all authentication-related operations.\n */\n auth: AuthClient;\n\n /**\n * Storage client providing methods for file operations (upload, download, delete).\n * Use this client to manage files in your Nhost storage.\n */\n storage: StorageClient;\n\n /**\n * GraphQL client providing methods for executing GraphQL operations against your Hasura backend.\n * Use this client to query and mutate data in your database through GraphQL.\n */\n graphql: GraphQLClient;\n\n /**\n * Functions client providing methods for invoking serverless functions.\n * Use this client to call your custom serverless functions deployed to Nhost.\n */\n functions: FunctionsClient;\n\n /**\n * Storage implementation used for persisting session information.\n * This handles saving, retrieving, and managing authentication sessions across requests.\n */\n sessionStorage: SessionStorage;\n\n /**\n * Create a new Nhost client. This constructor is reserved for advanced use cases.\n * For typical usage, use [createClient](#createclient) or [createServerClient](#createserverclient) instead.\n *\n * @param auth - Authentication client instance\n * @param storage - Storage client instance\n * @param graphql - GraphQL client instance\n * @param functions - Functions client instance\n * @param sessionStorage - Storage implementation for session persistence\n */\n constructor(\n auth: AuthClient,\n storage: StorageClient,\n graphql: GraphQLClient,\n functions: FunctionsClient,\n sessionStorage: SessionStorage,\n ) {\n this.auth = auth;\n this.storage = storage;\n this.graphql = graphql;\n this.functions = functions;\n this.sessionStorage = sessionStorage;\n }\n\n /**\n * Get the current session from storage.\n * This method retrieves the authenticated user's session information if one exists.\n *\n * @returns The current session or null if no session exists\n *\n * @example\n * ```ts\n * const session = nhost.getUserSession();\n * if (session) {\n * console.log('User is authenticated:', session.user.id);\n * } else {\n * console.log('No active session');\n * }\n * ```\n */\n getUserSession(): StoredSession | null {\n return this.sessionStorage.get();\n }\n\n /**\n * Refresh the session using the current refresh token\n * in the storage and update the storage with the new session.\n *\n * This method can be used to proactively refresh tokens before they expire\n * or to force a refresh when needed.\n *\n * @param marginSeconds - The number of seconds before the token expiration to refresh the session. If the token is still valid for this duration, it will not be refreshed. Set to 0 to force the refresh.\n *\n * @returns The new session or null if there is currently no session or if refresh fails\n *\n * @example\n * ```ts\n * // Refresh token if it's about to expire in the next 5 minutes\n * const refreshedSession = await nhost.refreshSession(300);\n *\n * // Force refresh regardless of current token expiration\n * const forcedRefresh = await nhost.refreshSession(0);\n * ```\n */\n async refreshSession(marginSeconds = 60): Promise<StoredSession | null> {\n return refreshSession(this.auth, this.sessionStorage, marginSeconds);\n }\n\n /**\n * Clear the session from storage.\n *\n * This method removes the current authentication session, effectively logging out the user.\n * Note that this is a client-side operation and doesn't invalidate the refresh token on\n * the server, which can be done with `nhost.auth.signOut({refreshToken: session.refreshTokenId})`.\n * If the middle `updateSessionFromResponseMiddleware` is used, the session will be removed\n * from the storage automatically and calling this method is not necessary.\n *\n * @example\n * ```ts\n * // Log out the user\n * nhost.clearSession();\n * ```\n */\n clearSession(): void {\n this.sessionStorage.remove();\n }\n}\n\n/**\n * Configuration options for creating an Nhost client\n */\nexport interface NhostClientOptions {\n /**\n * Nhost project subdomain (e.g., 'abcdefgh'). Used to construct the base URL for services for the Nhost cloud.\n */\n subdomain?: string;\n\n /**\n * Nhost region (e.g., 'eu-central-1'). Used to construct the base URL for services for the Nhost cloud.\n */\n region?: string;\n\n /**\n * Complete base URL for the auth service (overrides subdomain/region)\n */\n authUrl?: string;\n\n /**\n * Complete base URL for the storage service (overrides subdomain/region)\n */\n storageUrl?: string;\n\n /**\n * Complete base URL for the GraphQL service (overrides subdomain/region)\n */\n graphqlUrl?: string;\n\n /**\n * Complete base URL for the functions service (overrides subdomain/region)\n */\n functionsUrl?: string;\n\n /**\n * Storage backend to use for session persistence. If not provided, the SDK will\n * default to localStorage in the browser or memory in other environments.\n */\n storage?: SessionStorageBackend;\n\n /**\n * Configuration functions to be applied to the client after initialization.\n * These functions receive all clients and can attach middleware or perform other setup.\n */\n configure?: ClientConfigurationFn[];\n}\n\n/**\n * Creates and configures a new Nhost client instance with custom configuration.\n *\n * This is the main factory function for creating Nhost clients. It instantiates\n * all service clients (auth, storage, graphql, functions) and applies the provided\n * configuration functions to set up middleware and other customizations.\n *\n * @param options - Configuration options for the client\n * @returns A configured Nhost client\n *\n * @example\n * ```ts\n * // Create a basic client with no middleware\n * const nhost = createNhostClient({\n * subdomain: 'abcdefgh',\n * region: 'eu-central-1',\n * configure: []\n * });\n *\n * // Create a client with custom configuration\n * const nhost = createNhostClient({\n * subdomain: 'abcdefgh',\n * region: 'eu-central-1',\n * configure: [\n * withClientSideSessionMiddleware,\n * withChainFunctions([customLoggingMiddleware])\n * ]\n * });\n *\n * // Create an admin client\n * const nhost = createNhostClient({\n * subdomain,\n * region,\n * configure: [\n * withAdminSession({\n * adminSecret: \"nhost-admin-secret\",\n * role: \"user\",\n * sessionVariables: {\n * \"user-id\": \"54058C42-51F7-4B37-8B69-C89A841D2221\",\n * },\n * }),\n * ],\n * });\n\n * ```\n */\nexport function createNhostClient(\n options: NhostClientOptions = {},\n): NhostClient {\n const {\n subdomain,\n region,\n authUrl,\n storageUrl,\n graphqlUrl,\n functionsUrl,\n storage = detectStorage(),\n configure = [],\n } = options;\n\n const sessionStorage = new SessionStorage(storage);\n\n // Determine base URLs for each service\n const authBaseUrl = generateServiceUrl('auth', subdomain, region, authUrl);\n const storageBaseUrl = generateServiceUrl(\n 'storage',\n subdomain,\n region,\n storageUrl,\n );\n const graphqlBaseUrl = generateServiceUrl(\n 'graphql',\n subdomain,\n region,\n graphqlUrl,\n );\n const functionsBaseUrl = generateServiceUrl(\n 'functions',\n subdomain,\n region,\n functionsUrl,\n );\n\n // Create all clients\n const auth = createAuthClient(authBaseUrl);\n const storageClient = createStorageClient(storageBaseUrl, []);\n const graphqlClient = createGraphQLClient(graphqlBaseUrl, []);\n const functionsClient = createFunctionsClient(functionsBaseUrl, []);\n\n // Apply configuration functions\n for (const configFn of configure) {\n configFn({\n auth,\n storage: storageClient,\n graphql: graphqlClient,\n functions: functionsClient,\n sessionStorage,\n });\n }\n\n // Return an initialized NhostClient\n return new NhostClient(\n auth,\n storageClient,\n graphqlClient,\n functionsClient,\n sessionStorage,\n );\n}\n\n/**\n * Creates and configures a new Nhost client instance optimized for client-side usage.\n *\n * This helper method instantiates a fully configured Nhost client by:\n * - Instantiating the various service clients (auth, storage, functions and graphql)\n * - Auto-detecting and configuring an appropriate session storage (localStorage in browsers, memory otherwise)\n * - Setting up a sophisticated middleware chain for seamless authentication management:\n * - Automatically refreshing tokens before they expire\n * - Attaching authorization tokens to all service requests\n * - Updating the session storage when new tokens are received\n *\n * This method includes automatic session refresh middleware, making it ideal for\n * client-side applications where long-lived sessions are expected.\n *\n * @param options - Configuration options for the client\n * @returns A configured Nhost client\n *\n * @example\n * ```ts\n * // Create client using Nhost cloud default URLs\n * const nhost = createClient({\n * subdomain: 'abcdefgh',\n * region: 'eu-central-1'\n * });\n *\n * // Create client with custom service URLs\n * const customNhost = createClient({\n * authUrl: 'https://auth.example.com',\n * storageUrl: 'https://storage.example.com',\n * graphqlUrl: 'https://graphql.example.com',\n * functionsUrl: 'https://functions.example.com'\n * });\n *\n * // Create client using cookies for storing the session\n * import { CookieStorage } from \"@nhost/nhost-js/session\";\n *\n * const nhost = createClient({\n * subdomain: 'abcdefgh',\n * region: 'eu-central-1',\n * storage: new CookieStorage({\n * secure: import.meta.env.ENVIRONMENT === 'production',\n * })\n * });\n *\n * // Create client with additional custom middleware\n * const nhost = createClient({\n * subdomain: 'abcdefgh',\n * region: 'eu-central-1',\n * configure: [customLoggingMiddleware]\n * });\n * ```\n */\nexport function createClient(options: NhostClientOptions = {}): NhostClient {\n const storage = options.storage ?? detectStorage();\n\n return createNhostClient({\n ...options,\n storage,\n configure: [withClientSideSessionMiddleware, ...(options.configure ?? [])],\n });\n}\n\nexport interface NhostServerClientOptions extends NhostClientOptions {\n /**\n * Storage backend to use for session persistence in server environments.\n * Unlike the base options, this field is required for server-side usage\n * as the SDK cannot auto-detect an appropriate storage mechanism.\n */\n storage: SessionStorageBackend;\n}\n\n/**\n * Creates and configures a new Nhost client instance optimized for server-side usage.\n *\n * This helper method instantiates a fully configured Nhost client specifically designed for:\n * - Server components (in frameworks like Next.js or Remix)\n * - API routes and middleware\n * - Backend services and server-side rendering contexts\n *\n * Key differences from the standard client:\n * - Requires explicit storage implementation (must be provided)\n * - Disables automatic session refresh middleware (to prevent race conditions in server contexts)\n * - Still attaches authorization tokens and updates session storage from responses\n *\n * The server client is ideal for short-lived request contexts where session tokens\n * are passed in (like cookie-based authentication flows) and automatic refresh\n * mechanisms could cause issues with concurrent requests.\n *\n * @param options - Configuration options for the server client (requires storage implementation)\n * @returns A configured Nhost client optimized for server-side usage\n *\n * @example\n * ```ts\n * // Example with cookie storage for Next.js API route or server component\n * import { cookies } from 'next/headers';\n *\n * const nhost = createServerClient({\n * region: process.env[\"NHOST_REGION\"] || \"local\",\n * subdomain: process.env[\"NHOST_SUBDOMAIN\"] || \"local\",\n * storage: {\n * // storage compatible with Next.js server components\n * get: (): StoredSession | null => {\n * const s = cookieStore.get(key)?.value || null;\n * if (!s) {\n * return null;\n * }\n * const session = JSON.parse(s) as StoredSession;\n * return session;\n * },\n * set: (value: StoredSession) => {\n * cookieStore.set(key, JSON.stringify(value));\n * },\n * remove: () => {\n * cookieStore.delete(key);\n * },\n * },\n * });\n *\n * // Example with cookie storage for Next.js middleware\n * const nhost = createServerClient({\n * region: process.env[\"NHOST_REGION\"] || \"local\",\n * subdomain: process.env[\"NHOST_SUBDOMAIN\"] || \"local\",\n * storage: {\n * // storage compatible with Next.js middleware\n * get: (): StoredSession | null => {\n * const raw = request.cookies.get(key)?.value || null;\n * if (!raw) {\n * return null;\n * }\n * const session = JSON.parse(raw) as StoredSession;\n * return session;\n * },\n * set: (value: StoredSession) => {\n * response.cookies.set({\n * name: key,\n * value: JSON.stringify(value),\n * path: \"/\",\n * httpOnly: false, //if set to true we can't access it in the client\n * secure: process.env.NODE_ENV === \"production\",\n * sameSite: \"lax\",\n * maxAge: 60 * 60 * 24 * 30, // 30 days in seconds\n * });\n * },\n * remove: () => {\n * response.cookies.delete(key);\n * },\n * },\n * });\n *\n * // Example for express reading session from a cookie\n *\n * import express, { Request, Response } from \"express\";\n * import cookieParser from \"cookie-parser\";\n *\n * app.use(cookieParser());\n *\n * const nhostClientFromCookies = (req: Request) => {\n * return createServerClient({\n * subdomain: \"local\",\n * region: \"local\",\n * storage: {\n * get: (): StoredSession | null => {\n * const s = req.cookies.nhostSession || null;\n * if (!s) {\n * return null;\n * }\n * const session = JSON.parse(s) as StoredSession;\n * return session;\n * },\n * set: (_value: StoredSession) => {\n * throw new Error(\"It is easier to handle the session in the client\");\n * },\n * remove: () => {\n * throw new Error(\"It is easier to handle the session in the client\");\n * },\n * },\n * });\n * };\n *\n * // Example with additional custom middleware\n * const nhost = createServerClient({\n * region: process.env[\"NHOST_REGION\"] || \"local\",\n * subdomain: process.env[\"NHOST_SUBDOMAIN\"] || \"local\",\n * storage: myStorage,\n * configure: [customLoggingMiddleware]\n * });\n * ```\n */\nexport function createServerClient(\n options: NhostServerClientOptions,\n): NhostClient {\n return createNhostClient({\n ...options,\n configure: [withServerSideSessionMiddleware, ...(options.configure ?? [])],\n });\n}\n","/**\n * Main entry point for the Nhost JavaScript SDK.\n *\n * This package provides a unified client for interacting with Nhost services:\n * - Authentication\n * - Storage\n * - GraphQL\n * - Functions\n *\n * ## Import\n *\n * ```ts\n * import { createClient } from \"@nhost/nhost-js\";\n * ```\n *\n * ## Usage\n *\n * Create a client instance to interact with Nhost services:\n *\n * {@includeCode ./__tests__/docstrings.test.ts:15-119}\n *\n * ### Creating an admin client\n *\n * You can also create an admin client if needed. This client will have admin access to the database\n * and will bypass permissions. Additionally, it can impersonate users and set any role or session\n * variable.\n *\n * IMPORTANT!!! Keep your admin secret safe and never expose it in client-side code.\n *\n * {@includeCode ./__tests__/docstrings.test.ts:142-201}\n *\n * @packageDocumentation\n */\n\nexport {\n type ClientConfigurationFn,\n createClient,\n createNhostClient,\n createServerClient,\n type NhostClient,\n type NhostClientOptions,\n type NhostServerClientOptions,\n withAdminSession,\n withClientSideSessionMiddleware,\n withServerSideSessionMiddleware,\n} from './nhost';\nexport type { StoredSession } from './session';\n\n/**\n * Generates a base URL for a Nhost service based on configuration\n *\n * @param serviceType - Type of service (auth, storage, graphql, functions)\n * @param subdomain - Nhost project subdomain\n * @param region - Nhost region\n * @param customUrl - Custom URL override if provided\n * @returns The base URL for the service\n */\nexport const generateServiceUrl = (\n serviceType: 'auth' | 'storage' | 'graphql' | 'functions',\n subdomain?: string,\n region?: string,\n customUrl?: string,\n): string => {\n if (customUrl) {\n return customUrl;\n } else if (subdomain && region) {\n return `https://${subdomain}.${serviceType}.${region}.nhost.run/v1`;\n } else {\n return `https://local.${serviceType}.local.nhost.run/v1`;\n }\n};\n"],"mappings":"yUAiDA,IAAa,EAAA,EACX,OACA,UACA,UACA,YACA,qBAEA,MAAM,EAA2B,CAC/B,EAAA,yBAAyB,EAAM,GAC/B,EAAA,oCAAoC,GACpC,EAAA,4BAA4B,IAG9B,IAAK,MAAM,KAAM,EACf,EAAK,kBAAkB,GACvB,EAAQ,kBAAkB,GAC1B,EAAQ,kBAAkB,GAC1B,EAAU,kBAAkB,EAC9B,EAQW,EAAA,EACX,OACA,UACA,UACA,YACA,qBAEA,MAAM,EAA2B,CAC/B,EAAA,oCAAoC,GACpC,EAAA,4BAA4B,IAG9B,IAAK,MAAM,KAAM,EACf,EAAK,kBAAkB,GACvB,EAAQ,kBAAkB,GAC1B,EAAQ,kBAAkB,GAC1B,EAAU,kBAAkB,EAC9B,EAkDF,IAAa,EAAb,MAKE,KAMA,QAMA,QAMA,UAMA,eAYA,WAAA,CACE,EACA,EACA,EACA,EACA,GAEA,KAAK,KAAO,EACZ,KAAK,QAAU,EACf,KAAK,QAAU,EACf,KAAK,UAAY,EACjB,KAAK,eAAiB,CACxB,CAkBA,cAAA,GACE,OAAO,KAAK,eAAe,KAC7B,CAsBA,oBAAM,CAAe,EAAgB,IACnC,OAAO,EAAA,eAAe,KAAK,KAAM,KAAK,eAAgB,EACxD,CAiBA,YAAA,GACE,KAAK,eAAe,QACtB,GAgGF,SAAgB,EACd,EAA8B,CAAC,GAE/B,MAAM,UACJ,EAAA,OACA,EAAA,QACA,EAAA,WACA,EAAA,WACA,EAAA,aACA,EAAA,QACA,EAAU,EAAA,gBAAc,UACxB,EAAY,IACV,EAEE,EAAiB,IAAI,EAAA,eAAe,GAGpC,EAAc,EAAmB,OAAQ,EAAW,EAAQ,GAC5D,EAAiB,EACrB,UACA,EACA,EACA,GAEI,EAAiB,EACrB,UACA,EACA,EACA,GAEI,EAAmB,EACvB,YACA,EACA,EACA,GAII,EAAO,EAAA,gBAAiB,GACxB,EAAgB,EAAA,gBAAoB,EAAgB,IACpD,EAAgB,EAAA,gBAAoB,EAAgB,IACpD,EAAkB,EAAA,gBAAsB,EAAkB,IAGhE,IAAK,MAAM,KAAY,EACrB,EAAS,CACP,OACA,QAAS,EACT,QAAS,EACT,UAAW,EACX,mBAKJ,OAAO,IAAI,EACT,EACA,EACA,EACA,EACA,EAEJ,CCvWA,IAAa,EAAA,CACX,EACA,EACA,EACA,IAEI,IAEO,GAAa,EACf,WAAW,KAAa,KAAe,iBAEvC,iBAAiB,6CDkZ5B,SAA6B,EAA8B,CAAC,GAC1D,MAAM,EAAU,EAAQ,SAAW,EAAA,gBAEnC,OAAO,EAAkB,IACpB,EACH,UACA,UAAW,CAAC,KAAqC,EAAQ,WAAa,KAE1E,yDAgIA,SACE,GAEA,OAAO,EAAkB,IACpB,EACH,UAAW,CAAC,KAAqC,EAAQ,WAAa,KAE1E,wDA5fA,SACE,GAEA,MAAA,EAAU,UAAS,UAAS,gBAC1B,MAAM,EAAkB,EAAA,2BAA2B,GAEnD,EAAQ,kBAAkB,GAC1B,EAAQ,kBAAkB,GAC1B,EAAU,kBAAkB,EAAe,CAE/C"}