@meistrari/auth-nuxt 0.1.0 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ import type { CreateTeamPayload, InviteUserToOrganizationOptions, ListMembersOptions, RemoveUserFromOrganizationOptions, UpdateMemberRoleOptions, UpdateOrganizationPayload, UpdateTeamPayload } from '@meistrari/auth-core';
2
+ /**
3
+ * Composable for managing organizations and their members, invitations, and teams.
4
+ *
5
+ * @returns An object containing organization management functions and the active organization and member states.
6
+ */
7
+ export declare function useTelaOrganization(): {
8
+ activeOrganization: import("vue").Ref<any, any>;
9
+ activeMember: import("vue").Ref<any, any>;
10
+ getActiveOrganization: () => Promise<any>;
11
+ listOrganizations: () => Promise<any>;
12
+ setActiveOrganization: (id: string) => Promise<void>;
13
+ updateOrganization: (payload: UpdateOrganizationPayload) => Promise<any>;
14
+ listMembers: (options?: ListMembersOptions) => Promise<any>;
15
+ getActiveMember: () => Promise<any>;
16
+ inviteUserToOrganization: (options: InviteUserToOrganizationOptions) => Promise<any>;
17
+ acceptInvitation: (id: string) => Promise<void>;
18
+ cancelInvitation: (id: string) => Promise<void>;
19
+ removeUserFromOrganization: (options: RemoveUserFromOrganizationOptions) => Promise<void>;
20
+ updateMemberRole: (options: UpdateMemberRoleOptions) => Promise<void>;
21
+ createTeam: (payload: CreateTeamPayload) => Promise<any>;
22
+ updateTeam: (id: string, payload: UpdateTeamPayload) => Promise<any>;
23
+ deleteTeam: (id: string) => Promise<void>;
24
+ listTeams: () => Promise<any>;
25
+ listTeamMembers: (id: string) => Promise<any>;
26
+ addTeamMember: (teamId: string, userId: string) => Promise<any>;
27
+ removeTeamMember: (teamId: string, userId: string) => Promise<void>;
28
+ };
@@ -0,0 +1,164 @@
1
+ import { useCookie, useRuntimeConfig } from "#app";
2
+ import { createNuxtAuthClient } from "../shared.js";
3
+ import { useOrganizationState, useSessionState } from "./state.js";
4
+ export function useTelaOrganization() {
5
+ const { activeOrganization, activeMember } = useOrganizationState();
6
+ const { session } = useSessionState();
7
+ const { jwtCookieName, apiUrl } = useRuntimeConfig().public.telaAuth;
8
+ const tokenCookie = useCookie(jwtCookieName);
9
+ const authClient = createNuxtAuthClient(apiUrl, () => tokenCookie.value ?? null);
10
+ async function getActiveOrganization() {
11
+ if (!session.value?.activeOrganizationId) {
12
+ return;
13
+ }
14
+ const organization = await authClient.organization.getOrganization(
15
+ session.value?.activeOrganizationId,
16
+ {
17
+ includeMembers: true,
18
+ includeInvitations: true,
19
+ includeTeams: true
20
+ }
21
+ );
22
+ activeOrganization.value = organization;
23
+ return organization;
24
+ }
25
+ async function listOrganizations() {
26
+ return authClient.organization.listOrganizations();
27
+ }
28
+ async function setActiveOrganization(id) {
29
+ await authClient.organization.setActiveOrganization(id);
30
+ const organization = await authClient.organization.getOrganization(id, {
31
+ includeMembers: true,
32
+ includeInvitations: true,
33
+ includeTeams: true
34
+ });
35
+ activeOrganization.value = organization;
36
+ }
37
+ async function updateOrganization(payload) {
38
+ if (!activeOrganization.value) {
39
+ throw new Error("No active organization found");
40
+ }
41
+ const organization = await authClient.organization.updateOrganization(payload);
42
+ activeOrganization.value = { ...activeOrganization.value, ...organization };
43
+ return organization;
44
+ }
45
+ async function listMembers(options) {
46
+ return authClient.organization.listMembers(options);
47
+ }
48
+ async function getActiveMember() {
49
+ const member = await authClient.organization.getActiveMember();
50
+ activeMember.value = member;
51
+ return member;
52
+ }
53
+ async function inviteUserToOrganization(options) {
54
+ const invitation = await authClient.organization.inviteUserToOrganization(options);
55
+ if (activeOrganization.value) {
56
+ activeOrganization.value = {
57
+ ...activeOrganization.value,
58
+ invitations: [...activeOrganization.value?.invitations ?? [], invitation]
59
+ };
60
+ }
61
+ return invitation;
62
+ }
63
+ async function acceptInvitation(id) {
64
+ await authClient.organization.acceptInvitation(id);
65
+ const members = await authClient.organization.listMembers();
66
+ if (activeOrganization.value) {
67
+ activeOrganization.value = {
68
+ ...activeOrganization.value,
69
+ members
70
+ };
71
+ }
72
+ }
73
+ async function cancelInvitation(id) {
74
+ await authClient.organization.cancelInvitation(id);
75
+ if (activeOrganization.value) {
76
+ activeOrganization.value = {
77
+ ...activeOrganization.value,
78
+ invitations: activeOrganization.value?.invitations?.filter((invitation) => invitation.id !== id) ?? []
79
+ };
80
+ }
81
+ }
82
+ async function removeUserFromOrganization(options) {
83
+ await authClient.organization.removeUserFromOrganization(options);
84
+ if (activeOrganization.value) {
85
+ activeOrganization.value = {
86
+ ...activeOrganization.value,
87
+ members: activeOrganization.value?.members?.filter((member) => member.id !== options.memberId) ?? []
88
+ };
89
+ }
90
+ }
91
+ async function updateMemberRole(options) {
92
+ await authClient.organization.updateMemberRole(options);
93
+ const members = await authClient.organization.listMembers();
94
+ if (activeOrganization.value) {
95
+ activeOrganization.value = {
96
+ ...activeOrganization.value,
97
+ members
98
+ };
99
+ }
100
+ }
101
+ async function createTeam(payload) {
102
+ const team = await authClient.organization.createTeam(payload);
103
+ if (activeOrganization.value) {
104
+ activeOrganization.value = {
105
+ ...activeOrganization.value,
106
+ teams: [...activeOrganization.value?.teams ?? [], team]
107
+ };
108
+ }
109
+ return team;
110
+ }
111
+ async function updateTeam(id, payload) {
112
+ const updatedTeam = await authClient.organization.updateTeam(id, payload);
113
+ if (activeOrganization.value) {
114
+ activeOrganization.value = {
115
+ ...activeOrganization.value,
116
+ teams: activeOrganization.value?.teams?.map((team) => team.id === id ? updatedTeam : team) ?? []
117
+ };
118
+ }
119
+ return updatedTeam;
120
+ }
121
+ async function deleteTeam(id) {
122
+ await authClient.organization.deleteTeam(id);
123
+ if (activeOrganization.value) {
124
+ activeOrganization.value = {
125
+ ...activeOrganization.value,
126
+ teams: activeOrganization.value?.teams?.filter((team) => team.id !== id) ?? []
127
+ };
128
+ }
129
+ }
130
+ async function listTeams() {
131
+ return authClient.organization.listTeams();
132
+ }
133
+ async function listTeamMembers(id) {
134
+ return authClient.organization.listTeamMembers(id);
135
+ }
136
+ async function addTeamMember(teamId, userId) {
137
+ return authClient.organization.addTeamMember(teamId, userId);
138
+ }
139
+ async function removeTeamMember(teamId, userId) {
140
+ await authClient.organization.removeTeamMember(teamId, userId);
141
+ }
142
+ return {
143
+ activeOrganization,
144
+ activeMember,
145
+ getActiveOrganization,
146
+ listOrganizations,
147
+ setActiveOrganization,
148
+ updateOrganization,
149
+ listMembers,
150
+ getActiveMember,
151
+ inviteUserToOrganization,
152
+ acceptInvitation,
153
+ cancelInvitation,
154
+ removeUserFromOrganization,
155
+ updateMemberRole,
156
+ createTeam,
157
+ updateTeam,
158
+ deleteTeam,
159
+ listTeams,
160
+ listTeamMembers,
161
+ addTeamMember,
162
+ removeTeamMember
163
+ };
164
+ }
@@ -0,0 +1,18 @@
1
+ import { type SignInWithEmailAndPasswordOptions, type SignInWithSamlOptions, type SocialSignInOptions } from '@meistrari/auth-core';
2
+ /**
3
+ * Composable for managing user sessions and authentication.
4
+ *
5
+ * @returns An object containing session management functions and the user and session states.
6
+ */
7
+ export declare function useTelaSession(): {
8
+ user: import("vue").Ref<any, any>;
9
+ session: import("vue").Ref<any, any>;
10
+ getSession: () => Promise<any>;
11
+ getToken: () => Promise<any>;
12
+ signInWithEmailAndPassword: ({ email, password, callbackURL, errorCallbackURL, }: SignInWithEmailAndPasswordOptions) => Promise<void>;
13
+ signInWithSocialProvider: ({ provider, callbackURL, errorCallbackURL, }: SocialSignInOptions) => Promise<void>;
14
+ signInWithSaml: ({ email, callbackURL, errorCallbackURL, }: SignInWithSamlOptions) => Promise<void>;
15
+ signOut: (callback?: (() => void) | (() => Promise<void>)) => Promise<void>;
16
+ requestPasswordReset: (email: string, callbackURL: string) => Promise<void>;
17
+ resetPassword: (token: string, password: string) => Promise<void>;
18
+ };
@@ -0,0 +1,88 @@
1
+ import { useCookie, useRuntimeConfig } from "#app";
2
+ import { APIError } from "@meistrari/auth-core";
3
+ import { createNuxtAuthClient } from "../shared.js";
4
+ import { useSessionState, useOrganizationState } from "./state.js";
5
+ export function useTelaSession() {
6
+ const { user, session } = useSessionState();
7
+ const { jwtCookieName, apiUrl } = useRuntimeConfig().public.telaAuth;
8
+ const tokenCookie = useCookie(jwtCookieName);
9
+ const authClient = createNuxtAuthClient(apiUrl, () => tokenCookie.value ?? null);
10
+ async function getSession() {
11
+ return await authClient.session.getSession();
12
+ }
13
+ async function getToken() {
14
+ try {
15
+ const { token } = await authClient.session.getToken();
16
+ return token;
17
+ } catch (error) {
18
+ if (error instanceof APIError && error.status === 401) {
19
+ await signOut();
20
+ }
21
+ return null;
22
+ }
23
+ }
24
+ async function signInWithSocialProvider({
25
+ provider,
26
+ callbackURL,
27
+ errorCallbackURL
28
+ }) {
29
+ await authClient.session.signInWithSocialProvider({
30
+ provider,
31
+ callbackURL,
32
+ errorCallbackURL
33
+ });
34
+ }
35
+ async function signInWithSaml({
36
+ email,
37
+ callbackURL,
38
+ errorCallbackURL
39
+ }) {
40
+ await authClient.session.signInWithSaml({
41
+ email,
42
+ callbackURL,
43
+ errorCallbackURL
44
+ });
45
+ }
46
+ async function signInWithEmailAndPassword({
47
+ email,
48
+ password,
49
+ callbackURL,
50
+ errorCallbackURL
51
+ }) {
52
+ await authClient.session.signInWithEmailAndPassword({
53
+ email,
54
+ password,
55
+ callbackURL,
56
+ errorCallbackURL
57
+ });
58
+ }
59
+ async function requestPasswordReset(email, callbackURL) {
60
+ await authClient.session.requestPasswordReset(email, callbackURL);
61
+ }
62
+ async function resetPassword(token, password) {
63
+ await authClient.session.resetPassword(token, password);
64
+ }
65
+ async function signOut(callback) {
66
+ const { activeOrganization, activeMember } = useOrganizationState();
67
+ await authClient.session.signOut(async () => {
68
+ tokenCookie.value = null;
69
+ user.value = null;
70
+ session.value = null;
71
+ activeOrganization.value = null;
72
+ activeMember.value = null;
73
+ await callback?.();
74
+ });
75
+ }
76
+ return {
77
+ user,
78
+ session,
79
+ getSession,
80
+ getToken,
81
+ signInWithEmailAndPassword,
82
+ signInWithSocialProvider,
83
+ signInWithSaml,
84
+ signOut,
85
+ requestPasswordReset,
86
+ resetPassword
87
+ };
88
+ }
@@ -0,0 +1,22 @@
1
+ import type { FullOrganization, Invitation, Member, Team } from '@meistrari/auth-core';
2
+ export type FullOrganizationWithRelations = FullOrganization & {
3
+ members: Member[];
4
+ invitations: Invitation[];
5
+ teams: Team[];
6
+ };
7
+ /**
8
+ * Shared state for session management.
9
+ * This module provides access to session-related state without creating circular dependencies.
10
+ */
11
+ export declare function useSessionState(): {
12
+ user: import("vue").Ref<any, any>;
13
+ session: import("vue").Ref<any, any>;
14
+ };
15
+ /**
16
+ * Shared state for organization management.
17
+ * This module provides access to organization-related state without creating circular dependencies.
18
+ */
19
+ export declare function useOrganizationState(): {
20
+ activeOrganization: import("vue").Ref<any, any>;
21
+ activeMember: import("vue").Ref<any, any>;
22
+ };
@@ -0,0 +1,17 @@
1
+ import { useState } from "#app";
2
+ export function useSessionState() {
3
+ const user = useState("user", () => null);
4
+ const session = useState("session", () => null);
5
+ return {
6
+ user,
7
+ session
8
+ };
9
+ }
10
+ export function useOrganizationState() {
11
+ const activeOrganization = useState("activeOrganization", () => null);
12
+ const activeMember = useState("activeMember", () => null);
13
+ return {
14
+ activeOrganization,
15
+ activeMember
16
+ };
17
+ }
@@ -1,15 +1,2 @@
1
- import { createAuthClient } from '@meistrari/auth-core';
2
- declare const _default: import("#app").Plugin<{
3
- auth: {
4
- client: ReturnType<typeof createAuthClient>;
5
- getToken: () => Promise<string | null | undefined>;
6
- refreshToken: () => Promise<string | null | undefined>;
7
- };
8
- }> & import("#app").ObjectPlugin<{
9
- auth: {
10
- client: ReturnType<typeof createAuthClient>;
11
- getToken: () => Promise<string | null | undefined>;
12
- refreshToken: () => Promise<string | null | undefined>;
13
- };
14
- }>;
1
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
15
2
  export default _default;
@@ -1,105 +1,90 @@
1
- import { defineNuxtPlugin, useCookie, useRequestHeaders, useRuntimeConfig } from "#app";
1
+ import { defineNuxtPlugin, useCookie, useRuntimeConfig, useRequestURL } from "#app";
2
2
  import { watch } from "vue";
3
- import { createAuthClient, isTokenExpired } from "@meistrari/auth-core";
4
- import { useMeistrariAuth } from "./composable.js";
3
+ import { useTelaSession } from "./composables/session.js";
4
+ import { createNuxtAuthClient } from "./shared.js";
5
+ import { useRoute, navigateTo } from "#imports";
5
6
  export default defineNuxtPlugin({
6
- name: "meistrari-auth",
7
- parallel: true,
7
+ name: "tela-auth",
8
+ enforce: "pre",
9
+ env: {
10
+ islands: false
11
+ },
8
12
  async setup() {
9
- const config = useRuntimeConfig().public.auth;
10
- const authClient = createAuthClient(config.apiUrl);
11
- const { user, session } = useMeistrariAuth();
12
- async function getToken() {
13
- const token = useCookie(config.jwtCookieName);
14
- if (token.value) {
15
- if (!isTokenExpired(token.value)) {
16
- return token.value;
17
- }
18
- }
19
- try {
20
- return await refreshToken();
21
- } catch (error) {
22
- throw new Error("Failed to get token: " + (error instanceof Error ? error.message : String(error)));
23
- }
24
- }
25
- async function refreshToken() {
26
- const token = useCookie(config.jwtCookieName);
27
- const headers = useRequestHeaders();
28
- const session2 = await authClient.getSession({
29
- fetchOptions: {
30
- // on the client side we include credentials
31
- credentials: "include",
32
- // on the server side we forward the cookies
33
- headers,
34
- onSuccess: (ctx) => {
35
- const jwt = ctx.response.headers.get("set-auth-jwt");
36
- if (jwt) {
37
- token.value = jwt;
38
- }
13
+ const authConfig = useRuntimeConfig().public.telaAuth;
14
+ const { session, user, getToken } = useTelaSession();
15
+ const tokenCookie = useCookie(authConfig.jwtCookieName);
16
+ tokenCookie.value = null;
17
+ const authClient = createNuxtAuthClient(authConfig.apiUrl, () => tokenCookie.value ?? null);
18
+ const query = useRoute().query;
19
+ const nonce = query.nonce;
20
+ const origin = useRequestURL();
21
+ if (import.meta.server) {
22
+ if (nonce && typeof nonce === "string") {
23
+ if (nonce !== "null") {
24
+ try {
25
+ const payload = await authClient.session.getNoncePayload(nonce);
26
+ tokenCookie.value = payload.token;
27
+ } catch {
28
+ await navigateTo(`${authConfig.apiUrl}/api/auth/handshake?origin=${origin.toString()}`, {
29
+ external: true,
30
+ redirectCode: 302
31
+ });
32
+ return;
39
33
  }
40
34
  }
41
- });
42
- if (session2.error || !session2.data?.session) {
43
- throw new Error("Failed to refresh token");
35
+ } else {
36
+ await navigateTo(`${authConfig.apiUrl}/api/auth/handshake?origin=${origin.toString()}`, {
37
+ external: true,
38
+ redirectCode: 302
39
+ });
40
+ return;
41
+ }
42
+ } else if (import.meta.client && !session.value) {
43
+ const token = await getToken();
44
+ if (token) {
45
+ tokenCookie.value = token;
44
46
  }
45
- return token.value;
46
47
  }
47
48
  async function initializeSession() {
48
49
  if (session.value && user.value)
49
50
  return;
50
- const token = useCookie(config.jwtCookieName);
51
- const headers = import.meta.server ? useRequestHeaders() : void 0;
52
- const { data: sessionData, error: sessionError } = await authClient.getSession(
53
- {
54
- fetchOptions: {
55
- // on the client side we include credentials
56
- credentials: "include",
57
- // on the server side we forward the cookies
58
- headers,
59
- ...config.useJwt && {
60
- onSuccess: (context) => {
61
- const jwt = context.response.headers.get("Set-Auth-Jwt");
62
- if (jwt) {
63
- token.value = jwt;
64
- }
65
- }
66
- }
67
- }
68
- }
69
- );
70
- if (sessionError || !sessionData) {
51
+ const sessionData = await authClient.session.getSession();
52
+ if (!sessionData) {
71
53
  return;
72
54
  }
73
55
  user.value = sessionData.user;
74
56
  session.value = sessionData.session;
75
57
  }
76
- await initializeSession();
58
+ if (tokenCookie.value) {
59
+ await initializeSession();
60
+ }
77
61
  if (import.meta.client) {
78
- if (config.useJwt) {
79
- let tokenRefreshInterval = null;
80
- watch(session, async (newVal) => {
81
- if (tokenRefreshInterval) {
82
- clearTimeout(tokenRefreshInterval);
83
- tokenRefreshInterval = null;
84
- }
85
- if (newVal) {
86
- async function createTokenRefreshInterval() {
87
- await refreshToken();
88
- tokenRefreshInterval = window.setTimeout(createTokenRefreshInterval, 6e4);
62
+ let tokenRefreshInterval = null;
63
+ watch(session, async (newVal) => {
64
+ if (tokenRefreshInterval) {
65
+ clearTimeout(tokenRefreshInterval);
66
+ tokenRefreshInterval = null;
67
+ }
68
+ if (newVal) {
69
+ async function createTokenRefreshInterval() {
70
+ const token = await getToken();
71
+ if (token) {
72
+ tokenCookie.value = token;
89
73
  }
90
- createTokenRefreshInterval();
74
+ tokenRefreshInterval = window.setTimeout(createTokenRefreshInterval, 6e4);
91
75
  }
92
- }, { immediate: true });
93
- }
94
- }
95
- return {
96
- provide: {
97
- auth: {
98
- client: authClient,
99
- getToken,
100
- refreshToken
76
+ createTokenRefreshInterval();
101
77
  }
102
- }
103
- };
78
+ }, { immediate: true });
79
+ }
80
+ },
81
+ hooks: {
82
+ "app:mounted": () => {
83
+ const url = new URL(window.location.href);
84
+ url.searchParams.delete("session");
85
+ url.searchParams.delete("session_data");
86
+ url.searchParams.delete("nonce");
87
+ window.history.replaceState({}, "", url.pathname + url.search + url.hash);
88
+ }
104
89
  }
105
90
  });
@@ -1,26 +1,21 @@
1
+ import { validateToken, extractTokenPayload } from "@meistrari/auth-core";
1
2
  import { defineEventHandler, getCookie } from "h3";
2
3
  import { useRuntimeConfig } from "nitropack/runtime/config";
3
- import { createAuthClient } from "@meistrari/auth-core";
4
4
  async function setAuthContext(event) {
5
5
  event.context.auth = {
6
- session: null,
7
- user: null
6
+ user: null,
7
+ workspace: null
8
8
  };
9
- const sessionCookie = getCookie(event, "__Secure-__session");
10
- if (!sessionCookie)
9
+ const authConfig = useRuntimeConfig(event).public.telaAuth;
10
+ const tokenCookie = getCookie(event, authConfig.jwtCookieName);
11
+ if (!tokenCookie)
11
12
  return;
12
- const authConfig = useRuntimeConfig(event).public.auth;
13
- const authClient = createAuthClient(authConfig.apiUrl);
14
- const { data: sessionData, error: sessionError } = await authClient.getSession({
15
- fetchOptions: {
16
- headers: event.headers
17
- }
18
- });
19
- if (sessionError || !sessionData) {
13
+ const isValid = await validateToken(tokenCookie, authConfig.apiUrl);
14
+ if (!isValid)
20
15
  return;
21
- }
22
- event.context.auth.session = sessionData.session;
23
- event.context.auth.user = sessionData.user;
16
+ const payload = extractTokenPayload(tokenCookie);
17
+ event.context.auth.user = { email: payload.email, ...payload.user };
18
+ event.context.auth.workspace = payload.workspace;
24
19
  }
25
20
  export function meistrariAuthMiddleware(callback) {
26
21
  return defineEventHandler(async (event) => {
@@ -1,3 +1,6 @@
1
1
  {
2
- "extends": "../../../.nuxt/tsconfig.server.json",
2
+ "extends": [
3
+ "../../../../../../node_modules/@meistrari/mise-en-place/tsconfig.base.json",
4
+ "../../../.nuxt/tsconfig.server.json"
5
+ ],
3
6
  }
@@ -1,19 +1,19 @@
1
- import type { User, Session } from '@meistrari/auth-core'
1
+ import type { JWTTokenPayload } from '@meistrari/auth-core'
2
2
  import type { H3Event, H3EventContext } from 'h3'
3
3
 
4
4
  declare module 'h3' {
5
5
  interface H3EventContext {
6
6
  auth?: {
7
- user: User | null
8
- session: Session | null
7
+ user: { email: string } & JWTTokenPayload['user'] | null
8
+ workspace: JWTTokenPayload['workspace'] | null
9
9
  }
10
10
  }
11
11
  }
12
12
 
13
13
  export interface AuthenticatedH3EventContext extends H3EventContext {
14
14
  auth: {
15
- user: User | null
16
- session: Session | null
15
+ user: { email: string } & JWTTokenPayload['user'] | null
16
+ workspace: JWTTokenPayload['workspace'] | null
17
17
  }
18
18
  }
19
19
 
@@ -0,0 +1 @@
1
+ export declare function createNuxtAuthClient(apiUrl: string, getAuthToken: () => string | null): any;
@@ -0,0 +1,19 @@
1
+ import { AuthClient } from "@meistrari/auth-core";
2
+ import { version } from "../../package.json";
3
+ export function createNuxtAuthClient(apiUrl, getAuthToken) {
4
+ const serviceName = typeof process !== "undefined" ? process.env.SERVICE_NAME : "";
5
+ const userAgent = `auth-sdk:nuxt:${version}${serviceName ? `@${serviceName}` : ""}`;
6
+ return new AuthClient(apiUrl, {
7
+ headers: {
8
+ "X-User-Agent": userAgent
9
+ },
10
+ onRequest: (context) => {
11
+ const requestUrl = new URL(context.url);
12
+ const token = getAuthToken();
13
+ const isTokenRequest = requestUrl.pathname.endsWith("/api/auth/token");
14
+ if (token && !isTokenRequest) {
15
+ context.headers.set("Authorization", `Bearer ${token}`);
16
+ }
17
+ }
18
+ });
19
+ }