You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
131
132
```js
@@ -157,26 +158,32 @@ ClientResponseError {
157
158
}
158
159
```
159
160
160
-
####AuthStore
161
+
### AuthStore
161
162
162
163
The SDK keeps track of the authenticated token and auth model for you via the `client.authStore` instance.
163
-
It has the following public members that you can use:
164
+
165
+
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).
166
+
167
+
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:
164
168
165
169
```js
166
-
AuthStore {
167
-
// fields
168
-
token: string // the authenticated token
169
-
model: User|Admin|{}// the authenticated User or Admin model
170
-
isValid: boolean // checks if the store has existing and unexpired token
170
+
BaseAuthStore {
171
+
//base fields
172
+
token: string // the authenticated token
173
+
model: User|Admin|null// the authenticated User or Admin model
174
+
isValid: boolean // checks if the store has existing and unexpired token
171
175
172
-
// methods
176
+
//main methods
173
177
clear() // "logout" the authenticated User or Admin
174
178
save(token, model) // update the store with the new auth data
179
+
onChange(callback) // register a callback that will be called on store change
180
+
181
+
// cookie parse and serialize helpers
182
+
loadFromCookie(cookieHeader, key ='pb_auth')
183
+
exportToCookie(options = {}, key ='pb_auth')
175
184
}
176
185
```
177
186
178
-
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).
179
-
180
187
To _"logout"_ an authenticated user or admin, you can just call `client.authStore.clear()`.
181
188
182
189
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
The SDK client will auto cancel duplicated pending requests for you.
206
216
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()`
232
242
> If you want to completelly disable the auto cancellation behavior, you could use the `client.beforeSend` hook and
233
243
delete the `reqConfig.signal` property.
234
244
235
-
####Send hooks
245
+
### Send hooks
236
246
237
247
Sometimes you may want to modify the request sent data or to customize the response.
238
248
@@ -268,9 +278,199 @@ To accomplish this, the SDK provides 2 function hooks:
268
278
};
269
279
```
270
280
281
+
### SSR integration
282
+
283
+
Unfortunately, **there is no "one size fits all" solution** because each framework handle SSRdifferently (_and even in a single framework there is more than one way of doing things_).
284
+
285
+
But in general, the idea is to use a cookie based flow:
286
+
287
+
1. Create a new`PocketBase` instance for each server-side request
288
+
2."Load/Feed" your `client.authStore`with data from the request cookie
289
+
3. Perform your application server-side actions
290
+
4. Before returning the response to the client, update the cookie with the latest `client.authStore` state
291
+
292
+
All [`BaseAuthStore`](https://github.com/pocketbase/js-sdk/blob/master/src/stores/BaseAuthStore.ts) instances have 2 helper methods that
293
+
should make working with cookies a little bit easier:
294
+
295
+
```js
296
+
// update the store with the parsed data from the cookie string
297
+
client.authStore.loadFromCookie('pb_auth=...');
298
+
299
+
// exports the store data as cookie, with option to extend the default SameSite, Secure, HttpOnly, Path and Expires attributes
And then, in some of your server-side actions, you could directly access the previously created `event.locals.pocketbase` instance:
331
+
332
+
```js
333
+
// src/routes/login/+server.js
334
+
//
335
+
// creates a `POST/login` server-side endpoint
336
+
export function POST({ request, locals }) {
337
+
const { email, password } = await request.json();
338
+
339
+
const { token, user } = await locals.pocketbase.users.authViaEmail(email, password);
340
+
341
+
return new Response('Success...');
342
+
}
343
+
```
344
+
</details>
345
+
346
+
<details>
347
+
<summary><strong>Nuxt 3</strong></summary>
348
+
349
+
One way to integrate with Nuxt 3SSR could be to create the PocketBase client in a [nuxt plugin](https://v3.nuxtjs.org/guide/directory-structure/plugins)
350
+
and provide it as a helper to the `nuxtApp` instance:
351
+
352
+
```js
353
+
// plugins/pocketbase.js
354
+
import PocketBase from 'pocketbase';
355
+
356
+
export default defineNuxtPlugin((nuxtApp) => {
357
+
return {
358
+
provide: {
359
+
pocketbase: () => {
360
+
const client = new PocketBase('http://127.0.0.1:8090');
361
+
362
+
// load the store data from the request cookie string
And then in your component you could access it like this:
380
+
381
+
```html
382
+
<template>
383
+
<div>
384
+
Show: {{ data }}
385
+
</div>
386
+
</template>
387
+
388
+
<script setup>
389
+
const { data } = await useAsyncData(async (nuxtApp) => {
390
+
const client = nuxtApp.$pocketbase();
391
+
392
+
// fetch and return all "demo" records...
393
+
return await client.records.getFullList('demo');
394
+
})
395
+
</script>
396
+
```
397
+
398
+
> 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.
399
+
</details>
400
+
401
+
<details>
402
+
<summary><strong>Next.js</strong></summary>
403
+
404
+
Next.js doesn't seem to have a central place where you can read/modify the server request and response.
405
+
[There is support for middlewares](https://nextjs.org/docs/advanced-features/middleware),
406
+
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).
407
+
408
+
One way to integrate withNext.jsSSR could be to create a custom `PocketBase` instance in each of your `getServerSideProps`:
409
+
410
+
```jsx
411
+
import PocketBase, { BaseAuthStore } from 'pocketbase';
export async function getServerSideProps({ req, res }) {
437
+
const client = new PocketBase("https://pocketbase.io");
438
+
client.authStore = new NextAuthStore(req, res);
439
+
440
+
// fetch example records...
441
+
const result = await client.records.getList("example", 1, 30);
442
+
443
+
return {
444
+
props: {
445
+
// ...
446
+
},
447
+
}
448
+
}
449
+
450
+
export default function Home() {
451
+
return (
452
+
<div>Hello world!</div>
453
+
)
454
+
}
455
+
```
456
+
</details>
457
+
458
+
### Security
459
+
460
+
The most common frontend related vulnerability is XSS (and CSRF when dealing with cookies).
461
+
Fortunately, modern browsers can detect and mitigate most ofthis type of attacks if [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) is provided.
462
+
463
+
**To prevent a malicious user or 3rd party script to steal your PocketBase auth token, it is recommended to configure a basic CSPfor your application (either as `meta` tag or HTTP header).**
464
+
465
+
This is out of the scope of the SDK, but you could find more resources about CSP at:
0 commit comments