@nhost/nhost-js 5.0.0-beta.9 → 5.0.0-beta10

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 (93) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +20 -20
  3. package/dist/fetch-2PHmQBIJ.mjs.map +1 -1
  4. package/dist/fetch-DWXwEnoe.js.map +1 -1
  5. package/dist/nhost-js/auth.cjs.js +1 -1
  6. package/dist/nhost-js/auth.cjs.js.map +1 -1
  7. package/dist/nhost-js/auth.es.js +38 -38
  8. package/dist/nhost-js/auth.es.js.map +1 -1
  9. package/dist/nhost-js/fetch.cjs.js +1 -1
  10. package/dist/nhost-js/fetch.cjs.js.map +1 -1
  11. package/dist/nhost-js/fetch.es.js +3 -3
  12. package/dist/nhost-js/fetch.es.js.map +1 -1
  13. package/dist/nhost-js/functions.cjs.js.map +1 -1
  14. package/dist/nhost-js/functions.es.js.map +1 -1
  15. package/dist/nhost-js/graphql.cjs.js.map +1 -1
  16. package/dist/nhost-js/graphql.es.js.map +1 -1
  17. package/dist/nhost-js/session.cjs.js +1 -1
  18. package/dist/nhost-js/session.cjs.js.map +1 -1
  19. package/dist/nhost-js/session.es.js +1 -1
  20. package/dist/nhost-js/session.es.js.map +1 -1
  21. package/dist/nhost-js/storage.cjs.js +1 -1
  22. package/dist/nhost-js/storage.cjs.js.map +1 -1
  23. package/dist/nhost-js/storage.es.js +19 -17
  24. package/dist/nhost-js/storage.es.js.map +1 -1
  25. package/dist/nhost-js.cjs.js +1 -1
  26. package/dist/nhost-js.cjs.js.map +1 -1
  27. package/dist/nhost-js.es.js +4 -4
  28. package/dist/nhost-js.es.js.map +1 -1
  29. package/dist/nhost-js.umd.js +1 -1
  30. package/dist/nhost-js.umd.js.map +1 -1
  31. package/dist/refreshSession-Bw715ZmX.js +2 -0
  32. package/dist/refreshSession-Bw715ZmX.js.map +1 -0
  33. package/dist/{refreshSession-cGdPdFoG.mjs → refreshSession-WwGlzgtM.mjs} +9 -5
  34. package/dist/refreshSession-WwGlzgtM.mjs.map +1 -0
  35. package/dist/src/auth/client.d.ts.map +1 -1
  36. package/dist/src/auth/client.js +41 -41
  37. package/dist/src/auth/client.js.map +1 -1
  38. package/dist/src/fetch/fetch.d.ts +1 -1
  39. package/dist/src/fetch/fetch.d.ts.map +1 -1
  40. package/dist/src/fetch/fetch.js +0 -1
  41. package/dist/src/fetch/fetch.js.map +1 -1
  42. package/dist/src/fetch/index.d.ts +1 -1
  43. package/dist/src/fetch/index.d.ts.map +1 -1
  44. package/dist/src/fetch/index.js +1 -1
  45. package/dist/src/fetch/index.js.map +1 -1
  46. package/dist/src/fetch/middlewareSessionRefresh.d.ts +1 -1
  47. package/dist/src/fetch/middlewareSessionRefresh.d.ts.map +1 -1
  48. package/dist/src/fetch/middlewareSessionRefresh.js.map +1 -1
  49. package/dist/src/fetch/middlewareUpdateSessionFromResponse.js +2 -2
  50. package/dist/src/fetch/middlewareUpdateSessionFromResponse.js.map +1 -1
  51. package/dist/src/functions/client.d.ts +2 -2
  52. package/dist/src/functions/client.d.ts.map +1 -1
  53. package/dist/src/functions/client.js +0 -2
  54. package/dist/src/functions/client.js.map +1 -1
  55. package/dist/src/graphql/client.d.ts +4 -4
  56. package/dist/src/graphql/client.d.ts.map +1 -1
  57. package/dist/src/graphql/client.js.map +1 -1
  58. package/dist/src/graphql/index.d.ts +13 -5
  59. package/dist/src/graphql/index.d.ts.map +1 -1
  60. package/dist/src/graphql/index.js +13 -5
  61. package/dist/src/graphql/index.js.map +1 -1
  62. package/dist/src/index.d.ts +1 -1
  63. package/dist/src/index.d.ts.map +1 -1
  64. package/dist/src/index.js.map +1 -1
  65. package/dist/src/nhost.d.ts +3 -3
  66. package/dist/src/nhost.d.ts.map +1 -1
  67. package/dist/src/nhost.js +5 -5
  68. package/dist/src/nhost.js.map +1 -1
  69. package/dist/src/session/index.d.ts +3 -3
  70. package/dist/src/session/index.d.ts.map +1 -1
  71. package/dist/src/session/index.js +2 -2
  72. package/dist/src/session/index.js.map +1 -1
  73. package/dist/src/session/refreshSession.d.ts +4 -4
  74. package/dist/src/session/refreshSession.d.ts.map +1 -1
  75. package/dist/src/session/refreshSession.js +10 -11
  76. package/dist/src/session/refreshSession.js.map +1 -1
  77. package/dist/src/session/storage.d.ts +2 -2
  78. package/dist/src/session/storage.d.ts.map +1 -1
  79. package/dist/src/session/storage.js +1 -1
  80. package/dist/src/session/storage.js.map +1 -1
  81. package/dist/src/session/storageBackend.d.ts.map +1 -1
  82. package/dist/src/session/storageBackend.js +2 -0
  83. package/dist/src/session/storageBackend.js.map +1 -1
  84. package/dist/src/storage/client.d.ts.map +1 -1
  85. package/dist/src/storage/client.js +21 -17
  86. package/dist/src/storage/client.js.map +1 -1
  87. package/dist/src/storage/index.d.ts +2 -2
  88. package/dist/src/storage/index.js +2 -2
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +17 -17
  91. package/dist/refreshSession-bgb-tiu4.js +0 -2
  92. package/dist/refreshSession-bgb-tiu4.js.map +0 -1
  93. package/dist/refreshSession-cGdPdFoG.mjs.map +0 -1
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../fetch-DWXwEnoe.js"),n=require("../refreshSession-bgb-tiu4.js");function r(e,n){return n.accessToken&&e.set("Authorization",`Bearer ${n.accessToken}`),e}exports.FetchError=e.FetchError,exports.createEnhancedFetch=e.createEnhancedFetch,exports.attachAccessTokenMiddleware=e=>n=>async(s,t={})=>{const o=new Headers(t.headers||{});if(o.has("Authorization"))return n(s,t);const i=e.get();if(i?.accessToken){const e={...t,headers:r(o,i)};return n(s,e)}return n(s,t)},exports.sessionRefreshMiddleware=(e,r,s)=>{const{marginSeconds:t=60}=s||{};return s=>async(o,i={})=>{if(function(e,n){const r=new Headers(n.headers||{});if(r.has("Authorization"))return!0;if(e.endsWith("/v1/token"))return!0;return!1}(o,i))return s(o,i);try{await n.refreshSession(e,r,t)}catch{}return s(o,i)}},exports.updateSessionFromResponseMiddleware=e=>n=>async(r,s)=>{const t=await n(r,s);try{if(r.endsWith("/signout"))return e.remove(),t;if(r.endsWith("/token")||r.includes("/signin/")||r.includes("/signup/")){const n=t.clone(),r=await n.json().catch((()=>null));if(r){const n=function(e){return"string"==typeof e?null:"session"in e?e.session||null:"accessToken"in e&&"refreshToken"in e?e:null}(r);n&&n.accessToken&&n.refreshToken&&e.set(n)}}}catch(o){console.warn("Error in session response middleware:",o)}return t};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../fetch-DWXwEnoe.js"),n=require("../refreshSession-Bw715ZmX.js");function s(e,n){return n.accessToken&&e.set("Authorization",`Bearer ${n.accessToken}`),e}exports.FetchError=e.FetchError,exports.createEnhancedFetch=e.createEnhancedFetch,exports.attachAccessTokenMiddleware=e=>n=>async(r,t={})=>{const o=new Headers(t.headers||{});if(o.has("Authorization"))return n(r,t);const i=e.get();if(i?.accessToken){const e={...t,headers:s(o,i)};return n(r,e)}return n(r,t)},exports.sessionRefreshMiddleware=(e,s,r)=>{const{marginSeconds:t=60}=r||{};return r=>async(o,i={})=>{if(function(e,n){const s=new Headers(n.headers||{});if(s.has("Authorization"))return!0;if(e.endsWith("/v1/token"))return!0;return!1}(o,i))return r(o,i);try{await n.refreshSession(e,s,t)}catch{}return r(o,i)}},exports.updateSessionFromResponseMiddleware=e=>n=>async(s,r)=>{const t=await n(s,r);try{if(s.endsWith("/signout"))return e.remove(),t;if(s.endsWith("/token")||s.includes("/signin/")||s.includes("/signup/")){const n=t.clone(),s=await n.json().catch((()=>null));if(s){const n=(e=>"string"==typeof e?null:"session"in e?e.session||null:"accessToken"in e&&"refreshToken"in e?e:null)(s);n?.accessToken&&n.refreshToken&&e.set(n)}}}catch(o){console.warn("Error in session response middleware:",o)}return t};
2
2
  //# sourceMappingURL=fetch.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.cjs.js","sources":["../../src/fetch/middlewareAttachAccessToken.ts","../../src/fetch/middlewareSessionRefresh.ts","../../src/fetch/middlewareUpdateSessionFromResponse.ts"],"sourcesContent":["/**\n * Authorization token attachment middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * authorization tokens to outgoing API requests, ensuring the client\n * is properly authenticated.\n */\n\nimport type { Session } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that adds the Authorization header with the current access token.\n *\n * This middleware:\n * 1. Gets the current session from storage\n * 2. Adds the authorization header with the access token to outgoing requests\n *\n * This middleware should be used after the refresh middleware in the chain to\n * ensure the most recent token is used.\n *\n * @param storage - Storage implementation for retrieving session data\n * @returns A middleware function that adds Authorization headers\n */\nexport const attachAccessTokenMiddleware =\n (storage: SessionStorage): ChainFunction =>\n (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n const headers = new Headers(options.headers || {});\n\n // Skip if Authorization header is already set\n if (headers.has(\"Authorization\")) {\n return next(url, options);\n }\n\n // Get current session from storage\n const session = storage.get();\n\n if (session?.accessToken) {\n // Add authorization header\n const newOptions = {\n ...options,\n headers: addAuthorizationHeader(headers, session),\n };\n\n // Continue with the fetch chain\n return next(url, newOptions);\n }\n\n // No session or no access token, continue without authorization\n return next(url, options);\n };\n\n/**\n * Adds the Authorization header with the access token to the request headers\n *\n * @param headers - Original request headers\n * @param session - Current session containing the access token\n * @returns Modified headers with Authorization header\n */\nfunction addAuthorizationHeader(headers: Headers, session: Session): Headers {\n if (session.accessToken) {\n headers.set(\"Authorization\", `Bearer ${session.accessToken}`);\n }\n return headers;\n}\n","/**\n * Auth token refresh middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically refresh\n * authentication tokens before they expire, ensuring seamless API access\n * without requiring manual token refresh by the application.\n */\n\nimport type { Client } from \"../auth\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\nimport type { SessionStorage } from \"../session/storage\";\nimport { refreshSession } from \"../session/refreshSession\";\n\n/**\n * Creates a fetch middleware that automatically refreshes authentication tokens.\n *\n * This middleware:\n * 1. Checks if the current token is about to expire\n * 2. If so, uses the refresh token to obtain a new access token\n *\n * The middleware handles token refresh transparently, so the application\n * doesn't need to manually refresh tokens.\n *\n * @param auth - Auth API client for token refresh operations\n * @param storage - Storage implementation for persisting session data\n * @param options - Configuration options for token refresh behavior\n * @param options.marginSeconds - Number of seconds before token expiration to trigger a refresh, default is 60 seconds\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const sessionRefreshMiddleware = (\n auth: Client,\n storage: SessionStorage,\n options?: {\n marginSeconds?: number;\n },\n): ChainFunction => {\n const { marginSeconds = 60 } = options || {};\n\n // Create and return the chain function\n return (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n // Skip token handling for certain requests\n if (shouldSkipTokenHandling(url, options)) {\n return next(url, options);\n }\n\n try {\n await refreshSession(auth, storage, marginSeconds);\n } catch {\n // do nothing, we still want to call the next function\n }\n return next(url, options);\n };\n};\n\n/**\n * Determines if token handling should be skipped for this request\n *\n * @param url - Request URL\n * @param options - Request options\n * @returns True if token handling should be skipped, false otherwise\n */\nfunction shouldSkipTokenHandling(url: string, options: RequestInit): boolean {\n const headers = new Headers(options.headers || {});\n\n // If Authorization header is explicitly set, skip token handling\n if (headers.has(\"Authorization\")) {\n return true;\n }\n\n // If calling the token endpoint, skip to avoid infinite loops\n if (url.endsWith(\"/v1/token\")) {\n return true;\n }\n\n return false;\n}\n","/**\n * Session response middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically extract\n * and persist session information from authentication responses, ensuring\n * that new sessions are properly stored after sign-in operations.\n */\n\nimport type { Session, SessionPayload } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically extracts and stores session data from API responses.\n *\n * This middleware:\n * 1. Monitors responses from authentication-related endpoints\n * 2. Extracts session information when present\n * 3. Stores the session in the provided storage implementation\n * 4. Handles session removal on sign-out\n *\n * This ensures that session data is always up-to-date in storage after operations\n * that create or invalidate sessions.\n *\n * @param storage - Storage implementation for persisting session data\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const updateSessionFromResponseMiddleware = (\n storage: SessionStorage,\n): ChainFunction => {\n /**\n * Helper function to extract session data from various response formats\n *\n * @param body - Response data to extract session from\n * @returns Session object if found, null otherwise\n */\n const sessionExtractor = function (\n body: Session | SessionPayload | string,\n ): Session | null {\n if (typeof body === \"string\") {\n return null;\n }\n\n if (\"session\" in body) {\n // SessionPayload\n return body.session || null;\n }\n\n if (\"accessToken\" in body && \"refreshToken\" in body) {\n // Session\n return body;\n }\n\n return null;\n };\n\n return (next: (url: string, options?: RequestInit) => Promise<Response>) =>\n async (url: string, options?: RequestInit) => {\n // Call the next middleware in the chain\n const response = await next(url, options);\n\n try {\n // Check if this is a logout request\n if (url.endsWith(\"/signout\")) {\n // Remove session on sign-out\n storage.remove();\n return response;\n }\n\n // Check if this is an auth-related endpoint that might return session data\n if (\n url.endsWith(\"/token\") ||\n url.includes(\"/signin/\") ||\n url.includes(\"/signup/\")\n ) {\n // Clone the response to avoid consuming it\n const clonedResponse = response.clone();\n\n // Parse the JSON data\n const body = (await clonedResponse.json().catch(() => null)) as\n | Session\n | SessionPayload;\n\n if (body) {\n // Extract session data from response using provided extractor\n const session = sessionExtractor(body);\n\n // If session data is found, store it\n if (session && session.accessToken && session.refreshToken) {\n storage.set(session);\n }\n }\n }\n } catch (error) {\n console.warn(\"Error in session response middleware:\", error);\n }\n\n // Return the original response\n return response;\n };\n};\n"],"names":["addAuthorizationHeader","headers","session","accessToken","set","storage","next","async","url","options","Headers","has","get","newOptions","auth","marginSeconds","endsWith","shouldSkipTokenHandling","refreshSession","response","remove","includes","clonedResponse","clone","body","json","catch","sessionExtractor","refreshToken","error","console","warn"],"mappings":"mKA6DA,SAASA,EAAuBC,EAAkBC,GAIzC,OAHHA,EAAQC,aACVF,EAAQG,IAAI,gBAAiB,UAAUF,EAAQC,eAE1CF,CACT,uHAxCGI,GACAC,GACDC,MAAOC,EAAaC,EAAuB,MACzC,MAAMR,EAAU,IAAIS,QAAQD,EAAQR,SAAW,CAAA,GAG3C,GAAAA,EAAQU,IAAI,iBACP,OAAAL,EAAKE,EAAKC,GAIb,MAAAP,EAAUG,EAAQO,MAExB,GAAIV,GAASC,YAAa,CAExB,MAAMU,EAAa,IACdJ,EACHR,QAASD,EAAuBC,EAASC,IAIpC,OAAAI,EAAKE,EAAKK,EAAU,CAItB,OAAAP,EAAKE,EAAKC,qCCtBmB,CACtCK,EACAT,EACAI,KAIA,MAAMM,cAAEA,EAAgB,IAAON,GAAW,CAAC,EAG3C,OAAQH,GACNC,MAAOC,EAAaC,EAAuB,CAAA,KAErC,GAoBV,SAAiCD,EAAaC,GAC5C,MAAMR,EAAU,IAAIS,QAAQD,EAAQR,SAAW,CAAA,GAG3C,GAAAA,EAAQU,IAAI,iBACP,OAAA,EAIL,GAAAH,EAAIQ,SAAS,aACR,OAAA,EAGF,OAAA,CACT,CAlCUC,CAAwBT,EAAKC,GACxB,OAAAH,EAAKE,EAAKC,GAGf,UACIS,iBAAeJ,EAAMT,EAASU,EAAa,CAC3C,MAAA,CAGD,OAAAT,EAAKE,EAAKC,iDCvBrBJ,GA4BQC,GACNC,MAAOC,EAAaC,KAElB,MAAMU,QAAiBb,EAAKE,EAAKC,GAE7B,IAEE,GAAAD,EAAIQ,SAAS,YAGR,OADPX,EAAQe,SACDD,EAKP,GAAAX,EAAIQ,SAAS,WACbR,EAAIa,SAAS,aACbb,EAAIa,SAAS,YACb,CAEM,MAAAC,EAAiBH,EAASI,QAG1BC,QAAcF,EAAeG,OAAOC,OAAM,IAAM,OAItD,GAAIF,EAAM,CAEF,MAAAtB,EAjDS,SACvBsB,GAEI,MAAgB,iBAATA,EACF,KAGL,YAAaA,EAERA,EAAKtB,SAAW,KAGrB,gBAAiBsB,GAAQ,iBAAkBA,EAEtCA,EAGF,IACT,CA+B0BG,CAAiBH,GAG7BtB,GAAWA,EAAQC,aAAeD,EAAQ0B,cAC5CvB,EAAQD,IAAIF,EACd,CACF,QAEK2B,GACCC,QAAAC,KAAK,wCAAyCF,EAAK,CAItD,OAAAV"}
1
+ {"version":3,"file":"fetch.cjs.js","sources":["../../src/fetch/middlewareAttachAccessToken.ts","../../src/fetch/middlewareSessionRefresh.ts","../../src/fetch/middlewareUpdateSessionFromResponse.ts"],"sourcesContent":["/**\n * Authorization token attachment middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * authorization tokens to outgoing API requests, ensuring the client\n * is properly authenticated.\n */\n\nimport type { Session } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that adds the Authorization header with the current access token.\n *\n * This middleware:\n * 1. Gets the current session from storage\n * 2. Adds the authorization header with the access token to outgoing requests\n *\n * This middleware should be used after the refresh middleware in the chain to\n * ensure the most recent token is used.\n *\n * @param storage - Storage implementation for retrieving session data\n * @returns A middleware function that adds Authorization headers\n */\nexport const attachAccessTokenMiddleware =\n (storage: SessionStorage): ChainFunction =>\n (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n const headers = new Headers(options.headers || {});\n\n // Skip if Authorization header is already set\n if (headers.has(\"Authorization\")) {\n return next(url, options);\n }\n\n // Get current session from storage\n const session = storage.get();\n\n if (session?.accessToken) {\n // Add authorization header\n const newOptions = {\n ...options,\n headers: addAuthorizationHeader(headers, session),\n };\n\n // Continue with the fetch chain\n return next(url, newOptions);\n }\n\n // No session or no access token, continue without authorization\n return next(url, options);\n };\n\n/**\n * Adds the Authorization header with the access token to the request headers\n *\n * @param headers - Original request headers\n * @param session - Current session containing the access token\n * @returns Modified headers with Authorization header\n */\nfunction addAuthorizationHeader(headers: Headers, session: Session): Headers {\n if (session.accessToken) {\n headers.set(\"Authorization\", `Bearer ${session.accessToken}`);\n }\n return headers;\n}\n","/**\n * Auth token refresh middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically refresh\n * authentication tokens before they expire, ensuring seamless API access\n * without requiring manual token refresh by the application.\n */\n\nimport type { Client } from \"../auth\";\nimport { refreshSession } from \"../session/refreshSession\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically refreshes authentication tokens.\n *\n * This middleware:\n * 1. Checks if the current token is about to expire\n * 2. If so, uses the refresh token to obtain a new access token\n *\n * The middleware handles token refresh transparently, so the application\n * doesn't need to manually refresh tokens.\n *\n * @param auth - Auth API client for token refresh operations\n * @param storage - Storage implementation for persisting session data\n * @param options - Configuration options for token refresh behavior\n * @param options.marginSeconds - Number of seconds before token expiration to trigger a refresh, default is 60 seconds\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const sessionRefreshMiddleware = (\n auth: Client,\n storage: SessionStorage,\n options?: {\n marginSeconds?: number;\n },\n): ChainFunction => {\n const { marginSeconds = 60 } = options || {};\n\n // Create and return the chain function\n return (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n // Skip token handling for certain requests\n if (shouldSkipTokenHandling(url, options)) {\n return next(url, options);\n }\n\n try {\n await refreshSession(auth, storage, marginSeconds);\n } catch {\n // do nothing, we still want to call the next function\n }\n return next(url, options);\n };\n};\n\n/**\n * Determines if token handling should be skipped for this request\n *\n * @param url - Request URL\n * @param options - Request options\n * @returns True if token handling should be skipped, false otherwise\n */\nfunction shouldSkipTokenHandling(url: string, options: RequestInit): boolean {\n const headers = new Headers(options.headers || {});\n\n // If Authorization header is explicitly set, skip token handling\n if (headers.has(\"Authorization\")) {\n return true;\n }\n\n // If calling the token endpoint, skip to avoid infinite loops\n if (url.endsWith(\"/v1/token\")) {\n return true;\n }\n\n return false;\n}\n","/**\n * Session response middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically extract\n * and persist session information from authentication responses, ensuring\n * that new sessions are properly stored after sign-in operations.\n */\n\nimport type { Session, SessionPayload } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically extracts and stores session data from API responses.\n *\n * This middleware:\n * 1. Monitors responses from authentication-related endpoints\n * 2. Extracts session information when present\n * 3. Stores the session in the provided storage implementation\n * 4. Handles session removal on sign-out\n *\n * This ensures that session data is always up-to-date in storage after operations\n * that create or invalidate sessions.\n *\n * @param storage - Storage implementation for persisting session data\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const updateSessionFromResponseMiddleware = (\n storage: SessionStorage,\n): ChainFunction => {\n /**\n * Helper function to extract session data from various response formats\n *\n * @param body - Response data to extract session from\n * @returns Session object if found, null otherwise\n */\n const sessionExtractor = (\n body: Session | SessionPayload | string,\n ): Session | null => {\n if (typeof body === \"string\") {\n return null;\n }\n\n if (\"session\" in body) {\n // SessionPayload\n return body.session || null;\n }\n\n if (\"accessToken\" in body && \"refreshToken\" in body) {\n // Session\n return body;\n }\n\n return null;\n };\n\n return (next: (url: string, options?: RequestInit) => Promise<Response>) =>\n async (url: string, options?: RequestInit) => {\n // Call the next middleware in the chain\n const response = await next(url, options);\n\n try {\n // Check if this is a logout request\n if (url.endsWith(\"/signout\")) {\n // Remove session on sign-out\n storage.remove();\n return response;\n }\n\n // Check if this is an auth-related endpoint that might return session data\n if (\n url.endsWith(\"/token\") ||\n url.includes(\"/signin/\") ||\n url.includes(\"/signup/\")\n ) {\n // Clone the response to avoid consuming it\n const clonedResponse = response.clone();\n\n // Parse the JSON data\n const body = (await clonedResponse.json().catch(() => null)) as\n | Session\n | SessionPayload;\n\n if (body) {\n // Extract session data from response using provided extractor\n const session = sessionExtractor(body);\n\n // If session data is found, store it\n if (session?.accessToken && session.refreshToken) {\n storage.set(session);\n }\n }\n }\n } catch (error) {\n console.warn(\"Error in session response middleware:\", error);\n }\n\n // Return the original response\n return response;\n };\n};\n"],"names":["addAuthorizationHeader","headers","session","accessToken","set","storage","next","async","url","options","Headers","has","get","newOptions","auth","marginSeconds","endsWith","shouldSkipTokenHandling","refreshSession","response","remove","includes","clonedResponse","clone","body","json","catch","sessionExtractor","refreshToken","error","console","warn"],"mappings":"mKA6DA,SAASA,EAAuBC,EAAkBC,GAIhD,OAHIA,EAAQC,aACVF,EAAQG,IAAI,gBAAiB,UAAUF,EAAQC,eAE1CF,CACT,uHAxCGI,GACAC,GACDC,MAAOC,EAAaC,EAAuB,MACzC,MAAMR,EAAU,IAAIS,QAAQD,EAAQR,SAAW,CAAA,GAG/C,GAAIA,EAAQU,IAAI,iBACd,OAAOL,EAAKE,EAAKC,GAInB,MAAMP,EAAUG,EAAQO,MAExB,GAAIV,GAASC,YAAa,CAExB,MAAMU,EAAa,IACdJ,EACHR,QAASD,EAAuBC,EAASC,IAI3C,OAAOI,EAAKE,EAAKK,EACnB,CAGA,OAAOP,EAAKE,EAAKC,EAAO,mCCtBY,CACtCK,EACAT,EACAI,KAIA,MAAMM,cAAEA,EAAgB,IAAON,GAAW,CAAA,EAG1C,OAAQH,GACNC,MAAOC,EAAaC,EAAuB,CAAA,KAEzC,GAoBN,SAAiCD,EAAaC,GAC5C,MAAMR,EAAU,IAAIS,QAAQD,EAAQR,SAAW,CAAA,GAG/C,GAAIA,EAAQU,IAAI,iBACd,OAAO,EAIT,GAAIH,EAAIQ,SAAS,aACf,OAAO,EAGT,OAAO,CACT,CAlCUC,CAAwBT,EAAKC,GAC/B,OAAOH,EAAKE,EAAKC,GAGnB,UACQS,iBAAeJ,EAAMT,EAASU,EACtC,CAAA,MAEA,CACA,OAAOT,EAAKE,EAAKC,EAAO,CAC1B,8CCxBFJ,GA4BQC,GACNC,MAAOC,EAAaC,KAElB,MAAMU,QAAiBb,EAAKE,EAAKC,GAEjC,IAEE,GAAID,EAAIQ,SAAS,YAGf,OADAX,EAAQe,SACDD,EAIT,GACEX,EAAIQ,SAAS,WACbR,EAAIa,SAAS,aACbb,EAAIa,SAAS,YACb,CAEA,MAAMC,EAAiBH,EAASI,QAG1BC,QAAcF,EAAeG,OAAOC,OAAM,IAAM,OAItD,GAAIF,EAAM,CAER,MAAMtB,EAjDS,CACvBsB,GAEoB,iBAATA,EACF,KAGL,YAAaA,EAERA,EAAKtB,SAAW,KAGrB,gBAAiBsB,GAAQ,iBAAkBA,EAEtCA,EAGF,KAgCiBG,CAAiBH,GAG7BtB,GAASC,aAAeD,EAAQ0B,cAClCvB,EAAQD,IAAIF,EAEhB,CACF,CACF,OAAS2B,GACPC,QAAQC,KAAK,wCAAyCF,EACxD,CAGA,OAAOV,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { F, c } from "../fetch-2PHmQBIJ.mjs";
2
- import { r as refreshSession } from "../refreshSession-cGdPdFoG.mjs";
2
+ import { r as refreshSession } from "../refreshSession-WwGlzgtM.mjs";
3
3
  const attachAccessTokenMiddleware = (storage) => (next) => async (url, options = {}) => {
4
4
  const headers = new Headers(options.headers || {});
5
5
  if (headers.has("Authorization")) {
@@ -45,7 +45,7 @@ function shouldSkipTokenHandling(url, options) {
45
45
  return false;
46
46
  }
47
47
  const updateSessionFromResponseMiddleware = (storage) => {
48
- const sessionExtractor = function(body) {
48
+ const sessionExtractor = (body) => {
49
49
  if (typeof body === "string") {
50
50
  return null;
51
51
  }
@@ -69,7 +69,7 @@ const updateSessionFromResponseMiddleware = (storage) => {
69
69
  const body = await clonedResponse.json().catch(() => null);
70
70
  if (body) {
71
71
  const session = sessionExtractor(body);
72
- if (session && session.accessToken && session.refreshToken) {
72
+ if (session?.accessToken && session.refreshToken) {
73
73
  storage.set(session);
74
74
  }
75
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.es.js","sources":["../../src/fetch/middlewareAttachAccessToken.ts","../../src/fetch/middlewareSessionRefresh.ts","../../src/fetch/middlewareUpdateSessionFromResponse.ts"],"sourcesContent":["/**\n * Authorization token attachment middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * authorization tokens to outgoing API requests, ensuring the client\n * is properly authenticated.\n */\n\nimport type { Session } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that adds the Authorization header with the current access token.\n *\n * This middleware:\n * 1. Gets the current session from storage\n * 2. Adds the authorization header with the access token to outgoing requests\n *\n * This middleware should be used after the refresh middleware in the chain to\n * ensure the most recent token is used.\n *\n * @param storage - Storage implementation for retrieving session data\n * @returns A middleware function that adds Authorization headers\n */\nexport const attachAccessTokenMiddleware =\n (storage: SessionStorage): ChainFunction =>\n (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n const headers = new Headers(options.headers || {});\n\n // Skip if Authorization header is already set\n if (headers.has(\"Authorization\")) {\n return next(url, options);\n }\n\n // Get current session from storage\n const session = storage.get();\n\n if (session?.accessToken) {\n // Add authorization header\n const newOptions = {\n ...options,\n headers: addAuthorizationHeader(headers, session),\n };\n\n // Continue with the fetch chain\n return next(url, newOptions);\n }\n\n // No session or no access token, continue without authorization\n return next(url, options);\n };\n\n/**\n * Adds the Authorization header with the access token to the request headers\n *\n * @param headers - Original request headers\n * @param session - Current session containing the access token\n * @returns Modified headers with Authorization header\n */\nfunction addAuthorizationHeader(headers: Headers, session: Session): Headers {\n if (session.accessToken) {\n headers.set(\"Authorization\", `Bearer ${session.accessToken}`);\n }\n return headers;\n}\n","/**\n * Auth token refresh middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically refresh\n * authentication tokens before they expire, ensuring seamless API access\n * without requiring manual token refresh by the application.\n */\n\nimport type { Client } from \"../auth\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\nimport type { SessionStorage } from \"../session/storage\";\nimport { refreshSession } from \"../session/refreshSession\";\n\n/**\n * Creates a fetch middleware that automatically refreshes authentication tokens.\n *\n * This middleware:\n * 1. Checks if the current token is about to expire\n * 2. If so, uses the refresh token to obtain a new access token\n *\n * The middleware handles token refresh transparently, so the application\n * doesn't need to manually refresh tokens.\n *\n * @param auth - Auth API client for token refresh operations\n * @param storage - Storage implementation for persisting session data\n * @param options - Configuration options for token refresh behavior\n * @param options.marginSeconds - Number of seconds before token expiration to trigger a refresh, default is 60 seconds\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const sessionRefreshMiddleware = (\n auth: Client,\n storage: SessionStorage,\n options?: {\n marginSeconds?: number;\n },\n): ChainFunction => {\n const { marginSeconds = 60 } = options || {};\n\n // Create and return the chain function\n return (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n // Skip token handling for certain requests\n if (shouldSkipTokenHandling(url, options)) {\n return next(url, options);\n }\n\n try {\n await refreshSession(auth, storage, marginSeconds);\n } catch {\n // do nothing, we still want to call the next function\n }\n return next(url, options);\n };\n};\n\n/**\n * Determines if token handling should be skipped for this request\n *\n * @param url - Request URL\n * @param options - Request options\n * @returns True if token handling should be skipped, false otherwise\n */\nfunction shouldSkipTokenHandling(url: string, options: RequestInit): boolean {\n const headers = new Headers(options.headers || {});\n\n // If Authorization header is explicitly set, skip token handling\n if (headers.has(\"Authorization\")) {\n return true;\n }\n\n // If calling the token endpoint, skip to avoid infinite loops\n if (url.endsWith(\"/v1/token\")) {\n return true;\n }\n\n return false;\n}\n","/**\n * Session response middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically extract\n * and persist session information from authentication responses, ensuring\n * that new sessions are properly stored after sign-in operations.\n */\n\nimport type { Session, SessionPayload } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically extracts and stores session data from API responses.\n *\n * This middleware:\n * 1. Monitors responses from authentication-related endpoints\n * 2. Extracts session information when present\n * 3. Stores the session in the provided storage implementation\n * 4. Handles session removal on sign-out\n *\n * This ensures that session data is always up-to-date in storage after operations\n * that create or invalidate sessions.\n *\n * @param storage - Storage implementation for persisting session data\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const updateSessionFromResponseMiddleware = (\n storage: SessionStorage,\n): ChainFunction => {\n /**\n * Helper function to extract session data from various response formats\n *\n * @param body - Response data to extract session from\n * @returns Session object if found, null otherwise\n */\n const sessionExtractor = function (\n body: Session | SessionPayload | string,\n ): Session | null {\n if (typeof body === \"string\") {\n return null;\n }\n\n if (\"session\" in body) {\n // SessionPayload\n return body.session || null;\n }\n\n if (\"accessToken\" in body && \"refreshToken\" in body) {\n // Session\n return body;\n }\n\n return null;\n };\n\n return (next: (url: string, options?: RequestInit) => Promise<Response>) =>\n async (url: string, options?: RequestInit) => {\n // Call the next middleware in the chain\n const response = await next(url, options);\n\n try {\n // Check if this is a logout request\n if (url.endsWith(\"/signout\")) {\n // Remove session on sign-out\n storage.remove();\n return response;\n }\n\n // Check if this is an auth-related endpoint that might return session data\n if (\n url.endsWith(\"/token\") ||\n url.includes(\"/signin/\") ||\n url.includes(\"/signup/\")\n ) {\n // Clone the response to avoid consuming it\n const clonedResponse = response.clone();\n\n // Parse the JSON data\n const body = (await clonedResponse.json().catch(() => null)) as\n | Session\n | SessionPayload;\n\n if (body) {\n // Extract session data from response using provided extractor\n const session = sessionExtractor(body);\n\n // If session data is found, store it\n if (session && session.accessToken && session.refreshToken) {\n storage.set(session);\n }\n }\n }\n } catch (error) {\n console.warn(\"Error in session response middleware:\", error);\n }\n\n // Return the original response\n return response;\n };\n};\n"],"names":["options"],"mappings":";;AAyBa,MAAA,8BACX,CAAC,YACD,CAAC,SACD,OAAO,KAAa,UAAuB,OAA0B;AACnE,QAAM,UAAU,IAAI,QAAQ,QAAQ,WAAW,CAAA,CAAE;AAG7C,MAAA,QAAQ,IAAI,eAAe,GAAG;AACzB,WAAA,KAAK,KAAK,OAAO;AAAA,EAAA;AAIpB,QAAA,UAAU,QAAQ,IAAI;AAE5B,MAAI,SAAS,aAAa;AAExB,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,SAAS,uBAAuB,SAAS,OAAO;AAAA,IAClD;AAGO,WAAA,KAAK,KAAK,UAAU;AAAA,EAAA;AAItB,SAAA,KAAK,KAAK,OAAO;AAC1B;AASF,SAAS,uBAAuB,SAAkB,SAA2B;AAC3E,MAAI,QAAQ,aAAa;AACvB,YAAQ,IAAI,iBAAiB,UAAU,QAAQ,WAAW,EAAE;AAAA,EAAA;AAEvD,SAAA;AACT;ACrCO,MAAM,2BAA2B,CACtC,MACA,SACA,YAGkB;AAClB,QAAM,EAAE,gBAAgB,GAAG,IAAI,WAAW,CAAC;AAG3C,SAAO,CAAC,SACN,OAAO,KAAaA,WAAuB,CAAA,MAA0B;AAE/D,QAAA,wBAAwB,KAAKA,QAAO,GAAG;AAClC,aAAA,KAAK,KAAKA,QAAO;AAAA,IAAA;AAGtB,QAAA;AACI,YAAA,eAAe,MAAM,SAAS,aAAa;AAAA,IAAA,QAC3C;AAAA,IAAA;AAGD,WAAA,KAAK,KAAKA,QAAO;AAAA,EAC1B;AACJ;AASA,SAAS,wBAAwB,KAAa,SAA+B;AAC3E,QAAM,UAAU,IAAI,QAAQ,QAAQ,WAAW,CAAA,CAAE;AAG7C,MAAA,QAAQ,IAAI,eAAe,GAAG;AACzB,WAAA;AAAA,EAAA;AAIL,MAAA,IAAI,SAAS,WAAW,GAAG;AACtB,WAAA;AAAA,EAAA;AAGF,SAAA;AACT;ACjDa,MAAA,sCAAsC,CACjD,YACkB;AAOZ,QAAA,mBAAmB,SACvB,MACgB;AACZ,QAAA,OAAO,SAAS,UAAU;AACrB,aAAA;AAAA,IAAA;AAGT,QAAI,aAAa,MAAM;AAErB,aAAO,KAAK,WAAW;AAAA,IAAA;AAGrB,QAAA,iBAAiB,QAAQ,kBAAkB,MAAM;AAE5C,aAAA;AAAA,IAAA;AAGF,WAAA;AAAA,EACT;AAEA,SAAO,CAAC,SACN,OAAO,KAAa,YAA0B;AAE5C,UAAM,WAAW,MAAM,KAAK,KAAK,OAAO;AAEpC,QAAA;AAEE,UAAA,IAAI,SAAS,UAAU,GAAG;AAE5B,gBAAQ,OAAO;AACR,eAAA;AAAA,MAAA;AAKP,UAAA,IAAI,SAAS,QAAQ,KACrB,IAAI,SAAS,UAAU,KACvB,IAAI,SAAS,UAAU,GACvB;AAEM,cAAA,iBAAiB,SAAS,MAAM;AAGtC,cAAM,OAAQ,MAAM,eAAe,OAAO,MAAM,MAAM,IAAI;AAI1D,YAAI,MAAM;AAEF,gBAAA,UAAU,iBAAiB,IAAI;AAGrC,cAAI,WAAW,QAAQ,eAAe,QAAQ,cAAc;AAC1D,oBAAQ,IAAI,OAAO;AAAA,UAAA;AAAA,QACrB;AAAA,MACF;AAAA,aAEK,OAAO;AACN,cAAA,KAAK,yCAAyC,KAAK;AAAA,IAAA;AAItD,WAAA;AAAA,EACT;AACJ;"}
1
+ {"version":3,"file":"fetch.es.js","sources":["../../src/fetch/middlewareAttachAccessToken.ts","../../src/fetch/middlewareSessionRefresh.ts","../../src/fetch/middlewareUpdateSessionFromResponse.ts"],"sourcesContent":["/**\n * Authorization token attachment middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically attach\n * authorization tokens to outgoing API requests, ensuring the client\n * is properly authenticated.\n */\n\nimport type { Session } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that adds the Authorization header with the current access token.\n *\n * This middleware:\n * 1. Gets the current session from storage\n * 2. Adds the authorization header with the access token to outgoing requests\n *\n * This middleware should be used after the refresh middleware in the chain to\n * ensure the most recent token is used.\n *\n * @param storage - Storage implementation for retrieving session data\n * @returns A middleware function that adds Authorization headers\n */\nexport const attachAccessTokenMiddleware =\n (storage: SessionStorage): ChainFunction =>\n (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n const headers = new Headers(options.headers || {});\n\n // Skip if Authorization header is already set\n if (headers.has(\"Authorization\")) {\n return next(url, options);\n }\n\n // Get current session from storage\n const session = storage.get();\n\n if (session?.accessToken) {\n // Add authorization header\n const newOptions = {\n ...options,\n headers: addAuthorizationHeader(headers, session),\n };\n\n // Continue with the fetch chain\n return next(url, newOptions);\n }\n\n // No session or no access token, continue without authorization\n return next(url, options);\n };\n\n/**\n * Adds the Authorization header with the access token to the request headers\n *\n * @param headers - Original request headers\n * @param session - Current session containing the access token\n * @returns Modified headers with Authorization header\n */\nfunction addAuthorizationHeader(headers: Headers, session: Session): Headers {\n if (session.accessToken) {\n headers.set(\"Authorization\", `Bearer ${session.accessToken}`);\n }\n return headers;\n}\n","/**\n * Auth token refresh middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically refresh\n * authentication tokens before they expire, ensuring seamless API access\n * without requiring manual token refresh by the application.\n */\n\nimport type { Client } from \"../auth\";\nimport { refreshSession } from \"../session/refreshSession\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction, FetchFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically refreshes authentication tokens.\n *\n * This middleware:\n * 1. Checks if the current token is about to expire\n * 2. If so, uses the refresh token to obtain a new access token\n *\n * The middleware handles token refresh transparently, so the application\n * doesn't need to manually refresh tokens.\n *\n * @param auth - Auth API client for token refresh operations\n * @param storage - Storage implementation for persisting session data\n * @param options - Configuration options for token refresh behavior\n * @param options.marginSeconds - Number of seconds before token expiration to trigger a refresh, default is 60 seconds\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const sessionRefreshMiddleware = (\n auth: Client,\n storage: SessionStorage,\n options?: {\n marginSeconds?: number;\n },\n): ChainFunction => {\n const { marginSeconds = 60 } = options || {};\n\n // Create and return the chain function\n return (next: FetchFunction): FetchFunction =>\n async (url: string, options: RequestInit = {}): Promise<Response> => {\n // Skip token handling for certain requests\n if (shouldSkipTokenHandling(url, options)) {\n return next(url, options);\n }\n\n try {\n await refreshSession(auth, storage, marginSeconds);\n } catch {\n // do nothing, we still want to call the next function\n }\n return next(url, options);\n };\n};\n\n/**\n * Determines if token handling should be skipped for this request\n *\n * @param url - Request URL\n * @param options - Request options\n * @returns True if token handling should be skipped, false otherwise\n */\nfunction shouldSkipTokenHandling(url: string, options: RequestInit): boolean {\n const headers = new Headers(options.headers || {});\n\n // If Authorization header is explicitly set, skip token handling\n if (headers.has(\"Authorization\")) {\n return true;\n }\n\n // If calling the token endpoint, skip to avoid infinite loops\n if (url.endsWith(\"/v1/token\")) {\n return true;\n }\n\n return false;\n}\n","/**\n * Session response middleware for the Nhost SDK.\n *\n * This module provides middleware functionality to automatically extract\n * and persist session information from authentication responses, ensuring\n * that new sessions are properly stored after sign-in operations.\n */\n\nimport type { Session, SessionPayload } from \"../auth\";\nimport type { SessionStorage } from \"../session/storage\";\nimport type { ChainFunction } from \"./fetch\";\n\n/**\n * Creates a fetch middleware that automatically extracts and stores session data from API responses.\n *\n * This middleware:\n * 1. Monitors responses from authentication-related endpoints\n * 2. Extracts session information when present\n * 3. Stores the session in the provided storage implementation\n * 4. Handles session removal on sign-out\n *\n * This ensures that session data is always up-to-date in storage after operations\n * that create or invalidate sessions.\n *\n * @param storage - Storage implementation for persisting session data\n * @returns A middleware function that can be used in the fetch chain\n */\nexport const updateSessionFromResponseMiddleware = (\n storage: SessionStorage,\n): ChainFunction => {\n /**\n * Helper function to extract session data from various response formats\n *\n * @param body - Response data to extract session from\n * @returns Session object if found, null otherwise\n */\n const sessionExtractor = (\n body: Session | SessionPayload | string,\n ): Session | null => {\n if (typeof body === \"string\") {\n return null;\n }\n\n if (\"session\" in body) {\n // SessionPayload\n return body.session || null;\n }\n\n if (\"accessToken\" in body && \"refreshToken\" in body) {\n // Session\n return body;\n }\n\n return null;\n };\n\n return (next: (url: string, options?: RequestInit) => Promise<Response>) =>\n async (url: string, options?: RequestInit) => {\n // Call the next middleware in the chain\n const response = await next(url, options);\n\n try {\n // Check if this is a logout request\n if (url.endsWith(\"/signout\")) {\n // Remove session on sign-out\n storage.remove();\n return response;\n }\n\n // Check if this is an auth-related endpoint that might return session data\n if (\n url.endsWith(\"/token\") ||\n url.includes(\"/signin/\") ||\n url.includes(\"/signup/\")\n ) {\n // Clone the response to avoid consuming it\n const clonedResponse = response.clone();\n\n // Parse the JSON data\n const body = (await clonedResponse.json().catch(() => null)) as\n | Session\n | SessionPayload;\n\n if (body) {\n // Extract session data from response using provided extractor\n const session = sessionExtractor(body);\n\n // If session data is found, store it\n if (session?.accessToken && session.refreshToken) {\n storage.set(session);\n }\n }\n }\n } catch (error) {\n console.warn(\"Error in session response middleware:\", error);\n }\n\n // Return the original response\n return response;\n };\n};\n"],"names":["options"],"mappings":";;AAyBO,MAAM,8BACX,CAAC,YACD,CAAC,SACD,OAAO,KAAa,UAAuB,OAA0B;AACnE,QAAM,UAAU,IAAI,QAAQ,QAAQ,WAAW,CAAA,CAAE;AAGjD,MAAI,QAAQ,IAAI,eAAe,GAAG;AAChC,WAAO,KAAK,KAAK,OAAO;AAAA,EAC1B;AAGA,QAAM,UAAU,QAAQ,IAAA;AAExB,MAAI,SAAS,aAAa;AAExB,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,SAAS,uBAAuB,SAAS,OAAO;AAAA,IAAA;AAIlD,WAAO,KAAK,KAAK,UAAU;AAAA,EAC7B;AAGA,SAAO,KAAK,KAAK,OAAO;AAC1B;AASF,SAAS,uBAAuB,SAAkB,SAA2B;AAC3E,MAAI,QAAQ,aAAa;AACvB,YAAQ,IAAI,iBAAiB,UAAU,QAAQ,WAAW,EAAE;AAAA,EAC9D;AACA,SAAO;AACT;ACrCO,MAAM,2BAA2B,CACtC,MACA,SACA,YAGkB;AAClB,QAAM,EAAE,gBAAgB,GAAA,IAAO,WAAW,CAAA;AAG1C,SAAO,CAAC,SACN,OAAO,KAAaA,WAAuB,CAAA,MAA0B;AAEnE,QAAI,wBAAwB,KAAKA,QAAO,GAAG;AACzC,aAAO,KAAK,KAAKA,QAAO;AAAA,IAC1B;AAEA,QAAI;AACF,YAAM,eAAe,MAAM,SAAS,aAAa;AAAA,IACnD,QAAQ;AAAA,IAER;AACA,WAAO,KAAK,KAAKA,QAAO;AAAA,EAC1B;AACJ;AASA,SAAS,wBAAwB,KAAa,SAA+B;AAC3E,QAAM,UAAU,IAAI,QAAQ,QAAQ,WAAW,CAAA,CAAE;AAGjD,MAAI,QAAQ,IAAI,eAAe,GAAG;AAChC,WAAO;AAAA,EACT;AAGA,MAAI,IAAI,SAAS,WAAW,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;ACjDO,MAAM,sCAAsC,CACjD,YACkB;AAOlB,QAAM,mBAAmB,CACvB,SACmB;AACnB,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO;AAAA,IACT;AAEA,QAAI,aAAa,MAAM;AAErB,aAAO,KAAK,WAAW;AAAA,IACzB;AAEA,QAAI,iBAAiB,QAAQ,kBAAkB,MAAM;AAEnD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,SACN,OAAO,KAAa,YAA0B;AAE5C,UAAM,WAAW,MAAM,KAAK,KAAK,OAAO;AAExC,QAAI;AAEF,UAAI,IAAI,SAAS,UAAU,GAAG;AAE5B,gBAAQ,OAAA;AACR,eAAO;AAAA,MACT;AAGA,UACE,IAAI,SAAS,QAAQ,KACrB,IAAI,SAAS,UAAU,KACvB,IAAI,SAAS,UAAU,GACvB;AAEA,cAAM,iBAAiB,SAAS,MAAA;AAGhC,cAAM,OAAQ,MAAM,eAAe,OAAO,MAAM,MAAM,IAAI;AAI1D,YAAI,MAAM;AAER,gBAAM,UAAU,iBAAiB,IAAI;AAGrC,cAAI,SAAS,eAAe,QAAQ,cAAc;AAChD,oBAAQ,IAAI,OAAO;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,yCAAyC,KAAK;AAAA,IAC7D;AAGA,WAAO;AAAA,EACT;AACJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"functions.cjs.js","sources":["../../src/functions/client.ts"],"sourcesContent":["/**\n * Functions client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing serverless function calls\n * against Nhost serverless functions.\n */\n\nimport {\n createEnhancedFetch,\n FetchError,\n type ChainFunction,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Functions client interface providing methods for executing serverless function calls\n */\nexport interface Client {\n baseURL: string;\n\n /**\n * Execute a request to a serverless function\n * The response body will be automatically parsed based on the content type into the following types:\n * - Object if the response is application/json\n * - string text string if the response is text/*\n * - Blob if the response is any other type\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetch<T = any>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n post<T = any>(\n path: string,\n body?: unknown,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n}\n\n/**\n * Creates a Functions API client for interacting with serverless functions.\n *\n * This client provides methods for executing requests against serverless functions,\n * with support for middleware functions to handle authentication, error handling,\n * and other cross-cutting concerns.\n *\n * @param baseURL - Base URL for the functions endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns Functions client with fetch method\n */\nexport const createAPIClient = (\n baseURL: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n /**\n * Executes a request to a serverless function and processes the response\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. Body will be either\n * - JSON object if the response is application/json\n - text string if the response is text/*\n - Blob if the response is any other type\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fetch = async <T = any>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T | string | Blob>> => {\n const resp = await enhancedFetch(`${baseURL}${path}`, options);\n\n let body: T | string | Blob;\n // Process response based on content type\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n body = (await resp.json()) as T;\n } else if (resp.headers.get(\"content-type\")?.startsWith(\"text/\")) {\n body = await resp.text();\n } else {\n body = await resp.blob();\n }\n\n // Throw error for non-OK responses\n if (!resp.ok) {\n throw new FetchError(body, resp.status, resp.headers);\n }\n\n return {\n status: resp.status,\n body,\n headers: resp.headers,\n };\n };\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const post = async <T = any>(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n ): Promise<FetchResponse<T | string | Blob>> => {\n // Ensure the method is POST and set the body\n const requestOptions: RequestInit = {\n ...options,\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n };\n\n return fetch<T>(path, requestOptions);\n };\n\n // Return client object with the fetch method\n return {\n baseURL,\n fetch,\n post,\n } as Client;\n};\n"],"names":["baseURL","chainFunctions","enhancedFetch","createEnhancedFetch","fetch","async","path","options","resp","body","headers","get","includes","json","startsWith","text","blob","ok","FetchError","status","post","requestOptions","method","Accept","JSON","stringify"],"mappings":"gJAqE+B,CAC7BA,EACAC,EAAkC,MAE5B,MAAAC,EAAgBC,sBAAoBF,GAapCG,EAAQC,MACZC,EACAC,KAEM,MAAAC,QAAaN,EAAc,GAAGF,IAAUM,IAAQC,GAElD,IAAAE,EAWA,GARMA,EADND,EAAKE,QAAQC,IAAI,iBAAiBC,SAAS,0BAC/BJ,EAAKK,OACVL,EAAKE,QAAQC,IAAI,iBAAiBG,WAAW,eACzCN,EAAKO,aAELP,EAAKQ,QAIfR,EAAKS,GACR,MAAM,IAAIC,EAAWA,WAAAT,EAAMD,EAAKW,OAAQX,EAAKE,SAGxC,MAAA,CACLS,OAAQX,EAAKW,OACbV,OACAC,QAASF,EAAKE,UAwCX,MAAA,CACLV,UAAAI,MACAA,EACAgB,KAxBWf,MACXC,EACAG,EACAF,EAAuB,CAAA,KAGvB,MAAMc,EAA8B,IAC/Bd,EACHe,OAAQ,OACRZ,QAAS,CACPa,OAAQ,mBACR,eAAgB,sBACbhB,EAAQG,SAEbD,KAAMA,EAAOe,KAAKC,UAAUhB,QAAQ,GAG/BL,OAAAA,EAASE,EAAMe"}
1
+ {"version":3,"file":"functions.cjs.js","sources":["../../src/functions/client.ts"],"sourcesContent":["/**\n * Functions client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing serverless function calls\n * against Nhost serverless functions.\n */\n\nimport {\n type ChainFunction,\n createEnhancedFetch,\n FetchError,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Functions client interface providing methods for executing serverless function calls\n */\nexport interface Client {\n baseURL: string;\n\n /**\n * Execute a request to a serverless function\n * The response body will be automatically parsed based on the content type into the following types:\n * - Object if the response is application/json\n * - string text string if the response is text/*\n * - Blob if the response is any other type\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. */\n fetch<T = unknown>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n post<T = unknown>(\n path: string,\n body?: unknown,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n}\n\n/**\n * Creates a Functions API client for interacting with serverless functions.\n *\n * This client provides methods for executing requests against serverless functions,\n * with support for middleware functions to handle authentication, error handling,\n * and other cross-cutting concerns.\n *\n * @param baseURL - Base URL for the functions endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns Functions client with fetch method\n */\nexport const createAPIClient = (\n baseURL: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n /**\n * Executes a request to a serverless function and processes the response\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. Body will be either\n * - JSON object if the response is application/json\n - text string if the response is text/*\n - Blob if the response is any other type\n */\n const fetch = async <T = unknown>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T | string | Blob>> => {\n const resp = await enhancedFetch(`${baseURL}${path}`, options);\n\n let body: T | string | Blob;\n // Process response based on content type\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n body = (await resp.json()) as T;\n } else if (resp.headers.get(\"content-type\")?.startsWith(\"text/\")) {\n body = await resp.text();\n } else {\n body = await resp.blob();\n }\n\n // Throw error for non-OK responses\n if (!resp.ok) {\n throw new FetchError(body, resp.status, resp.headers);\n }\n\n return {\n status: resp.status,\n body,\n headers: resp.headers,\n };\n };\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n const post = async <T = unknown>(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n ): Promise<FetchResponse<T | string | Blob>> => {\n // Ensure the method is POST and set the body\n const requestOptions: RequestInit = {\n ...options,\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n };\n\n return fetch<T>(path, requestOptions);\n };\n\n // Return client object with the fetch method\n return {\n baseURL,\n fetch,\n post,\n } as Client;\n};\n"],"names":["baseURL","chainFunctions","enhancedFetch","createEnhancedFetch","fetch","async","path","options","resp","body","headers","get","includes","json","startsWith","text","blob","ok","FetchError","status","post","requestOptions","method","Accept","JSON","stringify"],"mappings":"gJAmE+B,CAC7BA,EACAC,EAAkC,MAElC,MAAMC,EAAgBC,EAAAA,oBAAoBF,GAYpCG,EAAQC,MACZC,EACAC,KAEA,MAAMC,QAAaN,EAAc,GAAGF,IAAUM,IAAQC,GAEtD,IAAIE,EAWJ,GAREA,EADED,EAAKE,QAAQC,IAAI,iBAAiBC,SAAS,0BAC/BJ,EAAKK,OACVL,EAAKE,QAAQC,IAAI,iBAAiBG,WAAW,eACzCN,EAAKO,aAELP,EAAKQ,QAIfR,EAAKS,GACR,MAAM,IAAIC,EAAAA,WAAWT,EAAMD,EAAKW,OAAQX,EAAKE,SAG/C,MAAO,CACLS,OAAQX,EAAKW,OACbV,OACAC,QAASF,EAAKE,QAAA,EAuClB,MAAO,CACLV,UAAAI,MACAA,EACAgB,KAxBWf,MACXC,EACAG,EACAF,EAAuB,CAAA,KAGvB,MAAMc,EAA8B,IAC/Bd,EACHe,OAAQ,OACRZ,QAAS,CACPa,OAAQ,mBACR,eAAgB,sBACbhB,EAAQG,SAEbD,KAAMA,EAAOe,KAAKC,UAAUhB,QAAQ,GAGtC,OAAOL,EAASE,EAAMe,EAAc,EAOpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"functions.es.js","sources":["../../src/functions/client.ts"],"sourcesContent":["/**\n * Functions client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing serverless function calls\n * against Nhost serverless functions.\n */\n\nimport {\n createEnhancedFetch,\n FetchError,\n type ChainFunction,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Functions client interface providing methods for executing serverless function calls\n */\nexport interface Client {\n baseURL: string;\n\n /**\n * Execute a request to a serverless function\n * The response body will be automatically parsed based on the content type into the following types:\n * - Object if the response is application/json\n * - string text string if the response is text/*\n * - Blob if the response is any other type\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fetch<T = any>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n post<T = any>(\n path: string,\n body?: unknown,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n}\n\n/**\n * Creates a Functions API client for interacting with serverless functions.\n *\n * This client provides methods for executing requests against serverless functions,\n * with support for middleware functions to handle authentication, error handling,\n * and other cross-cutting concerns.\n *\n * @param baseURL - Base URL for the functions endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns Functions client with fetch method\n */\nexport const createAPIClient = (\n baseURL: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n /**\n * Executes a request to a serverless function and processes the response\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. Body will be either\n * - JSON object if the response is application/json\n - text string if the response is text/*\n - Blob if the response is any other type\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const fetch = async <T = any>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T | string | Blob>> => {\n const resp = await enhancedFetch(`${baseURL}${path}`, options);\n\n let body: T | string | Blob;\n // Process response based on content type\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n body = (await resp.json()) as T;\n } else if (resp.headers.get(\"content-type\")?.startsWith(\"text/\")) {\n body = await resp.text();\n } else {\n body = await resp.blob();\n }\n\n // Throw error for non-OK responses\n if (!resp.ok) {\n throw new FetchError(body, resp.status, resp.headers);\n }\n\n return {\n status: resp.status,\n body,\n headers: resp.headers,\n };\n };\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const post = async <T = any>(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n ): Promise<FetchResponse<T | string | Blob>> => {\n // Ensure the method is POST and set the body\n const requestOptions: RequestInit = {\n ...options,\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n };\n\n return fetch<T>(path, requestOptions);\n };\n\n // Return client object with the fetch method\n return {\n baseURL,\n fetch,\n post,\n } as Client;\n};\n"],"names":[],"mappings":";AAqEO,MAAM,kBAAkB,CAC7B,SACA,iBAAkC,OACvB;AACL,QAAA,gBAAgB,oBAAoB,cAAc;AAalD,QAAA,QAAQ,OACZ,MACA,YAC8C;AACxC,UAAA,OAAO,MAAM,cAAc,GAAG,OAAO,GAAG,IAAI,IAAI,OAAO;AAEzD,QAAA;AAEJ,QAAI,KAAK,QAAQ,IAAI,cAAc,GAAG,SAAS,kBAAkB,GAAG;AAC1D,aAAA,MAAM,KAAK,KAAK;AAAA,IAAA,WACf,KAAK,QAAQ,IAAI,cAAc,GAAG,WAAW,OAAO,GAAG;AACzD,aAAA,MAAM,KAAK,KAAK;AAAA,IAAA,OAClB;AACE,aAAA,MAAM,KAAK,KAAK;AAAA,IAAA;AAIrB,QAAA,CAAC,KAAK,IAAI;AACZ,YAAM,IAAI,WAAW,MAAM,KAAK,QAAQ,KAAK,OAAO;AAAA,IAAA;AAG/C,WAAA;AAAA,MACL,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,SAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAiBA,QAAM,OAAO,OACX,MACA,MACA,UAAuB,CAAA,MACuB;AAE9C,UAAM,iBAA8B;AAAA,MAClC,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IACtC;AAEO,WAAA,MAAS,MAAM,cAAc;AAAA,EACtC;AAGO,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"functions.es.js","sources":["../../src/functions/client.ts"],"sourcesContent":["/**\n * Functions client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing serverless function calls\n * against Nhost serverless functions.\n */\n\nimport {\n type ChainFunction,\n createEnhancedFetch,\n FetchError,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Functions client interface providing methods for executing serverless function calls\n */\nexport interface Client {\n baseURL: string;\n\n /**\n * Execute a request to a serverless function\n * The response body will be automatically parsed based on the content type into the following types:\n * - Object if the response is application/json\n * - string text string if the response is text/*\n * - Blob if the response is any other type\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. */\n fetch<T = unknown>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n post<T = unknown>(\n path: string,\n body?: unknown,\n options?: RequestInit,\n ): Promise<FetchResponse<T>>;\n}\n\n/**\n * Creates a Functions API client for interacting with serverless functions.\n *\n * This client provides methods for executing requests against serverless functions,\n * with support for middleware functions to handle authentication, error handling,\n * and other cross-cutting concerns.\n *\n * @param baseURL - Base URL for the functions endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns Functions client with fetch method\n */\nexport const createAPIClient = (\n baseURL: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n /**\n * Executes a request to a serverless function and processes the response\n *\n * @param path - The path to the serverless function\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata. Body will be either\n * - JSON object if the response is application/json\n - text string if the response is text/*\n - Blob if the response is any other type\n */\n const fetch = async <T = unknown>(\n path: string,\n options?: RequestInit,\n ): Promise<FetchResponse<T | string | Blob>> => {\n const resp = await enhancedFetch(`${baseURL}${path}`, options);\n\n let body: T | string | Blob;\n // Process response based on content type\n if (resp.headers.get(\"content-type\")?.includes(\"application/json\")) {\n body = (await resp.json()) as T;\n } else if (resp.headers.get(\"content-type\")?.startsWith(\"text/\")) {\n body = await resp.text();\n } else {\n body = await resp.blob();\n }\n\n // Throw error for non-OK responses\n if (!resp.ok) {\n throw new FetchError(body, resp.status, resp.headers);\n }\n\n return {\n status: resp.status,\n body,\n headers: resp.headers,\n };\n };\n\n /**\n * Executes a POST request to a serverless function with a JSON body\n *\n * This is a convenience method assuming the request is a POST with JSON body\n * setting the `Content-Type` and 'Accept' headers to `application/json` and\n * automatically stringifying the body.\n *\n * For a more generic request, use the `fetch` method instead.\n *\n * @param path - The path to the serverless function\n * @param body - The JSON body to send in the request\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the function response and metadata\n */\n const post = async <T = unknown>(\n path: string,\n body?: unknown,\n options: RequestInit = {},\n ): Promise<FetchResponse<T | string | Blob>> => {\n // Ensure the method is POST and set the body\n const requestOptions: RequestInit = {\n ...options,\n method: \"POST\",\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n };\n\n return fetch<T>(path, requestOptions);\n };\n\n // Return client object with the fetch method\n return {\n baseURL,\n fetch,\n post,\n } as Client;\n};\n"],"names":[],"mappings":";AAmEO,MAAM,kBAAkB,CAC7B,SACA,iBAAkC,OACvB;AACX,QAAM,gBAAgB,oBAAoB,cAAc;AAYxD,QAAM,QAAQ,OACZ,MACA,YAC8C;AAC9C,UAAM,OAAO,MAAM,cAAc,GAAG,OAAO,GAAG,IAAI,IAAI,OAAO;AAE7D,QAAI;AAEJ,QAAI,KAAK,QAAQ,IAAI,cAAc,GAAG,SAAS,kBAAkB,GAAG;AAClE,aAAQ,MAAM,KAAK,KAAA;AAAA,IACrB,WAAW,KAAK,QAAQ,IAAI,cAAc,GAAG,WAAW,OAAO,GAAG;AAChE,aAAO,MAAM,KAAK,KAAA;AAAA,IACpB,OAAO;AACL,aAAO,MAAM,KAAK,KAAA;AAAA,IACpB;AAGA,QAAI,CAAC,KAAK,IAAI;AACZ,YAAM,IAAI,WAAW,MAAM,KAAK,QAAQ,KAAK,OAAO;AAAA,IACtD;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,SAAS,KAAK;AAAA,IAAA;AAAA,EAElB;AAgBA,QAAM,OAAO,OACX,MACA,MACA,UAAuB,CAAA,MACuB;AAE9C,UAAM,iBAA8B;AAAA,MAClC,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MAAA;AAAA,MAEb,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IAAA;AAGtC,WAAO,MAAS,MAAM,cAAc;AAAA,EACtC;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.cjs.js","sources":["../../src/graphql/client.ts"],"sourcesContent":["/**\n * GraphQL client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing GraphQL operations against\n * a Hasura GraphQL API.\n */\n\nimport {\n createEnhancedFetch,\n type ChainFunction,\n type FetchResponse,\n FetchError,\n} from \"../fetch\";\n\nimport type { TypedDocumentNode } from \"@graphql-typed-document-node/core\";\n\n/**\n * Variables object for GraphQL operations.\n * Key-value pairs of variable names and their values.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type GraphQLVariables = Record<string, any>;\n\n/**\n * GraphQL request object used for queries and mutations.\n */\nexport interface GraphQLRequest<TVariables = GraphQLVariables> {\n /** The GraphQL query or mutation string */\n query: string;\n /** Optional variables for parameterized queries */\n variables?: TVariables;\n /** Optional name of the operation to execute */\n operationName?: string;\n}\n\n/**\n * Represents a GraphQL error returned from the server.\n */\nexport interface GraphQLError {\n /** Error message */\n message: string;\n /** Source locations in the GraphQL document where the error occurred */\n locations?: { line: number; column: number }[];\n /** Path in the query where the error occurred */\n path?: string[];\n /** Additional error information specific to the GraphQL implementation */\n extensions?: { path: string; code: string };\n}\n\n/**\n * Standard GraphQL response format as defined by the GraphQL specification.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface GraphQLResponse<TResponseData = any> {\n /** The data returned from successful execution */\n data?: TResponseData;\n /** Array of errors if execution was unsuccessful or partially successful */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL client interface providing methods for executing queries and mutations\n */\nexport interface Client {\n /**\n * Execute a GraphQL query operation\n *\n * Queries are used to fetch data and should not modify any data on the server.\n *\n * @param request - GraphQL request object containing query and optional variables\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n request<TResponseData = any, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * Execute a GraphQL query operation using a typed document node\n *\n * @param document - TypedDocumentNode containing the query and type information\n * @param variables - Variables for the GraphQL operation\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * URL for the GraphQL endpoint.\n */\n url: string;\n}\n\n/**\n * Creates a GraphQL API client for interacting with a GraphQL endpoint.\n *\n * This client provides methods for executing queries and mutations against\n * a GraphQL API, with support for middleware functions to handle authentication,\n * error handling, and other cross-cutting concerns.\n *\n * @param url - Base URL for the GraphQL endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns GraphQL client with query and mutation methods\n */\nexport const createAPIClient = (\n url: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n const executeOperation = async <\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TResponseData = any,\n TVariables = GraphQLVariables,\n >(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> => {\n const response = await enhancedFetch(`${url}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n ...options,\n });\n\n const body = await response.text();\n const data: GraphQLResponse<TResponseData> = (\n body ? JSON.parse(body) : {}\n ) as GraphQLResponse<TResponseData>;\n\n const resp = {\n body: data,\n status: response.status,\n headers: response.headers,\n };\n\n if (data.errors) {\n throw new FetchError(data, response.status, response.headers);\n }\n\n return resp;\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function request<TResponseData = any, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n requestOrDocument:\n | GraphQLRequest<TVariables>\n | TypedDocumentNode<TResponseData, TVariables>,\n variablesOrOptions?: TVariables | RequestInit,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> {\n if (typeof requestOrDocument === \"object\" && \"kind\" in requestOrDocument) {\n const definition = requestOrDocument.definitions[0];\n\n const request: GraphQLRequest<TVariables> = {\n query: requestOrDocument.loc?.source.body || \"\",\n variables: variablesOrOptions as TVariables,\n operationName:\n definition && \"name\" in definition\n ? definition.name?.value\n : undefined,\n };\n return executeOperation(request, options);\n } else {\n // Handle GraphQLRequest\n const request = requestOrDocument;\n const requestOptions = variablesOrOptions as RequestInit;\n return executeOperation(request, requestOptions);\n }\n }\n\n return {\n request,\n url,\n } as Client;\n};\n"],"names":["url","chainFunctions","enhancedFetch","createEnhancedFetch","executeOperation","async","request","options","response","method","headers","body","JSON","stringify","text","data","parse","resp","status","errors","FetchError","requestOrDocument","variablesOrOptions","definition","definitions","query","loc","source","variables","operationName","name","value"],"mappings":"gJA8G+B,CAC7BA,EACAC,EAAkC,MAE5B,MAAAC,EAAgBC,sBAAoBF,GAEpCG,EAAmBC,MAKvBC,EACAC,KAEA,MAAMC,QAAiBN,EAAc,GAAGF,IAAO,CAC7CS,OAAQ,OACRC,QAAS,CACP,eAAgB,oBAElBC,KAAMC,KAAKC,UAAUP,MAClBC,IAGCI,QAAaH,EAASM,OACtBC,EACJJ,EAAOC,KAAKI,MAAML,GAAQ,CAAC,EAGvBM,EAAO,CACXN,KAAMI,EACNG,OAAQV,EAASU,OACjBR,QAASF,EAASE,SAGpB,GAAIK,EAAKI,OACP,MAAM,IAAIC,EAAWA,WAAAL,EAAMP,EAASU,OAAQV,EAASE,SAGhD,OAAAO,GAwCF,MAAA,CACLX,QA5BO,SACPe,EAGAC,EACAf,GAEA,GAAiC,iBAAtBc,GAAkC,SAAUA,EAAmB,CAClE,MAAAE,EAAaF,EAAkBG,YAAY,GAE3ClB,EAAsC,CAC1CmB,MAAOJ,EAAkBK,KAAKC,OAAOhB,MAAQ,GAC7CiB,UAAWN,EACXO,cACEN,GAAc,SAAUA,EACpBA,EAAWO,MAAMC,WACjB,GAED,OAAA3B,EAAiBE,EAASC,EAAO,CAKjC,OAAAH,EAFSiB,EACOC,EAEzB,EAKAtB"}
1
+ {"version":3,"file":"graphql.cjs.js","sources":["../../src/graphql/client.ts"],"sourcesContent":["/**\n * GraphQL client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing GraphQL operations against\n * a Hasura GraphQL API.\n */\n\nimport type { TypedDocumentNode } from \"@graphql-typed-document-node/core\";\nimport {\n type ChainFunction,\n createEnhancedFetch,\n FetchError,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Variables object for GraphQL operations.\n * Key-value pairs of variable names and their values.\n */\nexport type GraphQLVariables = Record<string, unknown>;\n\n/**\n * GraphQL request object used for queries and mutations.\n */\nexport interface GraphQLRequest<TVariables = GraphQLVariables> {\n /** The GraphQL query or mutation string */\n query: string;\n /** Optional variables for parameterized queries */\n variables?: TVariables;\n /** Optional name of the operation to execute */\n operationName?: string;\n}\n\n/**\n * Represents a GraphQL error returned from the server.\n */\nexport interface GraphQLError {\n /** Error message */\n message: string;\n /** Source locations in the GraphQL document where the error occurred */\n locations?: { line: number; column: number }[];\n /** Path in the query where the error occurred */\n path?: string[];\n /** Additional error information specific to the GraphQL implementation */\n extensions?: { path: string; code: string };\n}\n\n/**\n * Standard GraphQL response format as defined by the GraphQL specification.\n */\nexport interface GraphQLResponse<TResponseData = unknown> {\n /** The data returned from successful execution */\n data?: TResponseData;\n /** Array of errors if execution was unsuccessful or partially successful */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL client interface providing methods for executing queries and mutations\n */\nexport interface Client {\n /**\n * Execute a GraphQL query operation\n *\n * Queries are used to fetch data and should not modify any data on the server.\n *\n * @param request - GraphQL request object containing query and optional variables\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData = unknown, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * Execute a GraphQL query operation using a typed document node\n *\n * @param document - TypedDocumentNode containing the query and type information\n * @param variables - Variables for the GraphQL operation\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * URL for the GraphQL endpoint.\n */\n url: string;\n}\n\n/**\n * Creates a GraphQL API client for interacting with a GraphQL endpoint.\n *\n * This client provides methods for executing queries and mutations against\n * a GraphQL API, with support for middleware functions to handle authentication,\n * error handling, and other cross-cutting concerns.\n *\n * @param url - Base URL for the GraphQL endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns GraphQL client with query and mutation methods\n */\nexport const createAPIClient = (\n url: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n const executeOperation = async <\n TResponseData = unknown,\n TVariables = GraphQLVariables,\n >(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> => {\n const response = await enhancedFetch(`${url}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n ...options,\n });\n\n const body = await response.text();\n const data: GraphQLResponse<TResponseData> = (\n body ? JSON.parse(body) : {}\n ) as GraphQLResponse<TResponseData>;\n\n const resp = {\n body: data,\n status: response.status,\n headers: response.headers,\n };\n\n if (data.errors) {\n throw new FetchError(data, response.status, response.headers);\n }\n\n return resp;\n };\n\n function request<TResponseData = unknown, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n requestOrDocument:\n | GraphQLRequest<TVariables>\n | TypedDocumentNode<TResponseData, TVariables>,\n variablesOrOptions?: TVariables | RequestInit,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> {\n if (typeof requestOrDocument === \"object\" && \"kind\" in requestOrDocument) {\n const definition = requestOrDocument.definitions[0];\n\n const request: GraphQLRequest<TVariables> = {\n query: requestOrDocument.loc?.source.body || \"\",\n variables: variablesOrOptions as TVariables,\n operationName:\n definition && \"name\" in definition\n ? definition.name?.value\n : undefined,\n };\n return executeOperation(request, options);\n } else {\n // Handle GraphQLRequest\n const request = requestOrDocument;\n const requestOptions = variablesOrOptions as RequestInit;\n return executeOperation(request, requestOptions);\n }\n }\n\n return {\n request,\n url,\n } as Client;\n};\n"],"names":["url","chainFunctions","enhancedFetch","createEnhancedFetch","executeOperation","async","request","options","response","method","headers","body","JSON","stringify","text","data","parse","resp","status","errors","FetchError","requestOrDocument","variablesOrOptions","definition","definitions","query","loc","source","variables","operationName","name","value"],"mappings":"gJA0G+B,CAC7BA,EACAC,EAAkC,MAElC,MAAMC,EAAgBC,EAAAA,oBAAoBF,GAEpCG,EAAmBC,MAIvBC,EACAC,KAEA,MAAMC,QAAiBN,EAAc,GAAGF,IAAO,CAC7CS,OAAQ,OACRC,QAAS,CACP,eAAgB,oBAElBC,KAAMC,KAAKC,UAAUP,MAClBC,IAGCI,QAAaH,EAASM,OACtBC,EACJJ,EAAOC,KAAKI,MAAML,GAAQ,CAAA,EAGtBM,EAAO,CACXN,KAAMI,EACNG,OAAQV,EAASU,OACjBR,QAASF,EAASE,SAGpB,GAAIK,EAAKI,OACP,MAAM,IAAIC,EAAAA,WAAWL,EAAMP,EAASU,OAAQV,EAASE,SAGvD,OAAOO,CAAA,EAuCT,MAAO,CACLX,QA5BF,SACEe,EAGAC,EACAf,GAEA,GAAiC,iBAAtBc,GAAkC,SAAUA,EAAmB,CACxE,MAAME,EAAaF,EAAkBG,YAAY,GAE3ClB,EAAsC,CAC1CmB,MAAOJ,EAAkBK,KAAKC,OAAOhB,MAAQ,GAC7CiB,UAAWN,EACXO,cACEN,GAAc,SAAUA,EACpBA,EAAWO,MAAMC,WACjB,GAER,OAAO3B,EAAiBE,EAASC,EACnC,CAIE,OAAOH,EAFSiB,EACOC,EAG3B,EAIEtB,MAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.es.js","sources":["../../src/graphql/client.ts"],"sourcesContent":["/**\n * GraphQL client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing GraphQL operations against\n * a Hasura GraphQL API.\n */\n\nimport {\n createEnhancedFetch,\n type ChainFunction,\n type FetchResponse,\n FetchError,\n} from \"../fetch\";\n\nimport type { TypedDocumentNode } from \"@graphql-typed-document-node/core\";\n\n/**\n * Variables object for GraphQL operations.\n * Key-value pairs of variable names and their values.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type GraphQLVariables = Record<string, any>;\n\n/**\n * GraphQL request object used for queries and mutations.\n */\nexport interface GraphQLRequest<TVariables = GraphQLVariables> {\n /** The GraphQL query or mutation string */\n query: string;\n /** Optional variables for parameterized queries */\n variables?: TVariables;\n /** Optional name of the operation to execute */\n operationName?: string;\n}\n\n/**\n * Represents a GraphQL error returned from the server.\n */\nexport interface GraphQLError {\n /** Error message */\n message: string;\n /** Source locations in the GraphQL document where the error occurred */\n locations?: { line: number; column: number }[];\n /** Path in the query where the error occurred */\n path?: string[];\n /** Additional error information specific to the GraphQL implementation */\n extensions?: { path: string; code: string };\n}\n\n/**\n * Standard GraphQL response format as defined by the GraphQL specification.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface GraphQLResponse<TResponseData = any> {\n /** The data returned from successful execution */\n data?: TResponseData;\n /** Array of errors if execution was unsuccessful or partially successful */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL client interface providing methods for executing queries and mutations\n */\nexport interface Client {\n /**\n * Execute a GraphQL query operation\n *\n * Queries are used to fetch data and should not modify any data on the server.\n *\n * @param request - GraphQL request object containing query and optional variables\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n request<TResponseData = any, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * Execute a GraphQL query operation using a typed document node\n *\n * @param document - TypedDocumentNode containing the query and type information\n * @param variables - Variables for the GraphQL operation\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * URL for the GraphQL endpoint.\n */\n url: string;\n}\n\n/**\n * Creates a GraphQL API client for interacting with a GraphQL endpoint.\n *\n * This client provides methods for executing queries and mutations against\n * a GraphQL API, with support for middleware functions to handle authentication,\n * error handling, and other cross-cutting concerns.\n *\n * @param url - Base URL for the GraphQL endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns GraphQL client with query and mutation methods\n */\nexport const createAPIClient = (\n url: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n const executeOperation = async <\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TResponseData = any,\n TVariables = GraphQLVariables,\n >(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> => {\n const response = await enhancedFetch(`${url}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n ...options,\n });\n\n const body = await response.text();\n const data: GraphQLResponse<TResponseData> = (\n body ? JSON.parse(body) : {}\n ) as GraphQLResponse<TResponseData>;\n\n const resp = {\n body: data,\n status: response.status,\n headers: response.headers,\n };\n\n if (data.errors) {\n throw new FetchError(data, response.status, response.headers);\n }\n\n return resp;\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n function request<TResponseData = any, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n requestOrDocument:\n | GraphQLRequest<TVariables>\n | TypedDocumentNode<TResponseData, TVariables>,\n variablesOrOptions?: TVariables | RequestInit,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> {\n if (typeof requestOrDocument === \"object\" && \"kind\" in requestOrDocument) {\n const definition = requestOrDocument.definitions[0];\n\n const request: GraphQLRequest<TVariables> = {\n query: requestOrDocument.loc?.source.body || \"\",\n variables: variablesOrOptions as TVariables,\n operationName:\n definition && \"name\" in definition\n ? definition.name?.value\n : undefined,\n };\n return executeOperation(request, options);\n } else {\n // Handle GraphQLRequest\n const request = requestOrDocument;\n const requestOptions = variablesOrOptions as RequestInit;\n return executeOperation(request, requestOptions);\n }\n }\n\n return {\n request,\n url,\n } as Client;\n};\n"],"names":["request"],"mappings":";AA8GO,MAAM,kBAAkB,CAC7B,KACA,iBAAkC,OACvB;AACL,QAAA,gBAAgB,oBAAoB,cAAc;AAElD,QAAA,mBAAmB,OAKvBA,UACA,YAC2D;AAC3D,UAAM,WAAW,MAAM,cAAc,GAAG,GAAG,IAAI;AAAA,MAC7C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAUA,QAAO;AAAA,MAC5B,GAAG;AAAA,IAAA,CACJ;AAEK,UAAA,OAAO,MAAM,SAAS,KAAK;AACjC,UAAM,OACJ,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC;AAG7B,UAAM,OAAO;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS;AAAA,IACpB;AAEA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,WAAW,MAAM,SAAS,QAAQ,SAAS,OAAO;AAAA,IAAA;AAGvD,WAAA;AAAA,EACT;AAYS,WAAA,QACP,mBAGA,oBACA,SACwD;AACxD,QAAI,OAAO,sBAAsB,YAAY,UAAU,mBAAmB;AAClE,YAAA,aAAa,kBAAkB,YAAY,CAAC;AAElD,YAAMA,WAAsC;AAAA,QAC1C,OAAO,kBAAkB,KAAK,OAAO,QAAQ;AAAA,QAC7C,WAAW;AAAA,QACX,eACE,cAAc,UAAU,aACpB,WAAW,MAAM,QACjB;AAAA,MACR;AACO,aAAA,iBAAiBA,UAAS,OAAO;AAAA,IAAA,OACnC;AAEL,YAAMA,WAAU;AAChB,YAAM,iBAAiB;AAChB,aAAA,iBAAiBA,UAAS,cAAc;AAAA,IAAA;AAAA,EACjD;AAGK,SAAA;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;"}
1
+ {"version":3,"file":"graphql.es.js","sources":["../../src/graphql/client.ts"],"sourcesContent":["/**\n * GraphQL client for the Nhost JavaScript SDK.\n *\n * This module provides functionality for executing GraphQL operations against\n * a Hasura GraphQL API.\n */\n\nimport type { TypedDocumentNode } from \"@graphql-typed-document-node/core\";\nimport {\n type ChainFunction,\n createEnhancedFetch,\n FetchError,\n type FetchResponse,\n} from \"../fetch\";\n\n/**\n * Variables object for GraphQL operations.\n * Key-value pairs of variable names and their values.\n */\nexport type GraphQLVariables = Record<string, unknown>;\n\n/**\n * GraphQL request object used for queries and mutations.\n */\nexport interface GraphQLRequest<TVariables = GraphQLVariables> {\n /** The GraphQL query or mutation string */\n query: string;\n /** Optional variables for parameterized queries */\n variables?: TVariables;\n /** Optional name of the operation to execute */\n operationName?: string;\n}\n\n/**\n * Represents a GraphQL error returned from the server.\n */\nexport interface GraphQLError {\n /** Error message */\n message: string;\n /** Source locations in the GraphQL document where the error occurred */\n locations?: { line: number; column: number }[];\n /** Path in the query where the error occurred */\n path?: string[];\n /** Additional error information specific to the GraphQL implementation */\n extensions?: { path: string; code: string };\n}\n\n/**\n * Standard GraphQL response format as defined by the GraphQL specification.\n */\nexport interface GraphQLResponse<TResponseData = unknown> {\n /** The data returned from successful execution */\n data?: TResponseData;\n /** Array of errors if execution was unsuccessful or partially successful */\n errors?: GraphQLError[];\n}\n\n/**\n * GraphQL client interface providing methods for executing queries and mutations\n */\nexport interface Client {\n /**\n * Execute a GraphQL query operation\n *\n * Queries are used to fetch data and should not modify any data on the server.\n *\n * @param request - GraphQL request object containing query and optional variables\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData = unknown, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * Execute a GraphQL query operation using a typed document node\n *\n * @param document - TypedDocumentNode containing the query and type information\n * @param variables - Variables for the GraphQL operation\n * @param options - Additional fetch options to apply to the request\n * @returns Promise with the GraphQL response and metadata\n */\n request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n\n /**\n * URL for the GraphQL endpoint.\n */\n url: string;\n}\n\n/**\n * Creates a GraphQL API client for interacting with a GraphQL endpoint.\n *\n * This client provides methods for executing queries and mutations against\n * a GraphQL API, with support for middleware functions to handle authentication,\n * error handling, and other cross-cutting concerns.\n *\n * @param url - Base URL for the GraphQL endpoint\n * @param chainFunctions - Array of middleware functions for the fetch chain\n * @returns GraphQL client with query and mutation methods\n */\nexport const createAPIClient = (\n url: string,\n chainFunctions: ChainFunction[] = [],\n): Client => {\n const enhancedFetch = createEnhancedFetch(chainFunctions);\n\n const executeOperation = async <\n TResponseData = unknown,\n TVariables = GraphQLVariables,\n >(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> => {\n const response = await enhancedFetch(`${url}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(request),\n ...options,\n });\n\n const body = await response.text();\n const data: GraphQLResponse<TResponseData> = (\n body ? JSON.parse(body) : {}\n ) as GraphQLResponse<TResponseData>;\n\n const resp = {\n body: data,\n status: response.status,\n headers: response.headers,\n };\n\n if (data.errors) {\n throw new FetchError(data, response.status, response.headers);\n }\n\n return resp;\n };\n\n function request<TResponseData = unknown, TVariables = GraphQLVariables>(\n request: GraphQLRequest<TVariables>,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n document: TypedDocumentNode<TResponseData, TVariables>,\n variables?: TVariables,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>>;\n function request<TResponseData, TVariables = GraphQLVariables>(\n requestOrDocument:\n | GraphQLRequest<TVariables>\n | TypedDocumentNode<TResponseData, TVariables>,\n variablesOrOptions?: TVariables | RequestInit,\n options?: RequestInit,\n ): Promise<FetchResponse<GraphQLResponse<TResponseData>>> {\n if (typeof requestOrDocument === \"object\" && \"kind\" in requestOrDocument) {\n const definition = requestOrDocument.definitions[0];\n\n const request: GraphQLRequest<TVariables> = {\n query: requestOrDocument.loc?.source.body || \"\",\n variables: variablesOrOptions as TVariables,\n operationName:\n definition && \"name\" in definition\n ? definition.name?.value\n : undefined,\n };\n return executeOperation(request, options);\n } else {\n // Handle GraphQLRequest\n const request = requestOrDocument;\n const requestOptions = variablesOrOptions as RequestInit;\n return executeOperation(request, requestOptions);\n }\n }\n\n return {\n request,\n url,\n } as Client;\n};\n"],"names":["request"],"mappings":";AA0GO,MAAM,kBAAkB,CAC7B,KACA,iBAAkC,OACvB;AACX,QAAM,gBAAgB,oBAAoB,cAAc;AAExD,QAAM,mBAAmB,OAIvBA,UACA,YAC2D;AAC3D,UAAM,WAAW,MAAM,cAAc,GAAG,GAAG,IAAI;AAAA,MAC7C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAUA,QAAO;AAAA,MAC5B,GAAG;AAAA,IAAA,CACJ;AAED,UAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,UAAM,OACJ,OAAO,KAAK,MAAM,IAAI,IAAI,CAAA;AAG5B,UAAM,OAAO;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS;AAAA,IAAA;AAGpB,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,WAAW,MAAM,SAAS,QAAQ,SAAS,OAAO;AAAA,IAC9D;AAEA,WAAO;AAAA,EACT;AAWA,WAAS,QACP,mBAGA,oBACA,SACwD;AACxD,QAAI,OAAO,sBAAsB,YAAY,UAAU,mBAAmB;AACxE,YAAM,aAAa,kBAAkB,YAAY,CAAC;AAElD,YAAMA,WAAsC;AAAA,QAC1C,OAAO,kBAAkB,KAAK,OAAO,QAAQ;AAAA,QAC7C,WAAW;AAAA,QACX,eACE,cAAc,UAAU,aACpB,WAAW,MAAM,QACjB;AAAA,MAAA;AAER,aAAO,iBAAiBA,UAAS,OAAO;AAAA,IAC1C,OAAO;AAEL,YAAMA,WAAU;AAChB,YAAM,iBAAiB;AACvB,aAAO,iBAAiBA,UAAS,cAAc;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EAAA;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../refreshSession-bgb-tiu4.js"),t=e=>e.startsWith("{")&&e.endsWith("}"),s=e=>e&&"{}"!==e?e.slice(1,-1).split(",").map((e=>e.trim().replace(/^"(.*)"$/,"$1"))):[],o="nhostSession";class r{storageKey;constructor(e){this.storageKey=e?.storageKey||o}get(){try{const e=window.localStorage.getItem(this.storageKey);return e?JSON.parse(e):null}catch{return this.remove(),null}}set(e){window.localStorage.setItem(this.storageKey,JSON.stringify(e))}remove(){window.localStorage.removeItem(this.storageKey)}}class i{session=null;get(){return this.session}set(e){this.session=e}remove(){this.session=null}}exports.refreshSession=e.refreshSession,exports.CookieStorage=class{cookieName;expirationDays;secure;sameSite;constructor(e){this.cookieName=e?.cookieName||o,this.expirationDays=e?.expirationDays??30,this.secure=e?.secure??!0,this.sameSite=e?.sameSite||"lax"}get(){const e=document.cookie.split(";");for(const t of e){const[e,s]=t.trim().split("=");if(e===this.cookieName)try{return JSON.parse(decodeURIComponent(s||""))}catch{return this.remove(),null}}return null}set(e){const t=new Date;t.setTime(t.getTime()+24*this.expirationDays*60*60*1e3);const s=encodeURIComponent(JSON.stringify(e)),o=`${this.cookieName}=${s}; expires=${t.toUTCString()}; path=/; ${this.secure?"secure; ":""}SameSite=${this.sameSite}`;document.cookie=o}remove(){document.cookie=`${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure?"secure; ":""}SameSite=${this.sameSite}`}},exports.DEFAULT_SESSION_KEY=o,exports.LocalStorage=r,exports.MemoryStorage=i,exports.SessionStorage=class{storage;subscribers=new Set;constructor(e){this.storage=e}get(){return this.storage.get()}set(e){const o=(e=>{const o=e.split(".");if(3!==o.length||!o[1])throw new Error("Invalid access token format");const r=JSON.parse("undefined"!=typeof atob?atob(o[1]):Buffer.from(o[1],"base64").toString("utf-8")),i="number"==typeof r.iat?1e3*r.iat:void 0,n="number"==typeof r.exp?1e3*r.exp:void 0,a=r["https://hasura.io/jwt/claims"],c=a?Object.entries(a).reduce(((e,[o,r])=>("string"==typeof r&&t(r)?e[o]=s(r):e[o]=r,e)),{}):void 0;return{...r,iat:i,exp:n,"https://hasura.io/jwt/claims":c}})(e.accessToken),r={...e,decodedToken:o};this.storage.set(r),this.notifySubscribers(r)}remove(){this.storage.remove(),this.notifySubscribers(null)}onChange(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}notifySubscribers(e){for(const s of this.subscribers)try{s(e)}catch(t){console.error("Error notifying subscriber:",t)}}},exports.detectStorage=()=>"undefined"!=typeof window?new r:new i;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../refreshSession-Bw715ZmX.js"),t=e=>e.startsWith("{")&&e.endsWith("}"),s=e=>e&&"{}"!==e?e.slice(1,-1).split(",").map((e=>e.trim().replace(/^"(.*)"$/,"$1"))):[],o="nhostSession";class r{storageKey;constructor(e){this.storageKey=e?.storageKey||o}get(){try{const e=window.localStorage.getItem(this.storageKey);return e?JSON.parse(e):null}catch{return this.remove(),null}}set(e){window.localStorage.setItem(this.storageKey,JSON.stringify(e))}remove(){window.localStorage.removeItem(this.storageKey)}}class i{session=null;get(){return this.session}set(e){this.session=e}remove(){this.session=null}}exports.refreshSession=e.refreshSession,exports.CookieStorage=class{cookieName;expirationDays;secure;sameSite;constructor(e){this.cookieName=e?.cookieName||o,this.expirationDays=e?.expirationDays??30,this.secure=e?.secure??!0,this.sameSite=e?.sameSite||"lax"}get(){const e=document.cookie.split(";");for(const t of e){const[e,s]=t.trim().split("=");if(e===this.cookieName)try{return JSON.parse(decodeURIComponent(s||""))}catch{return this.remove(),null}}return null}set(e){const t=new Date;t.setTime(t.getTime()+24*this.expirationDays*60*60*1e3);const s=encodeURIComponent(JSON.stringify(e)),o=`${this.cookieName}=${s}; expires=${t.toUTCString()}; path=/; ${this.secure?"secure; ":""}SameSite=${this.sameSite}`;document.cookie=o}remove(){document.cookie=`${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure?"secure; ":""}SameSite=${this.sameSite}`}},exports.DEFAULT_SESSION_KEY=o,exports.LocalStorage=r,exports.MemoryStorage=i,exports.SessionStorage=class{storage;subscribers=new Set;constructor(e){this.storage=e}get(){return this.storage.get()}set(e){const o=(e=>{const o=e.split(".");if(3!==o.length||!o[1])throw new Error("Invalid access token format");const r=JSON.parse("undefined"!=typeof atob?atob(o[1]):Buffer.from(o[1],"base64").toString("utf-8")),i="number"==typeof r.iat?1e3*r.iat:void 0,n="number"==typeof r.exp?1e3*r.exp:void 0,a=r["https://hasura.io/jwt/claims"],c=a?Object.entries(a).reduce(((e,[o,r])=>("string"==typeof r&&t(r)?e[o]=s(r):e[o]=r,e)),{}):void 0;return{...r,iat:i,exp:n,"https://hasura.io/jwt/claims":c}})(e.accessToken),r={...e,decodedToken:o};this.storage.set(r),this.notifySubscribers(r)}remove(){this.storage.remove(),this.notifySubscribers(null)}onChange(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}notifySubscribers(e){for(const s of this.subscribers)try{s(e)}catch(t){console.error("Error notifying subscriber:",t)}}},exports.detectStorage=()=>"undefined"!=typeof window?new r:new i;
2
2
  //# sourceMappingURL=session.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.cjs.js","sources":["../../src/session/session.ts","../../src/session/storageBackend.ts","../../src/session/storage.ts"],"sourcesContent":["import type { Session as AuthSession } from \"../auth\";\n\n/**\n * Decoded JWT token payload with processed timestamps and Hasura claims\n */\nexport interface DecodedToken {\n /** Token expiration time as Date object */\n exp?: number;\n /** Token issued at time as Date object */\n iat?: number;\n /** Token issuer */\n iss?: string;\n /** Token subject (user ID) */\n sub?: string;\n /** Hasura JWT claims with PostgreSQL arrays converted to JavaScript arrays */\n \"https://hasura.io/jwt/claims\"?: Record<string, unknown>;\n /** Any other JWT claims */\n [key: string]: unknown;\n}\n\nexport interface Session extends AuthSession {\n /** Decoded JWT token payload with processed timestamps and Hasura claims */\n decodedToken: DecodedToken;\n}\n\nexport const decodeUserSession = (accessToken: string): DecodedToken => {\n const s = accessToken.split(\".\");\n if (s.length !== 3 || !s[1]) {\n throw new Error(\"Invalid access token format\");\n }\n\n const decodedToken = JSON.parse(\n typeof atob !== \"undefined\"\n ? atob(s[1])\n : Buffer.from(s[1], \"base64\").toString(\"utf-8\"),\n ) as Record<string, unknown>;\n\n // Convert iat and exp to Date objects\n const iat =\n typeof decodedToken[\"iat\"] === \"number\"\n ? decodedToken[\"iat\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n const exp =\n typeof decodedToken[\"exp\"] === \"number\"\n ? decodedToken[\"exp\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n\n // Process Hasura claims - dynamically convert PostgreSQL array notation to arrays\n const hasuraClaims = decodedToken[\"https://hasura.io/jwt/claims\"] as\n | Record<string, unknown>\n | undefined;\n const processedClaims = hasuraClaims\n ? Object.entries(hasuraClaims).reduce(\n (acc, [key, value]) => {\n if (typeof value === \"string\" && isPostgresArray(value)) {\n acc[key] = parsePostgresArray(value);\n } else {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, unknown>,\n )\n : undefined;\n\n return {\n ...decodedToken,\n iat,\n exp,\n \"https://hasura.io/jwt/claims\": processedClaims,\n };\n};\n\nconst isPostgresArray = (value: string): boolean => {\n return value.startsWith(\"{\") && value.endsWith(\"}\");\n};\n\nconst parsePostgresArray = (value: string): string[] => {\n if (!value || value === \"{}\") return [];\n // Remove curly braces and split by comma, handling quoted values\n return value\n .slice(1, -1)\n .split(\",\")\n .map((item) => item.trim().replace(/^\"(.*)\"$/, \"$1\"));\n};\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session } from \"./session\";\n\n/**\n * Session storage interface for session persistence.\n * This interface can be implemented to provide custom storage solutions.\n */\nexport interface SessionStorageBackend {\n /**\n * Get the current session from storage\n * @returns The stored session or null if not found\n */\n get(): Session | null;\n\n /**\n * Set the session in storage\n * @param value - The session to store\n */\n set(value: Session): void;\n\n /**\n * Remove the session from storage\n */\n remove(): void;\n}\n\n/**\n * Default storage key used for storing the Nhost session\n */\nexport const DEFAULT_SESSION_KEY = \"nhostSession\";\n\n/**\n * Browser localStorage implementation of StorageInterface.\n * Persists the session across page reloads and browser restarts.\n */\nexport class LocalStorage implements SessionStorageBackend {\n private readonly storageKey: string;\n\n /**\n * Creates a new LocalStorage instance\n * @param options - Configuration options\n * @param options.storageKey - The key to use in localStorage (defaults to \"nhostSession\")\n */\n constructor(options?: { storageKey?: string }) {\n this.storageKey = options?.storageKey || DEFAULT_SESSION_KEY;\n }\n\n /**\n * Gets the session from localStorage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n try {\n const value = window.localStorage.getItem(this.storageKey);\n return value ? (JSON.parse(value) as Session) : null;\n } catch {\n this.remove();\n return null;\n }\n }\n\n /**\n * Sets the session in localStorage\n * @param value - The session to store\n */\n set(value: Session): void {\n window.localStorage.setItem(this.storageKey, JSON.stringify(value));\n }\n\n /**\n * Removes the session from localStorage\n */\n remove(): void {\n window.localStorage.removeItem(this.storageKey);\n }\n}\n\n/**\n * In-memory storage implementation for non-browser environments or when\n * persistent storage is not available or desirable.\n */\nexport class MemoryStorage implements SessionStorageBackend {\n private session: Session | null = null;\n\n /**\n * Gets the session from memory\n * @returns The stored session or null if not set\n */\n get(): Session | null {\n return this.session;\n }\n\n /**\n * Sets the session in memory\n * @param value - The session to store\n */\n set(value: Session): void {\n this.session = value;\n }\n\n /**\n * Clears the session from memory\n */\n remove(): void {\n this.session = null;\n }\n}\n\n/**\n * Cookie-based storage implementation.\n * This storage uses web browser cookies to store the session so it's not\n * available in server-side environments. It is useful though for synchronizing\n * sessions between client and server environments.\n */\nexport class CookieStorage implements SessionStorageBackend {\n private readonly cookieName: string;\n private readonly expirationDays: number;\n private readonly secure: boolean;\n private readonly sameSite: \"strict\" | \"lax\" | \"none\";\n\n /**\n * Creates a new CookieStorage instance\n * @param options - Configuration options\n * @param options.cookieName - Name of the cookie to use (defaults to \"nhostSession\")\n * @param options.expirationDays - Number of days until the cookie expires (defaults to 30)\n * @param options.secure - Whether to set the Secure flag on the cookie (defaults to true)\n * @param options.sameSite - SameSite policy for the cookie (defaults to \"lax\")\n */\n constructor(options?: {\n cookieName?: string;\n expirationDays?: number;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n }) {\n this.cookieName = options?.cookieName || DEFAULT_SESSION_KEY;\n this.expirationDays = options?.expirationDays ?? 30;\n this.secure = options?.secure ?? true;\n this.sameSite = options?.sameSite || \"lax\";\n }\n\n /**\n * Gets the session from cookies\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === this.cookieName) {\n try {\n return JSON.parse(decodeURIComponent(value || \"\")) as Session;\n } catch {\n this.remove();\n return null;\n }\n }\n }\n return null;\n }\n\n /**\n * Sets the session in a cookie\n * @param value - The session to store\n */\n set(value: Session): void {\n const expires = new Date();\n expires.setTime(\n expires.getTime() + this.expirationDays * 24 * 60 * 60 * 1000,\n );\n\n const cookieValue = encodeURIComponent(JSON.stringify(value));\n const cookieString = `${this.cookieName}=${cookieValue}; expires=${expires.toUTCString()}; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n\n document.cookie = cookieString;\n }\n\n /**\n * Removes the session cookie\n */\n remove(): void {\n document.cookie = `${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n }\n}\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport {\n type SessionStorageBackend,\n LocalStorage,\n MemoryStorage,\n} from \"./storageBackend\";\nimport { decodeUserSession, type Session } from \"./session\";\nimport type { Session as AuthSession } from \"../auth\";\n\n/**\n * Callback function type for session change subscriptions\n */\nexport type SessionChangeCallback = (session: Session | null) => void;\n\n/**\n * A wrapper around any SessionStorageInterface implementation that adds\n * the ability to subscribe to session changes.\n */\nexport class SessionStorage {\n private readonly storage: SessionStorageBackend;\n private subscribers = new Set<SessionChangeCallback>();\n\n /**\n * Creates a new SessionStorage instance\n * @param storage - The underlying storage implementation to use\n */\n constructor(storage: SessionStorageBackend) {\n this.storage = storage;\n }\n\n /**\n * Gets the session from the underlying storage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n return this.storage.get();\n }\n\n /**\n * Sets the session in the underlying storage and notifies subscribers\n * @param value - The session to store\n */\n set(value: AuthSession): void {\n const decodedToken = decodeUserSession(value.accessToken);\n const decodedSession = {\n ...value,\n decodedToken: decodedToken,\n };\n\n this.storage.set(decodedSession);\n this.notifySubscribers(decodedSession);\n }\n\n /**\n * Removes the session from the underlying storage and notifies subscribers\n */\n remove(): void {\n this.storage.remove();\n this.notifySubscribers(null);\n }\n\n /**\n * Subscribe to session changes\n * @param callback - Function that will be called when the session changes\n * @returns An unsubscribe function to remove this subscription\n */\n onChange(callback: SessionChangeCallback) {\n this.subscribers.add(callback);\n\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers of a session change\n * @param session - The new session value or null if removed\n */\n private notifySubscribers(session: Session | null): void {\n for (const subscriber of this.subscribers) {\n try {\n subscriber(session);\n } catch (error) {\n console.error(\"Error notifying subscriber:\", error);\n }\n }\n }\n}\n\n/**\n * Detects the best available storage implementation for the current environment.\n *\n * The detection process follows this order:\n * 1. Try to use localStorage if we're in a browser environment\n * 2. Fall back to in-memory storage if localStorage isn't available\n *\n * @returns The best available storage implementation as a SessionStorageBackend\n */\nexport const detectStorage = (): SessionStorageBackend => {\n if (typeof window !== \"undefined\") {\n return new LocalStorage();\n }\n return new MemoryStorage();\n};\n"],"names":["isPostgresArray","value","startsWith","endsWith","parsePostgresArray","slice","split","map","item","trim","replace","DEFAULT_SESSION_KEY","LocalStorage","storageKey","constructor","options","this","get","window","localStorage","getItem","JSON","parse","remove","set","setItem","stringify","removeItem","MemoryStorage","session","cookieName","expirationDays","secure","sameSite","cookies","document","cookie","name","decodeURIComponent","expires","Date","setTime","getTime","cookieValue","encodeURIComponent","cookieString","toUTCString","storage","subscribers","Set","decodedToken","accessToken","s","length","Error","atob","Buffer","from","toString","iat","exp","hasuraClaims","processedClaims","Object","entries","reduce","acc","key","decodeUserSession","decodedSession","notifySubscribers","onChange","callback","add","delete","subscriber","error","console"],"mappings":"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"}
1
+ {"version":3,"file":"session.cjs.js","sources":["../../src/session/session.ts","../../src/session/storageBackend.ts","../../src/session/storage.ts"],"sourcesContent":["import type { Session as AuthSession } from \"../auth\";\n\n/**\n * Decoded JWT token payload with processed timestamps and Hasura claims\n */\nexport interface DecodedToken {\n /** Token expiration time as Date object */\n exp?: number;\n /** Token issued at time as Date object */\n iat?: number;\n /** Token issuer */\n iss?: string;\n /** Token subject (user ID) */\n sub?: string;\n /** Hasura JWT claims with PostgreSQL arrays converted to JavaScript arrays */\n \"https://hasura.io/jwt/claims\"?: Record<string, unknown>;\n /** Any other JWT claims */\n [key: string]: unknown;\n}\n\nexport interface Session extends AuthSession {\n /** Decoded JWT token payload with processed timestamps and Hasura claims */\n decodedToken: DecodedToken;\n}\n\nexport const decodeUserSession = (accessToken: string): DecodedToken => {\n const s = accessToken.split(\".\");\n if (s.length !== 3 || !s[1]) {\n throw new Error(\"Invalid access token format\");\n }\n\n const decodedToken = JSON.parse(\n typeof atob !== \"undefined\"\n ? atob(s[1])\n : Buffer.from(s[1], \"base64\").toString(\"utf-8\"),\n ) as Record<string, unknown>;\n\n // Convert iat and exp to Date objects\n const iat =\n typeof decodedToken[\"iat\"] === \"number\"\n ? decodedToken[\"iat\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n const exp =\n typeof decodedToken[\"exp\"] === \"number\"\n ? decodedToken[\"exp\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n\n // Process Hasura claims - dynamically convert PostgreSQL array notation to arrays\n const hasuraClaims = decodedToken[\"https://hasura.io/jwt/claims\"] as\n | Record<string, unknown>\n | undefined;\n const processedClaims = hasuraClaims\n ? Object.entries(hasuraClaims).reduce(\n (acc, [key, value]) => {\n if (typeof value === \"string\" && isPostgresArray(value)) {\n acc[key] = parsePostgresArray(value);\n } else {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, unknown>,\n )\n : undefined;\n\n return {\n ...decodedToken,\n iat,\n exp,\n \"https://hasura.io/jwt/claims\": processedClaims,\n };\n};\n\nconst isPostgresArray = (value: string): boolean => {\n return value.startsWith(\"{\") && value.endsWith(\"}\");\n};\n\nconst parsePostgresArray = (value: string): string[] => {\n if (!value || value === \"{}\") return [];\n // Remove curly braces and split by comma, handling quoted values\n return value\n .slice(1, -1)\n .split(\",\")\n .map((item) => item.trim().replace(/^\"(.*)\"$/, \"$1\"));\n};\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session } from \"./session\";\n\n/**\n * Session storage interface for session persistence.\n * This interface can be implemented to provide custom storage solutions.\n */\nexport interface SessionStorageBackend {\n /**\n * Get the current session from storage\n * @returns The stored session or null if not found\n */\n get(): Session | null;\n\n /**\n * Set the session in storage\n * @param value - The session to store\n */\n set(value: Session): void;\n\n /**\n * Remove the session from storage\n */\n remove(): void;\n}\n\n/**\n * Default storage key used for storing the Nhost session\n */\nexport const DEFAULT_SESSION_KEY = \"nhostSession\";\n\n/**\n * Browser localStorage implementation of StorageInterface.\n * Persists the session across page reloads and browser restarts.\n */\nexport class LocalStorage implements SessionStorageBackend {\n private readonly storageKey: string;\n\n /**\n * Creates a new LocalStorage instance\n * @param options - Configuration options\n * @param options.storageKey - The key to use in localStorage (defaults to \"nhostSession\")\n */\n constructor(options?: { storageKey?: string }) {\n this.storageKey = options?.storageKey || DEFAULT_SESSION_KEY;\n }\n\n /**\n * Gets the session from localStorage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n try {\n const value = window.localStorage.getItem(this.storageKey);\n return value ? (JSON.parse(value) as Session) : null;\n } catch {\n this.remove();\n return null;\n }\n }\n\n /**\n * Sets the session in localStorage\n * @param value - The session to store\n */\n set(value: Session): void {\n window.localStorage.setItem(this.storageKey, JSON.stringify(value));\n }\n\n /**\n * Removes the session from localStorage\n */\n remove(): void {\n window.localStorage.removeItem(this.storageKey);\n }\n}\n\n/**\n * In-memory storage implementation for non-browser environments or when\n * persistent storage is not available or desirable.\n */\nexport class MemoryStorage implements SessionStorageBackend {\n private session: Session | null = null;\n\n /**\n * Gets the session from memory\n * @returns The stored session or null if not set\n */\n get(): Session | null {\n return this.session;\n }\n\n /**\n * Sets the session in memory\n * @param value - The session to store\n */\n set(value: Session): void {\n this.session = value;\n }\n\n /**\n * Clears the session from memory\n */\n remove(): void {\n this.session = null;\n }\n}\n\n/**\n * Cookie-based storage implementation.\n * This storage uses web browser cookies to store the session so it's not\n * available in server-side environments. It is useful though for synchronizing\n * sessions between client and server environments.\n */\nexport class CookieStorage implements SessionStorageBackend {\n private readonly cookieName: string;\n private readonly expirationDays: number;\n private readonly secure: boolean;\n private readonly sameSite: \"strict\" | \"lax\" | \"none\";\n\n /**\n * Creates a new CookieStorage instance\n * @param options - Configuration options\n * @param options.cookieName - Name of the cookie to use (defaults to \"nhostSession\")\n * @param options.expirationDays - Number of days until the cookie expires (defaults to 30)\n * @param options.secure - Whether to set the Secure flag on the cookie (defaults to true)\n * @param options.sameSite - SameSite policy for the cookie (defaults to \"lax\")\n */\n constructor(options?: {\n cookieName?: string;\n expirationDays?: number;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n }) {\n this.cookieName = options?.cookieName || DEFAULT_SESSION_KEY;\n this.expirationDays = options?.expirationDays ?? 30;\n this.secure = options?.secure ?? true;\n this.sameSite = options?.sameSite || \"lax\";\n }\n\n /**\n * Gets the session from cookies\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === this.cookieName) {\n try {\n return JSON.parse(decodeURIComponent(value || \"\")) as Session;\n } catch {\n this.remove();\n return null;\n }\n }\n }\n return null;\n }\n\n /**\n * Sets the session in a cookie\n * @param value - The session to store\n */\n set(value: Session): void {\n const expires = new Date();\n expires.setTime(\n expires.getTime() + this.expirationDays * 24 * 60 * 60 * 1000,\n );\n\n const cookieValue = encodeURIComponent(JSON.stringify(value));\n const cookieString = `${this.cookieName}=${cookieValue}; expires=${expires.toUTCString()}; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n\n // biome-ignore lint/suspicious/noDocumentCookie: this is unnecessary\n document.cookie = cookieString;\n }\n\n /**\n * Removes the session cookie\n */\n remove(): void {\n // biome-ignore lint/suspicious/noDocumentCookie: this is unnecessary\n document.cookie = `${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n }\n}\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session as AuthSession } from \"../auth\";\nimport { decodeUserSession, type Session } from \"./session\";\nimport {\n LocalStorage,\n MemoryStorage,\n type SessionStorageBackend,\n} from \"./storageBackend\";\n\n/**\n * Callback function type for session change subscriptions\n */\nexport type SessionChangeCallback = (session: Session | null) => void;\n\n/**\n * A wrapper around any SessionStorageInterface implementation that adds\n * the ability to subscribe to session changes.\n */\nexport class SessionStorage {\n private readonly storage: SessionStorageBackend;\n private subscribers = new Set<SessionChangeCallback>();\n\n /**\n * Creates a new SessionStorage instance\n * @param storage - The underlying storage implementation to use\n */\n constructor(storage: SessionStorageBackend) {\n this.storage = storage;\n }\n\n /**\n * Gets the session from the underlying storage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n return this.storage.get();\n }\n\n /**\n * Sets the session in the underlying storage and notifies subscribers\n * @param value - The session to store\n */\n set(value: AuthSession): void {\n const decodedToken = decodeUserSession(value.accessToken);\n const decodedSession = {\n ...value,\n decodedToken: decodedToken,\n };\n\n this.storage.set(decodedSession);\n this.notifySubscribers(decodedSession);\n }\n\n /**\n * Removes the session from the underlying storage and notifies subscribers\n */\n remove(): void {\n this.storage.remove();\n this.notifySubscribers(null);\n }\n\n /**\n * Subscribe to session changes\n * @param callback - Function that will be called when the session changes\n * @returns An unsubscribe function to remove this subscription\n */\n onChange(callback: SessionChangeCallback) {\n this.subscribers.add(callback);\n\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers of a session change\n * @param session - The new session value or null if removed\n */\n private notifySubscribers(session: Session | null): void {\n for (const subscriber of this.subscribers) {\n try {\n subscriber(session);\n } catch (error) {\n console.error(\"Error notifying subscriber:\", error);\n }\n }\n }\n}\n\n/**\n * Detects the best available storage implementation for the current environment.\n *\n * The detection process follows this order:\n * 1. Try to use localStorage if we're in a browser environment\n * 2. Fall back to in-memory storage if localStorage isn't available\n *\n * @returns The best available storage implementation as a SessionStorageBackend\n */\nexport const detectStorage = (): SessionStorageBackend => {\n if (typeof window !== \"undefined\") {\n return new LocalStorage();\n }\n return new MemoryStorage();\n};\n"],"names":["isPostgresArray","value","startsWith","endsWith","parsePostgresArray","slice","split","map","item","trim","replace","DEFAULT_SESSION_KEY","LocalStorage","storageKey","constructor","options","this","get","window","localStorage","getItem","JSON","parse","remove","set","setItem","stringify","removeItem","MemoryStorage","session","cookieName","expirationDays","secure","sameSite","cookies","document","cookie","name","decodeURIComponent","expires","Date","setTime","getTime","cookieValue","encodeURIComponent","cookieString","toUTCString","storage","subscribers","Set","decodedToken","accessToken","s","length","Error","atob","Buffer","from","toString","iat","exp","hasuraClaims","processedClaims","Object","entries","reduce","acc","key","decodeUserSession","decodedSession","notifySubscribers","onChange","callback","add","delete","subscriber","error","console"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { r } from "../refreshSession-cGdPdFoG.mjs";
1
+ import { r } from "../refreshSession-WwGlzgtM.mjs";
2
2
  const decodeUserSession = (accessToken) => {
3
3
  const s = accessToken.split(".");
4
4
  if (s.length !== 3 || !s[1]) {
@@ -1 +1 @@
1
- {"version":3,"file":"session.es.js","sources":["../../src/session/session.ts","../../src/session/storageBackend.ts","../../src/session/storage.ts"],"sourcesContent":["import type { Session as AuthSession } from \"../auth\";\n\n/**\n * Decoded JWT token payload with processed timestamps and Hasura claims\n */\nexport interface DecodedToken {\n /** Token expiration time as Date object */\n exp?: number;\n /** Token issued at time as Date object */\n iat?: number;\n /** Token issuer */\n iss?: string;\n /** Token subject (user ID) */\n sub?: string;\n /** Hasura JWT claims with PostgreSQL arrays converted to JavaScript arrays */\n \"https://hasura.io/jwt/claims\"?: Record<string, unknown>;\n /** Any other JWT claims */\n [key: string]: unknown;\n}\n\nexport interface Session extends AuthSession {\n /** Decoded JWT token payload with processed timestamps and Hasura claims */\n decodedToken: DecodedToken;\n}\n\nexport const decodeUserSession = (accessToken: string): DecodedToken => {\n const s = accessToken.split(\".\");\n if (s.length !== 3 || !s[1]) {\n throw new Error(\"Invalid access token format\");\n }\n\n const decodedToken = JSON.parse(\n typeof atob !== \"undefined\"\n ? atob(s[1])\n : Buffer.from(s[1], \"base64\").toString(\"utf-8\"),\n ) as Record<string, unknown>;\n\n // Convert iat and exp to Date objects\n const iat =\n typeof decodedToken[\"iat\"] === \"number\"\n ? decodedToken[\"iat\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n const exp =\n typeof decodedToken[\"exp\"] === \"number\"\n ? decodedToken[\"exp\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n\n // Process Hasura claims - dynamically convert PostgreSQL array notation to arrays\n const hasuraClaims = decodedToken[\"https://hasura.io/jwt/claims\"] as\n | Record<string, unknown>\n | undefined;\n const processedClaims = hasuraClaims\n ? Object.entries(hasuraClaims).reduce(\n (acc, [key, value]) => {\n if (typeof value === \"string\" && isPostgresArray(value)) {\n acc[key] = parsePostgresArray(value);\n } else {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, unknown>,\n )\n : undefined;\n\n return {\n ...decodedToken,\n iat,\n exp,\n \"https://hasura.io/jwt/claims\": processedClaims,\n };\n};\n\nconst isPostgresArray = (value: string): boolean => {\n return value.startsWith(\"{\") && value.endsWith(\"}\");\n};\n\nconst parsePostgresArray = (value: string): string[] => {\n if (!value || value === \"{}\") return [];\n // Remove curly braces and split by comma, handling quoted values\n return value\n .slice(1, -1)\n .split(\",\")\n .map((item) => item.trim().replace(/^\"(.*)\"$/, \"$1\"));\n};\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session } from \"./session\";\n\n/**\n * Session storage interface for session persistence.\n * This interface can be implemented to provide custom storage solutions.\n */\nexport interface SessionStorageBackend {\n /**\n * Get the current session from storage\n * @returns The stored session or null if not found\n */\n get(): Session | null;\n\n /**\n * Set the session in storage\n * @param value - The session to store\n */\n set(value: Session): void;\n\n /**\n * Remove the session from storage\n */\n remove(): void;\n}\n\n/**\n * Default storage key used for storing the Nhost session\n */\nexport const DEFAULT_SESSION_KEY = \"nhostSession\";\n\n/**\n * Browser localStorage implementation of StorageInterface.\n * Persists the session across page reloads and browser restarts.\n */\nexport class LocalStorage implements SessionStorageBackend {\n private readonly storageKey: string;\n\n /**\n * Creates a new LocalStorage instance\n * @param options - Configuration options\n * @param options.storageKey - The key to use in localStorage (defaults to \"nhostSession\")\n */\n constructor(options?: { storageKey?: string }) {\n this.storageKey = options?.storageKey || DEFAULT_SESSION_KEY;\n }\n\n /**\n * Gets the session from localStorage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n try {\n const value = window.localStorage.getItem(this.storageKey);\n return value ? (JSON.parse(value) as Session) : null;\n } catch {\n this.remove();\n return null;\n }\n }\n\n /**\n * Sets the session in localStorage\n * @param value - The session to store\n */\n set(value: Session): void {\n window.localStorage.setItem(this.storageKey, JSON.stringify(value));\n }\n\n /**\n * Removes the session from localStorage\n */\n remove(): void {\n window.localStorage.removeItem(this.storageKey);\n }\n}\n\n/**\n * In-memory storage implementation for non-browser environments or when\n * persistent storage is not available or desirable.\n */\nexport class MemoryStorage implements SessionStorageBackend {\n private session: Session | null = null;\n\n /**\n * Gets the session from memory\n * @returns The stored session or null if not set\n */\n get(): Session | null {\n return this.session;\n }\n\n /**\n * Sets the session in memory\n * @param value - The session to store\n */\n set(value: Session): void {\n this.session = value;\n }\n\n /**\n * Clears the session from memory\n */\n remove(): void {\n this.session = null;\n }\n}\n\n/**\n * Cookie-based storage implementation.\n * This storage uses web browser cookies to store the session so it's not\n * available in server-side environments. It is useful though for synchronizing\n * sessions between client and server environments.\n */\nexport class CookieStorage implements SessionStorageBackend {\n private readonly cookieName: string;\n private readonly expirationDays: number;\n private readonly secure: boolean;\n private readonly sameSite: \"strict\" | \"lax\" | \"none\";\n\n /**\n * Creates a new CookieStorage instance\n * @param options - Configuration options\n * @param options.cookieName - Name of the cookie to use (defaults to \"nhostSession\")\n * @param options.expirationDays - Number of days until the cookie expires (defaults to 30)\n * @param options.secure - Whether to set the Secure flag on the cookie (defaults to true)\n * @param options.sameSite - SameSite policy for the cookie (defaults to \"lax\")\n */\n constructor(options?: {\n cookieName?: string;\n expirationDays?: number;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n }) {\n this.cookieName = options?.cookieName || DEFAULT_SESSION_KEY;\n this.expirationDays = options?.expirationDays ?? 30;\n this.secure = options?.secure ?? true;\n this.sameSite = options?.sameSite || \"lax\";\n }\n\n /**\n * Gets the session from cookies\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === this.cookieName) {\n try {\n return JSON.parse(decodeURIComponent(value || \"\")) as Session;\n } catch {\n this.remove();\n return null;\n }\n }\n }\n return null;\n }\n\n /**\n * Sets the session in a cookie\n * @param value - The session to store\n */\n set(value: Session): void {\n const expires = new Date();\n expires.setTime(\n expires.getTime() + this.expirationDays * 24 * 60 * 60 * 1000,\n );\n\n const cookieValue = encodeURIComponent(JSON.stringify(value));\n const cookieString = `${this.cookieName}=${cookieValue}; expires=${expires.toUTCString()}; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n\n document.cookie = cookieString;\n }\n\n /**\n * Removes the session cookie\n */\n remove(): void {\n document.cookie = `${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n }\n}\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport {\n type SessionStorageBackend,\n LocalStorage,\n MemoryStorage,\n} from \"./storageBackend\";\nimport { decodeUserSession, type Session } from \"./session\";\nimport type { Session as AuthSession } from \"../auth\";\n\n/**\n * Callback function type for session change subscriptions\n */\nexport type SessionChangeCallback = (session: Session | null) => void;\n\n/**\n * A wrapper around any SessionStorageInterface implementation that adds\n * the ability to subscribe to session changes.\n */\nexport class SessionStorage {\n private readonly storage: SessionStorageBackend;\n private subscribers = new Set<SessionChangeCallback>();\n\n /**\n * Creates a new SessionStorage instance\n * @param storage - The underlying storage implementation to use\n */\n constructor(storage: SessionStorageBackend) {\n this.storage = storage;\n }\n\n /**\n * Gets the session from the underlying storage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n return this.storage.get();\n }\n\n /**\n * Sets the session in the underlying storage and notifies subscribers\n * @param value - The session to store\n */\n set(value: AuthSession): void {\n const decodedToken = decodeUserSession(value.accessToken);\n const decodedSession = {\n ...value,\n decodedToken: decodedToken,\n };\n\n this.storage.set(decodedSession);\n this.notifySubscribers(decodedSession);\n }\n\n /**\n * Removes the session from the underlying storage and notifies subscribers\n */\n remove(): void {\n this.storage.remove();\n this.notifySubscribers(null);\n }\n\n /**\n * Subscribe to session changes\n * @param callback - Function that will be called when the session changes\n * @returns An unsubscribe function to remove this subscription\n */\n onChange(callback: SessionChangeCallback) {\n this.subscribers.add(callback);\n\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers of a session change\n * @param session - The new session value or null if removed\n */\n private notifySubscribers(session: Session | null): void {\n for (const subscriber of this.subscribers) {\n try {\n subscriber(session);\n } catch (error) {\n console.error(\"Error notifying subscriber:\", error);\n }\n }\n }\n}\n\n/**\n * Detects the best available storage implementation for the current environment.\n *\n * The detection process follows this order:\n * 1. Try to use localStorage if we're in a browser environment\n * 2. Fall back to in-memory storage if localStorage isn't available\n *\n * @returns The best available storage implementation as a SessionStorageBackend\n */\nexport const detectStorage = (): SessionStorageBackend => {\n if (typeof window !== \"undefined\") {\n return new LocalStorage();\n }\n return new MemoryStorage();\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.es.js","sources":["../../src/session/session.ts","../../src/session/storageBackend.ts","../../src/session/storage.ts"],"sourcesContent":["import type { Session as AuthSession } from \"../auth\";\n\n/**\n * Decoded JWT token payload with processed timestamps and Hasura claims\n */\nexport interface DecodedToken {\n /** Token expiration time as Date object */\n exp?: number;\n /** Token issued at time as Date object */\n iat?: number;\n /** Token issuer */\n iss?: string;\n /** Token subject (user ID) */\n sub?: string;\n /** Hasura JWT claims with PostgreSQL arrays converted to JavaScript arrays */\n \"https://hasura.io/jwt/claims\"?: Record<string, unknown>;\n /** Any other JWT claims */\n [key: string]: unknown;\n}\n\nexport interface Session extends AuthSession {\n /** Decoded JWT token payload with processed timestamps and Hasura claims */\n decodedToken: DecodedToken;\n}\n\nexport const decodeUserSession = (accessToken: string): DecodedToken => {\n const s = accessToken.split(\".\");\n if (s.length !== 3 || !s[1]) {\n throw new Error(\"Invalid access token format\");\n }\n\n const decodedToken = JSON.parse(\n typeof atob !== \"undefined\"\n ? atob(s[1])\n : Buffer.from(s[1], \"base64\").toString(\"utf-8\"),\n ) as Record<string, unknown>;\n\n // Convert iat and exp to Date objects\n const iat =\n typeof decodedToken[\"iat\"] === \"number\"\n ? decodedToken[\"iat\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n const exp =\n typeof decodedToken[\"exp\"] === \"number\"\n ? decodedToken[\"exp\"] * 1000 // Convert seconds to milliseconds\n : undefined;\n\n // Process Hasura claims - dynamically convert PostgreSQL array notation to arrays\n const hasuraClaims = decodedToken[\"https://hasura.io/jwt/claims\"] as\n | Record<string, unknown>\n | undefined;\n const processedClaims = hasuraClaims\n ? Object.entries(hasuraClaims).reduce(\n (acc, [key, value]) => {\n if (typeof value === \"string\" && isPostgresArray(value)) {\n acc[key] = parsePostgresArray(value);\n } else {\n acc[key] = value;\n }\n return acc;\n },\n {} as Record<string, unknown>,\n )\n : undefined;\n\n return {\n ...decodedToken,\n iat,\n exp,\n \"https://hasura.io/jwt/claims\": processedClaims,\n };\n};\n\nconst isPostgresArray = (value: string): boolean => {\n return value.startsWith(\"{\") && value.endsWith(\"}\");\n};\n\nconst parsePostgresArray = (value: string): string[] => {\n if (!value || value === \"{}\") return [];\n // Remove curly braces and split by comma, handling quoted values\n return value\n .slice(1, -1)\n .split(\",\")\n .map((item) => item.trim().replace(/^\"(.*)\"$/, \"$1\"));\n};\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session } from \"./session\";\n\n/**\n * Session storage interface for session persistence.\n * This interface can be implemented to provide custom storage solutions.\n */\nexport interface SessionStorageBackend {\n /**\n * Get the current session from storage\n * @returns The stored session or null if not found\n */\n get(): Session | null;\n\n /**\n * Set the session in storage\n * @param value - The session to store\n */\n set(value: Session): void;\n\n /**\n * Remove the session from storage\n */\n remove(): void;\n}\n\n/**\n * Default storage key used for storing the Nhost session\n */\nexport const DEFAULT_SESSION_KEY = \"nhostSession\";\n\n/**\n * Browser localStorage implementation of StorageInterface.\n * Persists the session across page reloads and browser restarts.\n */\nexport class LocalStorage implements SessionStorageBackend {\n private readonly storageKey: string;\n\n /**\n * Creates a new LocalStorage instance\n * @param options - Configuration options\n * @param options.storageKey - The key to use in localStorage (defaults to \"nhostSession\")\n */\n constructor(options?: { storageKey?: string }) {\n this.storageKey = options?.storageKey || DEFAULT_SESSION_KEY;\n }\n\n /**\n * Gets the session from localStorage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n try {\n const value = window.localStorage.getItem(this.storageKey);\n return value ? (JSON.parse(value) as Session) : null;\n } catch {\n this.remove();\n return null;\n }\n }\n\n /**\n * Sets the session in localStorage\n * @param value - The session to store\n */\n set(value: Session): void {\n window.localStorage.setItem(this.storageKey, JSON.stringify(value));\n }\n\n /**\n * Removes the session from localStorage\n */\n remove(): void {\n window.localStorage.removeItem(this.storageKey);\n }\n}\n\n/**\n * In-memory storage implementation for non-browser environments or when\n * persistent storage is not available or desirable.\n */\nexport class MemoryStorage implements SessionStorageBackend {\n private session: Session | null = null;\n\n /**\n * Gets the session from memory\n * @returns The stored session or null if not set\n */\n get(): Session | null {\n return this.session;\n }\n\n /**\n * Sets the session in memory\n * @param value - The session to store\n */\n set(value: Session): void {\n this.session = value;\n }\n\n /**\n * Clears the session from memory\n */\n remove(): void {\n this.session = null;\n }\n}\n\n/**\n * Cookie-based storage implementation.\n * This storage uses web browser cookies to store the session so it's not\n * available in server-side environments. It is useful though for synchronizing\n * sessions between client and server environments.\n */\nexport class CookieStorage implements SessionStorageBackend {\n private readonly cookieName: string;\n private readonly expirationDays: number;\n private readonly secure: boolean;\n private readonly sameSite: \"strict\" | \"lax\" | \"none\";\n\n /**\n * Creates a new CookieStorage instance\n * @param options - Configuration options\n * @param options.cookieName - Name of the cookie to use (defaults to \"nhostSession\")\n * @param options.expirationDays - Number of days until the cookie expires (defaults to 30)\n * @param options.secure - Whether to set the Secure flag on the cookie (defaults to true)\n * @param options.sameSite - SameSite policy for the cookie (defaults to \"lax\")\n */\n constructor(options?: {\n cookieName?: string;\n expirationDays?: number;\n secure?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n }) {\n this.cookieName = options?.cookieName || DEFAULT_SESSION_KEY;\n this.expirationDays = options?.expirationDays ?? 30;\n this.secure = options?.secure ?? true;\n this.sameSite = options?.sameSite || \"lax\";\n }\n\n /**\n * Gets the session from cookies\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n const cookies = document.cookie.split(\";\");\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split(\"=\");\n if (name === this.cookieName) {\n try {\n return JSON.parse(decodeURIComponent(value || \"\")) as Session;\n } catch {\n this.remove();\n return null;\n }\n }\n }\n return null;\n }\n\n /**\n * Sets the session in a cookie\n * @param value - The session to store\n */\n set(value: Session): void {\n const expires = new Date();\n expires.setTime(\n expires.getTime() + this.expirationDays * 24 * 60 * 60 * 1000,\n );\n\n const cookieValue = encodeURIComponent(JSON.stringify(value));\n const cookieString = `${this.cookieName}=${cookieValue}; expires=${expires.toUTCString()}; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n\n // biome-ignore lint/suspicious/noDocumentCookie: this is unnecessary\n document.cookie = cookieString;\n }\n\n /**\n * Removes the session cookie\n */\n remove(): void {\n // biome-ignore lint/suspicious/noDocumentCookie: this is unnecessary\n document.cookie = `${this.cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; ${this.secure ? \"secure; \" : \"\"}SameSite=${this.sameSite}`;\n }\n}\n","/**\n * Storage implementations for session persistence in different environments.\n *\n * This module provides different storage adapters for persisting authentication sessions\n * across page reloads and browser sessions.\n */\n\nimport type { Session as AuthSession } from \"../auth\";\nimport { decodeUserSession, type Session } from \"./session\";\nimport {\n LocalStorage,\n MemoryStorage,\n type SessionStorageBackend,\n} from \"./storageBackend\";\n\n/**\n * Callback function type for session change subscriptions\n */\nexport type SessionChangeCallback = (session: Session | null) => void;\n\n/**\n * A wrapper around any SessionStorageInterface implementation that adds\n * the ability to subscribe to session changes.\n */\nexport class SessionStorage {\n private readonly storage: SessionStorageBackend;\n private subscribers = new Set<SessionChangeCallback>();\n\n /**\n * Creates a new SessionStorage instance\n * @param storage - The underlying storage implementation to use\n */\n constructor(storage: SessionStorageBackend) {\n this.storage = storage;\n }\n\n /**\n * Gets the session from the underlying storage\n * @returns The stored session or null if not found\n */\n get(): Session | null {\n return this.storage.get();\n }\n\n /**\n * Sets the session in the underlying storage and notifies subscribers\n * @param value - The session to store\n */\n set(value: AuthSession): void {\n const decodedToken = decodeUserSession(value.accessToken);\n const decodedSession = {\n ...value,\n decodedToken: decodedToken,\n };\n\n this.storage.set(decodedSession);\n this.notifySubscribers(decodedSession);\n }\n\n /**\n * Removes the session from the underlying storage and notifies subscribers\n */\n remove(): void {\n this.storage.remove();\n this.notifySubscribers(null);\n }\n\n /**\n * Subscribe to session changes\n * @param callback - Function that will be called when the session changes\n * @returns An unsubscribe function to remove this subscription\n */\n onChange(callback: SessionChangeCallback) {\n this.subscribers.add(callback);\n\n return () => {\n this.subscribers.delete(callback);\n };\n }\n\n /**\n * Notify all subscribers of a session change\n * @param session - The new session value or null if removed\n */\n private notifySubscribers(session: Session | null): void {\n for (const subscriber of this.subscribers) {\n try {\n subscriber(session);\n } catch (error) {\n console.error(\"Error notifying subscriber:\", error);\n }\n }\n }\n}\n\n/**\n * Detects the best available storage implementation for the current environment.\n *\n * The detection process follows this order:\n * 1. Try to use localStorage if we're in a browser environment\n * 2. Fall back to in-memory storage if localStorage isn't available\n *\n * @returns The best available storage implementation as a SessionStorageBackend\n */\nexport const detectStorage = (): SessionStorageBackend => {\n if (typeof window !== \"undefined\") {\n return new LocalStorage();\n }\n return new MemoryStorage();\n};\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../fetch-DWXwEnoe.js");exports.createAPIClient=(e,s=[])=>{let a=t.createEnhancedFetch(s);return{baseURL:e,pushChainFunction:e=>{s.push(e),a=t.createEnhancedFetch(s)},uploadFiles:async(s,r)=>{const n=e+"/files",d=new FormData;void 0!==s["bucket-id"]&&d.append("bucket-id",s["bucket-id"]),void 0!==s["metadata[]"]&&s["metadata[]"].forEach((t=>d.append("metadata[]",new Blob([JSON.stringify(t)],{type:"application/json"}),""))),void 0!==s["file[]"]&&s["file[]"].forEach((t=>d.append("file[]",t)));const o=await a(n,{...r,method:"POST",body:d});if(o.status>=300){const e=[412].includes(o.status)?null:await o.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,o.status,o.headers)}const u=[204,205,304].includes(o.status)?null:await o.text();return{body:u?JSON.parse(u):{},status:o.status,headers:o.headers}},deleteFile:async(s,r)=>{const n=e+`/files/${s}`,d=await a(n,{...r,method:"DELETE",headers:{...r?.headers}});if(d.status>=300){const e=[412].includes(d.status)?null:await d.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,d.status,d.headers)}return{body:void 0,status:d.status,headers:d.headers}},getFile:async(s,r,n)=>{const d=r&&Object.entries(r).map((([t,e])=>{const s=Array.isArray(e)?e.join(","):"object"==typeof e?JSON.stringify(e):e;return`${t}=${encodeURIComponent(s)}`})).join("&"),o=d?e+`/files/${s}?${d}`:e+`/files/${s}`,u=await a(o,{...n,method:"GET",headers:{...n?.headers}});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}return{body:await u.blob(),status:u.status,headers:u.headers}},getFileMetadataHeaders:async(s,r,n)=>{const d=r&&Object.entries(r).map((([t,e])=>{const s=Array.isArray(e)?e.join(","):"object"==typeof e?JSON.stringify(e):e;return`${t}=${encodeURIComponent(s)}`})).join("&"),o=d?e+`/files/${s}?${d}`:e+`/files/${s}`,u=await a(o,{...n,method:"HEAD",headers:{...n?.headers}});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}return{body:void 0,status:u.status,headers:u.headers}},replaceFile:async(s,r,n)=>{const d=e+`/files/${s}`,o=new FormData;void 0!==r.metadata&&o.append("metadata",new Blob([JSON.stringify(r.metadata)],{type:"application/json"}),""),void 0!==r.file&&o.append("file",r.file);const u=await a(d,{...n,method:"PUT",body:o});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}const i=[204,205,304].includes(u.status)?null:await u.text();return{body:i?JSON.parse(i):{},status:u.status,headers:u.headers}},getFilePresignedURL:async(s,r)=>{const n=e+`/files/${s}/presignedurl`,d=await a(n,{...r,method:"GET",headers:{...r?.headers}});if(d.status>=300){const e=[412].includes(d.status)?null:await d.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,d.status,d.headers)}const o=[204,205,304].includes(d.status)?null:await d.text();return{body:o?JSON.parse(o):{},status:d.status,headers:d.headers}},deleteBrokenMetadata:async s=>{const r=e+"/ops/delete-broken-metadata",n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},deleteOrphanedFiles:async s=>{const r=e+"/ops/delete-orphans",n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listBrokenMetadata:async s=>{const r=e+"/ops/list-broken-metadata",n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listFilesNotUploaded:async s=>{const r=e+"/ops/list-not-uploaded",n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listOrphanedFiles:async s=>{const r=e+"/ops/list-orphans",n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},getVersion:async s=>{const r=e+"/version",n=await a(r,{...s,method:"GET",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../fetch-DWXwEnoe.js");exports.createAPIClient=(e,s=[])=>{let a=t.createEnhancedFetch(s);return{baseURL:e,pushChainFunction:e=>{s.push(e),a=t.createEnhancedFetch(s)},uploadFiles:async(s,r)=>{const n=`${e}/files`,d=new FormData;void 0!==s["bucket-id"]&&d.append("bucket-id",s["bucket-id"]),void 0!==s["metadata[]"]&&s["metadata[]"].forEach((t=>{d.append("metadata[]",new Blob([JSON.stringify(t)],{type:"application/json"}),"")})),void 0!==s["file[]"]&&s["file[]"].forEach((t=>{d.append("file[]",t)}));const o=await a(n,{...r,method:"POST",body:d});if(o.status>=300){const e=[412].includes(o.status)?null:await o.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,o.status,o.headers)}const u=[204,205,304].includes(o.status)?null:await o.text();return{body:u?JSON.parse(u):{},status:o.status,headers:o.headers}},deleteFile:async(s,r)=>{const n=`${e}/files/${s}`,d=await a(n,{...r,method:"DELETE",headers:{...r?.headers}});if(d.status>=300){const e=[412].includes(d.status)?null:await d.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,d.status,d.headers)}return{body:void 0,status:d.status,headers:d.headers}},getFile:async(s,r,n)=>{const d=r&&Object.entries(r).map((([t,e])=>{const s=Array.isArray(e)?e.join(","):"object"==typeof e?JSON.stringify(e):e;return`${t}=${encodeURIComponent(s)}`})).join("&"),o=d?`${e}/files/${s}?${d}`:`${e}/files/${s}`,u=await a(o,{...n,method:"GET",headers:{...n?.headers}});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}return{body:await u.blob(),status:u.status,headers:u.headers}},getFileMetadataHeaders:async(s,r,n)=>{const d=r&&Object.entries(r).map((([t,e])=>{const s=Array.isArray(e)?e.join(","):"object"==typeof e?JSON.stringify(e):e;return`${t}=${encodeURIComponent(s)}`})).join("&"),o=d?`${e}/files/${s}?${d}`:`${e}/files/${s}`,u=await a(o,{...n,method:"HEAD",headers:{...n?.headers}});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}return{body:void 0,status:u.status,headers:u.headers}},replaceFile:async(s,r,n)=>{const d=`${e}/files/${s}`,o=new FormData;void 0!==r.metadata&&o.append("metadata",new Blob([JSON.stringify(r.metadata)],{type:"application/json"}),""),void 0!==r.file&&o.append("file",r.file);const u=await a(d,{...n,method:"PUT",body:o});if(u.status>=300){const e=[412].includes(u.status)?null:await u.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,u.status,u.headers)}const i=[204,205,304].includes(u.status)?null:await u.text();return{body:i?JSON.parse(i):{},status:u.status,headers:u.headers}},getFilePresignedURL:async(s,r)=>{const n=`${e}/files/${s}/presignedurl`,d=await a(n,{...r,method:"GET",headers:{...r?.headers}});if(d.status>=300){const e=[412].includes(d.status)?null:await d.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,d.status,d.headers)}const o=[204,205,304].includes(d.status)?null:await d.text();return{body:o?JSON.parse(o):{},status:d.status,headers:d.headers}},deleteBrokenMetadata:async s=>{const r=`${e}/ops/delete-broken-metadata`,n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},deleteOrphanedFiles:async s=>{const r=`${e}/ops/delete-orphans`,n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listBrokenMetadata:async s=>{const r=`${e}/ops/list-broken-metadata`,n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listFilesNotUploaded:async s=>{const r=`${e}/ops/list-not-uploaded`,n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},listOrphanedFiles:async s=>{const r=`${e}/ops/list-orphans`,n=await a(r,{...s,method:"POST",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}},getVersion:async s=>{const r=`${e}/version`,n=await a(r,{...s,method:"GET",headers:{...s?.headers}});if(n.status>=300){const e=[412].includes(n.status)?null:await n.text(),s=e?JSON.parse(e):{};throw new t.FetchError(s,n.status,n.headers)}const d=[204,205,304].includes(n.status)?null:await n.text();return{body:d?JSON.parse(d):{},status:n.status,headers:n.headers}}}};
2
2
  //# sourceMappingURL=storage.cjs.js.map