diff --git a/README.md b/README.md
index 11bcdf3..0131069 100644
--- a/README.md
+++ b/README.md
@@ -11,13 +11,15 @@ Official JavaScript SDK (browser and node) for interacting with the [PocketBase
- [AuthStore](#authstore)
- [Auto cancellation](#auto-cancellation)
- [Send hooks](#send-hooks)
+ - [SSR integration](#ssr-integration)
+ - [Security](#security)
- [Definitions](#definitions)
- [Development](#development)
## Installation
-#### Browser (manually via script tag)
+### Browser (manually via script tag)
```html
@@ -31,7 +33,7 @@ _OR if you are using ES modules:_
```
-#### Node.js (via npm)
+### Node.js (via npm)
```sh
npm install pocketbase --save
@@ -58,7 +60,7 @@ const PocketBase = require('pocketbase/cjs')
> // npm install eventsource --save
> global.EventSource = require('eventsource');
> ```
----
+
## Usage
@@ -77,7 +79,6 @@ const result = await client.records.getList('example', 1, 20, {
// authenticate as regular user
const userData = await client.users.authViaEmail('test@example.com', '123456');
-
// or as admin
const adminData = await client.admins.authViaEmail('test@example.com', '123456');
@@ -88,7 +89,7 @@ const adminData = await client.admins.authViaEmail('test@example.com', '123456')
## Caveats
-#### File upload
+### File upload
PocketBase Web API supports file upload via `multipart/form-data` requests,
which means that to upload a file it is enough to provide a [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) object as body.
@@ -125,7 +126,7 @@ formData.append('title', 'Hello world!');
const createdRecord = await client.Records.create('example', formData);
```
-#### Errors handling
+### Errors handling
All services return a standard [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)-based response, so the error handling is straightforward:
```js
@@ -157,26 +158,32 @@ ClientResponseError {
}
```
-#### AuthStore
+### AuthStore
The SDK keeps track of the authenticated token and auth model for you via the `client.authStore` instance.
-It has the following public members that you can use:
+
+The default [`LocalAuthStore`](https://github.com/pocketbase/js-sdk/blob/master/src/stores/LocalAuthStore.ts) uses the browser's `LocalStorage` if available, otherwise - will fallback to runtime/memory (aka. on page refresh or service restart you'll have to authenticate again).
+
+The default `client.authStore` extends [`BaseAuthStore`](https://github.com/pocketbase/js-sdk/blob/master/src/stores/BaseAuthStore.ts) and has the following public members that you can use:
```js
-AuthStore {
- // fields
- token: string // the authenticated token
- model: User|Admin|{} // the authenticated User or Admin model
- isValid: boolean // checks if the store has existing and unexpired token
+BaseAuthStore {
+ // base fields
+ token: string // the authenticated token
+ model: User|Admin|null // the authenticated User or Admin model
+ isValid: boolean // checks if the store has existing and unexpired token
- // methods
+ // main methods
clear() // "logout" the authenticated User or Admin
save(token, model) // update the store with the new auth data
+ onChange(callback) // register a callback that will be called on store change
+
+ // cookie parse and serialize helpers
+ loadFromCookie(cookieHeader, key = 'pb_auth')
+ exportToCookie(options = {}, key = 'pb_auth')
}
```
-By default the SDK initialize a [`LocalAuthStore`](https://github.com/pocketbase/js-sdk/blob/master/src/stores/LocalAuthStore.ts), which uses the browser's `LocalStorage` if available, otherwise - will fallback to runtime/memory store (aka. on page refresh or service restart you'll have to authenticate again).
-
To _"logout"_ an authenticated user or admin, you can just call `client.authStore.clear()`.
To _"listen"_ for changes in the auth store, you can register a new listener via `client.authStore.onChange`, eg:
@@ -194,13 +201,16 @@ If you want to create your own `AuthStore`, you can extend [`BaseAuthStore`](htt
import PocketBase, { BaseAuthStore } from 'pocketbase';
class CustomAuthStore extends BaseAuthStore {
- ...
+ save(token, model) {
+ super.save(token, model);
+ // your custom business logic...
+ }
}
const client = new PocketBase('http://127.0.0.1:8090', 'en-US', CustomAuthStore());
```
-#### Auto cancellation
+### Auto cancellation
The SDK client will auto cancel duplicated pending requests for you.
For example, if you have the following 3 duplicated calls, only the last one will be executed, while the first 2 will be cancelled with `ClientResponseError` error:
@@ -232,7 +242,7 @@ To manually cancel pending requests, you could use `client.cancelAllRequests()`
> If you want to completelly disable the auto cancellation behavior, you could use the `client.beforeSend` hook and
delete the `reqConfig.signal` property.
-#### Send hooks
+### Send hooks
Sometimes you may want to modify the request sent data or to customize the response.
@@ -268,9 +278,199 @@ To accomplish this, the SDK provides 2 function hooks:
};
```
+### SSR integration
+
+Unfortunately, **there is no "one size fits all" solution** because each framework handle SSR differently (_and even in a single framework there is more than one way of doing things_).
+
+But in general, the idea is to use a cookie based flow:
+
+1. Create a new `PocketBase` instance for each server-side request
+2. "Load/Feed" your `client.authStore` with data from the request cookie
+3. Perform your application server-side actions
+4. Before returning the response to the client, update the cookie with the latest `client.authStore` state
+
+All [`BaseAuthStore`](https://github.com/pocketbase/js-sdk/blob/master/src/stores/BaseAuthStore.ts) instances have 2 helper methods that
+should make working with cookies a little bit easier:
+
+```js
+// update the store with the parsed data from the cookie string
+client.authStore.loadFromCookie('pb_auth=...');
+
+// exports the store data as cookie, with option to extend the default SameSite, Secure, HttpOnly, Path and Expires attributes
+client.authStore.exportToCookie({ httpOnly: false }); // Output: 'pb_auth=...'
+```
+
+Below you could find several examples:
+
+
+ SvelteKit
+
+One way to integrate with SvelteKit SSR could be to create the PocketBase client in a [hook handle](https://kit.svelte.dev/docs/hooks#handle)
+and pass it to the other server-side actions using the `event.locals`.
+
+```js
+// src/hooks.js
+import PocketBase from 'pocketbase';
+
+export async function handle({ event, resolve }) {
+ event.locals.pocketbase = new PocketBase("http://127.0.0.1:8090");
+
+ // load the store data from the request cookie string
+ event.locals.pocketbase.authStore.loadFromCookie(event.request.headers.get('cookie') || '');
+
+ const response = await resolve(event);
+
+ // send back the default 'pb_auth' cookie to the client with the latest store state
+ response.headers.set('set-cookie', event.locals.pocketbase.authStore.exportToCookie());
+
+ return response;
+}
+```
+
+And then, in some of your server-side actions, you could directly access the previously created `event.locals.pocketbase` instance:
+
+```js
+// src/routes/login/+server.js
+//
+// creates a `POST /login` server-side endpoint
+export function POST({ request, locals }) {
+ const { email, password } = await request.json();
+
+ const { token, user } = await locals.pocketbase.users.authViaEmail(email, password);
+
+ return new Response('Success...');
+}
+```
+
+
+
+ Nuxt 3
+
+One way to integrate with Nuxt 3 SSR could be to create the PocketBase client in a [nuxt plugin](https://v3.nuxtjs.org/guide/directory-structure/plugins)
+and provide it as a helper to the `nuxtApp` instance:
+
+```js
+// plugins/pocketbase.js
+import PocketBase from 'pocketbase';
+
+export default defineNuxtPlugin((nuxtApp) => {
+ return {
+ provide: {
+ pocketbase: () => {
+ const client = new PocketBase('http://127.0.0.1:8090');
+
+ // load the store data from the request cookie string
+ client.authStore.loadFromCookie(nuxtApp.ssrContext?.event?.req?.headers?.cookie || '');
+
+ // send back the default 'pb_auth' cookie to the client with the latest store state
+ client.authStore.onChange(() => {
+ if (nuxtApp.ssrContext?.event?.res) {
+ nuxtApp.ssrContext.event.res.setHeader('set-cookie', client.authStore.exportToCookie());
+ }
+ });
+
+ return client;
+ }
+ }
+ }
+});
+```
+
+And then in your component you could access it like this:
+
+```html
+
+
+ Show: {{ data }}
+
+
+
+
+```
+
+> For Nuxt 2 you could use similar approach, but instead of `nuxtApp` you could use a store state to store/create the local `PocketBase` instance.
+
+
+
+ Next.js
+
+Next.js doesn't seem to have a central place where you can read/modify the server request and response.
+[There is support for middlewares](https://nextjs.org/docs/advanced-features/middleware),
+but they are very limited and, at the time of writing, you can't pass data from a middleware to the `getServerSideProps` functions (https://github.com/vercel/next.js/discussions/31792).
+
+One way to integrate with Next.js SSR could be to create a custom `PocketBase` instance in each of your `getServerSideProps`:
+
+```jsx
+import PocketBase, { BaseAuthStore } from 'pocketbase';
+
+class NextAuthStore extends BaseAuthStore {
+ constructor(req, res) {
+ super();
+
+ this.req = req;
+ this.res = res;
+
+ this.loadFromCookie(this.req?.headers?.cookie);
+ }
+
+ save(token, model) {
+ super.save(token, model);
+
+ this.res?.setHeader('set-cookie', this.exportToCookie());
+ }
+
+ clear() {
+ super.clear();
+
+ this.res?.setHeader('set-cookie', this.exportToCookie());
+ }
+}
+
+export async function getServerSideProps({ req, res }) {
+ const client = new PocketBase("https://pocketbase.io");
+ client.authStore = new NextAuthStore(req, res);
+
+ // fetch example records...
+ const result = await client.records.getList("example", 1, 30);
+
+ return {
+ props: {
+ // ...
+ },
+ }
+}
+
+export default function Home() {
+ return (
+ Hello world!
+ )
+}
+```
+
+
+### Security
+
+The most common frontend related vulnerability is XSS (and CSRF when dealing with cookies).
+Fortunately, modern browsers can detect and mitigate most of this type of attacks if [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) is provided.
+
+**To prevent a malicious user or 3rd party script to steal your PocketBase auth token, it is recommended to configure a basic CSP for your application (either as `meta` tag or HTTP header).**
+
+This is out of the scope of the SDK, but you could find more resources about CSP at:
+
+- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
+- https://content-security-policy.com
+
+
## Definitions
-#### Creating new client instance
+### Creating new client instance
```js
const client = new PocketBase(
@@ -280,7 +480,7 @@ const client = new PocketBase(
);
```
-#### Instance methods
+### Instance methods
> Each instance method returns the `PocketBase` instance allowing chaining.
@@ -292,7 +492,7 @@ const client = new PocketBase(
| `client.buildUrl(path, reqConfig = {})` | Builds a full client url by safely concatenating the provided path. |
-#### API services
+### API services
> Each service call returns a `Promise` object with the API response.
diff --git a/dist/pocketbase.cjs.d.ts b/dist/pocketbase.cjs.d.ts
index 46eff9a..f014b4e 100644
--- a/dist/pocketbase.cjs.d.ts
+++ b/dist/pocketbase.cjs.d.ts
@@ -1,3 +1,14 @@
+interface SerializeOptions {
+ encode?: (val: string | number | boolean) => string;
+ maxAge?: number;
+ domain?: string;
+ path?: string;
+ expires?: Date;
+ httpOnly?: boolean;
+ secure?: boolean;
+ priority?: string;
+ sameSite?: boolean | string;
+}
declare abstract class BaseModel {
id: string;
created: string;
@@ -64,9 +75,66 @@ declare class Admin extends BaseModel {
[key: string]: any;
}): void;
}
+/**
+ * Base AuthStore class that is intented to be extended by all other
+ * PocketBase AuthStore implementations.
+ */
+declare abstract class BaseAuthStore {
+ protected baseToken: string;
+ protected baseModel: User | Admin | null;
+ private _onChangeCallbacks;
+ /**
+ * Retrieves the stored token (if any).
+ */
+ get token(): string;
+ /**
+ * Retrieves the stored model data (if any).
+ */
+ get model(): User | Admin | null;
+ /**
+ * Checks if the store has valid (aka. existing and unexpired) token.
+ */
+ get isValid(): boolean;
+ /**
+ * Saves the provided new token and model data in the auth store.
+ */
+ save(token: string, model: User | Admin | null): void;
+ /**
+ * Removes the stored token and model data form the auth store.
+ */
+ clear(): void;
+ /**
+ * Parses the provided cookie string and updates the store state
+ * with the cookie's token and model data.
+ */
+ loadFromCookie(cookie: string, key?: string): void;
+ /**
+ * Exports the current store state as cookie string.
+ *
+ * By default the following optional attributes are added:
+ * - Secure
+ * - HttpOnly
+ * - SameSite=Strict
+ * - Path=/
+ * - Expires={the token expiration date}
+ *
+ * NB! If the generated cookie exceeds 4096 bytes, this method will
+ * strip the model data to the bare minimum to try to fit within the
+ * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.
+ */
+ exportToCookie(options?: SerializeOptions, key?: string): string;
+ /**
+ * Register a callback function that will be called on store change.
+ *
+ * Returns a removal function that you could call to "unsubscribe" from the changes.
+ */
+ onChange(callback: () => void): () => void;
+ protected triggerChange(): void;
+}
/**
* The minimal AuthStore interface.
*
+ * @deprecated
* This interface predates the abstract BaseAuthStore class
* and it is kept mainly for backward compatibility.
*
@@ -81,7 +149,7 @@ type AuthStore = {
/**
* Retrieves the stored model data (if any).
*/
- readonly model: User | Admin | {};
+ readonly model: User | Admin | null;
/**
* Checks if the store has valid (aka. existing and unexpired) token.
*/
@@ -89,7 +157,7 @@ type AuthStore = {
/**
* Saves new token and model data in the auth store.
*/
- save(token: string, model: User | Admin | {}): void;
+ save(token: string, model: User | Admin | null): void;
/**
* Removes the stored token and model data form the auth store.
*/
@@ -564,7 +632,7 @@ declare class Client {
/**
* A replacable instance of the local `AuthStore` service.
*/
- authStore: AuthStore;
+ authStore: AuthStore | BaseAuthStore;
/**
* An instance of the service that handles the **Settings APIs**.
*/
@@ -594,7 +662,7 @@ declare class Client {
*/
readonly realtime: Realtime;
private cancelControllers;
- constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | null);
+ constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | BaseAuthStore | null);
/**
* @deprecated Legacy alias for `this.authStore`.
*/
diff --git a/dist/pocketbase.cjs.js b/dist/pocketbase.cjs.js
index c2f4822..7dd396d 100644
--- a/dist/pocketbase.cjs.js
+++ b/dist/pocketbase.cjs.js
@@ -1 +1 @@
-"use strict";var t=function(e,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},t(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return n=Object.assign||function(t){for(var e,n=1,i=arguments.length;n0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!i.exp||i.exp-n>Date.now()/1e3))},t}(),a=function(){function t(){this.baseToken="",this.baseModel={},this._onChangeCallbacks=[]}return Object.defineProperty(t.prototype,"token",{get:function(){return this.baseToken},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"model",{get:function(){return this.baseModel},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"isValid",{get:function(){return!u.isExpired(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t,this.baseModel=e,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel={},this.triggerChange()},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},b=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],u=function(a){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,a,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?u(a+1):s}))]}))}))};return u(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!n.exp||n.exp-e>Date.now()/1e3))}(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t||"",this.baseModel=null!==e&&"object"==typeof e?"undefined"!==(null==e?void 0:e.verified)?new f(e):new v(e):null,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel=null,this.triggerChange()},t.prototype.loadFromCookie=function(t,e){void 0===e&&(e="pb_auth");var n=function(t,e){var n={};if("string"!=typeof t)return n;for(var i=Object.assign({},e||{}).decode||l,o=0;o4096&&(a.model={id:null===(i=null==a?void 0:a.model)||void 0===i?void 0:i.id,email:null===(o=null==a?void 0:a.model)||void 0===o?void 0:o.email},this.model instanceof f&&(a.model.verified=this.model.verified),l=u(e,JSON.stringify(a),t)),l},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},w=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],a=function(u){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,u,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?a(u+1):s}))]}))}))};return a(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r string;
+ maxAge?: number;
+ domain?: string;
+ path?: string;
+ expires?: Date;
+ httpOnly?: boolean;
+ secure?: boolean;
+ priority?: string;
+ sameSite?: boolean | string;
+}
declare abstract class BaseModel {
id: string;
created: string;
@@ -64,9 +75,66 @@ declare class Admin extends BaseModel {
[key: string]: any;
}): void;
}
+/**
+ * Base AuthStore class that is intented to be extended by all other
+ * PocketBase AuthStore implementations.
+ */
+declare abstract class BaseAuthStore {
+ protected baseToken: string;
+ protected baseModel: User | Admin | null;
+ private _onChangeCallbacks;
+ /**
+ * Retrieves the stored token (if any).
+ */
+ get token(): string;
+ /**
+ * Retrieves the stored model data (if any).
+ */
+ get model(): User | Admin | null;
+ /**
+ * Checks if the store has valid (aka. existing and unexpired) token.
+ */
+ get isValid(): boolean;
+ /**
+ * Saves the provided new token and model data in the auth store.
+ */
+ save(token: string, model: User | Admin | null): void;
+ /**
+ * Removes the stored token and model data form the auth store.
+ */
+ clear(): void;
+ /**
+ * Parses the provided cookie string and updates the store state
+ * with the cookie's token and model data.
+ */
+ loadFromCookie(cookie: string, key?: string): void;
+ /**
+ * Exports the current store state as cookie string.
+ *
+ * By default the following optional attributes are added:
+ * - Secure
+ * - HttpOnly
+ * - SameSite=Strict
+ * - Path=/
+ * - Expires={the token expiration date}
+ *
+ * NB! If the generated cookie exceeds 4096 bytes, this method will
+ * strip the model data to the bare minimum to try to fit within the
+ * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.
+ */
+ exportToCookie(options?: SerializeOptions, key?: string): string;
+ /**
+ * Register a callback function that will be called on store change.
+ *
+ * Returns a removal function that you could call to "unsubscribe" from the changes.
+ */
+ onChange(callback: () => void): () => void;
+ protected triggerChange(): void;
+}
/**
* The minimal AuthStore interface.
*
+ * @deprecated
* This interface predates the abstract BaseAuthStore class
* and it is kept mainly for backward compatibility.
*
@@ -81,7 +149,7 @@ type AuthStore = {
/**
* Retrieves the stored model data (if any).
*/
- readonly model: User | Admin | {};
+ readonly model: User | Admin | null;
/**
* Checks if the store has valid (aka. existing and unexpired) token.
*/
@@ -89,7 +157,7 @@ type AuthStore = {
/**
* Saves new token and model data in the auth store.
*/
- save(token: string, model: User | Admin | {}): void;
+ save(token: string, model: User | Admin | null): void;
/**
* Removes the stored token and model data form the auth store.
*/
@@ -564,7 +632,7 @@ declare class Client {
/**
* A replacable instance of the local `AuthStore` service.
*/
- authStore: AuthStore;
+ authStore: AuthStore | BaseAuthStore;
/**
* An instance of the service that handles the **Settings APIs**.
*/
@@ -594,7 +662,7 @@ declare class Client {
*/
readonly realtime: Realtime;
private cancelControllers;
- constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | null);
+ constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | BaseAuthStore | null);
/**
* @deprecated Legacy alias for `this.authStore`.
*/
@@ -667,48 +735,12 @@ declare class ClientResponseError extends Error {
// @see https://github.com/vuex-orm/vuex-orm/issues/255
toJSON(): this;
}
-/**
- * Base AuthStore class that is intented to be extended by all other
- * PocketBase AuthStore implementations.
- */
-declare abstract class BaseAuthStore implements AuthStore {
- protected baseToken: string;
- protected baseModel: User | Admin | {};
- private _onChangeCallbacks;
- /**
- * Retrieves the stored token (if any).
- */
- get token(): string;
- /**
- * Retrieves the stored model data (if any).
- */
- get model(): User | Admin | {};
- /**
- * Checks if the store has valid (aka. existing and unexpired) token.
- */
- get isValid(): boolean;
- /**
- * Saves the provided new token and model data in the auth store.
- */
- save(token: string, model: User | Admin | {}): void;
- /**
- * Removes the stored token and model data form the auth store.
- */
- clear(): void;
- /**
- * Register a callback function that will be called on store change.
- *
- * Returns a removal function that you could call to "unsubscribe" from the changes.
- */
- onChange(callback: () => void): () => void;
- protected triggerChange(): void;
-}
/**
* The default token store for browsers with auto fallback
* to runtime/memory if local storage is undefined (eg. in node env).
*/
declare class LocalAuthStore extends BaseAuthStore {
- private fallback;
+ private storageFallback;
private storageKey;
constructor(storageKey?: string);
/**
@@ -718,11 +750,11 @@ declare class LocalAuthStore extends BaseAuthStore {
/**
* @inheritdoc
*/
- get model(): User | Admin | {};
+ get model(): User | Admin | null;
/**
* @inheritdoc
*/
- save(token: string, model: User | Admin | {}): void;
+ save(token: string, model: User | Admin | null): void;
/**
* @inheritdoc
*/
diff --git a/dist/pocketbase.es.mjs b/dist/pocketbase.es.mjs
index 54544c8..c678354 100644
--- a/dist/pocketbase.es.mjs
+++ b/dist/pocketbase.es.mjs
@@ -1,2 +1,2 @@
-var t=function(e,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},t(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return n=Object.assign||function(t){for(var e,n=1,i=arguments.length;n0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!i.exp||i.exp-n>Date.now()/1e3))},t}(),a=function(){function t(){this.baseToken="",this.baseModel={},this._onChangeCallbacks=[]}return Object.defineProperty(t.prototype,"token",{get:function(){return this.baseToken},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"model",{get:function(){return this.baseModel},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"isValid",{get:function(){return!u.isExpired(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t,this.baseModel=e,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel={},this.triggerChange()},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},b=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],u=function(a){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,a,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?u(a+1):s}))]}))}))};return u(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!n.exp||n.exp-e>Date.now()/1e3))}(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t||"",this.baseModel=null!==e&&"object"==typeof e?"undefined"!==(null==e?void 0:e.verified)?new f(e):new v(e):null,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel=null,this.triggerChange()},t.prototype.loadFromCookie=function(t,e){void 0===e&&(e="pb_auth");var n=function(t,e){var n={};if("string"!=typeof t)return n;for(var i=Object.assign({},e||{}).decode||l,o=0;o4096&&(a.model={id:null===(i=null==a?void 0:a.model)||void 0===i?void 0:i.id,email:null===(o=null==a?void 0:a.model)||void 0===o?void 0:o.email},this.model instanceof f&&(a.model.verified=this.model.verified),l=u(e,JSON.stringify(a),t)),l},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},S=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],a=function(u){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,u,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?a(u+1):s}))]}))}))};return a(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r Buffer.from(a, 'base64').toString('binary');\n}\n\nexport default class JWT {\n /**\n * Returns JWT token's payload data.\n */\n static getPayload(token: string): { [key: string]: any } {\n if (token) {\n try {\n\n let base64 = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(base64) || {};\n } catch (e) {\n }\n }\n\n return {};\n }\n\n /**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be substracted from the token `exp` property.\n */\n static isExpired(token: string, expirationThreshold = 0): boolean {\n let payload = JWT.getPayload(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}\n","import { AuthStore } from '@/stores/utils/AuthStore';\nimport JWT from '@/stores/utils/JWT';\nimport User from '@/models/User';\nimport Admin from '@/models/Admin';\n\ntype onChangeFunc = (token: string, model: User | Admin | {}) => void;\n\n/**\n * Base AuthStore class that is intented to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport default abstract class BaseAuthStore implements AuthStore {\n protected baseToken: string = '';\n protected baseModel: User | Admin | {} = {};\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): User | Admin | {} {\n return this.baseModel;\n }\n\n /**\n * Checks if the store has valid (aka. existing and unexpired) token.\n */\n get isValid(): boolean {\n return !JWT.isExpired(this.token);\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model: User | Admin | {}): void {\n this.baseToken = token;\n this.baseModel = model;\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 = {};\n this.triggerChange();\n }\n\n /**\n * Register a callback function that will be called on store change.\n *\n * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: () => void): () => void {\n this._onChangeCallbacks.push(callback);\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","export default abstract class BaseModel {\n id!: string;\n created!: string;\n updated!: string;\n\n constructor(data: { [key: string]: any } = {}) {\n this.load(data || {});\n }\n\n /**\n * Loads `data` into the current model.\n */\n load(data: { [key: string]: any }) {\n this.id = typeof data.id !== 'undefined' ? data.id : '';\n this.created = typeof data.created !== 'undefined' ? data.created : '';\n this.updated = typeof data.updated !== 'undefined' ? data.updated : '';\n }\n\n /**\n * Returns whether the current loaded data represent a stored db record.\n */\n get isNew(): boolean {\n return (\n // id is not set\n !this.id ||\n // zero uuid value\n this.id === '00000000-0000-0000-0000-000000000000'\n );\n }\n\n /**\n * Robust deep clone of a model.\n */\n clone(): BaseModel {\n return new (this.constructor as any)(JSON.parse(JSON.stringify(this)));\n }\n\n /**\n * Exports all model properties as a new plain object.\n */\n export(): { [key: string]: any } {\n return Object.assign({}, this);\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class Record extends BaseModel {\n [key: string]: any,\n\n '@collectionId'!: string;\n '@collectionName'!: string;\n '@expand'!: {[key: string]: any};\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n for (const [key, value] of Object.entries(data)) {\n this[key] = value;\n }\n\n // normalize common fields\n this['@collectionId'] = typeof data['@collectionId'] !== 'undefined' ? data['@collectionId'] : '';\n this['@collectionName'] = typeof data['@collectionName'] !== 'undefined' ? data['@collectionName'] : '';\n this['@expand'] = typeof data['@expand'] !== 'undefined' ? data['@expand'] : {};\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport Record from '@/models/Record';\n\nexport default class User extends BaseModel {\n email!: string;\n verified!: boolean;\n lastResetSentAt!: string;\n lastVerificationSentAt!: string;\n profile!: null|Record;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.email = typeof data.email === 'string' ? data.email : '';\n this.verified = !!data.verified;\n this.lastResetSentAt = typeof data.lastResetSentAt === 'string' ? data.lastResetSentAt : '';\n this.lastVerificationSentAt = typeof data.lastVerificationSentAt === 'string' ? data.lastVerificationSentAt : '';\n this.profile = data.profile ? new Record(data.profile) : null;\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class Admin extends BaseModel {\n avatar!: number;\n email!: string;\n lastResetSentAt!: string;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.avatar = typeof data.avatar === 'number' ? data.avatar : 0;\n this.email = typeof data.email === 'string' ? data.email : '';\n this.lastResetSentAt = typeof data.lastResetSentAt === 'string' ? data.lastResetSentAt : '';\n }\n}\n","import BaseAuthStore from '@/stores/BaseAuthStore';\nimport User from '@/models/User';\nimport Admin from '@/models/Admin';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport default class LocalAuthStore extends BaseAuthStore {\n private fallback: { [key: string]: any } = {};\n private storageKey: string\n\n constructor(storageKey = \"pocketbase_auth\") {\n super();\n\n this.storageKey = storageKey;\n }\n\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): User | Admin | {} {\n const data = this._storageGet(this.storageKey) || {};\n\n if (\n data === null ||\n typeof data !== 'object' ||\n data.model === null ||\n typeof data.model !== 'object'\n ) {\n return {};\n }\n\n // admins don't have `verified` prop\n if (typeof data.model?.verified !== 'undefined') {\n return new User(data.model);\n }\n\n return new Admin(data.model);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model: User | Admin | {}) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window?.localStorage?.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback to runtime/memory\n return this.fallback[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 runtime/memory\n this.fallback[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') {\n window?.localStorage?.removeItem(key);\n }\n\n // delete from runtime/memory\n delete this.fallback[key];\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport default abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import BaseService from '@/services/utils/BaseService';\n\nexport default class Settings extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(queryParams = {}): Promise<{ [key: string]: any }> {\n return this.client.send('/api/settings', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData) => responseData || {});\n }\n\n /**\n * Bulk updates app settings.\n */\n update(bodyParams = {}, queryParams = {}): Promise<{ [key: string]: any }> {\n return this.client.send('/api/settings', {\n 'method': 'PATCH',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData) => responseData || {});\n }\n\n /**\n * Performs a S3 storage connection test.\n */\n testS3(queryParams = {}): Promise {\n return this.client.send('/api/settings/test/s3', {\n 'method': 'POST',\n 'params': queryParams,\n }).then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, queryParams = {}): Promise {\n const bodyParams = {\n 'email': toEmail,\n 'template': emailTemplate,\n };\n\n return this.client.send('/api/settings/test/email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n}\n","import BaseModel from './BaseModel';\n\nexport default class ListResult {\n page!: number;\n perPage!: number;\n totalItems!: number;\n totalPages!: number;\n items!: Array;\n\n constructor(\n page: number,\n perPage: number,\n totalItems: number,\n totalPages: number,\n items: Array,\n ) {\n this.page = page > 0 ? page : 1;\n this.perPage = perPage >= 0 ? perPage : 0;\n this.totalItems = totalItems >= 0 ? totalItems : 0;\n this.totalPages = totalPages >= 0 ? totalPages : 0;\n this.items = items || [];\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseService from '@/services/utils/BaseService';\n\nexport default abstract class BaseCrudService extends BaseService {\n /**\n * Response data decoder.\n */\n abstract decode(data: { [key: string]: any }): M\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(basePath: string, batchSize = 100, queryParams = {}): Promise> {\n var result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this._getList(basePath, page, batchSize, queryParams).then((list) => {\n const castedList = (list as ListResult);\n const items = castedList.items;\n const totalItems = castedList.totalItems;\n\n result = result.concat(items);\n\n if (items.length && totalItems > result.length) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n\n /**\n * Returns paginated items list.\n */\n protected _getList(basePath: string, page = 1, perPage = 30, queryParams = {}): Promise> {\n queryParams = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, queryParams);\n\n return this.client.send(basePath, {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n const items: Array = [];\n if (responseData?.items) {\n responseData.items = responseData.items || [];\n for (const item of responseData.items) {\n items.push(this.decode(item));\n }\n }\n\n return new ListResult(\n responseData?.page || 1,\n responseData?.perPage || 0,\n responseData?.totalItems || 0,\n responseData?.totalPages || 0,\n items,\n );\n });\n }\n\n /**\n * Returns single item by its id.\n */\n protected _getOne(basePath: string, id: string, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n */\n protected _create(basePath: string, bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(basePath, {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n */\n protected _update(basePath: string, id: string, bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'PATCH',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n protected _delete(basePath: string, id: string, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'DELETE',\n 'params': queryParams,\n }).then(() => true);\n }\n}\n","import ListResult from '@/models/utils/ListResult';\nimport BaseModel from '@/models/utils/BaseModel';\nimport BaseCrudService from '@/services/utils/BaseCrudService';\n\nexport default abstract class CrudService extends BaseCrudService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract baseCrudPath(): string\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n getFullList(batchSize = 100, queryParams = {}): Promise> {\n return this._getFullList(this.baseCrudPath(), batchSize, queryParams);\n }\n\n /**\n * Returns paginated items list.\n */\n getList(page = 1, perPage = 30, queryParams = {}): Promise> {\n return this._getList(this.baseCrudPath(), page, perPage, queryParams);\n }\n\n /**\n * Returns single item by its id.\n */\n getOne(id: string, queryParams = {}): Promise {\n return this._getOne(this.baseCrudPath(), id, queryParams);\n }\n\n /**\n * Creates a new item.\n */\n create(bodyParams = {}, queryParams = {}): Promise {\n return this._create(this.baseCrudPath(), bodyParams, queryParams);\n }\n\n /**\n * Updates an existing item by its id.\n */\n update(id: string, bodyParams = {}, queryParams = {}): Promise {\n return this._update(this.baseCrudPath(), id, bodyParams, queryParams);\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, queryParams = {}): Promise {\n return this._delete(this.baseCrudPath(), id, queryParams);\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport Admin from '@/models/Admin';\n\nexport type AdminAuthResponse = {\n [key: string]: any,\n token: string,\n admin: Admin,\n}\n\nexport default class Admins extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Admin {\n return new Admin(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/admins';\n }\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account by its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authViaEmail(\n email: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n refresh(bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/refresh', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport User from '@/models/User';\n\nexport type UserAuthResponse = {\n [key: string]: any,\n token: string,\n user: User,\n}\n\nexport type AuthProviderInfo = {\n name: string,\n state: string,\n codeVerifier: string,\n codeChallenge: string,\n codeChallengeMethod: string,\n authUrl: string,\n}\n\nexport type AuthMethodsList = {\n [key: string]: any,\n emailPassword: boolean,\n authProviders: Array,\n}\n\nexport default class Users extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): User {\n return new User(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/users';\n }\n\n /**\n * Prepare successful authorization response.\n */\n protected authResponse(responseData: any): UserAuthResponse {\n const user = this.decode(responseData?.user || {});\n\n if (responseData?.token && responseData?.user) {\n this.client.authStore.save(responseData.token, user);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'user': user,\n });\n }\n\n /**\n * Returns all available application auth methods.\n */\n listAuthMethods(queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/auth-methods', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a user via its email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - new user authentication token\n * - the authenticated user model record\n */\n authViaEmail(\n email: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Authenticate a user via OAuth2 client provider.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - new user authentication token\n * - the authenticated user model record\n * - the OAuth2 user profile data (eg. name, email, avatar, etc.)\n */\n authViaOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-oauth2', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current user authenticated instance and\n * returns a new token and user data.\n *\n * On success this method also automatically updates the client's AuthStore data.\n */\n refresh(bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/refresh', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends user password reset request.\n */\n requestPasswordReset(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends user verification email request.\n */\n requestVerification(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-verification', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user email verification request.\n */\n confirmVerification(\n verificationToken: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': verificationToken,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-verification', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends an email change request to the authenticated user.\n */\n requestEmailChange(\n newEmail: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'newEmail': newEmail,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-email-change', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user new email address.\n */\n confirmEmailChange(\n emailChangeToken: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': emailChangeToken,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-email-change', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n}\n","export default class SchemaField {\n id!: string;\n name!: string;\n type!: string;\n system!: boolean;\n required!: boolean;\n unique!: boolean;\n options!: { [key: string]: any };\n\n constructor(data: { [key: string]: any } = {}) {\n this.load(data || {});\n }\n\n /**\n * Loads `data` into the field.\n */\n load(data: { [key: string]: any }) {\n this.id = typeof data.id !== 'undefined' ? data.id : '';\n this.name = typeof data.name !== 'undefined' ? data.name : '';\n this.type = typeof data.type !== 'undefined' ? data.type : 'text';\n this.system = !!data.system;\n this.required = !!data.required;\n this.unique = !!data.unique;\n this.options = typeof data.options === 'object' && data.options !== null ? data.options : {};\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport SchemaField from '@/models/utils/SchemaField';\n\nexport default class Collection extends BaseModel {\n name!: string;\n schema!: Array;\n system!: boolean;\n listRule!: null|string;\n viewRule!: null|string;\n createRule!: null|string;\n updateRule!: null|string;\n deleteRule!: null|string;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.name = typeof data.name === 'string' ? data.name : '';\n this.system = !!data.system;\n\n // rules\n this.listRule = typeof data.listRule === 'string' ? data.listRule : null;\n this.viewRule = typeof data.viewRule === 'string' ? data.viewRule : null;\n this.createRule = typeof data.createRule === 'string' ? data.createRule : null;\n this.updateRule = typeof data.updateRule === 'string' ? data.updateRule : null;\n this.deleteRule = typeof data.deleteRule === 'string' ? data.deleteRule : null;\n\n // schema\n data.schema = Array.isArray(data.schema) ? data.schema : [];\n this.schema = [];\n for (let field of data.schema) {\n this.schema.push(new SchemaField(field));\n }\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport Collection from '@/models/Collection';\n\nexport default class Collections extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Collection {\n return new Collection(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(collections: Array, deleteMissing: boolean = false, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/import', {\n 'method': 'PUT',\n 'params': queryParams,\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }).then(() => true);\n }\n}\n","import SubCrudService from '@/services/utils/SubCrudService';\nimport Record from '@/models/Record';\n\nexport default class Records extends SubCrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Record {\n return new Record(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(collectionIdOrName: string): string {\n return '/api/collections/' + encodeURIComponent(collectionIdOrName) + '/records';\n }\n\n /**\n * Builds and returns an absolute record file url.\n */\n getFileUrl(record: Record, filename: string, queryParams = {}): string {\n const parts = [];\n parts.push(this.client.baseUrl.replace(/\\/+$/gm, \"\"))\n parts.push(\"api\")\n parts.push(\"files\")\n parts.push(record[\"@collectionId\"])\n parts.push(record.id)\n parts.push(filename)\n let result = parts.join('/');\n\n if (Object.keys(queryParams).length) {\n const params = new URLSearchParams(queryParams);\n result += (result.includes(\"?\") ? \"&\" : \"?\") + params;\n }\n\n return result\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseCrudService from '@/services/utils/BaseCrudService';\n\nexport default abstract class SubCrudService extends BaseCrudService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/collections/{:sub}/records').\n */\n abstract baseCrudPath(sub: string): string\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n getFullList(sub: string, batchSize = 100, queryParams = {}): Promise> {\n return this._getFullList(this.baseCrudPath(sub), batchSize, queryParams);\n }\n\n /**\n * Returns paginated items list.\n */\n getList(sub: string, page = 1, perPage = 30, queryParams = {}): Promise> {\n return this._getList(this.baseCrudPath(sub), page, perPage, queryParams);\n }\n\n /**\n * Returns single item by its id.\n */\n getOne(sub: string, id: string, queryParams = {}): Promise {\n return this._getOne(this.baseCrudPath(sub), id, queryParams);\n }\n\n /**\n * Creates a new item.\n */\n create(sub: string, bodyParams = {}, queryParams = {}): Promise {\n return this._create(this.baseCrudPath(sub), bodyParams, queryParams);\n }\n\n /**\n * Updates an existing item by its id.\n */\n update(sub: string, id: string, bodyParams = {}, queryParams = {}): Promise {\n return this._update(this.baseCrudPath(sub), id, bodyParams, queryParams);\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(sub: string, id: string, queryParams = {}): Promise {\n return this._delete(this.baseCrudPath(sub), id, queryParams);\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class LogRequest extends BaseModel {\n url!: string;\n method!: string;\n status!: number;\n auth!: string;\n remoteIp!: string;\n userIp!: string;\n referer!: string;\n userAgent!: string;\n meta!: null|{ [key: string]: any };\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n // fallback to the ip field for backward compatability\n data.remoteIp = data.remoteIp || data.ip;\n\n this.url = typeof data.url === 'string' ? data.url : '';\n this.method = typeof data.method === 'string' ? data.method : 'GET';\n this.status = typeof data.status === 'number' ? data.status : 200;\n this.auth = typeof data.auth === 'string' ? data.auth : 'guest';\n this.remoteIp = typeof data.remoteIp === 'string' ? data.remoteIp : '';\n this.userIp = typeof data.userIp === 'string' ? data.userIp : '';\n this.referer = typeof data.referer === 'string' ? data.referer : '';\n this.userAgent = typeof data.userAgent === 'string' ? data.userAgent : '';\n this.meta = typeof data.meta === 'object' && data.meta !== null ? data.meta : {};\n }\n}\n","import LogRequest from '@/models/LogRequest';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseService from '@/services/utils/BaseService';\n\nexport type HourlyStats = {\n total: number,\n date: string,\n}\n\nexport default class Logs extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, queryParams = {}): Promise> {\n queryParams = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, queryParams);\n\n return this.client.send('/api/logs/requests', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n const items: Array = [];\n if (responseData?.items) {\n responseData.items = responseData?.items || [];\n for (const item of responseData.items) {\n items.push(new LogRequest(item));\n }\n }\n\n return new ListResult(\n responseData?.page || 1,\n responseData?.perPage || 0,\n responseData?.totalItems || 0,\n responseData?.totalPages || 0,\n items,\n );\n });\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, queryParams = {}): Promise {\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => new LogRequest(responseData));\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(queryParams = {}): Promise> {\n return this.client.send('/api/logs/requests/stats', {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => responseData);\n }\n}\n","import BaseService from '@/services/utils/BaseService';\nimport Record from '@/models/Record';\n\nexport interface MessageData {\n [key: string]: any;\n action: string;\n record: Record;\n}\n\nexport interface SubscriptionFunc{\n (data: MessageData):void;\n}\n\nexport default class Realtime extends BaseService {\n private clientId: string = \"\";\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: EventListener } = {};\n\n /**\n * Inits the sse connection (if not already) and register the subscription.\n */\n async subscribe(subscription: string, callback: SubscriptionFunc): Promise {\n if (!subscription) {\n throw new Error('subscription must be set.')\n }\n\n // unsubscribe existing\n if (this.subscriptions[subscription]) {\n this.eventSource?.removeEventListener(subscription, this.subscriptions[subscription]);\n }\n\n // register subscription\n this.subscriptions[subscription] = 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 if (!this.eventSource) {\n // start a new sse connection\n this.connect();\n } else if (this.clientId) {\n // otherwise - just persist the updated subscriptions\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from a subscription.\n *\n * If the `subscription` argument is not set,\n * then the client will unsubscribe from all registered subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operations there are no active subscriptions left.\n */\n async unsubscribe(subscription?: string): Promise {\n if (!subscription) {\n // remove all subscriptions\n this.removeSubscriptionListeners();\n this.subscriptions = {};\n } else if (this.subscriptions[subscription]) {\n // remove a single subscription\n this.eventSource?.removeEventListener(subscription, this.subscriptions[subscription]);\n delete this.subscriptions[subscription];\n } else {\n // not subscribed to the specified subscription\n return\n }\n\n if (this.clientId) {\n await this.submitSubscriptions();\n }\n\n // no more subscriptions -> close the sse connection\n if (!Object.keys(this.subscriptions).length) {\n this.disconnect();\n }\n }\n\n private async submitSubscriptions(): Promise {\n // optimistic update\n this.addSubscriptionListeners();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': Object.keys(this.subscriptions),\n },\n }).then(() => true);\n }\n\n private addSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeSubscriptionListeners();\n\n for (let sub in this.subscriptions) {\n this.eventSource.addEventListener(sub, this.subscriptions[sub]);\n }\n }\n\n private removeSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let sub in this.subscriptions) {\n this.eventSource.removeEventListener(sub, this.subscriptions[sub]);\n }\n }\n\n private connectHandler(e: Event): void {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n this.submitSubscriptions();\n }\n\n private connect(): void {\n this.disconnect();\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n this.eventSource.addEventListener('PB_CONNECT', (e) => this.connectHandler(e));\n }\n\n private disconnect(): void {\n this.removeSubscriptionListeners();\n this.eventSource?.removeEventListener('PB_CONNECT', (e) => this.connectHandler(e));\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n }\n}\n","import ClientResponseError from '@/ClientResponseError';\nimport { AuthStore } from '@/stores/utils/AuthStore';\nimport LocalAuthStore from '@/stores/LocalAuthStore';\nimport Settings from '@/services/Settings';\nimport Admins from '@/services/Admins';\nimport Users from '@/services/Users';\nimport Collections from '@/services/Collections';\nimport Records from '@/services/Records';\nimport Logs from '@/services/Logs';\nimport Realtime from '@/services/Realtime';\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect/modify the request config.\n *\n * Returns the new modified config that will be used to send the request.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, reqConfig) {\n * reqConfig.headers = Object.assign({}, reqConfig.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return reqConfig;\n * };\n * ```\n */\n beforeSend?: (url: string, reqConfig: { [key: string]: any }) => { [key: string]: any };\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replacable instance of the local `AuthStore` service.\n */\n authStore: AuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: Settings;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: Admins;\n\n /**\n * An instance of the service that handles the **User APIs**.\n */\n readonly users: Users;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: Collections;\n\n /**\n * An instance of the service that handles the **Record APIs**.\n */\n readonly records: Records;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: Logs;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: Realtime;\n\n private cancelControllers: { [key: string]: AbortController } = {}\n\n constructor(\n baseUrl = '/',\n lang = 'en-US',\n authStore?: AuthStore | null,\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new Admins(this);\n this.users = new Users(this);\n this.records = new Records(this);\n this.collections = new Collections(this);\n this.logs = new Logs(this);\n this.settings = new Settings(this);\n this.realtime = new Realtime(this);\n }\n\n /**\n * @deprecated Legacy alias for `this.authStore`.\n */\n get AuthStore(): AuthStore {\n return this.authStore;\n };\n\n /**\n * @deprecated Legacy alias for `this.settings`.\n */\n get Settings(): Settings {\n return this.settings;\n };\n\n /**\n * @deprecated Legacy alias for `this.admins`.\n */\n get Admins(): Admins {\n return this.admins;\n };\n\n /**\n * @deprecated Legacy alias for `this.users`.\n */\n get Users(): Users {\n return this.users;\n };\n\n /**\n * @deprecated Legacy alias for `this.collections`.\n */\n get Collections(): Collections {\n return this.collections;\n };\n\n /**\n * @deprecated Legacy alias for `this.records`.\n */\n get Records(): Records {\n return this.records;\n };\n\n /**\n * @deprecated Legacy alias for `this.logs`.\n */\n get Logs(): Logs {\n return this.logs;\n };\n\n /**\n * @deprecated Legacy alias for `this.realtime`.\n */\n get Realtime(): Realtime {\n return this.realtime;\n };\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(cancelKey: string): Client {\n if (this.cancelControllers[cancelKey]) {\n this.cancelControllers[cancelKey].abort();\n delete this.cancelControllers[cancelKey];\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 * Sends an api http request.\n */\n async send(path: string, reqConfig: { [key: string]: any }): Promise {\n let config = Object.assign({ method: 'GET' } as { [key: string]: any }, reqConfig);\n\n // serialize the body if needed and set the correct content type\n // note1: for FormData body the Content-Type header should be skipped\n // note2: we are checking the constructor name because FormData is not available natively in node\n if (config.body && config.body.constructor.name !== 'FormData') {\n if (typeof config.body !== 'string') {\n config.body = JSON.stringify(config.body);\n }\n\n // add the json header (if not already)\n if (typeof config?.headers?.['Content-Type'] === 'undefined') {\n config.headers = Object.assign({}, config.headers, {\n 'Content-Type': 'application/json',\n });\n }\n }\n\n // add Accept-Language header (if not already)\n if (typeof config?.headers?.['Accept-Language'] === 'undefined') {\n config.headers = Object.assign({}, config.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has stored token\n this.authStore?.token &&\n // auth header is not explicitly set\n (typeof config?.headers?.Authorization === 'undefined')\n ) {\n let authType = 'Admin';\n if (typeof (this.authStore.model as any)?.verified !== 'undefined') {\n authType = 'User'; // admins don't have verified\n }\n\n config.headers = Object.assign({}, config.headers, {\n 'Authorization': (authType + ' ' + this.authStore.token),\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (config.params?.$autoCancel !== false) {\n const cancelKey = config.params?.$cancelKey || ((config.method || 'GET') + path);\n\n // cancel previous pending requests\n this.cancelRequest(cancelKey);\n\n const controller = new AbortController();\n this.cancelControllers[cancelKey] = controller;\n config.signal = controller.signal;\n }\n // remove the special cancellation params from the other valid query params\n delete config.params?.$autoCancel;\n delete config.params?.$cancelKey;\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof config.params !== 'undefined') {\n const query = this.serializeQueryParams(config.params)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete config.params;\n }\n\n if (this.beforeSend) {\n config = Object.assign({}, this.beforeSend(url, config));\n }\n\n // send the request\n return fetch(url, config)\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 = this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\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 + (this.baseUrl.endsWith('/') ? '' : '/');\n if (path) {\n url += (path.startsWith('/') ? path.substring(1) : path);\n }\n return url;\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // \"repeat\" array params\n for (const v of value) {\n result.push(encodedKey + \"=\" + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + \"=\" + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + \"=\" + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + \"=\" + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["atobPolyfill","ClientResponseError","_super","errData","_this","this","call","url","status","data","isAbort","originalError","Object","setPrototypeOf","prototype","DOMException","name","message","_a","__extends","toJSON","__assign","Error","atob","a","Buffer","from","toString","JWT","getPayload","token","base64","decodeURIComponent","split","map","c","charCodeAt","slice","join","JSON","parse","e","isExpired","expirationThreshold","payload","keys","length","exp","Date","now","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","defineProperty","get","save","model","triggerChange","clear","onChange","callback","push","i","splice","_i","BaseModel","load","id","created","updated","clone","constructor","stringify","export","assign","Record","entries","_b","key","value","User","email","verified","lastResetSentAt","lastVerificationSentAt","profile","Admin","avatar","LocalAuthStore","storageKey","fallback","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","BaseService","client","Settings","getAll","queryParams","send","method","params","then","responseData","update","bodyParams","body","testS3","testEmail","toEmail","emailTemplate","template","ListResult","page","perPage","totalItems","totalPages","items","BaseCrudService","_getFullList","basePath","batchSize","result","request","__awaiter","_getList","list","castedList","concat","item","decode","_getOne","encodeURIComponent","_create","_update","_delete","CrudService","getFullList","baseCrudPath","getList","getOne","create","delete","Admins","authResponse","admin","authStore","authViaEmail","password","headers","Authorization","bind","refresh","requestPasswordReset","confirmPasswordReset","passwordResetToken","passwordConfirm","Users","user","listAuthMethods","emailPassword","authProviders","Array","isArray","authViaOAuth2","provider","code","codeVerifier","redirectUrl","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","SchemaField","type","system","required","unique","options","Collection","listRule","viewRule","createRule","updateRule","deleteRule","schema","field","Collections","import","collections","deleteMissing","Records","collectionIdOrName","getFileUrl","record","filename","parts","baseUrl","replace","URLSearchParams","includes","SubCrudService","sub","LogRequest","remoteIp","ip","auth","userIp","referer","userAgent","meta","Logs","getRequestsList","getRequest","getRequestsStats","Realtime","apply","arguments","clientId","eventSource","subscriptions","subscribe","subscription","removeEventListener","msgEvent","connect","submitSubscriptions","sent","unsubscribe","removeSubscriptionListeners","disconnect","addSubscriptionListeners","addEventListener","connectHandler","lastEventId","EventSource","buildUrl","close","Client","lang","cancelControllers","admins","users","records","logs","settings","realtime","cancelRequest","cancelKey","abort","cancelAllRequests","k","path","reqConfig","config","_c","_d","authType","_e","_f","$autoCancel","_g","$cancelKey","controller","AbortController","signal","_h","_j","query","serializeQueryParams","beforeSend","fetch","response","json","afterSend","catch","err","endsWith","startsWith","substring","encodedKey","value_1","v","toISOString"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"pocketbase.es.mjs","sources":["../src/ClientResponseError.ts","../src/stores/utils/jwt.ts","../src/stores/utils/cookie.ts","../src/models/utils/BaseModel.ts","../src/models/Record.ts","../src/models/User.ts","../src/models/Admin.ts","../src/stores/BaseAuthStore.ts","../src/stores/LocalAuthStore.ts","../src/services/utils/BaseService.ts","../src/services/Settings.ts","../src/models/utils/ListResult.ts","../src/services/utils/BaseCrudService.ts","../src/services/utils/CrudService.ts","../src/services/Admins.ts","../src/services/Users.ts","../src/models/utils/SchemaField.ts","../src/models/Collection.ts","../src/services/Collections.ts","../src/services/Records.ts","../src/services/utils/SubCrudService.ts","../src/models/LogRequest.ts","../src/services/Logs.ts","../src/services/Realtime.ts","../src/Client.ts"],"sourcesContent":["/**\n * ClientResponseError is a custom Error class that is intended to wrap\n * and normalize any error thrown by `Client.send()`.\n */\nexport default class ClientResponseError extends Error {\n url: string = '';\n status: number = 0;\n data: {[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 instanceof ClientResponseError)) {\n this.originalError = errData;\n }\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.data = errData.data !== null && typeof errData.data === 'object' ? errData.data : {};\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.data?.message || 'Something went wrong while processing your request.'\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 toJSON () {\n return { ...this };\n }\n}\n","let atobPolyfill: Function;\nif (typeof atob === 'function') {\n atobPolyfill = atob\n} else {\n atobPolyfill = (a: any) => Buffer.from(a, 'base64').toString('binary');\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\n let base64 = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n }).join(''));\n\n return JSON.parse(base64) || {};\n } catch (e) {\n }\n }\n\n return {};\n}\n\n/**\n * Checks whether a JWT token is expired or not.\n * Tokens without `exp` payload key are considered valid.\n * Tokens with empty payload (eg. invalid token strings) are considered expired.\n *\n * @param token The token to check.\n * @param [expirationThreshold] Time in seconds that will be substracted 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","/**\n * -------------------------------------------------------------------\n * Simple cookie parse and serialize utilities mostly based on the\n * node module https://github.com/jshttp/cookie.\n * -------------------------------------------------------------------\n */\n\n/**\n * RegExp to match field-content in RFC 7230 sec 3.2\n *\n * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\n * field-vchar = VCHAR / obs-text\n * obs-text = %x80-FF\n */\nconst fieldContentRegExp = /^[\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+$/;\n\nexport interface ParseOptions{\n decode?: (val: string) => string,\n}\n\n/**\n* Parses the given cookie header string into an object\n* The object has the various cookies as keys(names) => values\n*/\nexport function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {\n const result: { [key: string]: any } = {};\n\n if (typeof str !== 'string') {\n return result;\n }\n\n const opt = Object.assign({}, options || {});\n const decode = opt.decode || defaultDecode;\n\n let index = 0;\n while (index < str.length) {\n const eqIdx = str.indexOf('=', index);\n\n // no more cookie pairs\n if (eqIdx === -1) {\n break;\n }\n\n let endIdx = str.indexOf(';', index);\n\n if (endIdx === -1) {\n endIdx = str.length;\n } else if (endIdx < eqIdx) {\n // backtrack on prior semicolon\n index = str.lastIndexOf(';', eqIdx - 1) + 1;\n continue;\n }\n\n const key = str.slice(index, eqIdx).trim();\n\n // only assign once\n if (undefined === result[key]) {\n let val = str.slice(eqIdx + 1, endIdx).trim();\n\n // quoted values\n if (val.charCodeAt(0) === 0x22) {\n val = val.slice(1, -1);\n }\n\n try {\n result[key] = decode(val);\n } catch (_) {\n result[key] = val; // no decoding\n }\n }\n\n index = endIdx + 1;\n }\n\n return result;\n};\n\nexport interface SerializeOptions{\n encode?: (val: string | number | boolean) => string,\n maxAge?: number,\n domain?: string,\n path?: string,\n expires?: Date,\n httpOnly?: boolean,\n secure?: boolean,\n priority?: string,\n sameSite?: boolean|string,\n}\n\n/**\n * Serialize data into a cookie header.\n *\n * Serialize the a name value pair into a cookie string suitable for\n * http headers. An optional options object specified cookie parameters.\n *\n * ```js\n * cookieSerialize('foo', 'bar', { httpOnly: true }) // \"foo=bar; httpOnly\"\n * ```\n */\nexport function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {\n const opt = Object.assign({}, options || {});\n const encode = opt.encode || defaultEncode;\n\n if (!fieldContentRegExp.test(name)) {\n throw new TypeError('argument name is invalid');\n }\n\n const value = encode(val);\n\n if (value && !fieldContentRegExp.test(value)) {\n throw new TypeError('argument val is invalid');\n }\n\n let result = name + '=' + value;\n\n if (opt.maxAge != null) {\n const maxAge = opt.maxAge - 0;\n\n if (isNaN(maxAge) || !isFinite(maxAge)) {\n throw new TypeError('option maxAge is invalid');\n }\n\n result += '; Max-Age=' + Math.floor(maxAge);\n }\n\n if (opt.domain) {\n if (!fieldContentRegExp.test(opt.domain)) {\n throw new TypeError('option domain is invalid');\n }\n\n result += '; Domain=' + opt.domain;\n }\n\n if (opt.path) {\n if (!fieldContentRegExp.test(opt.path)) {\n throw new TypeError('option path is invalid');\n }\n\n result += '; Path=' + opt.path;\n }\n\n if (opt.expires) {\n if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {\n throw new TypeError('option expires is invalid');\n }\n\n result += '; Expires=' + opt.expires.toUTCString();\n }\n\n if (opt.httpOnly) {\n result += '; HttpOnly';\n }\n\n if (opt.secure) {\n result += '; Secure';\n }\n\n if (opt.priority) {\n const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;\n\n switch (priority) {\n case 'low':\n result += '; Priority=Low';\n break;\n case 'medium':\n result += '; Priority=Medium';\n break;\n case 'high':\n result += '; Priority=High';\n break;\n default:\n throw new TypeError('option priority is invalid');\n }\n }\n\n if (opt.sameSite) {\n const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;\n\n switch (sameSite) {\n case true:\n result += '; SameSite=Strict';\n break;\n case 'lax':\n result += '; SameSite=Lax';\n break;\n case 'strict':\n result += '; SameSite=Strict';\n break;\n case 'none':\n result += '; SameSite=None';\n break;\n default:\n throw new TypeError('option sameSite is invalid');\n }\n }\n\n return result;\n};\n\n/**\n * Default URL-decode string value function.\n * Optimized to skip native call when no `%`.\n */\nfunction defaultDecode(val: string): string {\n return val.indexOf('%') !== -1\n ? decodeURIComponent(val)\n : val;\n}\n\n/**\n * Default URL-encode value function.\n */\nfunction defaultEncode(val: string | number | boolean): string {\n return encodeURIComponent(val);\n}\n\n/**\n * Determines if value is a Date.\n */\nfunction isDate(val: any): boolean {\n return (\n Object.prototype.toString.call(val) === '[object Date]' ||\n val instanceof Date\n );\n}\n","export default abstract class BaseModel {\n id!: string;\n created!: string;\n updated!: string;\n\n constructor(data: { [key: string]: any } = {}) {\n this.load(data || {});\n }\n\n /**\n * Loads `data` into the current model.\n */\n load(data: { [key: string]: any }) {\n this.id = typeof data.id !== 'undefined' ? data.id : '';\n this.created = typeof data.created !== 'undefined' ? data.created : '';\n this.updated = typeof data.updated !== 'undefined' ? data.updated : '';\n }\n\n /**\n * Returns whether the current loaded data represent a stored db record.\n */\n get isNew(): boolean {\n return (\n // id is not set\n !this.id ||\n // zero uuid value\n this.id === '00000000-0000-0000-0000-000000000000'\n );\n }\n\n /**\n * Robust deep clone of a model.\n */\n clone(): BaseModel {\n return new (this.constructor as any)(JSON.parse(JSON.stringify(this)));\n }\n\n /**\n * Exports all model properties as a new plain object.\n */\n export(): { [key: string]: any } {\n return Object.assign({}, this);\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class Record extends BaseModel {\n [key: string]: any,\n\n '@collectionId'!: string;\n '@collectionName'!: string;\n '@expand'!: {[key: string]: any};\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n for (const [key, value] of Object.entries(data)) {\n this[key] = value;\n }\n\n // normalize common fields\n this['@collectionId'] = typeof data['@collectionId'] !== 'undefined' ? data['@collectionId'] : '';\n this['@collectionName'] = typeof data['@collectionName'] !== 'undefined' ? data['@collectionName'] : '';\n this['@expand'] = typeof data['@expand'] !== 'undefined' ? data['@expand'] : {};\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport Record from '@/models/Record';\n\nexport default class User extends BaseModel {\n email!: string;\n verified!: boolean;\n lastResetSentAt!: string;\n lastVerificationSentAt!: string;\n profile!: null|Record;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.email = typeof data.email === 'string' ? data.email : '';\n this.verified = !!data.verified;\n this.lastResetSentAt = typeof data.lastResetSentAt === 'string' ? data.lastResetSentAt : '';\n this.lastVerificationSentAt = typeof data.lastVerificationSentAt === 'string' ? data.lastVerificationSentAt : '';\n this.profile = data.profile ? new Record(data.profile) : null;\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class Admin extends BaseModel {\n avatar!: number;\n email!: string;\n lastResetSentAt!: string;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.avatar = typeof data.avatar === 'number' ? data.avatar : 0;\n this.email = typeof data.email === 'string' ? data.email : '';\n this.lastResetSentAt = typeof data.lastResetSentAt === 'string' ? data.lastResetSentAt : '';\n }\n}\n","import { cookieParse, cookieSerialize, SerializeOptions } from '@/stores/utils/cookie';\nimport { isTokenExpired, getTokenPayload } from '@/stores/utils/jwt';\nimport User from '@/models/User';\nimport Admin from '@/models/Admin';\n\ntype onChangeFunc = (token: string, model: User|Admin|null) => void;\n\nconst defaultCookieKey = 'pb_auth';\n\n/**\n * Base AuthStore class that is intented to be extended by all other\n * PocketBase AuthStore implementations.\n */\nexport default abstract class BaseAuthStore {\n protected baseToken: string = '';\n protected baseModel: User|Admin|null = null;\n\n private _onChangeCallbacks: Array = [];\n\n /**\n * Retrieves the stored token (if any).\n */\n get token(): string {\n return this.baseToken;\n }\n\n /**\n * Retrieves the stored model data (if any).\n */\n get model(): User|Admin|null {\n return this.baseModel;\n }\n\n /**\n * Checks if the store has valid (aka. existing and unexpired) token.\n */\n get isValid(): boolean {\n return !isTokenExpired(this.token);\n }\n\n /**\n * Saves the provided new token and model data in the auth store.\n */\n save(token: string, model: User|Admin|null): void {\n this.baseToken = token || '';\n\n // normalize the model instance\n if (model !== null && typeof model === 'object') {\n this.baseModel = (model as any)?.verified !== 'undefined' ?\n new User(model) : new Admin(model);\n } else {\n this.baseModel = null;\n }\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 loadFromCookie(cookie: string, key = defaultCookieKey): void {\n const rawData = cookieParse(cookie || '')[key] || '';\n\n let data: { [key: string]: any } = {};\n try {\n data = JSON.parse(rawData);\n // normalize\n if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {\n data = {};\n }\n } catch (_) {}\n\n this.save(data.token || '', data.model || {});\n }\n\n /**\n * Exports the current store state as cookie string.\n *\n * By default the following optional attributes are added:\n * - Secure\n * - HttpOnly\n * - SameSite=Strict\n * - Path=/\n * - Expires={the token expiration date}\n *\n * NB! If the generated cookie exceeds 4096 bytes, this method will\n * strip the model data to the bare minimum to try to fit within the\n * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.\n */\n exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {\n const defaultOptions: SerializeOptions = {\n secure: true,\n sameSite: true,\n httpOnly: true,\n path: \"/\",\n };\n\n // extract the token expiration date\n const payload = getTokenPayload(this.token);\n if (payload?.exp) {\n defaultOptions.expires = new Date(payload.exp * 1000);\n } else {\n defaultOptions.expires = new Date('1970-01-01');\n }\n\n // merge with the user defined options\n options = Object.assign({}, defaultOptions, options);\n\n const rawData = {\n token: this.token,\n model: this.model?.export() || null,\n };\n\n let result = cookieSerialize(key, JSON.stringify(rawData), options);\n\n // strip down the model data to the bare minimum\n if (rawData.model && new Blob([result]).size > 4096) {\n rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};\n if (this.model instanceof User) {\n rawData.model.verified = this.model.verified;\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 * Returns a removal function that you could call to \"unsubscribe\" from the changes.\n */\n onChange(callback: () => void): () => void {\n this._onChangeCallbacks.push(callback);\n\n return () => {\n for (let i = this._onChangeCallbacks.length - 1; i >= 0; i--) {\n if (this._onChangeCallbacks[i] == callback) {\n delete this._onChangeCallbacks[i]; // removes the function reference\n this._onChangeCallbacks.splice(i, 1); // reindex the array\n return;\n }\n }\n }\n }\n\n protected triggerChange(): void {\n for (const callback of this._onChangeCallbacks) {\n callback && callback(this.token, this.model);\n }\n }\n}\n","import BaseAuthStore from '@/stores/BaseAuthStore';\nimport User from '@/models/User';\nimport Admin from '@/models/Admin';\n\n/**\n * The default token store for browsers with auto fallback\n * to runtime/memory if local storage is undefined (eg. in node env).\n */\nexport default 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\n /**\n * @inheritdoc\n */\n get token(): string {\n const data = this._storageGet(this.storageKey) || {};\n\n return data.token || '';\n }\n\n /**\n * @inheritdoc\n */\n get model(): User|Admin|null {\n const data = this._storageGet(this.storageKey) || {};\n\n if (\n data === null ||\n typeof data !== 'object' ||\n data.model === null ||\n typeof data.model !== 'object'\n ) {\n return null;\n }\n\n // admins don't have `verified` prop\n if (typeof data.model?.verified !== 'undefined') {\n return new User(data.model);\n }\n\n return new Admin(data.model);\n }\n\n /**\n * @inheritdoc\n */\n save(token: string, model: User|Admin|null) {\n this._storageSet(this.storageKey, {\n 'token': token,\n 'model': model,\n });\n\n super.save(token, model);\n }\n\n /**\n * @inheritdoc\n */\n clear() {\n this._storageRemove(this.storageKey);\n\n super.clear();\n }\n\n // ---------------------------------------------------------------\n // Internal helpers:\n // ---------------------------------------------------------------\n\n /**\n * Retrieves `key` from the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageGet(key: string): any {\n if (typeof window !== 'undefined' && window?.localStorage) {\n const rawValue = window?.localStorage?.getItem(key) || '';\n try {\n return JSON.parse(rawValue);\n } catch (e) { // not a json\n return rawValue;\n }\n }\n\n // fallback\n return this.storageFallback[key];\n }\n\n /**\n * Stores a new data in the browser's local storage\n * (or runtime/memory if local storage is undefined).\n */\n private _storageSet(key: string, value: any) {\n if (typeof window !== 'undefined' && window?.localStorage) {\n // store in local storage\n let normalizedVal = value;\n if (typeof value !== 'string') {\n normalizedVal = JSON.stringify(value);\n }\n window?.localStorage?.setItem(key, normalizedVal);\n } else {\n // store in fallback\n this.storageFallback[key] = value;\n }\n }\n\n /**\n * Removes `key` from the browser's local storage and the runtime/memory.\n */\n private _storageRemove(key: string) {\n // delete from local storage\n if (typeof window !== 'undefined') {\n window?.localStorage?.removeItem(key);\n }\n\n // delete from fallback\n delete this.storageFallback[key];\n }\n}\n","import Client from '@/Client';\n\n/**\n * BaseService class that should be inherited from all API services.\n */\nexport default abstract class BaseService {\n readonly client: Client\n\n constructor(client: Client) {\n this.client = client;\n }\n}\n","import BaseService from '@/services/utils/BaseService';\n\nexport default class Settings extends BaseService {\n /**\n * Fetch all available app settings.\n */\n getAll(queryParams = {}): Promise<{ [key: string]: any }> {\n return this.client.send('/api/settings', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData) => responseData || {});\n }\n\n /**\n * Bulk updates app settings.\n */\n update(bodyParams = {}, queryParams = {}): Promise<{ [key: string]: any }> {\n return this.client.send('/api/settings', {\n 'method': 'PATCH',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData) => responseData || {});\n }\n\n /**\n * Performs a S3 storage connection test.\n */\n testS3(queryParams = {}): Promise {\n return this.client.send('/api/settings/test/s3', {\n 'method': 'POST',\n 'params': queryParams,\n }).then(() => true);\n }\n\n /**\n * Sends a test email.\n *\n * The possible `emailTemplate` values are:\n * - verification\n * - password-reset\n * - email-change\n */\n testEmail(toEmail: string, emailTemplate: string, queryParams = {}): Promise {\n const bodyParams = {\n 'email': toEmail,\n 'template': emailTemplate,\n };\n\n return this.client.send('/api/settings/test/email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n}\n","import BaseModel from './BaseModel';\n\nexport default class ListResult {\n page!: number;\n perPage!: number;\n totalItems!: number;\n totalPages!: number;\n items!: Array;\n\n constructor(\n page: number,\n perPage: number,\n totalItems: number,\n totalPages: number,\n items: Array,\n ) {\n this.page = page > 0 ? page : 1;\n this.perPage = perPage >= 0 ? perPage : 0;\n this.totalItems = totalItems >= 0 ? totalItems : 0;\n this.totalPages = totalPages >= 0 ? totalPages : 0;\n this.items = items || [];\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseService from '@/services/utils/BaseService';\n\nexport default abstract class BaseCrudService extends BaseService {\n /**\n * Response data decoder.\n */\n abstract decode(data: { [key: string]: any }): M\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n protected _getFullList(basePath: string, batchSize = 100, queryParams = {}): Promise> {\n var result: Array = [];\n\n let request = async (page: number): Promise> => {\n return this._getList(basePath, page, batchSize, queryParams).then((list) => {\n const castedList = (list as ListResult);\n const items = castedList.items;\n const totalItems = castedList.totalItems;\n\n result = result.concat(items);\n\n if (items.length && totalItems > result.length) {\n return request(page + 1);\n }\n\n return result;\n });\n }\n\n return request(1);\n }\n\n /**\n * Returns paginated items list.\n */\n protected _getList(basePath: string, page = 1, perPage = 30, queryParams = {}): Promise> {\n queryParams = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, queryParams);\n\n return this.client.send(basePath, {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n const items: Array = [];\n if (responseData?.items) {\n responseData.items = responseData.items || [];\n for (const item of responseData.items) {\n items.push(this.decode(item));\n }\n }\n\n return new ListResult(\n responseData?.page || 1,\n responseData?.perPage || 0,\n responseData?.totalItems || 0,\n responseData?.totalPages || 0,\n items,\n );\n });\n }\n\n /**\n * Returns single item by its id.\n */\n protected _getOne(basePath: string, id: string, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Creates a new item.\n */\n protected _create(basePath: string, bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(basePath, {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Updates an existing item by its id.\n */\n protected _update(basePath: string, id: string, bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'PATCH',\n 'params': queryParams,\n 'body': bodyParams,\n }).then((responseData: any) => this.decode(responseData));\n }\n\n /**\n * Deletes an existing item by its id.\n */\n protected _delete(basePath: string, id: string, queryParams = {}): Promise {\n return this.client.send(basePath + '/' + encodeURIComponent(id), {\n 'method': 'DELETE',\n 'params': queryParams,\n }).then(() => true);\n }\n}\n","import ListResult from '@/models/utils/ListResult';\nimport BaseModel from '@/models/utils/BaseModel';\nimport BaseCrudService from '@/services/utils/BaseCrudService';\n\nexport default abstract class CrudService extends BaseCrudService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/admins').\n */\n abstract baseCrudPath(): string\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n getFullList(batchSize = 100, queryParams = {}): Promise> {\n return this._getFullList(this.baseCrudPath(), batchSize, queryParams);\n }\n\n /**\n * Returns paginated items list.\n */\n getList(page = 1, perPage = 30, queryParams = {}): Promise> {\n return this._getList(this.baseCrudPath(), page, perPage, queryParams);\n }\n\n /**\n * Returns single item by its id.\n */\n getOne(id: string, queryParams = {}): Promise {\n return this._getOne(this.baseCrudPath(), id, queryParams);\n }\n\n /**\n * Creates a new item.\n */\n create(bodyParams = {}, queryParams = {}): Promise {\n return this._create(this.baseCrudPath(), bodyParams, queryParams);\n }\n\n /**\n * Updates an existing item by its id.\n */\n update(id: string, bodyParams = {}, queryParams = {}): Promise {\n return this._update(this.baseCrudPath(), id, bodyParams, queryParams);\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(id: string, queryParams = {}): Promise {\n return this._delete(this.baseCrudPath(), id, queryParams);\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport Admin from '@/models/Admin';\n\nexport type AdminAuthResponse = {\n [key: string]: any,\n token: string,\n admin: Admin,\n}\n\nexport default class Admins extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Admin {\n return new Admin(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/admins';\n }\n\n /**\n * Prepare successful authorize response.\n */\n protected authResponse(responseData: any): AdminAuthResponse {\n const admin = this.decode(responseData?.admin || {});\n\n if (responseData?.token && responseData?.admin) {\n this.client.authStore.save(responseData.token, admin);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'admin': admin,\n });\n }\n\n /**\n * Authenticate an admin account by its email and password\n * and returns a new admin token and data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n authViaEmail(\n email: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current admin authenticated instance and\n * returns a new token and admin data.\n *\n * On success this method automatically updates the client's AuthStore data.\n */\n refresh(bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/refresh', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends admin password reset request.\n */\n requestPasswordReset(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms admin password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport User from '@/models/User';\n\nexport type UserAuthResponse = {\n [key: string]: any,\n token: string,\n user: User,\n}\n\nexport type AuthProviderInfo = {\n name: string,\n state: string,\n codeVerifier: string,\n codeChallenge: string,\n codeChallengeMethod: string,\n authUrl: string,\n}\n\nexport type AuthMethodsList = {\n [key: string]: any,\n emailPassword: boolean,\n authProviders: Array,\n}\n\nexport default class Users extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): User {\n return new User(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/users';\n }\n\n /**\n * Prepare successful authorization response.\n */\n protected authResponse(responseData: any): UserAuthResponse {\n const user = this.decode(responseData?.user || {});\n\n if (responseData?.token && responseData?.user) {\n this.client.authStore.save(responseData.token, user);\n }\n\n return Object.assign({}, responseData, {\n // normalize common fields\n 'token': responseData?.token || '',\n 'user': user,\n });\n }\n\n /**\n * Returns all available application auth methods.\n */\n listAuthMethods(queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/auth-methods', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n return Object.assign({}, responseData, {\n // normalize common fields\n 'emailPassword': !!responseData?.emailPassword,\n 'authProviders': Array.isArray(responseData?.authProviders) ? responseData?.authProviders : [],\n });\n });\n }\n\n /**\n * Authenticate a user via its email and password.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - new user authentication token\n * - the authenticated user model record\n */\n authViaEmail(\n email: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-email', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Authenticate a user via OAuth2 client provider.\n *\n * On success, this method also automatically updates\n * the client's AuthStore data and returns:\n * - new user authentication token\n * - the authenticated user model record\n * - the OAuth2 user profile data (eg. name, email, avatar, etc.)\n */\n authViaOAuth2(\n provider: string,\n code: string,\n codeVerifier: string,\n redirectUrl: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'provider': provider,\n 'code': code,\n 'codeVerifier': codeVerifier,\n 'redirectUrl': redirectUrl,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/auth-via-oauth2', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n 'headers': {\n 'Authorization': '',\n },\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Refreshes the current user authenticated instance and\n * returns a new token and user data.\n *\n * On success this method also automatically updates the client's AuthStore data.\n */\n refresh(bodyParams = {}, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/refresh', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends user password reset request.\n */\n requestPasswordReset(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user password reset request.\n */\n confirmPasswordReset(\n passwordResetToken: string,\n password: string,\n passwordConfirm: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': passwordResetToken,\n 'password': password,\n 'passwordConfirm': passwordConfirm,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-password-reset', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends user verification email request.\n */\n requestVerification(\n email: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'email': email,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-verification', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user email verification request.\n */\n confirmVerification(\n verificationToken: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': verificationToken,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-verification', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n\n /**\n * Sends an email change request to the authenticated user.\n */\n requestEmailChange(\n newEmail: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'newEmail': newEmail,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/request-email-change', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(() => true);\n }\n\n /**\n * Confirms user new email address.\n */\n confirmEmailChange(\n emailChangeToken: string,\n password: string,\n bodyParams = {},\n queryParams = {},\n ): Promise {\n bodyParams = Object.assign({\n 'token': emailChangeToken,\n 'password': password,\n }, bodyParams);\n\n return this.client.send(this.baseCrudPath() + '/confirm-email-change', {\n 'method': 'POST',\n 'params': queryParams,\n 'body': bodyParams,\n }).then(this.authResponse.bind(this));\n }\n}\n","export default class SchemaField {\n id!: string;\n name!: string;\n type!: string;\n system!: boolean;\n required!: boolean;\n unique!: boolean;\n options!: { [key: string]: any };\n\n constructor(data: { [key: string]: any } = {}) {\n this.load(data || {});\n }\n\n /**\n * Loads `data` into the field.\n */\n load(data: { [key: string]: any }) {\n this.id = typeof data.id !== 'undefined' ? data.id : '';\n this.name = typeof data.name !== 'undefined' ? data.name : '';\n this.type = typeof data.type !== 'undefined' ? data.type : 'text';\n this.system = !!data.system;\n this.required = !!data.required;\n this.unique = !!data.unique;\n this.options = typeof data.options === 'object' && data.options !== null ? data.options : {};\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport SchemaField from '@/models/utils/SchemaField';\n\nexport default class Collection extends BaseModel {\n name!: string;\n schema!: Array;\n system!: boolean;\n listRule!: null|string;\n viewRule!: null|string;\n createRule!: null|string;\n updateRule!: null|string;\n deleteRule!: null|string;\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n this.name = typeof data.name === 'string' ? data.name : '';\n this.system = !!data.system;\n\n // rules\n this.listRule = typeof data.listRule === 'string' ? data.listRule : null;\n this.viewRule = typeof data.viewRule === 'string' ? data.viewRule : null;\n this.createRule = typeof data.createRule === 'string' ? data.createRule : null;\n this.updateRule = typeof data.updateRule === 'string' ? data.updateRule : null;\n this.deleteRule = typeof data.deleteRule === 'string' ? data.deleteRule : null;\n\n // schema\n data.schema = Array.isArray(data.schema) ? data.schema : [];\n this.schema = [];\n for (let field of data.schema) {\n this.schema.push(new SchemaField(field));\n }\n }\n}\n","import CrudService from '@/services/utils/CrudService';\nimport Collection from '@/models/Collection';\n\nexport default class Collections extends CrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Collection {\n return new Collection(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(): string {\n return '/api/collections';\n }\n\n /**\n * Imports the provided collections.\n *\n * If `deleteMissing` is `true`, all local collections and schema fields,\n * that are not present in the imported configuration, WILL BE DELETED\n * (including their related records data)!\n */\n async import(collections: Array, deleteMissing: boolean = false, queryParams = {}): Promise {\n return this.client.send(this.baseCrudPath() + '/import', {\n 'method': 'PUT',\n 'params': queryParams,\n 'body': {\n 'collections': collections,\n 'deleteMissing': deleteMissing,\n }\n }).then(() => true);\n }\n}\n","import SubCrudService from '@/services/utils/SubCrudService';\nimport Record from '@/models/Record';\n\nexport default class Records extends SubCrudService {\n /**\n * @inheritdoc\n */\n decode(data: { [key: string]: any }): Record {\n return new Record(data);\n }\n\n /**\n * @inheritdoc\n */\n baseCrudPath(collectionIdOrName: string): string {\n return '/api/collections/' + encodeURIComponent(collectionIdOrName) + '/records';\n }\n\n /**\n * Builds and returns an absolute record file url.\n */\n getFileUrl(record: Record, filename: string, queryParams = {}): string {\n const parts = [];\n parts.push(this.client.baseUrl.replace(/\\/+$/gm, \"\"))\n parts.push(\"api\")\n parts.push(\"files\")\n parts.push(record[\"@collectionId\"])\n parts.push(record.id)\n parts.push(filename)\n let result = parts.join('/');\n\n if (Object.keys(queryParams).length) {\n const params = new URLSearchParams(queryParams);\n result += (result.includes(\"?\") ? \"&\" : \"?\") + params;\n }\n\n return result\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseCrudService from '@/services/utils/BaseCrudService';\n\nexport default abstract class SubCrudService extends BaseCrudService {\n /**\n * Base path for the crud actions (without trailing slash, eg. '/collections/{:sub}/records').\n */\n abstract baseCrudPath(sub: string): string\n\n /**\n * Returns a promise with all list items batch fetched at once.\n */\n getFullList(sub: string, batchSize = 100, queryParams = {}): Promise> {\n return this._getFullList(this.baseCrudPath(sub), batchSize, queryParams);\n }\n\n /**\n * Returns paginated items list.\n */\n getList(sub: string, page = 1, perPage = 30, queryParams = {}): Promise> {\n return this._getList(this.baseCrudPath(sub), page, perPage, queryParams);\n }\n\n /**\n * Returns single item by its id.\n */\n getOne(sub: string, id: string, queryParams = {}): Promise {\n return this._getOne(this.baseCrudPath(sub), id, queryParams);\n }\n\n /**\n * Creates a new item.\n */\n create(sub: string, bodyParams = {}, queryParams = {}): Promise {\n return this._create(this.baseCrudPath(sub), bodyParams, queryParams);\n }\n\n /**\n * Updates an existing item by its id.\n */\n update(sub: string, id: string, bodyParams = {}, queryParams = {}): Promise {\n return this._update(this.baseCrudPath(sub), id, bodyParams, queryParams);\n }\n\n /**\n * Deletes an existing item by its id.\n */\n delete(sub: string, id: string, queryParams = {}): Promise {\n return this._delete(this.baseCrudPath(sub), id, queryParams);\n }\n}\n","import BaseModel from '@/models/utils/BaseModel';\n\nexport default class LogRequest extends BaseModel {\n url!: string;\n method!: string;\n status!: number;\n auth!: string;\n remoteIp!: string;\n userIp!: string;\n referer!: string;\n userAgent!: string;\n meta!: null|{ [key: string]: any };\n\n /**\n * @inheritdoc\n */\n load(data: { [key: string]: any }) {\n super.load(data);\n\n // fallback to the ip field for backward compatability\n data.remoteIp = data.remoteIp || data.ip;\n\n this.url = typeof data.url === 'string' ? data.url : '';\n this.method = typeof data.method === 'string' ? data.method : 'GET';\n this.status = typeof data.status === 'number' ? data.status : 200;\n this.auth = typeof data.auth === 'string' ? data.auth : 'guest';\n this.remoteIp = typeof data.remoteIp === 'string' ? data.remoteIp : '';\n this.userIp = typeof data.userIp === 'string' ? data.userIp : '';\n this.referer = typeof data.referer === 'string' ? data.referer : '';\n this.userAgent = typeof data.userAgent === 'string' ? data.userAgent : '';\n this.meta = typeof data.meta === 'object' && data.meta !== null ? data.meta : {};\n }\n}\n","import LogRequest from '@/models/LogRequest';\nimport ListResult from '@/models/utils/ListResult';\nimport BaseService from '@/services/utils/BaseService';\n\nexport type HourlyStats = {\n total: number,\n date: string,\n}\n\nexport default class Logs extends BaseService {\n /**\n * Returns paginated logged requests list.\n */\n getRequestsList(page = 1, perPage = 30, queryParams = {}): Promise> {\n queryParams = Object.assign({\n 'page': page,\n 'perPage': perPage,\n }, queryParams);\n\n return this.client.send('/api/logs/requests', {\n 'method': 'GET',\n 'params': queryParams,\n }).then((responseData: any) => {\n const items: Array = [];\n if (responseData?.items) {\n responseData.items = responseData?.items || [];\n for (const item of responseData.items) {\n items.push(new LogRequest(item));\n }\n }\n\n return new ListResult(\n responseData?.page || 1,\n responseData?.perPage || 0,\n responseData?.totalItems || 0,\n responseData?.totalPages || 0,\n items,\n );\n });\n }\n\n /**\n * Returns a single logged request by its id.\n */\n getRequest(id: string, queryParams = {}): Promise {\n return this.client.send('/api/logs/requests/' + encodeURIComponent(id), {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => new LogRequest(responseData));\n }\n\n /**\n * Returns request logs statistics.\n */\n getRequestsStats(queryParams = {}): Promise> {\n return this.client.send('/api/logs/requests/stats', {\n 'method': 'GET',\n 'params': queryParams\n }).then((responseData: any) => responseData);\n }\n}\n","import BaseService from '@/services/utils/BaseService';\nimport Record from '@/models/Record';\n\nexport interface MessageData {\n [key: string]: any;\n action: string;\n record: Record;\n}\n\nexport interface SubscriptionFunc{\n (data: MessageData):void;\n}\n\nexport default class Realtime extends BaseService {\n private clientId: string = \"\";\n private eventSource: EventSource | null = null;\n private subscriptions: { [key: string]: EventListener } = {};\n\n /**\n * Inits the sse connection (if not already) and register the subscription.\n */\n async subscribe(subscription: string, callback: SubscriptionFunc): Promise {\n if (!subscription) {\n throw new Error('subscription must be set.')\n }\n\n // unsubscribe existing\n if (this.subscriptions[subscription]) {\n this.eventSource?.removeEventListener(subscription, this.subscriptions[subscription]);\n }\n\n // register subscription\n this.subscriptions[subscription] = 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 if (!this.eventSource) {\n // start a new sse connection\n this.connect();\n } else if (this.clientId) {\n // otherwise - just persist the updated subscriptions\n await this.submitSubscriptions();\n }\n }\n\n /**\n * Unsubscribe from a subscription.\n *\n * If the `subscription` argument is not set,\n * then the client will unsubscribe from all registered subscriptions.\n *\n * The related sse connection will be autoclosed if after the\n * unsubscribe operations there are no active subscriptions left.\n */\n async unsubscribe(subscription?: string): Promise {\n if (!subscription) {\n // remove all subscriptions\n this.removeSubscriptionListeners();\n this.subscriptions = {};\n } else if (this.subscriptions[subscription]) {\n // remove a single subscription\n this.eventSource?.removeEventListener(subscription, this.subscriptions[subscription]);\n delete this.subscriptions[subscription];\n } else {\n // not subscribed to the specified subscription\n return\n }\n\n if (this.clientId) {\n await this.submitSubscriptions();\n }\n\n // no more subscriptions -> close the sse connection\n if (!Object.keys(this.subscriptions).length) {\n this.disconnect();\n }\n }\n\n private async submitSubscriptions(): Promise {\n // optimistic update\n this.addSubscriptionListeners();\n\n return this.client.send('/api/realtime', {\n 'method': 'POST',\n 'body': {\n 'clientId': this.clientId,\n 'subscriptions': Object.keys(this.subscriptions),\n },\n }).then(() => true);\n }\n\n private addSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n this.removeSubscriptionListeners();\n\n for (let sub in this.subscriptions) {\n this.eventSource.addEventListener(sub, this.subscriptions[sub]);\n }\n }\n\n private removeSubscriptionListeners(): void {\n if (!this.eventSource) {\n return;\n }\n\n for (let sub in this.subscriptions) {\n this.eventSource.removeEventListener(sub, this.subscriptions[sub]);\n }\n }\n\n private connectHandler(e: Event): void {\n const msgEvent = (e as MessageEvent);\n this.clientId = msgEvent?.lastEventId;\n this.submitSubscriptions();\n }\n\n private connect(): void {\n this.disconnect();\n this.eventSource = new EventSource(this.client.buildUrl('/api/realtime'))\n this.eventSource.addEventListener('PB_CONNECT', (e) => this.connectHandler(e));\n }\n\n private disconnect(): void {\n this.removeSubscriptionListeners();\n this.eventSource?.removeEventListener('PB_CONNECT', (e) => this.connectHandler(e));\n this.eventSource?.close();\n this.eventSource = null;\n this.clientId = \"\";\n }\n}\n","import ClientResponseError from '@/ClientResponseError';\nimport BaseAuthStore from '@/stores/BaseAuthStore';\nimport { AuthStore } from '@/stores/utils/AuthStore';\nimport LocalAuthStore from '@/stores/LocalAuthStore';\nimport Settings from '@/services/Settings';\nimport Admins from '@/services/Admins';\nimport Users from '@/services/Users';\nimport Collections from '@/services/Collections';\nimport Records from '@/services/Records';\nimport Logs from '@/services/Logs';\nimport Realtime from '@/services/Realtime';\n\n/**\n * PocketBase JS Client.\n */\nexport default class Client {\n /**\n * The base PocketBase backend url address (eg. 'http://127.0.0.1.8090').\n */\n baseUrl: string;\n\n /**\n * Hook that get triggered right before sending the fetch request,\n * allowing you to inspect/modify the request config.\n *\n * Returns the new modified config that will be used to send the request.\n *\n * For list of the possible options check https://developer.mozilla.org/en-US/docs/Web/API/fetch#options\n *\n * Example:\n * ```js\n * client.beforeSend = function (url, reqConfig) {\n * reqConfig.headers = Object.assign({}, reqConfig.headers, {\n * 'X-Custom-Header': 'example',\n * });\n *\n * return reqConfig;\n * };\n * ```\n */\n beforeSend?: (url: string, reqConfig: { [key: string]: any }) => { [key: string]: any };\n\n /**\n * Hook that get triggered after successfully sending the fetch request,\n * allowing you to inspect/modify the response object and its parsed data.\n *\n * Returns the new Promise resolved `data` that will be returned to the client.\n *\n * Example:\n * ```js\n * client.afterSend = function (response, data) {\n * if (response.status != 200) {\n * throw new ClientResponseError({\n * url: response.url,\n * status: response.status,\n * data: data,\n * });\n * }\n *\n * return data;\n * };\n * ```\n */\n afterSend?: (response: Response, data: any) => any;\n\n /**\n * Optional language code (default to `en-US`) that will be sent\n * with the requests to the server as `Accept-Language` header.\n */\n lang: string;\n\n /**\n * A replacable instance of the local `AuthStore` service.\n */\n authStore: AuthStore | BaseAuthStore;\n\n /**\n * An instance of the service that handles the **Settings APIs**.\n */\n readonly settings: Settings;\n\n /**\n * An instance of the service that handles the **Admin APIs**.\n */\n readonly admins: Admins;\n\n /**\n * An instance of the service that handles the **User APIs**.\n */\n readonly users: Users;\n\n /**\n * An instance of the service that handles the **Collection APIs**.\n */\n readonly collections: Collections;\n\n /**\n * An instance of the service that handles the **Record APIs**.\n */\n readonly records: Records;\n\n /**\n * An instance of the service that handles the **Log APIs**.\n */\n readonly logs: Logs;\n\n /**\n * An instance of the service that handles the **Realtime APIs**.\n */\n readonly realtime: Realtime;\n\n private cancelControllers: { [key: string]: AbortController } = {}\n\n constructor(\n baseUrl = '/',\n lang = 'en-US',\n authStore?: AuthStore | BaseAuthStore | null,\n ) {\n this.baseUrl = baseUrl;\n this.lang = lang;\n this.authStore = authStore || new LocalAuthStore();\n\n // services\n this.admins = new Admins(this);\n this.users = new Users(this);\n this.records = new Records(this);\n this.collections = new Collections(this);\n this.logs = new Logs(this);\n this.settings = new Settings(this);\n this.realtime = new Realtime(this);\n }\n\n /**\n * @deprecated Legacy alias for `this.authStore`.\n */\n get AuthStore(): AuthStore {\n return this.authStore;\n };\n\n /**\n * @deprecated Legacy alias for `this.settings`.\n */\n get Settings(): Settings {\n return this.settings;\n };\n\n /**\n * @deprecated Legacy alias for `this.admins`.\n */\n get Admins(): Admins {\n return this.admins;\n };\n\n /**\n * @deprecated Legacy alias for `this.users`.\n */\n get Users(): Users {\n return this.users;\n };\n\n /**\n * @deprecated Legacy alias for `this.collections`.\n */\n get Collections(): Collections {\n return this.collections;\n };\n\n /**\n * @deprecated Legacy alias for `this.records`.\n */\n get Records(): Records {\n return this.records;\n };\n\n /**\n * @deprecated Legacy alias for `this.logs`.\n */\n get Logs(): Logs {\n return this.logs;\n };\n\n /**\n * @deprecated Legacy alias for `this.realtime`.\n */\n get Realtime(): Realtime {\n return this.realtime;\n };\n\n /**\n * Cancels single request by its cancellation key.\n */\n cancelRequest(cancelKey: string): Client {\n if (this.cancelControllers[cancelKey]) {\n this.cancelControllers[cancelKey].abort();\n delete this.cancelControllers[cancelKey];\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 * Sends an api http request.\n */\n async send(path: string, reqConfig: { [key: string]: any }): Promise {\n let config = Object.assign({ method: 'GET' } as { [key: string]: any }, reqConfig);\n\n // serialize the body if needed and set the correct content type\n // note1: for FormData body the Content-Type header should be skipped\n // note2: we are checking the constructor name because FormData is not available natively in node\n if (config.body && config.body.constructor.name !== 'FormData') {\n if (typeof config.body !== 'string') {\n config.body = JSON.stringify(config.body);\n }\n\n // add the json header (if not already)\n if (typeof config?.headers?.['Content-Type'] === 'undefined') {\n config.headers = Object.assign({}, config.headers, {\n 'Content-Type': 'application/json',\n });\n }\n }\n\n // add Accept-Language header (if not already)\n if (typeof config?.headers?.['Accept-Language'] === 'undefined') {\n config.headers = Object.assign({}, config.headers, {\n 'Accept-Language': this.lang,\n });\n }\n\n // check if Authorization header can be added\n if (\n // has stored token\n this.authStore?.token &&\n // auth header is not explicitly set\n (typeof config?.headers?.Authorization === 'undefined')\n ) {\n let authType = 'Admin';\n if (typeof (this.authStore.model as any)?.verified !== 'undefined') {\n authType = 'User'; // admins don't have verified\n }\n\n config.headers = Object.assign({}, config.headers, {\n 'Authorization': (authType + ' ' + this.authStore.token),\n });\n }\n\n // handle auto cancelation for duplicated pending request\n if (config.params?.$autoCancel !== false) {\n const cancelKey = config.params?.$cancelKey || ((config.method || 'GET') + path);\n\n // cancel previous pending requests\n this.cancelRequest(cancelKey);\n\n const controller = new AbortController();\n this.cancelControllers[cancelKey] = controller;\n config.signal = controller.signal;\n }\n // remove the special cancellation params from the other valid query params\n delete config.params?.$autoCancel;\n delete config.params?.$cancelKey;\n\n // build url + path\n let url = this.buildUrl(path);\n\n // serialize the query parameters\n if (typeof config.params !== 'undefined') {\n const query = this.serializeQueryParams(config.params)\n if (query) {\n url += (url.includes('?') ? '&' : '?') + query;\n }\n delete config.params;\n }\n\n if (this.beforeSend) {\n config = Object.assign({}, this.beforeSend(url, config));\n }\n\n // send the request\n return fetch(url, config)\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 = this.afterSend(response, data);\n }\n\n if (response.status >= 400) {\n throw new ClientResponseError({\n url: response.url,\n status: response.status,\n data: data,\n });\n }\n\n return data;\n }).catch((err) => {\n // wrap to normalize all errors\n throw new ClientResponseError(err);\n });\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 + (this.baseUrl.endsWith('/') ? '' : '/');\n if (path) {\n url += (path.startsWith('/') ? path.substring(1) : path);\n }\n return url;\n }\n\n /**\n * Serializes the provided query parameters into a query string.\n */\n private serializeQueryParams(params: {[key: string]: any}): string {\n const result: Array = [];\n for (const key in params) {\n if (params[key] === null) {\n // skip null query params\n continue;\n }\n\n const value = params[key];\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n // \"repeat\" array params\n for (const v of value) {\n result.push(encodedKey + \"=\" + encodeURIComponent(v));\n }\n } else if (value instanceof Date) {\n result.push(encodedKey + \"=\" + encodeURIComponent(value.toISOString()));\n } else if (typeof value !== null && typeof value === 'object') {\n result.push(encodedKey + \"=\" + encodeURIComponent(JSON.stringify(value)));\n } else {\n result.push(encodedKey + \"=\" + encodeURIComponent(value));\n }\n }\n\n return result.join('&');\n }\n}\n"],"names":["atobPolyfill","ClientResponseError","_super","errData","_this","this","call","url","status","data","isAbort","originalError","Object","setPrototypeOf","prototype","DOMException","name","message","_a","__extends","toJSON","__assign","Error","fieldContentRegExp","cookieSerialize","val","options","opt","assign","encode","defaultEncode","test","TypeError","value","result","maxAge","isNaN","isFinite","Math","floor","domain","path","expires","toString","Date","isDate","valueOf","toUTCString","httpOnly","secure","priority","toLowerCase","sameSite","defaultDecode","indexOf","decodeURIComponent","encodeURIComponent","getTokenPayload","token","base64","split","map","c","charCodeAt","slice","join","JSON","parse","e","atob","a","Buffer","from","BaseModel","load","id","created","updated","defineProperty","get","clone","constructor","stringify","export","Record","_i","entries","length","_b","key","User","email","verified","lastResetSentAt","lastVerificationSentAt","profile","Admin","avatar","BaseAuthStore","baseToken","baseModel","_onChangeCallbacks","expirationThreshold","payload","keys","exp","now","isTokenExpired","save","model","triggerChange","clear","loadFromCookie","cookie","rawData","str","decode","index","eqIdx","endIdx","lastIndexOf","trim","undefined","_","cookieParse","Array","isArray","exportToCookie","defaultOptions","Blob","size","_c","onChange","callback","push","i","splice","LocalAuthStore","storageKey","storageFallback","_storageGet","_storageSet","_storageRemove","window","localStorage","rawValue","getItem","normalizedVal","setItem","removeItem","BaseService","client","Settings","getAll","queryParams","send","method","params","then","responseData","update","bodyParams","body","testS3","testEmail","toEmail","emailTemplate","template","ListResult","page","perPage","totalItems","totalPages","items","BaseCrudService","_getFullList","basePath","batchSize","request","__awaiter","_getList","list","castedList","concat","item","_getOne","_create","_update","_delete","CrudService","getFullList","baseCrudPath","getList","getOne","create","delete","Admins","authResponse","admin","authStore","authViaEmail","password","headers","Authorization","bind","refresh","requestPasswordReset","confirmPasswordReset","passwordResetToken","passwordConfirm","Users","user","listAuthMethods","emailPassword","authProviders","authViaOAuth2","provider","code","codeVerifier","redirectUrl","requestVerification","confirmVerification","verificationToken","requestEmailChange","newEmail","confirmEmailChange","emailChangeToken","SchemaField","type","system","required","unique","Collection","listRule","viewRule","createRule","updateRule","deleteRule","schema","field","Collections","import","collections","deleteMissing","Records","collectionIdOrName","getFileUrl","record","filename","parts","baseUrl","replace","URLSearchParams","includes","SubCrudService","sub","LogRequest","remoteIp","ip","auth","userIp","referer","userAgent","meta","Logs","getRequestsList","getRequest","getRequestsStats","Realtime","apply","arguments","clientId","eventSource","subscriptions","subscribe","subscription","removeEventListener","msgEvent","connect","submitSubscriptions","sent","unsubscribe","removeSubscriptionListeners","disconnect","addSubscriptionListeners","addEventListener","connectHandler","lastEventId","EventSource","buildUrl","close","Client","lang","cancelControllers","admins","users","records","logs","settings","realtime","cancelRequest","cancelKey","abort","cancelAllRequests","k","reqConfig","config","_d","authType","_e","_f","$autoCancel","_g","$cancelKey","controller","AbortController","signal","_h","_j","query","serializeQueryParams","beforeSend","fetch","response","json","afterSend","catch","err","endsWith","startsWith","substring","encodedKey","value_1","v","toISOString"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/pocketbase.iife.d.ts b/dist/pocketbase.iife.d.ts
index 46eff9a..f014b4e 100644
--- a/dist/pocketbase.iife.d.ts
+++ b/dist/pocketbase.iife.d.ts
@@ -1,3 +1,14 @@
+interface SerializeOptions {
+ encode?: (val: string | number | boolean) => string;
+ maxAge?: number;
+ domain?: string;
+ path?: string;
+ expires?: Date;
+ httpOnly?: boolean;
+ secure?: boolean;
+ priority?: string;
+ sameSite?: boolean | string;
+}
declare abstract class BaseModel {
id: string;
created: string;
@@ -64,9 +75,66 @@ declare class Admin extends BaseModel {
[key: string]: any;
}): void;
}
+/**
+ * Base AuthStore class that is intented to be extended by all other
+ * PocketBase AuthStore implementations.
+ */
+declare abstract class BaseAuthStore {
+ protected baseToken: string;
+ protected baseModel: User | Admin | null;
+ private _onChangeCallbacks;
+ /**
+ * Retrieves the stored token (if any).
+ */
+ get token(): string;
+ /**
+ * Retrieves the stored model data (if any).
+ */
+ get model(): User | Admin | null;
+ /**
+ * Checks if the store has valid (aka. existing and unexpired) token.
+ */
+ get isValid(): boolean;
+ /**
+ * Saves the provided new token and model data in the auth store.
+ */
+ save(token: string, model: User | Admin | null): void;
+ /**
+ * Removes the stored token and model data form the auth store.
+ */
+ clear(): void;
+ /**
+ * Parses the provided cookie string and updates the store state
+ * with the cookie's token and model data.
+ */
+ loadFromCookie(cookie: string, key?: string): void;
+ /**
+ * Exports the current store state as cookie string.
+ *
+ * By default the following optional attributes are added:
+ * - Secure
+ * - HttpOnly
+ * - SameSite=Strict
+ * - Path=/
+ * - Expires={the token expiration date}
+ *
+ * NB! If the generated cookie exceeds 4096 bytes, this method will
+ * strip the model data to the bare minimum to try to fit within the
+ * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.
+ */
+ exportToCookie(options?: SerializeOptions, key?: string): string;
+ /**
+ * Register a callback function that will be called on store change.
+ *
+ * Returns a removal function that you could call to "unsubscribe" from the changes.
+ */
+ onChange(callback: () => void): () => void;
+ protected triggerChange(): void;
+}
/**
* The minimal AuthStore interface.
*
+ * @deprecated
* This interface predates the abstract BaseAuthStore class
* and it is kept mainly for backward compatibility.
*
@@ -81,7 +149,7 @@ type AuthStore = {
/**
* Retrieves the stored model data (if any).
*/
- readonly model: User | Admin | {};
+ readonly model: User | Admin | null;
/**
* Checks if the store has valid (aka. existing and unexpired) token.
*/
@@ -89,7 +157,7 @@ type AuthStore = {
/**
* Saves new token and model data in the auth store.
*/
- save(token: string, model: User | Admin | {}): void;
+ save(token: string, model: User | Admin | null): void;
/**
* Removes the stored token and model data form the auth store.
*/
@@ -564,7 +632,7 @@ declare class Client {
/**
* A replacable instance of the local `AuthStore` service.
*/
- authStore: AuthStore;
+ authStore: AuthStore | BaseAuthStore;
/**
* An instance of the service that handles the **Settings APIs**.
*/
@@ -594,7 +662,7 @@ declare class Client {
*/
readonly realtime: Realtime;
private cancelControllers;
- constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | null);
+ constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | BaseAuthStore | null);
/**
* @deprecated Legacy alias for `this.authStore`.
*/
diff --git a/dist/pocketbase.iife.js b/dist/pocketbase.iife.js
index 1c62247..dc62aae 100644
--- a/dist/pocketbase.iife.js
+++ b/dist/pocketbase.iife.js
@@ -1 +1 @@
-var PocketBase=function(){"use strict";var t=function(e,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},t(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return n=Object.assign||function(t){for(var e,n=1,i=arguments.length;n0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!i.exp||i.exp-n>Date.now()/1e3))},t}(),a=function(){function t(){this.baseToken="",this.baseModel={},this._onChangeCallbacks=[]}return Object.defineProperty(t.prototype,"token",{get:function(){return this.baseToken},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"model",{get:function(){return this.baseModel},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"isValid",{get:function(){return!u.isExpired(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t,this.baseModel=e,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel={},this.triggerChange()},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},b=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],u=function(a){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,a,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?u(a+1):s}))]}))}))};return u(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!n.exp||n.exp-e>Date.now()/1e3))}(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t||"",this.baseModel=null!==e&&"object"==typeof e?"undefined"!==(null==e?void 0:e.verified)?new f(e):new v(e):null,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel=null,this.triggerChange()},t.prototype.loadFromCookie=function(t,e){void 0===e&&(e=y);var n=function(t,e){var n={};if("string"!=typeof t)return n;for(var i=Object.assign({},e||{}).decode||l,o=0;o4096&&(a.model={id:null===(i=null==a?void 0:a.model)||void 0===i?void 0:i.id,email:null===(o=null==a?void 0:a.model)||void 0===o?void 0:o.email},this.model instanceof f&&(a.model.verified=this.model.verified),l=u(e,JSON.stringify(a),t)),l},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},S=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],a=function(u){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,u,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?a(u+1):s}))]}))}))};return a(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r string;
+ maxAge?: number;
+ domain?: string;
+ path?: string;
+ expires?: Date;
+ httpOnly?: boolean;
+ secure?: boolean;
+ priority?: string;
+ sameSite?: boolean | string;
+}
declare abstract class BaseModel {
id: string;
created: string;
@@ -64,9 +75,66 @@ declare class Admin extends BaseModel {
[key: string]: any;
}): void;
}
+/**
+ * Base AuthStore class that is intented to be extended by all other
+ * PocketBase AuthStore implementations.
+ */
+declare abstract class BaseAuthStore {
+ protected baseToken: string;
+ protected baseModel: User | Admin | null;
+ private _onChangeCallbacks;
+ /**
+ * Retrieves the stored token (if any).
+ */
+ get token(): string;
+ /**
+ * Retrieves the stored model data (if any).
+ */
+ get model(): User | Admin | null;
+ /**
+ * Checks if the store has valid (aka. existing and unexpired) token.
+ */
+ get isValid(): boolean;
+ /**
+ * Saves the provided new token and model data in the auth store.
+ */
+ save(token: string, model: User | Admin | null): void;
+ /**
+ * Removes the stored token and model data form the auth store.
+ */
+ clear(): void;
+ /**
+ * Parses the provided cookie string and updates the store state
+ * with the cookie's token and model data.
+ */
+ loadFromCookie(cookie: string, key?: string): void;
+ /**
+ * Exports the current store state as cookie string.
+ *
+ * By default the following optional attributes are added:
+ * - Secure
+ * - HttpOnly
+ * - SameSite=Strict
+ * - Path=/
+ * - Expires={the token expiration date}
+ *
+ * NB! If the generated cookie exceeds 4096 bytes, this method will
+ * strip the model data to the bare minimum to try to fit within the
+ * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.
+ */
+ exportToCookie(options?: SerializeOptions, key?: string): string;
+ /**
+ * Register a callback function that will be called on store change.
+ *
+ * Returns a removal function that you could call to "unsubscribe" from the changes.
+ */
+ onChange(callback: () => void): () => void;
+ protected triggerChange(): void;
+}
/**
* The minimal AuthStore interface.
*
+ * @deprecated
* This interface predates the abstract BaseAuthStore class
* and it is kept mainly for backward compatibility.
*
@@ -81,7 +149,7 @@ type AuthStore = {
/**
* Retrieves the stored model data (if any).
*/
- readonly model: User | Admin | {};
+ readonly model: User | Admin | null;
/**
* Checks if the store has valid (aka. existing and unexpired) token.
*/
@@ -89,7 +157,7 @@ type AuthStore = {
/**
* Saves new token and model data in the auth store.
*/
- save(token: string, model: User | Admin | {}): void;
+ save(token: string, model: User | Admin | null): void;
/**
* Removes the stored token and model data form the auth store.
*/
@@ -564,7 +632,7 @@ declare class Client {
/**
* A replacable instance of the local `AuthStore` service.
*/
- authStore: AuthStore;
+ authStore: AuthStore | BaseAuthStore;
/**
* An instance of the service that handles the **Settings APIs**.
*/
@@ -594,7 +662,7 @@ declare class Client {
*/
readonly realtime: Realtime;
private cancelControllers;
- constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | null);
+ constructor(baseUrl?: string, lang?: string, authStore?: AuthStore | BaseAuthStore | null);
/**
* @deprecated Legacy alias for `this.authStore`.
*/
diff --git a/dist/pocketbase.umd.js b/dist/pocketbase.umd.js
index 137d74d..ae025c8 100644
--- a/dist/pocketbase.umd.js
+++ b/dist/pocketbase.umd.js
@@ -1 +1 @@
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).PocketBase=e()}(this,(function(){"use strict";var t=function(e,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},t(e,n)};function e(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function i(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}var n=function(){return n=Object.assign||function(t){for(var e,n=1,i=arguments.length;n0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!i.exp||i.exp-n>Date.now()/1e3))},t}(),a=function(){function t(){this.baseToken="",this.baseModel={},this._onChangeCallbacks=[]}return Object.defineProperty(t.prototype,"token",{get:function(){return this.baseToken},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"model",{get:function(){return this.baseModel},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"isValid",{get:function(){return!u.isExpired(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t,this.baseModel=e,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel={},this.triggerChange()},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},b=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],u=function(a){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,a,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?u(a+1):s}))]}))}))};return u(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r0&&o[o.length-1])||6!==r[0]&&2!==r[0])){s=0;continue}if(3===r[0]&&(!o||r[1]>o[0]&&r[1]0&&(!n.exp||n.exp-e>Date.now()/1e3))}(this.token)},enumerable:!1,configurable:!0}),t.prototype.save=function(t,e){this.baseToken=t||"",this.baseModel=null!==e&&"object"==typeof e?"undefined"!==(null==e?void 0:e.verified)?new f(e):new v(e):null,this.triggerChange()},t.prototype.clear=function(){this.baseToken="",this.baseModel=null,this.triggerChange()},t.prototype.loadFromCookie=function(t,e){void 0===e&&(e=y);var n=function(t,e){var n={};if("string"!=typeof t)return n;for(var i=Object.assign({},e||{}).decode||l,o=0;o4096&&(a.model={id:null===(i=null==a?void 0:a.model)||void 0===i?void 0:i.id,email:null===(o=null==a?void 0:a.model)||void 0===o?void 0:o.email},this.model instanceof f&&(a.model.verified=this.model.verified),l=u(e,JSON.stringify(a),t)),l},t.prototype.onChange=function(t){var e=this;return this._onChangeCallbacks.push(t),function(){for(var n=e._onChangeCallbacks.length-1;n>=0;n--)if(e._onChangeCallbacks[n]==t)return delete e._onChangeCallbacks[n],void e._onChangeCallbacks.splice(n,1)}},t.prototype.triggerChange=function(){for(var t=0,e=this._onChangeCallbacks;t0?t:1,this.perPage=e>=0?e:0,this.totalItems=n>=0?n:0,this.totalPages=i>=0?i:0,this.items=o||[]},S=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return e(n,t),n.prototype._getFullList=function(t,e,n){var r=this;void 0===e&&(e=100),void 0===n&&(n={});var s=[],a=function(u){return i(r,void 0,void 0,(function(){return o(this,(function(i){return[2,this._getList(t,u,e,n).then((function(t){var e=t,n=e.items,i=e.totalItems;return s=s.concat(n),n.length&&i>s.length?a(u+1):s}))]}))}))};return a(1)},n.prototype._getList=function(t,e,n,i){var o=this;return void 0===e&&(e=1),void 0===n&&(n=30),void 0===i&&(i={}),i=Object.assign({page:e,perPage:n},i),this.client.send(t,{method:"GET",params:i}).then((function(t){var e=[];if(null==t?void 0:t.items){t.items=t.items||[];for(var n=0,i=t.items;n=400)throw new s({url:t.url,status:t.status,data:e});return[2,e]}}))}))})).catch((function(t){throw new s(t)}))]}))}))},t.prototype.buildUrl=function(t){var e=this.baseUrl+(this.baseUrl.endsWith("/")?"":"/");return t&&(e+=t.startsWith("/")?t.substring(1):t),e},t.prototype.serializeQueryParams=function(t){var e=[];for(var n in t)if(null!==t[n]){var i=t[n],o=encodeURIComponent(n);if(Array.isArray(i))for(var r=0,s=i;r void;
+type onChangeFunc = (token: string, model: User|Admin|null) => void;
+
+const defaultCookieKey = 'pb_auth';
/**
* Base AuthStore class that is intented to be extended by all other
* PocketBase AuthStore implementations.
*/
-export default abstract class BaseAuthStore implements AuthStore {
+export default abstract class BaseAuthStore {
protected baseToken: string = '';
- protected baseModel: User | Admin | {} = {};
+ protected baseModel: User|Admin|null = null;
private _onChangeCallbacks: Array = [];
@@ -25,7 +27,7 @@ export default abstract class BaseAuthStore implements AuthStore {
/**
* Retrieves the stored model data (if any).
*/
- get model(): User | Admin | {} {
+ get model(): User|Admin|null {
return this.baseModel;
}
@@ -33,15 +35,23 @@ export default abstract class BaseAuthStore implements AuthStore {
* Checks if the store has valid (aka. existing and unexpired) token.
*/
get isValid(): boolean {
- return !JWT.isExpired(this.token);
+ return !isTokenExpired(this.token);
}
/**
* Saves the provided new token and model data in the auth store.
*/
- save(token: string, model: User | Admin | {}): void {
- this.baseToken = token;
- this.baseModel = model;
+ save(token: string, model: User|Admin|null): void {
+ this.baseToken = token || '';
+
+ // normalize the model instance
+ if (model !== null && typeof model === 'object') {
+ this.baseModel = (model as any)?.verified !== 'undefined' ?
+ new User(model) : new Admin(model);
+ } else {
+ this.baseModel = null;
+ }
+
this.triggerChange();
}
@@ -50,10 +60,81 @@ export default abstract class BaseAuthStore implements AuthStore {
*/
clear(): void {
this.baseToken = '';
- this.baseModel = {};
+ this.baseModel = null;
this.triggerChange();
}
+ /**
+ * Parses the provided cookie string and updates the store state
+ * with the cookie's token and model data.
+ */
+ loadFromCookie(cookie: string, key = defaultCookieKey): void {
+ const rawData = cookieParse(cookie || '')[key] || '';
+
+ let data: { [key: string]: any } = {};
+ try {
+ data = JSON.parse(rawData);
+ // normalize
+ if (typeof data === null || typeof data !== 'object' || Array.isArray(data)) {
+ data = {};
+ }
+ } catch (_) {}
+
+ this.save(data.token || '', data.model || {});
+ }
+
+ /**
+ * Exports the current store state as cookie string.
+ *
+ * By default the following optional attributes are added:
+ * - Secure
+ * - HttpOnly
+ * - SameSite=Strict
+ * - Path=/
+ * - Expires={the token expiration date}
+ *
+ * NB! If the generated cookie exceeds 4096 bytes, this method will
+ * strip the model data to the bare minimum to try to fit within the
+ * recommended size in https://www.rfc-editor.org/rfc/rfc6265#section-6.1.
+ */
+ exportToCookie(options?: SerializeOptions, key = defaultCookieKey): string {
+ const defaultOptions: SerializeOptions = {
+ secure: true,
+ sameSite: true,
+ httpOnly: true,
+ path: "/",
+ };
+
+ // extract the token expiration date
+ const payload = getTokenPayload(this.token);
+ if (payload?.exp) {
+ defaultOptions.expires = new Date(payload.exp * 1000);
+ } else {
+ defaultOptions.expires = new Date('1970-01-01');
+ }
+
+ // merge with the user defined options
+ options = Object.assign({}, defaultOptions, options);
+
+ const rawData = {
+ token: this.token,
+ model: this.model?.export() || null,
+ };
+
+ let result = cookieSerialize(key, JSON.stringify(rawData), options);
+
+ // strip down the model data to the bare minimum
+ if (rawData.model && new Blob([result]).size > 4096) {
+ rawData.model = {id: rawData?.model?.id, email: rawData?.model?.email};
+ if (this.model instanceof User) {
+ rawData.model.verified = this.model.verified;
+ }
+ result = cookieSerialize(key, JSON.stringify(rawData), options)
+ }
+
+ return result;
+ }
+
/**
* Register a callback function that will be called on store change.
*
diff --git a/src/stores/LocalAuthStore.ts b/src/stores/LocalAuthStore.ts
index 72d5176..b3cbd25 100644
--- a/src/stores/LocalAuthStore.ts
+++ b/src/stores/LocalAuthStore.ts
@@ -7,7 +7,7 @@ import Admin from '@/models/Admin';
* to runtime/memory if local storage is undefined (eg. in node env).
*/
export default class LocalAuthStore extends BaseAuthStore {
- private fallback: { [key: string]: any } = {};
+ private storageFallback: { [key: string]: any } = {};
private storageKey: string
constructor(storageKey = "pocketbase_auth") {
@@ -28,7 +28,7 @@ export default class LocalAuthStore extends BaseAuthStore {
/**
* @inheritdoc
*/
- get model(): User | Admin | {} {
+ get model(): User|Admin|null {
const data = this._storageGet(this.storageKey) || {};
if (
@@ -37,7 +37,7 @@ export default class LocalAuthStore extends BaseAuthStore {
data.model === null ||
typeof data.model !== 'object'
) {
- return {};
+ return null;
}
// admins don't have `verified` prop
@@ -51,7 +51,7 @@ export default class LocalAuthStore extends BaseAuthStore {
/**
* @inheritdoc
*/
- save(token: string, model: User | Admin | {}) {
+ save(token: string, model: User|Admin|null) {
this._storageSet(this.storageKey, {
'token': token,
'model': model,
@@ -87,8 +87,8 @@ export default class LocalAuthStore extends BaseAuthStore {
}
}
- // fallback to runtime/memory
- return this.fallback[key];
+ // fallback
+ return this.storageFallback[key];
}
/**
@@ -104,8 +104,8 @@ export default class LocalAuthStore extends BaseAuthStore {
}
window?.localStorage?.setItem(key, normalizedVal);
} else {
- // store in runtime/memory
- this.fallback[key] = value;
+ // store in fallback
+ this.storageFallback[key] = value;
}
}
@@ -118,7 +118,7 @@ export default class LocalAuthStore extends BaseAuthStore {
window?.localStorage?.removeItem(key);
}
- // delete from runtime/memory
- delete this.fallback[key];
+ // delete from fallback
+ delete this.storageFallback[key];
}
}
diff --git a/src/stores/utils/AuthStore.ts b/src/stores/utils/AuthStore.ts
index 3737e06..f021173 100644
--- a/src/stores/utils/AuthStore.ts
+++ b/src/stores/utils/AuthStore.ts
@@ -4,6 +4,7 @@ import Admin from '@/models/Admin';
/**
* The minimal AuthStore interface.
*
+ * @deprecated
* This interface predates the abstract BaseAuthStore class
* and it is kept mainly for backward compatibility.
*
@@ -19,7 +20,7 @@ export type AuthStore = {
/**
* Retrieves the stored model data (if any).
*/
- readonly model: User|Admin|{}
+ readonly model: User|Admin|null
/**
* Checks if the store has valid (aka. existing and unexpired) token.
@@ -29,7 +30,7 @@ export type AuthStore = {
/**
* Saves new token and model data in the auth store.
*/
- save(token: string, model: User|Admin|{}): void
+ save(token: string, model: User|Admin|null): void
/**
* Removes the stored token and model data form the auth store.
diff --git a/src/stores/utils/JWT.ts b/src/stores/utils/JWT.ts
deleted file mode 100644
index 4a37303..0000000
--- a/src/stores/utils/JWT.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-let atobPolyfill: Function;
-if (typeof atob === 'function') {
- atobPolyfill = atob
-} else {
- atobPolyfill = (a: any) => Buffer.from(a, 'base64').toString('binary');
-}
-
-export default class JWT {
- /**
- * Returns JWT token's payload data.
- */
- static getPayload(token: string): { [key: string]: any } {
- if (token) {
- try {
-
- let base64 = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {
- return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
- }).join(''));
-
- return JSON.parse(base64) || {};
- } catch (e) {
- }
- }
-
- return {};
- }
-
- /**
- * Checks whether a JWT token is expired or not.
- * Tokens without `exp` payload key are considered valid.
- * Tokens with empty payload (eg. invalid token strings) are considered expired.
- *
- * @param token The token to check.
- * @param [expirationThreshold] Time in seconds that will be substracted from the token `exp` property.
- */
- static isExpired(token: string, expirationThreshold = 0): boolean {
- let payload = JWT.getPayload(token);
-
- if (
- Object.keys(payload).length > 0 &&
- (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))
- ) {
- return false;
- }
-
- return true;
- }
-}
diff --git a/src/stores/utils/cookie.ts b/src/stores/utils/cookie.ts
new file mode 100644
index 0000000..69efc3b
--- /dev/null
+++ b/src/stores/utils/cookie.ts
@@ -0,0 +1,225 @@
+/**
+ * -------------------------------------------------------------------
+ * Simple cookie parse and serialize utilities mostly based on the
+ * node module https://github.com/jshttp/cookie.
+ * -------------------------------------------------------------------
+ */
+
+/**
+ * RegExp to match field-content in RFC 7230 sec 3.2
+ *
+ * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+ * field-vchar = VCHAR / obs-text
+ * obs-text = %x80-FF
+ */
+const fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
+
+export interface ParseOptions{
+ decode?: (val: string) => string,
+}
+
+/**
+* Parses the given cookie header string into an object
+* The object has the various cookies as keys(names) => values
+*/
+export function cookieParse(str: string, options?: ParseOptions): { [key: string]: any } {
+ const result: { [key: string]: any } = {};
+
+ if (typeof str !== 'string') {
+ return result;
+ }
+
+ const opt = Object.assign({}, options || {});
+ const decode = opt.decode || defaultDecode;
+
+ let index = 0;
+ while (index < str.length) {
+ const eqIdx = str.indexOf('=', index);
+
+ // no more cookie pairs
+ if (eqIdx === -1) {
+ break;
+ }
+
+ let endIdx = str.indexOf(';', index);
+
+ if (endIdx === -1) {
+ endIdx = str.length;
+ } else if (endIdx < eqIdx) {
+ // backtrack on prior semicolon
+ index = str.lastIndexOf(';', eqIdx - 1) + 1;
+ continue;
+ }
+
+ const key = str.slice(index, eqIdx).trim();
+
+ // only assign once
+ if (undefined === result[key]) {
+ let val = str.slice(eqIdx + 1, endIdx).trim();
+
+ // quoted values
+ if (val.charCodeAt(0) === 0x22) {
+ val = val.slice(1, -1);
+ }
+
+ try {
+ result[key] = decode(val);
+ } catch (_) {
+ result[key] = val; // no decoding
+ }
+ }
+
+ index = endIdx + 1;
+ }
+
+ return result;
+};
+
+export interface SerializeOptions{
+ encode?: (val: string | number | boolean) => string,
+ maxAge?: number,
+ domain?: string,
+ path?: string,
+ expires?: Date,
+ httpOnly?: boolean,
+ secure?: boolean,
+ priority?: string,
+ sameSite?: boolean|string,
+}
+
+/**
+ * Serialize data into a cookie header.
+ *
+ * Serialize the a name value pair into a cookie string suitable for
+ * http headers. An optional options object specified cookie parameters.
+ *
+ * ```js
+ * cookieSerialize('foo', 'bar', { httpOnly: true }) // "foo=bar; httpOnly"
+ * ```
+ */
+export function cookieSerialize(name: string, val: string, options?: SerializeOptions): string {
+ const opt = Object.assign({}, options || {});
+ const encode = opt.encode || defaultEncode;
+
+ if (!fieldContentRegExp.test(name)) {
+ throw new TypeError('argument name is invalid');
+ }
+
+ const value = encode(val);
+
+ if (value && !fieldContentRegExp.test(value)) {
+ throw new TypeError('argument val is invalid');
+ }
+
+ let result = name + '=' + value;
+
+ if (opt.maxAge != null) {
+ const maxAge = opt.maxAge - 0;
+
+ if (isNaN(maxAge) || !isFinite(maxAge)) {
+ throw new TypeError('option maxAge is invalid');
+ }
+
+ result += '; Max-Age=' + Math.floor(maxAge);
+ }
+
+ if (opt.domain) {
+ if (!fieldContentRegExp.test(opt.domain)) {
+ throw new TypeError('option domain is invalid');
+ }
+
+ result += '; Domain=' + opt.domain;
+ }
+
+ if (opt.path) {
+ if (!fieldContentRegExp.test(opt.path)) {
+ throw new TypeError('option path is invalid');
+ }
+
+ result += '; Path=' + opt.path;
+ }
+
+ if (opt.expires) {
+ if (!isDate(opt.expires) || isNaN(opt.expires.valueOf())) {
+ throw new TypeError('option expires is invalid');
+ }
+
+ result += '; Expires=' + opt.expires.toUTCString();
+ }
+
+ if (opt.httpOnly) {
+ result += '; HttpOnly';
+ }
+
+ if (opt.secure) {
+ result += '; Secure';
+ }
+
+ if (opt.priority) {
+ const priority = typeof opt.priority === 'string' ? opt.priority.toLowerCase() : opt.priority;
+
+ switch (priority) {
+ case 'low':
+ result += '; Priority=Low';
+ break;
+ case 'medium':
+ result += '; Priority=Medium';
+ break;
+ case 'high':
+ result += '; Priority=High';
+ break;
+ default:
+ throw new TypeError('option priority is invalid');
+ }
+ }
+
+ if (opt.sameSite) {
+ const sameSite = typeof opt.sameSite === 'string' ? opt.sameSite.toLowerCase() : opt.sameSite;
+
+ switch (sameSite) {
+ case true:
+ result += '; SameSite=Strict';
+ break;
+ case 'lax':
+ result += '; SameSite=Lax';
+ break;
+ case 'strict':
+ result += '; SameSite=Strict';
+ break;
+ case 'none':
+ result += '; SameSite=None';
+ break;
+ default:
+ throw new TypeError('option sameSite is invalid');
+ }
+ }
+
+ return result;
+};
+
+/**
+ * Default URL-decode string value function.
+ * Optimized to skip native call when no `%`.
+ */
+function defaultDecode(val: string): string {
+ return val.indexOf('%') !== -1
+ ? decodeURIComponent(val)
+ : val;
+}
+
+/**
+ * Default URL-encode value function.
+ */
+function defaultEncode(val: string | number | boolean): string {
+ return encodeURIComponent(val);
+}
+
+/**
+ * Determines if value is a Date.
+ */
+function isDate(val: any): boolean {
+ return (
+ Object.prototype.toString.call(val) === '[object Date]' ||
+ val instanceof Date
+ );
+}
diff --git a/src/stores/utils/jwt.ts b/src/stores/utils/jwt.ts
new file mode 100644
index 0000000..af2c3bc
--- /dev/null
+++ b/src/stores/utils/jwt.ts
@@ -0,0 +1,46 @@
+let atobPolyfill: Function;
+if (typeof atob === 'function') {
+ atobPolyfill = atob
+} else {
+ atobPolyfill = (a: any) => Buffer.from(a, 'base64').toString('binary');
+}
+
+/**
+ * Returns JWT token's payload data.
+ */
+export function getTokenPayload(token: string): { [key: string]: any } {
+ if (token) {
+ try {
+
+ let base64 = decodeURIComponent(atobPolyfill(token.split('.')[1]).split('').map(function (c: string) {
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
+ }).join(''));
+
+ return JSON.parse(base64) || {};
+ } catch (e) {
+ }
+ }
+
+ return {};
+}
+
+/**
+ * Checks whether a JWT token is expired or not.
+ * Tokens without `exp` payload key are considered valid.
+ * Tokens with empty payload (eg. invalid token strings) are considered expired.
+ *
+ * @param token The token to check.
+ * @param [expirationThreshold] Time in seconds that will be substracted from the token `exp` property.
+ */
+export function isTokenExpired(token: string, expirationThreshold = 0): boolean {
+ let payload = getTokenPayload(token);
+
+ if (
+ Object.keys(payload).length > 0 &&
+ (!payload.exp || (payload.exp - expirationThreshold) > (Date.now() / 1000))
+ ) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/tests/stores/LocalAuthStore.spec.ts b/tests/stores/LocalAuthStore.spec.ts
index 0546eac..9579e14 100644
--- a/tests/stores/LocalAuthStore.spec.ts
+++ b/tests/stores/LocalAuthStore.spec.ts
@@ -8,12 +8,12 @@ describe('LocalAuthStore', function() {
it('Should store auth data', function() {
const store = new LocalAuthStore();
- store.save('test1', { 'id': 'id1', 'verified': false });
+ store.save('test1', new User({ 'id': 'id1', 'verified': false }));
assert.equal(store.token, 'test1');
assert.deepEqual(store.model, new User({ 'id': 'id1', 'verified': false }));
// update
- store.save('test2', { 'id': 'id2' });
+ store.save('test2', new Admin({ 'id': 'id2' }));
assert.equal(store.token, 'test2');
assert.deepEqual(store.model, new Admin({ 'id': 'id2' }));
});
@@ -23,13 +23,13 @@ describe('LocalAuthStore', function() {
it('Should remove all stored auth data', function() {
const store = new LocalAuthStore();
- store.save('test', { 'id': 'id1' });
+ store.save('test', new Admin({ 'id': 'id1' }));
assert.equal(store.token, 'test');
assert.deepEqual(store.model, new Admin({ 'id': 'id1' }));
store.clear();
assert.equal(store.token, '');
- assert.deepEqual(store.model, {});
+ assert.deepEqual(store.model, null);
});
});
@@ -38,7 +38,7 @@ describe('LocalAuthStore', function() {
const store = new LocalAuthStore();
assert.equal(store.token, '');
- store.save('test', { 'id': 1 });
+ store.save('test', new User({ 'id': "1" }));
assert.equal(store.token, 'test');
});
});
@@ -47,9 +47,9 @@ describe('LocalAuthStore', function() {
it('Should extract the stored token value', function() {
const store = new LocalAuthStore();
- assert.deepEqual(store.model, {});
- store.save('test', { 'id': 1 });
- assert.deepEqual(store.model, new Admin({ 'id': 1 }));
+ assert.deepEqual(store.model, null);
+ store.save('test', new User({ 'id': "1" }));
+ assert.deepEqual(store.model, new User({ 'id': "1" }));
});
});
@@ -59,17 +59,95 @@ describe('LocalAuthStore', function() {
assert.isFalse(store.isValid, 'empty token string (initial)');
- store.save('test', { 'id': 1 });
+ store.save('test', new User({ 'id': "1" }));
assert.isFalse(store.isValid, 'invalid token string');
- store.save('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTYyNDc4ODAwMH0.WOzXh8TQh6fBXJJlOvHktBuv7D8eSyrYx4_IBj2Deyo', { 'id': 1 });
+ store.save('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTYyNDc4ODAwMH0.WOzXh8TQh6fBXJJlOvHktBuv7D8eSyrYx4_IBj2Deyo', new User({ 'id': "1" }));
assert.isFalse(store.isValid, 'expired token');
- store.save('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE', { 'id': 1 });
+ store.save('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE', new User({ 'id': "1" }));
assert.isTrue(store.isValid, 'valid token');
});
});
+ describe('loadFromCookie()', function() {
+ it('Should populate the store with the parsed cookie data', function() {
+ const store = new LocalAuthStore();
+
+ const data = {
+ token: "test_token",
+ model: {"id": 123},
+ };
+
+ store.loadFromCookie("pb_auth=" + JSON.stringify(data));
+
+ assert.equal(store.token, data.token);
+ assert.deepEqual((store.model as any).id, data.model?.id);
+ });
+ });
+
+ describe('exportToCookie()', function() {
+ it('Should generate a cookie from the store data (with default options)', function() {
+ const store = new LocalAuthStore();
+ store.save(
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE',
+ new User({ 'id': "1" }),
+ );
+
+ const result = store.exportToCookie();
+
+ assert.equal(result, "pb_auth=%7B%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE%22%2C%22model%22%3A%7B%22id%22%3A%221%22%2C%22created%22%3A%22%22%2C%22updated%22%3A%22%22%2C%22email%22%3A%22%22%2C%22verified%22%3Afalse%2C%22lastResetSentAt%22%3A%22%22%2C%22lastVerificationSentAt%22%3A%22%22%2C%22profile%22%3Anull%7D%7D; Path=/; Expires=Thu, 27 Jun 2030 10:00:00 GMT; HttpOnly; Secure; SameSite=Strict");
+ });
+
+ it('Should generate a cookie from the store data (with custom options)', function() {
+ const store = new LocalAuthStore();
+ store.save(
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE',
+ new User({
+ 'id': "1",
+ verified: true,
+ lastResetSentAt: "2022-01-01 00:00:00.000",
+ lastVerificationSentAt: "2022-01-01 00:00:00.000",
+ profile: {
+ "name": "test",
+ }
+ }),
+ );
+
+ const result = store.exportToCookie({
+ path: '/a/b/c',
+ expires: new Date('2022-01-01'),
+ httpOnly: true,
+ }, 'custom_key');
+
+ assert.equal(result, 'custom_key=%7B%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE%22%2C%22model%22%3A%7B%22id%22%3A%221%22%2C%22created%22%3A%22%22%2C%22updated%22%3A%22%22%2C%22email%22%3A%22%22%2C%22verified%22%3Atrue%2C%22lastResetSentAt%22%3A%222022-01-01%2000%3A00%3A00.000%22%2C%22lastVerificationSentAt%22%3A%222022-01-01%2000%3A00%3A00.000%22%2C%22profile%22%3A%7B%22id%22%3A%22%22%2C%22created%22%3A%22%22%2C%22updated%22%3A%22%22%2C%22name%22%3A%22test%22%2C%22%40collectionId%22%3A%22%22%2C%22%40collectionName%22%3A%22%22%2C%22%40expand%22%3A%7B%7D%7D%7D%7D; Path=/a/b/c; Expires=Sat, 01 Jan 2022 00:00:00 GMT; HttpOnly; Secure; SameSite=Strict');
+ });
+
+ it('Should strip the model data in the generated cookie if exceed 4096', function() {
+ const store = new LocalAuthStore();
+ store.save(
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE',
+ new User({
+ 'id': "1",
+ verified: true,
+ lastResetSentAt: "2022-01-01 00:00:00.000",
+ lastVerificationSentAt: "2022-01-01 00:00:00.000",
+ profile: {
+ "name": "a".repeat(4000),
+ }
+ }),
+ );
+
+ const result = store.exportToCookie({
+ path: '/a/b/c',
+ expires: new Date('2022-01-01'),
+ httpOnly: true,
+ });
+
+ assert.equal(result, 'pb_auth=%7B%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjMsImV4cCI6MTkwODc4NDgwMH0.vVbRVx-Bs7pusxfU8TTTOEtNcUEYSzmJUboC68PB5iE%22%2C%22model%22%3A%7B%22id%22%3A%221%22%2C%22email%22%3A%22%22%2C%22verified%22%3Atrue%7D%7D; Path=/a/b/c; Expires=Sat, 01 Jan 2022 00:00:00 GMT; HttpOnly; Secure; SameSite=Strict');
+ });
+ });
+
describe('onChange()', function() {
it('Should trigger the onChange() callbacks', function() {
const store = new LocalAuthStore();
@@ -86,7 +164,7 @@ describe('LocalAuthStore', function() {
});
// trigger save() change
- store.save('test', { 'id': 1 });
+ store.save('test', new User({ 'id': '1' }));
assert.equal(callback1Calls, 1);
assert.equal(callback2Calls, 1);
@@ -98,14 +176,14 @@ describe('LocalAuthStore', function() {
// remove the second listener (aka. callback1Calls shouldn't be called anymore)
removal1();
- store.save('test', { 'id': 1 });
+ store.save('test', new User({ 'id': '1' }));
assert.equal(callback1Calls, 2);
assert.equal(callback2Calls, 3);
// remove the second listener (aka. callback2Calls shouldn't be called anymore)
removal2();
- store.save('test', { 'id': 1 });
+ store.save('test', new User({ 'id': '1' }));
assert.equal(callback1Calls, 2);
assert.equal(callback2Calls, 3);
});
diff --git a/tests/stores/utils/cookie.spec.ts b/tests/stores/utils/cookie.spec.ts
new file mode 100644
index 0000000..8b04eef
--- /dev/null
+++ b/tests/stores/utils/cookie.spec.ts
@@ -0,0 +1,43 @@
+import { assert } from 'chai';
+import { cookieParse, cookieSerialize, } from '@/stores/utils/cookie';
+
+describe('cookie', function () {
+ describe('cookieParse()', function () {
+ it('Should return an empty object if no cookie string', function () {
+ const cookies = cookieParse('');
+ assert.deepEqual(cookies, {});
+ });
+
+ it('Should successfully parse a valid cookie string', function () {
+ const cookies = cookieParse('foo=bar; abc=12@3');
+ assert.deepEqual(cookies, { 'foo': 'bar', 'abc': '12@3' });
+ });
+ });
+
+ describe('cookieSerialize()', function () {
+ it('Should serialize an empty value', function () {
+ const result = cookieSerialize('test_cookie', '');
+ assert.equal(result, 'test_cookie=');
+ });
+
+ it('Should serialize a non empty value', function () {
+ const result = cookieSerialize('test_cookie', 'abc');
+ assert.equal(result, 'test_cookie=abc');
+ });
+
+ it('Should generate a cookie with all available options', function () {
+ const result = cookieSerialize('test_cookie', 'abc', {
+ maxAge: 123,
+ domain: 'test.com',
+ path: '/abc/',
+ expires: new Date('2022-01-01'),
+ httpOnly: true,
+ secure: true,
+ priority: "low",
+ sameSite: "lax",
+ encode: (val) => "encode_" + encodeURIComponent(val),
+ });
+ assert.equal(result, 'test_cookie=encode_abc; Max-Age=123; Domain=test.com; Path=/abc/; Expires=Sat, 01 Jan 2022 00:00:00 GMT; HttpOnly; Secure; Priority=Low; SameSite=Lax');
+ });
+ });
+});
diff --git a/tests/stores/utils/JWT.spec.ts b/tests/stores/utils/jwt.spec.ts
similarity index 81%
rename from tests/stores/utils/JWT.spec.ts
rename to tests/stores/utils/jwt.spec.ts
index ef5ac98..03784ab 100644
--- a/tests/stores/utils/JWT.spec.ts
+++ b/tests/stores/utils/jwt.spec.ts
@@ -1,12 +1,12 @@
import { assert } from 'chai';
-import JWT from '@/stores/utils/JWT';
+import { getTokenPayload, isTokenExpired } from '@/stores/utils/jwt';
-describe('JWT', function () {
- describe('getPayload()', function () {
+describe('jwt', function () {
+ describe('getTokenPayload()', function () {
it('Should extract JWT payload without validation', function () {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoxMjN9.da77dJt5jjPU43vaaCr6WeHEXrxzB37b0edfjwyD-2M'
- const payload = JWT.getPayload(token);
+ const payload = getTokenPayload(token);
assert.deepEqual(payload, { 'test': 123 });
});
@@ -15,13 +15,13 @@ describe('JWT', function () {
const testCases = ['', 'abc', 'a.b.c'];
for (let i in testCases) {
const test = testCases[i];
- const payload = JWT.getPayload(test);
+ const payload = getTokenPayload(test);
assert.deepEqual(payload, {}, 'scenario ' + i);
}
});
});
- describe('isExpired()', function () {
+ describe('isTokenExpired()', function () {
it('Should successfully verify that a JWT token is expired or not', function () {
const testCases = [
// invalid JWT string
@@ -37,7 +37,7 @@ describe('JWT', function () {
];
for (let i in testCases) {
const test = testCases[i];
- assert.equal(JWT.isExpired(test[1] as string), test[0], 'scenario ' + i);
+ assert.equal(isTokenExpired(test[1] as string), test[0], 'scenario ' + i);
}
});
});