@iglo.tech/iglo.base 0.0.0-stage → 1.0.1-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/LICENSE +18 -0
- package/README.md +778 -2
- package/dist/iglo-base.es.mjs +4 -0
- package/dist/iglo-base.es.mjs.map +34 -0
- package/dist/ssr-astro.es.mjs +4 -0
- package/dist/ssr-astro.es.mjs.map +12 -0
- package/dist/ssr-browser-client.es.mjs +4 -0
- package/dist/ssr-browser-client.es.mjs.map +13 -0
- package/dist/ssr-browser.es.mjs +4 -0
- package/dist/ssr-browser.es.mjs.map +10 -0
- package/dist/ssr-next.es.mjs +4 -0
- package/dist/ssr-next.es.mjs.map +12 -0
- package/dist/ssr-nuxt.es.mjs +4 -0
- package/dist/ssr-nuxt.es.mjs.map +12 -0
- package/dist/ssr-react-router.es.mjs +4 -0
- package/dist/ssr-react-router.es.mjs.map +12 -0
- package/dist/ssr-sveltekit.es.mjs +4 -0
- package/dist/ssr-sveltekit.es.mjs.map +12 -0
- package/dist/ssr.es.mjs +4 -0
- package/dist/ssr.es.mjs.map +22 -0
- package/dist/types/src/Client.d.ts +233 -0
- package/dist/types/src/ClientResponseError.d.ts +22 -0
- package/dist/types/src/index.d.ts +18 -0
- package/dist/types/src/services/BackupService.d.ts +59 -0
- package/dist/types/src/services/BaseService.d.ts +8 -0
- package/dist/types/src/services/BatchService.d.ts +56 -0
- package/dist/types/src/services/CollectionService.d.ts +47 -0
- package/dist/types/src/services/CronService.d.ts +20 -0
- package/dist/types/src/services/CrudService.d.ts +85 -0
- package/dist/types/src/services/FileService.d.ts +19 -0
- package/dist/types/src/services/HealthService.d.ts +16 -0
- package/dist/types/src/services/LogService.d.ts +35 -0
- package/dist/types/src/services/RealtimeService.d.ts +124 -0
- package/dist/types/src/services/RecordService.d.ts +374 -0
- package/dist/types/src/services/SQLService.d.ts +21 -0
- package/dist/types/src/services/SettingsService.d.ts +46 -0
- package/dist/types/src/ssr/adapter.d.ts +133 -0
- package/dist/types/src/ssr/astro.d.ts +27 -0
- package/dist/types/src/ssr/browser-client.d.ts +100 -0
- package/dist/types/src/ssr/browser-token.d.ts +29 -0
- package/dist/types/src/ssr/browser.d.ts +1 -0
- package/dist/types/src/ssr/cache.d.ts +9 -0
- package/dist/types/src/ssr/cookies.d.ts +68 -0
- package/dist/types/src/ssr/csrf.d.ts +38 -0
- package/dist/types/src/ssr/index.d.ts +12 -0
- package/dist/types/src/ssr/next.d.ts +53 -0
- package/dist/types/src/ssr/no-store-fetch.d.ts +7 -0
- package/dist/types/src/ssr/nuxt.d.ts +41 -0
- package/dist/types/src/ssr/oauth2.d.ts +56 -0
- package/dist/types/src/ssr/popup.d.ts +14 -0
- package/dist/types/src/ssr/react-router.d.ts +53 -0
- package/dist/types/src/ssr/renew.d.ts +25 -0
- package/dist/types/src/ssr/server-client.d.ts +83 -0
- package/dist/types/src/ssr/superuser-client.d.ts +24 -0
- package/dist/types/src/ssr/sveltekit.d.ts +44 -0
- package/dist/types/src/ssr/types.d.ts +118 -0
- package/dist/types/src/stores/AsyncAuthStore.d.ts +52 -0
- package/dist/types/src/stores/BaseAuthStore.d.ts +104 -0
- package/dist/types/src/stores/LocalAuthStore.d.ts +48 -0
- package/dist/types/src/tools/cookie.d.ts +31 -0
- package/dist/types/src/tools/dtos.d.ts +122 -0
- package/dist/types/src/tools/formdata.d.ts +30 -0
- package/dist/types/src/tools/jwt.d.ts +14 -0
- package/dist/types/src/tools/legacy.d.ts +2 -0
- package/dist/types/src/tools/loose.d.ts +5 -0
- package/dist/types/src/tools/options.d.ts +91 -0
- package/dist/types/src/tools/refresh.d.ts +3 -0
- package/package.json +73 -4
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
class ClientResponseError extends Error{constructor(errData){super("ClientResponseError");if(this.url="",this.status=0,this.response={},this.isAbort=!1,this.originalError=null,Object.setPrototypeOf(this,ClientResponseError.prototype),errData!==null&&typeof errData==="object"){let err=errData;if(this.originalError=err.originalError,this.url=typeof err.url==="string"?err.url:"",this.status=typeof err.status==="number"?err.status:0,this.isAbort=!!err.isAbort||err.name==="AbortError"||err.message==="Aborted",err.response!==null&&typeof err.response==="object")this.response=err.response;else if(err.data!==null&&typeof err.data==="object")this.response=err.data;else this.response={}}if(!this.originalError&&!(errData instanceof ClientResponseError))this.originalError=errData;if(this.name="ClientResponseError "+this.status,this.message=this.response?.message,!this.message)if(this.isAbort)this.message="The request was aborted (most likely autocancelled; you can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation).";else if(this.originalError?.cause?.message?.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).";else this.message="Something went wrong.";this.cause=this.originalError}get data(){return this.response}toJSON(){return{...this}}}var fieldContentRegExp=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function cookieParse(str,options){let result={};if(typeof str!=="string")return result;let decode=Object.assign({},options||{}).decode||defaultDecode,index=0;while(index<str.length){let eqIdx=str.indexOf("=",index);if(eqIdx===-1)break;let endIdx=str.indexOf(";",index);if(endIdx===-1)endIdx=str.length;else if(endIdx<eqIdx){index=str.lastIndexOf(";",eqIdx-1)+1;continue}let key=str.slice(index,eqIdx).trim();if(result[key]===void 0){let val=str.slice(eqIdx+1,endIdx).trim();if(val.charCodeAt(0)===34)val=val.slice(1,-1);try{result[key]=decode(val)}catch{result[key]=val}}index=endIdx+1}return result}function cookieSerialize(name,val,options){let opt=Object.assign({},options||{}),encode=opt.encode||defaultEncode;if(!fieldContentRegExp.test(name))throw TypeError("argument name is invalid");let value=encode(val);if(value&&!fieldContentRegExp.test(value))throw TypeError("argument val is invalid");let result=name+"="+value;if(opt.maxAge!=null){let maxAge=opt.maxAge-0;if(isNaN(maxAge)||!isFinite(maxAge))throw TypeError("option maxAge is invalid");result+="; Max-Age="+Math.floor(maxAge)}if(opt.domain){if(!fieldContentRegExp.test(opt.domain))throw TypeError("option domain is invalid");result+="; Domain="+opt.domain}if(opt.path){if(!fieldContentRegExp.test(opt.path))throw TypeError("option path is invalid");result+="; Path="+opt.path}if(opt.expires){if(!isDate(opt.expires)||isNaN(opt.expires.valueOf()))throw TypeError("option expires is invalid");result+="; Expires="+opt.expires.toUTCString()}if(opt.httpOnly)result+="; HttpOnly";if(opt.secure)result+="; Secure";if(opt.priority)switch(typeof opt.priority==="string"?opt.priority.toLowerCase():opt.priority){case"low":result+="; Priority=Low";break;case"medium":result+="; Priority=Medium";break;case"high":result+="; Priority=High";break;default:throw TypeError("option priority is invalid")}if(opt.sameSite)switch(typeof opt.sameSite==="string"?opt.sameSite.toLowerCase():opt.sameSite){case!0:result+="; SameSite=Strict";break;case"lax":result+="; SameSite=Lax";break;case"strict":result+="; SameSite=Strict";break;case"none":result+="; SameSite=None";break;default:throw TypeError("option sameSite is invalid")}return result}function defaultDecode(val){return val.indexOf("%")!==-1?decodeURIComponent(val):val}function defaultEncode(val){return encodeURIComponent(val)}function isDate(val){return Object.prototype.toString.call(val)==="[object Date]"||val instanceof Date}var isReactNative=typeof navigator<"u"&&navigator.product==="ReactNative"||typeof global<"u"&&global.HermesInternal,atobPolyfill;if(typeof atob==="function"&&!isReactNative)atobPolyfill=atob;else atobPolyfill=(input)=>{let str=String(input).replace(/=+$/,"");if(str.length%4==1)throw Error("'atob' failed: The string to be decoded is not correctly encoded.");for(var bc=0,bs,buffer,idx=0,output="";buffer=str.charAt(idx++);~buffer&&(bs=bc%4?bs*64+buffer:buffer,bc++%4)?output+=String.fromCharCode(255&bs>>(-2*bc&6)):0)buffer="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".indexOf(buffer);return output};function getTokenPayload(token){if(token)try{let encodedPayload=decodeURIComponent(atobPolyfill(token.split(".")[1]).split("").map(function(c){return"%"+("00"+c.charCodeAt(0).toString(16)).slice(-2)}).join(""));return JSON.parse(encodedPayload)||{}}catch{}return{}}function isTokenExpired(token,expirationThreshold=0){let payload=getTokenPayload(token);if(Object.keys(payload).length>0&&(!payload.exp||payload.exp-expirationThreshold>Date.now()/1000))return!1;return!0}var defaultCookieKey="pb_auth";class BaseAuthStore{constructor(){this.baseToken="",this.baseModel=null,this._onChangeCallbacks=[]}get token(){return this.baseToken}get record(){return this.baseModel}get model(){return this.baseModel}get isValid(){return!isTokenExpired(this.token)}get isSuperuser(){let payload=getTokenPayload(this.token);return payload.type=="auth"&&(this.record?.collectionName=="_superusers"||!this.record?.collectionName&&payload.collectionId=="pbc_3142635823")}get isAdmin(){return console.warn("Please replace pb.authStore.isAdmin with pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName"),this.isSuperuser}get isAuthRecord(){return console.warn("Please replace pb.authStore.isAuthRecord with !pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName"),getTokenPayload(this.token).type=="auth"&&!this.isSuperuser}save(token,record){this.baseToken=token||"",this.baseModel=record||null,this.triggerChange()}clear(){this.baseToken="",this.baseModel=null,this.triggerChange()}loadFromCookie(cookie,key=defaultCookieKey){let rawData=cookieParse(cookie||"")[key]||"",data={};try{let parsed=JSON.parse(rawData);if(parsed===null||typeof parsed!=="object"||Array.isArray(parsed))data={};else data=parsed}catch{}let token=typeof data.token==="string"?data.token:"",recordOrModel=data.record||data.model||null;this.save(token,recordOrModel)}exportToCookie(options,key=defaultCookieKey){let defaultOptions={secure:!0,sameSite:!0,httpOnly:!0,path:"/"},payload=getTokenPayload(this.token);if(payload?.exp)defaultOptions.expires=new Date(payload.exp*1000);else defaultOptions.expires=new Date("1970-01-01");options=Object.assign({},defaultOptions,options);let rawData={token:this.token,record:this.record?JSON.parse(JSON.stringify(this.record)):null},result=cookieSerialize(key,JSON.stringify(rawData),options),resultLength=typeof Blob<"u"?new Blob([result]).size:result.length;if(rawData.record&&resultLength>4096){rawData.record={id:rawData.record?.id,email:rawData.record?.email};let extraProps=["collectionId","collectionName","verified"];for(let prop in this.record)if(extraProps.includes(prop))rawData.record[prop]=this.record[prop];result=cookieSerialize(key,JSON.stringify(rawData),options)}return result}onChange(callback,fireImmediately=!1){if(this._onChangeCallbacks.push(callback),fireImmediately)callback(this.token,this.record);return()=>{for(let i=this._onChangeCallbacks.length-1;i>=0;i--)if(this._onChangeCallbacks[i]==callback){delete this._onChangeCallbacks[i],this._onChangeCallbacks.splice(i,1);return}}}triggerChange(){for(let callback of this._onChangeCallbacks)callback&&callback(this.token,this.record)}}class LocalAuthStore extends BaseAuthStore{constructor(storageKey="pocketbase_auth"){super();this.storageFallback={},this.storageKey=storageKey,this._bindStorageEvent()}get token(){return(this._storageGet(this.storageKey)||{}).token||""}get record(){let data=this._storageGet(this.storageKey)||{};return data.record||data.model||null}get model(){return this.record}save(token,record){this._storageSet(this.storageKey,{token,record}),super.save(token,record)}clear(){this._storageRemove(this.storageKey),super.clear()}_storageGet(key){if(typeof window<"u"&&window?.localStorage){let rawValue=window.localStorage.getItem(key)||"";try{return JSON.parse(rawValue)}catch{return rawValue}}return this.storageFallback[key]}_storageSet(key,value){if(typeof window<"u"&&window?.localStorage){let normalizedVal=value;if(typeof value!=="string")normalizedVal=JSON.stringify(value);window.localStorage.setItem(key,normalizedVal)}else this.storageFallback[key]=value}_storageRemove(key){if(typeof window<"u"&&window?.localStorage)window.localStorage?.removeItem(key);delete this.storageFallback[key]}_bindStorageEvent(){if(typeof window>"u"||!window?.localStorage||!window.addEventListener)return;window.addEventListener("storage",(e)=>{if(e.key!=this.storageKey)return;let data=this._storageGet(this.storageKey)||{};super.save(data.token||"",data.record||data.model||null)})}}class BaseService{constructor(client){this.client=client}}var knownSendOptionsKeys=["requestKey","$cancelKey","$autoCancel","fetch","headers","body","query","params","cache","credentials","headers","integrity","keepalive","method","mode","redirect","referrer","referrerPolicy","signal","window"];function normalizeUnknownQueryParams(options){if(!options)return;options.query=options.query||{};for(let key in options){if(knownSendOptionsKeys.includes(key))continue;options.query[key]=options[key],delete options[key]}}function serializeQueryParams(params){let result=[];for(let key in params){let encodedKey=encodeURIComponent(key),arrValue=Array.isArray(params[key])?params[key]:[params[key]];for(let v of arrValue){if(v=prepareQueryParamValue(v),v===null)continue;result.push(encodedKey+"="+v)}}return result.join("&")}function prepareQueryParamValue(value){if(value===null||typeof value>"u")return null;if(value instanceof Date)return encodeURIComponent(value.toISOString().replace("T"," "));if(typeof value==="object")return encodeURIComponent(JSON.stringify(value));return encodeURIComponent(value)}class SettingsService extends BaseService{async getAll(options){return options=Object.assign({method:"GET"},options),this.client.send("/api/settings",options)}async update(bodyParams,options){return options=Object.assign({method:"PATCH",body:bodyParams},options),this.client.send("/api/settings",options)}async testS3(filesystem="storage",options){return options=Object.assign({method:"POST",body:{filesystem}},options),this.client.send("/api/settings/test/s3",options).then(()=>!0)}async testEmail(collectionIdOrName,toEmail,emailTemplate,options){return options=Object.assign({method:"POST",body:{email:toEmail,template:emailTemplate,collection:collectionIdOrName}},options),this.client.send("/api/settings/test/email",options).then(()=>!0)}async generateAppleClientSecret(clientId,teamId,keyId,privateKey,duration,options){return options=Object.assign({method:"POST",body:{clientId,teamId,keyId,privateKey,duration}},options),this.client.send("/api/settings/apple/generate-client-secret",options)}}class RealtimeService extends BaseService{constructor(){super(...arguments);this.clientId="",this.eventSource=null,this.subscriptions={},this.lastSentSubscriptions=[],this.maxConnectTimeout=15000,this.reconnectAttempts=0,this.maxReconnectAttempts=1/0,this.predefinedReconnectIntervals=[200,300,500,1000,1200,1500,2000],this.pendingConnects=[],this.pendingSubmits=[],this.isProcessingPendingSubmits=!1,this.connectionGeneration=0}get isConnected(){return!!this.eventSource&&!!this.clientId&&!this.pendingConnects.length}async subscribe(topic,callback,options){if(!topic)throw Error("topic must be set.");let key=topic;if(options){options=Object.assign({},options),normalizeUnknownQueryParams(options);let serialized="options="+encodeURIComponent(JSON.stringify({query:options.query,headers:options.headers}));key+=(key.includes("?")?"&":"?")+serialized}let listener=function(e){let msgEvent=e,data;try{data=JSON.parse(msgEvent?.data)}catch{}callback(data||{})};if(!this.subscriptions[key])this.subscriptions[key]=[];if(this.subscriptions[key].push(listener),!this.isConnected)await this.connect();else if(this.subscriptions[key].length===1)await this.submitSubscriptions();else this.eventSource?.addEventListener(key,listener);return async()=>this.unsubscribeByTopicAndListener(topic,listener)}resubmit(){if(!this.clientId||!this.hasSubscriptionListeners())return Promise.resolve();return this.lastSentSubscriptions=[],this.submitSubscriptions()}reconnect(){if(!this.hasSubscriptionListeners())return this.disconnect(!1,!1),Promise.resolve();return this.disconnect(!0,!1),this.scheduleReconnect(),Promise.resolve()}async unsubscribe(topic){if(!topic)this.subscriptions={};else{let subs=this.getSubscriptionsByTopic(topic);for(let key in subs){if(!this.hasSubscriptionListeners(key))continue;for(let listener of this.subscriptions[key])this.eventSource?.removeEventListener(key,listener);delete this.subscriptions[key]}}await this.submitSubscriptions()}async unsubscribeByPrefix(keyPrefix){let hasAtleastOneTopic=!1;for(let key in this.subscriptions){if(!(key+"?").startsWith(keyPrefix))continue;hasAtleastOneTopic=!0;for(let listener of this.subscriptions[key])this.eventSource?.removeEventListener(key,listener);delete this.subscriptions[key]}if(!hasAtleastOneTopic)return;await this.submitSubscriptions()}async unsubscribeByTopicAndListener(topic,listener){let subs=this.getSubscriptionsByTopic(topic);for(let key in subs){if(!Array.isArray(this.subscriptions[key])||!this.subscriptions[key].length)continue;let exist=!1;for(let i=this.subscriptions[key].length-1;i>=0;i--){if(this.subscriptions[key][i]!==listener)continue;exist=!0,delete this.subscriptions[key][i],this.subscriptions[key].splice(i,1),this.eventSource?.removeEventListener(key,listener)}if(!exist)continue;if(!this.subscriptions[key].length)delete this.subscriptions[key]}await this.submitSubscriptions()}hasSubscriptionListeners(keyToCheck){if(this.subscriptions=this.subscriptions||{},keyToCheck)return!!this.subscriptions[keyToCheck]?.length;for(let key in this.subscriptions)if(this.subscriptions[key]?.length)return!0;return!1}async submitSubscriptions(){return new Promise((resolve,reject)=>{if(this.pendingSubmits.push({resolve,reject}),this.pendingSubmits.length==1)queueMicrotask(()=>this.finalizePendingSubscriptions())})}async finalizePendingSubscriptions(){if(this.isProcessingPendingSubmits||!this.pendingSubmits.length)return;let pending=this.pendingSubmits.slice();this.pendingSubmits=[],this.isProcessingPendingSubmits=!0;try{await this.sendSubscriptions();for(let p of pending)p.resolve()}catch(err){for(let p of pending)err?p.reject(err):p.resolve()}finally{if(this.isProcessingPendingSubmits=!1,this.pendingSubmits.length>0)await this.finalizePendingSubscriptions()}}getSubscriptionsCancelKey(){return"realtime_"+this.clientId}getSubscriptionsByTopic(topic){let result={};topic=topic.includes("?")?topic:topic+"?";for(let key in this.subscriptions)if((key+"?").startsWith(topic))result[key]=this.subscriptions[key];return result}getNonEmptySubscriptionKeys(){let result=[];for(let key in this.subscriptions)if(this.subscriptions[key].length)result.push(key);return result}hasUnsentSubscriptions(){let latestTopics=this.getNonEmptySubscriptionKeys();if(latestTopics.length!=this.lastSentSubscriptions.length)return!0;for(let t of latestTopics)if(!this.lastSentSubscriptions.includes(t))return!0;return!1}async sendSubscriptions(){if(!this.clientId)return;if(!this.hasSubscriptionListeners())return this.disconnect();if(!this.hasUnsentSubscriptions())return;return this.addAllSubscriptionListeners(),this.lastSentSubscriptions=this.getNonEmptySubscriptionKeys(),this.client.send("/api/realtime",{method:"POST",body:{clientId:this.clientId,subscriptions:this.lastSentSubscriptions},requestKey:this.getSubscriptionsCancelKey()}).catch((err)=>{if(err?.isAbort)return;throw err})}addAllSubscriptionListeners(){if(!this.eventSource)return;this.removeAllSubscriptionListeners();for(let key in this.subscriptions)for(let listener of this.subscriptions[key])this.eventSource.addEventListener(key,listener)}removeAllSubscriptionListeners(){if(!this.eventSource)return;for(let key in this.subscriptions)for(let listener of this.subscriptions[key])this.eventSource.removeEventListener(key,listener)}async connect(){if(this.reconnectAttempts>0)return;return new Promise((resolve,reject)=>{if(this.pendingConnects.push({resolve,reject}),this.pendingConnects.length==1)queueMicrotask(()=>this.initConnect())})}initConnect(){this.disconnect(!0);let generation=this.connectionGeneration,isCurrent=()=>generation===this.connectionGeneration;clearTimeout(this.connectTimeoutId),this.connectTimeoutId=setTimeout(()=>{if(isCurrent())this.connectErrorHandler(Error("EventSource connect took too long."))},this.maxConnectTimeout),this.eventSource=new EventSource(this.client.buildURL("/api/realtime")),this.eventSource.onerror=()=>{if(isCurrent())this.connectErrorHandler(Error("Failed to establish realtime connection."))},this.eventSource.addEventListener("PB_CONNECT",(e)=>{if(!isCurrent())return;let msgEvent=e;this.clientId=msgEvent?.lastEventId,this.lastSentSubscriptions=[],this.submitSubscriptions().then(async()=>{let maxResubmit=3;while(isCurrent()&&this.hasUnsentSubscriptions()&&maxResubmit>0)maxResubmit--,await this.submitSubscriptions();if(!isCurrent())return;for(let p of this.pendingConnects)p.resolve();this.pendingConnects=[],this.reconnectAttempts=0,clearTimeout(this.reconnectTimeoutId),clearTimeout(this.connectTimeoutId);let connectSubs=this.getSubscriptionsByTopic("PB_CONNECT");for(let key in connectSubs)for(let listener of connectSubs[key])listener(e);if(isCurrent()&&this.hasUnsentSubscriptions())await this.submitSubscriptions()}).catch((err)=>{if(!isCurrent())return;this.clientId="",this.lastSentSubscriptions=[],this.connectErrorHandler(err)})})}connectErrorHandler(err){if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),!this.clientId&&!this.reconnectAttempts||this.reconnectAttempts>this.maxReconnectAttempts){for(let p of this.pendingConnects)p.reject(new ClientResponseError(err));this.pendingConnects=[],this.disconnect();return}this.disconnect(!0),this.scheduleReconnect()}scheduleReconnect(){let timeout=this.predefinedReconnectIntervals[this.reconnectAttempts]||this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length-1];this.reconnectAttempts++;let generation=this.connectionGeneration;this.reconnectTimeoutId=setTimeout(()=>{if(generation===this.connectionGeneration)this.initConnect()},timeout)}disconnect(fromReconnect=!1,notify=!0){if(this.connectionGeneration++,notify&&this.clientId&&this.onDisconnect)this.onDisconnect(Object.keys(this.subscriptions));if(clearTimeout(this.connectTimeoutId),clearTimeout(this.reconnectTimeoutId),this.removeAllSubscriptionListeners(),this.client.cancelRequest(this.getSubscriptionsCancelKey()),this.eventSource?.close(),this.eventSource=null,this.clientId="",this.lastSentSubscriptions=[],!fromReconnect){this.reconnectAttempts=0;for(let p of this.pendingConnects)p.resolve();this.pendingConnects=[]}}}class CrudService extends BaseService{decode(data){return data}async getFullList(batchOrqueryParams,options){if(typeof batchOrqueryParams=="number")return this._getFullList(batchOrqueryParams,options);options=Object.assign({},batchOrqueryParams,options);let batch=1000;if(options.batch)batch=options.batch,delete options.batch;return this._getFullList(batch,options)}async getList(page=1,perPage=30,options){return options=Object.assign({method:"GET"},options),options.query=Object.assign({page,perPage},options.query),this.client.send(this.baseCrudPath,options).then((responseData)=>(responseData.items=responseData.items?.map((item)=>this.decode(item))||[],responseData))}async getFirstListItem(filter,options){return options=Object.assign({requestKey:"one_by_filter_"+this.baseCrudPath+"_"+filter},options),options.query=Object.assign({filter,skipTotal:1},options.query),this.getList(1,1,options).then((result)=>{if(!result?.items?.length)throw new ClientResponseError({status:404,response:{code:404,message:"The requested resource wasn't found.",data:{}}});return result.items[0]})}async getOne(id,options){if(!id)throw new ClientResponseError({url:this.client.buildURL(this.baseCrudPath+"/"),status:404,response:{code:404,message:"Missing required record id.",data:{}}});return options=Object.assign({method:"GET"},options),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(id),options).then((responseData)=>this.decode(responseData))}async create(bodyParams,options){return options=Object.assign({method:"POST",body:bodyParams},options),this.client.send(this.baseCrudPath,options).then((responseData)=>this.decode(responseData))}async update(id,bodyParams,options){return options=Object.assign({method:"PATCH",body:bodyParams},options),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(id),options).then((responseData)=>this.decode(responseData))}async delete(id,options){return options=Object.assign({method:"DELETE"},options),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(id),options).then(()=>!0)}_getFullList(batchSize=1000,options){options=options||{},options.query=Object.assign({skipTotal:1},options.query);let result=[],request=async(page)=>this.getList(page,batchSize||1000,options).then((list)=>{let items=list.items;if(result=result.concat(items),items.length==list.perPage)return request(page+1);return result});return request(1)}}function normalizeLegacyOptionsArgs(legacyWarn,baseOptions,bodyOrOptions,query){let hasBodyOrOptions=typeof bodyOrOptions<"u",hasQuery=typeof query<"u";if(!hasQuery&&!hasBodyOrOptions)return baseOptions;if(hasQuery)return console.warn(legacyWarn),baseOptions.body=Object.assign({},baseOptions.body,bodyOrOptions),baseOptions.query=Object.assign({},baseOptions.query,query),baseOptions;return Object.assign(baseOptions,bodyOrOptions)}function resetAutoRefresh(client){client._resetAutoRefresh?.()}function registerAutoRefresh(client,threshold,refreshFunc,reauthenticateFunc){resetAutoRefresh(client);let oldBeforeSend=client.beforeSend,oldModel=client.authStore.record,unsubStoreChange=client.authStore.onChange((newToken,model)=>{if(!newToken||model?.id!=oldModel?.id||(model?.collectionId||oldModel?.collectionId)&&model?.collectionId!=oldModel?.collectionId)resetAutoRefresh(client)});client._resetAutoRefresh=function(){unsubStoreChange(),client.beforeSend=oldBeforeSend,delete client._resetAutoRefresh},client.beforeSend=async(url,sendOptions)=>{let oldToken=client.authStore.token;if(sendOptions.query?.autoRefresh)return oldBeforeSend?oldBeforeSend(url,sendOptions):{url,sendOptions};let isValid=client.authStore.isValid;if(isValid&&isTokenExpired(client.authStore.token,threshold))try{await refreshFunc()}catch{isValid=!1}if(!isValid)await reauthenticateFunc();let headers=sendOptions.headers||{};for(let key in headers)if(key.toLowerCase()=="authorization"&&oldToken==headers[key]&&client.authStore.token){headers[key]=client.authStore.token;break}return sendOptions.headers=headers,oldBeforeSend?oldBeforeSend(url,sendOptions):{url,sendOptions}}}class RecordService extends CrudService{constructor(client,collectionIdOrName){super(client);this.collectionIdOrName=collectionIdOrName}get baseCrudPath(){return this.baseCollectionPath+"/records"}get baseCollectionPath(){return"/api/collections/"+encodeURIComponent(this.collectionIdOrName)}get isSuperusers(){return this.collectionIdOrName=="_superusers"||this.collectionIdOrName=="_pbc_2773867675"}async subscribe(topic,callback,options){if(!topic)throw Error("Missing topic.");if(!callback)throw Error("Missing subscription callback.");return this.client.realtime.subscribe(this.collectionIdOrName+"/"+topic,callback,options)}async unsubscribe(topic){if(topic)return this.client.realtime.unsubscribe(this.collectionIdOrName+"/"+topic);return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName)}async getFullList(batchOrOptions,options){if(typeof batchOrOptions=="number")return super.getFullList(batchOrOptions,options);let params=Object.assign({},batchOrOptions,options);return super.getFullList(params)}async getList(page=1,perPage=30,options){return super.getList(page,perPage,options)}async getFirstListItem(filter,options){return super.getFirstListItem(filter,options)}async getOne(id,options){return super.getOne(id,options)}async create(bodyParams,options){return super.create(bodyParams,options)}async update(id,bodyParams,options){return super.update(id,bodyParams,options).then((item)=>{if(this.client.authStore.record?.id===item?.id&&(this.client.authStore.record?.collectionId===this.collectionIdOrName||this.client.authStore.record?.collectionName===this.collectionIdOrName)){let authExpand=Object.assign({},this.client.authStore.record.expand),authRecord=Object.assign({},this.client.authStore.record,item);if(authExpand)authRecord.expand=Object.assign(authExpand,item.expand);this.client.authStore.save(this.client.authStore.token,authRecord)}return item})}async delete(id,options){return super.delete(id,options).then((success)=>{if(success&&this.client.authStore.record?.id===id&&(this.client.authStore.record?.collectionId===this.collectionIdOrName||this.client.authStore.record?.collectionName===this.collectionIdOrName))this.client.authStore.clear();return success})}authResponse(responseData){let record=this.decode(responseData?.record||{});return this.client.authStore.save(responseData?.token,record),Object.assign({},responseData,{token:responseData?.token||"",record})}async listAuthMethods(options){return options=Object.assign({method:"GET",fields:"mfa,otp,password,oauth2"},options),this.client.send(this.baseCollectionPath+"/auth-methods",options)}async authWithPassword(usernameOrEmail,password,options){options=Object.assign({method:"POST",body:{identity:usernameOrEmail,password}},options);let autoRefreshThreshold;if(this.isSuperusers){if(autoRefreshThreshold=options.autoRefreshThreshold,delete options.autoRefreshThreshold,!options.autoRefresh)resetAutoRefresh(this.client)}let authData=await this.client.send(this.baseCollectionPath+"/auth-with-password",options);if(authData=this.authResponse(authData),autoRefreshThreshold&&this.isSuperusers)registerAutoRefresh(this.client,autoRefreshThreshold,()=>this.authRefresh({autoRefresh:!0}),()=>this.authWithPassword(usernameOrEmail,password,Object.assign({autoRefresh:!0},options)));return authData}async authWithOAuth2Code(provider,code,codeVerifier,redirectURL,createData,bodyOrOptions,query){let options={method:"POST",body:{provider,code,codeVerifier,redirectURL,createData}};return options=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?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/auth-with-oauth2",options).then((data)=>this.authResponse(data))}authWithOAuth2(...args){if(args.length>1||typeof args?.[0]==="string"){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.");let legacyArgs=args;return this.authWithOAuth2Code(legacyArgs[0]||"",legacyArgs[1]||"",legacyArgs[2]||"",legacyArgs[3]||"",legacyArgs[4]||{},legacyArgs[5]||{},legacyArgs[6]||{})}let config=args[0]||{},eagerDefaultPopup=null;if(!config.urlCallback)eagerDefaultPopup=openBrowserPopup(void 0);let realtime=new RealtimeService(this.client);function cleanup(){eagerDefaultPopup?.close(),realtime.unsubscribe()}let requestKeyOptions={},requestKey=config.requestKey;if(requestKey)requestKeyOptions.requestKey=requestKey;return this.listAuthMethods(requestKeyOptions).then((authMethods)=>{let provider=authMethods.oauth2.providers.find((p)=>p.name===config.provider);if(!provider)throw new ClientResponseError(Error(`Missing or invalid provider "${config.provider}".`));let redirectURL=this.client.buildURL("/api/oauth2-redirect");return new Promise(async(resolve,reject)=>{let cancelController=requestKey?this.client.cancelControllers?.[requestKey]:void 0;if(cancelController)cancelController.signal.onabort=()=>{cleanup(),reject(new ClientResponseError({isAbort:!0,message:"manually cancelled"}))};realtime.onDisconnect=(activeSubscriptions)=>{if(activeSubscriptions.length&&reject)cleanup(),reject(new ClientResponseError(Error("realtime connection interrupted")))};try{await realtime.subscribe("@oauth2",async(e)=>{let oldState=realtime.clientId;try{if(!e.state||oldState!==e.state)throw Error("State parameters don't match.");if(e.error||!e.code)throw Error("OAuth2 redirect error or missing code: "+e.error);let options=Object.assign({},config);if(delete options.provider,delete options.scopes,delete options.createData,delete options.urlCallback,cancelController?.signal?.onabort)cancelController.signal.onabort=null;let authData=await this.authWithOAuth2Code(provider.name,e.code,provider.codeVerifier,redirectURL,config.createData,options);resolve(authData)}catch(err){reject(new ClientResponseError(err))}cleanup()});let replacements={state:realtime.clientId};if(config.scopes?.length)replacements.scope=config.scopes.join(" ");let url=this._replaceQueryParams(provider.authURL+redirectURL,replacements);await(config.urlCallback||function(url){if(eagerDefaultPopup)eagerDefaultPopup.location.href=url;else eagerDefaultPopup=openBrowserPopup(url)})(url)}catch(err){if(cancelController?.signal?.onabort)cancelController.signal.onabort=null;cleanup(),reject(new ClientResponseError(err))}})}).catch((err)=>{throw cleanup(),err})}async authRefresh(bodyOrOptions,query){let options={method:"POST"};return options=normalizeLegacyOptionsArgs("This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/auth-refresh",options).then((data)=>this.authResponse(data))}async requestPasswordReset(email,bodyOrOptions,query){let options={method:"POST",body:{email}};return options=normalizeLegacyOptionsArgs("This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/request-password-reset",options).then(()=>!0)}async confirmPasswordReset(passwordResetToken,password,passwordConfirm,bodyOrOptions,query){let options={method:"POST",body:{token:passwordResetToken,password,passwordConfirm}};return options=normalizeLegacyOptionsArgs("This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/confirm-password-reset",options).then(()=>!0)}async requestVerification(email,bodyOrOptions,query){let options={method:"POST",body:{email}};return options=normalizeLegacyOptionsArgs("This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/request-verification",options).then(()=>!0)}async confirmVerification(verificationToken,bodyOrOptions,query){let options={method:"POST",body:{token:verificationToken}};return options=normalizeLegacyOptionsArgs("This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/confirm-verification",options).then(()=>{let payload=getTokenPayload(verificationToken),model=this.client.authStore.record;if(model&&!model.verified&&model.id===payload.id&&model.collectionId===payload.collectionId)model.verified=!0,this.client.authStore.save(this.client.authStore.token,model);return!0})}async requestEmailChange(newEmail,bodyOrOptions,query){let options={method:"POST",body:{newEmail}};return options=normalizeLegacyOptionsArgs("This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/request-email-change",options).then(()=>!0)}async confirmEmailChange(emailChangeToken,password,bodyOrOptions,query){let options={method:"POST",body:{token:emailChangeToken,password}};return options=normalizeLegacyOptionsArgs("This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).",options,bodyOrOptions,query),this.client.send(this.baseCollectionPath+"/confirm-email-change",options).then(()=>{let payload=getTokenPayload(emailChangeToken),model=this.client.authStore.record;if(model&&model.id===payload.id&&model.collectionId===payload.collectionId)this.client.authStore.clear();return!0})}async listExternalAuths(recordId,options){return this.client.collection("_externalAuths").getFullList(Object.assign({},options,{filter:this.client.filter("recordRef = {:id}",{id:recordId})}))}async unlinkExternalAuth(recordId,provider,options){let ea=await this.client.collection("_externalAuths").getFirstListItem(this.client.filter("recordRef = {:recordId} && provider = {:provider}",{recordId,provider}));return this.client.collection("_externalAuths").delete(ea.id,options).then(()=>!0)}async requestOTP(email,options){return options=Object.assign({method:"POST",body:{email}},options),this.client.send(this.baseCollectionPath+"/request-otp",options)}async authWithOTP(otpId,password,options){return options=Object.assign({method:"POST",body:{otpId,password}},options),this.client.send(this.baseCollectionPath+"/auth-with-otp",options).then((data)=>this.authResponse(data))}async impersonate(recordId,duration,options){if(options=Object.assign({method:"POST",body:{duration}},options),options.headers=options.headers||{},!options.headers.Authorization)options.headers.Authorization=this.client.authStore.token;let client=new Client(this.client.baseURL,new BaseAuthStore,this.client.lang),authData=await client.send(this.baseCollectionPath+"/impersonate/"+encodeURIComponent(recordId),options);return client.authStore.save(authData?.token,this.decode(authData?.record||{})),client}_replaceQueryParams(url,replacements={}){let urlPath=url,query="";if(url.indexOf("?")>=0)urlPath=url.substring(0,url.indexOf("?")),query=url.substring(url.indexOf("?")+1);let parsedParams={},rawParams=query.split("&");for(let param of rawParams){if(param=="")continue;let pair=param.split("=");parsedParams[decodeURIComponent(pair[0].replace(/\+/g," "))]=decodeURIComponent((pair[1]||"").replace(/\+/g," "))}for(let key in replacements){if(!replacements.hasOwnProperty(key))continue;if(replacements[key]==null)delete parsedParams[key];else parsedParams[key]=String(replacements[key])}query="";for(let key in parsedParams){if(!parsedParams.hasOwnProperty(key))continue;if(query!="")query+="&";query+=encodeURIComponent(key.replace(/%20/g,"+"))+"="+encodeURIComponent(parsedParams[key].replace(/%20/g,"+"))}return query!=""?urlPath+"?"+query:urlPath}}function openBrowserPopup(url){if(typeof window>"u"||!window?.open)throw new ClientResponseError(Error("Not in a browser context - please pass a custom urlCallback function."));let width=1024,height=768,{innerWidth:windowWidth,innerHeight:windowHeight}=window;width=width>windowWidth?windowWidth:width,height=height>windowHeight?windowHeight:height;let left=windowWidth/2-width/2,top=windowHeight/2-height/2;return window.open(url,"popup_window","width="+width+",height="+height+",top="+top+",left="+left+",resizable,menubar=no")}class CollectionService extends CrudService{get baseCrudPath(){return"/api/collections"}async import(collections,deleteMissing=!1,options){return options=Object.assign({method:"PUT",body:{collections,deleteMissing}},options),this.client.send(this.baseCrudPath+"/import",options).then(()=>!0)}async truncate(collectionIdOrName,options){return options=Object.assign({method:"DELETE"},options),this.client.send(this.baseCrudPath+"/"+encodeURIComponent(collectionIdOrName)+"/truncate",options).then(()=>!0)}async getScaffolds(options){return options=Object.assign({method:"GET"},options),this.client.send(this.baseCrudPath+"/meta/scaffolds",options)}async getAllOAuth2Providers(options){return options=Object.assign({method:"GET"},options),this.client.send(this.baseCrudPath+"/meta/oauth2-providers",options)}async dryRunViewQuery(query,options){return options=Object.assign({method:"POST",body:{query}},options),this.client.send(this.baseCrudPath+"/meta/dry-run-view",options)}}class LogService extends BaseService{async getList(page=1,perPage=30,options){return options=Object.assign({method:"GET"},options),options.query=Object.assign({page,perPage},options.query),this.client.send("/api/logs",options)}async getOne(id,options){if(!id)throw new ClientResponseError({url:this.client.buildURL("/api/logs/"),status:404,response:{code:404,message:"Missing required log id.",data:{}}});return options=Object.assign({method:"GET"},options),this.client.send("/api/logs/"+encodeURIComponent(id),options)}async getStats(options){return options=Object.assign({method:"GET"},options),this.client.send("/api/logs/stats",options)}async truncate(options){return options=Object.assign({method:"DELETE"},options),this.client.send("/api/logs",options).then(()=>!0)}}class HealthService extends BaseService{async check(options){return options=Object.assign({method:"GET"},options),this.client.send("/api/health",options)}}class FileService extends BaseService{getUrl(record,filename,queryParams={}){return console.warn("Please replace pb.files.getUrl() with pb.files.getURL()"),this.getURL(record,filename,queryParams)}getURL(record,filename,queryParams={}){if(!filename||!record?.id||!(record?.collectionId||record?.collectionName))return"";let parts=[];parts.push("api"),parts.push("files"),parts.push(encodeURIComponent(record.collectionId||record.collectionName)),parts.push(encodeURIComponent(record.id)),parts.push(encodeURIComponent(filename));let result=this.client.buildURL(parts.join("/"));if(queryParams.download===!1)delete queryParams.download;let params=serializeQueryParams(queryParams);if(params)result+=(result.includes("?")?"&":"?")+params;return result}async getToken(options){return options=Object.assign({method:"POST"},options),this.client.send("/api/files/token",options).then((data)=>data?.token||"")}}class BackupService extends BaseService{async getFullList(options){return options=Object.assign({method:"GET"},options),this.client.send("/api/backups",options)}async create(basename,options){return options=Object.assign({method:"POST",body:{name:basename}},options),this.client.send("/api/backups",options).then(()=>!0)}async upload(bodyParams,options){return options=Object.assign({method:"POST",body:bodyParams},options),this.client.send("/api/backups/upload",options).then(()=>!0)}async delete(key,options){return options=Object.assign({method:"DELETE"},options),this.client.send(`/api/backups/${encodeURIComponent(key)}`,options).then(()=>!0)}async restore(key,options){return options=Object.assign({method:"POST"},options),this.client.send(`/api/backups/${encodeURIComponent(key)}/restore`,options).then(()=>!0)}getDownloadUrl(token,key){return console.warn("Please replace pb.backups.getDownloadUrl() with pb.backups.getDownloadURL()"),this.getDownloadURL(token,key)}getDownloadURL(token,key){return this.client.buildURL(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`)}}class CronService extends BaseService{async getFullList(options){return options=Object.assign({method:"GET"},options),this.client.send("/api/crons",options)}async run(jobId,options){return options=Object.assign({method:"POST"},options),this.client.send(`/api/crons/${encodeURIComponent(jobId)}`,options).then(()=>!0)}}class SQLService extends BaseService{async run(query,options){return options=Object.assign({method:"POST",body:{query}},options),this.client.send("/api/sql",options)}}function isFile(val){return Boolean(typeof Blob<"u"&&val instanceof Blob||typeof File<"u"&&val instanceof File||val!==null&&typeof val==="object"&&val.uri&&(typeof navigator<"u"&&navigator.product==="ReactNative"||typeof global<"u"&&global.HermesInternal))}function isFormData(body){return body&&(body.constructor?.name==="FormData"||typeof FormData<"u"&&body instanceof FormData)}function hasFileField(body){if(typeof body!=="object"||body===null)return!1;let obj=body;for(let key in obj){let values=Array.isArray(obj[key])?obj[key]:[obj[key]];for(let v of values)if(isFile(v))return!0}return!1}function convertToFormDataIfNeeded(body){if(typeof FormData>"u"||typeof body>"u"||typeof body!=="object"||body===null||isFormData(body)||!hasFileField(body))return body;let form=new FormData,obj=body;for(let key in obj){let val=obj[key];if(typeof val>"u")continue;if(typeof val==="object"&&!hasFileField({data:val})){let payload={};payload[key]=val,form.append("@jsonPayload",JSON.stringify(payload))}else{let normalizedVal=Array.isArray(val)?val:[val];for(let v of normalizedVal)form.append(key,v)}}return form}function convertFormDataToObject(formData){let result={};return formData.forEach((v,k)=>{if(k==="@jsonPayload"&&typeof v=="string")try{let parsed=JSON.parse(v);if(typeof parsed==="object"&&parsed!==null)Object.assign(result,parsed)}catch(err){console.warn("@jsonPayload error:",err)}else if(typeof result[k]<"u"){if(!Array.isArray(result[k]))result[k]=[result[k]];result[k].push(inferFormDataValue(v))}else result[k]=inferFormDataValue(v)}),result}var inferNumberCharsRegex=/^[-.\d]+$/;function inferFormDataValue(value){if(typeof value!="string")return value;if(value=="true")return!0;if(value=="false")return!1;if((value[0]==="-"||value[0]>="0"&&value[0]<="9")&&inferNumberCharsRegex.test(value)){let num=+value;if(""+num===value)return num}return value}class BatchService extends BaseService{constructor(){super(...arguments);this.requests=[],this.subs={}}collection(collectionIdOrName){if(!this.subs[collectionIdOrName])this.subs[collectionIdOrName]=new SubBatchService(this.requests,collectionIdOrName);return this.subs[collectionIdOrName]}async send(options){let formData=new FormData,jsonData=[];for(let i=0;i<this.requests.length;i++){let req=this.requests[i];if(jsonData.push({method:req.method,url:req.url,headers:req.headers,body:req.json}),req.files)for(let key in req.files){let files=req.files[key]||[];for(let file of files)formData.append("requests."+i+"."+key,file)}}return formData.append("@jsonPayload",JSON.stringify({requests:jsonData})),options=Object.assign({method:"POST",body:formData},options),this.client.send("/api/batch",options)}}class SubBatchService{constructor(requests,collectionIdOrName){this.requests=[],this.requests=requests,this.collectionIdOrName=collectionIdOrName}upsert(bodyParams,options){options=Object.assign({body:bodyParams||{}},options);let request={method:"PUT",url:"/api/collections/"+encodeURIComponent(this.collectionIdOrName)+"/records"};this.prepareRequest(request,options),this.requests.push(request)}create(bodyParams,options){options=Object.assign({body:bodyParams||{}},options);let request={method:"POST",url:"/api/collections/"+encodeURIComponent(this.collectionIdOrName)+"/records"};this.prepareRequest(request,options),this.requests.push(request)}update(id,bodyParams,options){options=Object.assign({body:bodyParams||{}},options);let request={method:"PATCH",url:"/api/collections/"+encodeURIComponent(this.collectionIdOrName)+"/records/"+encodeURIComponent(id)};this.prepareRequest(request,options),this.requests.push(request)}delete(id,options){options=Object.assign({},options);let request={method:"DELETE",url:"/api/collections/"+encodeURIComponent(this.collectionIdOrName)+"/records/"+encodeURIComponent(id)};this.prepareRequest(request,options),this.requests.push(request)}prepareRequest(request,options){if(normalizeUnknownQueryParams(options),request.headers=options.headers,request.json={},request.files={},typeof options.query<"u"){let query=serializeQueryParams(options.query);if(query)request.url+=(request.url.includes("?")?"&":"?")+query}let body=options.body;if(isFormData(body))body=convertFormDataToObject(body);for(let key in body){let val=body[key];if(isFile(val))request.files[key]=request.files[key]||[],request.files[key].push(val);else if(Array.isArray(val)){let foundFiles=[],foundRegular=[];for(let v of val)if(isFile(v))foundFiles.push(v);else foundRegular.push(v);if(foundFiles.length>0&&foundFiles.length==val.length){request.files[key]=request.files[key]||[];for(let file of foundFiles)request.files[key].push(file)}else if(request.json[key]=foundRegular,foundFiles.length>0){let fileKey=key;if(!key.startsWith("+")&&!key.endsWith("+"))fileKey+="+";request.files[fileKey]=request.files[fileKey]||[];for(let file of foundFiles)request.files[fileKey].push(file)}}else request.json[key]=val}}}if(!RegExp.escape)RegExp.escape=function(str){return str.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")};class Client{get baseUrl(){return this.baseURL}set baseUrl(v){this.baseURL=v}constructor(baseURL="/",authStore,lang="en-US"){if(this.cancelControllers={},this.recordServices={},this.enableAutoCancellation=!0,this.baseURL=baseURL,this.lang=lang,authStore)this.authStore=authStore;else if(typeof window<"u"&&!!window.Deno)this.authStore=new BaseAuthStore;else this.authStore=new LocalAuthStore;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),this.crons=new CronService(this),this.sql=new SQLService(this)}get admins(){return this.collection("_superusers")}createBatch(){return new BatchService(this)}collection(idOrName){if(!this.recordServices[idOrName])this.recordServices[idOrName]=new RecordService(this,idOrName);return this.recordServices[idOrName]}autoCancellation(enable){return this.enableAutoCancellation=!!enable,this}cancelRequest(requestKey){if(this.cancelControllers[requestKey])this.cancelControllers[requestKey].abort(),delete this.cancelControllers[requestKey];return this}cancelAllRequests(){for(let k in this.cancelControllers)this.cancelControllers[k]?.abort();return this.cancelControllers={},this}filter(raw,params){if(!params)return raw;let paramsWithPlaceholders={};for(let k in params)paramsWithPlaceholders["{:"+k+"}"]=params[k];let pattern=Object.keys(paramsWithPlaceholders).map((k)=>RegExp.escape(k)).join("|");if(!pattern)return raw;function stringify(val){switch(typeof val){case"boolean":case"number":return""+val;case"string":return JSON.stringify(val);default:if(val==null)return"null";if(val instanceof Date)return JSON.stringify(val.toISOString().replace("T"," "));let stringified=JSON.stringify(val);if(stringified.startsWith("[")||stringified.startsWith("{"))return JSON.stringify(stringified);return stringified}}return raw.replace(new RegExp(pattern,"g"),(match)=>stringify(paramsWithPlaceholders[match]))}getFileUrl(record,filename,queryParams={}){return console.warn("Please replace pb.getFileUrl() with pb.files.getURL()"),this.files.getURL(record,filename,queryParams)}buildUrl(path){return console.warn("Please replace pb.buildUrl() with pb.buildURL()"),this.buildURL(path)}buildURL(path){let url=this.baseURL;if(typeof window<"u"&&!!window.location&&!url.startsWith("https://")&&!url.startsWith("http://")){if(url=window.location.origin?.endsWith("/")?window.location.origin.substring(0,window.location.origin.length-1):window.location.origin||"",!this.baseURL.startsWith("/"))url+=window.location.pathname||"/",url+=url.endsWith("/")?"":"/";url+=this.baseURL}if(path)url+=url.endsWith("/")?"":"/",url+=path.startsWith("/")?path.substring(1):path;return url}async send(path,options){options=this.initSendOptions(path,options);let url=this.buildURL(path);if(this.beforeSend){let result=Object.assign({},await this.beforeSend(url,options));if(typeof result.url<"u"||typeof result.options<"u")url=result.url||url,options=result.options||options;else if(Object.keys(result).length)options=result,console?.warn&&console.warn("Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.")}if(typeof options.query<"u"){let query=serializeQueryParams(options.query);if(query)url+=(url.includes("?")?"&":"?")+query;delete options.query}if(this.getHeader(options.headers,"Content-Type")=="application/json"&&options.body&&typeof options.body!=="string")options.body=JSON.stringify(options.body);return(options.fetch||fetch)(url,options).then(async(response)=>{let data={};try{data=await response.json()}catch(err){if(options.signal?.aborted||err?.name=="AbortError"||err?.message=="Aborted")throw err}if(this.afterSend)data=await this.afterSend(response,data,options);if(response.status>=400)throw new ClientResponseError({url:response.url,status:response.status,data});return data}).catch((err)=>{throw new ClientResponseError(err)})}initSendOptions(path,options){if(options=Object.assign({method:"GET"},options),options.body=convertToFormDataIfNeeded(options.body),normalizeUnknownQueryParams(options),options.query=Object.assign({},options.params,options.query),typeof options.requestKey>"u"){if(options.$autoCancel===!1||options.query.$autoCancel===!1)options.requestKey=null;else if(options.$cancelKey||options.query.$cancelKey)options.requestKey=options.$cancelKey||options.query.$cancelKey}if(delete options.$autoCancel,delete options.query.$autoCancel,delete options.$cancelKey,delete options.query.$cancelKey,this.getHeader(options.headers,"Content-Type")===null&&!isFormData(options.body))options.headers=Object.assign({},options.headers,{"Content-Type":"application/json"});if(this.getHeader(options.headers,"Accept-Language")===null)options.headers=Object.assign({},options.headers,{"Accept-Language":this.lang});if(this.authStore.token&&this.getHeader(options.headers,"Authorization")===null)options.headers=Object.assign({},options.headers,{Authorization:this.authStore.token});if(this.enableAutoCancellation&&options.requestKey!==null){let requestKey=options.requestKey||(options.method||"GET")+path;delete options.requestKey,this.cancelRequest(requestKey);let controller=new AbortController;this.cancelControllers[requestKey]=controller,options.signal=controller.signal}return options}getHeader(headers,name){headers=headers||{},name=name.toLowerCase();for(let key in headers)if(key.toLowerCase()==name)return headers[key];return null}}class AsyncAuthStore extends BaseAuthStore{constructor(config){super();this.queue=[],this.saveFunc=config.save,this.clearFunc=config.clear,this._enqueue(()=>this._loadInitial(config.initial))}save(token,record){super.save(token,record);let value="";try{value=JSON.stringify({token,record})}catch{console.warn("AsyncAuthStore: failed to stringify the new state")}this._enqueue(()=>this.saveFunc(value))}clear(){if(super.clear(),this.clearFunc)this._enqueue(()=>this.clearFunc());else this._enqueue(()=>this.saveFunc(""))}async _loadInitial(payload){try{let resolved=await payload;if(resolved){let parsed;if(typeof resolved==="string"){let json=JSON.parse(resolved);if(typeof json==="object"&&json!==null)parsed=json;else parsed={}}else if(typeof resolved==="object"&&resolved!==null)parsed=resolved;let token=typeof parsed.token==="string"?parsed.token:"",recordOrModel=parsed.record||parsed.model||null;this.save(token,recordOrModel)}}catch{}}_enqueue(asyncCallback){if(this.queue.push(asyncCallback),this.queue.length==1)this._dequeue()}_dequeue(){if(!this.queue.length)return;this.queue[0]().finally(()=>{if(this.queue.shift(),!this.queue.length)return;this._dequeue()})}}var src_default=Client;export{AsyncAuthStore,BaseAuthStore,BatchService,ClientResponseError,CollectionService,CrudService,HealthService,LocalAuthStore,LogService,RealtimeService,RecordService,SubBatchService,cookieParse,cookieSerialize,src_default as default,getTokenPayload,isTokenExpired,normalizeUnknownQueryParams,serializeQueryParams};
|
|
2
|
+
|
|
3
|
+
//# debugId=7619569752442DB464756E2164756E21
|
|
4
|
+
//# sourceMappingURL=iglo-base.es.mjs.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": [".js/src/ClientResponseError.js", ".js/src/tools/cookie.js", ".js/src/tools/jwt.js", ".js/src/stores/BaseAuthStore.js", ".js/src/stores/LocalAuthStore.js", ".js/src/services/BaseService.js", ".js/src/tools/options.js", ".js/src/services/SettingsService.js", ".js/src/services/RealtimeService.js", ".js/src/services/CrudService.js", ".js/src/tools/legacy.js", ".js/src/tools/refresh.js", ".js/src/services/RecordService.js", ".js/src/services/CollectionService.js", ".js/src/services/LogService.js", ".js/src/services/HealthService.js", ".js/src/services/FileService.js", ".js/src/services/BackupService.js", ".js/src/services/CronService.js", ".js/src/services/SQLService.js", ".js/src/tools/formdata.js", ".js/src/services/BatchService.js", ".js/src/Client.js", ".js/src/stores/AsyncAuthStore.js", ".js/src/index.js"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\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 constructor(errData) {\n super(\"ClientResponseError\");\n this.url = \"\";\n this.status = 0;\n this.response = {};\n this.isAbort = false;\n this.originalError = null;\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 if (errData !== null && typeof errData === \"object\") {\n const err = errData;\n this.originalError = err.originalError;\n this.url = typeof err.url === \"string\" ? err.url : \"\";\n this.status = typeof err.status === \"number\" ? err.status : 0;\n // note: DOMException is not implemented yet in React Native\n // and aborting a fetch throws a plain Error with message \"Aborted\".\n this.isAbort = !!err.isAbort || err.name === \"AbortError\" || err.message === \"Aborted\";\n if (err.response !== null && typeof err.response === \"object\") {\n this.response = err.response;\n }\n else if (err.data !== null && typeof err.data === \"object\") {\n this.response = err.data;\n }\n else {\n this.response = {};\n }\n }\n if (!this.originalError && !(errData instanceof ClientResponseError)) {\n this.originalError = errData;\n }\n this.name = \"ClientResponseError \" + this.status;\n this.message = this.response?.message;\n if (!this.message) {\n if (this.isAbort) {\n this.message =\n \"The request was aborted (most likely autocancelled; you can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation).\";\n }\n else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n this.message =\n \"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 }\n else {\n this.message = \"Something went wrong.\";\n }\n }\n // set this.cause so that JS debugging tools can automatically connect\n // the dots between the original error and the wrapped one\n this.cause = this.originalError;\n }\n /**\n * Alias for `this.response` for backward compatibility.\n */\n get data() {\n return this.response;\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",
|
|
6
|
+
"/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\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 */\n// oxlint-disable-next-line no-control-regex -- RFC 6265 cookie spec allows horizontal tab (U+0009)\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\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, options) {\n const result = {};\n if (typeof str !== \"string\") {\n return result;\n }\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf(\"=\", index);\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n let endIdx = str.indexOf(\";\", index);\n if (endIdx === -1) {\n endIdx = str.length;\n }\n else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(\";\", eqIdx - 1) + 1;\n continue;\n }\n const key = str.slice(index, eqIdx).trim();\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n try {\n result[key] = decode(val);\n }\n catch {\n result[key] = val; // no decoding\n }\n }\n index = endIdx + 1;\n }\n return result;\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, val, options) {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError(\"argument name is invalid\");\n }\n const value = encode(val);\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError(\"argument val is invalid\");\n }\n let result = name + \"=\" + value;\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError(\"option maxAge is invalid\");\n }\n result += \"; Max-Age=\" + Math.floor(maxAge);\n }\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError(\"option domain is invalid\");\n }\n result += \"; Domain=\" + opt.domain;\n }\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError(\"option path is invalid\");\n }\n result += \"; Path=\" + opt.path;\n }\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError(\"option expires is invalid\");\n }\n result += \"; Expires=\" + opt.expires.toUTCString();\n }\n if (opt.httpOnly) {\n result += \"; HttpOnly\";\n }\n if (opt.secure) {\n result += \"; Secure\";\n }\n if (opt.priority) {\n const priority = typeof opt.priority === \"string\" ? opt.priority.toLowerCase() : opt.priority;\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 if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === \"string\" ? opt.sameSite.toLowerCase() : opt.sameSite;\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 return result;\n}\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val) {\n return val.indexOf(\"%\") !== -1 ? decodeURIComponent(val) : val;\n}\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val) {\n return encodeURIComponent(val);\n}\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val) {\n return Object.prototype.toString.call(val) === \"[object Date]\" || val instanceof Date;\n}\n",
|
|
7
|
+
"// @todo remove after https://github.com/reactwg/react-native-releases/issues/287\nconst isReactNative = (typeof navigator !== \"undefined\" && navigator.product === \"ReactNative\") ||\n (typeof global !== \"undefined\" && global.HermesInternal);\nlet atobPolyfill;\nif (typeof atob === \"function\" && !isReactNative) {\n atobPolyfill = atob;\n}\nelse {\n /**\n * The code was extracted from:\n * https://github.com/davidchambers/Base64.js\n */\n atobPolyfill = (input) => {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\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 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 * 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 // try to find character in table (0-63, not found => -1)\n buffer = chars.indexOf(buffer);\n }\n // oxlint-disable-next-line block-scoped-var -- upstream atob polyfill loop variable\n return output;\n };\n}\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token) {\n if (token) {\n try {\n const encodedPayload = decodeURIComponent(atobPolyfill(token.split(\".\")[1])\n .split(\"\")\n .map(function (c) {\n return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n })\n .join(\"\"));\n return JSON.parse(encodedPayload) || {};\n }\n catch { }\n }\n return {};\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, expirationThreshold = 0) {\n let payload = getTokenPayload(token);\n if (Object.keys(payload).length > 0 &&\n (!payload.exp || payload.exp - expirationThreshold > Date.now() / 1000)) {\n return false;\n }\n return true;\n}\n",
|
|
8
|
+
"// js-sdk v0.28.1 src/stores/BaseAuthStore.ts\nimport { cookieParse, cookieSerialize } from \"@sdk/tools/cookie\";\nimport { isTokenExpired, getTokenPayload } from \"@sdk/tools/jwt\";\nimport {} from \"@sdk/tools/dtos\";\nconst defaultCookieKey = \"pb_auth\";\n/**\n * Base AuthStore class that stores the auth state in runtime memory (aka. only for the duration of the store instane).\n *\n * Usually you wouldn't use it directly and instead use the builtin LocalAuthStore, AsyncAuthStore\n * or extend it with your own custom implementation.\n */\nexport class BaseAuthStore {\n constructor() {\n this.baseToken = \"\";\n this.baseModel = null;\n this._onChangeCallbacks = [];\n }\n /**\n * Retrieves the stored token (if any).\n */\n get token() {\n return this.baseToken;\n }\n /**\n * Retrieves the stored model data (if any).\n */\n get record() {\n return this.baseModel;\n }\n /**\n * @deprecated use `record` instead.\n */\n get model() {\n return this.baseModel;\n }\n /**\n * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n */\n get isValid() {\n return !isTokenExpired(this.token);\n }\n /**\n * Loosely checks whether the currently loaded store state is for superuser.\n *\n * Alternatively you can also compare directly `pb.authStore.record?.collectionName`.\n */\n get isSuperuser() {\n let payload = getTokenPayload(this.token);\n return (payload.type == \"auth\" &&\n (this.record?.collectionName == \"_superusers\" ||\n // fallback in case the record field is not populated and assuming\n // that the collection crc32 checksum id wasn't manually changed\n (!this.record?.collectionName && payload.collectionId == \"pbc_3142635823\")));\n }\n /**\n * @deprecated use `isSuperuser` instead or simply check the record.collectionName property.\n */\n get isAdmin() {\n console.warn(\"Please replace pb.authStore.isAdmin with pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName\");\n return this.isSuperuser;\n }\n /**\n * @deprecated use `!isSuperuser` instead or simply check the record.collectionName property.\n */\n get isAuthRecord() {\n console.warn(\"Please replace pb.authStore.isAuthRecord with !pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName\");\n return getTokenPayload(this.token).type == \"auth\" && !this.isSuperuser;\n }\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token, record) {\n this.baseToken = token || \"\";\n this.baseModel = record || null;\n this.triggerChange();\n }\n /**\n * Removes the stored token and model data form the auth store.\n */\n clear() {\n this.baseToken = \"\";\n this.baseModel = null;\n this.triggerChange();\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, key = defaultCookieKey) {\n const rawData = cookieParse(cookie || \"\")[key] || \"\";\n let data = {};\n try {\n const parsed = JSON.parse(rawData);\n // normalize\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n data = {};\n }\n else {\n data = parsed;\n }\n }\n catch { }\n const token = typeof data[\"token\"] === \"string\" ? data[\"token\"] : \"\";\n const recordOrModel = (data[\"record\"] || data[\"model\"] || null);\n this.save(token, recordOrModel);\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, key = defaultCookieKey) {\n const defaultOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\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 }\n else {\n defaultOptions.expires = new Date(\"1970-01-01\");\n }\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n const rawData = {\n token: this.token,\n record: this.record ? JSON.parse(JSON.stringify(this.record)) : null,\n };\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n const resultLength = typeof Blob !== \"undefined\" ? new Blob([result]).size : result.length;\n // strip down the model data to the bare minimum\n if (rawData.record && resultLength > 4096) {\n rawData.record = { id: rawData.record?.id, email: rawData.record?.email };\n const extraProps = [\"collectionId\", \"collectionName\", \"verified\"];\n for (const prop in this.record) {\n if (extraProps.includes(prop)) {\n rawData.record[prop] = this.record[prop];\n }\n }\n result = cookieSerialize(key, JSON.stringify(rawData), options);\n }\n return result;\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, fireImmediately = false) {\n this._onChangeCallbacks.push(callback);\n if (fireImmediately) {\n callback(this.token, this.record);\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 triggerChange() {\n for (const callback of this._onChangeCallbacks) {\n // oxlint-disable-next-line no-unused-expressions -- upstream short-circuit callback execution\n callback && callback(this.token, this.record);\n }\n }\n}\n",
|
|
9
|
+
"// js-sdk v0.28.1 src/stores/LocalAuthStore.ts\nimport { BaseAuthStore } from \"@sdk/stores/BaseAuthStore\";\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (e.g. in node env).\n */\nexport class LocalAuthStore extends BaseAuthStore {\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n this.storageFallback = {};\n this.storageKey = storageKey;\n this._bindStorageEvent();\n }\n /**\n * @inheritdoc\n */\n get token() {\n const data = this._storageGet(this.storageKey) || {};\n return data.token || \"\";\n }\n /**\n * @inheritdoc\n */\n get record() {\n const data = this._storageGet(this.storageKey) || {};\n return data.record || data.model || null;\n }\n /**\n * @deprecated use `record` instead.\n */\n get model() {\n return this.record;\n }\n /**\n * @inheritdoc\n */\n save(token, record) {\n this._storageSet(this.storageKey, {\n token: token,\n record: record,\n });\n super.save(token, record);\n }\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n super.clear();\n }\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n _storageGet(key) {\n if (typeof window !== \"undefined\" && window?.localStorage) {\n const rawValue = window.localStorage.getItem(key) || \"\";\n try {\n return JSON.parse(rawValue);\n }\n catch {\n // not a json\n return rawValue; // not an object, so every property read is undefined\n }\n }\n // fallback\n return this.storageFallback[key];\n }\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n _storageSet(key, value) {\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 }\n else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n _storageRemove(key) {\n // delete from local storage\n if (typeof window !== \"undefined\" && window?.localStorage) {\n window.localStorage?.removeItem(key);\n }\n // delete from fallback\n delete this.storageFallback[key];\n }\n /**\n * Updates the current store state on localStorage change.\n */\n _bindStorageEvent() {\n if (typeof window === \"undefined\" || !window?.localStorage || !window.addEventListener) {\n return;\n }\n window.addEventListener(\"storage\", (e) => {\n if (e.key != this.storageKey) {\n return;\n }\n const data = this._storageGet(this.storageKey) || {};\n super.save(data.token || \"\", data.record || data.model || null);\n });\n }\n}\n",
|
|
10
|
+
"// js-sdk v0.28.1 src/services/BaseService.ts\nimport Client from \"@sdk/Client\";\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport class BaseService {\n constructor(client) {\n this.client = client;\n }\n}\n",
|
|
11
|
+
"// -------------------------------------------------------------------\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// modifies in place the provided options by moving unknown send options as query parameters.\nexport function normalizeUnknownQueryParams(options) {\n if (!options) {\n return;\n }\n options.query = options.query || {};\n for (let key in options) {\n if (knownSendOptionsKeys.includes(key)) {\n continue;\n }\n options.query[key] = options[key];\n delete options[key];\n }\n}\nexport function serializeQueryParams(params) {\n const result = [];\n for (const key in params) {\n const encodedKey = encodeURIComponent(key);\n const arrValue = Array.isArray(params[key]) ? params[key] : [params[key]];\n for (let v of arrValue) {\n v = prepareQueryParamValue(v);\n if (v === null) {\n continue;\n }\n result.push(encodedKey + \"=\" + v);\n }\n }\n return result.join(\"&\");\n}\n// encodes and normalizes the provided query param value.\nfunction prepareQueryParamValue(value) {\n if (value === null || typeof value === \"undefined\") {\n return null;\n }\n if (value instanceof Date) {\n return encodeURIComponent(value.toISOString().replace(\"T\", \" \"));\n }\n if (typeof value === \"object\") {\n return encodeURIComponent(JSON.stringify(value));\n }\n return encodeURIComponent(value);\n}\n",
|
|
12
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/options\";\nexport class SettingsService extends BaseService {\n /**\n * Fetch all available app settings.\n *\n * @throws {ClientResponseError}\n */\n async getAll(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/settings\", options);\n }\n /**\n * Bulk updates app settings.\n *\n * @throws {ClientResponseError}\n */\n async update(bodyParams, options) {\n options = Object.assign({\n method: \"PATCH\",\n body: bodyParams,\n }, options);\n return this.client.send(\"/api/settings\", options);\n }\n /**\n * Performs a S3 filesystem connection test.\n *\n * The currently supported `filesystem` are \"storage\" and \"backups\".\n *\n * @throws {ClientResponseError}\n */\n async testS3(filesystem = \"storage\", options) {\n options = Object.assign({\n method: \"POST\",\n body: {\n filesystem: filesystem,\n },\n }, options);\n return this.client.send(\"/api/settings/test/s3\", options).then(() => true);\n }\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n *\n * @throws {ClientResponseError}\n */\n async testEmail(collectionIdOrName, toEmail, emailTemplate, options) {\n options = Object.assign({\n method: \"POST\",\n body: {\n email: toEmail,\n template: emailTemplate,\n collection: collectionIdOrName,\n },\n }, options);\n return this.client.send(\"/api/settings/test/email\", options).then(() => true);\n }\n /**\n * Generates a new Apple OAuth2 client secret.\n *\n * @throws {ClientResponseError}\n */\n async generateAppleClientSecret(clientId, teamId, keyId, privateKey, duration, options) {\n options = Object.assign({\n method: \"POST\",\n body: {\n clientId,\n teamId,\n keyId,\n privateKey,\n duration,\n },\n }, options);\n return this.client.send(\"/api/settings/apple/generate-client-secret\", options);\n }\n}\n",
|
|
13
|
+
"import { ClientResponseError } from \"@sdk/ClientResponseError\";\nimport { BaseService } from \"@sdk/services/BaseService\";\nimport { normalizeUnknownQueryParams } from \"@sdk/tools/options\";\nexport class RealtimeService extends BaseService {\n constructor() {\n super(...arguments);\n this.clientId = \"\";\n this.eventSource = null;\n this.subscriptions = {};\n this.lastSentSubscriptions = [];\n this.maxConnectTimeout = 15000;\n this.reconnectAttempts = 0;\n this.maxReconnectAttempts = Infinity;\n this.predefinedReconnectIntervals = [200, 300, 500, 1000, 1200, 1500, 2000];\n this.pendingConnects = [];\n this.pendingSubmits = [];\n this.isProcessingPendingSubmits = false;\n // Bumped by every close. A continuation of a connection captures the value when the connection\n // opens and does nothing once it differs: the connection was closed, or replaced by a new one\n // (a `reconnect()` while the subscriptions are being sent, for example).\n this.connectionGeneration = 0;\n }\n /**\n * Returns whether the realtime connection has been established.\n */\n get isConnected() {\n return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\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, callback, options) {\n if (!topic) {\n throw new Error(\"topic must be set.\");\n }\n let key = topic;\n // serialize and append the topic options (if any)\n if (options) {\n options = Object.assign({}, options); // shallow copy\n normalizeUnknownQueryParams(options);\n const serialized = \"options=\" +\n encodeURIComponent(JSON.stringify({ query: options.query, headers: options.headers }));\n key += (key.includes(\"?\") ? \"&\" : \"?\") + serialized;\n }\n const listener = function (e) {\n const msgEvent = e;\n let data;\n try {\n data = JSON.parse(msgEvent?.data);\n }\n catch { }\n callback(data || {});\n };\n // store the listener\n if (!this.subscriptions[key]) {\n this.subscriptions[key] = [];\n }\n this.subscriptions[key].push(listener);\n if (!this.isConnected) {\n // initialize sse connection\n await this.connect();\n }\n else if (this.subscriptions[key].length === 1) {\n // send the updated subscriptions (if it is the first for the key)\n await this.submitSubscriptions();\n }\n else {\n // only register the listener\n this.eventSource?.addEventListener(key, listener);\n }\n return async () => {\n return this.unsubscribeByTopicAndListener(topic, listener);\n };\n }\n /**\n * Sends the current subscriptions again, with the client's current authorization. Upstream\n * keeps a subscription's auth state on the server, so a new token for the same record is\n * accepted and replaces it (docs/design/13-ssr.md, \"Browser client and realtime\"). A no-op\n * when the connection is not established or there are no subscriptions.\n */\n resubmit() {\n if (!this.clientId || !this.hasSubscriptionListeners()) {\n return Promise.resolve();\n }\n this.lastSentSubscriptions = [];\n return this.submitSubscriptions();\n }\n /**\n * Closes the SSE connection and opens a new one with the same subscriptions, after an intended\n * change of authorization. The new connection gets its own client ID, and the subscriptions are\n * sent on it with the client's current authorization. Upstream keeps a connection's\n * authorization on the server and only accepts a change to the same record (a guest may then\n * sign in), so a different user or a sign-out needs a new connection\n * (docs/design/13-ssr.md, \"Browser client and realtime\").\n *\n * The new connection is opened the way a dropped one is reopened: its first attempt waits the\n * first backoff step, and a failed attempt retries in the background with the usual backoff\n * (`connectErrorHandler`). Unlike a dropped connection, it does not call `onDisconnect`, since\n * nothing went wrong on the network or the server. The returned promise resolves when the\n * reconnect is scheduled, not when the new connection is up. A no-op without subscriptions.\n */\n reconnect() {\n if (!this.hasSubscriptionListeners()) {\n this.disconnect(false, false);\n return Promise.resolve();\n }\n this.disconnect(true, false);\n this.scheduleReconnect();\n return Promise.resolve();\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) {\n if (!topic) {\n // remove all subscriptions\n this.subscriptions = {};\n }\n else {\n // remove all listeners related to the topic\n const subs = this.getSubscriptionsByTopic(topic);\n for (let key in subs) {\n if (!this.hasSubscriptionListeners(key)) {\n continue; // already unsubscribed\n }\n for (let listener of this.subscriptions[key]) {\n this.eventSource?.removeEventListener(key, listener);\n }\n delete this.subscriptions[key];\n }\n }\n await this.submitSubscriptions();\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(keyPrefix) {\n let hasAtleastOneTopic = false;\n for (let key in this.subscriptions) {\n // \"?\" so that it can be used as end delimiter for the prefix\n if (!(key + \"?\").startsWith(keyPrefix)) {\n continue;\n }\n hasAtleastOneTopic = true;\n for (let listener of this.subscriptions[key]) {\n this.eventSource?.removeEventListener(key, listener);\n }\n delete this.subscriptions[key];\n }\n if (!hasAtleastOneTopic) {\n return; // nothing to unsubscribe from\n }\n await this.submitSubscriptions();\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, listener) {\n const subs = this.getSubscriptionsByTopic(topic);\n for (let key in subs) {\n if (!Array.isArray(this.subscriptions[key]) || !this.subscriptions[key].length) {\n continue; // already unsubscribed\n }\n let exist = false;\n for (let i = this.subscriptions[key].length - 1; i >= 0; i--) {\n if (this.subscriptions[key][i] !== listener) {\n continue;\n }\n exist = true; // has at least one matching listener\n delete this.subscriptions[key][i]; // removes the function reference\n this.subscriptions[key].splice(i, 1); // reindex the array\n this.eventSource?.removeEventListener(key, listener);\n }\n if (!exist) {\n continue;\n }\n // remove the key from the subscriptions list if there are no other listeners\n if (!this.subscriptions[key].length) {\n delete this.subscriptions[key];\n }\n }\n await this.submitSubscriptions();\n }\n hasSubscriptionListeners(keyToCheck) {\n this.subscriptions = this.subscriptions || {};\n // check the specified key\n if (keyToCheck) {\n return !!this.subscriptions[keyToCheck]?.length;\n }\n // check for at least one non-empty subscription\n for (let key in this.subscriptions) {\n if (this.subscriptions[key]?.length) {\n return true;\n }\n }\n return false;\n }\n async submitSubscriptions() {\n return new Promise((resolve, reject) => {\n this.pendingSubmits.push({ resolve, reject });\n if (this.pendingSubmits.length == 1) {\n queueMicrotask(() => this.finalizePendingSubscriptions());\n }\n });\n }\n async finalizePendingSubscriptions() {\n if (this.isProcessingPendingSubmits || !this.pendingSubmits.length) {\n return;\n }\n // clone and reset the list to allow next items to queue\n const pending = this.pendingSubmits.slice();\n this.pendingSubmits = [];\n this.isProcessingPendingSubmits = true;\n try {\n await this.sendSubscriptions();\n for (let p of pending) {\n p.resolve();\n }\n }\n catch (err) {\n for (let p of pending) {\n // oxlint-disable-next-line no-unused-expressions -- upstream ternary dispatch for promise resolution\n err ? p.reject(err) : p.resolve();\n }\n }\n finally {\n this.isProcessingPendingSubmits = false;\n // another request came in while awaiting above\n if (this.pendingSubmits.length > 0) {\n await this.finalizePendingSubscriptions();\n }\n }\n }\n getSubscriptionsCancelKey() {\n return \"realtime_\" + this.clientId;\n }\n getSubscriptionsByTopic(topic) {\n const result = {};\n // \"?\" so that it can be used as end delimiter for the topic\n topic = topic.includes(\"?\") ? topic : topic + \"?\";\n for (let key in this.subscriptions) {\n if ((key + \"?\").startsWith(topic)) {\n result[key] = this.subscriptions[key];\n }\n }\n return result;\n }\n getNonEmptySubscriptionKeys() {\n const result = [];\n for (let key in this.subscriptions) {\n if (this.subscriptions[key].length) {\n result.push(key);\n }\n }\n return result;\n }\n hasUnsentSubscriptions() {\n const latestTopics = this.getNonEmptySubscriptionKeys();\n if (latestTopics.length != this.lastSentSubscriptions.length) {\n return true;\n }\n for (const t of latestTopics) {\n if (!this.lastSentSubscriptions.includes(t)) {\n return true;\n }\n }\n return false;\n }\n async sendSubscriptions() {\n // not initialized yet or connection closed\n if (!this.clientId) {\n return;\n }\n // no subscriptions -> close the SSE connection\n if (!this.hasSubscriptionListeners()) {\n return this.disconnect();\n }\n // no change\n if (!this.hasUnsentSubscriptions()) {\n return;\n }\n // optimistic update\n this.addAllSubscriptionListeners();\n this.lastSentSubscriptions = this.getNonEmptySubscriptionKeys();\n return this.client\n .send(\"/api/realtime\", {\n method: \"POST\",\n body: {\n clientId: this.clientId,\n subscriptions: this.lastSentSubscriptions,\n },\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 addAllSubscriptionListeners() {\n if (!this.eventSource) {\n return;\n }\n this.removeAllSubscriptionListeners();\n for (let key in this.subscriptions) {\n for (let listener of this.subscriptions[key]) {\n this.eventSource.addEventListener(key, listener);\n }\n }\n }\n removeAllSubscriptionListeners() {\n if (!this.eventSource) {\n return;\n }\n for (let key in this.subscriptions) {\n for (let listener of this.subscriptions[key]) {\n this.eventSource.removeEventListener(key, listener);\n }\n }\n }\n async connect() {\n if (this.reconnectAttempts > 0) {\n // immediately resolve the promise to avoid indefinitely\n // blocking the client during reconnection\n return;\n }\n return new Promise((resolve, reject) => {\n this.pendingConnects.push({ resolve, reject });\n if (this.pendingConnects.length == 1) {\n queueMicrotask(() => this.initConnect());\n }\n });\n }\n initConnect() {\n this.disconnect(true);\n // Every continuation of this connection (its timeout, its error handlers and its PB_CONNECT\n // work) checks this before it touches the client's state. A closed or replaced connection\n // must not resolve the pending connects, reset the attempts or cancel the next reconnect:\n // those belong to the connection that is current now.\n const generation = this.connectionGeneration;\n const isCurrent = () => generation === this.connectionGeneration;\n // wait up to 15s for connect\n clearTimeout(this.connectTimeoutId);\n this.connectTimeoutId = setTimeout(() => {\n if (isCurrent()) {\n this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n }\n }, this.maxConnectTimeout);\n this.eventSource = new EventSource(this.client.buildURL(\"/api/realtime\"));\n // oxlint-disable-next-line unicorn/prefer-add-event-listener -- EventSource.onerror matches upstream assignment\n this.eventSource.onerror = () => {\n if (isCurrent()) {\n this.connectErrorHandler(new Error(\"Failed to establish realtime connection.\"));\n }\n };\n this.eventSource.addEventListener(\"PB_CONNECT\", (e) => {\n if (!isCurrent()) {\n return;\n }\n const msgEvent = e;\n this.clientId = msgEvent?.lastEventId;\n this.lastSentSubscriptions = [];\n this.submitSubscriptions()\n .then(async () => {\n // This is in case new topics were being added while\n // the initial `submitSubscriptions()` was still pending\n //\n // It is a best effort attempt to try to submit\n // all topics before too eagerly resolving their promise.\n //\n // Or in other words, when there is no SSE established yet\n // and the user calls something like:\n // ```js\n // const p1 = pb.collection(\"col\").subscribe(\"topic2\")\n // queueMicrotask(() => {\n // const p2 = pb.collection(\"col\").subscribe(\"topic2\")\n // })\n // ```\n // We want both p1 and p2 to complete AFTER their subscribe\n // (SSE connect + submit subscription) calls complete.\n let maxResubmit = 3;\n while (isCurrent() && this.hasUnsentSubscriptions() && maxResubmit > 0) {\n maxResubmit--;\n await this.submitSubscriptions();\n }\n // the subscriptions may have been sent while the connection was closed or replaced\n if (!isCurrent()) {\n return;\n }\n // resolve connect promises\n for (let p of this.pendingConnects) {\n p.resolve();\n }\n // reset connect meta\n this.pendingConnects = [];\n this.reconnectAttempts = 0;\n clearTimeout(this.reconnectTimeoutId);\n clearTimeout(this.connectTimeoutId);\n // propagate the PB_CONNECT event\n const connectSubs = this.getSubscriptionsByTopic(\"PB_CONNECT\");\n for (let key in connectSubs) {\n for (let listener of connectSubs[key]) {\n listener(e);\n }\n }\n // just as a last resort in case the 3 retries from above weren't enough,\n // check for unset subscriptions after the pendingConnects has been resolved\n // (aka. subscribe in that case is no longer \"blocked\" because isConnected would be true)\n if (isCurrent() && this.hasUnsentSubscriptions()) {\n await this.submitSubscriptions();\n }\n })\n .catch((err) => {\n if (!isCurrent()) {\n return; // a closed connection's failure is not the current one's\n }\n this.clientId = \"\";\n this.lastSentSubscriptions = [];\n this.connectErrorHandler(err);\n });\n });\n }\n connectErrorHandler(err) {\n clearTimeout(this.connectTimeoutId);\n clearTimeout(this.reconnectTimeoutId);\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 for (let p of this.pendingConnects) {\n p.reject(new ClientResponseError(err));\n }\n this.pendingConnects = [];\n this.disconnect();\n return;\n }\n // otherwise -> reconnect in the background\n this.disconnect(true);\n this.scheduleReconnect();\n }\n /**\n * Schedules the next connection attempt after the backoff step for the current attempt count,\n * and counts the attempt. Shared by a dropped connection and by `reconnect()`, so both retry\n * the same way.\n */\n scheduleReconnect() {\n const timeout = this.predefinedReconnectIntervals[this.reconnectAttempts] ||\n this.predefinedReconnectIntervals[this.predefinedReconnectIntervals.length - 1];\n this.reconnectAttempts++;\n const generation = this.connectionGeneration;\n this.reconnectTimeoutId = setTimeout(() => {\n // disconnect() cancels this timer; the check keeps it from ever opening a connection that\n // was superseded in the meantime\n if (generation === this.connectionGeneration) {\n this.initConnect();\n }\n }, timeout);\n }\n /**\n * Closes the connection. `fromReconnect` keeps the reconnect attempts and the pending connects,\n * for a retry. `notify` is false when the close is intended (a `reconnect()`), so the\n * `onDisconnect` hook, which means a network or server error, is not called.\n */\n disconnect(fromReconnect = false, notify = true) {\n this.connectionGeneration++;\n if (notify && this.clientId && this.onDisconnect) {\n this.onDisconnect(Object.keys(this.subscriptions));\n }\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 this.lastSentSubscriptions = [];\n if (!fromReconnect) {\n this.reconnectAttempts = 0;\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",
|
|
14
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport { ClientResponseError } from \"@sdk/ClientResponseError\";\nimport {} from \"@sdk/tools/dtos\";\nimport {} from \"@sdk/tools/options\";\nexport class CrudService extends BaseService {\n /**\n * Response data decoder.\n */\n decode(data) {\n return data;\n }\n async getFullList(batchOrqueryParams, options) {\n if (typeof batchOrqueryParams == \"number\") {\n return this._getFullList(batchOrqueryParams, options);\n }\n options = Object.assign({}, batchOrqueryParams, options);\n let batch = 1000;\n if (options.batch) {\n batch = options.batch;\n delete options.batch;\n }\n return this._getFullList(batch, options);\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 * @throws {ClientResponseError}\n */\n async getList(page = 1, perPage = 30, options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n options.query = Object.assign({\n page: page,\n perPage: perPage,\n }, options.query);\n return this.client\n .send(this.baseCrudPath, options)\n .then((responseData) => {\n responseData.items =\n responseData.items?.map((item) => {\n return this.decode(item);\n }) || [];\n return responseData;\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 * @throws {ClientResponseError}\n */\n async getFirstListItem(filter, options) {\n options = Object.assign({\n requestKey: \"one_by_filter_\" + this.baseCrudPath + \"_\" + filter,\n }, options);\n options.query = Object.assign({\n filter: filter,\n skipTotal: 1,\n }, options.query);\n return this.getList(1, 1, options).then((result) => {\n if (!result?.items?.length) {\n throw new ClientResponseError({\n status: 404,\n response: {\n code: 404,\n message: \"The requested resource wasn't found.\",\n data: {},\n },\n });\n }\n return result.items[0];\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 * If `id` is empty it will throw a 404 error.\n *\n * @throws {ClientResponseError}\n */\n async getOne(id, options) {\n if (!id) {\n throw new ClientResponseError({\n url: this.client.buildURL(this.baseCrudPath + \"/\"),\n status: 404,\n response: {\n code: 404,\n message: \"Missing required record id.\",\n data: {},\n },\n });\n }\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client\n .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n .then((responseData) => this.decode(responseData));\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 * @throws {ClientResponseError}\n */\n async create(bodyParams, options) {\n options = Object.assign({\n method: \"POST\",\n body: bodyParams,\n }, options);\n return this.client\n .send(this.baseCrudPath, options)\n .then((responseData) => this.decode(responseData));\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 * @throws {ClientResponseError}\n */\n async update(id, bodyParams, options) {\n options = Object.assign({\n method: \"PATCH\",\n body: bodyParams,\n }, options);\n return this.client\n .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n .then((responseData) => this.decode(responseData));\n }\n /**\n * Deletes an existing item by its id.\n *\n * @throws {ClientResponseError}\n */\n async delete(id, options) {\n options = Object.assign({\n method: \"DELETE\",\n }, options);\n return this.client\n .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n .then(() => true);\n }\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n _getFullList(batchSize = 1000, options) {\n options = options || {};\n options.query = Object.assign({\n skipTotal: 1,\n }, options.query);\n let result = [];\n let request = async (page) => {\n return this.getList(page, batchSize || 1000, options).then((list) => {\n const castedList = list;\n const items = castedList.items;\n result = result.concat(items);\n if (items.length == list.perPage) {\n return request(page + 1);\n }\n return result;\n });\n };\n return request(1);\n }\n}\n",
|
|
15
|
+
"// js-sdk v0.28.1 src/tools/legacy.ts\nimport {} from \"@sdk/tools/options\";\nexport function normalizeLegacyOptionsArgs(legacyWarn, baseOptions, bodyOrOptions, query) {\n const hasBodyOrOptions = typeof bodyOrOptions !== \"undefined\";\n const hasQuery = typeof query !== \"undefined\";\n if (!hasQuery && !hasBodyOrOptions) {\n return baseOptions;\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 return baseOptions;\n }\n return Object.assign(baseOptions, bodyOrOptions);\n}\n",
|
|
16
|
+
"// js-sdk v0.28.1 src/tools/refresh.ts\nimport Client from \"@sdk/Client\";\nimport { isTokenExpired } from \"@sdk/tools/jwt\";\n// reset previous auto refresh registrations\nexport function resetAutoRefresh(client) {\n client._resetAutoRefresh?.();\n}\nexport function registerAutoRefresh(client, threshold, refreshFunc, reauthenticateFunc) {\n resetAutoRefresh(client);\n const oldBeforeSend = client.beforeSend;\n const oldModel = client.authStore.record;\n // unset the auto refresh in case the auth store was cleared\n // OR a new model was authenticated\n const unsubStoreChange = client.authStore.onChange((newToken, model) => {\n if (!newToken ||\n model?.id != oldModel?.id ||\n ((model?.collectionId || oldModel?.collectionId) &&\n model?.collectionId != oldModel?.collectionId)) {\n resetAutoRefresh(client);\n }\n });\n // initialize a reset function and attach it dynamically to the client\n client._resetAutoRefresh = function () {\n unsubStoreChange();\n client.beforeSend = oldBeforeSend;\n delete client._resetAutoRefresh;\n };\n client.beforeSend = async (url, sendOptions) => {\n const oldToken = client.authStore.token;\n if (sendOptions.query?.autoRefresh) {\n return oldBeforeSend ? oldBeforeSend(url, sendOptions) : { url, sendOptions };\n }\n let isValid = client.authStore.isValid;\n if (\n // is loosely valid\n isValid &&\n // but it is going to expire in the next \"threshold\" seconds\n isTokenExpired(client.authStore.token, threshold)) {\n try {\n await refreshFunc();\n }\n catch {\n isValid = false;\n }\n }\n // still invalid -> reauthenticate\n if (!isValid) {\n await reauthenticateFunc();\n }\n // the request wasn't sent with a custom token\n const headers = sendOptions.headers || {};\n for (let key in headers) {\n if (key.toLowerCase() == \"authorization\" &&\n // the request wasn't sent with a custom token\n oldToken == headers[key] &&\n client.authStore.token) {\n // set the latest store token\n headers[key] = client.authStore.token;\n break;\n }\n }\n sendOptions.headers = headers;\n return oldBeforeSend ? oldBeforeSend(url, sendOptions) : { url, sendOptions };\n };\n}\n",
|
|
17
|
+
"import Client from \"@sdk/Client\";\nimport { ClientResponseError } from \"@sdk/ClientResponseError\";\nimport { RealtimeService } from \"@sdk/services/RealtimeService\";\nimport { BaseAuthStore } from \"@sdk/stores/BaseAuthStore\";\nimport { CrudService } from \"@sdk/services/CrudService\";\nimport {} from \"@sdk/tools/dtos\";\nimport { normalizeLegacyOptionsArgs } from \"@sdk/tools/legacy\";\nimport {} from \"@sdk/tools/options\";\nimport { getTokenPayload } from \"@sdk/tools/jwt\";\nimport { registerAutoRefresh, resetAutoRefresh } from \"@sdk/tools/refresh\";\nexport class RecordService extends CrudService {\n constructor(client, collectionIdOrName) {\n super(client);\n this.collectionIdOrName = collectionIdOrName;\n }\n /**\n * @inheritdoc\n */\n get baseCrudPath() {\n return this.baseCollectionPath + \"/records\";\n }\n /**\n * Returns the current collection service base path.\n */\n get baseCollectionPath() {\n return \"/api/collections/\" + encodeURIComponent(this.collectionIdOrName);\n }\n /**\n * Returns whether the current service collection is superusers.\n */\n get isSuperusers() {\n return this.collectionIdOrName == \"_superusers\" || this.collectionIdOrName == \"_pbc_2773867675\";\n }\n // ---------------------------------------------------------------\n // Realtime handlers\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, callback, options) {\n if (!topic) {\n throw new Error(\"Missing topic.\");\n }\n if (!callback) {\n throw new Error(\"Missing subscription callback.\");\n }\n return this.client.realtime.subscribe(this.collectionIdOrName + \"/\" + topic, callback, options);\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) {\n // unsubscribe from the specified topic\n if (topic) {\n return this.client.realtime.unsubscribe(this.collectionIdOrName + \"/\" + topic);\n }\n // unsubscribe from everything related to the collection\n return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n }\n /**\n * @inheritdoc\n */\n async getFullList(batchOrOptions, options) {\n if (typeof batchOrOptions == \"number\") {\n return super.getFullList(batchOrOptions, options);\n }\n const params = Object.assign({}, batchOrOptions, options);\n return super.getFullList(params);\n }\n /**\n * @inheritdoc\n */\n async getList(page = 1, perPage = 30, options) {\n return super.getList(page, perPage, options);\n }\n /**\n * @inheritdoc\n */\n async getFirstListItem(filter, options) {\n return super.getFirstListItem(filter, options);\n }\n /**\n * @inheritdoc\n */\n async getOne(id, options) {\n return super.getOne(id, options);\n }\n /**\n * @inheritdoc\n */\n async create(bodyParams, options) {\n return super.create(bodyParams, options);\n }\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.record` matches with the updated id, then\n * on success the `client.authStore.record` will be updated with the new response record fields.\n */\n async update(id, bodyParams, options) {\n return super.update(id, bodyParams, options).then((item) => {\n if (\n // is record auth\n this.client.authStore.record?.id === item?.id &&\n (this.client.authStore.record?.collectionId === this.collectionIdOrName ||\n this.client.authStore.record?.collectionName === this.collectionIdOrName)) {\n let authExpand = Object.assign({}, this.client.authStore.record.expand);\n let authRecord = Object.assign({}, this.client.authStore.record, item);\n if (authExpand) {\n // for now \"merge\" only top-level expand\n authRecord.expand = Object.assign(authExpand, item.expand);\n }\n this.client.authStore.save(this.client.authStore.token, authRecord);\n }\n return item;\n });\n }\n /**\n * @inheritdoc\n *\n * If the current `client.authStore.record` matches with the deleted id,\n * then on success the `client.authStore` will be cleared.\n */\n async delete(id, options) {\n return super.delete(id, options).then((success) => {\n if (success &&\n // is record auth\n this.client.authStore.record?.id === id &&\n (this.client.authStore.record?.collectionId === this.collectionIdOrName ||\n this.client.authStore.record?.collectionName === this.collectionIdOrName)) {\n this.client.authStore.clear();\n }\n return success;\n });\n }\n // ---------------------------------------------------------------\n // Auth handlers\n // ---------------------------------------------------------------\n /**\n * Prepare successful collection authorization response.\n */\n authResponse(responseData) {\n const record = this.decode(responseData?.record || {});\n this.client.authStore.save(responseData?.token, record);\n return Object.assign({}, responseData, {\n // normalize common fields\n token: responseData?.token || \"\",\n record: record,\n });\n }\n /**\n * Returns all available collection auth methods.\n *\n * @throws {ClientResponseError}\n */\n async listAuthMethods(options) {\n options = Object.assign({\n method: \"GET\",\n // @todo remove after deleting the pre v0.23 API response fields\n fields: \"mfa,otp,password,oauth2\",\n }, options);\n return this.client.send(this.baseCollectionPath + \"/auth-methods\", options);\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 * @throws {ClientResponseError}\n */\n async authWithPassword(usernameOrEmail, password, options) {\n options = Object.assign({\n method: \"POST\",\n body: {\n identity: usernameOrEmail,\n password: password,\n },\n }, options);\n // note: consider to deprecate\n let autoRefreshThreshold;\n if (this.isSuperusers) {\n autoRefreshThreshold = options.autoRefreshThreshold;\n delete options.autoRefreshThreshold;\n if (!options.autoRefresh) {\n resetAutoRefresh(this.client);\n }\n }\n let authData = await this.client.send(this.baseCollectionPath + \"/auth-with-password\", options);\n authData = this.authResponse(authData);\n if (autoRefreshThreshold && this.isSuperusers) {\n registerAutoRefresh(this.client, autoRefreshThreshold, () => this.authRefresh({ autoRefresh: true }), () => this.authWithPassword(usernameOrEmail, password, Object.assign({ autoRefresh: true }, options)));\n }\n return authData;\n }\n async authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createData, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n provider: provider,\n code: code,\n codeVerifier: codeVerifier,\n redirectURL: redirectURL,\n createData: createData,\n },\n };\n options = 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?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/auth-with-oauth2\", options)\n .then((data) => this.authResponse(data));\n }\n authWithOAuth2(...args) {\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 const legacyArgs = args;\n return this.authWithOAuth2Code(legacyArgs[0] || \"\", legacyArgs[1] || \"\", legacyArgs[2] || \"\", legacyArgs[3] || \"\", legacyArgs[4] || {}, legacyArgs[5] || {}, legacyArgs[6] || {});\n }\n const config = (args[0] || {});\n // open a new popup window in case config.urlCallback is not set\n //\n // note: it is opened before any async calls due to Safari restrictions\n // (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061)\n let eagerDefaultPopup = null;\n if (!config.urlCallback) {\n eagerDefaultPopup = openBrowserPopup(undefined);\n }\n // initialize a one-off realtime service\n const realtime = new RealtimeService(this.client);\n function cleanup() {\n eagerDefaultPopup?.close();\n realtime.unsubscribe();\n }\n const requestKeyOptions = {};\n const requestKey = config.requestKey;\n if (requestKey) {\n requestKeyOptions.requestKey = requestKey;\n }\n return this.listAuthMethods(requestKeyOptions)\n .then((authMethods) => {\n const provider = authMethods.oauth2.providers.find((p) => p.name === config.provider);\n if (!provider) {\n throw new ClientResponseError(new Error(`Missing or invalid provider \"${config.provider}\".`));\n }\n const redirectURL = this.client.buildURL(\"/api/oauth2-redirect\");\n // oxlint-disable-next-line no-async-promise-executor -- upstream async promise executor\n return new Promise(async (resolve, reject) => {\n // find the AbortController associated with the current request key (if any)\n const cancelController = requestKey\n ? this.client[\"cancelControllers\"]?.[requestKey]\n : undefined;\n if (cancelController) {\n // oxlint-disable-next-line unicorn/prefer-add-event-listener -- signal.onabort is cleared by assigning null\n cancelController.signal.onabort = () => {\n cleanup();\n reject(new ClientResponseError({\n isAbort: true,\n message: \"manually cancelled\",\n }));\n };\n }\n // disconnected due to network/server error\n realtime.onDisconnect = (activeSubscriptions) => {\n if (activeSubscriptions.length && reject) {\n cleanup();\n reject(new ClientResponseError(new Error(\"realtime connection interrupted\")));\n }\n };\n try {\n await realtime.subscribe(\"@oauth2\", async (e) => {\n const oldState = realtime.clientId;\n try {\n if (!e.state || oldState !== e.state) {\n throw new Error(\"State parameters don't match.\");\n }\n if (e.error || !e.code) {\n throw new Error(\"OAuth2 redirect error or missing code: \" + e.error);\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 // reset the cancelController listener as it will be triggered by the next api call\n if (cancelController?.signal?.onabort) {\n // oxlint-disable-next-line unicorn/prefer-add-event-listener -- signal.onabort is cleared by assigning null\n cancelController.signal.onabort = null;\n }\n const authData = await this.authWithOAuth2Code(provider.name, e.code, provider.codeVerifier, redirectURL, config.createData, options);\n resolve(authData);\n }\n catch (err) {\n reject(new ClientResponseError(err));\n }\n cleanup();\n });\n const replacements = {\n state: realtime.clientId,\n };\n if (config.scopes?.length) {\n replacements[\"scope\"] = config.scopes.join(\" \");\n }\n const url = this._replaceQueryParams(provider.authURL + redirectURL, replacements);\n let urlCallback = config.urlCallback ||\n // oxlint-disable-next-line no-shadow -- upstream callback parameter name matches URL\n function (url) {\n if (eagerDefaultPopup) {\n eagerDefaultPopup.location.href = url;\n }\n else {\n // it could have been blocked due to its empty initial url,\n // try again...\n eagerDefaultPopup = openBrowserPopup(url);\n }\n };\n await urlCallback(url);\n }\n catch (err) {\n // reset the cancelController listener in case the request key is reused\n if (cancelController?.signal?.onabort) {\n // oxlint-disable-next-line unicorn/prefer-add-event-listener -- signal.onabort is cleared by assigning null\n cancelController.signal.onabort = null;\n }\n cleanup();\n reject(new ClientResponseError(err));\n }\n });\n })\n .catch((err) => {\n cleanup();\n throw err; // rethrow\n });\n }\n async authRefresh(bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n };\n options = normalizeLegacyOptionsArgs(\"This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/auth-refresh\", options)\n .then((data) => this.authResponse(data));\n }\n async requestPasswordReset(email, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n email: email,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/request-password-reset\", options)\n .then(() => true);\n }\n async confirmPasswordReset(passwordResetToken, password, passwordConfirm, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n token: passwordResetToken,\n password: password,\n passwordConfirm: passwordConfirm,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/confirm-password-reset\", options)\n .then(() => true);\n }\n async requestVerification(email, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n email: email,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/request-verification\", options)\n .then(() => true);\n }\n async confirmVerification(verificationToken, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n token: verificationToken,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).\", options, bodyOrOptions, query);\n return this.client.send(this.baseCollectionPath + \"/confirm-verification\", options).then(() => {\n // on success manually update the current auth record verified state\n const payload = getTokenPayload(verificationToken);\n const model = this.client.authStore.record;\n if (model &&\n !model.verified &&\n model.id === payload.id &&\n model.collectionId === payload.collectionId) {\n model.verified = true;\n this.client.authStore.save(this.client.authStore.token, model);\n }\n return true;\n });\n }\n async requestEmailChange(newEmail, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n newEmail: newEmail,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).\", options, bodyOrOptions, query);\n return this.client\n .send(this.baseCollectionPath + \"/request-email-change\", options)\n .then(() => true);\n }\n async confirmEmailChange(emailChangeToken, password, bodyOrOptions, query) {\n let options = {\n method: \"POST\",\n body: {\n token: emailChangeToken,\n password: password,\n },\n };\n options = normalizeLegacyOptionsArgs(\"This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).\", options, bodyOrOptions, query);\n return this.client.send(this.baseCollectionPath + \"/confirm-email-change\", options).then(() => {\n const payload = getTokenPayload(emailChangeToken);\n const model = this.client.authStore.record;\n if (model && model.id === payload.id && model.collectionId === payload.collectionId) {\n this.client.authStore.clear();\n }\n return true;\n });\n }\n /**\n * @deprecated use collection(\"_externalAuths\").*\n *\n * Lists all linked external auth providers for the specified auth record.\n *\n * @throws {ClientResponseError}\n */\n async listExternalAuths(recordId, options) {\n return this.client.collection(\"_externalAuths\").getFullList(Object.assign({}, options, {\n filter: this.client.filter(\"recordRef = {:id}\", { id: recordId }),\n }));\n }\n /**\n * @deprecated use collection(\"_externalAuths\").*\n *\n * Unlink a single external auth provider from the specified auth record.\n *\n * @throws {ClientResponseError}\n */\n async unlinkExternalAuth(recordId, provider, options) {\n const ea = await this.client.collection(\"_externalAuths\").getFirstListItem(this.client.filter(\"recordRef = {:recordId} && provider = {:provider}\", {\n recordId,\n provider,\n }));\n return this.client\n .collection(\"_externalAuths\")\n .delete(ea.id, options)\n .then(() => true);\n }\n /**\n * Sends auth record OTP to the provided email.\n *\n * @throws {ClientResponseError}\n */\n async requestOTP(email, options) {\n options = Object.assign({\n method: \"POST\",\n body: { email: email },\n }, options);\n return this.client.send(this.baseCollectionPath + \"/request-otp\", options);\n }\n /**\n * Authenticate a single auth collection record via OTP.\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 * @throws {ClientResponseError}\n */\n async authWithOTP(otpId, password, options) {\n options = Object.assign({\n method: \"POST\",\n body: { otpId, password },\n }, options);\n return this.client\n .send(this.baseCollectionPath + \"/auth-with-otp\", options)\n .then((data) => this.authResponse(data));\n }\n /**\n * Impersonate authenticates with the specified recordId and\n * returns a new client with the received auth token in a memory store.\n *\n * If `duration` is 0 the generated auth token will fallback\n * to the default collection auth token duration.\n *\n * This action currently requires superusers privileges.\n *\n * @throws {ClientResponseError}\n */\n async impersonate(recordId, duration, options) {\n options = Object.assign({\n method: \"POST\",\n body: { duration: duration },\n }, options);\n options.headers = options.headers || {};\n if (!options.headers.Authorization) {\n options.headers.Authorization = this.client.authStore.token;\n }\n // create a new client loaded with the impersonated auth state\n // ---\n const client = new Client(this.client.baseURL, new BaseAuthStore(), this.client.lang);\n const authData = await client.send(this.baseCollectionPath + \"/impersonate/\" + encodeURIComponent(recordId), options);\n client.authStore.save(authData?.token, this.decode(authData?.record || {}));\n // ---\n return client;\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 _replaceQueryParams(url, replacements = {}) {\n let urlPath = url;\n let query = \"\";\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 const parsedParams = {};\n // parse the query parameters\n const rawParams = query.split(\"&\");\n for (const param of rawParams) {\n if (param == \"\") {\n continue;\n }\n const pair = param.split(\"=\");\n parsedParams[decodeURIComponent(pair[0].replace(/\\+/g, \" \"))] = decodeURIComponent((pair[1] || \"\").replace(/\\+/g, \" \"));\n }\n // apply the replacements\n for (let key in replacements) {\n if (!replacements.hasOwnProperty(key)) {\n continue;\n }\n if (replacements[key] == null) {\n delete parsedParams[key];\n }\n else {\n parsedParams[key] = String(replacements[key]);\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 if (query != \"\") {\n query += \"&\";\n }\n query +=\n encodeURIComponent(key.replace(/%20/g, \"+\")) +\n \"=\" +\n encodeURIComponent(parsedParams[key].replace(/%20/g, \"+\"));\n }\n return query != \"\" ? urlPath + \"?\" + query : urlPath;\n }\n}\nfunction openBrowserPopup(url) {\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 let width = 1024;\n let height = 768;\n let windowWidth = window.innerWidth;\n let windowHeight = window.innerHeight;\n // normalize window size\n width = width > windowWidth ? windowWidth : width;\n height = height > windowHeight ? windowHeight : height;\n let left = windowWidth / 2 - width / 2;\n let top = windowHeight / 2 - height / 2;\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(url, \"popup_window\", \"width=\" +\n width +\n \",height=\" +\n height +\n \",top=\" +\n top +\n \",left=\" +\n left +\n \",resizable,menubar=no\");\n}\n",
|
|
18
|
+
"import { CrudService } from \"@sdk/services/CrudService\";\nimport {} from \"@sdk/tools/options\";\nimport {} from \"@sdk/tools/dtos\";\nexport class CollectionService extends CrudService {\n /**\n * @inheritdoc\n */\n get baseCrudPath() {\n return \"/api/collections\";\n }\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and their fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n *\n * @throws {ClientResponseError}\n */\n async import(collections, deleteMissing = false, options) {\n options = Object.assign({\n method: \"PUT\",\n body: {\n collections: collections,\n deleteMissing: deleteMissing,\n },\n }, options);\n return this.client.send(this.baseCrudPath + \"/import\", options).then(() => true);\n }\n /**\n * Deletes all records associated with the specified collection.\n *\n * @throws {ClientResponseError}\n */\n async truncate(collectionIdOrName, options) {\n options = Object.assign({\n method: \"DELETE\",\n }, options);\n return this.client\n .send(this.baseCrudPath + \"/\" + encodeURIComponent(collectionIdOrName) + \"/truncate\", options)\n .then(() => true);\n }\n /**\n * Returns type indexed map with scaffolded collection models\n * populated with their default field values.\n *\n * @throws {ClientResponseError}\n */\n async getScaffolds(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(this.baseCrudPath + \"/meta/scaffolds\", options);\n }\n /**\n * Returns a list with all configurable OAuth2 providers.\n *\n * @throws {ClientResponseError}\n */\n async getAllOAuth2Providers(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(this.baseCrudPath + \"/meta/oauth2-providers\", options);\n }\n /**\n * Executes the specified view query and returns a sample of the resulting records.\n *\n * @throws {ClientResponseError}\n */\n async dryRunViewQuery(query, options) {\n options = Object.assign({\n method: \"POST\",\n body: { query },\n }, options);\n return this.client.send(this.baseCrudPath + \"/meta/dry-run-view\", options);\n }\n}\n",
|
|
19
|
+
"// js-sdk v0.28.1 src/services/LogService.ts\nimport { ClientResponseError } from \"@sdk/ClientResponseError\";\nimport { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/dtos\";\nimport {} from \"@sdk/tools/options\";\nexport class LogService extends BaseService {\n /**\n * Returns paginated logs list.\n *\n * @throws {ClientResponseError}\n */\n async getList(page = 1, perPage = 30, options) {\n options = Object.assign({ method: \"GET\" }, options);\n options.query = Object.assign({\n page: page,\n perPage: perPage,\n }, options.query);\n return this.client.send(\"/api/logs\", options);\n }\n /**\n * Returns a single log by its id.\n *\n * If `id` is empty it will throw a 404 error.\n *\n * @throws {ClientResponseError}\n */\n async getOne(id, options) {\n if (!id) {\n throw new ClientResponseError({\n url: this.client.buildURL(\"/api/logs/\"),\n status: 404,\n response: {\n code: 404,\n message: \"Missing required log id.\",\n data: {},\n },\n });\n }\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/logs/\" + encodeURIComponent(id), options);\n }\n /**\n * Returns logs statistics.\n *\n * @throws {ClientResponseError}\n */\n async getStats(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/logs/stats\", options);\n }\n /**\n * Deletes all logs.\n *\n * @throws {ClientResponseError}\n */\n async truncate(options) {\n options = Object.assign({\n method: \"DELETE\",\n }, options);\n return this.client.send(\"/api/logs\", options).then(() => true);\n }\n}\n",
|
|
20
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/options\";\nexport class HealthService extends BaseService {\n /**\n * Checks the health status of the api.\n *\n * @throws {ClientResponseError}\n */\n async check(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/health\", options);\n }\n}\n",
|
|
21
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport { serializeQueryParams } from \"@sdk/tools/options\";\nexport class FileService extends BaseService {\n /**\n * @deprecated Please replace with `pb.files.getURL()`.\n */\n getUrl(record, filename, queryParams = {}) {\n console.warn(\"Please replace pb.files.getUrl() with pb.files.getURL()\");\n return this.getURL(record, filename, queryParams);\n }\n /**\n * Builds and returns an absolute record file url for the provided filename.\n */\n getURL(record, filename, queryParams = {}) {\n if (!filename || !record?.id || !(record?.collectionId || record?.collectionName)) {\n return \"\";\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 let result = this.client.buildURL(parts.join(\"/\"));\n // normalize the download query param for consistency with the Dart sdk\n if (queryParams.download === false) {\n delete queryParams.download;\n }\n const params = serializeQueryParams(queryParams);\n if (params) {\n result += (result.includes(\"?\") ? \"&\" : \"?\") + params;\n }\n return result;\n }\n /**\n * Requests a new private file access token for the current auth model.\n *\n * @throws {ClientResponseError}\n */\n async getToken(options) {\n options = Object.assign({\n method: \"POST\",\n }, options);\n return this.client.send(\"/api/files/token\", options).then((data) => data?.token || \"\");\n }\n}\n",
|
|
22
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/options\";\nexport class BackupService extends BaseService {\n /**\n * Returns list with all available backup files.\n *\n * @throws {ClientResponseError}\n */\n async getFullList(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/backups\", options);\n }\n /**\n * Initializes a new backup.\n *\n * @throws {ClientResponseError}\n */\n async create(basename, options) {\n options = Object.assign({\n method: \"POST\",\n body: {\n name: basename,\n },\n }, options);\n return this.client.send(\"/api/backups\", options).then(() => true);\n }\n /**\n * Uploads an existing backup file.\n *\n * Example:\n *\n * ```js\n * await pb.backups.upload({\n * file: new Blob([...]),\n * });\n * ```\n *\n * @throws {ClientResponseError}\n */\n async upload(bodyParams, options) {\n options = Object.assign({\n method: \"POST\",\n body: bodyParams,\n }, options);\n return this.client.send(\"/api/backups/upload\", options).then(() => true);\n }\n /**\n * Deletes a single backup file.\n *\n * @throws {ClientResponseError}\n */\n async delete(key, options) {\n options = Object.assign({\n method: \"DELETE\",\n }, options);\n return this.client.send(`/api/backups/${encodeURIComponent(key)}`, options).then(() => true);\n }\n /**\n * Initializes an app data restore from an existing backup.\n *\n * @throws {ClientResponseError}\n */\n async restore(key, options) {\n options = Object.assign({\n method: \"POST\",\n }, options);\n return this.client\n .send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n .then(() => true);\n }\n /**\n * @deprecated Please use `getDownloadURL()`.\n */\n getDownloadUrl(token, key) {\n console.warn(\"Please replace pb.backups.getDownloadUrl() with pb.backups.getDownloadURL()\");\n return this.getDownloadURL(token, key);\n }\n /**\n * Builds a download url for a single existing backup using a\n * superuser file token and the backup file key.\n *\n * The file token can be generated via `pb.files.getToken()`.\n */\n getDownloadURL(token, key) {\n return this.client.buildURL(`/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`);\n }\n}\n",
|
|
23
|
+
"// js-sdk v0.28.1 src/services/CronService.ts\nimport { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/options\";\nexport class CronService extends BaseService {\n /**\n * Returns list with all registered cron jobs.\n *\n * @throws {ClientResponseError}\n */\n async getFullList(options) {\n options = Object.assign({\n method: \"GET\",\n }, options);\n return this.client.send(\"/api/crons\", options);\n }\n /**\n * Runs the specified cron job.\n *\n * @throws {ClientResponseError}\n */\n async run(jobId, options) {\n options = Object.assign({\n method: \"POST\",\n }, options);\n return this.client.send(`/api/crons/${encodeURIComponent(jobId)}`, options).then(() => true);\n }\n}\n",
|
|
24
|
+
"// js-sdk v0.28.1 src/services/SQLService.ts\nimport { BaseService } from \"@sdk/services/BaseService\";\nimport {} from \"@sdk/tools/options\";\nexport class SQLService extends BaseService {\n /**\n * Executes the specified raw SQL query.\n * This operation is allowed only for superusers.\n *\n * @throws {ClientResponseError}\n */\n async run(query, options) {\n options = Object.assign({\n method: \"POST\",\n body: { query },\n }, options);\n return this.client.send(\"/api/sql\", options);\n }\n}\n",
|
|
25
|
+
"// js-sdk v0.28.1 src/tools/formdata.ts\n/**\n * Checks if the specified value is a file (aka. File, Blob, RN file object).\n */\nexport function isFile(val) {\n return Boolean((typeof Blob !== \"undefined\" && val instanceof Blob) ||\n (typeof File !== \"undefined\" && val instanceof File) ||\n // check for React Native file object format\n // (see https://github.com/pocketbase/pocketbase/discussions/2002#discussioncomment-5254168)\n (val !== null &&\n typeof val === \"object\" &&\n val.uri &&\n ((typeof navigator !== \"undefined\" && navigator.product === \"ReactNative\") ||\n (typeof global !== \"undefined\" && global.HermesInternal))));\n}\n/**\n * Loosely checks if the specified body is a FormData instance.\n */\nexport function isFormData(body) {\n // the original returns `body` itself when it is falsy; kept as is\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 * Checks if the submitted body object has at least one Blob/File field value.\n */\nexport function hasFileField(body) {\n if (typeof body !== \"object\" || body === null) {\n return false;\n }\n const obj = body;\n for (const key in obj) {\n const values = Array.isArray(obj[key]) ? obj[key] : [obj[key]];\n for (const v of values) {\n if (isFile(v)) {\n return true;\n }\n }\n }\n return false;\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 */\nexport function convertToFormDataIfNeeded(body) {\n if (typeof FormData === \"undefined\" ||\n typeof body === \"undefined\" ||\n typeof body !== \"object\" ||\n body === null ||\n isFormData(body) ||\n !hasFileField(body)) {\n return body;\n }\n const form = new FormData();\n const obj = body;\n for (const key in obj) {\n const val = obj[key];\n // skip undefined values for consistency with JSON.stringify\n // (see https://github.com/pocketbase/pocketbase/issues/6731#issuecomment-2812382827)\n if (typeof val === \"undefined\") {\n continue;\n }\n if (typeof val === \"object\" && !hasFileField({ data: val })) {\n // send json-like values as jsonPayload to avoid the implicit string value normalization\n const payload = {};\n payload[key] = val;\n form.append(\"@jsonPayload\", JSON.stringify(payload));\n }\n else {\n // in case of mixed string and file/blob\n const normalizedVal = Array.isArray(val) ? val : [val];\n for (const v of normalizedVal) {\n form.append(key, v);\n }\n }\n }\n return form;\n}\n/**\n * Converts the provided FormData instance into a plain object.\n *\n * For consistency with the server multipart/form-data inferring,\n * the following normalization rules are applied for plain multipart string values:\n * - \"true\" is converted to the json \"true\"\n * - \"false\" is converted to the json \"false\"\n * - numeric strings are converted to json number ONLY if the resulted\n * minimal number string representation is the same as the provided raw string\n * (aka. scientific notations, \"Infinity\", \"0.0\", \"0001\", etc. are kept as string)\n * - any other string (empty string too) is left as it is\n */\nexport function convertFormDataToObject(formData) {\n const result = {};\n formData.forEach((v, k) => {\n if (k === \"@jsonPayload\" && typeof v == \"string\") {\n try {\n const parsed = JSON.parse(v);\n if (typeof parsed === \"object\" && parsed !== null) {\n Object.assign(result, parsed);\n }\n }\n catch (err) {\n console.warn(\"@jsonPayload error:\", err);\n }\n }\n else {\n if (typeof result[k] !== \"undefined\") {\n if (!Array.isArray(result[k])) {\n result[k] = [result[k]];\n }\n result[k].push(inferFormDataValue(v));\n }\n else {\n result[k] = inferFormDataValue(v);\n }\n }\n });\n return result;\n}\nconst inferNumberCharsRegex = /^[-.\\d]+$/;\nfunction inferFormDataValue(value) {\n if (typeof value != \"string\") {\n return value;\n }\n if (value == \"true\") {\n return true;\n }\n if (value == \"false\") {\n return false;\n }\n // note: expects the provided raw string to match exactly with the minimal string representation of the parsed number\n if ((value[0] === \"-\" || (value[0] >= \"0\" && value[0] <= \"9\")) &&\n inferNumberCharsRegex.test(value)) {\n let num = +value;\n if (\"\" + num === value) {\n return num;\n }\n }\n return value;\n}\n",
|
|
26
|
+
"import { BaseService } from \"@sdk/services/BaseService\";\nimport { isFile, isFormData, convertFormDataToObject } from \"@sdk/tools/formdata\";\nimport { normalizeUnknownQueryParams, serializeQueryParams, } from \"@sdk/tools/options\";\nexport class BatchService extends BaseService {\n constructor() {\n super(...arguments);\n this.requests = [];\n this.subs = {};\n }\n /**\n * Starts constructing a batch request entry for the specified collection.\n */\n collection(collectionIdOrName) {\n if (!this.subs[collectionIdOrName]) {\n this.subs[collectionIdOrName] = new SubBatchService(this.requests, collectionIdOrName);\n }\n return this.subs[collectionIdOrName];\n }\n /**\n * Sends the batch requests.\n *\n * @throws {ClientResponseError}\n */\n async send(options) {\n const formData = new FormData();\n const jsonData = [];\n for (let i = 0; i < this.requests.length; i++) {\n const req = this.requests[i];\n jsonData.push({\n method: req.method,\n url: req.url,\n headers: req.headers,\n body: req.json,\n });\n if (req.files) {\n for (let key in req.files) {\n const files = req.files[key] || [];\n for (let file of files) {\n formData.append(\"requests.\" + i + \".\" + key, file);\n }\n }\n }\n }\n formData.append(\"@jsonPayload\", JSON.stringify({ requests: jsonData }));\n options = Object.assign({\n method: \"POST\",\n body: formData,\n }, options);\n return this.client.send(\"/api/batch\", options);\n }\n}\nexport class SubBatchService {\n constructor(requests, collectionIdOrName) {\n this.requests = [];\n this.requests = requests;\n this.collectionIdOrName = collectionIdOrName;\n }\n /**\n * Registers a record upsert request into the current batch queue.\n *\n * The request will be executed as update if `bodyParams` have a valid existing record `id` value, otherwise - create.\n */\n upsert(bodyParams, options) {\n options = Object.assign({\n body: bodyParams || {},\n }, options);\n const request = {\n method: \"PUT\",\n url: \"/api/collections/\" + encodeURIComponent(this.collectionIdOrName) + \"/records\",\n };\n this.prepareRequest(request, options);\n this.requests.push(request);\n }\n /**\n * Registers a record create request into the current batch queue.\n */\n create(bodyParams, options) {\n options = Object.assign({\n body: bodyParams || {},\n }, options);\n const request = {\n method: \"POST\",\n url: \"/api/collections/\" + encodeURIComponent(this.collectionIdOrName) + \"/records\",\n };\n this.prepareRequest(request, options);\n this.requests.push(request);\n }\n /**\n * Registers a record update request into the current batch queue.\n */\n update(id, bodyParams, options) {\n options = Object.assign({\n body: bodyParams || {},\n }, options);\n const request = {\n method: \"PATCH\",\n url: \"/api/collections/\" +\n encodeURIComponent(this.collectionIdOrName) +\n \"/records/\" +\n encodeURIComponent(id),\n };\n this.prepareRequest(request, options);\n this.requests.push(request);\n }\n /**\n * Registers a record delete request into the current batch queue.\n */\n delete(id, options) {\n options = Object.assign({}, options);\n const request = {\n method: \"DELETE\",\n url: \"/api/collections/\" +\n encodeURIComponent(this.collectionIdOrName) +\n \"/records/\" +\n encodeURIComponent(id),\n };\n this.prepareRequest(request, options);\n this.requests.push(request);\n }\n prepareRequest(request, options) {\n normalizeUnknownQueryParams(options);\n request.headers = options.headers;\n request.json = {};\n request.files = {};\n // serialize query parameters\n // -----------------------------------------------------------\n if (typeof options.query !== \"undefined\") {\n const query = serializeQueryParams(options.query);\n if (query) {\n request.url += (request.url.includes(\"?\") ? \"&\" : \"?\") + query;\n }\n }\n // extract json and files body data\n // -----------------------------------------------------------\n let body = options.body;\n if (isFormData(body)) {\n body = convertFormDataToObject(body);\n }\n for (const key in body) {\n const val = body[key];\n if (isFile(val)) {\n request.files[key] = request.files[key] || [];\n request.files[key].push(val);\n }\n else if (Array.isArray(val)) {\n const foundFiles = [];\n const foundRegular = [];\n for (const v of val) {\n if (isFile(v)) {\n foundFiles.push(v);\n }\n else {\n foundRegular.push(v);\n }\n }\n if (foundFiles.length > 0 && foundFiles.length == val.length) {\n // only files\n // ---\n request.files[key] = request.files[key] || [];\n for (let file of foundFiles) {\n request.files[key].push(file);\n }\n }\n else {\n // empty or mixed array (both regular and File/Blob values)\n // ---\n request.json[key] = foundRegular;\n if (foundFiles.length > 0) {\n // add \"+\" to append if not already since otherwise\n // the existing regular files will be deleted\n // (the mixed values order is preserved only within their corresponding groups)\n let fileKey = key;\n if (!key.startsWith(\"+\") && !key.endsWith(\"+\")) {\n fileKey += \"+\";\n }\n request.files[fileKey] = request.files[fileKey] || [];\n for (let file of foundFiles) {\n request.files[fileKey].push(file);\n }\n }\n }\n }\n else {\n request.json[key] = val;\n }\n }\n }\n}\n",
|
|
27
|
+
"import { ClientResponseError } from \"@sdk/ClientResponseError\";\nimport { BaseAuthStore } from \"@sdk/stores/BaseAuthStore\";\nimport { LocalAuthStore } from \"@sdk/stores/LocalAuthStore\";\nimport { SettingsService } from \"@sdk/services/SettingsService\";\nimport { RecordService } from \"@sdk/services/RecordService\";\nimport { CollectionService } from \"@sdk/services/CollectionService\";\nimport { LogService } from \"@sdk/services/LogService\";\nimport { RealtimeService } from \"@sdk/services/RealtimeService\";\nimport { HealthService } from \"@sdk/services/HealthService\";\nimport { FileService } from \"@sdk/services/FileService\";\nimport { BackupService } from \"@sdk/services/BackupService\";\nimport { CronService } from \"@sdk/services/CronService\";\nimport { SQLService } from \"@sdk/services/SQLService\";\nimport { BatchService } from \"@sdk/services/BatchService\";\nimport {} from \"@sdk/tools/dtos\";\nimport { normalizeUnknownQueryParams, serializeQueryParams, } from \"@sdk/tools/options\";\nimport { isFormData, convertToFormDataIfNeeded } from \"@sdk/tools/formdata\";\nif (!RegExp.escape) {\n // https://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript#answer-3561711\n RegExp.escape = function (str) {\n return str.replace(/[/\\-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n };\n}\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * Legacy getter alias for baseURL.\n * @deprecated Please replace with baseURL.\n */\n get baseUrl() {\n return this.baseURL;\n }\n /**\n * Legacy setter alias for baseURL.\n * @deprecated Please replace with baseURL.\n */\n set baseUrl(v) {\n this.baseURL = v;\n }\n constructor(baseURL = \"/\", authStore, lang = \"en-US\") {\n this.cancelControllers = {};\n this.recordServices = {};\n this.enableAutoCancellation = true;\n this.baseURL = baseURL;\n this.lang = lang;\n if (authStore) {\n this.authStore = authStore;\n }\n else if (typeof window != \"undefined\" && !!window.Deno) {\n // note: to avoid common security issues we fallback to runtime/memory store in case the code is running in Deno env\n this.authStore = new BaseAuthStore();\n }\n else {\n this.authStore = new LocalAuthStore();\n }\n // common services\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 this.crons = new CronService(this);\n this.sql = new SQLService(this);\n }\n /**\n * @deprecated\n * With PocketBase v0.23.0 admins are converted to a regular auth\n * collection named \"_superusers\", aka. you can use directly collection(\"_superusers\").\n */\n get admins() {\n return this.collection(\"_superusers\");\n }\n /**\n * Creates a new batch handler for sending multiple transactional\n * create/update/upsert/delete collection requests in one network call.\n *\n * Example:\n * ```js\n * const batch = pb.createBatch();\n *\n * batch.collection(\"example1\").create({ ... })\n * batch.collection(\"example2\").update(\"RECORD_ID\", { ... })\n * batch.collection(\"example3\").delete(\"RECORD_ID\")\n * batch.collection(\"example4\").upsert({ ... })\n *\n * await batch.send()\n * ```\n */\n createBatch() {\n return new BatchService(this);\n }\n /**\n * Returns the RecordService associated to the specified collection.\n */\n collection(idOrName) {\n if (!this.recordServices[idOrName]) {\n this.recordServices[idOrName] = new RecordService(this, idOrName);\n }\n return this.recordServices[idOrName];\n }\n /**\n * Globally enable or disable auto cancellation for pending duplicated requests.\n */\n autoCancellation(enable) {\n this.enableAutoCancellation = !!enable;\n return this;\n }\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(requestKey) {\n if (this.cancelControllers[requestKey]) {\n this.cancelControllers[requestKey].abort();\n delete this.cancelControllers[requestKey];\n }\n return this;\n }\n /**\n * Cancels all pending requests.\n */\n cancelAllRequests() {\n for (let k in this.cancelControllers) {\n this.cancelControllers[k]?.abort();\n }\n this.cancelControllers = {};\n return this;\n }\n /**\n * Constructs a filter expression with placeholders populated from a parameters object.\n *\n * Placeholder parameters are defined with the `{:paramName}` notation.\n *\n * The following parameter values are supported:\n *\n * - `string`\n * - `number`\n * - `boolean`\n * - `null`\n * - `undefined` (stringified as \"null\")\n * - `Date` object (_stringified into the PocketBase datetime format_)\n * - everything else is converted to a string using `JSON.stringify()`\n *\n * Example:\n *\n * ```js\n * pb.collection(\"example\").getFirstListItem(pb.filter(\n * 'title ~ {:title} && created >= {:created}',\n * { title: \"example\", created: new Date()}\n * ))\n * ```\n */\n filter(raw, params) {\n if (!params) {\n return raw;\n }\n const paramsWithPlaceholders = {};\n for (const k in params) {\n paramsWithPlaceholders[\"{:\" + k + \"}\"] = params[k];\n }\n const pattern = Object.keys(paramsWithPlaceholders)\n .map((k) => RegExp.escape(k))\n .join(\"|\");\n if (!pattern) {\n return raw; // no params to replace\n }\n // oxlint-disable-next-line unicorn/consistent-function-scoping -- keeps stringify scoped inside filter\n function stringify(val) {\n switch (typeof val) {\n case \"boolean\":\n case \"number\":\n return \"\" + val;\n case \"string\":\n return JSON.stringify(val);\n default:\n if (val == null) {\n return \"null\";\n }\n if (val instanceof Date) {\n return JSON.stringify(val.toISOString().replace(\"T\", \" \"));\n }\n const stringified = JSON.stringify(val);\n // wrap in double quotes in case of regular array, object, etc.\n if (stringified.startsWith(\"[\") || stringified.startsWith(\"{\")) {\n return JSON.stringify(stringified);\n }\n return stringified;\n }\n }\n return raw.replace(new RegExp(pattern, \"g\"), (match) => stringify(paramsWithPlaceholders[match]));\n }\n /**\n * @deprecated Please use `pb.files.getURL()`.\n */\n getFileUrl(record, filename, queryParams = {}) {\n console.warn(\"Please replace pb.getFileUrl() with pb.files.getURL()\");\n return this.files.getURL(record, filename, queryParams);\n }\n /**\n * @deprecated Please use `pb.buildURL()`.\n */\n buildUrl(path) {\n console.warn(\"Please replace pb.buildUrl() with pb.buildURL()\");\n return this.buildURL(path);\n }\n /**\n * Builds a full client url by safely concatenating the provided path.\n */\n buildURL(path) {\n let url = this.baseURL;\n // construct an absolute base url if in a browser environment\n if (typeof window !== \"undefined\" &&\n !!window.location &&\n !url.startsWith(\"https://\") &&\n !url.startsWith(\"http://\")) {\n url = window.location.origin?.endsWith(\"/\")\n ? window.location.origin.substring(0, window.location.origin.length - 1)\n : window.location.origin || \"\";\n if (!this.baseURL.startsWith(\"/\")) {\n url += window.location.pathname || \"/\";\n url += url.endsWith(\"/\") ? \"\" : \"/\";\n }\n url += this.baseURL;\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 return url;\n }\n /**\n * Sends an api http request.\n *\n * @throws {ClientResponseError}\n */\n async send(path, options) {\n options = this.initSendOptions(path, options);\n // build url + path\n let url = this.buildURL(path);\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 }\n else if (Object.keys(result).length) {\n // legacy behavior\n options = result;\n // oxlint-disable-next-line no-unused-expressions -- upstream short-circuit logging\n console?.warn &&\n console.warn(\"Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.\");\n }\n }\n // serialize the query parameters\n if (typeof options.query !== \"undefined\") {\n const query = serializeQueryParams(options.query);\n if (query) {\n url += (url.includes(\"?\") ? \"&\" : \"?\") + query;\n }\n delete options.query;\n }\n // ensures that the json body is serialized\n if (this.getHeader(options.headers, \"Content-Type\") == \"application/json\" &&\n options.body &&\n typeof options.body !== \"string\") {\n options.body = JSON.stringify(options.body);\n }\n // early throw an abort error in case the request was already cancelled\n const fetchFunc = options.fetch || fetch;\n // send the request\n return fetchFunc(url, options)\n .then(async (response) => {\n let data = {};\n try {\n data = await response.json();\n }\n catch (err) {\n // @todo map against the response content type\n // all api responses are expected to return json\n // with exception of the realtime events and 204\n if (options.signal?.aborted ||\n err?.name == \"AbortError\" ||\n err?.message == \"Aborted\") {\n throw err;\n }\n }\n if (this.afterSend) {\n data = await this.afterSend(response, data, options);\n }\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n return data;\n })\n .catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\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 initSendOptions(path, options) {\n options = Object.assign({ method: \"GET\" }, options);\n // auto convert the body to FormData, if needed\n options.body = convertToFormDataIfNeeded(options.body);\n // move unknown send options as query parameters\n normalizeUnknownQueryParams(options);\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 }\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 // 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 (this.getHeader(options.headers, \"Content-Type\") === null && !isFormData(options.body)) {\n options.headers = Object.assign({}, options.headers, {\n \"Content-Type\": \"application/json\",\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 // 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 options.headers = Object.assign({}, options.headers, {\n Authorization: this.authStore.token,\n });\n }\n // handle auto cancellation for duplicated pending request\n if (this.enableAutoCancellation && options.requestKey !== null) {\n const requestKey = options.requestKey || (options.method || \"GET\") + path;\n delete options.requestKey;\n // cancel previous pending requests\n this.cancelRequest(requestKey);\n // @todo evaluate if a cleanup after the request is necessary\n // (check also authWithOAuth2 as it currently relies on the controller)\n const controller = new AbortController();\n this.cancelControllers[requestKey] = controller;\n options.signal = controller.signal;\n }\n return options;\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 getHeader(headers, name) {\n headers = headers || {};\n name = name.toLowerCase();\n for (let key in headers) {\n if (key.toLowerCase() == name) {\n return headers[key];\n }\n }\n return null;\n }\n}\n",
|
|
28
|
+
"// js-sdk v0.28.1 src/stores/AsyncAuthStore.ts\nimport { BaseAuthStore } from \"@sdk/stores/BaseAuthStore\";\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: AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n constructor(config) {\n super();\n this.queue = [];\n this.saveFunc = config.save;\n this.clearFunc = config.clear;\n this._enqueue(() => this._loadInitial(config.initial));\n }\n /**\n * @inheritdoc\n */\n save(token, record) {\n super.save(token, record);\n let value = \"\";\n try {\n value = JSON.stringify({ token, record });\n }\n catch {\n console.warn(\"AsyncAuthStore: failed to stringify the new state\");\n }\n this._enqueue(() => this.saveFunc(value));\n }\n /**\n * @inheritdoc\n */\n clear() {\n super.clear();\n if (this.clearFunc) {\n this._enqueue(() => this.clearFunc());\n }\n else {\n this._enqueue(() => this.saveFunc(\"\"));\n }\n }\n /**\n * Initializes the auth store state.\n */\n async _loadInitial(payload) {\n try {\n const resolved = await payload;\n if (resolved) {\n let parsed;\n if (typeof resolved === \"string\") {\n const json = JSON.parse(resolved);\n if (typeof json === \"object\" && json !== null) {\n parsed = json;\n }\n else {\n parsed = {};\n }\n }\n else if (typeof resolved === \"object\" && resolved !== null) {\n parsed = resolved;\n }\n const token = typeof parsed.token === \"string\" ? parsed.token : \"\";\n const recordOrModel = (parsed.record || parsed.model || null);\n this.save(token, recordOrModel);\n }\n }\n catch { }\n }\n /**\n * Appends an async function to the queue.\n */\n _enqueue(asyncCallback) {\n this.queue.push(asyncCallback);\n if (this.queue.length == 1) {\n this._dequeue();\n }\n }\n /**\n * Starts the queue processing.\n */\n _dequeue() {\n if (!this.queue.length) {\n return;\n }\n this.queue[0]().finally(() => {\n this.queue.shift();\n if (!this.queue.length) {\n return;\n }\n this._dequeue();\n });\n }\n}\n",
|
|
29
|
+
"// js-sdk v0.28.1 src/index.ts\nimport Client from \"@sdk/Client\";\nexport * from \"@sdk/Client\";\nexport * from \"@sdk/ClientResponseError\";\nexport * from \"@sdk/services/CollectionService\";\nexport * from \"@sdk/services/HealthService\";\nexport * from \"@sdk/services/LogService\";\nexport * from \"@sdk/services/RealtimeService\";\nexport * from \"@sdk/services/RecordService\";\nexport * from \"@sdk/services/CrudService\";\nexport * from \"@sdk/services/BatchService\";\nexport * from \"@sdk/stores/AsyncAuthStore\";\nexport * from \"@sdk/stores/BaseAuthStore\";\nexport * from \"@sdk/stores/LocalAuthStore\";\nexport * from \"@sdk/tools/dtos\";\nexport * from \"@sdk/tools/options\";\nexport * from \"@sdk/tools/cookie\";\nexport * from \"@sdk/tools/jwt\";\nexport default Client;\n"
|
|
30
|
+
],
|
|
31
|
+
"mappings": "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",
|
|
32
|
+
"debugId": "7619569752442DB464756E2164756E21",
|
|
33
|
+
"names": []
|
|
34
|
+
}
|