-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
919 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
export { defineUserSignupFields } from './providers/types.js'; | ||
|
||
// PUBLIC | ||
export type { AuthUser } from '../server/_types' | ||
|
||
// PUBLIC | ||
export { getEmail, getUsername, getFirstProviderUserId, findUserIdentity } from './user.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
// todo(filip): turn into a proper import/path | ||
export type { SanitizedUser as User, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types/' | ||
export type { AuthUser, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
waspc/examples/todo-typescript/.wasp/out/sdk/wasp/api/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import axios, { type AxiosError } from 'axios' | ||
|
||
import config from 'wasp/core/config' | ||
import { storage } from 'wasp/core/storage' | ||
import { apiEventsEmitter } from './events.js' | ||
|
||
// PUBLIC API | ||
export const api = axios.create({ | ||
baseURL: config.apiUrl, | ||
}) | ||
|
||
const WASP_APP_AUTH_SESSION_ID_NAME = 'sessionId' | ||
|
||
let waspAppAuthSessionId = storage.get(WASP_APP_AUTH_SESSION_ID_NAME) as string | undefined | ||
|
||
// PRIVATE API (sdk) | ||
export function setSessionId(sessionId: string): void { | ||
waspAppAuthSessionId = sessionId | ||
storage.set(WASP_APP_AUTH_SESSION_ID_NAME, sessionId) | ||
apiEventsEmitter.emit('sessionId.set') | ||
} | ||
|
||
// PRIVATE API (sdk) | ||
export function getSessionId(): string | undefined { | ||
return waspAppAuthSessionId | ||
} | ||
|
||
// PRIVATE API (sdk) | ||
export function clearSessionId(): void { | ||
waspAppAuthSessionId = undefined | ||
storage.remove(WASP_APP_AUTH_SESSION_ID_NAME) | ||
apiEventsEmitter.emit('sessionId.clear') | ||
} | ||
|
||
// PRIVATE API (sdk) | ||
export function removeLocalUserData(): void { | ||
waspAppAuthSessionId = undefined | ||
storage.clear() | ||
apiEventsEmitter.emit('sessionId.clear') | ||
} | ||
|
||
api.interceptors.request.use((request) => { | ||
const sessionId = getSessionId() | ||
if (sessionId) { | ||
request.headers['Authorization'] = `Bearer ${sessionId}` | ||
} | ||
return request | ||
}) | ||
|
||
api.interceptors.response.use(undefined, (error) => { | ||
if (error.response?.status === 401) { | ||
clearSessionId() | ||
} | ||
return Promise.reject(error) | ||
}) | ||
|
||
// This handler will run on other tabs (not the active one calling API functions), | ||
// and will ensure they know about auth session ID changes. | ||
// Ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event | ||
// "Note: This won't work on the same page that is making the changes — it is really a way | ||
// for other pages on the domain using the storage to sync any changes that are made." | ||
window.addEventListener('storage', (event) => { | ||
if (event.key === storage.getPrefixedKey(WASP_APP_AUTH_SESSION_ID_NAME)) { | ||
if (!!event.newValue) { | ||
waspAppAuthSessionId = event.newValue | ||
apiEventsEmitter.emit('sessionId.set') | ||
} else { | ||
waspAppAuthSessionId = undefined | ||
apiEventsEmitter.emit('sessionId.clear') | ||
} | ||
} | ||
}) | ||
|
||
// PRIVATE API (sdk) | ||
/** | ||
* Takes an error returned by the app's API (as returned by axios), and transforms into a more | ||
* standard format to be further used by the client. It is also assumed that given API | ||
* error has been formatted as implemented by HttpError on the server. | ||
*/ | ||
export function handleApiError(error: AxiosError<{ message?: string, data?: unknown }>): void { | ||
if (error?.response) { | ||
// If error came from HTTP response, we capture most informative message | ||
// and also add .statusCode information to it. | ||
// If error had JSON response, we assume it is of format { message, data } and | ||
// add that info to the error. | ||
// TODO: We might want to use HttpError here instead of just Error, since | ||
// HttpError is also used on server to throw errors like these. | ||
// That would require copying HttpError code to web-app also and using it here. | ||
const responseJson = error.response?.data | ||
const responseStatusCode = error.response.status | ||
throw new WaspHttpError(responseStatusCode, responseJson?.message ?? error.message, responseJson) | ||
} else { | ||
// If any other error, we just propagate it. | ||
throw error | ||
} | ||
} | ||
|
||
class WaspHttpError extends Error { | ||
statusCode: number | ||
|
||
data: unknown | ||
|
||
constructor (statusCode: number, message: string, data: unknown) { | ||
super(message) | ||
this.statusCode = statusCode | ||
this.data = data | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
waspc/examples/todo-typescript/.wasp/out/sdk/wasp/auth/helpers/user.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { setSessionId } from 'wasp/client/api' | ||
import { invalidateAndRemoveQueries } from 'wasp/operations/resources' | ||
|
||
export async function initSession(sessionId: string): Promise<void> { | ||
setSessionId(sessionId) | ||
// We need to invalidate queries after login in order to get the correct user | ||
// data in the React components (using `useAuth`). | ||
// Redirects after login won't work properly without this. | ||
|
||
// TODO(filip): We are currently removing all the queries, but we should | ||
// remove only non-public, user-dependent queries - public queries are | ||
// expected not to change in respect to the currently logged in user. | ||
await invalidateAndRemoveQueries() | ||
} |
17 changes: 17 additions & 0 deletions
17
waspc/examples/todo-typescript/.wasp/out/sdk/wasp/auth/logout.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { api, removeLocalUserData } from 'wasp/client/api' | ||
import { invalidateAndRemoveQueries } from 'wasp/operations/resources' | ||
|
||
export default async function logout(): Promise<void> { | ||
try { | ||
await api.post('/auth/logout') | ||
} finally { | ||
// Even if the logout request fails, we still want to remove the local user data | ||
// in case the logout failed because of a network error and the user walked away | ||
// from the computer. | ||
removeLocalUserData() | ||
|
||
// TODO(filip): We are currently invalidating and removing all the queries, but | ||
// we should remove only the non-public, user-dependent ones. | ||
await invalidateAndRemoveQueries() | ||
} | ||
} |
2 changes: 2 additions & 0 deletions
2
waspc/examples/todo-typescript/.wasp/out/sdk/wasp/auth/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// todo(filip): turn into a proper import/path | ||
export type { AuthUser, ProviderName, DeserializedAuthIdentity } from 'wasp/server/_types' |
38 changes: 38 additions & 0 deletions
38
waspc/examples/todo-typescript/.wasp/out/sdk/wasp/auth/useAuth.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { deserialize as superjsonDeserialize } from 'superjson' | ||
import { useQuery } from 'wasp/rpc' | ||
import { api, handleApiError } from 'wasp/client/api' | ||
import { HttpMethod } from 'wasp/types' | ||
import type { AuthUser } from './types' | ||
import { addMetadataToQuery } from 'wasp/rpc/queries' | ||
|
||
export const getMe = createUserGetter() | ||
|
||
export default function useAuth(queryFnArgs?: unknown, config?: any) { | ||
return useQuery(getMe, queryFnArgs, config) | ||
} | ||
|
||
function createUserGetter() { | ||
const getMeRelativePath = 'auth/me' | ||
const getMeRoute = { method: HttpMethod.Get, path: `/${getMeRelativePath}` } | ||
async function getMe(): Promise<AuthUser | null> { | ||
try { | ||
const response = await api.get(getMeRoute.path) | ||
|
||
return superjsonDeserialize(response.data) | ||
} catch (error) { | ||
if (error.response?.status === 401) { | ||
return null | ||
} else { | ||
handleApiError(error) | ||
} | ||
} | ||
} | ||
|
||
addMetadataToQuery(getMe, { | ||
relativeQueryPath: getMeRelativePath, | ||
queryRoute: getMeRoute, | ||
entitiesUsed: ['User'], | ||
}) | ||
|
||
return getMe | ||
} |
Oops, something went wrong.