@quranjs/api 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- 'use strict';var j=require('humps');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var j__default=/*#__PURE__*/_interopDefault(j);var b={auth:{v1:{operations:{getV1Collections:{auth:"user",method:"get",path:"/v1/collections"},postV1Collections:{auth:"user",method:"post",path:"/v1/collections"},postV1CollectionsByCollectionIdBookmarks:{auth:"user",method:"post",path:"/v1/collections/{collectionId}/bookmarks"},deleteV1CollectionsByCollectionIdBookmarks:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}/bookmarks"},getV1CollectionsByCollectionId:{auth:"user",method:"get",path:"/v1/collections/{collectionId}"},postV1CollectionsByCollectionId:{auth:"user",method:"post",path:"/v1/collections/{collectionId}"},deleteV1CollectionsByCollectionId:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}"},deleteV1CollectionsByCollectionIdBookmarksByBookmarkId:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}/bookmarks/{bookmarkId}"},getV1CollectionsAll:{auth:"user",method:"get",path:"/v1/collections/all"},getV1Bookmarks:{auth:"user",method:"get",path:"/v1/bookmarks"},postV1Bookmarks:{auth:"user",method:"post",path:"/v1/bookmarks"},deleteV1BookmarksByBookmarkId:{auth:"user",method:"delete",path:"/v1/bookmarks/{bookmarkId}"},getV1BookmarksAyahsRange:{auth:"user",method:"get",path:"/v1/bookmarks/ayahs-range"},getV1BookmarksBookmark:{auth:"user",method:"get",path:"/v1/bookmarks/bookmark"},getV1BookmarksCollections:{auth:"user",method:"get",path:"/v1/bookmarks/collections"},getV1Preferences:{auth:"user",method:"get",path:"/v1/preferences"},postV1Preferences:{auth:"user",method:"post",path:"/v1/preferences"},postV1PreferencesBulk:{auth:"user",method:"post",path:"/v1/preferences/bulk"},getV1ReadingSessions:{auth:"user",method:"get",path:"/v1/reading-sessions"},postV1ReadingSessions:{auth:"user",method:"post",path:"/v1/reading-sessions"},getV1GoalsGetTodaysPlan:{auth:"user",method:"get",path:"/v1/goals/get-todays-plan"},putV1GoalsById:{auth:"user",method:"put",path:"/v1/goals/{id}"},deleteV1GoalsById:{auth:"user",method:"delete",path:"/v1/goals/{id}"},postV1Goals:{auth:"user",method:"post",path:"/v1/goals"},getV1GoalsEstimate:{auth:"user",method:"get",path:"/v1/goals/estimate"},getV1Streaks:{auth:"user",method:"get",path:"/v1/streaks"},getV1StreaksCurrentStreakDays:{auth:"user",method:"get",path:"/v1/streaks/current-streak-days"},getV1ActivityDays:{auth:"user",method:"get",path:"/v1/activity-days"},postV1ActivityDays:{auth:"user",method:"post",path:"/v1/activity-days"},getV1ActivityDaysEstimateReadingTime:{auth:"user",method:"get",path:"/v1/activity-days/estimate-reading-time"},getV1Notes:{auth:"user",method:"get",path:"/v1/notes"},postV1Notes:{auth:"user",method:"post",path:"/v1/notes"},getV1NotesByVerseByVerseKey:{auth:"user",method:"get",path:"/v1/notes/by-verse/{verseKey}"},getV1NotesByAttachedEntity:{auth:"user",method:"get",path:"/v1/notes/by-attached-entity"},getV1NotesCountWithinRange:{auth:"user",method:"get",path:"/v1/notes/count-within-range"},getV1NotesByRange:{auth:"user",method:"get",path:"/v1/notes/by-range"},getV1NotesByNoteId:{auth:"user",method:"get",path:"/v1/notes/{noteId}"},patchV1NotesByNoteId:{auth:"user",method:"patch",path:"/v1/notes/{noteId}"},deleteV1NotesByNoteId:{auth:"user",method:"delete",path:"/v1/notes/{noteId}"},postV1NotesByNoteIdPublish:{auth:"user",method:"post",path:"/v1/notes/{noteId}/publish"}},service:"auth",version:"v1"}},oauth2:{v1:{operations:{oauth2TokenExchange:{auth:"none",method:"post",path:"/oauth2/token"},introspectOauth2Token:{auth:"none",method:"post",path:"/oauth2/introspect"},revokeOauth2Token:{auth:"none",method:"post",path:"/oauth2/revoke"},oAuth2Authorize:{auth:"none",method:"get",path:"/oauth2/auth"},getOidcUserInfo:{auth:"user",method:"get",path:"/userinfo"},revokeOidcSession:{auth:"none",method:"get",path:"/oauth2/sessions/logout"}},service:"oauth2",version:"v1"}},quranReflect:{v1:{operations:{usersControllerProfile:{auth:"user",method:"get",path:"/v1/users/profile"},usersControllerUpdateProfile:{auth:"user",method:"put",path:"/v1/users/profile"},usersControllerEditProfile:{auth:"user",method:"patch",path:"/v1/users/profile"},usersControllerRooms:{auth:"user",method:"get",path:"/v1/users/my-rooms"},usersControllerSearch:{auth:"user",method:"get",path:"/v1/users/search"},usersControllerToggleFollow:{auth:"user",method:"post",path:"/v1/users/{followeeId}/toggle-follow"},usersControllerRemoveFollower:{auth:"user",method:"post",path:"/v1/users/{followerId}/remove-follower"},usersControllerGetUserProfile:{auth:"user",method:"get",path:"/v1/users/{id}"},usersControllerGetUserProfile2:{auth:"user",method:"get",path:"/v1/users/{username}/profile"},usersControllerGetUserFollowers:{auth:"user",method:"get",path:"/v1/users/{id}/followers"},usersControllerGetUserFollowing:{auth:"user",method:"get",path:"/v1/users/{id}/following"},roomsControllerAdminsAccess:{auth:"user",method:"post",path:"/v1/rooms/admins-access"},roomsControllerCreateNewGroup:{auth:"user",method:"post",path:"/v1/rooms/groups"},roomsControllerUpdateGroup:{auth:"user",method:"patch",path:"/v1/rooms/groups"},roomsControllerCreateNewPage:{auth:"user",method:"post",path:"/v1/rooms/pages"},roomsControllerUpdatePage:{auth:"user",method:"patch",path:"/v1/rooms/pages"},roomsControllerGetRoomMembers:{auth:"user",method:"get",path:"/v1/rooms/{id}/members"},roomsControllerGetClosedGroupJoinRequestStatus:{auth:"user",method:"get",path:"/v1/rooms/{groupId}/join-request"},roomsControllerRequestToJoinClosedGroup:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join-request"},roomsControllerCancelClosedGroupJoinRequest:{auth:"user",method:"delete",path:"/v1/rooms/{groupId}/join-request"},roomsControllerGetPendingClosedGroupJoinRequests:{auth:"user",method:"get",path:"/v1/rooms/{groupId}/join-requests"},roomsControllerApproveClosedGroupJoinRequest:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join-requests/{userId}/approve"},roomsControllerRejectClosedGroupJoinRequest:{auth:"user",method:"delete",path:"/v1/rooms/{groupId}/join-requests/{userId}"},roomsControllerInviteUserToRoom:{auth:"user",method:"post",path:"/v1/rooms/{id}/invite"},roomsControllerAcceptInvite:{auth:"user",method:"get",path:"/v1/rooms/{id}/accept-invite"},roomsControllerRejectInvite:{auth:"user",method:"get",path:"/v1/rooms/{id}/reject-invite"},roomsControllerRemoveMember:{auth:"user",method:"delete",path:"/v1/rooms/{id}/members/{userId}"},roomsControllerGetRooms:{auth:"user",method:"get",path:"/v1/rooms/joined-rooms"},roomsControllerGetRooms2:{auth:"user",method:"get",path:"/v1/rooms/managed-rooms"},roomsControllerSearchRooms:{auth:"user",method:"get",path:"/v1/rooms/search"},roomsControllerGetRoomProfile:{auth:"user",method:"get",path:"/v1/rooms/group/{url}"},roomsControllerGetRoomProfile2:{auth:"user",method:"get",path:"/v1/rooms/page/{subdomain}"},roomsControllerAcceptByPrivateToken:{auth:"user",method:"get",path:"/v1/rooms/group/{url}/accept/{token}"},roomsControllerAcceptByPrivateToken2:{auth:"user",method:"get",path:"/v1/rooms/page/{subdomain}/accept/{token}"},roomsControllerGetRoomProfileById:{auth:"user",method:"get",path:"/v1/rooms/{id}"},roomsControllerGetRoomPosts:{auth:"user",method:"get",path:"/v1/rooms/{id}/posts"},roomsControllerJoinRoom:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join"},roomsControllerLeaveGroup:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/leave"},roomsControllerFollowPage:{auth:"user",method:"post",path:"/v1/rooms/{pageId}/follow"},roomsControllerUnfollowPage:{auth:"user",method:"post",path:"/v1/rooms/{pageId}/unfollow"},roomsControllerUpdatePostPrivacy:{auth:"user",method:"patch",path:"/v1/rooms/{roomId}/posts/{postId}/privacy"},postsControllerFeed:{auth:"user",method:"get",path:"/v1/posts/feed"},postsControllerGetRelatedPosts:{auth:"user",method:"get",path:"/v1/posts/{postId}/related"},postsControllerGetReReflections:{auth:"user",method:"get",path:"/v1/posts/{postId}/re-reflections"},postsControllerGetLoggedinUserPosts:{auth:"user",method:"get",path:"/v1/posts/my-posts"},postsControllerGetMyPostsCountWithinRange:{auth:"user",method:"get",path:"/v1/posts/count-within-range"},postsControllerGetLikedState:{auth:"user",method:"get",path:"/v1/posts/{id}/liked"},postsControllerFindOne:{auth:"user",method:"get",path:"/v1/posts/{id}"},postsControllerEdit:{auth:"user",method:"patch",path:"/v1/posts/{id}"},postsControllerDelete:{auth:"user",method:"delete",path:"/v1/posts/{id}"},postsControllerViewTracking:{auth:"user",method:"post",path:"/v1/posts/viewed/{id}"},postsControllerReadTracking:{auth:"user",method:"post",path:"/v1/posts/read/{id}"},postsControllerCreate:{auth:"user",method:"post",path:"/v1/posts"},postsControllerReportAbuse:{auth:"user",method:"post",path:"/v1/posts/{id}/report"},postsControllerGetUserPost:{auth:"user",method:"get",path:"/v1/posts/user-posts/{id}"},postsControllerToggleLike:{auth:"user",method:"post",path:"/v1/posts/{id}/toggle-like"},postsControllerToggleSave:{auth:"user",method:"post",path:"/v1/posts/{id}/toggle-save"},postsControllerGetComments:{auth:"user",method:"get",path:"/v1/posts/{id}/comments"},postsControllerGetAllComment:{auth:"user",method:"get",path:"/v1/posts/{id}/all-comments"},postsControllerExportMultiplePosts:{auth:"user",method:"post",path:"/v1/posts/export/pdf"},postsControllerGetPublicPostCountByVerse:{auth:"user",method:"get",path:"/v1/posts/count-by-verse/{verseId}"},postsControllerGetMyPostsByVerse:{auth:"user",method:"get",path:"/v1/posts/by-verse/{verseKey}"},tagsControllerFind:{auth:"user",method:"get",path:"/v1/tags"},commentsControllerCreate:{auth:"user",method:"post",path:"/v1/comments"},commentsControllerEdit:{auth:"user",method:"patch",path:"/v1/comments/{id}"},commentsControllerDeleteComment:{auth:"user",method:"get",path:"/v1/comments/{id}/delete"},commentsControllerToggleLike:{auth:"user",method:"post",path:"/v1/comments/{id}/toggle-like"},commentsControllerGet:{auth:"user",method:"get",path:"/v1/comments/{id}/replies"},exploreControllerFind:{auth:"user",method:"get",path:"/v1/explore"},trendingHashtagsControllerFind:{auth:"user",method:"get",path:"/v1/trending-hashtags"}},service:"quranReflect",version:"v1"}}};var l=b;var T=(o,t)=>{if(!(o.body===void 0||o.body===null))return typeof o.body=="string"||o.body instanceof URLSearchParams?(o.contentType&&t.set("Content-Type",o.contentType),o.body):(t.set("Content-Type",o.contentType??"application/json"),JSON.stringify(o.body))},S=(o,t)=>{let r=o.expiresIn??o.expires_in,s=o.accessToken??o.access_token,e=o.idToken??o.id_token??t?.idToken,n=o.refreshToken??o.refresh_token??t?.refreshToken,a=o.tokenType??o.token_type??t?.tokenType,i=o.scope??t?.scope,p=r?Date.now()+r*1e3:t?.expiresAt;return {accessToken:s,expiresAt:p,idToken:e,refreshToken:n,scope:i,tokenType:a}};var P=(o,t,r)=>({...r,operationName:r.operationName??t,service:r.service??o.service,tags:r.tags??[],version:r.version??o.version});var O={delete:"remove",get:"list",patch:"update",post:"create",put:"update"},d=o=>{let t=o.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[^A-Za-z0-9]+/g," ").trim().split(/\s+/).filter(Boolean);return t.length===0?"misc":t.map((r,s)=>{let e=r.toLowerCase();return s===0?e:e.charAt(0).toUpperCase()+e.slice(1)}).join("")},M=o=>{let t=d(o);return t.charAt(0).toUpperCase()+t.slice(1)},h=o=>o.startsWith("{")&&o.endsWith("}"),w=o=>{let t=o.split("/").filter(Boolean);return t[0]?.match(/^v\d+$/)?t.slice(1):t},N=o=>{let t=w(o.path),r=t.at(-1),s=t.filter(a=>!h(a)),e=s.at(-1),n=s[0];return t.length===1?O[o.method]:t.length===2&&r&&h(r)?o.method==="get"?"get":o.method==="delete"?"remove":"update":r&&!h(r)&&e?e===n?`${O[o.method]}ById`:d(e):d(o.operationName)},m=(o,t)=>{let r={};for(let[s,e]of Object.entries(t.operations)){let n=P(t,s,e);r[s]=a=>o.requestOperation(n,a);}return r},y=(o,t)=>{let r={};for(let[s,e]of Object.entries(o.operations)){let n=P(o,s,e),a=w(n.path).filter(v=>!h(v)),i=d(a[0]??"misc"),p=N(n),u=r[i]??{},c=p;u[c]&&(c=`${p}${M(s)}`),u[c]=t[s],r[i]=u;}return r};var{decamelize:R}=j__default.default,C=o=>o.startsWith("/")?o:`/${o}`,k=o=>o.endsWith("/")?o.slice(0,-1):o;var g=(o,t)=>o.replace(/\{([^}]+)\}/g,(r,s)=>{let e=t?.[s];if(e===void 0)throw new Error(`Missing path parameter: ${s}`);return encodeURIComponent(String(e))}),E=o=>o.replace(/(^|\/):([A-Za-z0-9_]+)/g,"$1{$2}"),A=["wordFields","translationFields","fields"],G=new Set([...A,...A.map(o=>R(o))]),L=new Set(["navigationalResultsNumber","pageSize","versesResultsNumber"]),U=(o,t={})=>{if(!o)return "";let r=new URLSearchParams;for(let[s,e]of Object.entries(o)){if(e===void 0)continue;let n=t.preserveCase||L.has(s)?s:R(s);if(G.has(s)||G.has(n)){let a=Object.entries(e).filter(([,i])=>i).map(([i])=>R(i));a.length>0&&r.set(n,a.join(","));continue}typeof e=="string"?r.set(n,e):typeof e=="number"||typeof e=="boolean"?r.set(n,e.toString()):Array.isArray(e)&&r.set(n,e.join(","));}return r.size===0?"":`?${r.toString()}`};var H=o=>!!o&&typeof o=="object"&&!Array.isArray(o),$=o=>H(o)?typeof o.body=="string"&&typeof o.draft=="boolean"&&Array.isArray(o.references)&&Array.isArray(o.mentions):false,q=(o,t)=>({...o,create:n=>$(n)?t("POST","/v1/posts",{body:{post:n}}):t("POST","/v1/posts",n),get:(n,a)=>typeof n=="string"||typeof n=="number"?t("GET","/v1/posts/{id}",{path:{id:n},query:a}):t("GET","/v1/posts/{id}",n),update:(n,a)=>a!==void 0?t("PATCH","/v1/posts/{id}",{body:a,path:{id:n}}):t("PATCH","/v1/posts/{id}",n)});var I={analytics:"https://apis.quran.foundation/analytics",auth:"https://apis.quran.foundation/auth",content:"https://apis.quran.foundation/content",oauth2:"https://oauth2.quran.foundation",quranReflect:"https://apis.quran.foundation/quran-reflect",search:"https://apis.quran.foundation/search"},x={analytics:"/v1",auth:"/v1",content:"/api/v4",oauth2:"",quranReflect:"/v1",search:"/v1"},B={analytics:"/analytics/v1",auth:"/auth/v1",content:"/content/api/v4",oauth2:"",quranReflect:"/quran-reflect/v1",search:"/search/v1"},Q={analytics:["/analytics/v1","/v1"],auth:["/auth/v1","/v1"],content:["/content/api/v4","/api/v4"],oauth2:[],quranReflect:["/quran-reflect/v1","/v1"],search:["/search/v1","/v1"]};var{camelizeKeys:K}=j__default.default,f=class{constructor(t){this.config=t;this.userSession=t.userSession;}userSession;clearCachedTokens(){}getFetch(){let t=this.config.fetch??globalThis.fetch;if(typeof t!="function")throw new Error("No fetch function available. Please provide a fetch implementation or ensure global fetch is available.");return t}async getUserSession(){let t=await this.config.storage?.getSession?.();return t!==void 0?t:this.userSession??null}async setUserSession(t){if(!this.config.storage){this.userSession=t;return}if(!t){if(this.config.storage.clearSession){await this.config.storage.clearSession(),this.userSession=null;return}await this.config.storage.setSession?.(null),this.userSession=null;return}await this.config.storage.setSession?.(t),this.userSession=t;}buildServiceUrl(t,r,s){let{baseUrl:e,usesGateway:n}=this.resolveServiceBaseUrl(t),a=this.normalizeServicePath(t,r,n);return `${e}${a}${U(s,{preserveCase:t==="auth"||t==="quranReflect"})}`}async requestOperation(t,r){return this.request(t.service,g(t.path,r?.path),r?.query,{...r,auth:r?.auth==="auto"||!r?.auth?t.auth:r.auth,method:r?.method??t.method.toUpperCase(),path:void 0})}async request(t,r,s,e={}){if(e.basicAuth)throw new Error("client_secret is server-only. Use @quranjs/api/server.");let n=this.resolveAuthMode(t,e.auth),a=this.buildServiceUrl(t,r,s),i=new Headers(e.headers),p=T(e,i);t!=="oauth2"&&i.set("x-client-id",this.config.clientId),await this.applyAuthenticationHeaders(t,n,i,e);let u=await this.getFetch()(a,{body:p,headers:i,method:e.method??"GET"});if(!u.ok)throw new Error(`${u.status} ${u.statusText}`);if(u.status===204)return;if(!(u.headers.get("content-type")??"").includes("application/json"))return await u.text();let v=await u.json();return K(v)}resolveAuthMode(t,r="auto"){if(r!=="auto"){if(r==="app")throw new Error("This API requires @quranjs/api/server or a backend. Content and search are server-side for confidential clients.");return r}return t==="auth"||t==="quranReflect"?"user":"none"}async applyAuthenticationHeaders(t,r,s,e){if(e.accessToken){this.setTokenHeaders(t,s,e.accessToken);return}if(r==="none")return;let n=await this.getUserSession();if(!n?.accessToken)throw new Error("This operation requires a user session. Sign in first or use @quranjs/api/server.");this.setTokenHeaders(t,s,n.accessToken);}setTokenHeaders(t,r,s){if(t==="oauth2"){r.set("Authorization",`Bearer ${s}`);return}r.set("x-auth-token",s);}resolveServiceBaseUrl(t){let{services:r}=this.config,s=t==="auth"?r?.authBaseUrl:t==="quranReflect"?r?.quranReflectBaseUrl:r?.oauth2BaseUrl??r?.tokenHost;return s?{baseUrl:k(s),usesGateway:false}:r?.gatewayUrl&&t!=="oauth2"?{baseUrl:k(r.gatewayUrl),usesGateway:true}:{baseUrl:I[t],usesGateway:false}}normalizeServicePath(t,r,s){let e=C(E(r));for(let a of Q[t])if(e.startsWith(a)){e=C(e.slice(a.length));break}let n=s?B[t]:x[t];return e.startsWith(n)||n.length===0?e:`${n}${e}`}};var V="This API requires @quranjs/api/server or a backend. Content and search are server-side for confidential clients.",W="auth.bookmarks.get(bookmarkId) is not supported because /v1/bookmarks/bookmark expects bookmark detail query parameters. Pass a query object such as { mushafId, key, type, verseNumber } or { mushafId, isReading: true }.",_=(o,t)=>(r,s,e)=>o.request(t,g(s,e?.path),e?.query,{...e,auth:"user",method:r,path:void 0,query:void 0}),J=o=>{let t=m(o,l.auth.v1),r=y(l.auth.v1,t),s=_(o,"auth");return {...r,collections:{...r.collections,addBookmark:(e,n)=>s("POST","/v1/collections/{collectionId}/bookmarks",{body:n,path:{collectionId:e}}),create:e=>s("POST","/v1/collections",{body:e}),get:(e,n)=>s("GET","/v1/collections/{collectionId}",{path:{collectionId:e},query:n}),list:e=>s("GET","/v1/collections",{query:e}),listAll:e=>s("GET","/v1/collections/all",{query:e}),remove:e=>s("DELETE","/v1/collections/{collectionId}",{path:{collectionId:e}}),removeBookmark:(e,n)=>s("DELETE","/v1/collections/{collectionId}/bookmarks/{bookmarkId}",{path:{bookmarkId:n,collectionId:e}}),update:(e,n)=>s("POST","/v1/collections/{collectionId}",{body:n,path:{collectionId:e}})},bookmarks:{...r.bookmarks,create:e=>s("POST","/v1/bookmarks",{body:e}),get:async e=>{if(typeof e=="string")throw new Error(W);return s("GET","/v1/bookmarks/bookmark",{query:e})},list:e=>s("GET","/v1/bookmarks",{query:e}),listCollections:e=>s("GET","/v1/bookmarks/collections",{query:e}),listRange:e=>s("GET","/v1/bookmarks/ayahs-range",{query:e}),remove:e=>s("DELETE","/v1/bookmarks/{bookmarkId}",{path:{bookmarkId:e}})},goals:{...r.goals,create:e=>s("POST","/v1/goals",{body:e}),estimate:e=>s("GET","/v1/goals/estimate",{query:e}),getTodaysPlan:e=>s("GET","/v1/goals/get-todays-plan",{query:e}),remove:e=>s("DELETE","/v1/goals/{id}",{path:{id:e}}),update:(e,n)=>s("PUT","/v1/goals/{id}",{body:n,path:{id:e}})},notes:{...r.notes,create:e=>s("POST","/v1/notes",{body:e}),get:e=>s("GET","/v1/notes/{noteId}",{path:{noteId:e}}),list:e=>s("GET","/v1/notes",{query:e}),listByAttachedEntity:e=>s("GET","/v1/notes/by-attached-entity",{query:e}),listByRange:e=>s("GET","/v1/notes/by-range",{query:e}),listByVerseKey:(e,n)=>s("GET","/v1/notes/by-verse/{verseKey}",{path:{verseKey:e},query:n}),publish:(e,n)=>s("POST","/v1/notes/{noteId}/publish",{body:n,path:{noteId:e}}),remove:e=>s("DELETE","/v1/notes/{noteId}",{path:{noteId:e}}),update:(e,n)=>s("PATCH","/v1/notes/{noteId}",{body:n,path:{noteId:e}})},preferences:{...r.preferences,bulkUpdate:e=>s("POST","/v1/preferences/bulk",{body:e}),get:e=>s("GET","/v1/preferences",{query:e}),update:e=>s("POST","/v1/preferences",{body:e})},raw:t,readingSessions:{...r.readingSessions,create:e=>s("POST","/v1/reading-sessions",{body:e}),list:e=>s("GET","/v1/reading-sessions",{query:e})}}},X=o=>{let t=m(o,l.quranReflect.v1),r=y(l.quranReflect.v1,t);return {comments:r.comments??{},posts:q(r.posts??{},_(o,"quranReflect")),raw:t,rooms:r.rooms??{},tags:r.tags??{},users:r.users??{}}},Y=(o,t)=>{let r=m(o,l.oauth2.v1),s=async(e,n={})=>{if(t.clientType!=="public")throw new Error("This OAuth2 exchange requires a backend because your client is confidential.");if(n.requiresRefreshToken&&!e.get("refresh_token"))throw new Error("Missing refresh token.");e.set("client_id",t.clientId);let a=e.get("refresh_token")??void 0,i=n.requiresRefreshToken?await o.getUserSession():null,p=n.requiresRefreshToken&&a?{...i??{},refreshToken:a}:i,u=await o.request("oauth2","/oauth2/token",void 0,{auth:"none",body:e,contentType:"application/x-www-form-urlencoded",method:"POST"});return await o.setUserSession(S(u,p)),u};return {authorizeUrl:e=>o.buildServiceUrl("oauth2","/oauth2/auth",e),exchangeCode:e=>{let n=new URLSearchParams({code:e.code,grant_type:"authorization_code",redirect_uri:e.redirectUri});return e.codeVerifier&&n.set("code_verifier",e.codeVerifier),e.scope&&n.set("scope",e.scope),s(n)},getUserInfo:e=>o.request("oauth2","/userinfo",void 0,{accessToken:e,auth:"user",method:"GET"}),introspect:()=>{throw new Error("Token introspection requires @quranjs/api/server or a backend.")},logout:e=>o.request("oauth2","/oauth2/sessions/logout",e,{auth:"none",method:"GET"}),raw:r,refresh:async e=>{let n=await o.getUserSession(),a=new URLSearchParams({grant_type:"refresh_token",refresh_token:e??n?.refreshToken??""});return s(a,{requiresRefreshToken:true})}}},Z=()=>{let o=()=>Promise.reject(new Error(V)),t=new Proxy(o,{apply(){return Promise.reject(new Error(V))},get(r,s){if(s!=="then")return t}});return t},F=o=>{let t=new f(o);t.getFetch();let r=J(t),s=X(t),e=Y(t,o),n=Z(),a={auth:{v1:r.raw},content:{v4:n},oauth2:{v1:e.raw},quranReflect:{v1:s.raw},search:{v1:n}};return {answers:n,audio:n,auth:{...r,v1:r},chapters:n,clearCachedTokens:()=>t.clearCachedTokens(),content:n,getUserSession:()=>t.getUserSession(),hadithReferences:n,juzs:n,oauth2:{...e,v1:e},quranReflect:{...s,v1:s},raw:a,resources:n,search:n,verses:n}};var Te=o=>{if(o.clientSecret)throw new Error("client_secret is server-only. Use @quranjs/api/server.");return F(o)};
2
- exports.createPublicClient=Te;//# sourceMappingURL=public.min.js.map
1
+ 'use strict';var Be=require('humps');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Be__default=/*#__PURE__*/_interopDefault(Be);var W={auth:{v1:{operations:{getUserCsrfToken:{auth:"user",method:"get",path:"/users/csrf-token"},listUserConnectedApps:{auth:"user",method:"get",path:"/users/connected-apps"},runUserConnectedAppLifecycle:{auth:"user",method:"post",path:"/users/connected-apps/{appId}/lifecycle"},getAppStateConfiguration:{auth:"user",method:"get",path:"/v1/app-state:config"},bootstrapAppState:{auth:"user",method:"get",path:"/v1/app-state:bootstrap"},getAppStateChanges:{auth:"user",method:"get",path:"/v1/app-state:changes"},listAppStateDocuments:{auth:"user",method:"get",path:"/v1/app-state/{collection}"},getAppStateDocument:{auth:"user",method:"get",path:"/v1/app-state/{collection}/{key}"},putAppStateDocument:{auth:"user",method:"put",path:"/v1/app-state/{collection}/{key}"},deleteAppStateDocument:{auth:"user",method:"delete",path:"/v1/app-state/{collection}/{key}"},getV1Collections:{auth:"user",method:"get",path:"/v1/collections"},postV1Collections:{auth:"user",method:"post",path:"/v1/collections"},postV1CollectionsByCollectionIdBookmarks:{auth:"user",method:"post",path:"/v1/collections/{collectionId}/bookmarks"},deleteV1CollectionsByCollectionIdBookmarks:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}/bookmarks"},getV1CollectionsByCollectionId:{auth:"user",method:"get",path:"/v1/collections/{collectionId}"},postV1CollectionsByCollectionId:{auth:"user",method:"post",path:"/v1/collections/{collectionId}"},deleteV1CollectionsByCollectionId:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}"},deleteV1CollectionsByCollectionIdBookmarksByBookmarkId:{auth:"user",method:"delete",path:"/v1/collections/{collectionId}/bookmarks/{bookmarkId}"},getV1CollectionsAll:{auth:"user",method:"get",path:"/v1/collections/all"},getV1Bookmarks:{auth:"user",method:"get",path:"/v1/bookmarks"},postV1Bookmarks:{auth:"user",method:"post",path:"/v1/bookmarks"},deleteV1BookmarksByBookmarkId:{auth:"user",method:"delete",path:"/v1/bookmarks/{bookmarkId}"},getV1BookmarksAyahsRange:{auth:"user",method:"get",path:"/v1/bookmarks/ayahs-range"},getV1BookmarksBookmark:{auth:"user",method:"get",path:"/v1/bookmarks/bookmark"},getV1BookmarksCollections:{auth:"user",method:"get",path:"/v1/bookmarks/collections"},getV1Preferences:{auth:"user",method:"get",path:"/v1/preferences"},postV1Preferences:{auth:"user",method:"post",path:"/v1/preferences"},postV1PreferencesBulk:{auth:"user",method:"post",path:"/v1/preferences/bulk"},getV1ReadingSessions:{auth:"user",method:"get",path:"/v1/reading-sessions"},postV1ReadingSessions:{auth:"user",method:"post",path:"/v1/reading-sessions"},getV1GoalsGetTodaysPlan:{auth:"user",method:"get",path:"/v1/goals/get-todays-plan"},putV1GoalsById:{auth:"user",method:"put",path:"/v1/goals/{id}"},deleteV1GoalsById:{auth:"user",method:"delete",path:"/v1/goals/{id}"},postV1Goals:{auth:"user",method:"post",path:"/v1/goals"},getV1GoalsEstimate:{auth:"user",method:"get",path:"/v1/goals/estimate"},getV1Streaks:{auth:"user",method:"get",path:"/v1/streaks"},getV1StreaksCurrentStreakDays:{auth:"user",method:"get",path:"/v1/streaks/current-streak-days"},getV1ActivityDays:{auth:"user",method:"get",path:"/v1/activity-days"},postV1ActivityDays:{auth:"user",method:"post",path:"/v1/activity-days"},getV1ActivityDaysEstimateReadingTime:{auth:"user",method:"get",path:"/v1/activity-days/estimate-reading-time"},getV1Notes:{auth:"user",method:"get",path:"/v1/notes"},postV1Notes:{auth:"user",method:"post",path:"/v1/notes"},getV1NotesByVerseByVerseKey:{auth:"user",method:"get",path:"/v1/notes/by-verse/{verseKey}"},getV1NotesByAttachedEntity:{auth:"user",method:"get",path:"/v1/notes/by-attached-entity"},getV1NotesCountWithinRange:{auth:"user",method:"get",path:"/v1/notes/count-within-range"},getV1NotesByRange:{auth:"user",method:"get",path:"/v1/notes/by-range"},getV1NotesByNoteId:{auth:"user",method:"get",path:"/v1/notes/{noteId}"},patchV1NotesByNoteId:{auth:"user",method:"patch",path:"/v1/notes/{noteId}"},deleteV1NotesByNoteId:{auth:"user",method:"delete",path:"/v1/notes/{noteId}"},postV1NotesByNoteIdPublish:{auth:"user",method:"post",path:"/v1/notes/{noteId}/publish"}},service:"auth",version:"v1"}},oauth2:{v1:{operations:{oauth2TokenExchange:{auth:"none",method:"post",path:"/oauth2/token"},introspectOauth2Token:{auth:"none",method:"post",path:"/oauth2/introspect"},revokeOauth2Token:{auth:"none",method:"post",path:"/oauth2/revoke"},oAuth2Authorize:{auth:"none",method:"get",path:"/oauth2/auth"},getOidcUserInfo:{auth:"user",method:"get",path:"/userinfo"},revokeOidcSession:{auth:"none",method:"get",path:"/oauth2/sessions/logout"}},service:"oauth2",version:"v1"}},quranReflect:{v1:{operations:{usersControllerProfile:{auth:"user",method:"get",path:"/v1/users/profile"},usersControllerUpdateProfile:{auth:"user",method:"put",path:"/v1/users/profile"},usersControllerEditProfile:{auth:"user",method:"patch",path:"/v1/users/profile"},usersControllerRooms:{auth:"user",method:"get",path:"/v1/users/my-rooms"},usersControllerSearch:{auth:"user",method:"get",path:"/v1/users/search"},usersControllerToggleFollow:{auth:"user",method:"post",path:"/v1/users/{followeeId}/toggle-follow"},usersControllerRemoveFollower:{auth:"user",method:"post",path:"/v1/users/{followerId}/remove-follower"},usersControllerGetUserProfile:{auth:"user",method:"get",path:"/v1/users/{id}"},usersControllerGetUserProfile2:{auth:"user",method:"get",path:"/v1/users/{username}/profile"},usersControllerGetUserFollowers:{auth:"user",method:"get",path:"/v1/users/{id}/followers"},usersControllerGetUserFollowing:{auth:"user",method:"get",path:"/v1/users/{id}/following"},roomsControllerAdminsAccess:{auth:"user",method:"post",path:"/v1/rooms/admins-access"},roomsControllerCreateNewGroup:{auth:"user",method:"post",path:"/v1/rooms/groups"},roomsControllerUpdateGroup:{auth:"user",method:"patch",path:"/v1/rooms/groups"},roomsControllerCreateNewPage:{auth:"user",method:"post",path:"/v1/rooms/pages"},roomsControllerUpdatePage:{auth:"user",method:"patch",path:"/v1/rooms/pages"},roomsControllerGetRoomMembers:{auth:"user",method:"get",path:"/v1/rooms/{id}/members"},roomsControllerGetClosedGroupJoinRequestStatus:{auth:"user",method:"get",path:"/v1/rooms/{groupId}/join-request"},roomsControllerRequestToJoinClosedGroup:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join-request"},roomsControllerCancelClosedGroupJoinRequest:{auth:"user",method:"delete",path:"/v1/rooms/{groupId}/join-request"},roomsControllerGetPendingClosedGroupJoinRequests:{auth:"user",method:"get",path:"/v1/rooms/{groupId}/join-requests"},roomsControllerApproveClosedGroupJoinRequest:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join-requests/{userId}/approve"},roomsControllerRejectClosedGroupJoinRequest:{auth:"user",method:"delete",path:"/v1/rooms/{groupId}/join-requests/{userId}"},roomsControllerInviteUserToRoom:{auth:"user",method:"post",path:"/v1/rooms/{id}/invite"},roomsControllerAcceptInvite:{auth:"user",method:"get",path:"/v1/rooms/{id}/accept-invite"},roomsControllerRejectInvite:{auth:"user",method:"get",path:"/v1/rooms/{id}/reject-invite"},roomsControllerRemoveMember:{auth:"user",method:"delete",path:"/v1/rooms/{id}/members/{userId}"},roomsControllerGetRooms:{auth:"user",method:"get",path:"/v1/rooms/joined-rooms"},roomsControllerGetRooms2:{auth:"user",method:"get",path:"/v1/rooms/managed-rooms"},roomsControllerSearchRooms:{auth:"user",method:"get",path:"/v1/rooms/search"},roomsControllerGetRoomProfile:{auth:"user",method:"get",path:"/v1/rooms/group/{url}"},roomsControllerGetRoomProfile2:{auth:"user",method:"get",path:"/v1/rooms/page/{subdomain}"},roomsControllerAcceptByPrivateToken:{auth:"user",method:"get",path:"/v1/rooms/group/{url}/accept/{token}"},roomsControllerAcceptByPrivateToken2:{auth:"user",method:"get",path:"/v1/rooms/page/{subdomain}/accept/{token}"},roomsControllerGetRoomProfileById:{auth:"user",method:"get",path:"/v1/rooms/{id}"},roomsControllerGetRoomPosts:{auth:"user",method:"get",path:"/v1/rooms/{id}/posts"},roomsControllerJoinRoom:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/join"},roomsControllerLeaveGroup:{auth:"user",method:"post",path:"/v1/rooms/{groupId}/leave"},roomsControllerFollowPage:{auth:"user",method:"post",path:"/v1/rooms/{pageId}/follow"},roomsControllerUnfollowPage:{auth:"user",method:"post",path:"/v1/rooms/{pageId}/unfollow"},roomsControllerUpdatePostPrivacy:{auth:"user",method:"patch",path:"/v1/rooms/{roomId}/posts/{postId}/privacy"},postsControllerFeed:{auth:"user",method:"get",path:"/v1/posts/feed"},postsControllerGetRelatedPosts:{auth:"user",method:"get",path:"/v1/posts/{postId}/related"},postsControllerGetReReflections:{auth:"user",method:"get",path:"/v1/posts/{postId}/re-reflections"},postsControllerGetLoggedinUserPosts:{auth:"user",method:"get",path:"/v1/posts/my-posts"},postsControllerGetMyPostsCountWithinRange:{auth:"user",method:"get",path:"/v1/posts/count-within-range"},postsControllerGetLikedState:{auth:"user",method:"get",path:"/v1/posts/{id}/liked"},postsControllerFindOne:{auth:"user",method:"get",path:"/v1/posts/{id}"},postsControllerEdit:{auth:"user",method:"patch",path:"/v1/posts/{id}"},postsControllerDelete:{auth:"user",method:"delete",path:"/v1/posts/{id}"},postsControllerViewTracking:{auth:"user",method:"post",path:"/v1/posts/viewed/{id}"},postsControllerReadTracking:{auth:"user",method:"post",path:"/v1/posts/read/{id}"},postsControllerCreate:{auth:"user",method:"post",path:"/v1/posts"},postsControllerReportAbuse:{auth:"user",method:"post",path:"/v1/posts/{id}/report"},postsControllerGetUserPost:{auth:"user",method:"get",path:"/v1/posts/user-posts/{id}"},postsControllerToggleLike:{auth:"user",method:"post",path:"/v1/posts/{id}/toggle-like"},postsControllerToggleSave:{auth:"user",method:"post",path:"/v1/posts/{id}/toggle-save"},postsControllerGetComments:{auth:"user",method:"get",path:"/v1/posts/{id}/comments"},postsControllerGetAllComment:{auth:"user",method:"get",path:"/v1/posts/{id}/all-comments"},postsControllerExportMultiplePosts:{auth:"user",method:"post",path:"/v1/posts/export/pdf"},postsControllerGetPublicPostCountByVerse:{auth:"user",method:"get",path:"/v1/posts/count-by-verse/{verseId}"},postsControllerGetMyPostsByVerse:{auth:"user",method:"get",path:"/v1/posts/by-verse/{verseKey}"},tagsControllerFind:{auth:"user",method:"get",path:"/v1/tags"},commentsControllerCreate:{auth:"user",method:"post",path:"/v1/comments"},commentsControllerEdit:{auth:"user",method:"patch",path:"/v1/comments/{id}"},commentsControllerDeleteComment:{auth:"user",method:"get",path:"/v1/comments/{id}/delete"},commentsControllerToggleLike:{auth:"user",method:"post",path:"/v1/comments/{id}/toggle-like"},commentsControllerGet:{auth:"user",method:"get",path:"/v1/comments/{id}/replies"},exploreControllerFind:{auth:"user",method:"get",path:"/v1/explore"},trendingHashtagsControllerFind:{auth:"user",method:"get",path:"/v1/trending-hashtags"}},service:"quranReflect",version:"v1"}}};var b=W;var X=(e,t)=>{if(!(e.body===void 0||e.body===null))return typeof e.body=="string"||e.body instanceof URLSearchParams?(e.contentType&&t.set("Content-Type",e.contentType),e.body):(t.set("Content-Type",e.contentType??"application/json"),JSON.stringify(e.body))},Y=(e,t)=>{let n=e.expiresIn??e.expires_in,r=e.accessToken??e.access_token,o=e.idToken??e.id_token??t?.idToken,s=e.refreshToken??e.refresh_token??t?.refreshToken,i=e.tokenType??e.token_type??t?.tokenType,h=e.scope??t?.scope,f=n?Date.now()+n*1e3:t?.expiresAt;return {accessToken:r,expiresAt:f,idToken:o,refreshToken:s,scope:h,tokenType:i}};var Q=(e,t,n)=>({...n,operationName:n.operationName??t,service:n.service??e.service,tags:n.tags??[],version:n.version??e.version});var Z={delete:"remove",get:"list",patch:"update",post:"create",put:"update"},q=e=>{let t=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[^A-Za-z0-9]+/g," ").trim().split(/\s+/).filter(Boolean);return t.length===0?"misc":t.map((n,r)=>{let o=n.toLowerCase();return r===0?o:o.charAt(0).toUpperCase()+o.slice(1)}).join("")},qe=e=>{let t=q(e);return t.charAt(0).toUpperCase()+t.slice(1)},U=e=>e.startsWith("{")&&e.endsWith("}"),ee=e=>{let t=e.split("/").filter(Boolean);return t[0]?.match(/^v\d+$/)?t.slice(1):t},Ie=e=>{let t=ee(e.path),n=t.at(-1),r=t.filter(i=>!U(i)),o=r.at(-1),s=r[0];return t.length===1?Z[e.method]:t.length===2&&n&&U(n)?e.method==="get"?"get":e.method==="delete"?"remove":"update":n&&!U(n)&&o?o===s?`${Z[e.method]}ById`:q(o):q(e.operationName)},I=(e,t)=>{let n={};for(let[r,o]of Object.entries(t.operations)){let s=Q(t,r,o);n[r]=i=>e.requestOperation(s,i);}return n},V=(e,t)=>{let n={};for(let[r,o]of Object.entries(e.operations)){let s=Q(e,r,o),i=ee(s.path).filter(A=>!U(A)),h=q(i[0]??"misc"),f=Ie(s),g=n[h]??{},l=f;g[l]&&(l=`${f}${qe(r)}`),g[l]=t[r],n[h]=g;}return n};var{decamelize:N}=Be__default.default,j=e=>e.startsWith("/")?e:`/${e}`,H=e=>e.endsWith("/")?e.slice(0,-1):e;var k=(e,t)=>e.replace(/\{([^}]+)\}/g,(n,r)=>{let o=t?.[r];if(o===void 0)throw new Error(`Missing path parameter: ${r}`);return encodeURIComponent(String(o))}),re=e=>e.replace(/(^|\/):([A-Za-z0-9_]+)/g,"$1{$2}"),te=["wordFields","translationFields","fields"],oe=new Set([...te,...te.map(e=>N(e))]),xe=new Set(["navigationalResultsNumber","pageSize","versesResultsNumber"]),ne=(e,t={})=>{if(!e)return "";let n=new URLSearchParams;for(let[r,o]of Object.entries(e)){if(o===void 0)continue;let s=t.preserveCase||xe.has(r)?r:N(r);if(oe.has(r)||oe.has(s)){let i=Object.entries(o).filter(([,h])=>h).map(([h])=>N(h));i.length>0&&n.set(s,i.join(","));continue}typeof o=="string"?n.set(s,o):typeof o=="number"||typeof o=="boolean"?n.set(s,o.toString()):Array.isArray(o)&&n.set(s,o.join(","));}return n.size===0?"":`?${n.toString()}`};var De=e=>!!e&&typeof e=="object"&&!Array.isArray(e),Qe=e=>De(e)?typeof e.body=="string"&&typeof e.draft=="boolean"&&Array.isArray(e.references)&&Array.isArray(e.mentions):false,se=(e,t)=>({...e,create:s=>Qe(s)?t("POST","/v1/posts",{body:{post:s}}):t("POST","/v1/posts",s),get:(s,i)=>typeof s=="string"||typeof s=="number"?t("GET","/v1/posts/{id}",{path:{id:s},query:i}):t("GET","/v1/posts/{id}",s),update:(s,i)=>i!==void 0?t("PATCH","/v1/posts/{id}",{body:i,path:{id:s}}):t("PATCH","/v1/posts/{id}",s)});var F=(e,t)=>k("/v1/app-state/{collection}/{key}",{collection:e,key:t}),ae=e=>{let{idempotencyKey:t,ifMatch:n,ifNoneMatch:r}=e;if(n!==void 0&&r!==void 0)throw new Error("App State mutations accept only one of ifMatch or ifNoneMatch.");return Object.freeze({"Idempotency-Key":t,...n===void 0?{}:{"If-Match":n},...r===void 0?{}:{"If-None-Match":r}})},Ve=e=>{let t=JSON.parse(JSON.stringify(e)),n=r=>{if(!(typeof r!="object"||r===null)){Object.freeze(r);for(let o of Object.values(r))n(o);}};return n(t),t},ie=e=>{let t=(r,o,s,i={})=>e.request("auth",o,s,{...i,auth:"user",method:r,preserveResponseKeys:true}),n=async(r,o,s={})=>{let i=null,h=0;return {...await t(r,o,void 0,{...s,onResponse:g=>{i=g.headers.get("etag"),h=g.status;}}),etag:i,status:h}};return {bootstrap:(r={})=>t("GET","/v1/app-state:bootstrap",r),deleteDocument:async(r,o,s)=>{await t("DELETE",F(r,o),void 0,{headers:ae(s)});},getChanges:(r,o={})=>t("GET","/v1/app-state:changes",{...o,since:r}),getConfiguration:()=>t("GET","/v1/app-state:config"),getDocument:(r,o)=>n("GET",F(r,o)),listDocuments:(r,o={})=>t("GET",k("/v1/app-state/{collection}",{collection:r}),o),putDocument:async(r,o,s,i)=>{let h=ae(i),f=Ve(s);return n("PUT",F(r,o),{body:f,headers:h})}}};var Ne=async e=>{try{let t=await e.text();if(!t)return;if(e.headers.get("content-type")?.toLowerCase().includes("json"))try{return JSON.parse(t)}catch{return t}return t}catch{return}},pe=class ue extends Error{headers;payload;status;constructor(t,n){super(`${t.status} ${t.statusText}`),this.name="QuranHttpError",this.headers=new Headers(t.headers),this.payload=n,this.status=t.status;}static async fromResponse(t){return new ue(t,await Ne(t))}};Object.defineProperty(pe,"name",{configurable:true,value:"QuranHttpError"});var ce=Symbol.for("@quranjs/api/QuranHttpError/v1"),le=globalThis,w=le[ce]??pe;le[ce]=w;var de={analytics:"https://apis.quran.foundation/analytics",auth:"https://apis.quran.foundation/auth",content:"https://apis.quran.foundation/content",oauth2:"https://oauth2.quran.foundation",quranReflect:"https://apis.quran.foundation/quran-reflect",search:"https://apis.quran.foundation/search"},he={analytics:"/v1",auth:"/v1",content:"/api/v4",oauth2:"",quranReflect:"/v1",search:"/v1"},me={analytics:"/analytics/v1",auth:"/auth/v1",content:"/content/api/v4",oauth2:"",quranReflect:"/quran-reflect/v1",search:"/search/v1"},ge={analytics:["/analytics/v1","/v1"],auth:["/auth/v1","/v1"],content:["/content/api/v4","/api/v4"],oauth2:[],quranReflect:["/quran-reflect/v1","/v1"],search:["/search/v1","/v1"]};var{camelizeKeys:He}=Be__default.default,B=class{constructor(t){this.config=t;this.userSession=t.userSession;}userSession;clearCachedTokens(){}getFetch(){let t=this.config.fetch??globalThis.fetch;if(typeof t!="function")throw new Error("No fetch function available. Please provide a fetch implementation or ensure global fetch is available.");return t}async getUserSession(){let t=await this.config.storage?.getSession?.();return t!==void 0?t:this.userSession??null}async setUserSession(t){if(!this.config.storage){this.userSession=t;return}if(!t){if(this.config.storage.clearSession){await this.config.storage.clearSession(),this.userSession=null;return}await this.config.storage.setSession?.(null),this.userSession=null;return}await this.config.storage.setSession?.(t),this.userSession=t;}buildServiceUrl(t,n,r){let{baseUrl:o,usesGateway:s}=this.resolveServiceBaseUrl(t),i=this.normalizeServicePath(t,n,s);return `${o}${i}${ne(r,{preserveCase:t==="auth"||t==="quranReflect"})}`}async requestOperation(t,n){return this.request(t.service,k(t.path,n?.path),n?.query,{...n,auth:n?.auth==="auto"||!n?.auth?t.auth:n.auth,method:n?.method??t.method.toUpperCase(),path:void 0})}async request(t,n,r,o={}){if(o.basicAuth)throw new Error("client_secret is server-only. Use @quranjs/api/server.");let s=this.resolveAuthMode(t,o.auth),i=this.buildServiceUrl(t,n,r),h=new Headers(o.headers),f=X(o,h);t!=="oauth2"&&h.set("x-client-id",this.config.clientId),await this.applyAuthenticationHeaders(t,s,h,o);let g=await this.getFetch()(i,{body:f,headers:h,method:o.method??"GET"});if(!g.ok)throw await w.fromResponse(g);if(o.onResponse?.({headers:g.headers,status:g.status}),g.status===204)return;if(!(g.headers.get("content-type")??"").includes("application/json"))return await g.text();let A=await g.json();return o.preserveResponseKeys?A:He(A)}resolveAuthMode(t,n="auto"){if(n!=="auto"){if(n==="app")throw new Error("This API requires @quranjs/api/server or a backend. Content and search are server-side for confidential clients.");return n}return t==="auth"||t==="quranReflect"?"user":"none"}async applyAuthenticationHeaders(t,n,r,o){if(o.accessToken){this.setTokenHeaders(t,r,o.accessToken);return}if(n==="none")return;let s=await this.getUserSession();if(!s?.accessToken)throw new Error("This operation requires a user session. Sign in first or use @quranjs/api/server.");this.setTokenHeaders(t,r,s.accessToken);}setTokenHeaders(t,n,r){if(t==="oauth2"){n.set("Authorization",`Bearer ${r}`);return}n.set("x-auth-token",r);}resolveServiceBaseUrl(t){let{services:n}=this.config,r=t==="auth"?n?.authBaseUrl:t==="quranReflect"?n?.quranReflectBaseUrl:n?.oauth2BaseUrl??n?.tokenHost;return r?{baseUrl:H(r),usesGateway:false}:n?.gatewayUrl&&t!=="oauth2"?{baseUrl:H(n.gatewayUrl),usesGateway:true}:{baseUrl:de[t],usesGateway:false}}normalizeServicePath(t,n,r){let o=j(re(n));for(let i of ge[t])if(o.startsWith(i)){o=j(o.slice(i.length));break}let s=r?me[t]:he[t];return o.startsWith(s)||s.length===0?o:`${s}${o}`}};var fe="This API requires @quranjs/api/server or a backend. Content and search are server-side for confidential clients.",Fe="auth.bookmarks.get(bookmarkId) is not supported because /v1/bookmarks/bookmark expects bookmark detail query parameters. Pass a query object such as { mushafId, key, type, verseNumber } or { mushafId, isReading: true }.",ye=(e,t)=>(n,r,o)=>e.request(t,k(r,o?.path),o?.query,{...o,auth:"user",method:n,path:void 0,query:void 0}),Le=e=>{let t=I(e,b.auth.v1),n=V(b.auth.v1,t),r=ye(e,"auth");return {...n,appState:ie(e),collections:{...n.collections,addBookmark:(o,s)=>r("POST","/v1/collections/{collectionId}/bookmarks",{body:s,path:{collectionId:o}}),create:o=>r("POST","/v1/collections",{body:o}),get:(o,s)=>r("GET","/v1/collections/{collectionId}",{path:{collectionId:o},query:s}),list:o=>r("GET","/v1/collections",{query:o}),listAll:o=>r("GET","/v1/collections/all",{query:o}),remove:o=>r("DELETE","/v1/collections/{collectionId}",{path:{collectionId:o}}),removeBookmark:(o,s)=>r("DELETE","/v1/collections/{collectionId}/bookmarks/{bookmarkId}",{path:{bookmarkId:s,collectionId:o}}),update:(o,s)=>r("POST","/v1/collections/{collectionId}",{body:s,path:{collectionId:o}})},bookmarks:{...n.bookmarks,create:o=>r("POST","/v1/bookmarks",{body:o}),get:async o=>{if(typeof o=="string")throw new Error(Fe);return r("GET","/v1/bookmarks/bookmark",{query:o})},list:o=>r("GET","/v1/bookmarks",{query:o}),listCollections:o=>r("GET","/v1/bookmarks/collections",{query:o}),listRange:o=>r("GET","/v1/bookmarks/ayahs-range",{query:o}),remove:o=>r("DELETE","/v1/bookmarks/{bookmarkId}",{path:{bookmarkId:o}})},goals:{...n.goals,create:o=>r("POST","/v1/goals",{body:o}),estimate:o=>r("GET","/v1/goals/estimate",{query:o}),getTodaysPlan:o=>r("GET","/v1/goals/get-todays-plan",{query:o}),remove:o=>r("DELETE","/v1/goals/{id}",{path:{id:o}}),update:(o,s)=>r("PUT","/v1/goals/{id}",{body:s,path:{id:o}})},notes:{...n.notes,create:o=>r("POST","/v1/notes",{body:o}),get:o=>r("GET","/v1/notes/{noteId}",{path:{noteId:o}}),list:o=>r("GET","/v1/notes",{query:o}),listByAttachedEntity:o=>r("GET","/v1/notes/by-attached-entity",{query:o}),listByRange:o=>r("GET","/v1/notes/by-range",{query:o}),listByVerseKey:(o,s)=>r("GET","/v1/notes/by-verse/{verseKey}",{path:{verseKey:o},query:s}),publish:(o,s)=>r("POST","/v1/notes/{noteId}/publish",{body:s,path:{noteId:o}}),remove:o=>r("DELETE","/v1/notes/{noteId}",{path:{noteId:o}}),update:(o,s)=>r("PATCH","/v1/notes/{noteId}",{body:s,path:{noteId:o}})},preferences:{...n.preferences,bulkUpdate:o=>r("POST","/v1/preferences/bulk",{body:o}),get:o=>r("GET","/v1/preferences",{query:o}),update:o=>r("POST","/v1/preferences",{body:o})},raw:t,readingSessions:{...n.readingSessions,create:o=>r("POST","/v1/reading-sessions",{body:o}),list:o=>r("GET","/v1/reading-sessions",{query:o})}}},$e=e=>{let t=I(e,b.quranReflect.v1),n=V(b.quranReflect.v1,t);return {comments:n.comments??{},posts:se(n.posts??{},ye(e,"quranReflect")),raw:t,rooms:n.rooms??{},tags:n.tags??{},users:n.users??{}}},Je=(e,t)=>{let n=I(e,b.oauth2.v1),r=async(o,s={})=>{if(t.clientType!=="public")throw new Error("This OAuth2 exchange requires a backend because your client is confidential.");if(s.requiresRefreshToken&&!o.get("refresh_token"))throw new Error("Missing refresh token.");o.set("client_id",t.clientId);let i=o.get("refresh_token")??void 0,h=s.requiresRefreshToken?await e.getUserSession():null,f=s.requiresRefreshToken&&i?{...h??{},refreshToken:i}:h,g=await e.request("oauth2","/oauth2/token",void 0,{auth:"none",body:o,contentType:"application/x-www-form-urlencoded",method:"POST"});return await e.setUserSession(Y(g,f)),g};return {authorizeUrl:o=>e.buildServiceUrl("oauth2","/oauth2/auth",o),exchangeCode:o=>{let s=new URLSearchParams({code:o.code,grant_type:"authorization_code",redirect_uri:o.redirectUri});return o.codeVerifier&&s.set("code_verifier",o.codeVerifier),o.scope&&s.set("scope",o.scope),r(s)},getUserInfo:o=>e.request("oauth2","/userinfo",void 0,{accessToken:o,auth:"user",method:"GET"}),introspect:()=>{throw new Error("Token introspection requires @quranjs/api/server or a backend.")},logout:o=>e.request("oauth2","/oauth2/sessions/logout",o,{auth:"none",method:"GET"}),raw:n,refresh:async o=>{let s=await e.getUserSession(),i=new URLSearchParams({grant_type:"refresh_token",refresh_token:o??s?.refreshToken??""});return r(i,{requiresRefreshToken:true})}}},Ke=()=>{let e=()=>Promise.reject(new Error(fe)),t=new Proxy(e,{apply(){return Promise.reject(new Error(fe))},get(n,r){if(r!=="then")return t}});return t},Se=e=>{let t=new B(e);t.getFetch();let n=Le(t),r=$e(t),o=Je(t,e),s=Ke(),i={auth:{v1:n.raw},content:{v4:s},oauth2:{v1:o.raw},quranReflect:{v1:r.raw},search:{v1:s}};return {answers:s,audio:s,auth:{...n,v1:n},chapters:s,clearCachedTokens:()=>t.clearCachedTokens(),content:s,getUserSession:()=>t.getUserSession(),hadithReferences:s,juzs:s,oauth2:{...o,v1:o},quranReflect:{...r,v1:r},raw:i,resources:s,search:s,verses:s}};var ze=new Set(["app_state_data_deleted","app_state_disabled","app_state_policy_changed","app_state_unavailable","bootstrap_required","collection_not_allowed","document_not_found","document_too_large","idempotency_key_reused","internal_server_error","insufficient_scope","invalid_collection","invalid_etag","invalid_idempotency_key","invalid_json","invalid_key","invalid_precondition","invalid_sync_token","invalid_token","namespace_resolution_unavailable","payload_too_large","precondition_failed","precondition_required","quota_exceeded","rate_limit_exceeded","sync_token_expired"]),T=e=>{if(!(e instanceof w))return;let t=e.payload;if(typeof t!="object"||t===null)return;let n=t.details;if(typeof n!="object"||n===null)return;let r=n.error,o=typeof r=="string"?r:typeof r=="object"&&r!==null?r.code:void 0;return typeof o=="string"&&ze.has(o)?o:void 0};function We(e,t){let n=T(e);return n!==void 0&&(t===void 0||t===n)}var v=class extends Error{code;constructor(t){super(`App State reconciliation protocol error: ${t}`),this.name="AppStateProtocolError",this.code=t;}},S=e=>JSON.parse(JSON.stringify(e)),P=e=>{if(typeof e!="object"||e===null||Object.isFrozen(e))return e;for(let t of Object.values(e))P(t);return Object.freeze(e)},x=e=>{if(Array.isArray(e))return `[${e.map(x).join(",")}]`;if(typeof e=="object"&&e!==null){let t=e;return `{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${x(t[n])}`).join(",")}}`}return JSON.stringify(e)},E=(e,t)=>`${e}/${encodeURIComponent(t)}`,Xe=()=>({bootstrapCursor:null,localRevision:0,pendingMutations:[],shadow:{},stagingBootstrap:null,syncToken:null}),Ye=e=>{if(typeof e=="object"&&e!==null&&"then"in e&&typeof e.then=="function")throw new TypeError("App State store reducers must be synchronous.")},Ze=(e={})=>{let t=new Map(Object.entries(e).map(([r,o])=>[r,P(S(o))])),n=new Map;return {transaction:(r,o)=>{if(!r)return Promise.reject(new TypeError("App State transactions require an account ID."));let i=(n.get(r)??Promise.resolve()).then(()=>{let h=t.get(r)??Xe(),f=S(h),g=o(f);return Ye(g),P(f),t.set(r,f),g});return n.set(r,i.then(()=>{},()=>{})),i}}},ve=(e,t)=>{let n=E(t.collection,t.key),r=e[n];if(!(r&&t.version<r.version)){if(r&&t.version===r.version){if(x(r)!==x(t))throw new v("same_version_conflict");return}e[n]=S(t);}},_=(e,t,n,r="shadow")=>{let o=r==="shadow"?e.shadow:e.stagingBootstrap??{},s=S(o);for(let i of t)ve(s,i);r==="shadow"?e.shadow=s:e.stagingBootstrap=s,e.syncToken=n;},Ae=(e,t,n)=>{let r=S(e.stagingBootstrap??{});for(let o of t)ve(r,o);e.stagingBootstrap=r,e.bootstrapCursor=n;},Pe=e=>{e.shadow=S(e.stagingBootstrap??{}),e.stagingBootstrap=null,e.bootstrapCursor=null;},Re=(e,t,n)=>{let r=e.shadow[E(t,n)];return r?.operation==="upsert"?{ifMatch:r.etag}:{ifNoneMatch:"*"}},ke=(e,t,n,r,o)=>{let s=e.localRevision+1,i={...Re(e,t,n),body:S(r),collection:t,idempotencyKey:o,key:n,localRevision:s,method:"PUT"};return P(i),e.pendingMutations=[...e.pendingMutations,i],e.localRevision=s,s},be=(e,t,n,r)=>{let o=e.localRevision+1,s={...Re(e,t,n),collection:t,idempotencyKey:r,key:n,localRevision:o,method:"DELETE"};return P(s),e.pendingMutations=[...e.pendingMutations,s],e.localRevision=o,o},et=e=>{let t={};for(let[n,r]of Object.entries(e))r.operation!=="delete"&&(t[n]={collection:r.collection,etag:r.etag,key:r.key,pending:false,schemaVersion:r.schemaVersion,updatedAt:r.updatedAt,value:S(r.value),version:r.version});return t},we=e=>{let t=S(e),n=et(t.shadow);for(let r of t.pendingMutations){let o=E(r.collection,r.key);if(r.method==="DELETE"){delete n[o];continue}let s=n[o];n[o]={collection:r.collection,etag:s?.etag??null,key:r.key,pending:true,schemaVersion:r.body.schemaVersion,updatedAt:s?.updatedAt??null,value:S(r.body.value),version:s?.version??null};}return P({...t,visible:n})},Te=e=>P(S(e.pendingMutations)),L=(e,t)=>{e.pendingMutations=e.pendingMutations.filter(n=>n.localRevision!==t);},Ce=(e,t)=>{e.pendingMutations=e.pendingMutations.map(n=>n.localRevision===t.localRevision?P(S(t)):n);};var tt=100,ot=3,rt=3,nt=()=>{let e=globalThis.crypto;if(typeof e?.randomUUID!="function")throw new Error("App State reconciliation requires createIdempotencyKey when crypto.randomUUID is unavailable.");return e.randomUUID()},Oe=e=>e.ifMatch!==void 0?{idempotencyKey:e.idempotencyKey,ifMatch:e.ifMatch}:e.ifNoneMatch!==void 0?{idempotencyKey:e.idempotencyKey,ifNoneMatch:e.ifNoneMatch}:{idempotencyKey:e.idempotencyKey},st=e=>e.map(t=>({...t,operation:"upsert"})),$=e=>{let t=T(e);return t==="bootstrap_required"||t==="sync_token_expired"},at=(e,t)=>{if(!Number.isInteger(e)||e<=0)throw new TypeError(`${t} must be a positive integer.`);return e},it=({accountId:e,createIdempotencyKey:t=nt,maxRebaseAttempts:n=rt,pageSize:r=tt,store:o,transport:s})=>{if(!e)throw new TypeError("App State reconciliation requires an account ID.");if(at(r,"pageSize"),!Number.isInteger(n)||n<0)throw new TypeError("maxRebaseAttempts must be a non-negative integer.");let i=e,h=s,f=0,g=Promise.resolve(),l=a=>a.accountId===i&&a.generation===f,A=()=>({accountId:i,generation:f,transport:h}),R=async(a,p)=>l(a)?o.transaction(a.accountId,u=>l(a)?(p(u),true):false):false,G=a=>o.transaction(a.accountId,p=>({bootstrapCursor:p.bootstrapCursor,hasStaging:p.stagingBootstrap!==null,syncToken:p.syncToken})),J=a=>R(a,p=>{p.bootstrapCursor=null,p.stagingBootstrap={},p.syncToken=null;}),M=async(a,p)=>{let u=0;if(!(p&&!await J(a)))for(;l(a);){for(;l(a);){let c=await G(a);if(!l(a))return;if(c.hasStaging&&c.bootstrapCursor===null&&c.syncToken!==null)break;let m;try{m=await a.transport.bootstrap({...c.bootstrapCursor===null?{}:{cursor:c.bootstrapCursor},limit:r});}catch(O){if(!l(a))return;throw O}if(!l(a))return;let d=m.data;if(d.hasMore&&d.nextCursor===null)throw new v("bootstrap_cursor_missing");if(!d.hasMore&&d.nextSyncToken===null)throw new v("bootstrap_sync_token_missing");if(!await R(a,O=>{Ae(O,st(d.items),d.hasMore?d.nextCursor:null),d.hasMore||(O.syncToken=d.nextSyncToken);}))return;if(!d.hasMore)break}for(;l(a);){let{syncToken:c}=await G(a);if(!l(a))return;if(c===null)throw new v("bootstrap_sync_token_missing");let m;try{m=await a.transport.getChanges(c,{limit:r});}catch(y){if(!l(a))return;if(!$(y))throw y;if(!await J(a))return;if(u>=ot)throw y;u+=1;break}if(!l(a)||!await R(a,y=>{_(y,m.data.changes,m.data.nextSyncToken,"stagingBootstrap"),m.data.hasMore||Pe(y);})||!m.data.hasMore)return}}},K=async a=>{let p=await G(a);if(l(a)){if(p.syncToken===null||p.hasStaging){await M(a,false);return}for(;l(a);){let{syncToken:u}=await G(a);if(!l(a))return;if(u===null){await M(a,false);return}try{let c=await a.transport.getChanges(u,{limit:r});if(!l(a)||!await R(a,d=>{_(d,c.data.changes,c.data.nextSyncToken);})||!c.data.hasMore)return}catch(c){if(!l(a))return;if(!$(c))throw c;await M(a,true);return}}}},Ee=async(a,p,u)=>{let c=u.etag;if(c===null)throw new v("put_response_etag_missing");await R(a,m=>{if(m.syncToken!==null){let d={...u.data,etag:c,operation:"upsert",value:p.body.value};_(m,[d],m.syncToken);}L(m,p.localRevision);});},D=async(a,p)=>{await R(a,u=>{let c=E(p.collection,p.key),m=u.shadow[c];m&&(u.shadow[c]={...m,operation:"delete",value:null}),L(u,p.localRevision);});},_e=async(a,p)=>{let u;try{u=await a.transport.getDocument(p.collection,p.key);}catch(d){if(T(d)!=="document_not_found")throw d;u=null;}if(!l(a))return null;if(u!==null&&u.etag===null)throw new Error("App State conflict refresh did not return an ETag.");if(u===null&&p.method==="DELETE")return await D(a,p),null;let c=p.method==="PUT"?{body:p.body,collection:p.collection,idempotencyKey:t(),...u===null?{ifNoneMatch:"*"}:{ifMatch:u.etag},key:p.key,localRevision:p.localRevision,method:"PUT"}:{collection:p.collection,idempotencyKey:t(),ifMatch:u.etag,key:p.key,localRevision:p.localRevision,method:"DELETE"};return await R(a,d=>{u!==null&&d.syncToken!==null&&_(d,[{...u.data,etag:u.etag,operation:"upsert"}],d.syncToken),Ce(d,c);})?c:null},Ge=async(a,p)=>{let u=p,c=0;for(;l(a);)try{if(u.method==="PUT"){let m=await a.transport.putDocument(u.collection,u.key,u.body,Oe(u));if(!l(a))return;await Ee(a,u,m);}else {if(await a.transport.deleteDocument(u.collection,u.key,Oe(u)),!l(a))return;await D(a,u);}return}catch(m){if(!l(a))return;let d=T(m);if(u.method==="DELETE"&&d==="document_not_found"){await D(a,u);return}if(d!=="precondition_failed"||c>=n)throw m;c+=1;let y=await _e(a,u);if(y===null)return;u=y;}},z=async a=>{let p=await o.transaction(a.accountId,Te);for(let u of p){if(!l(a))return;await Ge(a,u);}},Me=async a=>{if(await K(a),!!l(a)){try{await z(a);}catch(p){if(!$(p))throw p;if(await M(a,true),!l(a))return;await z(a);}l(a)&&await K(a);}},C=a=>o.transaction(a,we);return {deleteDocument:async(a,p)=>{let u=A(),c=t();return await o.transaction(u.accountId,m=>{be(m,a,p,c);}),C(i)},getState:()=>C(i),putDocument:async(a,p,u)=>{let c=A(),m=t(),d=JSON.parse(JSON.stringify(u));return await o.transaction(c.accountId,y=>{ke(y,a,p,d,m);}),C(i)},reconcile:()=>{let a=A(),p=g.then(()=>Me(a));return g=p.then(()=>{},()=>{}),p.then(()=>C(i))},switchAccount:(a,p)=>a?(f+=1,i=a,h=p,C(a)):Promise.reject(new TypeError("App State reconciliation requires an account ID."))}};var Ht=e=>{if(e.clientSecret)throw new Error("client_secret is server-only. Use @quranjs/api/server.");return Se(e)};
2
+ exports.AppStateProtocolError=v;exports.QuranHttpError=w;exports.createAppStateMemoryStore=Ze;exports.createAppStateReconciler=it;exports.createPublicClient=Ht;exports.getAppStateErrorCode=T;exports.isAppStateHttpError=We;//# sourceMappingURL=public.min.js.map
3
3
  //# sourceMappingURL=public.min.js.map