{"version":3,"file":"pocketbase.es.mjs","sources":["../src/ClientResponseError.ts","../src/tools/cookie.ts","../src/tools/jwt.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/BaseService.ts","../src/services/SettingsService.ts","../src/tools/options.ts","../src/services/RealtimeService.ts","../src/services/CrudService.ts","../src/tools/legacy.ts","../src/tools/refresh.ts","../src/services/RecordService.ts","../src/services/CollectionService.ts","../src/services/LogService.ts","../src/services/HealthService.ts","../src/services/FileService.ts","../src/services/BackupService.ts","../src/services/CronService.ts","../src/tools/formdata.ts","../src/services/BatchService.ts","../src/Client.ts","../src/stores/AsyncAuthStore.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport class ClientResponseError extends Error {\n    url: string = \"\";\n    status: number = 0;\n    response: { [key: string]: any } = {};\n    isAbort: boolean = false;\n    originalError: any = null;\n\n    constructor(errData?: any) {\n        super(\"ClientResponseError\");\n\n        // Set the prototype explicitly.\n        // https://github.com/Microsoft/TypeScript-wiki/blob/main/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n        Object.setPrototypeOf(this, ClientResponseError.prototype);\n\n        if (errData !== null && typeof errData === \"object\") {\n            this.url = typeof errData.url === \"string\" ? errData.url : \"\";\n            this.status = typeof errData.status === \"number\" ? errData.status : 0;\n            this.isAbort = !!errData.isAbort;\n            this.originalError = errData.originalError;\n\n            if (errData.response !== null && typeof errData.response === \"object\") {\n                this.response = errData.response;\n            } else if (errData.data !== null && typeof errData.data === \"object\") {\n                this.response = errData.data;\n            } else {\n                this.response = {};\n            }\n        }\n\n        if (!this.originalError && !(errData instanceof ClientResponseError)) {\n            this.originalError = errData;\n        }\n\n        if (typeof DOMException !== \"undefined\" && errData instanceof DOMException) {\n            this.isAbort = true;\n        }\n\n        this.name = \"ClientResponseError \" + this.status;\n        this.message = this.response?.message;\n        if (!this.message) {\n            if (this.isAbort) {\n                this.message =\n                    \"The request was autocancelled. You can find more info in https://github.com/pocketbase/js-sdk#auto-cancellation.\";\n            } else if (this.originalError?.cause?.message?.includes(\"ECONNREFUSED ::1\")) {\n                this.message =\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            } else {\n                this.message = \"Something went wrong while processing your request.\";\n            }\n        }\n    }\n\n    /**\n     * Alias for `this.response` for backward compatibility.\n     */\n    get data() {\n        return this.response;\n    }\n\n    /**\n     * Make a POJO's copy of the current error class instance.\n     * @see https://github.com/vuex-orm/vuex-orm/issues/255\n     */\n    toJSON() {\n        return { ...this };\n    }\n}\n","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar   = VCHAR / obs-text\n * obs-text      = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions {\n    decode?: (val: string) => string;\n}\n\n/**\n * Parses the given cookie header string into an object\n * The object has the various cookies as keys(names) => values\n */\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n    const result: { [key: string]: any } = {};\n\n    if (typeof str !== \"string\") {\n        return result;\n    }\n\n    const opt = Object.assign({}, options || {});\n    const decode = opt.decode || defaultDecode;\n\n    let index = 0;\n    while (index < str.length) {\n        const eqIdx = str.indexOf(\"=\", index);\n\n        // no more cookie pairs\n        if (eqIdx === -1) {\n            break;\n        }\n\n        let endIdx = str.indexOf(\";\", index);\n\n        if (endIdx === -1) {\n            endIdx = str.length;\n        } else if (endIdx < eqIdx) {\n            // backtrack on prior semicolon\n            index = str.lastIndexOf(\";\", eqIdx - 1) + 1;\n            continue;\n        }\n\n        const key = str.slice(index, eqIdx).trim();\n\n        // only assign once\n        if (undefined === result[key]) {\n            let val = str.slice(eqIdx + 1, endIdx).trim();\n\n            // quoted values\n            if (val.charCodeAt(0) === 0x22) {\n                val = val.slice(1, -1);\n            }\n\n            try {\n                result[key] = decode(val);\n            } catch (_) {\n                result[key] = val; // no decoding\n            }\n        }\n\n        index = endIdx + 1;\n    }\n\n    return result;\n}\n\nexport interface SerializeOptions {\n    encode?: (val: string | number | boolean) => string;\n    maxAge?: number;\n    domain?: string;\n    path?: string;\n    expires?: Date;\n    httpOnly?: boolean;\n    secure?: boolean;\n    priority?: string;\n    sameSite?: boolean | string;\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(\n    name: string,\n    val: string,\n    options?: SerializeOptions,\n): string {\n    const opt = Object.assign({}, options || {});\n    const encode = opt.encode || defaultEncode;\n\n    if (!fieldContentRegExp.test(name)) {\n        throw new TypeError(\"argument name is invalid\");\n    }\n\n    const value = encode(val);\n\n    if (value && !fieldContentRegExp.test(value)) {\n        throw new TypeError(\"argument val is invalid\");\n    }\n\n    let result = name + \"=\" + value;\n\n    if (opt.maxAge != null) {\n        const maxAge = opt.maxAge - 0;\n\n        if (isNaN(maxAge) || !isFinite(maxAge)) {\n            throw new TypeError(\"option maxAge is invalid\");\n        }\n\n        result += \"; Max-Age=\" + Math.floor(maxAge);\n    }\n\n    if (opt.domain) {\n        if (!fieldContentRegExp.test(opt.domain)) {\n            throw new TypeError(\"option domain is invalid\");\n        }\n\n        result += \"; Domain=\" + opt.domain;\n    }\n\n    if (opt.path) {\n        if (!fieldContentRegExp.test(opt.path)) {\n            throw new TypeError(\"option path is invalid\");\n        }\n\n        result += \"; Path=\" + opt.path;\n    }\n\n    if (opt.expires) {\n        if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n            throw new TypeError(\"option expires is invalid\");\n        }\n\n        result += \"; Expires=\" + opt.expires.toUTCString();\n    }\n\n    if (opt.httpOnly) {\n        result += \"; HttpOnly\";\n    }\n\n    if (opt.secure) {\n        result += \"; Secure\";\n    }\n\n    if (opt.priority) {\n        const priority =\n            typeof opt.priority === \"string\" ? opt.priority.toLowerCase() : opt.priority;\n\n        switch (priority) {\n            case \"low\":\n                result += \"; Priority=Low\";\n                break;\n            case \"medium\":\n                result += \"; Priority=Medium\";\n                break;\n            case \"high\":\n                result += \"; Priority=High\";\n                break;\n            default:\n                throw new TypeError(\"option priority is invalid\");\n        }\n    }\n\n    if (opt.sameSite) {\n        const sameSite =\n            typeof opt.sameSite === \"string\" ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n        switch (sameSite) {\n            case true:\n                result += \"; SameSite=Strict\";\n                break;\n            case \"lax\":\n                result += \"; SameSite=Lax\";\n                break;\n            case \"strict\":\n                result += \"; SameSite=Strict\";\n                break;\n            case \"none\":\n                result += \"; SameSite=None\";\n                break;\n            default:\n                throw new TypeError(\"option sameSite is invalid\");\n        }\n    }\n\n    return result;\n}\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n    return val.indexOf(\"%\") !== -1 ? decodeURIComponent(val) : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n    return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n    return Object.prototype.toString.call(val) === \"[object Date]\" || val instanceof Date;\n}\n","// @todo remove after https://github.com/reactwg/react-native-releases/issues/287\nconst isReactNative =\n    (typeof navigator !== \"undefined\" && navigator.product === \"ReactNative\") ||\n    (typeof global !== \"undefined\" && (global as any).HermesInternal);\n\nlet atobPolyfill: Function;\nif (typeof atob === \"function\" && !isReactNative) {\n    atobPolyfill = atob;\n} else {\n    /**\n     * The code was extracted from:\n     * https://github.com/davidchambers/Base64.js\n     */\n    atobPolyfill = (input: any) => {\n        const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n        let str = String(input).replace(/=+$/, \"\");\n        if (str.length % 4 == 1) {\n            throw new Error(\n                \"'atob' failed: The string to be decoded is not correctly encoded.\",\n            );\n        }\n\n        for (\n            // initialize result and counters\n            var bc = 0, bs, buffer, idx = 0, output = \"\";\n            // get next character\n            (buffer = str.charAt(idx++));\n            // character found in table? initialize bit storage and add its ascii value;\n            ~buffer &&\n            ((bs = bc % 4 ? (bs as any) * 64 + buffer : buffer),\n            // and if not first of each 4 characters,\n            // convert the first 8 bits to one ascii character\n            bc++ % 4)\n                ? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))\n                : 0\n        ) {\n            // try to find character in table (0-63, not found => -1)\n            buffer = chars.indexOf(buffer);\n        }\n\n        return output;\n    };\n}\n\n/**\n * Returns JWT token's payload data.\n */\nexport function getTokenPayload(token: string): { [key: string]: any } {\n    if (token) {\n        try {\n            const encodedPayload = decodeURIComponent(\n                atobPolyfill(token.split(\".\")[1])\n                    .split(\"\")\n                    .map(function (c: string) {\n                        return \"%\" + (\"00\" + c.charCodeAt(0).toString(16)).slice(-2);\n                    })\n                    .join(\"\"),\n            );\n\n            return JSON.parse(encodedPayload) || {};\n        } catch (e) {}\n    }\n\n    return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be subtracted from the token `exp` property.\n */\nexport function isTokenExpired(token: string, expirationThreshold = 0): boolean {\n    let payload = getTokenPayload(token);\n\n    if (\n        Object.keys(payload).length > 0 &&\n        (!payload.exp || payload.exp - expirationThreshold > Date.now() / 1000)\n    ) {\n        return false;\n    }\n\n    return true;\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from \"@/tools/cookie\";\nimport { isTokenExpired, getTokenPayload } from \"@/tools/jwt\";\nimport { RecordModel } from \"@/tools/dtos\";\n\nexport type AuthRecord = RecordModel | null;\n\nexport type AuthModel = AuthRecord; // for backward compatibility\n\nexport type OnStoreChangeFunc = (token: string, record: AuthRecord) => void;\n\nconst defaultCookieKey = \"pb_auth\";\n\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    protected baseToken: string = \"\";\n    protected baseModel: AuthRecord = null;\n\n    private _onChangeCallbacks: Array<OnStoreChangeFunc> = [];\n\n    /**\n     * Retrieves the stored token (if any).\n     */\n    get token(): string {\n        return this.baseToken;\n    }\n\n    /**\n     * Retrieves the stored model data (if any).\n     */\n    get record(): AuthRecord {\n        return this.baseModel;\n    }\n\n    /**\n     * @deprecated use `record` instead.\n     */\n    get model(): AuthRecord {\n        return this.baseModel;\n    }\n\n    /**\n     * Loosely checks if the store has valid token (aka. existing and unexpired exp claim).\n     */\n    get isValid(): boolean {\n        return !isTokenExpired(this.token);\n    }\n\n    /**\n     * 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(): boolean {\n        let payload = getTokenPayload(this.token);\n\n        return (\n            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 &&\n                    payload.collectionId == \"pbc_3142635823\"))\n        );\n    }\n\n    /**\n     * @deprecated use `isSuperuser` instead or simply check the record.collectionName property.\n     */\n    get isAdmin(): boolean {\n        console.warn(\n            \"Please replace pb.authStore.isAdmin with pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName\",\n        );\n        return this.isSuperuser;\n    }\n\n    /**\n     * @deprecated use `!isSuperuser` instead or simply check the record.collectionName property.\n     */\n    get isAuthRecord(): boolean {\n        console.warn(\n            \"Please replace pb.authStore.isAuthRecord with !pb.authStore.isSuperuser OR simply check the value of pb.authStore.record?.collectionName\",\n        );\n        return getTokenPayload(this.token).type == \"auth\" && !this.isSuperuser;\n    }\n\n    /**\n     * Saves the provided new token and model data in the auth store.\n     */\n    save(token: string, record?: AuthRecord): void {\n        this.baseToken = token || \"\";\n        this.baseModel = record || null;\n\n        this.triggerChange();\n    }\n\n    /**\n     * Removes the stored token and model data form the auth store.\n     */\n    clear(): void {\n        this.baseToken = \"\";\n        this.baseModel = null;\n        this.triggerChange();\n    }\n\n    /**\n     * Parses the provided cookie string and updates the store state\n     * with the cookie's token and model data.\n     *\n     * NB! This function doesn't validate the token or its data.\n     * Usually this isn't a concern if you are interacting only with the\n     * PocketBase API because it has the proper server-side security checks in place,\n     * but if you are using the store `isValid` state for permission controls\n     * in a node server (eg. SSR), then it is recommended to call `authRefresh()`\n     * after loading the cookie to ensure an up-to-date token and model state.\n     * For example:\n     *\n     * ```js\n     * pb.authStore.loadFromCookie(\"cookie string...\");\n     *\n     * try {\n     *     // get an up-to-date auth store state by veryfing and refreshing the loaded auth model (if any)\n     *     pb.authStore.isValid && await pb.collection('users').authRefresh();\n     * } catch (_) {\n     *     // clear the auth store on failed refresh\n     *     pb.authStore.clear();\n     * }\n     * ```\n     */\n    loadFromCookie(cookie: string, key = defaultCookieKey): void {\n        const rawData = cookieParse(cookie || \"\")[key] || \"\";\n\n        let data: { [key: string]: any } = {};\n        try {\n            data = JSON.parse(rawData);\n            // normalize\n            if (typeof data === null || typeof data !== \"object\" || Array.isArray(data)) {\n                data = {};\n            }\n        } catch (_) {}\n\n        this.save(data.token || \"\", data.record || data.model || null);\n    }\n\n    /**\n     * Exports the current store state as cookie string.\n     *\n     * By default the following optional attributes are added:\n     * - Secure\n     * - HttpOnly\n     * - SameSite=Strict\n     * - Path=/\n     * - Expires={the token expiration date}\n     *\n     * NB! If the generated cookie exceeds 4096 bytes, this method will\n     * strip the model data to the bare minimum to try to fit within the\n     * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n     */\n    exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n        const defaultOptions: SerializeOptions = {\n            secure: true,\n            sameSite: true,\n            httpOnly: true,\n            path: \"/\",\n        };\n\n        // extract the token expiration date\n        const payload = getTokenPayload(this.token);\n        if (payload?.exp) {\n            defaultOptions.expires = new Date(payload.exp * 1000);\n        } else {\n            defaultOptions.expires = new Date(\"1970-01-01\");\n        }\n\n        // merge with the user defined options\n        options = Object.assign({}, defaultOptions, options);\n\n        const rawData = {\n            token: this.token,\n            record: this.record ? JSON.parse(JSON.stringify(this.record)) : null,\n        };\n\n        let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n        const resultLength =\n            typeof Blob !== \"undefined\" ? new Blob([result]).size : result.length;\n\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\n        return result;\n    }\n\n    /**\n     * Register a callback function that will be called on store change.\n     *\n     * You can set the `fireImmediately` argument to true in order to invoke\n     * the provided callback right after registration.\n     *\n     * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n     */\n    onChange(callback: OnStoreChangeFunc, fireImmediately = false): () => void {\n        this._onChangeCallbacks.push(callback);\n\n        if (fireImmediately) {\n            callback(this.token, this.record);\n        }\n\n        return () => {\n            for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n                if (this._onChangeCallbacks[i] == callback) {\n                    delete this._onChangeCallbacks[i]; // removes the function reference\n                    this._onChangeCallbacks.splice(i, 1); // reindex the array\n                    return;\n                }\n            }\n        };\n    }\n\n    protected triggerChange(): void {\n        for (const callback of this._onChangeCallbacks) {\n            callback && callback(this.token, this.record);\n        }\n    }\n}\n","import { BaseAuthStore, AuthRecord } from \"@/stores/BaseAuthStore\";\n\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    private storageFallback: { [key: string]: any } = {};\n    private storageKey: string;\n\n    constructor(storageKey = \"pocketbase_auth\") {\n        super();\n\n        this.storageKey = storageKey;\n\n        this._bindStorageEvent();\n    }\n\n    /**\n     * @inheritdoc\n     */\n    get token(): string {\n        const data = this._storageGet(this.storageKey) || {};\n\n        return data.token || \"\";\n    }\n\n    /**\n     * @inheritdoc\n     */\n    get record(): AuthRecord {\n        const data = this._storageGet(this.storageKey) || {};\n\n        return data.record || data.model || null;\n    }\n\n    /**\n     * @deprecated use `record` instead.\n     */\n    get model(): AuthRecord {\n        return this.record;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    save(token: string, record?: AuthRecord) {\n        this._storageSet(this.storageKey, {\n            token: token,\n            record: record,\n        });\n\n        super.save(token, record);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    clear() {\n        this._storageRemove(this.storageKey);\n\n        super.clear();\n    }\n\n    // ---------------------------------------------------------------\n    // Internal helpers:\n    // ---------------------------------------------------------------\n\n    /**\n     * Retrieves `key` from the browser's local storage\n     * (or runtime/memory if local storage is undefined).\n     */\n    private _storageGet(key: string): any {\n        if (typeof window !== \"undefined\" && window?.localStorage) {\n            const rawValue = window.localStorage.getItem(key) || \"\";\n            try {\n                return JSON.parse(rawValue);\n            } catch (e) {\n                // not a json\n                return rawValue;\n            }\n        }\n\n        // fallback\n        return this.storageFallback[key];\n    }\n\n    /**\n     * Stores a new data in the browser's local storage\n     * (or runtime/memory if local storage is undefined).\n     */\n    private _storageSet(key: string, value: any) {\n        if (typeof window !== \"undefined\" && window?.localStorage) {\n            // store in local storage\n            let normalizedVal = value;\n            if (typeof value !== \"string\") {\n                normalizedVal = JSON.stringify(value);\n            }\n            window.localStorage.setItem(key, normalizedVal);\n        } else {\n            // store in fallback\n            this.storageFallback[key] = value;\n        }\n    }\n\n    /**\n     * Removes `key` from the browser's local storage and the runtime/memory.\n     */\n    private _storageRemove(key: string) {\n        // delete from local storage\n        if (typeof window !== \"undefined\" && window?.localStorage) {\n            window.localStorage?.removeItem(key);\n        }\n\n        // delete from fallback\n        delete this.storageFallback[key];\n    }\n\n    /**\n     * Updates the current store state on localStorage change.\n     */\n    private _bindStorageEvent() {\n        if (\n            typeof window === \"undefined\" ||\n            !window?.localStorage ||\n            !window.addEventListener\n        ) {\n            return;\n        }\n\n        window.addEventListener(\"storage\", (e) => {\n            if (e.key != this.storageKey) {\n                return;\n            }\n\n            const data = this._storageGet(this.storageKey) || {};\n\n            super.save(data.token || \"\", data.record || data.model || null);\n        });\n    }\n}\n","import Client from \"@/Client\";\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport abstract class BaseService {\n    readonly client: Client;\n\n    constructor(client: Client) {\n        this.client = client;\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { CommonOptions } from \"@/tools/options\";\n\ninterface appleClientSecret {\n    secret: string;\n}\n\nexport class SettingsService extends BaseService {\n    /**\n     * Fetch all available app settings.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getAll(options?: CommonOptions): Promise<{ [key: string]: any }> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/settings\", options);\n    }\n\n    /**\n     * Bulk updates app settings.\n     *\n     * @throws {ClientResponseError}\n     */\n    async update(\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: CommonOptions,\n    ): Promise<{ [key: string]: any }> {\n        options = Object.assign(\n            {\n                method: \"PATCH\",\n                body: bodyParams,\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/settings\", options);\n    }\n\n    /**\n     * Performs a S3 filesystem connection test.\n     *\n     * The currently supported `filesystem` are \"storage\" and \"backups\".\n     *\n     * @throws {ClientResponseError}\n     */\n    async testS3(\n        filesystem: string = \"storage\",\n        options?: CommonOptions,\n    ): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: {\n                    filesystem: filesystem,\n                },\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/settings/test/s3\", options).then(() => true);\n    }\n\n    /**\n     * Sends a test email.\n     *\n     * The possible `emailTemplate` values are:\n     * - verification\n     * - password-reset\n     * - email-change\n     *\n     * @throws {ClientResponseError}\n     */\n    async testEmail(\n        collectionIdOrName: string,\n        toEmail: string,\n        emailTemplate: string,\n        options?: CommonOptions,\n    ): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: {\n                    email: toEmail,\n                    template: emailTemplate,\n                    collection: collectionIdOrName,\n                },\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/settings/test/email\", options).then(() => true);\n    }\n\n    /**\n     * Generates a new Apple OAuth2 client secret.\n     *\n     * @throws {ClientResponseError}\n     */\n    async generateAppleClientSecret(\n        clientId: string,\n        teamId: string,\n        keyId: string,\n        privateKey: string,\n        duration: number,\n        options?: CommonOptions,\n    ): Promise<appleClientSecret> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: {\n                    clientId,\n                    teamId,\n                    keyId,\n                    privateKey,\n                    duration,\n                },\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/settings/apple/generate-client-secret\", options);\n    }\n}\n","export interface SendOptions extends RequestInit {\n    // for backward compatibility and to minimize the verbosity,\n    // any top-level field that doesn't exist in RequestInit or the\n    // fields below will be treated as query parameter.\n    [key: string]: any;\n\n    /**\n     * Optional custom fetch function to use for sending the request.\n     */\n    fetch?: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response>;\n\n    /**\n     * Custom headers to send with the requests.\n     */\n    headers?: { [key: string]: string };\n\n    /**\n     * The body of the request (serialized automatically for json requests).\n     */\n    body?: any;\n\n    /**\n     * Query parameters that will be appended to the request url.\n     */\n    query?: { [key: string]: any };\n\n    /**\n     * @deprecated use `query` instead\n     *\n     * for backward-compatibility `params` values are merged with `query`,\n     * but this option may get removed in the final v1 release\n     */\n    params?: { [key: string]: any };\n\n    /**\n     * The request identifier that can be used to cancel pending requests.\n     */\n    requestKey?: string | null;\n\n    /**\n     * @deprecated use `requestKey:string` instead\n     */\n    $cancelKey?: string;\n\n    /**\n     * @deprecated use `requestKey:null` instead\n     */\n    $autoCancel?: boolean;\n}\n\nexport interface CommonOptions extends SendOptions {\n    fields?: string;\n}\n\nexport interface ListOptions extends CommonOptions {\n    page?: number;\n    perPage?: number;\n    sort?: string;\n    filter?: string;\n    skipTotal?: boolean;\n}\n\nexport interface FullListOptions extends ListOptions {\n    batch?: number;\n}\n\nexport interface RecordOptions extends CommonOptions {\n    expand?: string;\n}\n\nexport interface RecordListOptions extends ListOptions, RecordOptions {}\n\nexport interface RecordFullListOptions extends FullListOptions, RecordOptions {}\n\nexport interface RecordSubscribeOptions extends SendOptions {\n    fields?: string;\n    filter?: string;\n    expand?: string;\n}\n\nexport interface LogStatsOptions extends CommonOptions {\n    filter?: string;\n}\n\nexport interface FileOptions extends CommonOptions {\n    thumb?: string;\n    download?: boolean;\n}\n\nexport interface AuthOptions extends CommonOptions {\n    /**\n     * If autoRefreshThreshold is set it will take care to auto refresh\n     * when necessary the auth data before each request to ensure that\n     * the auth state is always valid.\n     *\n     * The value must be in seconds, aka. the amount of seconds\n     * that will be subtracted from the current token `exp` claim in order\n     * to determine whether it is going to expire within the specified time threshold.\n     *\n     * For example, if you want to auto refresh the token if it is\n     * going to expire in the next 30mins (or already has expired),\n     * it can be set to `1800`\n     */\n    autoRefreshThreshold?: number;\n}\n\n// -------------------------------------------------------------------\n\n// list of known SendOptions keys (everything else is treated as query param)\nconst knownSendOptionsKeys = [\n    \"requestKey\",\n    \"$cancelKey\",\n    \"$autoCancel\",\n    \"fetch\",\n    \"headers\",\n    \"body\",\n    \"query\",\n    \"params\",\n    // ---,\n    \"cache\",\n    \"credentials\",\n    \"headers\",\n    \"integrity\",\n    \"keepalive\",\n    \"method\",\n    \"mode\",\n    \"redirect\",\n    \"referrer\",\n    \"referrerPolicy\",\n    \"signal\",\n    \"window\",\n];\n\n// modifies in place the provided options by moving unknown send options as query parameters.\nexport function normalizeUnknownQueryParams(options?: SendOptions): void {\n    if (!options) {\n        return;\n    }\n\n    options.query = options.query || {};\n    for (let key in options) {\n        if (knownSendOptionsKeys.includes(key)) {\n            continue;\n        }\n\n        options.query[key] = options[key];\n        delete options[key];\n    }\n}\n\nexport function serializeQueryParams(params: { [key: string]: any }): string {\n    const result: Array<string> = [];\n\n    for (const key in params) {\n        const encodedKey = encodeURIComponent(key);\n        const arrValue = Array.isArray(params[key]) ? params[key] : [params[key]];\n\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\n    return result.join(\"&\");\n}\n\n// encodes and normalizes the provided query param value.\nfunction prepareQueryParamValue(value: any): null|string {\n    if (value === null || typeof value === \"undefined\") {\n        return null;\n    }\n\n    if (value instanceof Date) {\n        return encodeURIComponent(value.toISOString().replace(\"T\", \" \"));\n    }\n\n    if (typeof value === \"object\") {\n        return encodeURIComponent(JSON.stringify(value));\n    }\n\n    return encodeURIComponent(value)\n}\n","import { ClientResponseError } from \"@/ClientResponseError\";\nimport { BaseService } from \"@/services/BaseService\";\nimport { SendOptions, normalizeUnknownQueryParams } from \"@/tools/options\";\n\ninterface promiseCallbacks {\n    resolve: Function;\n    reject: Function;\n}\n\ntype Subscriptions = { [key: string]: Array<EventListener> };\n\nexport type UnsubscribeFunc = () => Promise<void>;\n\nexport class RealtimeService extends BaseService {\n    clientId: string = \"\";\n\n    private eventSource: EventSource | null = null;\n    private subscriptions: Subscriptions = {};\n    private lastSentSubscriptions: Array<string> = [];\n    private connectTimeoutId: any;\n    private maxConnectTimeout: number = 15000;\n    private reconnectTimeoutId: any;\n    private reconnectAttempts: number = 0;\n    private maxReconnectAttempts: number = Infinity;\n    private predefinedReconnectIntervals: Array<number> = [\n        200, 300, 500, 1000, 1200, 1500, 2000,\n    ];\n    private pendingConnects: Array<promiseCallbacks> = [];\n\n    /**\n     * Returns whether the realtime connection has been established.\n     */\n    get isConnected(): boolean {\n        return !!this.eventSource && !!this.clientId && !this.pendingConnects.length;\n    }\n\n    /**\n     * An optional hook that is invoked when the realtime client disconnects\n     * either when unsubscribing from all subscriptions or when the\n     * connection was interrupted or closed by the server.\n     *\n     * The received argument could be used to determine whether the disconnect\n     * is a result from unsubscribing (`activeSubscriptions.length == 0`)\n     * or because of network/server error (`activeSubscriptions.length > 0`).\n     *\n     * If you want to listen for the opposite, aka. when the client connection is established,\n     * subscribe to the `PB_CONNECT` event.\n     */\n    onDisconnect?: (activeSubscriptions: Array<string>) => void;\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(\n        topic: string,\n        callback: (data: any) => void,\n        options?: SendOptions,\n    ): Promise<UnsubscribeFunc> {\n        if (!topic) {\n            throw new Error(\"topic must be set.\");\n        }\n\n        let key = topic;\n\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 =\n                \"options=\" +\n                encodeURIComponent(\n                    JSON.stringify({ query: options.query, headers: options.headers }),\n                );\n            key += (key.includes(\"?\") ? \"&\" : \"?\") + serialized;\n        }\n\n        const listener = function (e: Event) {\n            const msgEvent = e as MessageEvent;\n\n            let data;\n            try {\n                data = JSON.parse(msgEvent?.data);\n            } catch {}\n\n            callback(data || {});\n        };\n\n        // store the listener\n        if (!this.subscriptions[key]) {\n            this.subscriptions[key] = [];\n        }\n        this.subscriptions[key].push(listener);\n\n        if (!this.isConnected) {\n            // initialize sse connection\n            await this.connect();\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        } else {\n            // only register the listener\n            this.eventSource?.addEventListener(key, listener);\n        }\n\n        return async (): Promise<void> => {\n            return this.unsubscribeByTopicAndListener(topic, listener);\n        };\n    }\n\n    /**\n     * Unsubscribe from all subscription listeners with the specified topic.\n     *\n     * If `topic` is not provided, then this method will unsubscribe\n     * from all active subscriptions.\n     *\n     * This method is no-op if there are no active subscriptions.\n     *\n     * The related sse connection will be autoclosed if after the\n     * unsubscribe operation there are no active subscriptions left.\n     */\n    async unsubscribe(topic?: string): Promise<void> {\n        let needToSubmit = false;\n\n        if (!topic) {\n            // remove all subscriptions\n            this.subscriptions = {};\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\n                for (let listener of this.subscriptions[key]) {\n                    this.eventSource?.removeEventListener(key, listener);\n                }\n                delete this.subscriptions[key];\n\n                // mark for subscriptions change submit if there are no other listeners\n                if (!needToSubmit) {\n                    needToSubmit = true;\n                }\n            }\n        }\n\n        if (!this.hasSubscriptionListeners()) {\n            // no other active subscriptions -> close the sse connection\n            this.disconnect();\n        } else if (needToSubmit) {\n            await this.submitSubscriptions();\n        }\n    }\n\n    /**\n     * Unsubscribe from all subscription listeners starting with the specified topic prefix.\n     *\n     * This method is no-op if there are no active subscriptions with the specified topic prefix.\n     *\n     * The related sse connection will be autoclosed if after the\n     * unsubscribe operation there are no active subscriptions left.\n     */\n    async unsubscribeByPrefix(keyPrefix: string): Promise<void> {\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\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\n        if (!hasAtleastOneTopic) {\n            return; // nothing to unsubscribe from\n        }\n\n        if (this.hasSubscriptionListeners()) {\n            // submit the deleted subscriptions\n            await this.submitSubscriptions();\n        } else {\n            // no other active subscriptions -> close the sse connection\n            this.disconnect();\n        }\n    }\n\n    /**\n     * Unsubscribe from all subscriptions matching the specified topic and listener function.\n     *\n     * This method is no-op if there are no active subscription with\n     * the specified topic and listener.\n     *\n     * The related sse connection will be autoclosed if after the\n     * unsubscribe operation there are no active subscriptions left.\n     */\n    async unsubscribeByTopicAndListener(\n        topic: string,\n        listener: EventListener,\n    ): Promise<void> {\n        let needToSubmit = false;\n\n        const subs = this.getSubscriptionsByTopic(topic);\n        for (let key in subs) {\n            if (\n                !Array.isArray(this.subscriptions[key]) ||\n                !this.subscriptions[key].length\n            ) {\n                continue; // already unsubscribed\n            }\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\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\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            // mark for subscriptions change submit if there are no other listeners\n            if (!needToSubmit && !this.hasSubscriptionListeners(key)) {\n                needToSubmit = true;\n            }\n        }\n\n        if (!this.hasSubscriptionListeners()) {\n            // no other active subscriptions -> close the sse connection\n            this.disconnect();\n        } else if (needToSubmit) {\n            await this.submitSubscriptions();\n        }\n    }\n\n    private hasSubscriptionListeners(keyToCheck?: string): boolean {\n        this.subscriptions = this.subscriptions || {};\n\n        // check the specified key\n        if (keyToCheck) {\n            return !!this.subscriptions[keyToCheck]?.length;\n        }\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\n        return false;\n    }\n\n    private async submitSubscriptions(): Promise<void> {\n        if (!this.clientId) {\n            return; // no client/subscriber\n        }\n\n        // optimistic update\n        this.addAllSubscriptionListeners();\n\n        this.lastSentSubscriptions = this.getNonEmptySubscriptionKeys();\n\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\n    private getSubscriptionsCancelKey(): string {\n        return \"realtime_\" + this.clientId;\n    }\n\n    private getSubscriptionsByTopic(topic: string): Subscriptions {\n        const result: Subscriptions = {};\n\n        // \"?\" so that it can be used as end delimiter for the topic\n        topic = topic.includes(\"?\") ? topic : topic + \"?\";\n\n        for (let key in this.subscriptions) {\n            if ((key + \"?\").startsWith(topic)) {\n                result[key] = this.subscriptions[key];\n            }\n        }\n\n        return result;\n    }\n\n    private getNonEmptySubscriptionKeys(): Array<string> {\n        const result: Array<string> = [];\n\n        for (let key in this.subscriptions) {\n            if (this.subscriptions[key].length) {\n                result.push(key);\n            }\n        }\n\n        return result;\n    }\n\n    private addAllSubscriptionListeners(): void {\n        if (!this.eventSource) {\n            return;\n        }\n\n        this.removeAllSubscriptionListeners();\n\n        for (let key in this.subscriptions) {\n            for (let listener of this.subscriptions[key]) {\n                this.eventSource.addEventListener(key, listener);\n            }\n        }\n    }\n\n    private removeAllSubscriptionListeners(): void {\n        if (!this.eventSource) {\n            return;\n        }\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\n    private async connect(): Promise<void> {\n        if (this.reconnectAttempts > 0) {\n            // immediately resolve the promise to avoid indefinitely\n            // blocking the client during reconnection\n            return;\n        }\n\n        return new Promise((resolve, reject) => {\n            this.pendingConnects.push({ resolve, reject });\n\n            if (this.pendingConnects.length > 1) {\n                // all promises will be resolved once the connection is established\n                return;\n            }\n\n            this.initConnect();\n        });\n    }\n\n    private initConnect() {\n        this.disconnect(true);\n\n        // wait up to 15s for connect\n        clearTimeout(this.connectTimeoutId);\n        this.connectTimeoutId = setTimeout(() => {\n            this.connectErrorHandler(new Error(\"EventSource connect took too long.\"));\n        }, this.maxConnectTimeout);\n\n        this.eventSource = new EventSource(this.client.buildURL(\"/api/realtime\"));\n\n        this.eventSource.onerror = (_) => {\n            this.connectErrorHandler(\n                new Error(\"Failed to establish realtime connection.\"),\n            );\n        };\n\n        this.eventSource.addEventListener(\"PB_CONNECT\", (e) => {\n            const msgEvent = e as MessageEvent;\n            this.clientId = msgEvent?.lastEventId;\n\n            this.submitSubscriptions()\n                .then(async () => {\n                    let retries = 3;\n                    while (this.hasUnsentSubscriptions() && retries > 0) {\n                        retries--;\n                        // resubscribe to ensure that the latest topics are submitted\n                        //\n                        // This is needed because missed topics could happen on reconnect\n                        // if after the pending sent `submitSubscriptions()` call another `subscribe()`\n                        // was made before the submit was able to complete.\n                        await this.submitSubscriptions();\n                    }\n                })\n                .then(() => {\n                    for (let p of this.pendingConnects) {\n                        p.resolve();\n                    }\n\n                    // reset connect meta\n                    this.pendingConnects = [];\n                    this.reconnectAttempts = 0;\n                    clearTimeout(this.reconnectTimeoutId);\n                    clearTimeout(this.connectTimeoutId);\n\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                })\n                .catch((err) => {\n                    this.clientId = \"\";\n                    this.connectErrorHandler(err);\n                });\n        });\n    }\n\n    private hasUnsentSubscriptions(): boolean {\n        const latestTopics = this.getNonEmptySubscriptionKeys();\n        if (latestTopics.length != this.lastSentSubscriptions.length) {\n            return true;\n        }\n\n        for (const t of latestTopics) {\n            if (!this.lastSentSubscriptions.includes(t)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    private connectErrorHandler(err: any) {\n        clearTimeout(this.connectTimeoutId);\n        clearTimeout(this.reconnectTimeoutId);\n\n        if (\n            // wasn't previously connected -> direct reject\n            (!this.clientId && !this.reconnectAttempts) ||\n            // was previously connected but the max reconnection limit has been reached\n            this.reconnectAttempts > this.maxReconnectAttempts\n        ) {\n            for (let p of this.pendingConnects) {\n                p.reject(new ClientResponseError(err));\n            }\n            this.pendingConnects = [];\n            this.disconnect();\n            return;\n        }\n\n        // otherwise -> reconnect in the background\n        this.disconnect(true);\n        const timeout =\n            this.predefinedReconnectIntervals[this.reconnectAttempts] ||\n            this.predefinedReconnectIntervals[\n                this.predefinedReconnectIntervals.length - 1\n            ];\n        this.reconnectAttempts++;\n        this.reconnectTimeoutId = setTimeout(() => {\n            this.initConnect();\n        }, timeout);\n    }\n\n    private disconnect(fromReconnect = false): void {\n        if (this.clientId && this.onDisconnect) {\n            this.onDisconnect(Object.keys(this.subscriptions));\n        }\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\n        if (!fromReconnect) {\n            this.reconnectAttempts = 0;\n\n            // resolve any remaining connect promises\n            //\n            // this is done to avoid unnecessary throwing errors in case\n            // unsubscribe is called before the pending connect promises complete\n            // (see https://github.com/pocketbase/pocketbase/discussions/2897#discussioncomment-6423818)\n            for (let p of this.pendingConnects) {\n                p.resolve();\n            }\n            this.pendingConnects = [];\n        }\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { ClientResponseError } from \"@/ClientResponseError\";\nimport { ListResult } from \"@/tools/dtos\";\nimport { CommonOptions, ListOptions, FullListOptions } from \"@/tools/options\";\n\nexport abstract class CrudService<M> extends BaseService {\n    /**\n     * Base path for the crud actions (without trailing slash, eg. '/admins').\n     */\n    abstract get baseCrudPath(): string;\n\n    /**\n     * Response data decoder.\n     */\n    decode<T = M>(data: { [key: string]: any }): T {\n        return data as T;\n    }\n\n    /**\n     * Returns a promise with all list items batch fetched at once\n     * (by default 500 items per request; to change it set the `batch` query param).\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getFullList<T = M>(options?: FullListOptions): Promise<Array<T>>;\n\n    /**\n     * Legacy version of getFullList with explicitly specified batch size.\n     */\n    async getFullList<T = M>(batch?: number, options?: ListOptions): Promise<Array<T>>;\n\n    async getFullList<T = M>(\n        batchOrqueryParams?: number | FullListOptions,\n        options?: ListOptions,\n    ): Promise<Array<T>> {\n        if (typeof batchOrqueryParams == \"number\") {\n            return this._getFullList<T>(batchOrqueryParams, options);\n        }\n\n        options = Object.assign({}, batchOrqueryParams, options);\n\n        let batch = 500;\n        if (options.batch) {\n            batch = options.batch;\n            delete options.batch;\n        }\n\n        return this._getFullList<T>(batch, options);\n    }\n\n    /**\n     * Returns paginated items list.\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getList<T = M>(\n        page = 1,\n        perPage = 30,\n        options?: ListOptions,\n    ): Promise<ListResult<T>> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        options.query = Object.assign(\n            {\n                page: page,\n                perPage: perPage,\n            },\n            options.query,\n        );\n\n        return this.client.send(this.baseCrudPath, options).then((responseData: any) => {\n            responseData.items =\n                responseData.items?.map((item: any) => {\n                    return this.decode<T>(item);\n                }) || [];\n\n            return responseData;\n        });\n    }\n\n    /**\n     * Returns the first found item by the specified filter.\n     *\n     * Internally it calls `getList(1, 1, { filter, skipTotal })` and\n     * returns the first found item.\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * For consistency with `getOne`, this method will throw a 404\n     * ClientResponseError if no item was found.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getFirstListItem<T = M>(filter: string, options?: CommonOptions): Promise<T> {\n        options = Object.assign(\n            {\n                requestKey: \"one_by_filter_\" + this.baseCrudPath + \"_\" + filter,\n            },\n            options,\n        );\n\n        options.query = Object.assign(\n            {\n                filter: filter,\n                skipTotal: 1,\n            },\n            options.query,\n        );\n\n        return this.getList<T>(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\n            return result.items[0];\n        });\n    }\n\n    /**\n     * Returns single item by its id.\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * If `id` is empty it will throw a 404 error.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getOne<T = M>(id: string, options?: CommonOptions): Promise<T> {\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\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n            .then((responseData: any) => this.decode<T>(responseData));\n    }\n\n    /**\n     * Creates a new item.\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async create<T = M>(\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: CommonOptions,\n    ): Promise<T> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: bodyParams,\n            },\n            options,\n        );\n\n        return this.client\n            .send(this.baseCrudPath, options)\n            .then((responseData: any) => this.decode<T>(responseData));\n    }\n\n    /**\n     * Updates an existing item by its id.\n     *\n     * You can use the generic T to supply a wrapper type of the crud model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async update<T = M>(\n        id: string,\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: CommonOptions,\n    ): Promise<T> {\n        options = Object.assign(\n            {\n                method: \"PATCH\",\n                body: bodyParams,\n            },\n            options,\n        );\n\n        return this.client\n            .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n            .then((responseData: any) => this.decode<T>(responseData));\n    }\n\n    /**\n     * Deletes an existing item by its id.\n     *\n     * @throws {ClientResponseError}\n     */\n    async delete(id: string, options?: CommonOptions): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"DELETE\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(this.baseCrudPath + \"/\" + encodeURIComponent(id), options)\n            .then(() => true);\n    }\n\n    /**\n     * Returns a promise with all list items batch fetched at once.\n     */\n    protected _getFullList<T = M>(\n        batchSize = 500,\n        options?: ListOptions,\n    ): Promise<Array<T>> {\n        options = options || {};\n        options.query = Object.assign(\n            {\n                skipTotal: 1,\n            },\n            options.query,\n        );\n\n        let result: Array<T> = [];\n\n        let request = async (page: number): Promise<Array<any>> => {\n            return this.getList(page, batchSize || 500, options).then((list) => {\n                const castedList = list as any as ListResult<T>;\n                const items = castedList.items;\n\n                result = result.concat(items);\n\n                if (items.length == list.perPage) {\n                    return request(page + 1);\n                }\n\n                return result;\n            });\n        };\n\n        return request(1);\n    }\n}\n","import { SendOptions } from \"@/tools/options\";\n\nexport function normalizeLegacyOptionsArgs(\n    legacyWarn: string,\n    baseOptions: SendOptions,\n    bodyOrOptions?: any,\n    query?: any,\n): SendOptions {\n    const hasBodyOrOptions = typeof bodyOrOptions !== \"undefined\";\n    const hasQuery = typeof query !== \"undefined\";\n\n    if (!hasQuery && !hasBodyOrOptions) {\n        return baseOptions;\n    }\n\n    if (hasQuery) {\n        console.warn(legacyWarn);\n        baseOptions.body = Object.assign({}, baseOptions.body, bodyOrOptions);\n        baseOptions.query = Object.assign({}, baseOptions.query, query);\n\n        return baseOptions;\n    }\n\n    return Object.assign(baseOptions, bodyOrOptions);\n}\n","import Client from \"@/Client\";\nimport { isTokenExpired } from \"@/tools/jwt\";\n\n// reset previous auto refresh registrations\nexport function resetAutoRefresh(client: Client) {\n    (client as any)._resetAutoRefresh?.();\n}\n\nexport function registerAutoRefresh(\n    client: Client,\n    threshold: number,\n    refreshFunc: () => Promise<any>,\n    reauthenticateFunc: () => Promise<any>,\n) {\n    resetAutoRefresh(client);\n\n    const oldBeforeSend = client.beforeSend;\n    const oldModel = client.authStore.record;\n\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 (\n            !newToken ||\n            model?.id != oldModel?.id ||\n            ((model?.collectionId || oldModel?.collectionId) &&\n                model?.collectionId != oldModel?.collectionId)\n        ) {\n            resetAutoRefresh(client);\n        }\n    });\n\n    // initialize a reset function and attach it dynamically to the client\n    (client as any)._resetAutoRefresh = function () {\n        unsubStoreChange();\n        client.beforeSend = oldBeforeSend;\n        delete (client as any)._resetAutoRefresh;\n    };\n\n    client.beforeSend = async (url, sendOptions) => {\n        const oldToken = client.authStore.token;\n\n        if (sendOptions.query?.autoRefresh) {\n            return oldBeforeSend ? oldBeforeSend(url, sendOptions) : { url, sendOptions };\n        }\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        ) {\n            try {\n                await refreshFunc();\n            } catch (_) {\n                isValid = false;\n            }\n        }\n\n        // still invalid -> reauthenticate\n        if (!isValid) {\n            await reauthenticateFunc();\n        }\n\n        // the request wasn't sent with a custom token\n        const headers = sendOptions.headers || {};\n        for (let key in headers) {\n            if (\n                key.toLowerCase() == \"authorization\" &&\n                // the request wasn't sent with a custom token\n                oldToken == headers[key] &&\n                client.authStore.token\n            ) {\n                // set the latest store token\n                headers[key] = client.authStore.token;\n                break;\n            }\n        }\n        sendOptions.headers = headers;\n\n        return oldBeforeSend ? oldBeforeSend(url, sendOptions) : { url, sendOptions };\n    };\n}\n","import Client from \"@/Client\";\nimport { ClientResponseError } from \"@/ClientResponseError\";\nimport { RealtimeService, UnsubscribeFunc } from \"@/services/RealtimeService\";\nimport { BaseAuthStore } from \"@/stores/BaseAuthStore\";\nimport { CrudService } from \"@/services/CrudService\";\nimport { ListResult, RecordModel } from \"@/tools/dtos\";\nimport { normalizeLegacyOptionsArgs } from \"@/tools/legacy\";\nimport {\n    CommonOptions,\n    RecordFullListOptions,\n    RecordListOptions,\n    RecordOptions,\n    SendOptions,\n    RecordSubscribeOptions,\n} from \"@/tools/options\";\nimport { getTokenPayload } from \"@/tools/jwt\";\nimport { registerAutoRefresh, resetAutoRefresh } from \"@/tools/refresh\";\n\nexport interface RecordAuthResponse<T = RecordModel> {\n    /**\n     * The signed PocketBase auth record.\n     */\n    record: T;\n\n    /**\n     * The PocketBase record auth token.\n     *\n     * If you are looking for the OAuth2 access and refresh tokens\n     * they are available under the `meta.accessToken` and `meta.refreshToken` props.\n     */\n    token: string;\n\n    /**\n     * Auth meta data usually filled when OAuth2 is used.\n     */\n    meta?: { [key: string]: any };\n}\n\nexport interface AuthProviderInfo {\n    name: string;\n    displayName: string;\n    state: string;\n    authURL: string;\n    codeVerifier: string;\n    codeChallenge: string;\n    codeChallengeMethod: string;\n}\n\nexport interface AuthMethodsList {\n    mfa: {\n        enabled: boolean;\n        duration: number;\n    };\n    otp: {\n        enabled: boolean;\n        duration: number;\n    };\n    password: {\n        enabled: boolean;\n        identityFields: Array<string>;\n    };\n    oauth2: {\n        enabled: boolean;\n        providers: Array<AuthProviderInfo>;\n    };\n}\n\nexport interface RecordSubscription<T = RecordModel> {\n    action: string; // eg. create, update, delete\n    record: T;\n}\n\nexport type OAuth2UrlCallback = (url: string) => void | Promise<void>;\n\nexport interface OAuth2AuthConfig extends SendOptions {\n    // the name of the OAuth2 provider (eg. \"google\")\n    provider: string;\n\n    // custom scopes to overwrite the default ones\n    scopes?: Array<string>;\n\n    // optional record create data\n    createData?: { [key: string]: any };\n\n    // optional callback that is triggered after the OAuth2 sign-in/sign-up url generation\n    urlCallback?: OAuth2UrlCallback;\n\n    // optional query params to send with the PocketBase auth request (eg. fields, expand, etc.)\n    query?: RecordOptions;\n}\n\nexport interface OTPResponse {\n    otpId: string;\n}\n\nexport class RecordService<M = RecordModel> extends CrudService<M> {\n    readonly collectionIdOrName: string;\n\n    constructor(client: Client, collectionIdOrName: string) {\n        super(client);\n\n        this.collectionIdOrName = collectionIdOrName;\n    }\n\n    /**\n     * @inheritdoc\n     */\n    get baseCrudPath(): string {\n        return this.baseCollectionPath + \"/records\";\n    }\n\n    /**\n     * Returns the current collection service base path.\n     */\n    get baseCollectionPath(): string {\n        return \"/api/collections/\" + encodeURIComponent(this.collectionIdOrName);\n    }\n\n    /**\n     * Returns whether the current service collection is superusers.\n     */\n    get isSuperusers(): boolean {\n        return (\n            this.collectionIdOrName == \"_superusers\" ||\n            this.collectionIdOrName == \"_pbc_2773867675\"\n        );\n    }\n\n    // ---------------------------------------------------------------\n    // Realtime handlers\n    // ---------------------------------------------------------------\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<T = M>(\n        topic: string,\n        callback: (data: RecordSubscription<T>) => void,\n        options?: RecordSubscribeOptions,\n    ): Promise<UnsubscribeFunc> {\n        if (!topic) {\n            throw new Error(\"Missing topic.\");\n        }\n\n        if (!callback) {\n            throw new Error(\"Missing subscription callback.\");\n        }\n\n        return this.client.realtime.subscribe(\n            this.collectionIdOrName + \"/\" + topic,\n            callback,\n            options,\n        );\n    }\n\n    /**\n     * Unsubscribe from all subscriptions of the specified topic\n     * (\"*\" or record id).\n     *\n     * If `topic` is not set, then this method will unsubscribe from\n     * all subscriptions associated to the current collection.\n     */\n    async unsubscribe(topic?: string): Promise<void> {\n        // unsubscribe from the specified topic\n        if (topic) {\n            return this.client.realtime.unsubscribe(\n                this.collectionIdOrName + \"/\" + topic,\n            );\n        }\n\n        // unsubscribe from everything related to the collection\n        return this.client.realtime.unsubscribeByPrefix(this.collectionIdOrName);\n    }\n\n    // ---------------------------------------------------------------\n    // Crud handers\n    // ---------------------------------------------------------------\n    /**\n     * @inheritdoc\n     */\n    async getFullList<T = M>(options?: RecordFullListOptions): Promise<Array<T>>;\n\n    /**\n     * @inheritdoc\n     */\n    async getFullList<T = M>(\n        batch?: number,\n        options?: RecordListOptions,\n    ): Promise<Array<T>>;\n\n    /**\n     * @inheritdoc\n     */\n    async getFullList<T = M>(\n        batchOrOptions?: number | RecordFullListOptions,\n        options?: RecordListOptions,\n    ): Promise<Array<T>> {\n        if (typeof batchOrOptions == \"number\") {\n            return super.getFullList<T>(batchOrOptions, options);\n        }\n\n        const params = Object.assign({}, batchOrOptions, options);\n\n        return super.getFullList<T>(params);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    async getList<T = M>(\n        page = 1,\n        perPage = 30,\n        options?: RecordListOptions,\n    ): Promise<ListResult<T>> {\n        return super.getList<T>(page, perPage, options);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    async getFirstListItem<T = M>(\n        filter: string,\n        options?: RecordListOptions,\n    ): Promise<T> {\n        return super.getFirstListItem<T>(filter, options);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    async getOne<T = M>(id: string, options?: RecordOptions): Promise<T> {\n        return super.getOne<T>(id, options);\n    }\n\n    /**\n     * @inheritdoc\n     */\n    async create<T = M>(\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: RecordOptions,\n    ): Promise<T> {\n        return super.create<T>(bodyParams, options);\n    }\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<T = M>(\n        id: string,\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: RecordOptions,\n    ): Promise<T> {\n        return super.update<RecordModel>(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 ===\n                        this.collectionIdOrName)\n            ) {\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\n                this.client.authStore.save(this.client.authStore.token, authRecord);\n            }\n\n            return item as any as T;\n        });\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: string, options?: CommonOptions): Promise<boolean> {\n        return super.delete(id, options).then((success) => {\n            if (\n                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 ===\n                        this.collectionIdOrName)\n            ) {\n                this.client.authStore.clear();\n            }\n\n            return success;\n        });\n    }\n\n    // ---------------------------------------------------------------\n    // Auth handlers\n    // ---------------------------------------------------------------\n\n    /**\n     * Prepare successful collection authorization response.\n     */\n    protected authResponse<T = M>(responseData: any): RecordAuthResponse<T> {\n        const record = this.decode(responseData?.record || {});\n\n        this.client.authStore.save(responseData?.token, record as any);\n\n        return Object.assign({}, responseData, {\n            // normalize common fields\n            token: responseData?.token || \"\",\n            record: record as any as T,\n        });\n    }\n\n    /**\n     * Returns all available collection auth methods.\n     *\n     * @throws {ClientResponseError}\n     */\n    async listAuthMethods(options?: CommonOptions): Promise<AuthMethodsList> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n                // @todo remove after deleting the pre v0.23 API response fields\n                fields: \"mfa,otp,password,oauth2\",\n            },\n            options,\n        );\n\n        return this.client.send(this.baseCollectionPath + \"/auth-methods\", options);\n    }\n\n    /**\n     * Authenticate a single auth collection record via its username/email and password.\n     *\n     * On success, this method also automatically updates\n     * the client's AuthStore data and returns:\n     * - the authentication token\n     * - the authenticated record model\n     *\n     * @throws {ClientResponseError}\n     */\n    async authWithPassword<T = M>(\n        usernameOrEmail: string,\n        password: string,\n        options?: RecordOptions,\n    ): Promise<RecordAuthResponse<T>> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: {\n                    identity: usernameOrEmail,\n                    password: password,\n                },\n            },\n            options,\n        );\n\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\n        let authData = await this.client.send(\n            this.baseCollectionPath + \"/auth-with-password\",\n            options,\n        );\n\n        authData = this.authResponse<T>(authData);\n\n        if (autoRefreshThreshold && this.isSuperusers) {\n            registerAutoRefresh(\n                this.client,\n                autoRefreshThreshold,\n                () => this.authRefresh({ autoRefresh: true }),\n                () =>\n                    this.authWithPassword<T>(\n                        usernameOrEmail,\n                        password,\n                        Object.assign({ autoRefresh: true }, options),\n                    ),\n            );\n        }\n\n        return authData;\n    }\n\n    /**\n     * Authenticate a single auth collection record with OAuth2 code.\n     *\n     * If you don't have an OAuth2 code you may also want to check `authWithOAuth2` method.\n     *\n     * On success, this method also automatically updates\n     * the client's AuthStore data and returns:\n     * - the authentication token\n     * - the authenticated record model\n     * - the OAuth2 account data (eg. name, email, avatar, etc.)\n     *\n     * @throws {ClientResponseError}\n     */\n    async authWithOAuth2Code<T = M>(\n        provider: string,\n        code: string,\n        codeVerifier: string,\n        redirectURL: string,\n        createData?: { [key: string]: any },\n        options?: RecordOptions,\n    ): Promise<RecordAuthResponse<T>>;\n\n    /**\n     * @deprecated\n     * Consider using authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createdData, options?).\n     */\n    async authWithOAuth2Code<T = M>(\n        provider: string,\n        code: string,\n        codeVerifier: string,\n        redirectURL: string,\n        createData?: { [key: string]: any },\n        body?: any,\n        query?: any,\n    ): Promise<RecordAuthResponse<T>>;\n\n    async authWithOAuth2Code<T = M>(\n        provider: string,\n        code: string,\n        codeVerifier: string,\n        redirectURL: string,\n        createData?: { [key: string]: any },\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<RecordAuthResponse<T>> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                provider: provider,\n                code: code,\n                codeVerifier: codeVerifier,\n                redirectURL: redirectURL,\n                createData: createData,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createData?, body?, query?) is deprecated. Consider replacing it with authWithOAuth2Code(provider, code, codeVerifier, redirectURL, createData?, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/auth-with-oauth2\", options)\n            .then((data) => this.authResponse<T>(data));\n    }\n\n    /**\n     * @deprecated This form of authWithOAuth2 is deprecated.\n     *\n     * Please use `authWithOAuth2Code()` OR its simplified realtime version\n     * as shown in https://pocketbase.io/docs/authentication/#oauth2-integration.\n     */\n    async authWithOAuth2<T = M>(\n        provider: string,\n        code: string,\n        codeVerifier: string,\n        redirectURL: string,\n        createData?: { [key: string]: any },\n        bodyParams?: { [key: string]: any },\n        queryParams?: RecordOptions,\n    ): Promise<RecordAuthResponse<T>>;\n\n    /**\n     * Authenticate a single auth collection record with OAuth2\n     * **without custom redirects, deeplinks or even page reload**.\n     *\n     * This method initializes a one-off realtime subscription and will\n     * open a popup window with the OAuth2 vendor page to authenticate.\n     * Once the external OAuth2 sign-in/sign-up flow is completed, the popup\n     * window will be automatically closed and the OAuth2 data sent back\n     * to the user through the previously established realtime connection.\n     *\n     * You can specify an optional `urlCallback` prop to customize\n     * the default url `window.open` behavior.\n     *\n     * On success, this method also automatically updates\n     * the client's AuthStore data and returns:\n     * - the authentication token\n     * - the authenticated record model\n     * - the OAuth2 account data (eg. name, email, avatar, etc.)\n     *\n     * Example:\n     *\n     * ```js\n     * const authData = await pb.collection(\"users\").authWithOAuth2({\n     *     provider: \"google\",\n     * })\n     * ```\n     *\n     * Note1: When creating the OAuth2 app in the provider dashboard\n     * you have to configure `https://yourdomain.com/api/oauth2-redirect`\n     * as redirect URL.\n     *\n     * Note2: Safari may block the default `urlCallback` popup because\n     * it doesn't allow `window.open` calls as part of an `async` click functions.\n     * To workaround this you can either change your click handler to not be marked as `async`\n     * OR manually call `window.open` before your `async` function and use the\n     * window reference in your own custom `urlCallback` (see https://github.com/pocketbase/pocketbase/discussions/2429#discussioncomment-5943061).\n     * For example:\n     * ```js\n     * <button id=\"btn\">Login with Gitlab</button>\n     * ...\n     * document.getElementById(\"btn\").addEventListener(\"click\", () => {\n     *     pb.collection(\"users\").authWithOAuth2({\n     *         provider: \"gitlab\",\n     *     }).then((authData) => {\n     *         console.log(authData)\n     *     }).catch((err) => {\n     *         console.log(err, err.originalError);\n     *     });\n     * })\n     * ```\n     *\n     * @throws {ClientResponseError}\n     */\n    async authWithOAuth2<T = M>(\n        options: OAuth2AuthConfig,\n    ): Promise<RecordAuthResponse<T>>;\n\n    authWithOAuth2<T = M>(...args: any): Promise<RecordAuthResponse<T>> {\n        // fallback to legacy format\n        if (args.length > 1 || typeof args?.[0] === \"string\") {\n            console.warn(\n                \"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            );\n            return this.authWithOAuth2Code<T>(\n                args?.[0] || \"\",\n                args?.[1] || \"\",\n                args?.[2] || \"\",\n                args?.[3] || \"\",\n                args?.[4] || {},\n                args?.[5] || {},\n                args?.[6] || {},\n            );\n        }\n\n        const config = args?.[0] || {};\n\n        // 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: Window | null = null;\n        if (!config.urlCallback) {\n            eagerDefaultPopup = openBrowserPopup(undefined);\n        }\n\n        // initialize a one-off realtime service\n        const realtime = new RealtimeService(this.client);\n\n        function cleanup() {\n            eagerDefaultPopup?.close();\n            realtime.unsubscribe();\n        }\n\n        const requestKeyOptions: SendOptions = {};\n        const requestKey = config.requestKey;\n        if (requestKey) {\n            requestKeyOptions.requestKey = requestKey;\n        }\n\n        return this.listAuthMethods(requestKeyOptions)\n            .then((authMethods) => {\n                const provider = authMethods.oauth2.providers.find(\n                    (p) => p.name === config.provider,\n                );\n                if (!provider) {\n                    throw new ClientResponseError(\n                        new Error(`Missing or invalid provider \"${config.provider}\".`),\n                    );\n                }\n\n                const redirectURL = this.client.buildURL(\"/api/oauth2-redirect\");\n\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                    cancelController.signal.onabort = () => {\n                        cleanup();\n                    };\n                }\n\n                return new Promise(async (resolve, reject) => {\n                    try {\n                        await realtime.subscribe(\"@oauth2\", async (e) => {\n                            const oldState = realtime.clientId;\n\n                            try {\n                                if (!e.state || oldState !== e.state) {\n                                    throw new Error(\"State parameters don't match.\");\n                                }\n\n                                if (e.error || !e.code) {\n                                    throw new Error(\n                                        \"OAuth2 redirect error or missing code: \" +\n                                            e.error,\n                                    );\n                                }\n\n                                // clear the non SendOptions props\n                                const options = Object.assign({}, config);\n                                delete options.provider;\n                                delete options.scopes;\n                                delete options.createData;\n                                delete options.urlCallback;\n\n                                // reset the cancelController listener as it will be triggered by the next api call\n                                if (cancelController?.signal?.onabort) {\n                                    cancelController.signal.onabort = null;\n                                }\n\n                                const authData = await this.authWithOAuth2Code<T>(\n                                    provider.name,\n                                    e.code,\n                                    provider.codeVerifier,\n                                    redirectURL,\n                                    config.createData,\n                                    options,\n                                );\n\n                                resolve(authData);\n                            } catch (err) {\n                                reject(new ClientResponseError(err));\n                            }\n\n                            cleanup();\n                        });\n\n                        const replacements: { [key: string]: any } = {\n                            state: realtime.clientId,\n                        };\n                        if (config.scopes?.length) {\n                            replacements[\"scope\"] = config.scopes.join(\" \");\n                        }\n\n                        const url = this._replaceQueryParams(\n                            provider.authURL + redirectURL,\n                            replacements,\n                        );\n\n                        let urlCallback =\n                            config.urlCallback ||\n                            function (url: string) {\n                                if (eagerDefaultPopup) {\n                                    eagerDefaultPopup.location.href = url;\n                                } else {\n                                    // it could have been blocked due to its empty initial url,\n                                    // try again...\n                                    eagerDefaultPopup = openBrowserPopup(url);\n                                }\n                            };\n\n                        await urlCallback(url);\n                    } catch (err) {\n                        cleanup();\n                        reject(new ClientResponseError(err));\n                    }\n                });\n            })\n            .catch((err) => {\n                cleanup();\n                throw err; // rethrow\n            }) as Promise<RecordAuthResponse<T>>;\n    }\n\n    /**\n     * Refreshes the current authenticated record instance and\n     * returns a new token and record data.\n     *\n     * On success this method also automatically updates the client's AuthStore.\n     *\n     * @throws {ClientResponseError}\n     */\n    async authRefresh<T = M>(options?: RecordOptions): Promise<RecordAuthResponse<T>>;\n\n    /**\n     * @deprecated\n     * Consider using authRefresh(options?).\n     */\n    async authRefresh<T = M>(body?: any, query?: any): Promise<RecordAuthResponse<T>>;\n\n    async authRefresh<T = M>(\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<RecordAuthResponse<T>> {\n        let options: any = {\n            method: \"POST\",\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of authRefresh(body?, query?) is deprecated. Consider replacing it with authRefresh(options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/auth-refresh\", options)\n            .then((data) => this.authResponse<T>(data));\n    }\n\n    /**\n     * Sends auth record password reset request.\n     *\n     * @throws {ClientResponseError}\n     */\n    async requestPasswordReset(email: string, options?: CommonOptions): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using requestPasswordReset(email, options?).\n     */\n    async requestPasswordReset(email: string, body?: any, query?: any): Promise<boolean>;\n\n    async requestPasswordReset(\n        email: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                email: email,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of requestPasswordReset(email, body?, query?) is deprecated. Consider replacing it with requestPasswordReset(email, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/request-password-reset\", options)\n            .then(() => true);\n    }\n\n    /**\n     * Confirms auth record password reset request.\n     *\n     * @throws {ClientResponseError}\n     */\n    async confirmPasswordReset(\n        passwordResetToken: string,\n        password: string,\n        passwordConfirm: string,\n        options?: CommonOptions,\n    ): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using confirmPasswordReset(passwordResetToken, password, passwordConfirm, options?).\n     */\n    async confirmPasswordReset(\n        passwordResetToken: string,\n        password: string,\n        passwordConfirm: string,\n        body?: any,\n        query?: any,\n    ): Promise<boolean>;\n\n    async confirmPasswordReset(\n        passwordResetToken: string,\n        password: string,\n        passwordConfirm: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                token: passwordResetToken,\n                password: password,\n                passwordConfirm: passwordConfirm,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of confirmPasswordReset(token, password, passwordConfirm, body?, query?) is deprecated. Consider replacing it with confirmPasswordReset(token, password, passwordConfirm, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/confirm-password-reset\", options)\n            .then(() => true);\n    }\n\n    /**\n     * Sends auth record verification email request.\n     *\n     * @throws {ClientResponseError}\n     */\n    async requestVerification(email: string, options?: CommonOptions): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using requestVerification(email, options?).\n     */\n    async requestVerification(email: string, body?: any, query?: any): Promise<boolean>;\n\n    async requestVerification(\n        email: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                email: email,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of requestVerification(email, body?, query?) is deprecated. Consider replacing it with requestVerification(email, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/request-verification\", options)\n            .then(() => true);\n    }\n\n    /**\n     * Confirms auth record email verification request.\n     *\n     * If the current `client.authStore.record` matches with the auth record from the token,\n     * then on success the `client.authStore.record.verified` will be updated to `true`.\n     *\n     * @throws {ClientResponseError}\n     */\n    async confirmVerification(\n        verificationToken: string,\n        options?: CommonOptions,\n    ): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using confirmVerification(verificationToken, options?).\n     */\n    async confirmVerification(\n        verificationToken: string,\n        body?: any,\n        query?: any,\n    ): Promise<boolean>;\n\n    async confirmVerification(\n        verificationToken: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                token: verificationToken,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of confirmVerification(token, body?, query?) is deprecated. Consider replacing it with confirmVerification(token, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/confirm-verification\", options)\n            .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 (\n                    model &&\n                    !model.verified &&\n                    model.id === payload.id &&\n                    model.collectionId === payload.collectionId\n                ) {\n                    model.verified = true;\n                    this.client.authStore.save(this.client.authStore.token, model);\n                }\n\n                return true;\n            });\n    }\n\n    /**\n     * Sends an email change request to the authenticated record model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async requestEmailChange(newEmail: string, options?: CommonOptions): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using requestEmailChange(newEmail, options?).\n     */\n    async requestEmailChange(newEmail: string, body?: any, query?: any): Promise<boolean>;\n\n    async requestEmailChange(\n        newEmail: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                newEmail: newEmail,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of requestEmailChange(newEmail, body?, query?) is deprecated. Consider replacing it with requestEmailChange(newEmail, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/request-email-change\", options)\n            .then(() => true);\n    }\n\n    /**\n     * Confirms auth record's new email address.\n     *\n     * If the current `client.authStore.record` matches with the auth record from the token,\n     * then on success the `client.authStore` will be cleared.\n     *\n     * @throws {ClientResponseError}\n     */\n    async confirmEmailChange(\n        emailChangeToken: string,\n        password: string,\n        options?: CommonOptions,\n    ): Promise<boolean>;\n\n    /**\n     * @deprecated\n     * Consider using confirmEmailChange(emailChangeToken, password, options?).\n     */\n    async confirmEmailChange(\n        emailChangeToken: string,\n        password: string,\n        body?: any,\n        query?: any,\n    ): Promise<boolean>;\n\n    async confirmEmailChange(\n        emailChangeToken: string,\n        password: string,\n        bodyOrOptions?: any,\n        query?: any,\n    ): Promise<boolean> {\n        let options: any = {\n            method: \"POST\",\n            body: {\n                token: emailChangeToken,\n                password: password,\n            },\n        };\n\n        options = normalizeLegacyOptionsArgs(\n            \"This form of confirmEmailChange(token, password, body?, query?) is deprecated. Consider replacing it with confirmEmailChange(token, password, options?).\",\n            options,\n            bodyOrOptions,\n            query,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/confirm-email-change\", options)\n            .then(() => {\n                const payload = getTokenPayload(emailChangeToken);\n                const model = this.client.authStore.record;\n                if (\n                    model &&\n                    model.id === payload.id &&\n                    model.collectionId === payload.collectionId\n                ) {\n                    this.client.authStore.clear();\n                }\n\n                return true;\n            });\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(\n        recordId: string,\n        options?: CommonOptions,\n    ): Promise<Array<RecordModel>> {\n        return this.client.collection(\"_externalAuths\").getFullList(\n            Object.assign({}, options, {\n                filter: this.client.filter(\"recordRef = {:id}\", { id: recordId }),\n            }),\n        );\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(\n        recordId: string,\n        provider: string,\n        options?: CommonOptions,\n    ): Promise<boolean> {\n        const ea = await this.client.collection(\"_externalAuths\").getFirstListItem(\n            this.client.filter(\"recordRef = {:recordId} && provider = {:provider}\", {\n                recordId,\n                provider,\n            }),\n        );\n\n        return this.client\n            .collection(\"_externalAuths\")\n            .delete(ea.id, options)\n            .then(() => true);\n    }\n\n    /**\n     * Sends auth record OTP to the provided email.\n     *\n     * @throws {ClientResponseError}\n     */\n    async requestOTP(email: string, options?: CommonOptions): Promise<OTPResponse> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: { email: email },\n            },\n            options,\n        );\n\n        return this.client.send(this.baseCollectionPath + \"/request-otp\", options);\n    }\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<T = M>(\n        otpId: string,\n        password: string,\n        options?: CommonOptions,\n    ): Promise<RecordAuthResponse<T>> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: { otpId, password },\n            },\n            options,\n        );\n\n        return this.client\n            .send(this.baseCollectionPath + \"/auth-with-otp\", options)\n            .then((data) => this.authResponse<T>(data));\n    }\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(\n        recordId: string,\n        duration: number,\n        options?: CommonOptions,\n    ): Promise<Client> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: { duration: duration },\n            },\n            options,\n        );\n        options.headers = options.headers || {};\n        if (!options.headers.Authorization) {\n            options.headers.Authorization = this.client.authStore.token;\n        }\n\n        // create a new client loaded with the impersonated auth state\n        // ---\n        const client = new Client(\n            this.client.baseURL,\n            new BaseAuthStore(),\n            this.client.lang,\n        );\n\n        const authData = await client.send(\n            this.baseCollectionPath + \"/impersonate/\" + encodeURIComponent(recordId),\n            options,\n        );\n\n        client.authStore.save(authData?.token, this.decode(authData?.record || {}));\n        // ---\n\n        return client;\n    }\n\n    // ---------------------------------------------------------------\n\n    // very rudimentary url query params replacement because at the moment\n    // URL (and URLSearchParams) doesn't seem to be fully supported in React Native\n    //\n    // note: for details behind some of the decode/encode parsing check https://unixpapa.com/js/querystring.html\n    private _replaceQueryParams(\n        url: string,\n        replacements: { [key: string]: any } = {},\n    ): string {\n        let urlPath = url;\n        let query = \"\";\n\n        const queryIndex = url.indexOf(\"?\");\n        if (queryIndex >= 0) {\n            urlPath = url.substring(0, url.indexOf(\"?\"));\n            query = url.substring(url.indexOf(\"?\") + 1);\n        }\n\n        const parsedParams: { [key: string]: string } = {};\n\n        // parse the query parameters\n        const rawParams = query.split(\"&\");\n        for (const param of rawParams) {\n            if (param == \"\") {\n                continue;\n            }\n\n            const pair = param.split(\"=\");\n            parsedParams[decodeURIComponent(pair[0].replace(/\\+/g, \" \"))] =\n                decodeURIComponent((pair[1] || \"\").replace(/\\+/g, \" \"));\n        }\n\n        // apply the replacements\n        for (let key in replacements) {\n            if (!replacements.hasOwnProperty(key)) {\n                continue;\n            }\n\n            if (replacements[key] == null) {\n                delete parsedParams[key];\n            } else {\n                parsedParams[key] = replacements[key];\n            }\n        }\n\n        // construct back the full query string\n        query = \"\";\n        for (let key in parsedParams) {\n            if (!parsedParams.hasOwnProperty(key)) {\n                continue;\n            }\n\n            if (query != \"\") {\n                query += \"&\";\n            }\n\n            query +=\n                encodeURIComponent(key.replace(/%20/g, \"+\")) +\n                \"=\" +\n                encodeURIComponent(parsedParams[key].replace(/%20/g, \"+\"));\n        }\n\n        return query != \"\" ? urlPath + \"?\" + query : urlPath;\n    }\n}\n\nfunction openBrowserPopup(url?: string): Window | null {\n    if (typeof window === \"undefined\" || !window?.open) {\n        throw new ClientResponseError(\n            new Error(\n                `Not in a browser context - please pass a custom urlCallback function.`,\n            ),\n        );\n    }\n\n    let width = 1024;\n    let height = 768;\n\n    let windowWidth = window.innerWidth;\n    let windowHeight = window.innerHeight;\n\n    // normalize window size\n    width = width > windowWidth ? windowWidth : width;\n    height = height > windowHeight ? windowHeight : height;\n\n    let left = windowWidth / 2 - width / 2;\n    let top = windowHeight / 2 - height / 2;\n\n    // note: we don't use the noopener and noreferrer attributes since\n    // for some reason browser blocks such windows then url is undefined/blank\n    return window.open(\n        url,\n        \"popup_window\",\n        \"width=\" +\n            width +\n            \",height=\" +\n            height +\n            \",top=\" +\n            top +\n            \",left=\" +\n            left +\n            \",resizable,menubar=no\",\n    );\n}\n","import { CrudService } from \"@/services/CrudService\";\nimport { CollectionModel } from \"@/tools/dtos\";\nimport { CommonOptions } from \"@/tools/options\";\n\nexport class CollectionService extends CrudService<CollectionModel> {\n    /**\n     * @inheritdoc\n     */\n    get baseCrudPath(): string {\n        return \"/api/collections\";\n    }\n\n    /**\n     * Imports the provided collections.\n     *\n     * If `deleteMissing` is `true`, all local collections and 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(\n        collections: Array<CollectionModel>,\n        deleteMissing: boolean = false,\n        options?: CommonOptions,\n    ): Promise<true> {\n        options = Object.assign(\n            {\n                method: \"PUT\",\n                body: {\n                    collections: collections,\n                    deleteMissing: deleteMissing,\n                },\n            },\n            options,\n        );\n\n        return this.client.send(this.baseCrudPath + \"/import\", options).then(() => true);\n    }\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(\n        options?: CommonOptions,\n    ): Promise<{ [key: string]: CollectionModel }> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(this.baseCrudPath + \"/meta/scaffolds\", options);\n    }\n\n    /**\n     * Deletes all records associated with the specified collection.\n     *\n     * @throws {ClientResponseError}\n     */\n    async truncate(collectionIdOrName: string, options?: CommonOptions): Promise<true> {\n        options = Object.assign(\n            {\n                method: \"DELETE\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(\n                this.baseCrudPath +\n                    \"/\" +\n                    encodeURIComponent(collectionIdOrName) +\n                    \"/truncate\",\n                options,\n            )\n            .then(() => true);\n    }\n}\n","import { ClientResponseError } from \"@/ClientResponseError\";\nimport { BaseService } from \"@/services/BaseService\";\nimport { ListResult, LogModel } from \"@/tools/dtos\";\nimport { CommonOptions, ListOptions, LogStatsOptions } from \"@/tools/options\";\n\nexport interface HourlyStats {\n    total: number;\n    date: string;\n}\n\nexport class LogService extends BaseService {\n    /**\n     * Returns paginated logs list.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getList(\n        page = 1,\n        perPage = 30,\n        options?: ListOptions,\n    ): Promise<ListResult<LogModel>> {\n        options = Object.assign({ method: \"GET\" }, options);\n\n        options.query = Object.assign(\n            {\n                page: page,\n                perPage: perPage,\n            },\n            options.query,\n        );\n\n        return this.client.send(\"/api/logs\", options);\n    }\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: string, options?: CommonOptions): Promise<LogModel> {\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\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/logs/\" + encodeURIComponent(id), options);\n    }\n\n    /**\n     * Returns logs statistics.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getStats(options?: LogStatsOptions): Promise<Array<HourlyStats>> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/logs/stats\", options);\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { CommonOptions } from \"@/tools/options\";\n\nexport interface HealthCheckResponse {\n    code: number;\n    message: string;\n    data: { [key: string]: any };\n}\n\nexport class HealthService extends BaseService {\n    /**\n     * Checks the health status of the api.\n     *\n     * @throws {ClientResponseError}\n     */\n    async check(options?: CommonOptions): Promise<HealthCheckResponse> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/health\", options);\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { CommonOptions, FileOptions } from \"@/tools/options\";\n\nexport class FileService extends BaseService {\n    /**\n     * @deprecated Please replace with `pb.files.getURL()`.\n     */\n    getUrl(\n        record: { [key: string]: any },\n        filename: string,\n        queryParams: FileOptions = {},\n    ): string {\n        console.warn(\"Please replace pb.files.getUrl() with pb.files.getURL()\");\n        return this.getURL(record, filename, queryParams);\n    }\n\n    /**\n     * Builds and returns an absolute record file url for the provided filename.\n     */\n    getURL(\n        record: { [key: string]: any },\n        filename: string,\n        queryParams: FileOptions = {},\n    ): string {\n        if (\n            !filename ||\n            !record?.id ||\n            !(record?.collectionId || record?.collectionName)\n        ) {\n            return \"\";\n        }\n\n        const parts = [];\n        parts.push(\"api\");\n        parts.push(\"files\");\n        parts.push(encodeURIComponent(record.collectionId || record.collectionName));\n        parts.push(encodeURIComponent(record.id));\n        parts.push(encodeURIComponent(filename));\n\n        let result = this.client.buildURL(parts.join(\"/\"));\n\n        if (Object.keys(queryParams).length) {\n            // normalize the download query param for consistency with the Dart sdk\n            if (queryParams.download === false) {\n                delete queryParams.download;\n            }\n\n            const params = new URLSearchParams(queryParams);\n\n            result += (result.includes(\"?\") ? \"&\" : \"?\") + params;\n        }\n\n        return result;\n    }\n\n    /**\n     * Requests a new private file access token for the current auth model.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getToken(options?: CommonOptions): Promise<string> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(\"/api/files/token\", options)\n            .then((data) => data?.token || \"\");\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { CommonOptions } from \"@/tools/options\";\n\nexport interface BackupFileInfo {\n    key: string;\n    size: number;\n    modified: string;\n}\n\nexport class BackupService extends BaseService {\n    /**\n     * Returns list with all available backup files.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getFullList(options?: CommonOptions): Promise<Array<BackupFileInfo>> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/backups\", options);\n    }\n\n    /**\n     * Initializes a new backup.\n     *\n     * @throws {ClientResponseError}\n     */\n    async create(basename: string, options?: CommonOptions): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: {\n                    name: basename,\n                },\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/backups\", options).then(() => true);\n    }\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(\n        bodyParams: { [key: string]: any } | FormData,\n        options?: CommonOptions,\n    ): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: bodyParams,\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/backups/upload\", options).then(() => true);\n    }\n\n    /**\n     * Deletes a single backup file.\n     *\n     * @throws {ClientResponseError}\n     */\n    async delete(key: string, options?: CommonOptions): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"DELETE\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(`/api/backups/${encodeURIComponent(key)}`, options)\n            .then(() => true);\n    }\n\n    /**\n     * Initializes an app data restore from an existing backup.\n     *\n     * @throws {ClientResponseError}\n     */\n    async restore(key: string, options?: CommonOptions): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(`/api/backups/${encodeURIComponent(key)}/restore`, options)\n            .then(() => true);\n    }\n\n    /**\n     * @deprecated Please use `getDownloadURL()`.\n     */\n    getDownloadUrl(token: string, key: string): string {\n        console.warn(\n            \"Please replace pb.backups.getDownloadUrl() with pb.backups.getDownloadURL()\",\n        );\n        return this.getDownloadURL(token, key);\n    }\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: string, key: string): string {\n        return this.client.buildURL(\n            `/api/backups/${encodeURIComponent(key)}?token=${encodeURIComponent(token)}`,\n        );\n    }\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { CommonOptions } from \"@/tools/options\";\n\nexport interface CronJob {\n    id: string;\n    expression: string;\n}\n\nexport class CronService extends BaseService {\n    /**\n     * Returns list with all registered cron jobs.\n     *\n     * @throws {ClientResponseError}\n     */\n    async getFullList(options?: CommonOptions): Promise<Array<CronJob>> {\n        options = Object.assign(\n            {\n                method: \"GET\",\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/crons\", options);\n    }\n\n    /**\n     * Runs the specified cron job.\n     *\n     * @throws {ClientResponseError}\n     */\n    async run(jobId: string, options?: CommonOptions): Promise<boolean> {\n        options = Object.assign(\n            {\n                method: \"POST\",\n            },\n            options,\n        );\n\n        return this.client\n            .send(`/api/crons/${encodeURIComponent(jobId)}`, options)\n            .then(() => true);\n    }\n}\n","/**\n * Checks if the specified value is a file (aka. File, Blob, RN file object).\n */\nexport function isFile(val: any): boolean {\n    return (\n        (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 as any).HermesInternal)))\n    );\n}\n\n/**\n * Loosely checks if the specified body is a FormData instance.\n */\nexport function isFormData(body: any): boolean {\n    return (\n        body &&\n        // we are checking the constructor name because FormData\n        // is not available natively in some environments and the\n        // polyfill(s) may not be globally accessible\n        (body.constructor.name === \"FormData\" ||\n            // fallback to global FormData instance check\n            // note: this is needed because the constructor.name could be different in case of\n            //       custom global FormData implementation, eg. React Native on Android/iOS\n            (typeof FormData !== \"undefined\" && body instanceof FormData))\n    );\n}\n\n/**\n * Checks if the submitted body object has at least one Blob/File field value.\n */\nexport function hasFileField(body: { [key: string]: any }): boolean {\n    for (const key in body) {\n        const values = Array.isArray(body[key]) ? body[key] : [body[key]];\n        for (const v of values) {\n            if (isFile(v)) {\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\n/**\n * Converts analyzes the provided body and converts it to FormData\n * in case a plain object with File/Blob values is used.\n */\nexport function convertToFormDataIfNeeded(body: any): any {\n    if (\n        typeof FormData === \"undefined\" ||\n        typeof body === \"undefined\" ||\n        typeof body !== \"object\" ||\n        body === null ||\n        isFormData(body) ||\n        !hasFileField(body)\n    ) {\n        return body;\n    }\n\n    const form = new FormData();\n\n    for (const key in body) {\n        const val = body[key];\n\n        if (typeof val === \"object\" && !hasFileField({ data: val })) {\n            // send json-like values as jsonPayload to avoid the implicit string value normalization\n            let payload: { [key: string]: any } = {};\n            payload[key] = val;\n            form.append(\"@jsonPayload\", JSON.stringify(payload));\n        } else {\n            // in case of mixed string and file/blob\n            const normalizedVal = Array.isArray(val) ? val : [val];\n            for (let v of normalizedVal) {\n                form.append(key, v);\n            }\n        }\n    }\n\n    return form;\n}\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: FormData): { [key: string]: any } {\n    let result: { [key: string]: any } = {};\n\n    formData.forEach((v, k) => {\n        if (k === \"@jsonPayload\" && typeof v == \"string\") {\n            try {\n                let parsed = JSON.parse(v);\n                Object.assign(result, parsed);\n            } catch (err) {\n                console.warn(\"@jsonPayload error:\", err);\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            } else {\n                result[k] = inferFormDataValue(v);\n            }\n        }\n    });\n\n    return result;\n}\n\nconst inferNumberCharsRegex = /^[\\-\\.\\d]+$/;\n\nfunction inferFormDataValue(value: any): any {\n    if (typeof value != \"string\") {\n        return value;\n    }\n\n    if (value == \"true\") {\n        return true;\n    }\n\n    if (value == \"false\") {\n        return false;\n    }\n\n    // note: expects the provided raw string to match exactly with the minimal string representation of the parsed number\n    if (\n        (value[0] === \"-\" || (value[0] >= \"0\" && value[0] <= \"9\")) &&\n        inferNumberCharsRegex.test(value)\n    ) {\n        let num = +value;\n        if (\"\" + num === value) {\n            return num;\n        }\n    }\n\n    return value;\n}\n","import { BaseService } from \"@/services/BaseService\";\nimport { isFile, isFormData, convertFormDataToObject } from \"@/tools/formdata\";\nimport {\n    SendOptions,\n    RecordOptions,\n    normalizeUnknownQueryParams,\n    serializeQueryParams,\n} from \"@/tools/options\";\n\nexport interface BatchRequest {\n    method: string;\n    url: string;\n    json?: { [key: string]: any };\n    files?: { [key: string]: Array<any> };\n    headers?: { [key: string]: string };\n}\n\nexport interface BatchRequestResult {\n    status: number;\n    body: any;\n}\n\nexport class BatchService extends BaseService {\n    private requests: Array<BatchRequest> = [];\n    private subs: { [key: string]: SubBatchService } = {};\n\n    /**\n     * Starts constructing a batch request entry for the specified collection.\n     */\n    collection(collectionIdOrName: string): SubBatchService {\n        if (!this.subs[collectionIdOrName]) {\n            this.subs[collectionIdOrName] = new SubBatchService(\n                this.requests,\n                collectionIdOrName,\n            );\n        }\n\n        return this.subs[collectionIdOrName];\n    }\n\n    /**\n     * Sends the batch requests.\n     *\n     * @throws {ClientResponseError}\n     */\n    async send(options?: SendOptions): Promise<Array<BatchRequestResult>> {\n        const formData = new FormData();\n\n        const jsonData = [];\n\n        for (let i = 0; i < this.requests.length; i++) {\n            const req = this.requests[i];\n\n            jsonData.push({\n                method: req.method,\n                url: req.url,\n                headers: req.headers,\n                body: req.json,\n            });\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\n        formData.append(\"@jsonPayload\", JSON.stringify({ requests: jsonData }));\n\n        options = Object.assign(\n            {\n                method: \"POST\",\n                body: formData,\n            },\n            options,\n        );\n\n        return this.client.send(\"/api/batch\", options);\n    }\n}\n\nexport class SubBatchService {\n    private requests: Array<BatchRequest> = [];\n    private readonly collectionIdOrName: string;\n\n    constructor(requests: Array<BatchRequest>, collectionIdOrName: string) {\n        this.requests = requests;\n        this.collectionIdOrName = collectionIdOrName;\n    }\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(\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: RecordOptions,\n    ): void {\n        options = Object.assign(\n            {\n                body: bodyParams || {},\n            },\n            options,\n        );\n\n        const request: BatchRequest = {\n            method: \"PUT\",\n            url:\n                \"/api/collections/\" +\n                encodeURIComponent(this.collectionIdOrName) +\n                \"/records\",\n        };\n\n        this.prepareRequest(request, options);\n\n        this.requests.push(request);\n    }\n\n    /**\n     * Registers a record create request into the current batch queue.\n     */\n    create(\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: RecordOptions,\n    ): void {\n        options = Object.assign(\n            {\n                body: bodyParams || {},\n            },\n            options,\n        );\n\n        const request: BatchRequest = {\n            method: \"POST\",\n            url:\n                \"/api/collections/\" +\n                encodeURIComponent(this.collectionIdOrName) +\n                \"/records\",\n        };\n\n        this.prepareRequest(request, options);\n\n        this.requests.push(request);\n    }\n\n    /**\n     * Registers a record update request into the current batch queue.\n     */\n    update(\n        id: string,\n        bodyParams?: { [key: string]: any } | FormData,\n        options?: RecordOptions,\n    ): void {\n        options = Object.assign(\n            {\n                body: bodyParams || {},\n            },\n            options,\n        );\n\n        const request: BatchRequest = {\n            method: \"PATCH\",\n            url:\n                \"/api/collections/\" +\n                encodeURIComponent(this.collectionIdOrName) +\n                \"/records/\" +\n                encodeURIComponent(id),\n        };\n\n        this.prepareRequest(request, options);\n\n        this.requests.push(request);\n    }\n\n    /**\n     * Registers a record delete request into the current batch queue.\n     */\n    delete(id: string, options?: SendOptions): void {\n        options = Object.assign({}, options);\n\n        const request: BatchRequest = {\n            method: \"DELETE\",\n            url:\n                \"/api/collections/\" +\n                encodeURIComponent(this.collectionIdOrName) +\n                \"/records/\" +\n                encodeURIComponent(id),\n        };\n\n        this.prepareRequest(request, options);\n\n        this.requests.push(request);\n    }\n\n    private prepareRequest(request: BatchRequest, options: SendOptions) {\n        normalizeUnknownQueryParams(options);\n\n        request.headers = options.headers;\n        request.json = {};\n        request.files = {};\n\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\n        // extract json and files body data\n        // -----------------------------------------------------------\n        let body = options.body;\n        if (isFormData(body)) {\n            body = convertFormDataToObject(body);\n        }\n\n        for (const key in body) {\n            const val = body[key];\n\n            if (isFile(val)) {\n                request.files[key] = request.files[key] || [];\n                request.files[key].push(val);\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                    } else {\n                        foundRegular.push(v);\n                    }\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                } else {\n                    // empty or mixed array (both regular and File/Blob values)\n                    // ---\n                    request.json[key] = foundRegular;\n\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\n                        request.files[fileKey] = request.files[fileKey] || [];\n                        for (let file of foundFiles) {\n                            request.files[fileKey].push(file);\n                        }\n                    }\n                }\n            } else {\n                request.json[key] = val;\n            }\n        }\n    }\n}\n","import { ClientResponseError } from \"@/ClientResponseError\";\nimport { BaseAuthStore } from \"@/stores/BaseAuthStore\";\nimport { LocalAuthStore } from \"@/stores/LocalAuthStore\";\nimport { SettingsService } from \"@/services/SettingsService\";\nimport { RecordService } from \"@/services/RecordService\";\nimport { CollectionService } from \"@/services/CollectionService\";\nimport { LogService } from \"@/services/LogService\";\nimport { RealtimeService } from \"@/services/RealtimeService\";\nimport { HealthService } from \"@/services/HealthService\";\nimport { FileService } from \"@/services/FileService\";\nimport { BackupService } from \"@/services/BackupService\";\nimport { CronService } from \"@/services/CronService\";\nimport { BatchService } from \"@/services/BatchService\";\nimport { RecordModel } from \"@/tools/dtos\";\nimport {\n    SendOptions,\n    FileOptions,\n    normalizeUnknownQueryParams,\n    serializeQueryParams,\n} from \"@/tools/options\";\nimport { isFormData, convertToFormDataIfNeeded } from \"@/tools/formdata\";\n\nexport interface BeforeSendResult {\n    [key: string]: any; // for backward compatibility\n    url?: string;\n    options?: { [key: string]: any };\n}\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n    /**\n     * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n     */\n    baseURL: string;\n\n    /**\n     * Legacy getter alias for baseURL.\n     * @deprecated Please replace with baseURL.\n     */\n    get baseUrl(): string {\n        return this.baseURL;\n    }\n\n    /**\n     * Legacy setter alias for baseURL.\n     * @deprecated Please replace with baseURL.\n     */\n    set baseUrl(v: string) {\n        this.baseURL = v;\n    }\n\n    /**\n     * Hook that get triggered right before sending the fetch request,\n     * allowing you to inspect and modify the url and request options.\n     *\n     * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n     *\n     * You can return a non-empty result object `{ url, options }` to replace the url and request options entirely.\n     *\n     * Example:\n     * ```js\n     * client.beforeSend = function (url, options) {\n     *     options.headers = Object.assign({}, options.headers, {\n     *         'X-Custom-Header': 'example',\n     *     });\n     *\n     *     return { url, options }\n     * };\n     * ```\n     */\n    beforeSend?: (\n        url: string,\n        options: SendOptions,\n    ) => BeforeSendResult | Promise<BeforeSendResult>;\n\n    /**\n     * Hook that get triggered after successfully sending the fetch request,\n     * allowing you to inspect/modify the response object and its parsed data.\n     *\n     * Returns the new Promise resolved `data` that will be returned to the client.\n     *\n     * Example:\n     * ```js\n     * client.afterSend = function (response, data, options) {\n     *     if (response.status != 200) {\n     *         throw new ClientResponseError({\n     *             url:      response.url,\n     *             status:   response.status,\n     *             response: { ... },\n     *         });\n     *     }\n     *\n     *     return data;\n     * };\n     * ```\n     */\n    afterSend?: ((response: Response, data: any) => any) &\n        ((response: Response, data: any, options: SendOptions) => any);\n\n    /**\n     * Optional language code (default to `en-US`) that will be sent\n     * with the requests to the server as `Accept-Language` header.\n     */\n    lang: string;\n\n    /**\n     * A replaceable instance of the local auth store service.\n     */\n    authStore: BaseAuthStore;\n\n    /**\n     * An instance of the service that handles the **Settings APIs**.\n     */\n    readonly settings: SettingsService;\n\n    /**\n     * An instance of the service that handles the **Collection APIs**.\n     */\n    readonly collections: CollectionService;\n\n    /**\n     * An instance of the service that handles the **File APIs**.\n     */\n    readonly files: FileService;\n\n    /**\n     * An instance of the service that handles the **Log APIs**.\n     */\n    readonly logs: LogService;\n\n    /**\n     * An instance of the service that handles the **Realtime APIs**.\n     */\n    readonly realtime: RealtimeService;\n\n    /**\n     * An instance of the service that handles the **Health APIs**.\n     */\n    readonly health: HealthService;\n\n    /**\n     * An instance of the service that handles the **Backup APIs**.\n     */\n    readonly backups: BackupService;\n\n    /**\n     * An instance of the service that handles the **Cron APIs**.\n     */\n    readonly crons: CronService;\n\n    private cancelControllers: { [key: string]: AbortController } = {};\n    private recordServices: { [key: string]: RecordService } = {};\n    private enableAutoCancellation: boolean = true;\n\n    constructor(baseURL = \"/\", authStore?: BaseAuthStore | null, lang = \"en-US\") {\n        this.baseURL = baseURL;\n        this.lang = lang;\n\n        if (authStore) {\n            this.authStore = authStore;\n        } else if (typeof window != \"undefined\" && !!(window as any).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        } else {\n            this.authStore = new LocalAuthStore();\n        }\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    }\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(): RecordService {\n        return this.collection(\"_superusers\");\n    }\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(): BatchService {\n        return new BatchService(this);\n    }\n\n    /**\n     * Returns the RecordService associated to the specified collection.\n     */\n    collection<M = RecordModel>(idOrName: string): RecordService<M> {\n        if (!this.recordServices[idOrName]) {\n            this.recordServices[idOrName] = new RecordService(this, idOrName);\n        }\n\n        return this.recordServices[idOrName];\n    }\n\n    /**\n     * Globally enable or disable auto cancellation for pending duplicated requests.\n     */\n    autoCancellation(enable: boolean): Client {\n        this.enableAutoCancellation = !!enable;\n\n        return this;\n    }\n\n    /**\n     * Cancels single request by its cancellation key.\n     */\n    cancelRequest(requestKey: string): Client {\n        if (this.cancelControllers[requestKey]) {\n            this.cancelControllers[requestKey].abort();\n            delete this.cancelControllers[requestKey];\n        }\n\n        return this;\n    }\n\n    /**\n     * Cancels all pending requests.\n     */\n    cancelAllRequests(): Client {\n        for (let k in this.cancelControllers) {\n            this.cancelControllers[k].abort();\n        }\n\n        this.cancelControllers = {};\n\n        return this;\n    }\n\n    /**\n     * 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` (_single quotes are autoescaped_)\n     * - `number`\n     * - `boolean`\n     * - `Date` object (_stringified into the PocketBase datetime format_)\n     * - `null`\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: string, params?: { [key: string]: any }): string {\n        if (!params) {\n            return raw;\n        }\n\n        for (let key in params) {\n            let val = params[key];\n            switch (typeof val) {\n                case \"boolean\":\n                case \"number\":\n                    val = \"\" + val;\n                    break;\n                case \"string\":\n                    val = \"'\" + val.replace(/'/g, \"\\\\'\") + \"'\";\n                    break;\n                default:\n                    if (val === null) {\n                        val = \"null\";\n                    } else if (val instanceof Date) {\n                        val = \"'\" + val.toISOString().replace(\"T\", \" \") + \"'\";\n                    } else {\n                        val = \"'\" + JSON.stringify(val).replace(/'/g, \"\\\\'\") + \"'\";\n                    }\n            }\n            raw = raw.replaceAll(\"{:\" + key + \"}\", val);\n        }\n\n        return raw;\n    }\n\n    /**\n     * @deprecated Please use `pb.files.getURL()`.\n     */\n    getFileUrl(\n        record: { [key: string]: any },\n        filename: string,\n        queryParams: FileOptions = {},\n    ): string {\n        console.warn(\"Please replace pb.getFileUrl() with pb.files.getURL()\");\n        return this.files.getURL(record, filename, queryParams);\n    }\n\n    /**\n     * @deprecated Please use `pb.buildURL()`.\n     */\n    buildUrl(path: string): string {\n        console.warn(\"Please replace pb.buildUrl() with pb.buildURL()\");\n        return this.buildURL(path);\n    }\n\n    /**\n     * Builds a full client url by safely concatenating the provided path.\n     */\n    buildURL(path: string): string {\n        let url = this.baseURL;\n\n        // construct an absolute base url if in a browser environment\n        if (\n            typeof window !== \"undefined\" &&\n            !!window.location &&\n            !url.startsWith(\"https://\") &&\n            !url.startsWith(\"http://\")\n        ) {\n            url = window.location.origin?.endsWith(\"/\")\n                ? window.location.origin.substring(0, window.location.origin.length - 1)\n                : window.location.origin || \"\";\n\n            if (!this.baseURL.startsWith(\"/\")) {\n                url += window.location.pathname || \"/\";\n                url += url.endsWith(\"/\") ? \"\" : \"/\";\n            }\n\n            url += this.baseURL;\n        }\n\n        // concatenate the path\n        if (path) {\n            url += url.endsWith(\"/\") ? \"\" : \"/\"; // append trailing slash if missing\n            url += path.startsWith(\"/\") ? path.substring(1) : path;\n        }\n\n        return url;\n    }\n\n    /**\n     * Sends an api http request.\n     *\n     * @throws {ClientResponseError}\n     */\n    async send<T = any>(path: string, options: SendOptions): Promise<T> {\n        options = this.initSendOptions(path, options);\n\n        // build url + path\n        let url = this.buildURL(path);\n\n        if (this.beforeSend) {\n            const result = Object.assign({}, await this.beforeSend(url, options));\n            if (\n                typeof result.url !== \"undefined\" ||\n                typeof result.options !== \"undefined\"\n            ) {\n                url = result.url || url;\n                options = result.options || options;\n            } else if (Object.keys(result).length) {\n                // legacy behavior\n                options = result as SendOptions;\n                console?.warn &&\n                    console.warn(\n                        \"Deprecated format of beforeSend return: please use `return { url, options }`, instead of `return options`.\",\n                    );\n            }\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\n        // ensures that the json body is serialized\n        if (\n            this.getHeader(options.headers, \"Content-Type\") == \"application/json\" &&\n            options.body &&\n            typeof options.body !== \"string\"\n        ) {\n            options.body = JSON.stringify(options.body);\n        }\n\n        const fetchFunc = options.fetch || fetch;\n\n        // send the request\n        return fetchFunc(url, options)\n            .then(async (response) => {\n                let data: any = {};\n\n                try {\n                    data = await response.json();\n                } catch (_) {\n                    // all api responses are expected to return json\n                    // with the exception of the realtime event and 204\n                }\n\n                if (this.afterSend) {\n                    data = await this.afterSend(response, data, options);\n                }\n\n                if (response.status >= 400) {\n                    throw new ClientResponseError({\n                        url: response.url,\n                        status: response.status,\n                        data: data,\n                    });\n                }\n\n                return data as T;\n            })\n            .catch((err) => {\n                // wrap to normalize all errors\n                throw new ClientResponseError(err);\n            });\n    }\n\n    /**\n     * Shallow copy the provided object and takes care to initialize\n     * any options required to preserve the backward compatability.\n     *\n     * @param  {SendOptions} options\n     * @return {SendOptions}\n     */\n    private initSendOptions(path: string, options: SendOptions): SendOptions {\n        options = Object.assign({ method: \"GET\" } as SendOptions, options);\n\n        // auto convert the body to FormData, if needed\n        options.body = convertToFormDataIfNeeded(options.body);\n\n        // move unknown send options as query parameters\n        normalizeUnknownQueryParams(options);\n\n        // requestKey normalizations for backward-compatibility\n        // ---\n        options.query = Object.assign({}, options.params, options.query);\n        if (typeof options.requestKey === \"undefined\") {\n            if (options.$autoCancel === false || options.query.$autoCancel === false) {\n                options.requestKey = null;\n            } else if (options.$cancelKey || options.query.$cancelKey) {\n                options.requestKey = options.$cancelKey || options.query.$cancelKey;\n            }\n        }\n        // remove the deprecated special cancellation params from the other query params\n        delete options.$autoCancel;\n        delete options.query.$autoCancel;\n        delete options.$cancelKey;\n        delete options.query.$cancelKey;\n        // ---\n\n        // add the json header, if not explicitly set\n        // (for FormData body the Content-Type header should be skipped since the boundary is autogenerated)\n        if (\n            this.getHeader(options.headers, \"Content-Type\") === null &&\n            !isFormData(options.body)\n        ) {\n            options.headers = Object.assign({}, options.headers, {\n                \"Content-Type\": \"application/json\",\n            });\n        }\n\n        // add Accept-Language header, if not explicitly set\n        if (this.getHeader(options.headers, \"Accept-Language\") === null) {\n            options.headers = Object.assign({}, options.headers, {\n                \"Accept-Language\": this.lang,\n            });\n        }\n\n        // check if Authorization header can be added\n        if (\n            // has valid token\n            this.authStore.token &&\n            // auth header is not explicitly set\n            this.getHeader(options.headers, \"Authorization\") === null\n        ) {\n            options.headers = Object.assign({}, options.headers, {\n                Authorization: this.authStore.token,\n            });\n        }\n\n        // handle auto cancelation for duplicated pending request\n        if (this.enableAutoCancellation && options.requestKey !== null) {\n            const requestKey = options.requestKey || (options.method || \"GET\") + path;\n\n            delete options.requestKey;\n\n            // cancel previous pending requests\n            this.cancelRequest(requestKey);\n\n            const controller = new AbortController();\n            this.cancelControllers[requestKey] = controller;\n            options.signal = controller.signal;\n        }\n\n        return options;\n    }\n\n    /**\n     * Extracts the header with the provided name in case-insensitive manner.\n     * Returns `null` if no header matching the name is found.\n     */\n    private getHeader(\n        headers: { [key: string]: string } | undefined,\n        name: string,\n    ): string | null {\n        headers = headers || {};\n        name = name.toLowerCase();\n\n        for (let key in headers) {\n            if (key.toLowerCase() == name) {\n                return headers[key];\n            }\n        }\n\n        return null;\n    }\n}\n","import { BaseAuthStore, AuthRecord } from \"@/stores/BaseAuthStore\";\n\nexport type AsyncSaveFunc = (serializedPayload: string) => Promise<void>;\n\nexport type AsyncClearFunc = () => Promise<void>;\n\ntype queueFunc = () => Promise<void>;\n\n/**\n * AsyncAuthStore is a helper auth store implementation\n * that could be used with any external async persistent layer\n * (key-value db, local file, etc.).\n *\n * Here is an example with the React Native AsyncStorage package:\n *\n * ```\n * import AsyncStorage from \"@react-native-async-storage/async-storage\";\n * import PocketBase, { AsyncAuthStore } from \"pocketbase\";\n *\n * const store = new AsyncAuthStore({\n *     save:    async (serialized) => AsyncStorage.setItem(\"pb_auth\", serialized),\n *     initial: AsyncStorage.getItem(\"pb_auth\"),\n * });\n *\n * const pb = new PocketBase(\"https://example.com\", store)\n * ```\n */\nexport class AsyncAuthStore extends BaseAuthStore {\n    private saveFunc: AsyncSaveFunc;\n    private clearFunc?: AsyncClearFunc;\n    private queue: Array<queueFunc> = [];\n\n    constructor(config: {\n        // The async function that is called every time\n        // when the auth store state needs to be persisted.\n        save: AsyncSaveFunc;\n\n        /// An *optional* async function that is called every time\n        /// when the auth store needs to be cleared.\n        ///\n        /// If not explicitly set, `saveFunc` with empty data will be used.\n        clear?: AsyncClearFunc;\n\n        // An *optional* initial data to load into the store.\n        initial?: string | Promise<any>;\n    }) {\n        super();\n\n        this.saveFunc = config.save;\n        this.clearFunc = config.clear;\n\n        this._enqueue(() => this._loadInitial(config.initial));\n    }\n\n    /**\n     * @inheritdoc\n     */\n    save(token: string, record?: AuthRecord): void {\n        super.save(token, record);\n\n        let value = \"\";\n        try {\n            value = JSON.stringify({ token, record });\n        } catch (err) {\n            console.warn(\"AsyncAuthStore: failed to stringify the new state\");\n        }\n\n        this._enqueue(() => this.saveFunc(value));\n    }\n\n    /**\n     * @inheritdoc\n     */\n    clear(): void {\n        super.clear();\n\n        if (this.clearFunc) {\n            this._enqueue(() => this.clearFunc!());\n        } else {\n            this._enqueue(() => this.saveFunc(\"\"));\n        }\n    }\n\n    /**\n     * Initializes the auth store state.\n     */\n    private async _loadInitial(payload?: string | Promise<any>) {\n        try {\n            payload = await payload;\n\n            if (payload) {\n                let parsed;\n                if (typeof payload === \"string\") {\n                    parsed = JSON.parse(payload) || {};\n                } else if (typeof payload === \"object\") {\n                    parsed = payload;\n                }\n\n                this.save(parsed.token || \"\", parsed.record || parsed.model || null);\n            }\n        } catch (_) {}\n    }\n\n    /**\n     * Appends an async function to the queue.\n     */\n    private _enqueue(asyncCallback: () => Promise<void>) {\n        this.queue.push(asyncCallback);\n\n        if (this.queue.length == 1) {\n            this._dequeue();\n        }\n    }\n\n    /**\n     * Starts the queue processing.\n     */\n    private _dequeue() {\n        if (!this.queue.length) {\n            return;\n        }\n\n        this.queue[0]().finally(() => {\n            this.queue.shift();\n\n            if (!this.queue.length) {\n                return;\n            }\n\n            this._dequeue();\n        });\n    }\n}\n"],"names":["ClientResponseError","Error","constructor","errData","super","this","url","status","response","isAbort","originalError","Object","setPrototypeOf","prototype","data","DOMException","name","message","cause","includes","toJSON","fieldContentRegExp","cookieParse","str","options","result","decode","assign","defaultDecode","index","length","eqIdx","indexOf","endIdx","lastIndexOf","key","slice","trim","undefined","val","charCodeAt","_","cookieSerialize","opt","encode","defaultEncode","test","TypeError","value","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","isDate","toString","call","Date","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","decodeURIComponent","encodeURIComponent","isReactNative","navigator","product","global","HermesInternal","atobPolyfill","getTokenPayload","token","encodedPayload","split","map","c","join","JSON","parse","e","isTokenExpired","expirationThreshold","payload","keys","exp","now","atob","input","String","replace","bs","buffer","bc","idx","output","charAt","fromCharCode","defaultCookieKey","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","record","model","isValid","isSuperuser","type","collectionName","collectionId","isAdmin","console","warn","isAuthRecord","save","triggerChange","clear","loadFromCookie","cookie","rawData","Array","isArray","exportToCookie","defaultOptions","stringify","resultLength","Blob","size","id","email","extraProps","prop","onChange","callback","fireImmediately","push","i","splice","LocalAuthStore","storageKey","storageFallback","_bindStorageEvent","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","addEventListener","BaseService","client","SettingsService","getAll","method","send","update","bodyParams","body","testS3","filesystem","then","testEmail","collectionIdOrName","toEmail","emailTemplate","template","collection","generateAppleClientSecret","clientId","teamId","keyId","privateKey","duration","knownSendOptionsKeys","normalizeUnknownQueryParams","query","serializeQueryParams","params","encodedKey","arrValue","v","prepareQueryParamValue","toISOString","RealtimeService","eventSource","subscriptions","lastSentSubscriptions","maxConnectTimeout","reconnectAttempts","maxReconnectAttempts","Infinity","predefinedReconnectIntervals","pendingConnects","isConnected","subscribe","topic","serialized","headers","listener","msgEvent","submitSubscriptions","connect","async","unsubscribeByTopicAndListener","unsubscribe","needToSubmit","subs","getSubscriptionsByTopic","hasSubscriptionListeners","removeEventListener","disconnect","unsubscribeByPrefix","keyPrefix","hasAtleastOneTopic","startsWith","exist","keyToCheck","addAllSubscriptionListeners","getNonEmptySubscriptionKeys","requestKey","getSubscriptionsCancelKey","catch","err","removeAllSubscriptionListeners","Promise","resolve","reject","initConnect","clearTimeout","connectTimeoutId","setTimeout","connectErrorHandler","EventSource","buildURL","onerror","lastEventId","retries","hasUnsentSubscriptions","p","reconnectTimeoutId","connectSubs","latestTopics","t","timeout","fromReconnect","onDisconnect","cancelRequest","close","CrudService","getFullList","batchOrqueryParams","_getFullList","batch","getList","page","perPage","baseCrudPath","responseData","items","item","getFirstListItem","filter","skipTotal","code","getOne","create","batchSize","request","list","concat","normalizeLegacyOptionsArgs","legacyWarn","baseOptions","bodyOrOptions","hasQuery","resetAutoRefresh","_resetAutoRefresh","RecordService","baseCollectionPath","isSuperusers","realtime","batchOrOptions","authStore","authExpand","expand","authRecord","delete","success","authResponse","listAuthMethods","fields","authWithPassword","usernameOrEmail","password","autoRefreshThreshold","identity","autoRefresh","authData","registerAutoRefresh","threshold","refreshFunc","reauthenticateFunc","oldBeforeSend","beforeSend","oldModel","unsubStoreChange","newToken","sendOptions","oldToken","authRefresh","authWithOAuth2Code","provider","codeVerifier","redirectURL","createData","authWithOAuth2","args","config","eagerDefaultPopup","urlCallback","openBrowserPopup","cleanup","requestKeyOptions","authMethods","oauth2","providers","find","cancelController","signal","onabort","oldState","state","error","scopes","replacements","_replaceQueryParams","authURL","location","href","requestPasswordReset","confirmPasswordReset","passwordResetToken","passwordConfirm","requestVerification","confirmVerification","verificationToken","verified","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","listExternalAuths","recordId","unlinkExternalAuth","ea","requestOTP","authWithOTP","otpId","impersonate","Authorization","Client","baseURL","lang","urlPath","substring","parsedParams","rawParams","param","pair","hasOwnProperty","open","width","height","windowWidth","innerWidth","windowHeight","innerHeight","left","top","CollectionService","import","collections","deleteMissing","getScaffolds","truncate","LogService","getStats","HealthService","check","FileService","getUrl","filename","queryParams","getURL","parts","download","URLSearchParams","getToken","BackupService","basename","upload","restore","getDownloadUrl","getDownloadURL","CronService","run","jobId","isFile","File","uri","isFormData","FormData","hasFileField","values","inferNumberCharsRegex","inferFormDataValue","num","BatchService","requests","SubBatchService","formData","jsonData","req","json","files","file","append","upsert","prepareRequest","convertFormDataToObject","forEach","k","parsed","foundFiles","foundRegular","fileKey","endsWith","baseUrl","cancelControllers","recordServices","enableAutoCancellation","Deno","logs","settings","health","backups","crons","admins","createBatch","idOrName","autoCancellation","enable","abort","cancelAllRequests","raw","replaceAll","getFileUrl","buildUrl","origin","pathname","initSendOptions","getHeader","fetch","afterSend","convertToFormDataIfNeeded","form","$autoCancel","$cancelKey","controller","AbortController","AsyncAuthStore","queue","saveFunc","clearFunc","_enqueue","_loadInitial","initial","asyncCallback","_dequeue","finally","shift"],"mappings":"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"}