From c2bc7661e92058f830cba7cbd690858a72b02424 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Sun, 27 Aug 2023 11:05:33 +0300 Subject: [PATCH] bumped package version --- CHANGELOG.md | 5 +++++ dist/pocketbase.cjs.js | 2 +- dist/pocketbase.cjs.js.map | 2 +- dist/pocketbase.es.js | 2 +- dist/pocketbase.es.js.map | 2 +- dist/pocketbase.es.mjs | 2 +- dist/pocketbase.es.mjs.map | 2 +- dist/pocketbase.iife.js | 2 +- dist/pocketbase.iife.js.map | 2 +- dist/pocketbase.umd.js | 2 +- dist/pocketbase.umd.js.map | 2 +- package.json | 2 +- 12 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e4a679..26d6abf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.17.1 + +- Fixed typo in the deprecation console.warn messages ([#235](https://github.com/pocketbase/js-sdk/pull/235); thanks @heloineto). + + ## 0.17.0 - To simplify file uploads, we now allow sending the `multipart/form-data` request body also as plain object if at least one of the object props has `File` or `Blob` value. diff --git a/dist/pocketbase.cjs.js b/dist/pocketbase.cjs.js index 66491f9..8a820ee 100644 --- a/dist/pocketbase.cjs.js +++ b/dist/pocketbase.cjs.js @@ -1,2 +1,2 @@ -"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);l=cookieSerialize(t,JSON.stringify(a),e)}return l}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const l={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(l.scope=t.scopes.join(" "));const c=this._replaceQueryParams(i.authUrl+s,l);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(c)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];module.exports=class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}; +"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);l=cookieSerialize(t,JSON.stringify(a),e)}return l}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const l={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(l.scope=t.scopes.join(" "));const c=this._replaceQueryParams(i.authUrl+s,l);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(c)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];module.exports=class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}; //# sourceMappingURL=pocketbase.cjs.js.map diff --git a/dist/pocketbase.cjs.js.map b/dist/pocketbase.cjs.js.map index 33569a4..8df32a8 100644 --- a/dist/pocketbase.cjs.js.map +++ b/dist/pocketbase.cjs.js.map @@ -1 +1 @@ -{"version":3,"file":"pocketbase.cjs.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pocketbase.cjs.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"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"} \ No newline at end of file diff --git a/dist/pocketbase.es.js b/dist/pocketbase.es.js index e02c3b2..ae70345 100644 --- a/dist/pocketbase.es.js +++ b/dist/pocketbase.es.js @@ -1,2 +1,2 @@ -function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n0&&(!i.exp||i.exp-t>Date.now()/1e3))}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!isTokenExpired(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=cookieParse(e||"")[t]||"";let n={};try{n=JSON.parse(s),(null===typeof n||"object"!=typeof n||Array.isArray(n))&&(n={})}catch(e){}this.save(n.token||"",n.model||null)}exportToCookie(e,t=i){var s,n;const o={secure:!0,sameSite:!0,httpOnly:!0,path:"/"},r=getTokenPayload(this.token);(null==r?void 0:r.exp)?o.expires=new Date(1e3*r.exp):o.expires=new Date("1970-01-01"),e=Object.assign({},o,e);const a={token:this.token,model:this.model?JSON.parse(JSON.stringify(this.model)):null};let c=cookieSerialize(t,JSON.stringify(a),e);const l="undefined"!=typeof Blob?new Blob([c]).size:c.length;if(a.model&&l>4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}class AsyncAuthStore extends BaseAuthStore{constructor(e){super(),this.queue=[],this.saveFunc=e.save,this.clearFunc=e.clear,this._loadInitial(e.initial)}save(e,t){super.save(e,t);let i="";try{i=JSON.stringify({token:e,model:t})}catch(e){console.warn("AsyncAuthStore: failed to stringify the new state")}this._enqueue((()=>this.saveFunc(i)))}clear(){super.clear(),this.clearFunc?this._enqueue((()=>this.clearFunc())):this._enqueue((()=>this.saveFunc("")))}_loadInitial(e){if(e)try{const t=JSON.parse(e)||{};this.save(t.token||"",t.model||null)}catch(e){}}_enqueue(e){this.queue.push(e),1==this.queue.length&&this._dequeue()}_dequeue(){this.queue.length&&this.queue[0]().finally((()=>{this.queue.shift(),this.queue.length&&this._dequeue()}))}}export{AdminService,AsyncAuthStore,BaseAuthStore,ClientResponseError,CollectionService,CrudService,LocalAuthStore,LogService,RealtimeService,RecordService,cookieParse,cookieSerialize,Client as default,getTokenPayload,isTokenExpired}; +function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n0&&(!i.exp||i.exp-t>Date.now()/1e3))}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!isTokenExpired(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=cookieParse(e||"")[t]||"";let n={};try{n=JSON.parse(s),(null===typeof n||"object"!=typeof n||Array.isArray(n))&&(n={})}catch(e){}this.save(n.token||"",n.model||null)}exportToCookie(e,t=i){var s,n;const o={secure:!0,sameSite:!0,httpOnly:!0,path:"/"},r=getTokenPayload(this.token);(null==r?void 0:r.exp)?o.expires=new Date(1e3*r.exp):o.expires=new Date("1970-01-01"),e=Object.assign({},o,e);const a={token:this.token,model:this.model?JSON.parse(JSON.stringify(this.model)):null};let c=cookieSerialize(t,JSON.stringify(a),e);const l="undefined"!=typeof Blob?new Blob([c]).size:c.length;if(a.model&&l>4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}class AsyncAuthStore extends BaseAuthStore{constructor(e){super(),this.queue=[],this.saveFunc=e.save,this.clearFunc=e.clear,this._loadInitial(e.initial)}save(e,t){super.save(e,t);let i="";try{i=JSON.stringify({token:e,model:t})}catch(e){console.warn("AsyncAuthStore: failed to stringify the new state")}this._enqueue((()=>this.saveFunc(i)))}clear(){super.clear(),this.clearFunc?this._enqueue((()=>this.clearFunc())):this._enqueue((()=>this.saveFunc("")))}_loadInitial(e){if(e)try{const t=JSON.parse(e)||{};this.save(t.token||"",t.model||null)}catch(e){}}_enqueue(e){this.queue.push(e),1==this.queue.length&&this._dequeue()}_dequeue(){this.queue.length&&this.queue[0]().finally((()=>{this.queue.shift(),this.queue.length&&this._dequeue()}))}}export{AdminService,AsyncAuthStore,BaseAuthStore,ClientResponseError,CollectionService,CrudService,LocalAuthStore,LogService,RealtimeService,RecordService,cookieParse,cookieSerialize,Client as default,getTokenPayload,isTokenExpired}; //# sourceMappingURL=pocketbase.es.js.map diff --git a/dist/pocketbase.es.js.map b/dist/pocketbase.es.js.map index 8cb21cb..fd654e1 100644 --- a/dist/pocketbase.es.js.map +++ b/dist/pocketbase.es.js.map @@ -1 +1 @@ -{"version":3,"file":"pocketbase.es.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts","../src/stores/AsyncAuthStore.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\nexport type AsyncSaveFunc = (serializedPayload: string) => Promise;\n\nexport type AsyncClearFunc = () => Promise;\n\ntype queueFunc = () => Promise;\n\n/**\n * AsyncAuthStore is a helper auth store implementation\n * that could be used with any external async persistent layer\n * (key-value db, local file, etc.).\n *\n * Here is an example with the React Native AsyncStorage package:\n *\n * ```\n * import AsyncStorage from \"@react-native-async-storage/async-storage\";\n * import PocketBase, { AsyncAuthStore } from \"pocketbase\";\n *\n * const store = new AsyncAuthStore({\n * save: async (serialized) => AsyncStorage.setItem(\"pb_auth\", serialized),\n * initial: await AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n private saveFunc: AsyncSaveFunc;\n private clearFunc?: AsyncClearFunc;\n private queue: Array = [];\n\n constructor(config: {\n // The async function that is called every time\n // when the auth store state needs to be persisted.\n save: AsyncSaveFunc,\n\n /// An *optional* async function that is called every time\n /// when the auth store needs to be cleared.\n ///\n /// If not explicitly set, `saveFunc` with empty data will be used.\n clear?: AsyncClearFunc,\n\n // initial data to load into the store\n initial?: string,\n }) {\n super();\n\n this.saveFunc = config.save;\n this.clearFunc = config.clear;\n\n this._loadInitial(config.initial);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel): void {\n super.save(token, model);\n\n let value = '';\n try {\n value = JSON.stringify({token, model})\n } catch (err) {\n console.warn('AsyncAuthStore: failed to stringify the new state');\n }\n\n this._enqueue(() => this.saveFunc(value));\n }\n\n /**\n * @inheritdoc\n */\n clear(): void {\n super.clear();\n\n if (this.clearFunc) {\n this._enqueue(() => this.clearFunc!());\n } else {\n this._enqueue(() => this.saveFunc(\"\"));\n }\n }\n\n\n /**\n * Initializes the auth store state.\n */\n private _loadInitial(payload?: string) {\n if (!payload) {\n return; // nothing to load\n }\n\n try {\n const parsed = JSON.parse(payload) || {};\n\n this.save(parsed.token || \"\", parsed.model || null);\n } catch (_) {}\n }\n\n /**\n * Appends an async function to the queue.\n */\n private _enqueue(asyncCallback: () => Promise) {\n this.queue.push(asyncCallback);\n\n if (this.queue.length == 1) {\n this._dequeue();\n }\n }\n\n /**\n * Starts the queue processing.\n */\n private _dequeue() {\n if (!this.queue.length) {\n return;\n }\n\n this.queue[0]().finally(() => {\n this.queue.shift();\n\n if (!this.queue.length) {\n return;\n }\n\n this._dequeue();\n });\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieParse","str","options","result","decode","defaultDecode","index","length","eqIdx","indexOf","endIdx","lastIndexOf","key","slice","trim","undefined","val","charCodeAt","_","cookieSerialize","opt","encode","defaultEncode","test","TypeError","value","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","join","JSON","parse","e","isTokenExpired","expirationThreshold","payload","keys","exp","now","atob","input","String","replace","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","rawData","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString","AsyncAuthStore","queue","saveFunc","clearFunc","_loadInitial","initial","_enqueue","parsed","asyncCallback","_dequeue","finally","shift"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pocketbase.es.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts","../src/stores/AsyncAuthStore.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\nexport type AsyncSaveFunc = (serializedPayload: string) => Promise;\n\nexport type AsyncClearFunc = () => Promise;\n\ntype queueFunc = () => Promise;\n\n/**\n * AsyncAuthStore is a helper auth store implementation\n * that could be used with any external async persistent layer\n * (key-value db, local file, etc.).\n *\n * Here is an example with the React Native AsyncStorage package:\n *\n * ```\n * import AsyncStorage from \"@react-native-async-storage/async-storage\";\n * import PocketBase, { AsyncAuthStore } from \"pocketbase\";\n *\n * const store = new AsyncAuthStore({\n * save: async (serialized) => AsyncStorage.setItem(\"pb_auth\", serialized),\n * initial: await AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n private saveFunc: AsyncSaveFunc;\n private clearFunc?: AsyncClearFunc;\n private queue: Array = [];\n\n constructor(config: {\n // The async function that is called every time\n // when the auth store state needs to be persisted.\n save: AsyncSaveFunc,\n\n /// An *optional* async function that is called every time\n /// when the auth store needs to be cleared.\n ///\n /// If not explicitly set, `saveFunc` with empty data will be used.\n clear?: AsyncClearFunc,\n\n // initial data to load into the store\n initial?: string,\n }) {\n super();\n\n this.saveFunc = config.save;\n this.clearFunc = config.clear;\n\n this._loadInitial(config.initial);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel): void {\n super.save(token, model);\n\n let value = '';\n try {\n value = JSON.stringify({token, model})\n } catch (err) {\n console.warn('AsyncAuthStore: failed to stringify the new state');\n }\n\n this._enqueue(() => this.saveFunc(value));\n }\n\n /**\n * @inheritdoc\n */\n clear(): void {\n super.clear();\n\n if (this.clearFunc) {\n this._enqueue(() => this.clearFunc!());\n } else {\n this._enqueue(() => this.saveFunc(\"\"));\n }\n }\n\n\n /**\n * Initializes the auth store state.\n */\n private _loadInitial(payload?: string) {\n if (!payload) {\n return; // nothing to load\n }\n\n try {\n const parsed = JSON.parse(payload) || {};\n\n this.save(parsed.token || \"\", parsed.model || null);\n } catch (_) {}\n }\n\n /**\n * Appends an async function to the queue.\n */\n private _enqueue(asyncCallback: () => Promise) {\n this.queue.push(asyncCallback);\n\n if (this.queue.length == 1) {\n this._dequeue();\n }\n }\n\n /**\n * Starts the queue processing.\n */\n private _dequeue() {\n if (!this.queue.length) {\n return;\n }\n\n this.queue[0]().finally(() => {\n this.queue.shift();\n\n if (!this.queue.length) {\n return;\n }\n\n this._dequeue();\n });\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieParse","str","options","result","decode","defaultDecode","index","length","eqIdx","indexOf","endIdx","lastIndexOf","key","slice","trim","undefined","val","charCodeAt","_","cookieSerialize","opt","encode","defaultEncode","test","TypeError","value","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","join","JSON","parse","e","isTokenExpired","expirationThreshold","payload","keys","exp","now","atob","input","String","replace","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","rawData","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString","AsyncAuthStore","queue","saveFunc","clearFunc","_loadInitial","initial","_enqueue","parsed","asyncCallback","_dequeue","finally","shift"],"mappings":"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"} \ No newline at end of file diff --git a/dist/pocketbase.es.mjs b/dist/pocketbase.es.mjs index c58045f..382a8a6 100644 --- a/dist/pocketbase.es.mjs +++ b/dist/pocketbase.es.mjs @@ -1,2 +1,2 @@ -function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n0&&(!i.exp||i.exp-t>Date.now()/1e3))}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!isTokenExpired(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=cookieParse(e||"")[t]||"";let n={};try{n=JSON.parse(s),(null===typeof n||"object"!=typeof n||Array.isArray(n))&&(n={})}catch(e){}this.save(n.token||"",n.model||null)}exportToCookie(e,t=i){var s,n;const o={secure:!0,sameSite:!0,httpOnly:!0,path:"/"},r=getTokenPayload(this.token);(null==r?void 0:r.exp)?o.expires=new Date(1e3*r.exp):o.expires=new Date("1970-01-01"),e=Object.assign({},o,e);const a={token:this.token,model:this.model?JSON.parse(JSON.stringify(this.model)):null};let c=cookieSerialize(t,JSON.stringify(a),e);const l="undefined"!=typeof Blob?new Blob([c]).size:c.length;if(a.model&&l>4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}class AsyncAuthStore extends BaseAuthStore{constructor(e){super(),this.queue=[],this.saveFunc=e.save,this.clearFunc=e.clear,this._loadInitial(e.initial)}save(e,t){super.save(e,t);let i="";try{i=JSON.stringify({token:e,model:t})}catch(e){console.warn("AsyncAuthStore: failed to stringify the new state")}this._enqueue((()=>this.saveFunc(i)))}clear(){super.clear(),this.clearFunc?this._enqueue((()=>this.clearFunc())):this._enqueue((()=>this.saveFunc("")))}_loadInitial(e){if(e)try{const t=JSON.parse(e)||{};this.save(t.token||"",t.model||null)}catch(e){}}_enqueue(e){this.queue.push(e),1==this.queue.length&&this._dequeue()}_dequeue(){this.queue.length&&this.queue[0]().finally((()=>{this.queue.shift(),this.queue.length&&this._dequeue()}))}}export{AdminService,AsyncAuthStore,BaseAuthStore,ClientResponseError,CollectionService,CrudService,LocalAuthStore,LogService,RealtimeService,RecordService,cookieParse,cookieSerialize,Client as default,getTokenPayload,isTokenExpired}; +function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n0&&(!i.exp||i.exp-t>Date.now()/1e3))}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!isTokenExpired(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=cookieParse(e||"")[t]||"";let n={};try{n=JSON.parse(s),(null===typeof n||"object"!=typeof n||Array.isArray(n))&&(n={})}catch(e){}this.save(n.token||"",n.model||null)}exportToCookie(e,t=i){var s,n;const o={secure:!0,sameSite:!0,httpOnly:!0,path:"/"},r=getTokenPayload(this.token);(null==r?void 0:r.exp)?o.expires=new Date(1e3*r.exp):o.expires=new Date("1970-01-01"),e=Object.assign({},o,e);const a={token:this.token,model:this.model?JSON.parse(JSON.stringify(this.model)):null};let c=cookieSerialize(t,JSON.stringify(a),e);const l="undefined"!=typeof Blob?new Blob([c]).size:c.length;if(a.model&&l>4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}class AsyncAuthStore extends BaseAuthStore{constructor(e){super(),this.queue=[],this.saveFunc=e.save,this.clearFunc=e.clear,this._loadInitial(e.initial)}save(e,t){super.save(e,t);let i="";try{i=JSON.stringify({token:e,model:t})}catch(e){console.warn("AsyncAuthStore: failed to stringify the new state")}this._enqueue((()=>this.saveFunc(i)))}clear(){super.clear(),this.clearFunc?this._enqueue((()=>this.clearFunc())):this._enqueue((()=>this.saveFunc("")))}_loadInitial(e){if(e)try{const t=JSON.parse(e)||{};this.save(t.token||"",t.model||null)}catch(e){}}_enqueue(e){this.queue.push(e),1==this.queue.length&&this._dequeue()}_dequeue(){this.queue.length&&this.queue[0]().finally((()=>{this.queue.shift(),this.queue.length&&this._dequeue()}))}}export{AdminService,AsyncAuthStore,BaseAuthStore,ClientResponseError,CollectionService,CrudService,LocalAuthStore,LogService,RealtimeService,RecordService,cookieParse,cookieSerialize,Client as default,getTokenPayload,isTokenExpired}; //# sourceMappingURL=pocketbase.es.mjs.map diff --git a/dist/pocketbase.es.mjs.map b/dist/pocketbase.es.mjs.map index caf34d2..b1f57cb 100644 --- a/dist/pocketbase.es.mjs.map +++ b/dist/pocketbase.es.mjs.map @@ -1 +1 @@ -{"version":3,"file":"pocketbase.es.mjs","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts","../src/stores/AsyncAuthStore.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\nexport type AsyncSaveFunc = (serializedPayload: string) => Promise;\n\nexport type AsyncClearFunc = () => Promise;\n\ntype queueFunc = () => Promise;\n\n/**\n * AsyncAuthStore is a helper auth store implementation\n * that could be used with any external async persistent layer\n * (key-value db, local file, etc.).\n *\n * Here is an example with the React Native AsyncStorage package:\n *\n * ```\n * import AsyncStorage from \"@react-native-async-storage/async-storage\";\n * import PocketBase, { AsyncAuthStore } from \"pocketbase\";\n *\n * const store = new AsyncAuthStore({\n * save: async (serialized) => AsyncStorage.setItem(\"pb_auth\", serialized),\n * initial: await AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n private saveFunc: AsyncSaveFunc;\n private clearFunc?: AsyncClearFunc;\n private queue: Array = [];\n\n constructor(config: {\n // The async function that is called every time\n // when the auth store state needs to be persisted.\n save: AsyncSaveFunc,\n\n /// An *optional* async function that is called every time\n /// when the auth store needs to be cleared.\n ///\n /// If not explicitly set, `saveFunc` with empty data will be used.\n clear?: AsyncClearFunc,\n\n // initial data to load into the store\n initial?: string,\n }) {\n super();\n\n this.saveFunc = config.save;\n this.clearFunc = config.clear;\n\n this._loadInitial(config.initial);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel): void {\n super.save(token, model);\n\n let value = '';\n try {\n value = JSON.stringify({token, model})\n } catch (err) {\n console.warn('AsyncAuthStore: failed to stringify the new state');\n }\n\n this._enqueue(() => this.saveFunc(value));\n }\n\n /**\n * @inheritdoc\n */\n clear(): void {\n super.clear();\n\n if (this.clearFunc) {\n this._enqueue(() => this.clearFunc!());\n } else {\n this._enqueue(() => this.saveFunc(\"\"));\n }\n }\n\n\n /**\n * Initializes the auth store state.\n */\n private _loadInitial(payload?: string) {\n if (!payload) {\n return; // nothing to load\n }\n\n try {\n const parsed = JSON.parse(payload) || {};\n\n this.save(parsed.token || \"\", parsed.model || null);\n } catch (_) {}\n }\n\n /**\n * Appends an async function to the queue.\n */\n private _enqueue(asyncCallback: () => Promise) {\n this.queue.push(asyncCallback);\n\n if (this.queue.length == 1) {\n this._dequeue();\n }\n }\n\n /**\n * Starts the queue processing.\n */\n private _dequeue() {\n if (!this.queue.length) {\n return;\n }\n\n this.queue[0]().finally(() => {\n this.queue.shift();\n\n if (!this.queue.length) {\n return;\n }\n\n this._dequeue();\n });\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieParse","str","options","result","decode","defaultDecode","index","length","eqIdx","indexOf","endIdx","lastIndexOf","key","slice","trim","undefined","val","charCodeAt","_","cookieSerialize","opt","encode","defaultEncode","test","TypeError","value","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","join","JSON","parse","e","isTokenExpired","expirationThreshold","payload","keys","exp","now","atob","input","String","replace","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","rawData","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString","AsyncAuthStore","queue","saveFunc","clearFunc","_loadInitial","initial","_enqueue","parsed","asyncCallback","_dequeue","finally","shift"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pocketbase.es.mjs","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts","../src/stores/AsyncAuthStore.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\nexport type AsyncSaveFunc = (serializedPayload: string) => Promise;\n\nexport type AsyncClearFunc = () => Promise;\n\ntype queueFunc = () => Promise;\n\n/**\n * AsyncAuthStore is a helper auth store implementation\n * that could be used with any external async persistent layer\n * (key-value db, local file, etc.).\n *\n * Here is an example with the React Native AsyncStorage package:\n *\n * ```\n * import AsyncStorage from \"@react-native-async-storage/async-storage\";\n * import PocketBase, { AsyncAuthStore } from \"pocketbase\";\n *\n * const store = new AsyncAuthStore({\n * save: async (serialized) => AsyncStorage.setItem(\"pb_auth\", serialized),\n * initial: await AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n private saveFunc: AsyncSaveFunc;\n private clearFunc?: AsyncClearFunc;\n private queue: Array = [];\n\n constructor(config: {\n // The async function that is called every time\n // when the auth store state needs to be persisted.\n save: AsyncSaveFunc,\n\n /// An *optional* async function that is called every time\n /// when the auth store needs to be cleared.\n ///\n /// If not explicitly set, `saveFunc` with empty data will be used.\n clear?: AsyncClearFunc,\n\n // initial data to load into the store\n initial?: string,\n }) {\n super();\n\n this.saveFunc = config.save;\n this.clearFunc = config.clear;\n\n this._loadInitial(config.initial);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel): void {\n super.save(token, model);\n\n let value = '';\n try {\n value = JSON.stringify({token, model})\n } catch (err) {\n console.warn('AsyncAuthStore: failed to stringify the new state');\n }\n\n this._enqueue(() => this.saveFunc(value));\n }\n\n /**\n * @inheritdoc\n */\n clear(): void {\n super.clear();\n\n if (this.clearFunc) {\n this._enqueue(() => this.clearFunc!());\n } else {\n this._enqueue(() => this.saveFunc(\"\"));\n }\n }\n\n\n /**\n * Initializes the auth store state.\n */\n private _loadInitial(payload?: string) {\n if (!payload) {\n return; // nothing to load\n }\n\n try {\n const parsed = JSON.parse(payload) || {};\n\n this.save(parsed.token || \"\", parsed.model || null);\n } catch (_) {}\n }\n\n /**\n * Appends an async function to the queue.\n */\n private _enqueue(asyncCallback: () => Promise) {\n this.queue.push(asyncCallback);\n\n if (this.queue.length == 1) {\n this._dequeue();\n }\n }\n\n /**\n * Starts the queue processing.\n */\n private _dequeue() {\n if (!this.queue.length) {\n return;\n }\n\n this.queue[0]().finally(() => {\n this.queue.shift();\n\n if (!this.queue.length) {\n return;\n }\n\n this._dequeue();\n });\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieParse","str","options","result","decode","defaultDecode","index","length","eqIdx","indexOf","endIdx","lastIndexOf","key","slice","trim","undefined","val","charCodeAt","_","cookieSerialize","opt","encode","defaultEncode","test","TypeError","value","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","join","JSON","parse","e","isTokenExpired","expirationThreshold","payload","keys","exp","now","atob","input","String","replace","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","rawData","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString","AsyncAuthStore","queue","saveFunc","clearFunc","_loadInitial","initial","_enqueue","parsed","asyncCallback","_dequeue","finally","shift"],"mappings":"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"} \ No newline at end of file diff --git a/dist/pocketbase.iife.js b/dist/pocketbase.iife.js index 9ecef13..ac0c0e0 100644 --- a/dist/pocketbase.iife.js +++ b/dist/pocketbase.iife.js @@ -1,2 +1,2 @@ -var PocketBase=function(){"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];return class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}}(); +var PocketBase=function(){"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);c=cookieSerialize(t,JSON.stringify(a),e)}return c}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const c={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(c.scope=t.scopes.join(" "));const l=this._replaceQueryParams(i.authUrl+s,c);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(l)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];return class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}}(); //# sourceMappingURL=pocketbase.iife.js.map diff --git a/dist/pocketbase.iife.js.map b/dist/pocketbase.iife.js.map index b1509ad..e562422 100644 --- a/dist/pocketbase.iife.js.map +++ b/dist/pocketbase.iife.js.map @@ -1 +1 @@ -{"version":3,"file":"pocketbase.iife.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pocketbase.iife.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"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"} \ No newline at end of file diff --git a/dist/pocketbase.umd.js b/dist/pocketbase.umd.js index 4bb58e4..ec93a0e 100644 --- a/dist/pocketbase.umd.js +++ b/dist/pocketbase.umd.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).PocketBase=t()}(this,(function(){"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);l=cookieSerialize(t,JSON.stringify(a),e)}return l}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const l={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(l.scope=t.scopes.join(" "));const c=this._replaceQueryParams(i.authUrl+s,l);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(c)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];return class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}})); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).PocketBase=t()}(this,(function(){"use strict";function __awaiter(e,t,i,s){return new(i||(i=Promise))((function(n,o){function fulfilled(e){try{step(s.next(e))}catch(e){o(e)}}function rejected(e){try{step(s.throw(e))}catch(e){o(e)}}function step(e){e.done?n(e.value):function adopt(e){return e instanceof i?e:new i((function(t){t(e)}))}(e.value).then(fulfilled,rejected)}step((s=s.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class ClientResponseError extends Error{constructor(e){var t,i,s,n;super("ClientResponseError"),this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),null!==e&&"object"==typeof e&&(this.url="string"==typeof e.url?e.url:"",this.status="number"==typeof e.status?e.status:0,this.isAbort=!!e.isAbort,this.originalError=e.originalError,null!==e.response&&"object"==typeof e.response?this.response=e.response:null!==e.data&&"object"==typeof e.data?this.response=e.data:this.response={}),this.originalError||e instanceof ClientResponseError||(this.originalError=e),"undefined"!=typeof DOMException&&e instanceof DOMException&&(this.isAbort=!0),this.name="ClientResponseError "+this.status,this.message=null===(t=this.response)||void 0===t?void 0:t.message,this.message||(this.isAbort?this.message="The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.":(null===(n=null===(s=null===(i=this.originalError)||void 0===i?void 0:i.cause)||void 0===s?void 0:s.message)||void 0===n?void 0:n.includes("ECONNREFUSED ::1"))?this.message="Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).":this.message="Something went wrong while processing your request.")}get data(){return this.response}toJSON(){return Object.assign({},this)}}const e=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieSerialize(t,i,s){const n=Object.assign({},s||{}),o=n.encode||defaultEncode;if(!e.test(t))throw new TypeError("argument name is invalid");const r=o(i);if(r&&!e.test(r))throw new TypeError("argument val is invalid");let a=t+"="+r;if(null!=n.maxAge){const e=n.maxAge-0;if(isNaN(e)||!isFinite(e))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(e)}if(n.domain){if(!e.test(n.domain))throw new TypeError("option domain is invalid");a+="; Domain="+n.domain}if(n.path){if(!e.test(n.path))throw new TypeError("option path is invalid");a+="; Path="+n.path}if(n.expires){if(!function isDate(e){return"[object Date]"===Object.prototype.toString.call(e)||e instanceof Date}(n.expires)||isNaN(n.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+n.expires.toUTCString()}if(n.httpOnly&&(a+="; HttpOnly"),n.secure&&(a+="; Secure"),n.priority){switch("string"==typeof n.priority?n.priority.toLowerCase():n.priority){case"low":a+="; Priority=Low";break;case"medium":a+="; Priority=Medium";break;case"high":a+="; Priority=High";break;default:throw new TypeError("option priority is invalid")}}if(n.sameSite){switch("string"==typeof n.sameSite?n.sameSite.toLowerCase():n.sameSite){case!0:a+="; SameSite=Strict";break;case"lax":a+="; SameSite=Lax";break;case"strict":a+="; SameSite=Strict";break;case"none":a+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return a}function defaultDecode(e){return-1!==e.indexOf("%")?decodeURIComponent(e):e}function defaultEncode(e){return encodeURIComponent(e)}let t;function getTokenPayload(e){if(e)try{const i=decodeURIComponent(t(e.split(".")[1]).split("").map((function(e){return"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)})).join(""));return JSON.parse(i)||{}}catch(e){}return{}}t="function"==typeof atob?atob:e=>{let t=String(e).replace(/=+$/,"");if(t.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var i,s,n=0,o=0,r="";s=t.charAt(o++);~s&&(i=n%4?64*i+s:s,n++%4)?r+=String.fromCharCode(255&i>>(-2*n&6)):0)s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(s);return r};const i="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get model(){return this.baseModel}get isValid(){return!function isTokenExpired(e,t=0){let i=getTokenPayload(e);return!(Object.keys(i).length>0&&(!i.exp||i.exp-t>Date.now()/1e3))}(this.token)}get isAdmin(){return"admin"===getTokenPayload(this.token).type}get isAuthRecord(){return"authRecord"===getTokenPayload(this.token).type}save(e,t){this.baseToken=e||"",this.baseModel=t||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(e,t=i){const s=function cookieParse(e,t){const i={};if("string"!=typeof e)return i;const s=Object.assign({},t||{}).decode||defaultDecode;let n=0;for(;n4096){a.model={id:null===(s=null==a?void 0:a.model)||void 0===s?void 0:s.id,email:null===(n=null==a?void 0:a.model)||void 0===n?void 0:n.email};const i=["collectionId","username","verified"];for(const e in this.model)i.includes(e)&&(a.model[e]=this.model[e]);l=cookieSerialize(t,JSON.stringify(a),e)}return l}onChange(e,t=!1){return this._onChangeCallbacks.push(e),t&&e(this.token,this.model),()=>{for(let t=this._onChangeCallbacks.length-1;t>=0;t--)if(this._onChangeCallbacks[t]==e)return delete this._onChangeCallbacks[t],void this._onChangeCallbacks.splice(t,1)}}triggerChange(){for(const e of this._onChangeCallbacks)e&&e(this.token,this.model)}}class LocalAuthStore extends BaseAuthStore{constructor(e="pocketbase_auth"){super(),this.storageFallback={},this.storageKey=e,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get model(){return(this._storageGet(this.storageKey)||{}).model||null}save(e,t){this._storageSet(this.storageKey,{token:e,model:t}),super.save(e,t)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(e){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){const t=window.localStorage.getItem(e)||"";try{return JSON.parse(t)}catch(e){return t}}return this.storageFallback[e]}_storageSet(e,t){if("undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)){let i=t;"string"!=typeof t&&(i=JSON.stringify(t)),window.localStorage.setItem(e,i)}else this.storageFallback[e]=t}_storageRemove(e){var t;"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&(null===(t=window.localStorage)||void 0===t||t.removeItem(e)),delete this.storageFallback[e]}_bindStorageEvent(){"undefined"!=typeof window&&(null===window||void 0===window?void 0:window.localStorage)&&window.addEventListener&&window.addEventListener("storage",(e=>{if(e.key!=this.storageKey)return;const t=this._storageGet(this.storageKey)||{};super.save(t.token||"",t.model||null)}))}}class BaseService{constructor(e){this.client=e}}class SettingsService extends BaseService{getAll(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/settings",e)}update(e,t){return t=Object.assign({method:"PATCH",body:e},t),this.client.send("/api/settings",t)}testS3(e="storage",t){return t=Object.assign({method:"POST",body:{filesystem:e}},t),this.client.send("/api/settings/test/s3",t).then((()=>!0))}testEmail(e,t,i){return i=Object.assign({method:"POST",body:{email:e,template:t}},i),this.client.send("/api/settings/test/email",i).then((()=>!0))}generateAppleClientSecret(e,t,i,s,n,o){return o=Object.assign({method:"POST",body:{clientId:e,teamId:t,keyId:i,privateKey:s,duration:n}},o),this.client.send("/api/settings/apple/generate-client-secret",o)}}class CrudService extends BaseService{decode(e){return e}getFullList(e,t){if("number"==typeof e)return this._getFullList(e,t);let i=500;return(t=Object.assign({},e,t)).batch&&(i=t.batch,delete t.batch),this._getFullList(i,t)}getList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send(this.baseCrudPath,i).then((e=>{var t;return e.items=(null===(t=e.items)||void 0===t?void 0:t.map((e=>this.decode(e))))||[],e}))}getFirstListItem(e,t){return(t=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+e},t)).query=Object.assign({filter:e,skipTotal:1},t.query),this.getList(1,1,t).then((e=>{var t;if(!(null===(t=null==e?void 0:e.items)||void 0===t?void 0:t.length))throw new ClientResponseError({status:404,data:{code:404,message:"The requested resource wasn't found.",data:{}}});return e.items[0]}))}getOne(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((e=>this.decode(e)))}create(e,t){return t=Object.assign({method:"POST",body:e},t),this.client.send(this.baseCrudPath,t).then((e=>this.decode(e)))}update(e,t,i){return i=Object.assign({method:"PATCH",body:t},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),i).then((e=>this.decode(e)))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e),t).then((()=>!0))}_getFullList(e=500,t){(t=t||{}).query=Object.assign({skipTotal:1},t.query);let i=[],request=s=>__awaiter(this,void 0,void 0,(function*(){return this.getList(s,e||500,t).then((e=>{const t=e.items;return i=i.concat(t),t.length==e.perPage?request(s+1):i}))}));return request(1)}}function normalizeLegacyOptionsArgs(e,t,i,s){const n=void 0!==s;return n||void 0!==i?n?(console.warn(e),t.body=Object.assign({},t.body,i),t.query=Object.assign({},t.query,s),t):t=Object.assign(t,i):t}class AdminService extends CrudService{get baseCrudPath(){return"/api/admins"}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)===e.id&&void 0===(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)&&this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s;return t&&(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)===e&&void 0===(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)&&this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.admin)||{});return(null==e?void 0:e.token)&&(null==e?void 0:e.admin)&&this.client.authStore.save(e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",admin:t})}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).",n,i,s),this.client.send(this.baseCrudPath+"/auth-with-password",n).then(this.authResponse.bind(this))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCrudPath+"/auth-refresh",i).then(this.authResponse.bind(this))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCrudPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCrudPath+"/confirm-password-reset",o).then((()=>!0))}}class RealtimeService extends BaseService{constructor(){super(...arguments),this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentTopics=[],this.maxConnectTimeout=15e3,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1e3,1200,1500,2e3],this.pendingConnects=[]}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}subscribe(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!e)throw new Error("topic must be set.");const listener=function(e){const i=e;let s;try{s=JSON.parse(null==i?void 0:i.data)}catch(e){}t(s||{})};return this.subscriptions[e]||(this.subscriptions[e]=[]),this.subscriptions[e].push(listener),this.isConnected?1===this.subscriptions[e].length?yield this.submitSubscriptions():null===(i=this.eventSource)||void 0===i||i.addEventListener(e,listener):yield this.connect(),()=>__awaiter(this,void 0,void 0,(function*(){return this.unsubscribeByTopicAndListener(e,listener)}))}))}unsubscribe(e){var t;return __awaiter(this,void 0,void 0,(function*(){if(this.hasSubscriptionListeners(e)){if(e){for(let i of this.subscriptions[e])null===(t=this.eventSource)||void 0===t||t.removeEventListener(e,i);delete this.subscriptions[e]}else this.subscriptions={};this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect()}}))}unsubscribeByPrefix(e){var t;return __awaiter(this,void 0,void 0,(function*(){let i=!1;for(let s in this.subscriptions)if(s.startsWith(e)){i=!0;for(let e of this.subscriptions[s])null===(t=this.eventSource)||void 0===t||t.removeEventListener(s,e);delete this.subscriptions[s]}i&&(this.hasSubscriptionListeners()?yield this.submitSubscriptions():this.disconnect())}))}unsubscribeByTopicAndListener(e,t){var i;return __awaiter(this,void 0,void 0,(function*(){if(!Array.isArray(this.subscriptions[e])||!this.subscriptions[e].length)return;let s=!1;for(let n=this.subscriptions[e].length-1;n>=0;n--)this.subscriptions[e][n]===t&&(s=!0,delete this.subscriptions[e][n],this.subscriptions[e].splice(n,1),null===(i=this.eventSource)||void 0===i||i.removeEventListener(e,t));s&&(this.subscriptions[e].length||delete this.subscriptions[e],this.hasSubscriptionListeners()?this.hasSubscriptionListeners(e)||(yield this.submitSubscriptions()):this.disconnect())}))}hasSubscriptionListeners(e){var t,i;if(this.subscriptions=this.subscriptions||{},e)return!!(null===(t=this.subscriptions[e])||void 0===t?void 0:t.length);for(let e in this.subscriptions)if(null===(i=this.subscriptions[e])||void 0===i?void 0:i.length)return!0;return!1}submitSubscriptions(){return __awaiter(this,void 0,void 0,(function*(){if(this.clientId)return this.addAllSubscriptionListeners(),this.lastSentTopics=this.getNonEmptySubscriptionTopics(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentTopics},query:{requestKey:this.getSubscriptionsCancelKey()}}).catch((e=>{if(!(null==e?void 0:e.isAbort))throw e}))}))}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getNonEmptySubscriptionTopics(){const e=[];for(let t in this.subscriptions)this.subscriptions[t].length&&e.push(t);return e}addAllSubscriptionListeners(){if(this.eventSource){this.removeAllSubscriptionListeners();for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.addEventListener(e,t)}}removeAllSubscriptionListeners(){if(this.eventSource)for(let e in this.subscriptions)for(let t of this.subscriptions[e])this.eventSource.removeEventListener(e,t)}connect(){return __awaiter(this,void 0,void 0,(function*(){if(!(this.reconnectAttempts>0))return new Promise(((e,t)=>{this.pendingConnects.push({resolve:e,reject:t}),this.pendingConnects.length>1||this.initConnect()}))}))}initConnect(){this.disconnect(!0),clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout((()=>{this.connectErrorHandler(new Error("EventSource connect took too long."))}),this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildUrl("/api/realtime")),this.eventSource.onerror=e=>{this.connectErrorHandler(new Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e=>{const t=e;this.clientId=null==t?void 0:t.lastEventId,this.submitSubscriptions().then((()=>__awaiter(this,void 0,void 0,(function*(){let e=3;for(;this.hasUnsentSubscriptions()&&e>0;)e--,yield this.submitSubscriptions()})))).then((()=>{for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId)})).catch((e=>{this.clientId="",this.connectErrorHandler(e)}))}))}hasUnsentSubscriptions(){const e=this.getNonEmptySubscriptionTopics();if(e.length!=this.lastSentTopics.length)return!0;for(const t of e)if(!this.lastSentTopics.includes(t))return!0;return!1}connectErrorHandler(e){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let t of this.pendingConnects)t.reject(new ClientResponseError(e));return this.pendingConnects=[],void this.disconnect()}this.disconnect(!0);const t=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++,this.reconnectTimeoutId=setTimeout((()=>{this.initConnect()}),t)}disconnect(e=!1){var t;if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),null===(t=this.eventSource)||void 0===t||t.close(),this.eventSource=null,this.clientId="",!e){this.reconnectAttempts=0;for(let e of this.pendingConnects)e.resolve();this.pendingConnects=[]}}}class RecordService extends CrudService{constructor(e,t){super(e),this.collectionIdOrName=t}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}subscribeOne(e,t){return __awaiter(this,void 0,void 0,(function*(){return console.warn("PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback)."),this.client.realtime.subscribe(this.collectionIdOrName+"/"+e,t)}))}subscribe(e,t){return __awaiter(this,void 0,void 0,(function*(){if("function"==typeof e)return console.warn("PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback)."),this.client.realtime.subscribe(this.collectionIdOrName,e);if(!t)throw new Error("Missing subscription callback.");if(""===e)throw new Error("Missing topic.");let i=this.collectionIdOrName;return"*"!==e&&(i+="/"+e),this.client.realtime.subscribe(i,t)}))}unsubscribe(e){return __awaiter(this,void 0,void 0,(function*(){return"*"===e?this.client.realtime.unsubscribe(this.collectionIdOrName):e?this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+e):this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}))}getFullList(e,t){if("number"==typeof e)return super.getFullList(e,t);const i=Object.assign({},e,t);return super.getFullList(i)}getList(e=1,t=30,i){return super.getList(e,t,i)}getFirstListItem(e,t){return super.getFirstListItem(e,t)}getOne(e,t){return super.getOne(e,t)}create(e,t){return super.create(e,t)}update(e,t,i){return super.update(e,t,i).then((e=>{var t,i,s;return(null===(t=this.client.authStore.model)||void 0===t?void 0:t.id)!==(null==e?void 0:e.id)||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.collectionId)!==this.collectionIdOrName&&(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionName)!==this.collectionIdOrName||this.client.authStore.save(this.client.authStore.token,e),e}))}delete(e,t){return super.delete(e,t).then((t=>{var i,s,n;return!t||(null===(i=this.client.authStore.model)||void 0===i?void 0:i.id)!==e||(null===(s=this.client.authStore.model)||void 0===s?void 0:s.collectionId)!==this.collectionIdOrName&&(null===(n=this.client.authStore.model)||void 0===n?void 0:n.collectionName)!==this.collectionIdOrName||this.client.authStore.clear(),t}))}authResponse(e){const t=this.decode((null==e?void 0:e.record)||{});return this.client.authStore.save(null==e?void 0:e.token,t),Object.assign({},e,{token:(null==e?void 0:e.token)||"",record:t})}listAuthMethods(e){return e=Object.assign({method:"GET"},e),this.client.send(this.baseCollectionPath+"/auth-methods",e).then((e=>Object.assign({},e,{usernamePassword:!!(null==e?void 0:e.usernamePassword),emailPassword:!!(null==e?void 0:e.emailPassword),authProviders:Array.isArray(null==e?void 0:e.authProviders)?null==e?void 0:e.authProviders:[]})))}authWithPassword(e,t,i,s){let n={method:"POST",body:{identity:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/auth-with-password",n).then((e=>this.authResponse(e)))}authWithOAuth2Code(e,t,i,s,n,o,r){let a={method:"POST",body:{provider:e,code:t,codeVerifier:i,redirectUrl:s,createData:n}};return a=normalizeLegacyOptionsArgs("This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).",a,o,r),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",a).then((e=>this.authResponse(e)))}authWithOAuth2(...e){return __awaiter(this,void 0,void 0,(function*(){if(e.length>1||"string"==typeof(null==e?void 0:e[0]))return console.warn("PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration."),this.authWithOAuth2Code((null==e?void 0:e[0])||"",(null==e?void 0:e[1])||"",(null==e?void 0:e[2])||"",(null==e?void 0:e[3])||"",(null==e?void 0:e[4])||{},(null==e?void 0:e[5])||{},(null==e?void 0:e[6])||{});const t=(null==e?void 0:e[0])||{},i=(yield this.listAuthMethods()).authProviders.find((e=>e.name===t.provider));if(!i)throw new ClientResponseError(new Error(`Missing or invalid provider "${t.provider}".`));const s=this.client.buildUrl("/api/oauth2-redirect"),n=new RealtimeService(this.client);let o=null;function cleanup(){null==o||o.close(),n.unsubscribe()}return t.urlCallback||(o=openBrowserPopup(void 0)),new Promise(((e,r)=>__awaiter(this,void 0,void 0,(function*(){var a;try{yield n.subscribe("@oauth2",(o=>__awaiter(this,void 0,void 0,(function*(){const a=n.clientId;try{if(!o.state||a!==o.state)throw new Error("State parameters don't match.");const n=Object.assign({},t);delete n.provider,delete n.scopes,delete n.createData,delete n.urlCallback;const r=yield this.authWithOAuth2Code(i.name,o.code,i.codeVerifier,s,t.createData,n);e(r)}catch(e){r(new ClientResponseError(e))}cleanup()}))));const l={state:n.clientId};(null===(a=t.scopes)||void 0===a?void 0:a.length)&&(l.scope=t.scopes.join(" "));const c=this._replaceQueryParams(i.authUrl+s,l);let d=t.urlCallback||function(e){o?o.location.href=e:o=openBrowserPopup(e)};yield d(c)}catch(e){cleanup(),r(new ClientResponseError(e))}}))))}))}authRefresh(e,t){let i={method:"POST"};return i=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",i,e,t),this.client.send(this.baseCollectionPath+"/auth-refresh",i).then((e=>this.authResponse(e)))}requestPasswordReset(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-password-reset",s).then((()=>!0))}confirmPasswordReset(e,t,i,s,n){let o={method:"POST",body:{token:e,password:t,passwordConfirm:i}};return o=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",o,s,n),this.client.send(this.baseCollectionPath+"/confirm-password-reset",o).then((()=>!0))}requestVerification(e,t,i){let s={method:"POST",body:{email:e}};return s=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-verification",s).then((()=>!0))}confirmVerification(e,t,i){let s={method:"POST",body:{token:e}};return s=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/confirm-verification",s).then((()=>!0))}requestEmailChange(e,t,i){let s={method:"POST",body:{newEmail:e}};return s=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",s,t,i),this.client.send(this.baseCollectionPath+"/request-email-change",s).then((()=>!0))}confirmEmailChange(e,t,i,s){let n={method:"POST",body:{token:e,password:t}};return n=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",n,i,s),this.client.send(this.baseCollectionPath+"/confirm-email-change",n).then((()=>!0))}listExternalAuths(e,t){return t=Object.assign({method:"GET"},t),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths",t)}unlinkExternalAuth(e,t,i){return i=Object.assign({method:"DELETE"},i),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(e)+"/external-auths/"+encodeURIComponent(t),i).then((()=>!0))}_replaceQueryParams(e,t={}){let i=e,s="";e.indexOf("?")>=0&&(i=e.substring(0,e.indexOf("?")),s=e.substring(e.indexOf("?")+1));const n={},o=s.split("&");for(const e of o){if(""==e)continue;const t=e.split("=");n[decodeURIComponent(t[0].replace(/\+/g," "))]=decodeURIComponent((t[1]||"").replace(/\+/g," "))}for(let e in t)t.hasOwnProperty(e)&&(null==t[e]?delete n[e]:n[e]=t[e]);s="";for(let e in n)n.hasOwnProperty(e)&&(""!=s&&(s+="&"),s+=encodeURIComponent(e.replace(/%20/g,"+"))+"="+encodeURIComponent(n[e].replace(/%20/g,"+")));return""!=s?i+"?"+s:i}}function openBrowserPopup(e){if("undefined"==typeof window||!(null===window||void 0===window?void 0:window.open))throw new ClientResponseError(new Error("Not in a browser context - please pass a custom urlCallback function."));let t=1024,i=768,s=window.innerWidth,n=window.innerHeight;t=t>s?s:t,i=i>n?n:i;let o=s/2-t/2,r=n/2-i/2;return window.open(e,"popup_window","width="+t+",height="+i+",top="+r+",left="+o+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}import(e,t=!1,i){return __awaiter(this,void 0,void 0,(function*(){return i=Object.assign({method:"PUT",body:{collections:e,deleteMissing:t}},i),this.client.send(this.baseCrudPath+"/import",i).then((()=>!0))}))}}class LogService extends BaseService{getRequestsList(e=1,t=30,i){return(i=Object.assign({method:"GET"},i)).query=Object.assign({page:e,perPage:t},i.query),this.client.send("/api/logs/requests",i)}getRequest(e,t){return t=Object.assign({method:"GET"},t),this.client.send("/api/logs/requests/"+encodeURIComponent(e),t)}getRequestsStats(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/logs/requests/stats",e)}}class HealthService extends BaseService{check(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/health",e)}}class FileService extends BaseService{getUrl(e,t,i={}){if(!t||!(null==e?void 0:e.id))return"";const s=[];s.push("api"),s.push("files"),s.push(encodeURIComponent(e.collectionId||e.collectionName)),s.push(encodeURIComponent(e.id)),s.push(encodeURIComponent(t));let n=this.client.buildUrl(s.join("/"));if(Object.keys(i).length){!1===i.download&&delete i.download;const e=new URLSearchParams(i);n+=(n.includes("?")?"&":"?")+e}return n}getToken(e){return e=Object.assign({method:"POST"},e),this.client.send("/api/files/token",e).then((e=>(null==e?void 0:e.token)||""))}}class BackupService extends BaseService{getFullList(e){return e=Object.assign({method:"GET"},e),this.client.send("/api/backups",e)}create(e,t){return t=Object.assign({method:"POST",body:{name:e}},t),this.client.send("/api/backups",t).then((()=>!0))}delete(e,t){return t=Object.assign({method:"DELETE"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}`,t).then((()=>!0))}restore(e,t){return t=Object.assign({method:"POST"},t),this.client.send(`/api/backups/${encodeURIComponent(e)}/restore`,t).then((()=>!0))}getDownloadUrl(e,t){return this.client.buildUrl(`/api/backups/${encodeURIComponent(t)}?token=${encodeURIComponent(e)}`)}}const s=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];return class Client{constructor(e="/",t,i="en-US"){this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseUrl=e,this.lang=i,this.authStore=t||new LocalAuthStore,this.admins=new AdminService(this),this.collections=new CollectionService(this),this.files=new FileService(this),this.logs=new LogService(this),this.settings=new SettingsService(this),this.realtime=new RealtimeService(this),this.health=new HealthService(this),this.backups=new BackupService(this)}collection(e){return this.recordServices[e]||(this.recordServices[e]=new RecordService(this,e)),this.recordServices[e]}autoCancellation(e){return this.enableAutoCancellation=!!e,this}cancelRequest(e){return this.cancelControllers[e]&&(this.cancelControllers[e].abort(),delete this.cancelControllers[e]),this}cancelAllRequests(){for(let e in this.cancelControllers)this.cancelControllers[e].abort();return this.cancelControllers={},this}getFileUrl(e,t,i={}){return this.files.getUrl(e,t,i)}buildUrl(e){var t;let i=this.baseUrl;return"undefined"==typeof window||!window.location||i.startsWith("https://")||i.startsWith("http://")||(i=(null===(t=window.location.origin)||void 0===t?void 0:t.endsWith("/"))?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",this.baseUrl.startsWith("/")||(i+=window.location.pathname||"/",i+=i.endsWith("/")?"":"/"),i+=this.baseUrl),e&&(i+=i.endsWith("/")?"":"/",i+=e.startsWith("/")?e.substring(1):e),i}send(e,t){return __awaiter(this,void 0,void 0,(function*(){t=this.initSendOptions(e,t);let i=this.buildUrl(e);if(void 0!==t.query){const e=this.serializeQueryParams(t.query);e&&(i+=(i.includes("?")?"&":"?")+e),delete t.query}if(this.beforeSend){const e=Object.assign({},yield this.beforeSend(i,t));void 0!==e.url||void 0!==e.options?(i=e.url||i,t=e.options||t):Object.keys(e).length&&(t=e,(null===console||void 0===console?void 0:console.warn)&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`."))}"application/json"==this.getHeader(t.headers,"Content-Type")&&t.body&&"string"!=typeof t.body&&(t.body=JSON.stringify(t.body));return(t.fetch||fetch)(i,t).then((e=>__awaiter(this,void 0,void 0,(function*(){let t={};try{t=yield e.json()}catch(e){}if(this.afterSend&&(t=yield this.afterSend(e,t)),e.status>=400)throw new ClientResponseError({url:e.url,status:e.status,data:t});return t})))).catch((e=>{throw new ClientResponseError(e)}))}))}initSendOptions(e,t){(t=Object.assign({method:"GET"},t)).query=t.query||{},t.body=this.convertToFormDataIfNeeded(t.body);for(let e in t)s.includes(e)||(t.query[e]=t[e],delete t[e]);if(t.query=Object.assign({},t.params,t.query),void 0===t.requestKey&&(!1===t.$autoCancel||!1===t.query.$autoCancel?t.requestKey=null:(t.$cancelKey||t.query.$cancelKey)&&(t.requestKey=t.$cancelKey||t.query.$cancelKey)),delete t.$autoCancel,delete t.query.$autoCancel,delete t.$cancelKey,delete t.query.$cancelKey,null!==this.getHeader(t.headers,"Content-Type")||this.isFormData(t.body)||(t.headers=Object.assign({},t.headers,{"Content-Type":"application/json"})),null===this.getHeader(t.headers,"Accept-Language")&&(t.headers=Object.assign({},t.headers,{"Accept-Language":this.lang})),this.authStore.token&&null===this.getHeader(t.headers,"Authorization")&&(t.headers=Object.assign({},t.headers,{Authorization:this.authStore.token})),this.enableAutoCancellation&&null!==t.requestKey){const i=t.requestKey||(t.method||"GET")+e;delete t.requestKey,this.cancelRequest(i);const s=new AbortController;this.cancelControllers[i]=s,t.signal=s.signal}return t}convertToFormDataIfNeeded(e){if("undefined"==typeof FormData||void 0===e||"object"!=typeof e||null===e||this.isFormData(e)||!this.hasBlobField(e))return e;const t=new FormData;for(let i in e)t.append(i,e[i]);return t}hasBlobField(e){for(let t in e){const i=Array.isArray(e[t])?e[t]:[e[t]];for(let e of i)if("undefined"!=typeof Blob&&e instanceof Blob||"undefined"!=typeof File&&e instanceof File)return!0}return!1}getHeader(e,t){e=e||{},t=t.toLowerCase();for(let i in e)if(i.toLowerCase()==t)return e[i];return null}isFormData(e){return e&&("FormData"===e.constructor.name||"undefined"!=typeof FormData&&e instanceof FormData)}serializeQueryParams(e){const t=[];for(const i in e){if(null===e[i])continue;const s=e[i],n=encodeURIComponent(i);if(Array.isArray(s))for(const e of s)t.push(n+"="+encodeURIComponent(e));else s instanceof Date?t.push(n+"="+encodeURIComponent(s.toISOString())):null!==typeof s&&"object"==typeof s?t.push(n+"="+encodeURIComponent(JSON.stringify(s))):t.push(n+"="+encodeURIComponent(s))}return t.join("&")}}})); //# sourceMappingURL=pocketbase.umd.js.map diff --git a/dist/pocketbase.umd.js.map b/dist/pocketbase.umd.js.map index 8be8e34..8075d4b 100644 --- a/dist/pocketbase.umd.js.map +++ b/dist/pocketbase.umd.js.map @@ -1 +1 @@ -{"version":3,"file":"pocketbase.umd.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is depreacted. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is depreacted. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is depreacted. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is depreacted. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is depreacted. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is depreacted. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is depreacted. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is depreacted. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is depreacted. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"pocketbase.umd.js","sources":["../src/ClientResponseError.ts","../src/stores/utils/cookie.ts","../src/stores/utils/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/SettingsService.ts","../src/services/utils/CrudService.ts","../src/services/utils/legacy.ts","../src/services/AdminService.ts","../src/services/RealtimeService.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n response: {[key: string]: any} = {};\n isAbort: boolean = false;\n originalError: any = null;\n\n constructor(errData?: any) {\n super(\"ClientResponseError\");\n\n // Set the prototype explicitly.\n // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n if (errData !== null && typeof errData === 'object') {\n this.url = typeof errData.url === 'string' ? errData.url : '';\n this.status = typeof errData.status === 'number' ? errData.status : 0;\n this.isAbort = !!errData.isAbort;\n this.originalError = errData.originalError;\n\n if (errData.response !== null && typeof errData.response === 'object') {\n this.response = errData.response;\n } else if (errData.data !== null && typeof errData.data === 'object') {\n this.response = errData.data;\n } else {\n this.response = {};\n }\n }\n\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n\n if (typeof DOMException !== 'undefined' && errData instanceof DOMException) {\n this.isAbort = true;\n }\n\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message = 'The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.';\n } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message = 'Failed to connect to the PocketBase server. Try changing the SDK URL from localhost to 127.0.0.1 (https://github.com/pocketbase/js-sdk/issues/21).';\n } else {\n this.message = 'Something went wrong while processing your request.';\n }\n }\n }\n\n /**\n * Alias for `this.response` to preserve the backward compatibility.\n */\n get data() {\n return this.response;\n }\n\n /**\n * Make a POJO's copy of the current error class instance.\n * @see https://github.com/vuex-orm/vuex-orm/issues/255\n */\n toJSON() {\n return { ...this };\n }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions {\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input: any) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n let str = String(input).replace(/=+$/, \"\");\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n\n for (\n // initialize result and counters\n var bc = 0, bs, buffer, idx = 0, output = \"\";\n // get next character\n (buffer = str.charAt(idx++));\n // character found in table? initialize bit storage and add its ascii value;\n ~buffer &&\n ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n // and if not first of each 4 characters,\n // convert the first 8 bits to one ascii character\n bc++ % 4) ?\n (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)))) :\n 0\n ) {\n // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(encodedPayload) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n let payload = getTokenPayload(token);\n\n if (\n Object.keys(payload).length > 0 &&\n (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))\n ) {\n return false;\n }\n\n return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport { RecordModel, AdminModel } from '@/services/utils/dtos';\n\nexport type AuthModel = RecordModel|AdminModel|null;\n\nexport type OnStoreChangeFunc = (token: string, model: AuthModel) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intended to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: AuthModel = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): AuthModel {\n return this.baseModel;\n }\n\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Checks whether the current store state is for admin authentication.\n */\n get isAdmin(): boolean {\n return getTokenPayload(this.token).type === \"admin\";\n }\n\n /**\n * Checks whether the current store state is for auth record authentication.\n */\n get isAuthRecord(): boolean {\n return getTokenPayload(this.token).type === \"authRecord\";\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model?: AuthModel): void {\n this.baseToken = token || '';\n this.baseModel = model || null;\n\n this.triggerChange();\n }\n\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear(): void {\n this.baseToken = '';\n this.baseModel = null;\n this.triggerChange();\n }\n\n /**\n * Parses the provided cookie string and updates the store state\n * with the cookie's token and model data.\n *\n * NB! This function doesn't validate the token or its data.\n * Usually this isn't a concern if you are interacting only with the\n * PocketBase API because it has the proper server-side security checks in place,\n * but if you are using the store `isValid` state for permission controls\n * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n * after loading the cookie to ensure an up-to-date token and model state.\n * For example:\n *\n * ```js\n * pb.authStore.loadFromCookie(\"cookie string...\");\n *\n * try {\n * // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n * pb.authStore.isValid && await pb.collection('users').authRefresh();\n * } catch (_) {\n * // clear the auth store on failed refresh\n * pb.authStore.clear();\n * }\n * ```\n */\n loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || null);\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model ? JSON.parse(JSON.stringify(this.model)) : null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n const resultLength = typeof Blob !== 'undefined' ?\n (new Blob([result])).size : result.length;\n\n // strip down the model data to the bare minimum\n if (rawData.model && resultLength > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n const extraProps = [\"collectionId\", \"username\", \"verified\"];\n for (const prop in this.model) {\n if (extraProps.includes(prop)) {\n rawData.model[prop] = this.model[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n\n return result;\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * You can set the `fireImmediately` argument to true in order to invoke\n * the provided callback right after registration.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n this._onChangeCallbacks.push(callback);\n\n if (fireImmediately) {\n callback(this.token, this.model);\n }\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import { BaseAuthStore, AuthModel } from '@/stores/BaseAuthStore';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageFallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n\n this._bindStorageEvent();\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): AuthModel {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.model || null;\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model?: AuthModel) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window.localStorage.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined' && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n\n /**\n * Updates the current store state on localStorage change.\n */\n private _bindStorageEvent() {\n if (typeof window === 'undefined' || !window?.localStorage || !window.addEventListener) {\n return;\n }\n\n window.addEventListener('storage', (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n\n const data = this._storageGet(this.storageKey) || {};\n\n super.save(data.token || '', data.model || null);\n });\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\ninterface appleClientSecret {\n secret: string;\n}\n\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(options?: CommonOptions): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Bulk updates app settings.\n */\n update(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise<{[key: string]:any}> {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send('/api/settings', options);\n }\n\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n */\n testS3(filesystem: string = \"storage\", options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'filesystem': filesystem,\n },\n }, options);\n\n return this.client.send('/api/settings/test/s3', options)\n .then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'email': toEmail,\n 'template': emailTemplate,\n },\n }, options);\n\n return this.client.send('/api/settings/test/email', options)\n .then(() => true);\n }\n\n /**\n * Generates a new Apple OAuth2 client secret.\n */\n generateAppleClientSecret(\n clientId: string,\n teamId: string,\n keyId: string,\n privateKey: string,\n duration: number,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n\n return this.client.send('/api/settings/apple/generate-client-secret', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n FullListOptions\n} from '@/services/utils/options';\n\nexport abstract class CrudService extends BaseService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract get baseCrudPath(): string\n\n /**\n * Response data decoder.\n */\n decode(data: { [key: string]: any }): T {\n return data as T;\n }\n\n /**\n * Returns a promise with all list items batch fetched at once\n * (by default 500 items per request; to change it set the `batch` query param).\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getFullList(options?: FullListOptions): Promise>\n\n /**\n * Legacy version of getFullList with explicitly specified batch size.\n */\n getFullList(batch?: number, options?: ListOptions): Promise>\n\n getFullList(batchOrqueryParams?: number|FullListOptions, options?: ListOptions): Promise> {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n\n options = Object.assign({}, batchOrqueryParams, options);\n\n let batch = 500;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n\n return this._getFullList(batch, options);\n }\n\n /**\n * Returns paginated items list.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({\n method: 'GET'\n }, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => {\n responseData.items = responseData.items?.map((item: any) => {\n return this.decode(item);\n }) || [];\n\n return responseData;\n });\n }\n\n /**\n * Returns the first found item by the specified filter.\n *\n * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n * returns the first found item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n *\n * For consistency with `getOne`, this method will throw a 404\n * ClientResponseError if no item was found.\n */\n getFirstListItem(filter: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'requestKey': 'one_by_filter_' + this.baseCrudPath + \"_\" + filter,\n }, options);\n\n options.query = Object.assign({\n 'filter': filter,\n 'skipTotal': 1,\n }, options.query);\n\n return this.getList(1, 1, options)\n .then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n data: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n\n return result.items[0];\n });\n }\n\n /**\n * Returns single item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n getOne(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n create(\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath, options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n *\n * You can use the generic T to supply a wrapper type of the crud model.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PATCH',\n 'body': bodyParams,\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(id), options)\n .then(() => true);\n }\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(batchSize = 500, options?: ListOptions): Promise> {\n options = options || {};\n options.query = Object.assign({\n 'skipTotal': 1,\n }, options.query);\n\n let result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this.getList(page, batchSize || 500, options).then((list) => {\n const castedList = (list as any as ListResult);\n const items = castedList.items;\n\n result = result.concat(items);\n\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n}\n","import { SendOptions } from '@/services/utils/options';\n\nexport function normalizeLegacyOptionsArgs(legacyWarn: string, baseOptions: SendOptions, bodyOrOptions?: any, query?: any): SendOptions {\n const hasBodyOrOptions = typeof bodyOrOptions !== 'undefined';\n const hasQuery = typeof query !== 'undefined';\n\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\n }\n\n if (hasQuery) {\n console.warn(legacyWarn);\n baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n return baseOptions;\n }\n\n baseOptions = Object.assign(baseOptions, bodyOrOptions);\n return baseOptions;\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { AdminModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface AdminAuthResponse {\n [key: string]: any;\n\n token: string;\n admin: AdminModel;\n}\n\nexport class AdminService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/admins';\n }\n\n // ---------------------------------------------------------------\n // Post update/delete AuthStore sync\n // ---------------------------------------------------------------\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(\n id: string,\n bodyParams?: {[key:string]:any}|FormData,\n options?: CommonOptions,\n ): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n // update the store state if the updated item id matches with the stored model\n if (\n this.client.authStore.model?.id === item.id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n // clear the store state if the deleted item id matches with the stored model\n if (\n success &&\n this.client.authStore.model?.id === id &&\n typeof this.client.authStore.model?.collectionId === 'undefined' // is not record auth\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account with its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authWithPassword(email: string, password: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authWithPassword(email, password, options?).\n */\n authWithPassword(email: string, password: string, body?: any, query?: any): Promise\n\n authWithPassword(\n email: string,\n password: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': email,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(email, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(email, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-with-password', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authRefresh(options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/auth-refresh', options)\n .then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/request-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(resetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, body?: any, query?: any): Promise\n\n confirmPasswordReset(resetToken: string, password: string, passwordConfirm: string, bodyOrOptions?: any, query?: any): Promise{\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': resetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(resetToken, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(resetToken, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCrudPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ClientResponseError } from '@/ClientResponseError';\n\ninterface promiseCallbacks {\n resolve: Function\n reject: Function\n}\n\nexport type UnsubscribeFunc = () => Promise;\n\nexport class RealtimeService extends BaseService {\n clientId: string = \"\";\n\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: Array } = {};\n private lastSentTopics: Array = [];\n private connectTimeoutId: any;\n private maxConnectTimeout: number = 15000;\n private reconnectTimeoutId: any;\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = Infinity;\n private predefinedReconnectIntervals: Array = [\n 200, 300, 500, 1000, 1200, 1500, 2000,\n ];\n private pendingConnects: Array = [];\n\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected(): boolean {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n }\n\n /**\n * Register the subscription listener.\n *\n * You can subscribe multiple times to the same topic.\n *\n * If the SSE connection is not started yet,\n * this method will also initialize it.\n */\n async subscribe(topic: string, callback: (data: any) => void): Promise {\n if (!topic) {\n throw new Error('topic must be set.')\n }\n\n const listener = function (e: Event) {\n const msgEvent = (e as MessageEvent);\n\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n } catch {}\n\n callback(data || {});\n };\n\n // store the listener\n if (!this.subscriptions[topic]) {\n this.subscriptions[topic] = [];\n }\n this.subscriptions[topic].push(listener);\n\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n } else if (this.subscriptions[topic].length === 1) {\n // send the updated subscriptions (if it is the first for the topic)\n await this.submitSubscriptions();\n } else {\n // only register the listener\n this.eventSource?.addEventListener(topic, listener);\n }\n\n return async (): Promise => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n\n /**\n * Unsubscribe from all subscription listeners with the specified topic.\n *\n * If `topic` is not provided, then this method will unsubscribe\n * from all active subscriptions.\n *\n * This method is no-op if there are no active subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribe(topic?: string): Promise {\n if (!this.hasSubscriptionListeners(topic)) {\n return; // already unsubscribed\n }\n\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n } else {\n // remove all topic listeners\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n *\n * This method is no-op if there are no active subscriptions with the specified topic prefix.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByPrefix(topicPrefix: string): Promise {\n let hasAtleastOneTopic = false;\n for (let topic in this.subscriptions) {\n if (!topic.startsWith(topicPrefix)) {\n continue;\n }\n\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[topic]) {\n this.eventSource?.removeEventListener(topic, listener);\n }\n delete this.subscriptions[topic];\n }\n\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n\n if (this.hasSubscriptionListeners()) {\n // submit the deleted subscriptions\n await this.submitSubscriptions();\n } else {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n }\n }\n\n /**\n * Unsubscribe from all subscriptions matching the specified topic and listener function.\n *\n * This method is no-op if there are no active subscription with\n * the specified topic and listener.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operation there are no active subscriptions left.\n */\n async unsubscribeByTopicAndListener(topic: string, listener: EventListener): Promise {\n if (!Array.isArray(this.subscriptions[topic]) || !this.subscriptions[topic].length) {\n return; // already unsubscribed\n }\n\n let exist = false;\n for (let i = this.subscriptions[topic].length - 1; i >= 0; i--) {\n if (this.subscriptions[topic][i] !== listener) {\n continue;\n }\n\n exist = true; // has at least one matching listener\n delete this.subscriptions[topic][i]; // removes the function reference\n this.subscriptions[topic].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(topic, listener);\n }\n if (!exist) {\n return;\n }\n\n // remove the topic from the subscriptions list if there are no other listeners\n if (!this.subscriptions[topic].length) {\n delete this.subscriptions[topic];\n }\n\n if (!this.hasSubscriptionListeners()) {\n // no other active subscriptions -> close the sse connection\n this.disconnect();\n } else if (!this.hasSubscriptionListeners(topic)) {\n // submit subscriptions change if there are no other active subscriptions related to the topic\n await this.submitSubscriptions();\n }\n }\n\n private hasSubscriptionListeners(topicToCheck?: string): boolean {\n this.subscriptions = this.subscriptions || {};\n\n // check the specified topic\n if (topicToCheck) {\n return !!this.subscriptions[topicToCheck]?.length;\n }\n\n // check for at least one non-empty topic\n for (let topic in this.subscriptions) {\n if (!!this.subscriptions[topic]?.length) {\n return true\n }\n }\n\n return false;\n }\n\n private async submitSubscriptions(): Promise {\n if (!this.clientId) {\n return; // no client/subscriber\n }\n\n // optimistic update\n this.addAllSubscriptionListeners();\n\n this.lastSentTopics = this.getNonEmptySubscriptionTopics();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': this.lastSentTopics,\n },\n 'query': {\n 'requestKey': this.getSubscriptionsCancelKey(),\n },\n }).catch((err) => {\n if (err?.isAbort) {\n return; // silently ignore aborted pending requests\n }\n throw err;\n });\n }\n\n private getSubscriptionsCancelKey(): string {\n return \"realtime_\" + this.clientId;\n }\n\n private getNonEmptySubscriptionTopics(): Array {\n const result : Array = [];\n\n for (let topic in this.subscriptions) {\n if (this.subscriptions[topic].length) {\n result.push(topic);\n }\n }\n\n return result;\n }\n\n private addAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeAllSubscriptionListeners();\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.addEventListener(topic, listener);\n }\n }\n }\n\n private removeAllSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let topic in this.subscriptions) {\n for (let listener of this.subscriptions[topic]) {\n this.eventSource.removeEventListener(topic, listener);\n }\n }\n }\n\n private async connect(): Promise {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n\n if (this.pendingConnects.length > 1) {\n // all promises will be resolved once the connection is established\n return;\n }\n\n this.initConnect();\n })\n }\n\n private initConnect() {\n this.disconnect(true);\n\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }, this.maxConnectTimeout);\n\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n\n this.eventSource.onerror = (_) => {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n };\n\n this.eventSource.addEventListener('PB_CONNECT', (e) => {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n\n this.submitSubscriptions()\n .then(async () => {\n let retries = 3;\n while (this.hasUnsentSubscriptions() && retries > 0) {\n retries--;\n // resubscribe to ensure that the latest topics are submitted\n //\n // This is needed because missed topics could happen on reconnect\n // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n // was made before the submit was able to complete.\n await this.submitSubscriptions();\n }\n }).then(() => {\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n }).catch((err) => {\n this.clientId = \"\";\n this.connectErrorHandler(err);\n });\n });\n }\n\n private hasUnsentSubscriptions(): boolean {\n const latestTopics = this.getNonEmptySubscriptionTopics();\n if (latestTopics.length != this.lastSentTopics.length) {\n return true;\n }\n\n for (const t of latestTopics) {\n if (!this.lastSentTopics.includes(t)) {\n return true;\n }\n }\n\n return false;\n }\n\n private connectErrorHandler(err: any) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n\n if (\n // wasn't previously connected -> direct reject\n (!this.clientId && !this.reconnectAttempts) ||\n // was previously connected but the max reconnection limit has been reached\n this.reconnectAttempts > this.maxReconnectAttempts\n ) {\n for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n\n // otherwise -> reconnect in the background\n this.disconnect(true);\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] || this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n this.reconnectTimeoutId = setTimeout(() => {\n this.initConnect();\n }, timeout);\n }\n\n private disconnect(fromReconnect = false): void {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\n this.removeAllSubscriptionListeners();\n this.client.cancelRequest(this.getSubscriptionsCancelKey());\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\n\n // resolve any remaining connect promises\n //\n // this is done to avoid unnecessary throwing errors in case\n // unsubscribe is called before the pending connect promises complete\n // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n this.pendingConnects = [];\n }\n }\n}\n","import Client from '@/Client';\nimport { CrudService } from '@/services/utils/CrudService';\nimport { RealtimeService, UnsubscribeFunc } from '@/services/RealtimeService';\nimport { ClientResponseError } from '@/ClientResponseError';\nimport { ListResult, RecordModel, ExternalAuthModel } from '@/services/utils/dtos';\nimport {\n SendOptions,\n CommonOptions,\n RecordOptions,\n RecordListOptions,\n RecordFullListOptions,\n} from '@/services/utils/options';\nimport { normalizeLegacyOptionsArgs } from '@/services/utils/legacy';\n\nexport interface RecordAuthResponse {\n // The signed PocketBase auth record.\n record: T;\n\n // The PocketBase record auth token.\n //\n // If you are looking for the OAuth2 access and refresh tokens\n // they are available under the `meta.accessToken` and `meta.refreshToken` props.\n token: string;\n\n // Auth meta data usually filled when OAuth2 is used.\n meta?: {[key: string]: any};\n}\n\nexport interface AuthProviderInfo {\n name: string;\n state: string;\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: string;\n authUrl: string;\n}\n\nexport interface AuthMethodsList {\n usernamePassword: boolean;\n emailPassword: boolean;\n authProviders: Array;\n}\n\nexport interface RecordSubscription {\n action: string; // eg. create, update, delete\n record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void|Promise;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n // the name of the OAuth2 provider (eg. \"google\")\n provider: string;\n\n // custom scopes to overwrite the default ones\n scopes?: Array;\n\n // optional record create data\n createData?: {[key: string]: any};\n\n // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n urlCallback?: OAuth2UrlCallback;\n\n // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n query?: RecordOptions;\n}\n\nexport class RecordService extends CrudService {\n readonly collectionIdOrName: string;\n\n constructor(client: Client, collectionIdOrName: string) {\n super(client);\n\n this.collectionIdOrName = collectionIdOrName;\n }\n\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return this.baseCollectionPath + '/records';\n }\n\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath(): string {\n return '/api/collections/' + encodeURIComponent(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Realtime handlers\n // ---------------------------------------------------------------\n\n /**\n * @deprecated Use subscribe(recordId, callback) instead.\n *\n * Subscribe to the realtime changes of a single record in the collection.\n */\n async subscribeOne(recordId: string, callback: (data: RecordSubscription) => void): Promise {\n console.warn(\"PocketBase: subscribeOne(recordId, callback) is deprecated. Please replace it with subscribe(recordId, callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + recordId, callback);\n }\n\n /**\n * @deprecated This form of subscribe is deprecated. Please use `subscribe(\"*\", callback)`.\n */\n async subscribe(callback: (data: RecordSubscription) => void): Promise\n\n /**\n * Subscribe to realtime changes to the specified topic (\"*\" or record id).\n *\n * If `topic` is the wildcard \"*\", then this method will subscribe to\n * any record changes in the collection.\n *\n * If `topic` is a record id, then this method will subscribe only\n * to changes of the specified record id.\n *\n * It's OK to subscribe multiple times to the same topic.\n * You can use the returned `UnsubscribeFunc` to remove only a single subscription.\n * Or use `unsubscribe(topic)` if you want to remove all subscriptions attached to the topic.\n */\n async subscribe(topic: string, callback: (data: RecordSubscription) => void): Promise\n\n async subscribe(\n topicOrCallback: string|((data: RecordSubscription) => void),\n callback?: (data: RecordSubscription) => void\n ): Promise {\n if (typeof topicOrCallback === 'function') {\n console.warn(\"PocketBase: subscribe(callback) is deprecated. Please replace it with subscribe('*', callback).\");\n return this.client.realtime.subscribe(this.collectionIdOrName, topicOrCallback);\n }\n\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n\n if (topicOrCallback === \"\") {\n throw new Error(\"Missing topic.\");\n }\n\n let topic = this.collectionIdOrName;\n if (topicOrCallback !== \"*\") {\n topic += ('/' + topicOrCallback);\n }\n\n return this.client.realtime.subscribe(topic, callback)\n }\n\n /**\n * Unsubscribe from all subscriptions of the specified topic\n * (\"*\" or record id).\n *\n * If `topic` is not set, then this method will unsubscribe from\n * all subscriptions associated to the current collection.\n */\n async unsubscribe(topic?: string): Promise {\n // unsubscribe wildcard topic\n if (topic === \"*\") {\n return this.client.realtime.unsubscribe(this.collectionIdOrName);\n }\n\n // unsubscribe recordId topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n\n // ---------------------------------------------------------------\n // Crud handers\n // ---------------------------------------------------------------\n /**\n * @inheritdoc\n */\n getFullList(options?: RecordFullListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batch?: number, options?: RecordListOptions): Promise>\n\n /**\n * @inheritdoc\n */\n getFullList(batchOrOptions?: number|RecordFullListOptions, options?: RecordListOptions): Promise> {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n\n const params = Object.assign({}, batchOrOptions, options);\n\n return super.getFullList(params);\n }\n\n /**\n * @inheritdoc\n */\n getList(page = 1, perPage = 30, options?: RecordListOptions): Promise> {\n return super.getList(page, perPage, options);\n }\n\n /**\n * @inheritdoc\n */\n getFirstListItem(filter: string, options?: RecordListOptions): Promise {\n return super.getFirstListItem(filter, options);\n }\n\n /**\n * @inheritdoc\n */\n getOne(id: string, options?: RecordOptions): Promise {\n return super.getOne(id, options);\n }\n\n /**\n * @inheritdoc\n */\n create(bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.create(bodyParams, options);\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the updated id, then\n * on success the `client.authStore.model` will be updated with the result.\n */\n update(id: string, bodyParams?: {[key:string]:any}|FormData, options?: RecordOptions): Promise {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.model?.id === item?.id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.save(this.client.authStore.token, item);\n }\n\n return item as any as T;\n });\n }\n\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.model` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n delete(id: string, options?: CommonOptions): Promise {\n return super.delete(id, options).then((success) => {\n if (\n success &&\n // is record auth\n this.client.authStore.model?.id === id &&\n (\n this.client.authStore.model?.collectionId === this.collectionIdOrName ||\n this.client.authStore.model?.collectionName === this.collectionIdOrName\n )\n ) {\n this.client.authStore.clear();\n }\n\n return success;\n });\n }\n\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n\n /**\n * Prepare successful collection authorization response.\n */\n protected authResponse(responseData: any): RecordAuthResponse {\n const record = this.decode(responseData?.record || {});\n\n this.client.authStore.save(responseData?.token, record);\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'record': record as any as T,\n });\n }\n\n /**\n * Returns all available collection auth methods.\n */\n listAuthMethods(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCollectionPath + '/auth-methods', options)\n .then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'usernamePassword': !!responseData?.usernamePassword,\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a single auth collection record via its username/email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n */\n authWithPassword(usernameOrEmail: string, password: string, options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authWithPassword(usernameOrEmail, password, options?).\n */\n authWithPassword(usernameOrEmail: string, password: string, body?: any, query?: any): Promise>\n\n authWithPassword(usernameOrEmail: string, password: string, bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'identity': usernameOrEmail,\n 'password': password,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithPassword(usernameOrEmail, pass, body?, query?) is deprecated. Consider replacing it with authWithPassword(usernameOrEmail, pass, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-password', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Authenticate a single auth collection record with OAuth2 code.\n *\n * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n options?: RecordOptions,\n ): Promise>\n\n /**\n * @deprecated\n * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createdData, options?).\n */\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n body?: any,\n query?: any\n ): Promise>\n\n authWithOAuth2Code(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key:string]:any},\n bodyOrOptions?: any,\n query?: any\n ): Promise> {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n 'createData': createData,\n },\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectUrl, createData?, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-with-oauth2', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * @deprecated This form of authWithOAuth2 is deprecated.\n *\n * Please use `authWithOAuth2Code()` OR its simplified realtime version\n * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n */\n async authWithOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n createData?: {[key: string]: any},\n bodyParams?: {[key: string]: any},\n queryParams?: RecordOptions,\n ): Promise>\n\n /**\n * Authenticate a single auth collection record with OAuth2\n * **without custom redirects, deeplinks or even page reload**.\n *\n * This method initializes a one-off realtime subscription and will\n * open a popup window with the OAuth2 vendor page to authenticate.\n * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n * window will be automatically closed and the OAuth2 data sent back\n * to the user through the previously established realtime connection.\n *\n * You can specify an optional `urlCallback` prop to customize\n * the default url `window.open` behavior.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - the authentication token\n * - the authenticated record model\n * - the OAuth2 account data (eg. name, email, avatar, etc.)\n *\n * Example:\n *\n * ```js\n * const authData = await pb.collection(\"users\").authWithOAuth2({\n * provider: \"google\",\n * })\n * ```\n *\n * _Site-note_: when creating the OAuth2 app in the provider dashboard\n * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n * as redirect URL.\n */\n async authWithOAuth2(options: OAuth2AuthConfig): Promise>\n\n async authWithOAuth2(...args: any): Promise> {\n // fallback to legacy format\n if (args.length > 1 || typeof args?.[0] === 'string') {\n console.warn(\"PocketBase: This form of authWithOAuth2() is deprecated and may get removed in the future. Please replace with authWithOAuth2Code() OR use the authWithOAuth2() realtime form as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\");\n return this.authWithOAuth2Code(\n args?.[0] || '',\n args?.[1] || '',\n args?.[2] || '',\n args?.[3] || '',\n args?.[4] || {},\n args?.[5] || {},\n args?.[6] || {},\n );\n }\n\n const config = args?.[0] || {};\n\n const authMethods = await this.listAuthMethods();\n\n const provider = authMethods.authProviders.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n\n const redirectUrl = this.client.buildUrl('/api/oauth2-redirect');\n\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before the async call due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup: Window|null = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n\n return new Promise(async (resolve, reject) => {\n try {\n await realtime.subscribe('@oauth2', async (e) => {\n const oldState = realtime.clientId;\n\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n\n // clear the non SendOptions props\n const options = Object.assign({}, config);\n delete options.provider;\n delete options.scopes;\n delete options.createData;\n delete options.urlCallback;\n\n const authData = await this.authWithOAuth2Code(\n provider.name,\n e.code,\n provider.codeVerifier,\n redirectUrl,\n config.createData,\n options,\n );\n\n resolve(authData);\n } catch (err) {\n reject(new ClientResponseError(err));\n }\n\n cleanup();\n });\n\n const replacements: {[key: string]: any} = {\n \"state\": realtime.clientId,\n }\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n\n const url = this._replaceQueryParams(provider.authUrl + redirectUrl, replacements);\n\n let urlCallback = config.urlCallback || function (url: string) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n } else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n }\n\n await urlCallback(url);\n } catch (err) {\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n }\n\n /**\n * Refreshes the current authenticated record instance and\n * returns a new token and record data.\n *\n * On success this method also automatically updates the client's AuthStore.\n */\n authRefresh(options?: RecordOptions): Promise>\n\n /**\n * @deprecated\n * Consider using authRefresh(options?).\n */\n authRefresh(body?: any, query?: any): Promise>\n\n authRefresh(bodyOrOptions?: any, query?: any): Promise> {\n let options: any = {\n 'method': 'POST',\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/auth-refresh', options)\n .then((data) => this.authResponse(data));\n }\n\n /**\n * Sends auth record password reset request.\n */\n requestPasswordReset(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestPasswordReset(email, options?).\n */\n requestPasswordReset(email: string, body?: any, query?: any): Promise\n\n requestPasswordReset(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-password-reset', options).then(() => true);\n }\n\n /**\n * Confirms auth record password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n options?: CommonOptions,\n ): Promise\n\n /**\n * @deprecated\n * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n body?: any,\n query?: any,\n ): Promise\n\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyOrOptions?: any,\n query?: any,\n ): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-password-reset', options)\n .then(() => true);\n }\n\n /**\n * Sends auth record verification email request.\n */\n requestVerification(email: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestVerification(email, options?).\n */\n requestVerification(email: string, body?: any, query?: any): Promise\n\n requestVerification(email: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'email': email,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-verification', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record email verification request.\n */\n confirmVerification(verificationToken: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using confirmVerification(verificationToken, options?).\n */\n confirmVerification(verificationToken: string, body?: any, query?: any): Promise\n\n confirmVerification(verificationToken: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': verificationToken,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-verification', options)\n .then(() => true);\n }\n\n /**\n * Sends an email change request to the authenticated record model.\n */\n requestEmailChange(newEmail: string, options?: CommonOptions): Promise\n\n /**\n * @deprecated\n * Consider using requestEmailChange(newEmail, options?).\n */\n requestEmailChange(newEmail: string, body?: any, query?: any): Promise\n\n requestEmailChange(newEmail: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'newEmail': newEmail,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/request-email-change', options)\n .then(() => true);\n }\n\n /**\n * Confirms auth record's new email address.\n */\n confirmEmailChange(emailChangeToken: string, password: string, options?: CommonOptions): Promise\n\n\n /**\n * @deprecated\n * Consider using confirmEmailChange(emailChangeToken, password, options?).\n */\n confirmEmailChange(emailChangeToken: string, password: string, body?: any, query?: any): Promise\n\n confirmEmailChange(emailChangeToken: string, password: string, bodyOrOptions?: any, query?: any): Promise {\n let options: any = {\n 'method': 'POST',\n 'body': {\n 'token': emailChangeToken,\n 'password': password,\n }\n };\n\n options = normalizeLegacyOptionsArgs(\n 'This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).',\n options,\n bodyOrOptions,\n query\n );\n\n return this.client.send(this.baseCollectionPath + '/confirm-email-change', options)\n .then(() => true);\n }\n\n /**\n * Lists all linked external auth providers for the specified auth record.\n */\n listExternalAuths(recordId: string, options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths', options);\n }\n\n /**\n * Unlink a single external auth provider from the specified auth record.\n */\n unlinkExternalAuth(recordId: string, provider: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(this.baseCrudPath + '/' + encodeURIComponent(recordId) + '/external-auths/' + encodeURIComponent(provider), options)\n .then(() => true);\n }\n\n // ---------------------------------------------------------------\n\n // very rudimentary url query params replacement because at the moment\n // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n //\n // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n private _replaceQueryParams(url: string, replacements: {[key: string]: any} = {}): string {\n let urlPath = url\n let query = \"\";\n\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex >= 0) {\n urlPath = url.substring(0, url.indexOf(\"?\"));\n query = url.substring(url.indexOf(\"?\") + 1);\n }\n\n const parsedParams: {[key: string]: string} = {};\n\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue\n }\n\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g,' '))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g,' '));\n }\n\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n\n if (replacements[key] == null) {\n delete parsedParams[key];\n } else {\n parsedParams[key] = replacements[key];\n }\n }\n\n // construct back the full query string\n query = \"\";\n for (let key in parsedParams) {\n if (!parsedParams.hasOwnProperty(key)) {\n continue;\n }\n\n if (query != \"\") {\n query += \"&\";\n }\n\n query += encodeURIComponent(key.replace(/%20/g,'+')) + \"=\" + encodeURIComponent(parsedParams[key].replace(/%20/g,'+'));\n }\n\n return query != \"\" ? (urlPath + \"?\" + query) : urlPath;\n }\n}\n\nfunction openBrowserPopup(url?: string): Window|null {\n if (typeof window === \"undefined\" || !window?.open) {\n throw new ClientResponseError(new Error(`Not in a browser context - please pass a custom urlCallback function.`));\n }\n\n let width = 1024;\n let height = 768;\n\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n\n let left = (windowWidth / 2) - (width / 2);\n let top = (windowHeight / 2) - (height / 2);\n\n // note: we don't use the noopener and noreferrer attributes since\n // for some reason browser blocks such windows then url is undefined/blank\n return window.open(\n url,\n 'popup_window',\n 'width='+width+',height='+height+',top='+top+',left='+left+',resizable,menubar=no'\n );\n}\n","import { CrudService } from '@/services/utils/CrudService';\nimport { CollectionModel } from '@/services/utils/dtos';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(\n collections: Array,\n deleteMissing: boolean = false,\n options?: CommonOptions,\n ): Promise {\n options = Object.assign({\n 'method': 'PUT',\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }, options);\n\n return this.client.send(this.baseCrudPath + '/import', options)\n .then(() => true);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { ListResult, LogRequestModel } from '@/services/utils/dtos';\nimport {\n CommonOptions,\n ListOptions,\n LogStatsOptions,\n} from '@/services/utils/options';\n\nexport interface HourlyStats {\n total: number;\n date: string;\n}\n\nexport class LogService extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, options?: ListOptions): Promise> {\n options = Object.assign({'method': 'GET'}, options);\n\n options.query = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, options.query);\n\n return this.client.send('/api/logs/requests', options);\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), options);\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(options?: LogStatsOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/logs/requests/stats', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface HealthCheckResponse {\n code: number;\n message: string;\n data: {[key: string]: any};\n}\n\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n */\n check(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/health', options);\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions, FileOptions } from '@/services/utils/options';\n\nexport class FileService extends BaseService {\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n if (!filename || !record?.id) {\n return '';\n }\n\n const parts = [];\n parts.push('api')\n parts.push('files')\n parts.push(encodeURIComponent(record.collectionId || record.collectionName))\n parts.push(encodeURIComponent(record.id))\n parts.push(encodeURIComponent(filename))\n\n let result = this.client.buildUrl(parts.join('/'));\n\n if (Object.keys(queryParams).length) {\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete(queryParams.download);\n }\n\n const params = new URLSearchParams(queryParams);\n\n result += (result.includes('?') ? '&' : '?') + params;\n }\n\n return result\n }\n\n /**\n * Requests a new private file access token for the current auth model (admin or record).\n */\n getToken(options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send('/api/files/token', options)\n .then((data) => data?.token || '');\n }\n}\n","import { BaseService } from '@/services/utils/BaseService';\nimport { CommonOptions } from '@/services/utils/options';\n\nexport interface BackupFileInfo {\n key: string;\n size: number;\n modified: string;\n}\n\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n */\n getFullList(options?: CommonOptions): Promise> {\n options = Object.assign({\n 'method': 'GET',\n }, options);\n\n return this.client.send('/api/backups', options);\n }\n\n /**\n * Initializes a new backup.\n */\n create(basename: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n 'body': {\n 'name': basename,\n },\n }, options);\n\n return this.client.send('/api/backups', options)\n .then(() => true);\n }\n\n /**\n * Deletes a single backup file.\n */\n delete(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'DELETE',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options)\n .then(() => true);\n }\n\n /**\n * Initializes an app data restore from an existing backup.\n */\n restore(key: string, options?: CommonOptions): Promise {\n options = Object.assign({\n 'method': 'POST',\n }, options);\n\n return this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n\n /**\n * Builds a download url for a single existing backup using an\n * admin file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadUrl(token: string, key: string): string {\n return this.client.buildUrl(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n","import { ClientResponseError } from '@/ClientResponseError';\nimport { BaseAuthStore } from '@/stores/BaseAuthStore';\nimport { LocalAuthStore } from '@/stores/LocalAuthStore';\nimport { SettingsService } from '@/services/SettingsService';\nimport { AdminService } from '@/services/AdminService';\nimport { RecordService } from '@/services/RecordService';\nimport { CollectionService } from '@/services/CollectionService';\nimport { LogService } from '@/services/LogService';\nimport { RealtimeService } from '@/services/RealtimeService';\nimport { HealthService } from '@/services/HealthService';\nimport { FileService } from '@/services/FileService';\nimport { BackupService } from '@/services/BackupService';\nimport { SendOptions, FileOptions } from '@/services/utils/options';\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n 'requestKey',\n '$cancelKey',\n '$autoCancel',\n 'fetch',\n 'headers',\n 'body',\n 'query',\n 'params',\n // ---,\n 'cache',\n 'credentials',\n 'headers',\n 'integrity',\n 'keepalive',\n 'method',\n 'mode',\n 'redirect',\n 'referrer',\n 'referrerPolicy',\n 'signal',\n 'window',\n];\n\nexport interface BeforeSendResult {\n [key: string]: any, // for backward compatibility\n url?: string,\n options?: {[key: string]: any}\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect and modify the url and request options.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, options) {\n * options.headers = Object.assign({}, options.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return { url, options }\n * };\n * ```\n */\n beforeSend?: (url: string, options: SendOptions) => BeforeSendResult|Promise;\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replaceable instance of the local auth store service.\n */\n authStore: BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: SettingsService;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: AdminService;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: CollectionService;\n\n /**\n * An instance of the service that handles the **File APIs**.\n */\n readonly files: FileService;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: LogService;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: RealtimeService;\n\n /**\n * An instance of the service that handles the **Health APIs**.\n */\n readonly health: HealthService;\n\n /**\n * An instance of the service that handles the **Backup APIs**.\n */\n readonly backups: BackupService;\n\n private cancelControllers: { [key: string]: AbortController } = {};\n private recordServices: { [key: string]: RecordService } = {};\n private enableAutoCancellation: boolean = true;\n\n constructor(\n baseUrl = '/',\n authStore?: BaseAuthStore | null,\n lang = 'en-US',\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.files = new FileService(this);\n this.logs = new LogService(this);\n this.settings = new SettingsService(this);\n this.realtime = new RealtimeService(this);\n this.health = new HealthService(this);\n this.backups = new BackupService(this);\n }\n\n /**\n * Returns the RecordService associated to the specified collection.\n *\n * @param {string} idOrName\n * @return {RecordService}\n */\n collection(idOrName: string): RecordService {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n\n return this.recordServices[idOrName];\n }\n\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable: boolean): Client {\n this.enableAutoCancellation = !!enable;\n\n return this;\n }\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey: string): Client {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n\n return this;\n }\n\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests(): Client {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k].abort();\n }\n\n this.cancelControllers = {};\n\n return this;\n }\n\n /**\n * Legacy alias of `pb.files.getUrl()`.\n */\n getFileUrl(\n record: Pick<{[key:string]:any}, 'id' | 'collectionId' | 'collectionName'>,\n filename: string,\n queryParams: FileOptions = {}\n ): string {\n return this.files.getUrl(record, filename, queryParams);\n }\n\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildUrl(path: string): string {\n let url = this.baseUrl;\n\n // construct an absolute base url if in a browser environment\n if (\n typeof window !== 'undefined' &&\n !!window.location &&\n !url.startsWith('https://') &&\n !url.startsWith('http://')\n ) {\n url = window.location.origin?.endsWith('/') ?\n window.location.origin.substring(0, window.location.origin.length - 1) :\n (window.location.origin || '');\n\n if (!this.baseUrl.startsWith('/')) {\n url += window.location.pathname || '/';\n url += url.endsWith('/') ? '' : '/';\n }\n\n url += this.baseUrl;\n }\n\n // concatenate the path\n if (path) {\n url += url.endsWith('/') ? '' : '/'; // append trailing slash if missing\n url += path.startsWith('/') ? path.substring(1) : path;\n }\n\n return url;\n }\n\n /**\n * Sends an api http request.\n */\n async send(path: string, options: SendOptions): Promise {\n options = this.initSendOptions(path, options);\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof options.query !== 'undefined') {\n const query = this.serializeQueryParams(options.query)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete options.query;\n }\n\n if (this.beforeSend) {\n const result = Object.assign({}, await this.beforeSend(url, options));\n if (typeof result.url !== 'undefined' || typeof result.options !== 'undefined') {\n url = result.url || url;\n options = result.options || options;\n } else if (Object.keys(result).length) {\n // legacy behavior\n options = result as SendOptions;\n console?.warn && console.warn('Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.');\n }\n }\n\n // ensures that the json body is serialized\n if (\n this.getHeader(options.headers, 'Content-Type') == 'application/json' &&\n options.body && typeof options.body !== 'string'\n ) {\n options.body = JSON.stringify(options.body);\n }\n\n const fetchFunc = options.fetch || fetch;\n\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data : any = {};\n\n try {\n data = await response.json();\n } catch (_) {\n // all api responses are expected to return json\n // with the exception of the realtime event and 204\n }\n\n if (this.afterSend) {\n data = await this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data as T;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\n }\n\n /**\n * Shallow copy the provided object and takes care to initialize\n * any options required to preserve the backward compatability.\n *\n * @param {SendOptions} options\n * @return {SendOptions}\n */\n private initSendOptions(path: string, options: SendOptions): SendOptions {\n options = Object.assign({ method: 'GET' } as SendOptions, options)\n options.query = options.query || {};\n\n // auto convert the body to FormData, if needed\n options.body = this.convertToFormDataIfNeeded(options.body);\n\n // move unknown send options as query parameters\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue\n }\n\n options.query[key] = options[key];\n delete (options[key]);\n }\n\n // requestKey normalizations for backward-compatibility\n // ---\n options.query = Object.assign({}, options.params, options.query);\n if (typeof options.requestKey === 'undefined') {\n if (options.$autoCancel === false || options.query.$autoCancel === false) {\n options.requestKey = null;\n } else if (options.$cancelKey || options.query.$cancelKey) {\n options.requestKey = options.$cancelKey || options.query.$cancelKey;\n }\n }\n // remove the deprecated special cancellation params from the other query params\n delete options.$autoCancel;\n delete options.query.$autoCancel;\n delete options.$cancelKey;\n delete options.query.$cancelKey;\n // ---\n\n // add the json header, if not explicitly set\n // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n if (\n this.getHeader(options.headers, 'Content-Type') === null &&\n !this.isFormData(options.body)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Content-Type': 'application/json',\n });\n }\n\n // add Accept-Language header, if not explicitly set\n if (this.getHeader(options.headers, 'Accept-Language') === null) {\n options.headers = Object.assign({}, options.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has valid token\n this.authStore.token &&\n // auth header is not explicitly set\n (this.getHeader(options.headers, 'Authorization') === null)\n ) {\n options.headers = Object.assign({}, options.headers, {\n 'Authorization': this.authStore.token,\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || ((options.method || 'GET') + path);\n\n delete options.requestKey;\n\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n\n return options\n }\n\n /**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\n private convertToFormDataIfNeeded(body: any): any {\n if (\n typeof FormData === 'undefined' ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n this.isFormData(body) ||\n !this.hasBlobField(body)\n ) {\n return body;\n }\n\n const form = new FormData();\n\n for (let key in body) {\n form.append(key, body[key]);\n }\n\n return form;\n }\n\n /**\n * Checks if the submitted body object has at least one Blob/File field.\n */\n private hasBlobField(body: {[key:string]: any}): boolean {\n for (let key in body) {\n const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n for (let v of values) {\n if (\n (typeof Blob !== 'undefined' && v instanceof Blob) ||\n (typeof File !== 'undefined' && v instanceof File)\n ) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Extracts the header with the provided name in case-insensitive manner.\n * Returns `null` if no header matching the name is found.\n */\n private getHeader(headers: {[key:string]:string}|undefined, name: string): string|null {\n headers = headers || {};\n name = name.toLowerCase();\n\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n\n return null;\n }\n\n /**\n * Loosely checks if the specified body is a FormData instance.\n */\n private isFormData(body: any): boolean {\n return body && (\n // we are checking the constructor name because FormData\n // is not available natively in some environments and the\n // polyfill(s) may not be globally accessible\n body.constructor.name === 'FormData' ||\n // fallback to global FormData instance check\n // note: this is needed because the constructor.name could be different in case of\n // custom global FormData implementation, eg. React Native on Android/iOS\n (typeof FormData !== 'undefined' && body instanceof FormData)\n )\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // repeat array params\n for (const v of value) {\n result.push(encodedKey + '=' + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + '=' + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + '=' + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + '=' + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","_a","_d","_c","_b","cause","includes","toJSON","assign","fieldContentRegExp","cookieSerialize","val","options","opt","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","input","str","String","replace","length","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","model","isValid","isTokenExpired","expirationThreshold","payload","keys","exp","now","isAdmin","type","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","key","rawData","cookieParse","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","toEmail","emailTemplate","template","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","query","baseCrudPath","responseData","items","item","getFirstListItem","filter","requestKey","skipTotal","code","getOne","create","batchSize","request","__awaiter","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","console","warn","AdminService","authStore","collectionId","delete","success","authResponse","admin","authWithPassword","password","identity","bind","authRefresh","requestPasswordReset","confirmPasswordReset","resetToken","passwordConfirm","RealtimeService","eventSource","subscriptions","lastSentTopics","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","listener","msgEvent","submitSubscriptions","connect","unsubscribeByTopicAndListener","unsubscribe","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","topicPrefix","hasAtleastOneTopic","startsWith","exist","topicToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionTopics","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildUrl","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","latestTopics","t","timeout","fromReconnect","cancelRequest","close","RecordService","collectionIdOrName","baseCollectionPath","subscribeOne","recordId","realtime","topicOrCallback","batchOrOptions","params","collectionName","record","listAuthMethods","usernamePassword","emailPassword","authProviders","usernameOrEmail","authWithOAuth2Code","provider","codeVerifier","redirectUrl","createData","authWithOAuth2","args","config","find","eagerDefaultPopup","cleanup","urlCallback","openBrowserPopup","oldState","state","scopes","authData","replacements","_replaceQueryParams","authUrl","location","href","passwordResetToken","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","unlinkExternalAuth","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","LogService","getRequestsList","getRequest","getRequestsStats","HealthService","check","FileService","getUrl","filename","queryParams","parts","download","URLSearchParams","getToken","BackupService","basename","restore","getDownloadUrl","knownSendOptionsKeys","Client","baseUrl","lang","cancelControllers","recordServices","enableAutoCancellation","admins","files","logs","settings","health","backups","collection","idOrName","autoCancellation","enable","abort","cancelAllRequests","k","getFileUrl","origin","endsWith","pathname","initSendOptions","serializeQueryParams","beforeSend","getHeader","headers","fetch","json","afterSend","convertToFormDataIfNeeded","$autoCancel","$cancelKey","isFormData","Authorization","controller","AbortController","signal","FormData","hasBlobField","form","append","values","v","File","encodedKey","toISOString"],"mappings":"uoBAIM,MAAOA,4BAA4BC,MAOrC,WAAAC,CAAYC,eACRC,MAAM,uBAPVC,KAAGC,IAA8B,GACjCD,KAAME,OAA2B,EACjCF,KAAQG,SAAyB,GACjCH,KAAOI,SAA0B,EACjCJ,KAAaK,cAAoB,KAO7BC,OAAOC,eAAeP,KAAML,oBAAoBa,WAEhC,OAAZV,GAAuC,iBAAZA,IAC3BE,KAAKC,IAAuC,iBAAhBH,EAAQG,IAAmBH,EAAQG,IAAM,GACrED,KAAKE,OAA0C,iBAAnBJ,EAAQI,OAAsBJ,EAAQI,OAAS,EAC3EF,KAAKI,UAAkBN,EAAQM,QAC/BJ,KAAKK,cAAgBP,EAAQO,cAEJ,OAArBP,EAAQK,UAAiD,iBAArBL,EAAQK,SAC5CH,KAAKG,SAAYL,EAAQK,SACD,OAAjBL,EAAQW,MAAyC,iBAAjBX,EAAQW,KAC/CT,KAAKG,SAAYL,EAAQW,KAEzBT,KAAKG,SAAY,IAIpBH,KAAKK,eAAmBP,aAAmBH,sBAC5CK,KAAKK,cAAgBP,GAGG,oBAAjBY,cAAgCZ,aAAmBY,eAC1DV,KAAKI,SAAU,GAGnBJ,KAAKW,KAAO,uBAAyBX,KAAKE,OAC1CF,KAAKY,QAAyB,QAAfC,EAAAb,KAAKG,gBAAU,IAAAU,OAAA,EAAAA,EAAAD,QACzBZ,KAAKY,UACFZ,KAAKI,QACLJ,KAAKY,QAAU,oHAC4B,QAApCE,EAAyB,QAAzBC,EAAkB,QAAlBC,EAAAhB,KAAKK,qBAAa,IAAAW,OAAA,EAAAA,EAAEC,aAAK,IAAAF,OAAA,EAAAA,EAAEH,eAAS,IAAAE,OAAA,EAAAA,EAAAI,SAAS,qBACpDlB,KAAKY,QAAU,qJAEfZ,KAAKY,QAAU,sDAG1B,CAKD,QAAIH,GACA,OAAOT,KAAKG,QACf,CAMD,MAAAgB,GACI,OAAAb,OAAAc,OAAA,CAAA,EAAYpB,KACf,ECrDL,MAAMqB,EAAqB,iDAqFXC,gBAAgBX,EAAcY,EAAaC,GACvD,MAAMC,EAASnB,OAAOc,OAAO,CAAA,EAAII,GAAW,CAAA,GACtCE,EAASD,EAAIC,QAAUC,cAE7B,IAAKN,EAAmBO,KAAKjB,GACzB,MAAM,IAAIkB,UAAU,4BAGxB,MAAMC,EAAQJ,EAAOH,GAErB,GAAIO,IAAUT,EAAmBO,KAAKE,GAClC,MAAM,IAAID,UAAU,2BAGxB,IAAIE,EAASpB,EAAO,IAAMmB,EAE1B,GAAkB,MAAdL,EAAIO,OAAgB,CACpB,MAAMA,EAASP,EAAIO,OAAS,EAE5B,GAAIC,MAAMD,KAAYE,SAASF,GAC3B,MAAM,IAAIH,UAAU,4BAGxBE,GAAU,aAAeI,KAAKC,MAAMJ,EACvC,CAED,GAAIP,EAAIY,OAAQ,CACZ,IAAKhB,EAAmBO,KAAKH,EAAIY,QAC7B,MAAM,IAAIR,UAAU,4BAGxBE,GAAU,YAAcN,EAAIY,MAC/B,CAED,GAAIZ,EAAIa,KAAM,CACV,IAAKjB,EAAmBO,KAAKH,EAAIa,MAC7B,MAAM,IAAIT,UAAU,0BAGxBE,GAAU,UAAYN,EAAIa,IAC7B,CAED,GAAIb,EAAIc,QAAS,CACb,IA6ER,SAASC,OAAOjB,GACZ,MAC4C,kBAAxCjB,OAAOE,UAAUiC,SAASC,KAAKnB,IAC/BA,aAAeoB,IAEvB,CAlFaH,CAAOf,EAAIc,UAAYN,MAAMR,EAAIc,QAAQK,WAC1C,MAAM,IAAIf,UAAU,6BAGxBE,GAAU,aAAeN,EAAIc,QAAQM,aACxC,CAUD,GARIpB,EAAIqB,WACJf,GAAU,cAGVN,EAAIsB,SACJhB,GAAU,YAGVN,EAAIuB,SAAU,CAGd,OAFyC,iBAAjBvB,EAAIuB,SAAwBvB,EAAIuB,SAASC,cAAgBxB,EAAIuB,UAGjF,IAAK,MACDjB,GAAU,iBACV,MACJ,IAAK,SACDA,GAAU,oBACV,MACJ,IAAK,OACDA,GAAU,kBACV,MACJ,QACI,MAAM,IAAIF,UAAU,8BAE/B,CAED,GAAIJ,EAAIyB,SAAU,CAGd,OAFyC,iBAAjBzB,EAAIyB,SAAwBzB,EAAIyB,SAASD,cAAgBxB,EAAIyB,UAGjF,KAAK,EACDnB,GAAU,oBACV,MACJ,IAAK,MACDA,GAAU,iBACV,MACJ,IAAK,SACDA,GAAU,oBACV,MACJ,IAAK,OACDA,GAAU,kBACV,MACJ,QACI,MAAM,IAAIF,UAAU,8BAE/B,CAED,OAAOE,CACX,CAMA,SAASoB,cAAc5B,GACnB,OAA6B,IAAtBA,EAAI6B,QAAQ,KACbC,mBAAmB9B,GACnBA,CACV,CAKA,SAASI,cAAcJ,GACnB,OAAO+B,mBAAmB/B,EAC9B,CCtNA,IAAIgC,EAyCE,SAAUC,gBAAgBC,GAC5B,GAAIA,EACA,IACI,MAAMC,EAAiBL,mBAAmBE,EAAaE,EAAME,MAAM,KAAK,IAAIA,MAAM,IAAIC,KAAI,SAAUC,GAChG,MAAO,KAAO,KAAOA,EAAEC,WAAW,GAAGrB,SAAS,KAAKsB,OAAO,EAC9D,IAAGC,KAAK,KAER,OAAOC,KAAKC,MAAMR,IAAmB,CAAA,CACxC,CAAC,MAAOS,GACR,CAGL,MAAO,EACX,CApDIZ,EADgB,mBAATa,KACQA,KAMCC,IAGZ,IAAIC,EAAMC,OAAOF,GAAOG,QAAQ,MAAO,IACvC,GAAIF,EAAIG,OAAS,GAAK,EAClB,MAAM,IAAI7E,MAAM,qEAGpB,IAEI,IAAY8E,EAAIC,EAAZC,EAAK,EAAeC,EAAM,EAAGC,EAAS,GAEzCH,EAASL,EAAIS,OAAOF,MAEpBF,IACCD,EAAKE,EAAK,EAAkB,GAAbF,EAAkBC,EAASA,EAGxCC,IAAO,GACVE,GAAUP,OAAOS,aAAa,IAAON,KAAS,EAAIE,EAAM,IACzD,EAGAD,EAtBU,oEAsBKvB,QAAQuB,GAG3B,OAAOG,CAAM,EC1BrB,MAAMG,EAAmB,gBAMHC,cAAtB,WAAArF,GACcG,KAASmF,UAAW,GACpBnF,KAASoF,UAAc,KAEzBpF,KAAkBqF,mBAA6B,EAwL1D,CAnLG,SAAI5B,GACA,OAAOzD,KAAKmF,SACf,CAKD,SAAIG,GACA,OAAOtF,KAAKoF,SACf,CAKD,WAAIG,GACA,gBD0BQC,eAAe/B,EAAegC,EAAsB,GAChE,IAAIC,EAAUlC,gBAAgBC,GAE9B,QACInD,OAAOqF,KAAKD,GAASjB,OAAS,KAC5BiB,EAAQE,KAAQF,EAAQE,IAAMH,EAAwB9C,KAAKkD,MAAQ,KAM7E,CCrCgBL,CAAexF,KAAKyD,MAC/B,CAKD,WAAIqC,GACA,MAA4C,UAArCtC,gBAAgBxD,KAAKyD,OAAOsC,IACtC,CAKD,gBAAIC,GACA,MAA4C,eAArCxC,gBAAgBxD,KAAKyD,OAAOsC,IACtC,CAKD,IAAAE,CAAKxC,EAAe6B,GAChBtF,KAAKmF,UAAY1B,GAAS,GAC1BzD,KAAKoF,UAAYE,GAAS,KAE1BtF,KAAKkG,eACR,CAKD,KAAAC,GACInG,KAAKmF,UAAY,GACjBnF,KAAKoF,UAAY,KACjBpF,KAAKkG,eACR,CA0BD,cAAAE,CAAeC,EAAgBC,EAAMrB,GACjC,MAAMsB,EF3EE,SAAAC,YAAYlC,EAAa9C,GACrC,MAAMO,EAAiC,CAAA,EAEvC,GAAmB,iBAARuC,EACP,OAAOvC,EAGX,MACM0E,EADSnG,OAAOc,OAAO,CAAA,EAAII,GAAW,CAAA,GACzBiF,QAAUtD,cAE7B,IAAIuD,EAAQ,EACZ,KAAOA,EAAQpC,EAAIG,QAAQ,CACvB,MAAMkC,EAAQrC,EAAIlB,QAAQ,IAAKsD,GAG/B,IAAe,IAAXC,EACA,MAGJ,IAAIC,EAAStC,EAAIlB,QAAQ,IAAKsD,GAE9B,IAAgB,IAAZE,EACAA,EAAStC,EAAIG,YACV,GAAImC,EAASD,EAAO,CAEvBD,EAAQpC,EAAIuC,YAAY,IAAKF,EAAQ,GAAK,EAC1C,QACH,CAED,MAAML,EAAMhC,EAAIP,MAAM2C,EAAOC,GAAOG,OAGpC,QAAIC,IAAchF,EAAOuE,GAAM,CAC3B,IAAI/E,EAAM+C,EAAIP,MAAM4C,EAAQ,EAAGC,GAAQE,OAGb,KAAtBvF,EAAIuC,WAAW,KACfvC,EAAMA,EAAIwC,MAAM,GAAI,IAGxB,IACIhC,EAAOuE,GAAOG,EAAOlF,EACxB,CAAC,MAAOyF,GACLjF,EAAOuE,GAAO/E,CACjB,CACJ,CAEDmF,EAAQE,EAAS,CACpB,CAED,OAAO7E,CACX,CEwBwByE,CAAYH,GAAU,IAAIC,IAAQ,GAElD,IAAI7F,EAA+B,CAAA,EACnC,IACIA,EAAOwD,KAAKC,MAAMqC,IAEE,cAAT9F,GAAiC,iBAATA,GAAqBwG,MAAMC,QAAQzG,MAClEA,EAAO,CAAA,EAEd,CAAC,MAAOuG,GAAK,CAEdhH,KAAKiG,KAAKxF,EAAKgD,OAAS,GAAIhD,EAAK6E,OAAS,KAC7C,CAgBD,cAAA6B,CAAe3F,EAA4B8E,EAAMrB,WAC7C,MAAMmC,EAAmC,CACrCrE,QAAU,EACVG,UAAU,EACVJ,UAAU,EACVR,KAAU,KAIRoD,EAAUlC,gBAAgBxD,KAAKyD,QACjCiC,eAAAA,EAASE,KACTwB,EAAe7E,QAAU,IAAII,KAAmB,IAAd+C,EAAQE,KAE1CwB,EAAe7E,QAAU,IAAII,KAAK,cAItCnB,EAAUlB,OAAOc,OAAO,CAAE,EAAEgG,EAAgB5F,GAE5C,MAAM+E,EAAU,CACZ9C,MAAOzD,KAAKyD,MACZ6B,MAAOtF,KAAKsF,MAAQrB,KAAKC,MAAMD,KAAKoD,UAAUrH,KAAKsF,QAAU,MAGjE,IAAIvD,EAAST,gBAAgBgF,EAAKrC,KAAKoD,UAAUd,GAAU/E,GAE3D,MAAM8F,EAA+B,oBAATC,KACxB,IAAKA,KAAK,CAACxF,IAAUyF,KAAOzF,EAAO0C,OAGvC,GAAI8B,EAAQjB,OAASgC,EAAe,KAAM,CACtCf,EAAQjB,MAAQ,CAACmC,GAAkB,QAAd5G,EAAA0F,aAAA,EAAAA,EAASjB,aAAK,IAAAzE,OAAA,EAAAA,EAAE4G,GAAIC,MAAuB,QAAhB1G,EAAAuF,aAAA,EAAAA,EAASjB,aAAO,IAAAtE,OAAA,EAAAA,EAAA0G,OAChE,MAAMC,EAAa,CAAC,eAAgB,WAAY,YAChD,IAAK,MAAMC,KAAQ5H,KAAKsF,MAChBqC,EAAWzG,SAAS0G,KACpBrB,EAAQjB,MAAMsC,GAAQ5H,KAAKsF,MAAMsC,IAGzC7F,EAAST,gBAAgBgF,EAAKrC,KAAKoD,UAAUd,GAAU/E,EAC1D,CAED,OAAOO,CACV,CAUD,QAAA8F,CAASC,EAA6BC,GAAkB,GAOpD,OANA/H,KAAKqF,mBAAmB2C,KAAKF,GAEzBC,GACAD,EAAS9H,KAAKyD,MAAOzD,KAAKsF,OAGvB,KACH,IAAK,IAAI2C,EAAIjI,KAAKqF,mBAAmBZ,OAAS,EAAGwD,GAAK,EAAGA,IACrD,GAAIjI,KAAKqF,mBAAmB4C,IAAMH,EAG9B,cAFO9H,KAAKqF,mBAAmB4C,QAC/BjI,KAAKqF,mBAAmB6C,OAAOD,EAAG,EAGzC,CAER,CAES,aAAA/B,GACN,IAAK,MAAM4B,KAAY9H,KAAKqF,mBACxByC,GAAYA,EAAS9H,KAAKyD,MAAOzD,KAAKsF,MAE7C,ECnMC,MAAO6C,uBAAuBjD,cAIhC,WAAArF,CAAYuI,EAAa,mBACrBrI,QAJIC,KAAeqI,gBAA2B,GAM9CrI,KAAKoI,WAAaA,EAElBpI,KAAKsI,mBACR,CAKD,SAAI7E,GAGA,OAFazD,KAAKuI,YAAYvI,KAAKoI,aAAe,IAEtC3E,OAAS,EACxB,CAKD,SAAI6B,GAGA,OAFatF,KAAKuI,YAAYvI,KAAKoI,aAAe,IAEtC9C,OAAS,IACxB,CAKD,IAAAW,CAAKxC,EAAe6B,GAChBtF,KAAKwI,YAAYxI,KAAKoI,WAAY,CAC9B3E,MAASA,EACT6B,MAASA,IAGbvF,MAAMkG,KAAKxC,EAAO6B,EACrB,CAKD,KAAAa,GACInG,KAAKyI,eAAezI,KAAKoI,YAEzBrI,MAAMoG,OACT,CAUO,WAAAoC,CAAYjC,GAChB,GAAsB,oBAAXoC,SAA0B,OAAAA,aAAA,IAAAA,YAAA,EAAAA,OAAQC,cAAc,CACvD,MAAMC,EAAWF,OAAOC,aAAaE,QAAQvC,IAAQ,GACrD,IACI,OAAOrC,KAAKC,MAAM0E,EACrB,CAAC,MAAOzE,GACL,OAAOyE,CACV,CACJ,CAGD,OAAO5I,KAAKqI,gBAAgB/B,EAC/B,CAMO,WAAAkC,CAAYlC,EAAaxE,GAC7B,GAAsB,oBAAX4G,SAA0B,OAAAA,aAAA,IAAAA,YAAA,EAAAA,OAAQC,cAAc,CAEvD,IAAIG,EAAgBhH,EACC,iBAAVA,IACPgH,EAAgB7E,KAAKoD,UAAUvF,IAEnC4G,OAAOC,aAAaI,QAAQzC,EAAKwC,EACpC,MAEG9I,KAAKqI,gBAAgB/B,GAAOxE,CAEnC,CAKO,cAAA2G,CAAenC,SAEG,oBAAXoC,SAA0B,OAAAA,aAAA,IAAAA,YAAA,EAAAA,OAAQC,gBACtB,QAAnB9H,EAAA6H,OAAOC,oBAAY,IAAA9H,GAAAA,EAAEmI,WAAW1C,WAI7BtG,KAAKqI,gBAAgB/B,EAC/B,CAKO,iBAAAgC,GACkB,oBAAXI,SAA2B,OAAAA,iBAAAA,cAAAA,OAAQC,eAAiBD,OAAOO,kBAItEP,OAAOO,iBAAiB,WAAY9E,IAChC,GAAIA,EAAEmC,KAAOtG,KAAKoI,WACd,OAGJ,MAAM3H,EAAOT,KAAKuI,YAAYvI,KAAKoI,aAAe,GAElDrI,MAAMkG,KAAKxF,EAAKgD,OAAS,GAAIhD,EAAK6E,OAAS,KAAK,GAEvD,QC1HiB4D,YAGlB,WAAArJ,CAAYsJ,GACRnJ,KAAKmJ,OAASA,CACjB,ECHC,MAAOC,wBAAwBF,YAIjC,MAAAG,CAAO7H,GAKH,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,gBAAiB/H,EAC5C,CAKD,MAAAgI,CACIC,EACAjI,GAOA,OALAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,QACVI,KAAUD,GACXjI,GAEIxB,KAAKmJ,OAAOI,KAAK,gBAAiB/H,EAC5C,CAOD,MAAAmI,CAAOC,EAAqB,UAAWpI,GAQnC,OAPAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACVI,KAAQ,CACJE,WAAcA,IAEnBpI,GAEIxB,KAAKmJ,OAAOI,KAAK,wBAAyB/H,GAC5CqI,MAAK,KAAM,GACnB,CAUD,SAAAC,CAAUC,EAAiBC,EAAuBxI,GAS9C,OARAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACVI,KAAQ,CACJhC,MAAYqC,EACZE,SAAYD,IAEjBxI,GAEIxB,KAAKmJ,OAAOI,KAAK,2BAA4B/H,GAC/CqI,MAAK,KAAM,GACnB,CAKD,yBAAAK,CACIC,EACAC,EACAC,EACAC,EACAC,EACA/I,GAaA,OAXAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACVI,KAAQ,CACJS,WACAC,SACAC,QACAC,aACAC,aAEL/I,GAEIxB,KAAKmJ,OAAOI,KAAK,6CAA8C/H,EACzE,ECtFC,MAAgBgJ,oBAAuBtB,YASzC,MAAAzC,CAAchG,GACV,OAAOA,CACV,CAeD,WAAAgK,CAAmBC,EAA6ClJ,GAC5D,GAAiC,iBAAtBkJ,EACP,OAAO1K,KAAK2K,aAAgBD,EAAoBlJ,GAKpD,IAAIoJ,EAAQ,IAMZ,OARApJ,EAAUlB,OAAOc,OAAO,CAAE,EAAEsJ,EAAoBlJ,IAGpCoJ,QACRA,EAAQpJ,EAAQoJ,aACTpJ,EAAQoJ,OAGZ5K,KAAK2K,aAAgBC,EAAOpJ,EACtC,CAOD,OAAAqJ,CAAeC,EAAO,EAAGC,EAAU,GAAIvJ,GAUnC,OATAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAQ,OACT9H,IAEKwJ,MAAQ1K,OAAOc,OAAO,CAC1B0J,KAAWA,EACXC,QAAWA,GACZvJ,EAAQwJ,OAEJhL,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAczJ,GACtCqI,MAAMqB,UAKH,OAJAA,EAAaC,OAA0B,UAAlBD,EAAaC,aAAK,IAAAtK,OAAA,EAAAA,EAAE+C,KAAKwH,GACnCpL,KAAKyG,OAAU2E,OACpB,GAECF,CAAY,GAE9B,CAaD,gBAAAG,CAAwBC,EAAgB9J,GAUpC,OATAA,EAAUlB,OAAOc,OAAO,CACpBmK,WAAc,iBAAmBvL,KAAKiL,aAAe,IAAMK,GAC5D9J,IAEKwJ,MAAQ1K,OAAOc,OAAO,CAC1BkK,OAAcA,EACdE,UAAc,GACfhK,EAAQwJ,OAEJhL,KAAK6K,QAAW,EAAG,EAAGrJ,GACxBqI,MAAM9H,UACH,KAAoB,QAAflB,EAAAkB,aAAA,EAAAA,EAAQoJ,aAAO,IAAAtK,OAAA,EAAAA,EAAA4D,QAChB,MAAM,IAAI9E,oBAAoB,CAC1BO,OAAQ,IACRO,KAAM,CACFgL,KAAM,IACN7K,QAAS,uCACTH,KAAM,CAAE,KAKpB,OAAOsB,EAAOoJ,MAAM,EAAE,GAEjC,CAOD,MAAAO,CAAcjE,EAAYjG,GAKtB,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,IAAM3H,mBAAmBmE,GAAKjG,GACrEqI,MAAMqB,GAAsBlL,KAAKyG,OAAUyE,IACnD,CAOD,MAAAS,CACIlC,EACAjI,GAOA,OALAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACVI,KAAUD,GACXjI,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAczJ,GACtCqI,MAAMqB,GAAsBlL,KAAKyG,OAAUyE,IACnD,CAOD,MAAA1B,CACI/B,EACAgC,EACAjI,GAOA,OALAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,QACVI,KAAUD,GACXjI,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,IAAM3H,mBAAmBmE,GAAKjG,GACrEqI,MAAMqB,GAAsBlL,KAAKyG,OAAUyE,IACnD,CAKD,OAAOzD,EAAYjG,GAKf,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,UACX9H,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,IAAM3H,mBAAmBmE,GAAKjG,GACrEqI,MAAK,KAAM,GACnB,CAKS,YAAAc,CAAoBiB,EAAY,IAAKpK,IAC3CA,EAAUA,GAAW,IACbwJ,MAAQ1K,OAAOc,OAAO,CAC1BoK,UAAa,GACdhK,EAAQwJ,OAEX,IAAIjJ,EAAmB,GAEnB8J,QAAiBf,GAAqCgB,UAAA9L,UAAA,OAAA,GAAA,YACtD,OAAOA,KAAK6K,QAAQC,EAAMc,GAAa,IAAKpK,GAASqI,MAAMkC,IACvD,MACMZ,EADcY,EACUZ,MAI9B,OAFApJ,EAASA,EAAOiK,OAAOb,GAEnBA,EAAM1G,QAAUsH,EAAKhB,QACdc,QAAQf,EAAO,GAGnB/I,CAAM,GAErB,IAEA,OAAO8J,QAAQ,EAClB,EC1MC,SAAUI,2BAA2BC,EAAoBC,EAA0BC,EAAqBpB,GAC1G,MACMqB,OAA4B,IAAVrB,EAExB,OAAKqB,QAH6C,IAAlBD,EAO5BC,GACAC,QAAQC,KAAKL,GACbC,EAAYzC,KAAOpJ,OAAOc,OAAO,CAAE,EAAE+K,EAAYzC,KAAM0C,GACvDD,EAAYnB,MAAQ1K,OAAOc,OAAO,CAAE,EAAE+K,EAAYnB,MAAOA,GAElDmB,GAGXA,EAAc7L,OAAOc,OAAO+K,EAAaC,GAX9BD,CAaf,CCRM,MAAOK,qBAAqBhC,YAI9B,gBAAIS,GACA,MAAO,aACV,CAYD,MAAAzB,CACI/B,EACAgC,EACAjI,GAEA,OAAOzB,MAAMyJ,OAAO/B,EAAIgC,EAAYjI,GAASqI,MAAMuB,YAS/C,OANiC,QAA7BvK,EAAAb,KAAKmJ,OAAOsD,UAAUnH,aAAO,IAAAzE,OAAA,EAAAA,EAAA4G,MAAO2D,EAAK3D,SACY,aAA9CzG,EAAAhB,KAAKmJ,OAAOsD,UAAUnH,4BAAOoH,eAEpC1M,KAAKmJ,OAAOsD,UAAUxG,KAAKjG,KAAKmJ,OAAOsD,UAAUhJ,MAAO2H,GAGrDA,CAAgB,GAE9B,CAQD,OAAO3D,EAAYjG,GACf,OAAOzB,MAAM4M,OAAOlF,EAAIjG,GAASqI,MAAM+C,YAUnC,OAPIA,IAC2B,QAA3B/L,EAAAb,KAAKmJ,OAAOsD,UAAUnH,aAAK,IAAAzE,OAAA,EAAAA,EAAE4G,MAAOA,QACiB,aAA9CzG,EAAAhB,KAAKmJ,OAAOsD,UAAUnH,4BAAOoH,eAEpC1M,KAAKmJ,OAAOsD,UAAUtG,QAGnByG,CAAO,GAErB,CASS,YAAAC,CAAa3B,GACnB,MAAM4B,EAAQ9M,KAAKyG,QAAOyE,eAAAA,EAAc4B,QAAS,CAAE,GAMnD,OAJI5B,aAAY,EAAZA,EAAczH,SAASyH,aAAY,EAAZA,EAAc4B,QACrC9M,KAAKmJ,OAAOsD,UAAUxG,KAAKiF,EAAazH,MAAOqJ,GAG5CxM,OAAOc,OAAO,CAAE,EAAE8J,EAAc,CAEnCzH,OAASyH,eAAAA,EAAczH,QAAS,GAChCqJ,MAASA,GAEhB,CAgBD,gBAAAC,CACIrF,EACAsF,EACAZ,EACApB,GAEA,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJuD,SAAYvF,EACZsF,SAAYA,IAWpB,OAPAxL,EAAUyK,2BACN,+IACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,sBAAuBzJ,GAC9DqI,KAAK7J,KAAK6M,aAAaK,KAAKlN,MACpC,CAgBD,WAAAmN,CAAYf,EAAqBpB,GAC7B,IAAIxJ,EAAe,CACf8H,OAAU,QAUd,OAPA9H,EAAUyK,2BACN,2GACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,gBAAiBzJ,GACxDqI,KAAK7J,KAAK6M,aAAaK,KAAKlN,MACpC,CAaD,oBAAAoN,CAAqB1F,EAAe0E,EAAqBpB,GACrD,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJhC,MAASA,IAWjB,OAPAlG,EAAUyK,2BACN,2IACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,0BAA2BzJ,GAClEqI,MAAK,KAAM,GACnB,CAaD,oBAAAwD,CAAqBC,EAAoBN,EAAkBO,EAAyBnB,EAAqBpB,GACrG,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJjG,MAAmB6J,EACnBN,SAAmBA,EACnBO,gBAAmBA,IAW3B,OAPA/L,EAAUyK,2BACN,2MACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,0BAA2BzJ,GAClEqI,MAAK,KAAM,GACnB,ECjNC,MAAO2D,wBAAwBtE,YAArC,WAAArJ,uBACIG,KAAQmK,SAAW,GAEXnK,KAAWyN,YAAuB,KAClCzN,KAAa0N,cAA4C,GACzD1N,KAAc2N,eAAkB,GAEhC3N,KAAiB4N,kBAAW,KAE5B5N,KAAiB6N,kBAAW,EAC5B7N,KAAoB8N,qBAAWC,IAC/B/N,KAAAgO,6BAA8C,CAClD,IAAK,IAAK,IAAK,IAAM,KAAM,KAAM,KAE7BhO,KAAeiO,gBAA4B,EAoYtD,CA/XG,eAAIC,GACA,QAASlO,KAAKyN,eAAiBzN,KAAKmK,WAAanK,KAAKiO,gBAAgBxJ,MACzE,CAUK,SAAA0J,CAAUC,EAAetG,0DAC3B,IAAKsG,EACD,MAAM,IAAIxO,MAAM,sBAGpB,MAAMyO,SAAW,SAAUlK,GACvB,MAAMmK,EAAYnK,EAElB,IAAI1D,EACJ,IACIA,EAAOwD,KAAKC,MAAMoK,aAAA,EAAAA,EAAU7N,KAC/B,CAAC,MAAAI,GAAQ,CAEViH,EAASrH,GAAQ,CAAA,EACrB,EAmBA,OAhBKT,KAAK0N,cAAcU,KACpBpO,KAAK0N,cAAcU,GAAS,IAEhCpO,KAAK0N,cAAcU,GAAOpG,KAAKqG,UAE1BrO,KAAKkO,YAGsC,IAArClO,KAAK0N,cAAcU,GAAO3J,aAE3BzE,KAAKuO,sBAGO,QAAlB1N,EAAAb,KAAKyN,mBAAa,IAAA5M,GAAAA,EAAAoI,iBAAiBmF,EAAOC,gBANpCrO,KAAKwO,UASR,IAA0B1C,UAAA9L,UAAA,OAAA,GAAA,YAC7B,OAAOA,KAAKyO,8BAA8BL,EAAOC,SACrD,MACH,CAaK,WAAAK,CAAYN,0DACd,GAAKpO,KAAK2O,yBAAyBP,GAAnC,CAIA,GAAKA,EAGE,CAEH,IAAK,IAAIC,KAAYrO,KAAK0N,cAAcU,GAClB,QAAlBvN,EAAAb,KAAKyN,mBAAa,IAAA5M,GAAAA,EAAA+N,oBAAoBR,EAAOC,UAE1CrO,KAAK0N,cAAcU,EAC7B,MAPGpO,KAAK0N,cAAgB,GASpB1N,KAAK2O,2BAGE3O,KAAK2O,yBAAyBP,WAEhCpO,KAAKuO,uBAHXvO,KAAK6O,YAfR,IAoBJ,CAUK,mBAAAC,CAAoBC,0DACtB,IAAIC,GAAqB,EACzB,IAAK,IAAIZ,KAASpO,KAAK0N,cACnB,GAAKU,EAAMa,WAAWF,GAAtB,CAIAC,GAAqB,EACrB,IAAK,IAAIX,KAAYrO,KAAK0N,cAAcU,GAClB,QAAlBvN,EAAAb,KAAKyN,mBAAa,IAAA5M,GAAAA,EAAA+N,oBAAoBR,EAAOC,UAE1CrO,KAAK0N,cAAcU,EANzB,CASAY,IAIDhP,KAAK2O,iCAEC3O,KAAKuO,sBAGXvO,KAAK6O,gBAEZ,CAWK,6BAAAJ,CAA8BL,EAAeC,0DAC/C,IAAKpH,MAAMC,QAAQlH,KAAK0N,cAAcU,MAAYpO,KAAK0N,cAAcU,GAAO3J,OACxE,OAGJ,IAAIyK,GAAQ,EACZ,IAAK,IAAIjH,EAAIjI,KAAK0N,cAAcU,GAAO3J,OAAS,EAAGwD,GAAK,EAAGA,IACnDjI,KAAK0N,cAAcU,GAAOnG,KAAOoG,IAIrCa,GAAQ,SACDlP,KAAK0N,cAAcU,GAAOnG,GACjCjI,KAAK0N,cAAcU,GAAOlG,OAAOD,EAAG,GAClB,QAAlBpH,EAAAb,KAAKyN,mBAAa,IAAA5M,GAAAA,EAAA+N,oBAAoBR,EAAOC,IAE5Ca,IAKAlP,KAAK0N,cAAcU,GAAO3J,eACpBzE,KAAK0N,cAAcU,GAGzBpO,KAAK2O,2BAGE3O,KAAK2O,yBAAyBP,WAEhCpO,KAAKuO,uBAHXvO,KAAK6O,gBAKZ,CAEO,wBAAAF,CAAyBQ,WAI7B,GAHAnP,KAAK0N,cAAgB1N,KAAK0N,eAAiB,CAAA,EAGvCyB,EACA,SAA2C,QAAlCtO,EAAAb,KAAK0N,cAAcyB,UAAe,IAAAtO,OAAA,EAAAA,EAAA4D,QAI/C,IAAK,IAAI2J,KAASpO,KAAK0N,cACnB,GAAiC,QAA3B1M,EAAAhB,KAAK0N,cAAcU,UAAQ,IAAApN,OAAA,EAAAA,EAAAyD,OAC7B,OAAO,EAIf,OAAO,CACV,CAEa,mBAAA8J,oDACV,GAAKvO,KAAKmK,SASV,OAJAnK,KAAKoP,8BAELpP,KAAK2N,eAAiB3N,KAAKqP,gCAEpBrP,KAAKmJ,OAAOI,KAAK,gBAAiB,CACrCD,OAAU,OACVI,KAAQ,CACJS,SAAYnK,KAAKmK,SACjBuD,cAAiB1N,KAAK2N,gBAE1B3C,MAAS,CACLO,WAAcvL,KAAKsP,+BAExBC,OAAOC,IACN,KAAIA,eAAAA,EAAKpP,SAGT,MAAMoP,CAAG,MAEhB,CAEO,yBAAAF,GACJ,MAAO,YAActP,KAAKmK,QAC7B,CAEO,6BAAAkF,GACJ,MAAMtN,EAAyB,GAE/B,IAAK,IAAIqM,KAASpO,KAAK0N,cACf1N,KAAK0N,cAAcU,GAAO3J,QAC1B1C,EAAOiG,KAAKoG,GAIpB,OAAOrM,CACV,CAEO,2BAAAqN,GACJ,GAAKpP,KAAKyN,YAAV,CAIAzN,KAAKyP,iCAEL,IAAK,IAAIrB,KAASpO,KAAK0N,cACnB,IAAK,IAAIW,KAAYrO,KAAK0N,cAAcU,GACpCpO,KAAKyN,YAAYxE,iBAAiBmF,EAAOC,EANhD,CASJ,CAEO,8BAAAoB,GACJ,GAAKzP,KAAKyN,YAIV,IAAK,IAAIW,KAASpO,KAAK0N,cACnB,IAAK,IAAIW,KAAYrO,KAAK0N,cAAcU,GACpCpO,KAAKyN,YAAYmB,oBAAoBR,EAAOC,EAGvD,CAEa,OAAAG,oDACV,KAAIxO,KAAK6N,kBAAoB,GAM7B,OAAO,IAAI6B,SAAQ,CAACC,EAASC,KACzB5P,KAAKiO,gBAAgBjG,KAAK,CAAE2H,UAASC,WAEjC5P,KAAKiO,gBAAgBxJ,OAAS,GAKlCzE,KAAK6P,aAAa,MAEzB,CAEO,WAAAA,GACJ7P,KAAK6O,YAAW,GAGhBiB,aAAa9P,KAAK+P,kBAClB/P,KAAK+P,iBAAmBC,YAAW,KAC/BhQ,KAAKiQ,oBAAoB,IAAIrQ,MAAM,sCAAsC,GAC1EI,KAAK4N,mBAER5N,KAAKyN,YAAc,IAAIyC,YAAYlQ,KAAKmJ,OAAOgH,SAAS,kBAExDnQ,KAAKyN,YAAY2C,QAAWpJ,IACxBhH,KAAKiQ,oBAAoB,IAAIrQ,MAAM,4CAA4C,EAGnFI,KAAKyN,YAAYxE,iBAAiB,cAAe9E,IAC7C,MAAMmK,EAAYnK,EAClBnE,KAAKmK,SAAWmE,aAAA,EAAAA,EAAU+B,YAE1BrQ,KAAKuO,sBACJ1E,MAAK,IAAWiC,UAAA9L,UAAA,OAAA,GAAA,YACb,IAAIsQ,EAAU,EACd,KAAOtQ,KAAKuQ,0BAA4BD,EAAU,GAC9CA,UAMMtQ,KAAKuO,qBAEnB,MAAG1E,MAAK,KACJ,IAAK,IAAI2G,KAAKxQ,KAAKiO,gBACfuC,EAAEb,UAIN3P,KAAKiO,gBAAkB,GACvBjO,KAAK6N,kBAAoB,EACzBiC,aAAa9P,KAAKyQ,oBAClBX,aAAa9P,KAAK+P,iBAAiB,IACpCR,OAAOC,IACNxP,KAAKmK,SAAW,GAChBnK,KAAKiQ,oBAAoBT,EAAI,GAC/B,GAET,CAEO,sBAAAe,GACJ,MAAMG,EAAe1Q,KAAKqP,gCAC1B,GAAIqB,EAAajM,QAAUzE,KAAK2N,eAAelJ,OAC3C,OAAO,EAGX,IAAK,MAAMkM,KAAKD,EACZ,IAAK1Q,KAAK2N,eAAezM,SAASyP,GAC9B,OAAO,EAIf,OAAO,CACV,CAEO,mBAAAV,CAAoBT,GAIxB,GAHAM,aAAa9P,KAAK+P,kBAClBD,aAAa9P,KAAKyQ,qBAIZzQ,KAAKmK,WAAanK,KAAK6N,mBAEzB7N,KAAK6N,kBAAoB7N,KAAK8N,qBAChC,CACE,IAAK,IAAI0C,KAAKxQ,KAAKiO,gBACfuC,EAAEZ,OAAO,IAAIjQ,oBAAoB6P,IAIrC,OAFAxP,KAAKiO,gBAAkB,QACvBjO,KAAK6O,YAER,CAGD7O,KAAK6O,YAAW,GAChB,MAAM+B,EAAU5Q,KAAKgO,6BAA6BhO,KAAK6N,oBAAsB7N,KAAKgO,6BAA6BhO,KAAKgO,6BAA6BvJ,OAAS,GAC1JzE,KAAK6N,oBACL7N,KAAKyQ,mBAAqBT,YAAW,KACjChQ,KAAK6P,aAAa,GACnBe,EACN,CAEO,UAAA/B,CAAWgC,GAAgB,SAS/B,GARAf,aAAa9P,KAAK+P,kBAClBD,aAAa9P,KAAKyQ,oBAClBzQ,KAAKyP,iCACLzP,KAAKmJ,OAAO2H,cAAc9Q,KAAKsP,6BACb,QAAlBzO,EAAAb,KAAKyN,mBAAa,IAAA5M,GAAAA,EAAAkQ,QAClB/Q,KAAKyN,YAAc,KACnBzN,KAAKmK,SAAW,IAEX0G,EAAe,CAChB7Q,KAAK6N,kBAAoB,EAOzB,IAAK,IAAI2C,KAAKxQ,KAAKiO,gBACfuC,EAAEb,UAEN3P,KAAKiO,gBAAkB,EAC1B,CACJ,ECxVC,MAAO+C,sBAAsBxG,YAG/B,WAAA3K,CAAYsJ,EAAgB8H,GACxBlR,MAAMoJ,GAENnJ,KAAKiR,mBAAqBA,CAC7B,CAKD,gBAAIhG,GACA,OAAOjL,KAAKkR,mBAAqB,UACpC,CAKD,sBAAIA,GACA,MAAO,oBAAsB5N,mBAAmBtD,KAAKiR,mBACxD,CAWK,YAAAE,CAA8BC,EAAkBtJ,oDAElD,OADAwE,QAAQC,KAAK,qHACNvM,KAAKmJ,OAAOkI,SAASlD,UAAUnO,KAAKiR,mBAAqB,IAAMG,EAAUtJ,KACnF,CAsBK,SAAAqG,CACFmD,EACAxJ,oDAEA,GAA+B,mBAApBwJ,EAEP,OADAhF,QAAQC,KAAK,mGACNvM,KAAKmJ,OAAOkI,SAASlD,UAAUnO,KAAKiR,mBAAoBK,GAGnE,IAAKxJ,EACD,MAAM,IAAIlI,MAAM,kCAGpB,GAAwB,KAApB0R,EACA,MAAM,IAAI1R,MAAM,kBAGpB,IAAIwO,EAAQpO,KAAKiR,mBAKjB,MAJwB,MAApBK,IACAlD,GAAU,IAAMkD,GAGbtR,KAAKmJ,OAAOkI,SAASlD,UAAUC,EAAOtG,KAChD,CASK,WAAA4G,CAAYN,oDAEd,MAAc,MAAVA,EACOpO,KAAKmJ,OAAOkI,SAAS3C,YAAY1O,KAAKiR,oBAI7C7C,EACOpO,KAAKmJ,OAAOkI,SAAS3C,YAAY1O,KAAKiR,mBAAqB,IAAM7C,GAIrEpO,KAAKmJ,OAAOkI,SAASvC,oBAAoB9O,KAAKiR,sBACxD,CAkBD,WAAAxG,CAA6B8G,EAA+C/P,GACxE,GAA6B,iBAAlB+P,EACP,OAAOxR,MAAM0K,YAAe8G,EAAgB/P,GAGhD,MAAMgQ,EAASlR,OAAOc,OAAO,CAAA,EAAImQ,EAAgB/P,GAEjD,OAAOzB,MAAM0K,YAAe+G,EAC/B,CAKD,OAAA3G,CAAyBC,EAAO,EAAGC,EAAU,GAAIvJ,GAC7C,OAAOzB,MAAM8K,QAAWC,EAAMC,EAASvJ,EAC1C,CAKD,gBAAA6J,CAAkCC,EAAgB9J,GAC9C,OAAOzB,MAAMsL,iBAAoBC,EAAQ9J,EAC5C,CAKD,MAAAkK,CAAwBjE,EAAYjG,GAChC,OAAOzB,MAAM2L,OAAUjE,EAAIjG,EAC9B,CAKD,MAAAmK,CAAwBlC,EAA0CjI,GAC9D,OAAOzB,MAAM4L,OAAUlC,EAAYjI,EACtC,CAQD,MAAAgI,CAAwB/B,EAAYgC,EAA0CjI,GAC1E,OAAOzB,MAAMyJ,OAAoB/B,EAAIgC,EAAYjI,GAASqI,MAAMuB,cAY5D,OAT+B,UAA3BpL,KAAKmJ,OAAOsD,UAAUnH,aAAK,IAAAzE,OAAA,EAAAA,EAAE4G,OAAO2D,eAAAA,EAAM3D,MAET,QAA7BzG,EAAAhB,KAAKmJ,OAAOsD,UAAUnH,aAAO,IAAAtE,OAAA,EAAAA,EAAA0L,gBAAiB1M,KAAKiR,qBACxB,QAA3BlQ,EAAAf,KAAKmJ,OAAOsD,UAAUnH,aAAK,IAAAvE,OAAA,EAAAA,EAAE0Q,kBAAmBzR,KAAKiR,oBAGzDjR,KAAKmJ,OAAOsD,UAAUxG,KAAKjG,KAAKmJ,OAAOsD,UAAUhJ,MAAO2H,GAGrDA,CAAgB,GAE9B,CAQD,OAAO3D,EAAYjG,GACf,OAAOzB,MAAM4M,OAAOlF,EAAIjG,GAASqI,MAAM+C,cAanC,OAXIA,IAE2B,QAA3B/L,EAAAb,KAAKmJ,OAAOsD,UAAUnH,aAAK,IAAAzE,OAAA,EAAAA,EAAE4G,MAAOA,IAEH,QAA7BzG,EAAAhB,KAAKmJ,OAAOsD,UAAUnH,aAAO,IAAAtE,OAAA,EAAAA,EAAA0L,gBAAiB1M,KAAKiR,qBACxB,QAA3BlQ,EAAAf,KAAKmJ,OAAOsD,UAAUnH,aAAK,IAAAvE,OAAA,EAAAA,EAAE0Q,kBAAmBzR,KAAKiR,oBAGzDjR,KAAKmJ,OAAOsD,UAAUtG,QAGnByG,CAAO,GAErB,CASS,YAAAC,CAA8B3B,GACpC,MAAMwG,EAAS1R,KAAKyG,QAAOyE,eAAAA,EAAcwG,SAAU,CAAE,GAIrD,OAFA1R,KAAKmJ,OAAOsD,UAAUxG,KAAKiF,eAAAA,EAAczH,MAAOiO,GAEzCpR,OAAOc,OAAO,CAAE,EAAE8J,EAAc,CAEnCzH,OAAUyH,eAAAA,EAAczH,QAAS,GACjCiO,OAAUA,GAEjB,CAKD,eAAAC,CAAgBnQ,GAKZ,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,gBAAiB1P,GAC9DqI,MAAMqB,GACI5K,OAAOc,OAAO,CAAE,EAAE8J,EAAc,CAEnC0G,oBAAsB1G,aAAA,EAAAA,EAAc0G,kBACpCC,iBAAsB3G,aAAA,EAAAA,EAAc2G,eACpCC,cAAoB7K,MAAMC,QAAQgE,aAAY,EAAZA,EAAc4G,eAAiB5G,aAAY,EAAZA,EAAc4G,cAAgB,MAG9G,CAkBD,gBAAA/E,CAAkCgF,EAAyB/E,EAAkBZ,EAAqBpB,GAC9F,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJuD,SAAY8E,EACZ/E,SAAYA,IAWpB,OAPAxL,EAAUyK,2BACN,mKACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,sBAAuB1P,GACpEqI,MAAMpJ,GAAST,KAAK6M,aAAgBpM,IAC5C,CAoCD,kBAAAuR,CACIC,EACAxG,EACAyG,EACAC,EACAC,EACAhG,EACApB,GAEA,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJuI,SAAgBA,EAChBxG,KAAgBA,EAChByG,aAAgBA,EAChBC,YAAgBA,EAChBC,WAAgBA,IAWxB,OAPA5Q,EAAUyK,2BACN,yOACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,oBAAqB1P,GAClEqI,MAAMpJ,GAAST,KAAK6M,aAAgBpM,IAC5C,CAmDK,cAAA4R,IAAmCC,oDAErC,GAAIA,EAAK7N,OAAS,GAA0B,iBAAd6N,aAAI,EAAJA,EAAO,IAEjC,OADAhG,QAAQC,KAAK,4PACNvM,KAAKgS,oBACRM,aAAI,EAAJA,EAAO,KAAM,IACbA,aAAI,EAAJA,EAAO,KAAM,IACbA,eAAAA,EAAO,KAAM,IACbA,aAAA,EAAAA,EAAO,KAAM,IACbA,aAAA,EAAAA,EAAO,KAAM,CAAA,GACbA,aAAI,EAAJA,EAAO,KAAM,CAAE,GACfA,aAAI,EAAJA,EAAO,KAAM,CAAA,GAIrB,MAAMC,GAASD,aAAA,EAAAA,EAAO,KAAM,CAAA,EAItBL,SAFoBjS,KAAK2R,mBAEFG,cAAcU,MAAMhC,GAAMA,EAAE7P,OAAS4R,EAAON,WACzE,IAAKA,EACD,MAAM,IAAItS,oBAAoB,IAAIC,MAAM,gCAAgC2S,EAAON,eAGnF,MAAME,EAAcnS,KAAKmJ,OAAOgH,SAAS,wBAGnCkB,EAAW,IAAI7D,gBAAgBxN,KAAKmJ,QAM1C,IAAIsJ,EAAiC,KAKrC,SAASC,UACLD,SAAAA,EAAmB1B,QACnBM,EAAS3C,aACZ,CAED,OATK6D,EAAOI,cACRF,EAAoBG,sBAAiB7L,IAQlC,IAAI2I,SAAQ,CAAOC,EAASC,IAAU9D,UAAA9L,UAAA,OAAA,GAAA,kBACzC,UACUqR,EAASlD,UAAU,WAAkBhK,GAAK2H,UAAA9L,UAAA,OAAA,GAAA,YAC5C,MAAM6S,EAAWxB,EAASlH,SAE1B,IACI,IAAKhG,EAAE2O,OAASD,IAAa1O,EAAE2O,MAC3B,MAAM,IAAIlT,MAAM,iCAIpB,MAAM4B,EAAUlB,OAAOc,OAAO,CAAE,EAAEmR,UAC3B/Q,EAAQyQ,gBACRzQ,EAAQuR,cACRvR,EAAQ4Q,kBACR5Q,EAAQmR,YAEf,MAAMK,QAAiBhT,KAAKgS,mBACxBC,EAAStR,KACTwD,EAAEsH,KACFwG,EAASC,aACTC,EACAI,EAAOH,WACP5Q,GAGJmO,EAAQqD,EACX,CAAC,MAAOxD,GACLI,EAAO,IAAIjQ,oBAAoB6P,GAClC,CAEDkD,SACH,MAED,MAAMO,EAAqC,CACvCH,MAASzB,EAASlH,WAEL,UAAboI,EAAOQ,cAAM,IAAAlS,OAAA,EAAAA,EAAE4D,UACfwO,EAAoB,MAAIV,EAAOQ,OAAO/O,KAAK,MAG/C,MAAM/D,EAAMD,KAAKkT,oBAAoBjB,EAASkB,QAAUhB,EAAac,GAErE,IAAIN,EAAcJ,EAAOI,aAAe,SAAU1S,GAC1CwS,EACDA,EAAkBW,SAASC,KAAOpT,EAIjCwS,EAAoBG,iBAAiB3S,EAE7C,QAEM0S,EAAY1S,EACrB,CAAC,MAAOuP,GACLkD,UACA9C,EAAO,IAAIjQ,oBAAoB6P,GAClC,CACJ,QACJ,CAgBD,WAAArC,CAA6Bf,EAAqBpB,GAC9C,IAAIxJ,EAAe,CACf8H,OAAU,QAUd,OAPA9H,EAAUyK,2BACN,2GACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,gBAAiB1P,GAC9DqI,MAAMpJ,GAAST,KAAK6M,aAAgBpM,IAC5C,CAaD,oBAAA2M,CAAqB1F,EAAe0E,EAAqBpB,GACrD,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJhC,MAASA,IAWjB,OAPAlG,EAAUyK,2BACN,2IACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,0BAA2B1P,GAASqI,MAAK,KAAM,GACpG,CAwBD,oBAAAwD,CACIiG,EACAtG,EACAO,EACAnB,EACApB,GAEA,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJjG,MAAmB6P,EACnBtG,SAAmBA,EACnBO,gBAAmBA,IAW3B,OAPA/L,EAAUyK,2BACN,iMACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,0BAA2B1P,GACxEqI,MAAK,KAAM,GACnB,CAaD,mBAAA0J,CAAoB7L,EAAe0E,EAAqBpB,GACpD,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJhC,MAASA,IAWjB,OAPAlG,EAAUyK,2BACN,yIACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,wBAAyB1P,GACtEqI,MAAK,KAAM,GACnB,CAaD,mBAAA2J,CAAoBC,EAA2BrH,EAAqBpB,GAChE,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJjG,MAASgQ,IAWjB,OAPAjS,EAAUyK,2BACN,yIACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,wBAAyB1P,GACtEqI,MAAK,KAAM,GACnB,CAaD,kBAAA6J,CAAmBC,EAAkBvH,EAAqBpB,GACtD,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJiK,SAAYA,IAWpB,OAPAnS,EAAUyK,2BACN,6IACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,wBAAyB1P,GACtEqI,MAAK,KAAM,GACnB,CAcD,kBAAA+J,CAAmBC,EAA0B7G,EAAkBZ,EAAqBpB,GAChF,IAAIxJ,EAAe,CACf8H,OAAU,OACVI,KAAQ,CACJjG,MAAYoQ,EACZ7G,SAAYA,IAWpB,OAPAxL,EAAUyK,2BACN,2JACAzK,EACA4K,EACApB,GAGGhL,KAAKmJ,OAAOI,KAAKvJ,KAAKkR,mBAAqB,wBAAyB1P,GACtEqI,MAAK,KAAM,GACnB,CAKD,iBAAAiK,CAAkB1C,EAAkB5P,GAKhC,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,IAAM3H,mBAAmB8N,GAAY,kBAAmB5P,EACvG,CAKD,kBAAAuS,CAAmB3C,EAAkBa,EAAkBzQ,GAKnD,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,UACX9H,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,IAAM3H,mBAAmB8N,GAAY,mBAAqB9N,mBAAmB2O,GAAWzQ,GAC/HqI,MAAK,KAAM,GACnB,CAQO,mBAAAqJ,CAAoBjT,EAAagT,EAAqC,IAC1E,IAAIe,EAAU/T,EACV+K,EAAQ,GAEO/K,EAAImD,QAAQ,MACb,IACd4Q,EAAU/T,EAAIgU,UAAU,EAAGhU,EAAImD,QAAQ,MACvC4H,EAAQ/K,EAAIgU,UAAUhU,EAAImD,QAAQ,KAAO,IAG7C,MAAM8Q,EAAwC,CAAA,EAGxCC,EAAYnJ,EAAMrH,MAAM,KAC9B,IAAK,MAAMyQ,KAASD,EAAW,CAC3B,GAAa,IAATC,EACA,SAGJ,MAAMC,EAAOD,EAAMzQ,MAAM,KACzBuQ,EAAa7Q,mBAAmBgR,EAAK,GAAG7P,QAAQ,MAAM,OAASnB,oBAAoBgR,EAAK,IAAM,IAAI7P,QAAQ,MAAM,KACnH,CAGD,IAAK,IAAI8B,KAAO2M,EACPA,EAAaqB,eAAehO,KAIR,MAArB2M,EAAa3M,UACN4N,EAAa5N,GAEpB4N,EAAa5N,GAAO2M,EAAa3M,IAKzC0E,EAAQ,GACR,IAAK,IAAI1E,KAAO4N,EACPA,EAAaI,eAAehO,KAIpB,IAAT0E,IACAA,GAAS,KAGbA,GAAS1H,mBAAmBgD,EAAI9B,QAAQ,OAAO,MAAQ,IAAMlB,mBAAmB4Q,EAAa5N,GAAK9B,QAAQ,OAAO,OAGrH,MAAgB,IAATwG,EAAegJ,EAAU,IAAMhJ,EAASgJ,CAClD,EAGL,SAASpB,iBAAiB3S,GACtB,GAAsB,oBAAXyI,UAAiC,OAANA,aAAA,IAAAA,YAAA,EAAAA,OAAQ6L,MAC1C,MAAM,IAAI5U,oBAAoB,IAAIC,MAAM,0EAG5C,IAAI4U,EAAS,KACTC,EAAS,IAETC,EAAehM,OAAOiM,WACtBC,EAAelM,OAAOmM,YAG1BL,EAASA,EAAQE,EAAcA,EAAcF,EAC7CC,EAASA,EAASG,EAAeA,EAAeH,EAEhD,IAAIK,EAAQJ,EAAc,EAAMF,EAAQ,EACpCO,EAAQH,EAAe,EAAMH,EAAS,EAI1C,OAAO/L,OAAO6L,KACVtU,EACA,eACA,SAASuU,EAAM,WAAWC,EAAO,QAAQM,EAAI,SAASD,EAAK,wBAEnE,CCl4BM,MAAOE,0BAA0BxK,YAInC,gBAAIS,GACA,MAAO,kBACV,CASK,MAAAgK,CACFC,EACAC,GAAyB,EACzB3T,oDAUA,OARAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,MACVI,KAAQ,CACJwL,YAAiBA,EACjBC,cAAiBA,IAEtB3T,GAEIxB,KAAKmJ,OAAOI,KAAKvJ,KAAKiL,aAAe,UAAWzJ,GAClDqI,MAAK,KAAM,MACnB,ECrBC,MAAOuL,mBAAmBlM,YAI5B,eAAAmM,CAAgBvK,EAAO,EAAGC,EAAU,GAAIvJ,GAQpC,OAPAA,EAAUlB,OAAOc,OAAO,CAACkI,OAAU,OAAQ9H,IAEnCwJ,MAAQ1K,OAAOc,OAAO,CAC1B0J,KAAWA,EACXC,QAAWA,GACZvJ,EAAQwJ,OAEJhL,KAAKmJ,OAAOI,KAAK,qBAAsB/H,EACjD,CAKD,UAAA8T,CAAW7N,EAAYjG,GAKnB,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,sBAAwBjG,mBAAmBmE,GAAKjG,EAC3E,CAKD,gBAAA+T,CAAiB/T,GAKb,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,2BAA4B/H,EACvD,ECvCC,MAAOgU,sBAAsBtM,YAI/B,KAAAuM,CAAMjU,GAKF,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,cAAe/H,EAC1C,EChBC,MAAOkU,oBAAoBxM,YAI7B,MAAAyM,CACIjE,EACAkE,EACAC,EAA2B,CAAA,GAE3B,IAAKD,KAAalE,aAAA,EAAAA,EAAQjK,IACtB,MAAO,GAGX,MAAMqO,EAAQ,GACdA,EAAM9N,KAAK,OACX8N,EAAM9N,KAAK,SACX8N,EAAM9N,KAAK1E,mBAAmBoO,EAAOhF,cAAgBgF,EAAOD,iBAC5DqE,EAAM9N,KAAK1E,mBAAmBoO,EAAOjK,KACrCqO,EAAM9N,KAAK1E,mBAAmBsS,IAE9B,IAAI7T,EAAS/B,KAAKmJ,OAAOgH,SAAS2F,EAAM9R,KAAK,MAE7C,GAAI1D,OAAOqF,KAAKkQ,GAAapR,OAAQ,EAEJ,IAAzBoR,EAAYE,iBACLF,EAAoB,SAG/B,MAAMrE,EAAS,IAAIwE,gBAAgBH,GAEnC9T,IAAWA,EAAOb,SAAS,KAAO,IAAM,KAAOsQ,CAClD,CAED,OAAOzP,CACV,CAKD,QAAAkU,CAASzU,GAKL,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,QACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,mBAAoB/H,GACvCqI,MAAMpJ,IAASA,eAAAA,EAAMgD,QAAS,IACtC,ECxCC,MAAOyS,sBAAsBhN,YAI/B,WAAAuB,CAAYjJ,GAKR,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,eAAgB/H,EAC3C,CAKD,MAAAmK,CAAOwK,EAAkB3U,GAQrB,OAPAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,OACVI,KAAU,CACN/I,KAAQwV,IAEb3U,GAEIxB,KAAKmJ,OAAOI,KAAK,eAAgB/H,GACnCqI,MAAK,KAAM,GACnB,CAKD,OAAOvD,EAAa9E,GAKhB,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,UACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,gBAAgBjG,mBAAmBgD,KAAQ9E,GAC9DqI,MAAK,KAAM,GACnB,CAKD,OAAAuM,CAAQ9P,EAAa9E,GAKjB,OAJAA,EAAUlB,OAAOc,OAAO,CACpBkI,OAAU,QACX9H,GAEIxB,KAAKmJ,OAAOI,KAAK,gBAAgBjG,mBAAmBgD,aAAgB9E,GACtEqI,MAAK,KAAM,GACnB,CAQD,cAAAwM,CAAe5S,EAAe6C,GAC1B,OAAOtG,KAAKmJ,OAAOgH,SAAS,gBAAgB7M,mBAAmBgD,YAAchD,mBAAmBG,KACnG,ECrDL,MAAM6S,EAAuB,CACzB,aACA,aACA,cACA,QACA,UACA,OACA,QACA,SAEA,QACA,cACA,UACA,YACA,YACA,SACA,OACA,WACA,WACA,iBACA,SACA,iBAYU,MAAOC,OAyGjB,WAAA1W,CACI2W,EAAU,IACV/J,EACAgK,EAAO,SAPHzW,KAAiB0W,kBAAuC,GACxD1W,KAAc2W,eAAqC,GACnD3W,KAAsB4W,wBAAY,EAOtC5W,KAAKwW,QAAYA,EACjBxW,KAAKyW,KAAYA,EACjBzW,KAAKyM,UAAYA,GAAa,IAAItE,eAGlCnI,KAAK6W,OAAc,IAAIrK,aAAaxM,MACpCA,KAAKkV,YAAc,IAAIF,kBAAkBhV,MACzCA,KAAK8W,MAAc,IAAIpB,YAAY1V,MACnCA,KAAK+W,KAAc,IAAI3B,WAAWpV,MAClCA,KAAKgX,SAAc,IAAI5N,gBAAgBpJ,MACvCA,KAAKqR,SAAc,IAAI7D,gBAAgBxN,MACvCA,KAAKiX,OAAc,IAAIzB,cAAcxV,MACrCA,KAAKkX,QAAc,IAAIhB,cAAclW,KACxC,CAQD,UAAAmX,CAAWC,GAKP,OAJKpX,KAAK2W,eAAeS,KACrBpX,KAAK2W,eAAeS,GAAY,IAAIpG,cAAchR,KAAMoX,IAGrDpX,KAAK2W,eAAeS,EAC9B,CAKD,gBAAAC,CAAiBC,GAGb,OAFAtX,KAAK4W,yBAA2BU,EAEzBtX,IACV,CAKD,aAAA8Q,CAAcvF,GAMV,OALIvL,KAAK0W,kBAAkBnL,KACvBvL,KAAK0W,kBAAkBnL,GAAYgM,eAC5BvX,KAAK0W,kBAAkBnL,IAG3BvL,IACV,CAKD,iBAAAwX,GACI,IAAK,IAAIC,KAAKzX,KAAK0W,kBACf1W,KAAK0W,kBAAkBe,GAAGF,QAK9B,OAFAvX,KAAK0W,kBAAoB,GAElB1W,IACV,CAKD,UAAA0X,CACIhG,EACAkE,EACAC,EAA2B,CAAA,GAE3B,OAAO7V,KAAK8W,MAAMnB,OAAOjE,EAAQkE,EAAUC,EAC9C,CAKD,QAAA1F,CAAS7N,SACL,IAAIrC,EAAMD,KAAKwW,QA2Bf,MAvBsB,oBAAX9N,SACLA,OAAO0K,UACRnT,EAAIgP,WAAW,aACfhP,EAAIgP,WAAW,aAEhBhP,GAA4B,QAAtBY,EAAA6H,OAAO0K,SAASuE,cAAM,IAAA9W,OAAA,EAAAA,EAAE+W,SAAS,MACnClP,OAAO0K,SAASuE,OAAO1D,UAAU,EAAGvL,OAAO0K,SAASuE,OAAOlT,OAAS,GACnEiE,OAAO0K,SAASuE,QAAU,GAE1B3X,KAAKwW,QAAQvH,WAAW,OACzBhP,GAAOyI,OAAO0K,SAASyE,UAAY,IACnC5X,GAAOA,EAAI2X,SAAS,KAAO,GAAK,KAGpC3X,GAAOD,KAAKwW,SAIZlU,IACArC,GAAOA,EAAI2X,SAAS,KAAO,GAAK,IAChC3X,GAAOqC,EAAK2M,WAAW,KAAO3M,EAAK2R,UAAU,GAAK3R,GAG/CrC,CACV,CAKK,IAAAsJ,CAAcjH,EAAcd,oDAC9BA,EAAUxB,KAAK8X,gBAAgBxV,EAAMd,GAGrC,IAAIvB,EAAMD,KAAKmQ,SAAS7N,GAGxB,QAA6B,IAAlBd,EAAQwJ,MAAuB,CACtC,MAAMA,EAAQhL,KAAK+X,qBAAqBvW,EAAQwJ,OAC5CA,IACA/K,IAAQA,EAAIiB,SAAS,KAAO,IAAM,KAAO8J,UAEtCxJ,EAAQwJ,KAClB,CAED,GAAIhL,KAAKgY,WAAY,CACjB,MAAMjW,EAASzB,OAAOc,OAAO,CAAE,QAAQpB,KAAKgY,WAAW/X,EAAKuB,SAClC,IAAfO,EAAO9B,UAAiD,IAAnB8B,EAAOP,SACnDvB,EAAM8B,EAAO9B,KAAOA,EACpBuB,EAAUO,EAAOP,SAAWA,GACrBlB,OAAOqF,KAAK5D,GAAQ0C,SAE3BjD,EAAUO,GACH,OAAPuK,cAAO,IAAPA,aAAO,EAAPA,QAASC,OAAQD,QAAQC,KAAK,8GAErC,CAIsD,oBAAnDvM,KAAKiY,UAAUzW,EAAQ0W,QAAS,iBAChC1W,EAAQkI,MAAgC,iBAAjBlI,EAAQkI,OAE/BlI,EAAQkI,KAAOzF,KAAKoD,UAAU7F,EAAQkI,OAM1C,OAHkBlI,EAAQ2W,OAASA,OAGlBlY,EAAKuB,GACjBqI,MAAY1J,GAAY2L,UAAA9L,UAAA,OAAA,GAAA,YACrB,IAAIS,EAAa,CAAA,EAEjB,IACIA,QAAaN,EAASiY,MACzB,CAAC,MAAOpR,GAGR,CAMD,GAJIhH,KAAKqY,YACL5X,QAAaT,KAAKqY,UAAUlY,EAAUM,IAGtCN,EAASD,QAAU,IACnB,MAAM,IAAIP,oBAAoB,CAC1BM,IAAUE,EAASF,IACnBC,OAAUC,EAASD,OACnBO,KAAUA,IAIlB,OAAOA,OACR8O,OAAOC,IAEN,MAAM,IAAI7P,oBAAoB6P,EAAI,MAE7C,CASO,eAAAsI,CAAgBxV,EAAcd,IAClCA,EAAUlB,OAAOc,OAAO,CAAEkI,OAAQ,OAAwB9H,IAClDwJ,MAAQxJ,EAAQwJ,OAAS,CAAA,EAGjCxJ,EAAQkI,KAAO1J,KAAKsY,0BAA0B9W,EAAQkI,MAGtD,IAAK,IAAIpD,KAAO9E,EACR8U,EAAqBpV,SAASoF,KAIlC9E,EAAQwJ,MAAM1E,GAAO9E,EAAQ8E,UACrB9E,EAAQ8E,IAmDpB,GA9CA9E,EAAQwJ,MAAQ1K,OAAOc,OAAO,CAAA,EAAII,EAAQgQ,OAAQhQ,EAAQwJ,YACxB,IAAvBxJ,EAAQ+J,cACa,IAAxB/J,EAAQ+W,cAAuD,IAA9B/W,EAAQwJ,MAAMuN,YAC/C/W,EAAQ+J,WAAa,MACd/J,EAAQgX,YAAchX,EAAQwJ,MAAMwN,cAC3ChX,EAAQ+J,WAAa/J,EAAQgX,YAAchX,EAAQwJ,MAAMwN,oBAI1DhX,EAAQ+W,mBACR/W,EAAQwJ,MAAMuN,mBACd/W,EAAQgX,kBACRhX,EAAQwJ,MAAMwN,WAMmC,OAApDxY,KAAKiY,UAAUzW,EAAQ0W,QAAS,iBAC/BlY,KAAKyY,WAAWjX,EAAQkI,QAEzBlI,EAAQ0W,QAAU5X,OAAOc,OAAO,CAAE,EAAEI,EAAQ0W,QAAS,CACjD,eAAgB,sBAKmC,OAAvDlY,KAAKiY,UAAUzW,EAAQ0W,QAAS,qBAChC1W,EAAQ0W,QAAU5X,OAAOc,OAAO,CAAE,EAAEI,EAAQ0W,QAAS,CACjD,kBAAmBlY,KAAKyW,QAO5BzW,KAAKyM,UAAUhJ,OAEuC,OAArDzD,KAAKiY,UAAUzW,EAAQ0W,QAAS,mBAEjC1W,EAAQ0W,QAAU5X,OAAOc,OAAO,CAAE,EAAEI,EAAQ0W,QAAS,CACjDQ,cAAiB1Y,KAAKyM,UAAUhJ,SAKpCzD,KAAK4W,wBAAiD,OAAvBpV,EAAQ+J,WAAqB,CAC5D,MAAMA,EAAa/J,EAAQ+J,aAAgB/J,EAAQ8H,QAAU,OAAShH,SAE/Dd,EAAQ+J,WAGfvL,KAAK8Q,cAAcvF,GAEnB,MAAMoN,EAAa,IAAIC,gBACvB5Y,KAAK0W,kBAAkBnL,GAAcoN,EACrCnX,EAAQqX,OAASF,EAAWE,MAC/B,CAED,OAAOrX,CACV,CAMO,yBAAA8W,CAA0B5O,GAC9B,GACwB,oBAAboP,eACS,IAATpP,GACS,iBAATA,GACE,OAATA,GACA1J,KAAKyY,WAAW/O,KACf1J,KAAK+Y,aAAarP,GAEnB,OAAOA,EAGX,MAAMsP,EAAO,IAAIF,SAEjB,IAAK,IAAIxS,KAAOoD,EACZsP,EAAKC,OAAO3S,EAAKoD,EAAKpD,IAG1B,OAAO0S,CACV,CAKO,YAAAD,CAAarP,GACjB,IAAK,IAAIpD,KAAOoD,EAAM,CAClB,MAAMwP,EAASjS,MAAMC,QAAQwC,EAAKpD,IAAQoD,EAAKpD,GAAO,CAACoD,EAAKpD,IAC5D,IAAK,IAAI6S,KAAKD,EACV,GACqB,oBAAT3R,MAAwB4R,aAAa5R,MAC5B,oBAAT6R,MAAwBD,aAAaC,KAE7C,OAAO,CAGlB,CAED,OAAO,CACV,CAMO,SAAAnB,CAAUC,EAA0CvX,GACxDuX,EAAUA,GAAW,GACrBvX,EAAOA,EAAKsC,cAEZ,IAAK,IAAIqD,KAAO4R,EACZ,GAAI5R,EAAIrD,eAAiBtC,EACrB,OAAOuX,EAAQ5R,GAIvB,OAAO,IACV,CAKO,UAAAmS,CAAW/O,GACf,OAAOA,IAIuB,aAA1BA,EAAK7J,YAAYc,MAII,oBAAbmY,UAA4BpP,aAAgBoP,SAE3D,CAKO,oBAAAf,CAAqBvG,GACzB,MAAMzP,EAAwB,GAC9B,IAAK,MAAMuE,KAAOkL,EAAQ,CACtB,GAAoB,OAAhBA,EAAOlL,GAEP,SAGJ,MAAMxE,EAAQ0P,EAAOlL,GACf+S,EAAa/V,mBAAmBgD,GAEtC,GAAIW,MAAMC,QAAQpF,GAEd,IAAK,MAAMqX,KAAKrX,EACZC,EAAOiG,KAAKqR,EAAa,IAAM/V,mBAAmB6V,SAE/CrX,aAAiBa,KACxBZ,EAAOiG,KAAKqR,EAAa,IAAM/V,mBAAmBxB,EAAMwX,gBAChC,cAAVxX,GAAmC,iBAAVA,EACvCC,EAAOiG,KAAKqR,EAAa,IAAM/V,mBAAmBW,KAAKoD,UAAUvF,KAEjEC,EAAOiG,KAAKqR,EAAa,IAAM/V,mBAAmBxB,GAEzD,CAED,OAAOC,EAAOiC,KAAK,IACtB"} \ No newline at end of file diff --git a/package.json b/package.json index 44e8fb1..0ef4809 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.17.0", + "version": "0.17.1", "name": "pocketbase", "description": "PocketBase JavaScript SDK", "author": "Gani Georgiev",