Skip to content

Commit

Permalink
[PR changes #392] feat: move pointer and sessionDataType to the Sessi…
Browse files Browse the repository at this point in the history
…onConfig (#592)

* feat: add generic to "jsonPointerGet"

* feat: implement the sessionDataJsonPointer

* feat: add to docs

* feat: move pointer and sessionDataType to the SessionConfig

* fix: remove default baseUrl

* fix merge conflicts from main

* fix: merge conflict with SessionConfig

* reset to main branch state

* fix: lint

* feat: make session refresh params optional

* feat: rebase `jsonPointerGet` function on @Danielwinkelmann's original modifications

* refacto: set the return type when extracting json pointers

* fix: should use the pointer to retrieve the user session not datatype + improves returned error

* revert: import as type

* fix lint

* fix: type issue - forgotten changes from daniel

* move the session data type back to the providers (local and refresh)

* forget to remove baseurl while testing

* fix: use config directly

* docs: add session data type to the refresh docs

* fix(playground): reset to default pointer '/'

Co-authored-by: Marsel Shayhin <[email protected]>

* Update useAuth.ts

* Update useAuth.ts

* Update helpers.ts

* Update helpers.ts

* fix: usage of `/` in json pointer get

---------

Co-authored-by: Daniel Winkelmann <[email protected]>
Co-authored-by: Daniel <[email protected]>
Co-authored-by: Zoey <[email protected]>
Co-authored-by: Valentin Hutter <[email protected]>
Co-authored-by: Valentin Hutter <[email protected]>
Co-authored-by: Marsel Shayhin <[email protected]>
  • Loading branch information
7 people authored May 16, 2024
1 parent 4dfe9eb commit a863d92
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 36 deletions.
66 changes: 50 additions & 16 deletions docs/content/2.configuration/2.nuxt-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,31 @@ type ProviderLocal = {
*/
cookieDomain?: string;
},
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account', subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
/*
* Settings for the session-data that `nuxt-auth` receives from the `getSession` endpoint.
*/
sessionDataType?: SessionDataObject,
session?: {
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account', subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
*/
dataType?: SessionDataObject;
/**
* How to extract the session-data from the session response.
*
* E.g., setting this to `/data/user` and returning an object like `{ data: { user: { id:number, name: string } }, status: 'ok' }` from the `getSession` endpoint will
* storing the 'User' object typed as the type created via the 'dataType' prop.
*
* This follows the JSON Pointer standard, see it's RFC6901 here: https://www.rfc-editor.org/rfc/rfc6901
*
* @default / Access the root of the session response object
* @example /data/user Access the `data/user` property of the session response object
*/
dataResponsePointer?: string;
}
}

```
Expand Down Expand Up @@ -406,7 +423,7 @@ type ProviderRefresh = {
* @default '/refreshToken' Access the `refreshToken` property of the sign-in response object
* @example / Access the root of the sign-in response object, useful when your endpoint returns a plain, non-object string as the refreshToken
*/
signInResponseRefreshTokenPointer?: string
signInResponseRefreshTokenPointer?: string,
/**
* How to do a fetch for the refresh token.
*
Expand Down Expand Up @@ -445,14 +462,31 @@ type ProviderRefresh = {
*/
cookieDomain?: string;
},
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account', subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
/*
* Settings for the session-data that `nuxt-auth` receives from the `getSession` endpoint.
*/
sessionDataType?: SessionDataObject,
session?: {
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account', subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
*/
dataType?: SessionDataObject;
/**
* How to extract the session-data from the session response.
*
* E.g., setting this to `/data/user` and returning an object like `{ data: { user: { id:number, name: string } }, status: 'ok' }` from the `getSession` endpoint will
* storing the 'User' object typed as the type created via the 'dataType' prop.
*
* This follows the JSON Pointer standard, see it's RFC6901 here: https://www.rfc-editor.org/rfc/rfc6901
*
* @default / Access the root of the session response object
* @example /data/user Access the `data/user` property of the session response object
*/
dataResponsePointer?: string;
}
}
```
```ts [SessionConfig]
Expand All @@ -471,7 +505,7 @@ type SessionConfig = {
* @default false
*
*/
enableRefreshPeriodically: number | boolean
enableRefreshPeriodically: number | boolean,
/**
* Whether to refresh the session every time the browser window is refocused.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ inferface SessionData {
id: string | number
}

// Option B: You configured `auth.provider.sessionDataType` to something like ` { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account' }`
// Option B: You configured `auth.provider.session.dataType` to something like ` { id: 'string', email: 'string', name: 'string', role: 'admin | guest | account' }`
inferface SessionData {
id: string
email: string
Expand All @@ -196,7 +196,7 @@ inferface SessionData {
```
::

### About `auth.provider.sessionDataType`
### About `auth.provider.session.dataType`

This is a configuration option available to dynamically type the `SessionData` that the `local` provider will return when accessing `data.value`. Read more about this in the [nuxt.config.ts configuration documentation](/nuxt-auth/v0.6/configuration/nuxt-config) of the `local` provider.

Expand Down
6 changes: 4 additions & 2 deletions playground-local/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ export default defineNuxtConfig({
token: {
signInResponseTokenPointer: '/token/accessToken'
},
sessionDataType: { id: 'string', email: 'string', name: 'string', role: "'admin' | 'guest' | 'account'", subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
session: {
dataType: { id: 'string', email: 'string', name: 'string', role: "'admin' | 'guest' | 'account'", subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" },
dataResponsePointer: '/'
}
},
session: {
// Whether to refresh the session every time the browser window is refocused.
enableRefreshOnWindowFocus: true,

// Whether to refresh the session every `X` milliseconds. Set this to `false` to turn it off. The session will only be refreshed if a session already exists.
enableRefreshPeriodically: 5000
},
Expand Down
12 changes: 9 additions & 3 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ const defaultsByBackend: {
sameSiteAttribute: 'lax',
cookieDomain: ''
},
sessionDataType: { id: 'string | number' }
session: {
dataType: { id: 'string | number' },
dataResponsePointer: '/'
}
},

refresh: {
Expand Down Expand Up @@ -92,7 +95,10 @@ const defaultsByBackend: {
maxAgeInSeconds: 60 * 60 * 24 * 7, // 7 days
cookieDomain: ''
},
sessionDataType: { id: 'string | number' }
session: {
dataType: { id: 'string | number' },
dataResponsePointer: '/'
}
},

authjs: {
Expand Down Expand Up @@ -201,7 +207,7 @@ export default defineNuxtModule<ModuleOptions>({
...(options.provider.type === 'local'
? [genInterface(
'SessionData',
(options.provider as any).sessionDataType
(options.provider as any).session.dataType
)]
: []
),
Expand Down
10 changes: 8 additions & 2 deletions src/runtime/composables/local/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,14 @@ const getSession: GetSessionFunc<SessionData | null | void> = async (getSessionO

loading.value = true
try {
data.value = await _fetch<SessionData>(nuxt, path, { method, headers })
} catch {
const result = await _fetch<any>(nuxt, path, { method, headers })
const { dataResponsePointer: sessionDataResponsePointer } = config.session
data.value = jsonPointerGet<SessionData>(result, sessionDataResponsePointer)
} catch (err) {
if (!data.value && err instanceof Error) {
console.error(`Session: unable to extract session, ${err.message}`)
}

// Clear all data: Request failed so we must not be authenticated
data.value = null
rawToken.value = null
Expand Down
8 changes: 4 additions & 4 deletions src/runtime/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ export const useTypedBackendConfig = <T extends SupportedAuthProviders>(
* @param obj
* @param pointer
*/
export function jsonPointerGet (
export function jsonPointerGet <TResult = string | Record<string, any>> (
obj: Record<string, any>,
pointer: string
): string | Record<string, any> {
): TResult {
const refTokens = Array.isArray(pointer) ? pointer : jsonPointerParse(pointer)

for (let i = 0; i < refTokens.length; ++i) {
Expand All @@ -62,7 +62,7 @@ export function jsonPointerGet (
}
obj = obj[tok]
}
return obj
return obj as TResult
}

/**
Expand Down Expand Up @@ -130,7 +130,7 @@ export function objectFromJsonPointer (pointer: string | string[], value: any):
* Adapted from https://github.com/manuelstofer/json-pointer/blob/931b0f9c7178ca09778087b4b0ac7e4f505620c2/index.js#L217-L221
*/
function jsonPointerParse (pointer: string): string[] {
if (pointer === '') {
if (pointer === '' || pointer === '/') {
return []
}
if (pointer.charAt(0) !== '/') {
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/plugins/refresh-token.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default defineNuxtPlugin({
return
}

// check if refereshTokenOnly
// check if refreshTokenOnly
if (!configToken.refreshOnlyToken) {
const extractedRefreshToken = jsonPointerGet(
response,
Expand Down
29 changes: 23 additions & 6 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,30 @@ export type ProviderLocal = {
cookieDomain?: string;
};
/**
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: "'admin' | 'guest' | 'account", subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
* Settings for the session-data that `nuxt-auth` receives from the `getSession` endpoint.
*/
sessionDataType?: SessionDataObject;
session?: {
/*
* Define an interface for the session data object that `nuxt-auth` expects to receive from the `getSession` endpoint.
*
* @default { id: 'string | number' }
* @example { id: 'string', name: 'string', email: 'string' }
* @advanced_array_example { id: 'string', email: 'string', name: 'string', role: "'admin' | 'guest' | 'account'", subscriptions: "{ id: number, status: 'ACTIVE' | 'INACTIVE' }[]" }
*/
dataType?: SessionDataObject;
/**
* How to extract the session-data from the session response.
*
* E.g., setting this to `/data/user` and returning an object like `{ data: { user: { id:number, name: string } }, status: 'ok' }` from the `getSession` endpoint will
* storing the 'User' object typed as the type created via the 'dataType' prop.
*
* This follows the JSON Pointer standard, see it's RFC6901 here: https://www.rfc-editor.org/rfc/rfc6901
*
* @default / Access the root of the session response object
* @example /data/user Access the `data/user` property of the session response object
*/
dataResponsePointer?: string;
};
};

/**
Expand Down

0 comments on commit a863d92

Please sign in to comment.