@strands.gg/accui 2.0.0 → 2.1.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.
- package/dist/nuxt/runtime/composables/useAuthenticatedFetch.cjs.js +1 -0
- package/dist/nuxt/runtime/composables/useAuthenticatedFetch.cjs.js.map +1 -0
- package/dist/nuxt/runtime/composables/useAuthenticatedFetch.es.js +131 -0
- package/dist/nuxt/runtime/composables/useAuthenticatedFetch.es.js.map +1 -0
- package/dist/nuxt/runtime/plugins/auth-interceptor.client.cjs.js +1 -0
- package/dist/nuxt/runtime/plugins/auth-interceptor.client.cjs.js.map +1 -0
- package/dist/nuxt/runtime/plugins/auth-interceptor.client.es.js +77 -0
- package/dist/nuxt/runtime/plugins/auth-interceptor.client.es.js.map +1 -0
- package/dist/nuxt-v4/runtime/composables/useAuthenticatedFetch.cjs.js +1 -0
- package/dist/nuxt-v4/runtime/composables/useAuthenticatedFetch.cjs.js.map +1 -0
- package/dist/nuxt-v4/runtime/composables/useAuthenticatedFetch.es.js +131 -0
- package/dist/nuxt-v4/runtime/composables/useAuthenticatedFetch.es.js.map +1 -0
- package/dist/nuxt-v4/runtime/plugins/auth-interceptor.client.cjs.js +1 -0
- package/dist/nuxt-v4/runtime/plugins/auth-interceptor.client.cjs.js.map +1 -0
- package/dist/nuxt-v4/runtime/plugins/auth-interceptor.client.es.js +77 -0
- package/dist/nuxt-v4/runtime/plugins/auth-interceptor.client.es.js.map +1 -0
- package/dist/nuxt-v4.cjs.js +1 -0
- package/dist/nuxt-v4.cjs.js.map +1 -0
- package/dist/nuxt-v4.es.js +11 -0
- package/dist/nuxt-v4.es.js.map +1 -0
- package/dist/nuxt.cjs.js +1 -0
- package/dist/nuxt.cjs.js.map +1 -0
- package/dist/nuxt.es.js +11 -0
- package/dist/nuxt.es.js.map +1 -0
- package/dist/strands-auth-ui.cjs.js +1 -1
- package/dist/strands-auth-ui.cjs.js.map +1 -1
- package/dist/strands-auth-ui.es.js +128 -0
- package/dist/strands-auth-ui.es.js.map +1 -1
- package/package.json +6 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useStrandsAuth.cjs.js");function t(){const{currentSession:t,refreshToken:s,getAuthHeaders:n}=e.useStrandsAuth(),o=async(e,o={})=>{const{autoRefresh:r=!0,requireAuth:a=!0,baseURL:c,...h}=o;if(a&&!t.value?.accessToken)throw new Error("User is not authenticated");let u=e;c&&"string"==typeof e&&!e.startsWith("http")&&(u=new URL(e,c).toString());const i=new Headers(h.headers);if(t.value?.accessToken)try{const e=n();Object.entries(e).forEach(([e,t])=>{i.set(e,t)})}catch(y){if(a)throw y}const p={...h,headers:i};let d=await fetch(u,p);if(401===d.status&&r&&t.value?.refreshToken)try{if(await s()&&t.value?.accessToken){const e=n();Object.entries(e).forEach(([e,t])=>{i.set(e,t)}),d=await fetch(u,{...p,headers:i})}}catch(f){}return d};return{authenticatedFetch:o,get:(e,t)=>o(e,{...t,method:"GET"}),post:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"POST",headers:n,body:"object"==typeof t?JSON.stringify(t):t})},put:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"PUT",headers:n,body:"object"==typeof t?JSON.stringify(t):t})},delete:(e,t)=>o(e,{...t,method:"DELETE"}),patch:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"PATCH",headers:n,body:"object"==typeof t?JSON.stringify(t):t})}}}const s={get:async(e,s)=>{const{get:n}=t();return n(e,s)},post:async(e,s,n)=>{const{post:o}=t();return o(e,s,n)},put:async(e,s,n)=>{const{put:o}=t();return o(e,s,n)},delete:async(e,s)=>{const{delete:n}=t();return n(e,s)},patch:async(e,s,n)=>{const{patch:o}=t();return o(e,s,n)}};exports.$authFetch=s,exports.useAuthenticatedFetch=t;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthenticatedFetch.cjs.js","sources":["../../../../../../apps/accounts-ui/src/nuxt/runtime/composables/useAuthenticatedFetch.ts"],"sourcesContent":["import { useStrandsAuth } from './useStrandsAuth'\nimport type { AuthenticatedFetchOptions } from '../../../types'\n\n/**\n * Enhanced fetch composable that automatically includes auth headers\n * and handles token refresh for API requests\n */\nexport function useAuthenticatedFetch() {\n const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth()\n\n const authenticatedFetch = async (\n url: string | URL,\n options: AuthenticatedFetchOptions = {}\n ): Promise<Response> => {\n const {\n autoRefresh = true,\n requireAuth = true,\n baseURL,\n ...fetchOptions\n } = options\n\n // Check if user is authenticated when required\n if (requireAuth && !currentSession.value?.accessToken) {\n throw new Error('User is not authenticated')\n }\n\n // Construct full URL if baseURL is provided\n let fullUrl: string | URL = url\n if (baseURL && typeof url === 'string' && !url.startsWith('http')) {\n fullUrl = new URL(url, baseURL).toString()\n }\n\n // Prepare headers\n const headers = new Headers(fetchOptions.headers)\n \n // Add auth headers if available\n if (currentSession.value?.accessToken) {\n try {\n const authHeaders = getAuthHeaders()\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n } catch (error) {\n console.warn('[Strands Auth] Failed to get auth headers:', error)\n if (requireAuth) {\n throw error\n }\n }\n }\n\n // Make the request\n const enhancedOptions: RequestInit = {\n ...fetchOptions,\n headers\n }\n\n let response = await fetch(fullUrl, enhancedOptions)\n\n // Handle 401 with auto-refresh\n if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {\n console.log('[Strands Auth] Request failed with 401, attempting token refresh...')\n \n try {\n // Attempt to refresh token\n const refreshed = await refreshToken()\n \n if (refreshed && currentSession.value?.accessToken) {\n // Update headers with new token\n const newAuthHeaders = getAuthHeaders()\n Object.entries(newAuthHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Retry the request with new token\n console.log('[Strands Auth] Retrying request with refreshed token')\n response = await fetch(fullUrl, { ...enhancedOptions, headers })\n }\n } catch (refreshError) {\n console.error('[Strands Auth] Token refresh failed:', refreshError)\n // Return the original 401 response\n }\n }\n\n return response\n }\n\n /**\n * Convenience method for making authenticated GET requests\n */\n const get = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'GET' })\n }\n\n /**\n * Convenience method for making authenticated POST requests\n */\n const post = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n // Auto-set content type for JSON requests\n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'POST',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated PUT requests\n */\n const put = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PUT',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated DELETE requests\n */\n const del = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'DELETE' })\n }\n\n /**\n * Convenience method for making authenticated PATCH requests\n */\n const patch = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PATCH',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n return {\n authenticatedFetch,\n get,\n post,\n put,\n delete: del,\n patch\n }\n}\n\n// Export convenience functions for non-composable usage\nexport const $authFetch = {\n get: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { get } = useAuthenticatedFetch()\n return get(url, options)\n },\n post: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { post } = useAuthenticatedFetch()\n return post(url, body, options)\n },\n put: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { put } = useAuthenticatedFetch()\n return put(url, body, options)\n },\n delete: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { delete: del } = useAuthenticatedFetch()\n return del(url, options)\n },\n patch: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { patch } = useAuthenticatedFetch()\n return patch(url, body, options)\n }\n}"],"names":["useAuthenticatedFetch","currentSession","refreshToken","getAuthHeaders","useStrandsAuth","authenticatedFetch","async","url","options","autoRefresh","requireAuth","baseURL","fetchOptions","value","accessToken","Error","fullUrl","startsWith","URL","toString","headers","Headers","authHeaders","Object","entries","forEach","key","set","error","enhancedOptions","response","fetch","status","newAuthHeaders","refreshError","get","method","post","body","has","JSON","stringify","put","delete","patch","$authFetch","del"],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useStrandsAuth } from "./useStrandsAuth.es.js";
|
|
2
|
+
function useAuthenticatedFetch() {
|
|
3
|
+
const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth();
|
|
4
|
+
const authenticatedFetch = async (url, options = {}) => {
|
|
5
|
+
const {
|
|
6
|
+
autoRefresh = true,
|
|
7
|
+
requireAuth = true,
|
|
8
|
+
baseURL,
|
|
9
|
+
...fetchOptions
|
|
10
|
+
} = options;
|
|
11
|
+
if (requireAuth && !currentSession.value?.accessToken) {
|
|
12
|
+
throw new Error("User is not authenticated");
|
|
13
|
+
}
|
|
14
|
+
let fullUrl = url;
|
|
15
|
+
if (baseURL && typeof url === "string" && !url.startsWith("http")) {
|
|
16
|
+
fullUrl = new URL(url, baseURL).toString();
|
|
17
|
+
}
|
|
18
|
+
const headers = new Headers(fetchOptions.headers);
|
|
19
|
+
if (currentSession.value?.accessToken) {
|
|
20
|
+
try {
|
|
21
|
+
const authHeaders = getAuthHeaders();
|
|
22
|
+
Object.entries(authHeaders).forEach(([key, value]) => {
|
|
23
|
+
headers.set(key, value);
|
|
24
|
+
});
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.warn("[Strands Auth] Failed to get auth headers:", error);
|
|
27
|
+
if (requireAuth) {
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const enhancedOptions = {
|
|
33
|
+
...fetchOptions,
|
|
34
|
+
headers
|
|
35
|
+
};
|
|
36
|
+
let response = await fetch(fullUrl, enhancedOptions);
|
|
37
|
+
if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {
|
|
38
|
+
console.log("[Strands Auth] Request failed with 401, attempting token refresh...");
|
|
39
|
+
try {
|
|
40
|
+
const refreshed = await refreshToken();
|
|
41
|
+
if (refreshed && currentSession.value?.accessToken) {
|
|
42
|
+
const newAuthHeaders = getAuthHeaders();
|
|
43
|
+
Object.entries(newAuthHeaders).forEach(([key, value]) => {
|
|
44
|
+
headers.set(key, value);
|
|
45
|
+
});
|
|
46
|
+
console.log("[Strands Auth] Retrying request with refreshed token");
|
|
47
|
+
response = await fetch(fullUrl, { ...enhancedOptions, headers });
|
|
48
|
+
}
|
|
49
|
+
} catch (refreshError) {
|
|
50
|
+
console.error("[Strands Auth] Token refresh failed:", refreshError);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return response;
|
|
54
|
+
};
|
|
55
|
+
const get = (url, options) => {
|
|
56
|
+
return authenticatedFetch(url, { ...options, method: "GET" });
|
|
57
|
+
};
|
|
58
|
+
const post = (url, body, options) => {
|
|
59
|
+
const headers = new Headers(options?.headers);
|
|
60
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
61
|
+
headers.set("Content-Type", "application/json");
|
|
62
|
+
}
|
|
63
|
+
return authenticatedFetch(url, {
|
|
64
|
+
...options,
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers,
|
|
67
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const put = (url, body, options) => {
|
|
71
|
+
const headers = new Headers(options?.headers);
|
|
72
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
73
|
+
headers.set("Content-Type", "application/json");
|
|
74
|
+
}
|
|
75
|
+
return authenticatedFetch(url, {
|
|
76
|
+
...options,
|
|
77
|
+
method: "PUT",
|
|
78
|
+
headers,
|
|
79
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const del = (url, options) => {
|
|
83
|
+
return authenticatedFetch(url, { ...options, method: "DELETE" });
|
|
84
|
+
};
|
|
85
|
+
const patch = (url, body, options) => {
|
|
86
|
+
const headers = new Headers(options?.headers);
|
|
87
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
88
|
+
headers.set("Content-Type", "application/json");
|
|
89
|
+
}
|
|
90
|
+
return authenticatedFetch(url, {
|
|
91
|
+
...options,
|
|
92
|
+
method: "PATCH",
|
|
93
|
+
headers,
|
|
94
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
authenticatedFetch,
|
|
99
|
+
get,
|
|
100
|
+
post,
|
|
101
|
+
put,
|
|
102
|
+
delete: del,
|
|
103
|
+
patch
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const $authFetch = {
|
|
107
|
+
get: async (url, options) => {
|
|
108
|
+
const { get } = useAuthenticatedFetch();
|
|
109
|
+
return get(url, options);
|
|
110
|
+
},
|
|
111
|
+
post: async (url, body, options) => {
|
|
112
|
+
const { post } = useAuthenticatedFetch();
|
|
113
|
+
return post(url, body, options);
|
|
114
|
+
},
|
|
115
|
+
put: async (url, body, options) => {
|
|
116
|
+
const { put } = useAuthenticatedFetch();
|
|
117
|
+
return put(url, body, options);
|
|
118
|
+
},
|
|
119
|
+
delete: async (url, options) => {
|
|
120
|
+
const { delete: del } = useAuthenticatedFetch();
|
|
121
|
+
return del(url, options);
|
|
122
|
+
},
|
|
123
|
+
patch: async (url, body, options) => {
|
|
124
|
+
const { patch } = useAuthenticatedFetch();
|
|
125
|
+
return patch(url, body, options);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
export {
|
|
129
|
+
$authFetch,
|
|
130
|
+
useAuthenticatedFetch
|
|
131
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthenticatedFetch.es.js","sources":["../../../../../../apps/accounts-ui/src/nuxt/runtime/composables/useAuthenticatedFetch.ts"],"sourcesContent":["import { useStrandsAuth } from './useStrandsAuth'\nimport type { AuthenticatedFetchOptions } from '../../../types'\n\n/**\n * Enhanced fetch composable that automatically includes auth headers\n * and handles token refresh for API requests\n */\nexport function useAuthenticatedFetch() {\n const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth()\n\n const authenticatedFetch = async (\n url: string | URL,\n options: AuthenticatedFetchOptions = {}\n ): Promise<Response> => {\n const {\n autoRefresh = true,\n requireAuth = true,\n baseURL,\n ...fetchOptions\n } = options\n\n // Check if user is authenticated when required\n if (requireAuth && !currentSession.value?.accessToken) {\n throw new Error('User is not authenticated')\n }\n\n // Construct full URL if baseURL is provided\n let fullUrl: string | URL = url\n if (baseURL && typeof url === 'string' && !url.startsWith('http')) {\n fullUrl = new URL(url, baseURL).toString()\n }\n\n // Prepare headers\n const headers = new Headers(fetchOptions.headers)\n \n // Add auth headers if available\n if (currentSession.value?.accessToken) {\n try {\n const authHeaders = getAuthHeaders()\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n } catch (error) {\n console.warn('[Strands Auth] Failed to get auth headers:', error)\n if (requireAuth) {\n throw error\n }\n }\n }\n\n // Make the request\n const enhancedOptions: RequestInit = {\n ...fetchOptions,\n headers\n }\n\n let response = await fetch(fullUrl, enhancedOptions)\n\n // Handle 401 with auto-refresh\n if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {\n console.log('[Strands Auth] Request failed with 401, attempting token refresh...')\n \n try {\n // Attempt to refresh token\n const refreshed = await refreshToken()\n \n if (refreshed && currentSession.value?.accessToken) {\n // Update headers with new token\n const newAuthHeaders = getAuthHeaders()\n Object.entries(newAuthHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Retry the request with new token\n console.log('[Strands Auth] Retrying request with refreshed token')\n response = await fetch(fullUrl, { ...enhancedOptions, headers })\n }\n } catch (refreshError) {\n console.error('[Strands Auth] Token refresh failed:', refreshError)\n // Return the original 401 response\n }\n }\n\n return response\n }\n\n /**\n * Convenience method for making authenticated GET requests\n */\n const get = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'GET' })\n }\n\n /**\n * Convenience method for making authenticated POST requests\n */\n const post = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n // Auto-set content type for JSON requests\n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'POST',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated PUT requests\n */\n const put = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PUT',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated DELETE requests\n */\n const del = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'DELETE' })\n }\n\n /**\n * Convenience method for making authenticated PATCH requests\n */\n const patch = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PATCH',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n return {\n authenticatedFetch,\n get,\n post,\n put,\n delete: del,\n patch\n }\n}\n\n// Export convenience functions for non-composable usage\nexport const $authFetch = {\n get: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { get } = useAuthenticatedFetch()\n return get(url, options)\n },\n post: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { post } = useAuthenticatedFetch()\n return post(url, body, options)\n },\n put: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { put } = useAuthenticatedFetch()\n return put(url, body, options)\n },\n delete: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { delete: del } = useAuthenticatedFetch()\n return del(url, options)\n },\n patch: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { patch } = useAuthenticatedFetch()\n return patch(url, body, options)\n }\n}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const e=require("nuxt/app").defineNuxtPlugin({name:"strands-auth-interceptor",setup(){if(process.server)return;const e=globalThis.fetch;globalThis.fetch=async(t,s)=>{try{const{useStrandsAuth:o}=await Promise.resolve().then(()=>require("../composables/useStrandsAuth.cjs.js")),{currentSession:c,getAuthHeaders:n}=o();let i;i="string"==typeof t?t:t instanceof URL?t.toString():t.url;const a=function(e){if(!e.startsWith("http"))return!1;const t=["googleapis.com","github.com/api","api.github.com","discord.com/api","graph.microsoft.com","api.stripe.com","api.twilio.com"].some(t=>e.includes(t));if(t)return!1;const s=["/api/","/v1/","/v2/","/graphql","/trpc"].some(t=>e.includes(t)),r=[":3001",":8000",":8080",":5000",":4000"].some(t=>e.includes(t));return s||r}(i);if(a&&c.value?.accessToken)try{const r=n(),o=new Headers(s?.headers);Object.entries(r).forEach(([e,t])=>{o.set(e,t)});const c={...s,headers:o};return e(t,c)}catch(r){}return e(t,s)}catch(r){return e(t,s)}}}});module.exports=e;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-interceptor.client.cjs.js","sources":["../../../../../../apps/accounts-ui/src/nuxt/runtime/plugins/auth-interceptor.client.ts"],"sourcesContent":["import { defineNuxtPlugin } from 'nuxt/app'\n\nexport default defineNuxtPlugin({\n name: 'strands-auth-interceptor',\n setup() {\n // Only run on client side\n if (process.server) return\n\n // Store original fetch function\n const originalFetch = globalThis.fetch\n\n // Create interceptor function\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n try {\n // Import auth composable dynamically to avoid SSR issues\n const { useStrandsAuth } = await import('../composables/useStrandsAuth')\n const { currentSession, getAuthHeaders } = useStrandsAuth()\n\n // Parse request URL to determine if it's an API request that needs auth\n let url: string\n if (typeof input === 'string') {\n url = input\n } else if (input instanceof URL) {\n url = input.toString()\n } else {\n url = input.url\n }\n\n // Check if this is an API request that should include auth headers\n const shouldAddAuth = shouldInjectAuth(url)\n\n if (shouldAddAuth && currentSession.value?.accessToken) {\n // Get auth headers\n try {\n const authHeaders = getAuthHeaders()\n \n // Merge headers with existing headers\n const headers = new Headers(init?.headers)\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Create new init object with merged headers\n const enhancedInit: RequestInit = {\n ...init,\n headers\n }\n\n console.log('[Strands Auth] Injecting auth headers for request:', url)\n return originalFetch(input, enhancedInit)\n } catch (error) {\n // If we can't get auth headers, continue with original request\n console.warn('[Strands Auth] Failed to inject auth headers:', error)\n }\n }\n\n // Return original request\n return originalFetch(input, init)\n } catch (error) {\n // If anything goes wrong, fallback to original fetch\n console.error('[Strands Auth] Error in fetch interceptor:', error)\n return originalFetch(input, init)\n }\n }\n }\n})\n\n/**\n * Determine if a URL should have auth headers injected\n */\nfunction shouldInjectAuth(url: string): boolean {\n // Skip data URLs, blob URLs, etc.\n if (!url.startsWith('http')) {\n return false\n }\n\n // Skip third-party APIs that shouldn't receive our auth tokens\n const skipDomains = [\n 'googleapis.com',\n 'github.com/api',\n 'api.github.com',\n 'discord.com/api',\n 'graph.microsoft.com',\n 'api.stripe.com',\n 'api.twilio.com',\n // Add other third-party APIs here\n ]\n\n const shouldSkip = skipDomains.some(domain => url.includes(domain))\n if (shouldSkip) {\n return false\n }\n\n // Include auth for any API endpoints that contain common API patterns\n const apiPatterns = [\n '/api/',\n '/v1/',\n '/v2/',\n '/graphql',\n '/trpc',\n ]\n\n const isApiRequest = apiPatterns.some(pattern => url.includes(pattern))\n \n // Also check for common backend ports that might be API servers\n const apiPorts = [':3001', ':8000', ':8080', ':5000', ':4000']\n const hasApiPort = apiPorts.some(port => url.includes(port))\n\n return isApiRequest || hasApiPort\n}"],"names":["authInterceptor_client","name","setup","process","server","originalFetch","globalThis","fetch","async","input","init","useStrandsAuth","Promise","resolve","then","require","currentSession","getAuthHeaders","url","URL","toString","shouldAddAuth","startsWith","shouldSkip","some","includes","domain","isApiRequest","pattern","hasApiPort","port","shouldInjectAuth","value","accessToken","authHeaders","headers","Headers","Object","entries","forEach","key","set","enhancedInit","error"],"mappings":"mBAEAA,uCAAgC,CAC9BC,KAAM,2BACN,KAAAC,GAEE,GAAIC,QAAQC,OAAQ,OAGpB,MAAMC,EAAgBC,WAAWC,MAGjCD,WAAWC,MAAQC,MAAOC,EAA0BC,KAClD,IAEE,MAAMC,eAAEA,SAAyBC,QAAAC,UAAAC,KAAA,IAAAC,QAAO,0CAClCC,eAAEA,EAAAC,eAAgBA,GAAmBN,IAG3C,IAAIO,EAEFA,EADmB,iBAAVT,EACHA,EACGA,aAAiBU,IACpBV,EAAMW,WAENX,EAAMS,IAId,MAAMG,EAyCd,SAA0BH,GAExB,IAAKA,EAAII,WAAW,QAClB,OAAO,EAIT,MAWMC,EAXc,CAClB,iBACA,iBACA,iBACA,kBACA,sBACA,iBACA,kBAI6BC,QAAeN,EAAIO,SAASC,IAC3D,GAAIH,EACF,OAAO,EAIT,MAQMI,EARc,CAClB,QACA,OACA,OACA,WACA,SAG+BH,QAAgBN,EAAIO,SAASG,IAIxDC,EADW,CAAC,QAAS,QAAS,QAAS,QAAS,SAC1BL,QAAaN,EAAIO,SAASK,IAEtD,OAAOH,GAAgBE,CACzB,CAhF8BE,CAAiBb,GAEvC,GAAIG,GAAiBL,EAAegB,OAAOC,YAEzC,IACE,MAAMC,EAAcjB,IAGdkB,EAAU,IAAIC,QAAQ1B,GAAMyB,SAClCE,OAAOC,QAAQJ,GAAaK,QAAQ,EAAEC,EAAKR,MACzCG,EAAQM,IAAID,EAAKR,KAInB,MAAMU,EAA4B,IAC7BhC,EACHyB,WAIF,OAAO9B,EAAcI,EAAOiC,EAC9B,OAASC,GAGT,CAIF,OAAOtC,EAAcI,EAAOC,EAC9B,OAASiC,GAGP,OAAOtC,EAAcI,EAAOC,EAC9B,EAEJ"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "nuxt/app";
|
|
2
|
+
const authInterceptor_client = defineNuxtPlugin({
|
|
3
|
+
name: "strands-auth-interceptor",
|
|
4
|
+
setup() {
|
|
5
|
+
if (process.server) return;
|
|
6
|
+
const originalFetch = globalThis.fetch;
|
|
7
|
+
globalThis.fetch = async (input, init) => {
|
|
8
|
+
try {
|
|
9
|
+
const { useStrandsAuth } = await import("../composables/useStrandsAuth.es.js");
|
|
10
|
+
const { currentSession, getAuthHeaders } = useStrandsAuth();
|
|
11
|
+
let url;
|
|
12
|
+
if (typeof input === "string") {
|
|
13
|
+
url = input;
|
|
14
|
+
} else if (input instanceof URL) {
|
|
15
|
+
url = input.toString();
|
|
16
|
+
} else {
|
|
17
|
+
url = input.url;
|
|
18
|
+
}
|
|
19
|
+
const shouldAddAuth = shouldInjectAuth(url);
|
|
20
|
+
if (shouldAddAuth && currentSession.value?.accessToken) {
|
|
21
|
+
try {
|
|
22
|
+
const authHeaders = getAuthHeaders();
|
|
23
|
+
const headers = new Headers(init?.headers);
|
|
24
|
+
Object.entries(authHeaders).forEach(([key, value]) => {
|
|
25
|
+
headers.set(key, value);
|
|
26
|
+
});
|
|
27
|
+
const enhancedInit = {
|
|
28
|
+
...init,
|
|
29
|
+
headers
|
|
30
|
+
};
|
|
31
|
+
console.log("[Strands Auth] Injecting auth headers for request:", url);
|
|
32
|
+
return originalFetch(input, enhancedInit);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn("[Strands Auth] Failed to inject auth headers:", error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return originalFetch(input, init);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("[Strands Auth] Error in fetch interceptor:", error);
|
|
40
|
+
return originalFetch(input, init);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
function shouldInjectAuth(url) {
|
|
46
|
+
if (!url.startsWith("http")) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const skipDomains = [
|
|
50
|
+
"googleapis.com",
|
|
51
|
+
"github.com/api",
|
|
52
|
+
"api.github.com",
|
|
53
|
+
"discord.com/api",
|
|
54
|
+
"graph.microsoft.com",
|
|
55
|
+
"api.stripe.com",
|
|
56
|
+
"api.twilio.com"
|
|
57
|
+
// Add other third-party APIs here
|
|
58
|
+
];
|
|
59
|
+
const shouldSkip = skipDomains.some((domain) => url.includes(domain));
|
|
60
|
+
if (shouldSkip) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const apiPatterns = [
|
|
64
|
+
"/api/",
|
|
65
|
+
"/v1/",
|
|
66
|
+
"/v2/",
|
|
67
|
+
"/graphql",
|
|
68
|
+
"/trpc"
|
|
69
|
+
];
|
|
70
|
+
const isApiRequest = apiPatterns.some((pattern) => url.includes(pattern));
|
|
71
|
+
const apiPorts = [":3001", ":8000", ":8080", ":5000", ":4000"];
|
|
72
|
+
const hasApiPort = apiPorts.some((port) => url.includes(port));
|
|
73
|
+
return isApiRequest || hasApiPort;
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
authInterceptor_client as default
|
|
77
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-interceptor.client.es.js","sources":["../../../../../../apps/accounts-ui/src/nuxt/runtime/plugins/auth-interceptor.client.ts"],"sourcesContent":["import { defineNuxtPlugin } from 'nuxt/app'\n\nexport default defineNuxtPlugin({\n name: 'strands-auth-interceptor',\n setup() {\n // Only run on client side\n if (process.server) return\n\n // Store original fetch function\n const originalFetch = globalThis.fetch\n\n // Create interceptor function\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n try {\n // Import auth composable dynamically to avoid SSR issues\n const { useStrandsAuth } = await import('../composables/useStrandsAuth')\n const { currentSession, getAuthHeaders } = useStrandsAuth()\n\n // Parse request URL to determine if it's an API request that needs auth\n let url: string\n if (typeof input === 'string') {\n url = input\n } else if (input instanceof URL) {\n url = input.toString()\n } else {\n url = input.url\n }\n\n // Check if this is an API request that should include auth headers\n const shouldAddAuth = shouldInjectAuth(url)\n\n if (shouldAddAuth && currentSession.value?.accessToken) {\n // Get auth headers\n try {\n const authHeaders = getAuthHeaders()\n \n // Merge headers with existing headers\n const headers = new Headers(init?.headers)\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Create new init object with merged headers\n const enhancedInit: RequestInit = {\n ...init,\n headers\n }\n\n console.log('[Strands Auth] Injecting auth headers for request:', url)\n return originalFetch(input, enhancedInit)\n } catch (error) {\n // If we can't get auth headers, continue with original request\n console.warn('[Strands Auth] Failed to inject auth headers:', error)\n }\n }\n\n // Return original request\n return originalFetch(input, init)\n } catch (error) {\n // If anything goes wrong, fallback to original fetch\n console.error('[Strands Auth] Error in fetch interceptor:', error)\n return originalFetch(input, init)\n }\n }\n }\n})\n\n/**\n * Determine if a URL should have auth headers injected\n */\nfunction shouldInjectAuth(url: string): boolean {\n // Skip data URLs, blob URLs, etc.\n if (!url.startsWith('http')) {\n return false\n }\n\n // Skip third-party APIs that shouldn't receive our auth tokens\n const skipDomains = [\n 'googleapis.com',\n 'github.com/api',\n 'api.github.com',\n 'discord.com/api',\n 'graph.microsoft.com',\n 'api.stripe.com',\n 'api.twilio.com',\n // Add other third-party APIs here\n ]\n\n const shouldSkip = skipDomains.some(domain => url.includes(domain))\n if (shouldSkip) {\n return false\n }\n\n // Include auth for any API endpoints that contain common API patterns\n const apiPatterns = [\n '/api/',\n '/v1/',\n '/v2/',\n '/graphql',\n '/trpc',\n ]\n\n const isApiRequest = apiPatterns.some(pattern => url.includes(pattern))\n \n // Also check for common backend ports that might be API servers\n const apiPorts = [':3001', ':8000', ':8080', ':5000', ':4000']\n const hasApiPort = apiPorts.some(port => url.includes(port))\n\n return isApiRequest || hasApiPort\n}"],"names":[],"mappings":";AAEA,MAAA,yBAAe,iBAAiB;AAAA,EAC9B,MAAM;AAAA,EACN,QAAQ;AAEN,QAAI,QAAQ,OAAQ;AAGpB,UAAM,gBAAgB,WAAW;AAGjC,eAAW,QAAQ,OAAO,OAA0B,SAA0C;AAC5F,UAAI;AAEF,cAAM,EAAE,eAAA,IAAmB,MAAM,OAAO,qCAA+B;AACvE,cAAM,EAAE,gBAAgB,eAAA,IAAmB,eAAA;AAG3C,YAAI;AACJ,YAAI,OAAO,UAAU,UAAU;AAC7B,gBAAM;AAAA,QACR,WAAW,iBAAiB,KAAK;AAC/B,gBAAM,MAAM,SAAA;AAAA,QACd,OAAO;AACL,gBAAM,MAAM;AAAA,QACd;AAGA,cAAM,gBAAgB,iBAAiB,GAAG;AAE1C,YAAI,iBAAiB,eAAe,OAAO,aAAa;AAEtD,cAAI;AACF,kBAAM,cAAc,eAAA;AAGpB,kBAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,mBAAO,QAAQ,WAAW,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACpD,sBAAQ,IAAI,KAAK,KAAK;AAAA,YACxB,CAAC;AAGD,kBAAM,eAA4B;AAAA,cAChC,GAAG;AAAA,cACH;AAAA,YAAA;AAGF,oBAAQ,IAAI,sDAAsD,GAAG;AACrE,mBAAO,cAAc,OAAO,YAAY;AAAA,UAC1C,SAAS,OAAO;AAEd,oBAAQ,KAAK,iDAAiD,KAAK;AAAA,UACrE;AAAA,QACF;AAGA,eAAO,cAAc,OAAO,IAAI;AAAA,MAClC,SAAS,OAAO;AAEd,gBAAQ,MAAM,8CAA8C,KAAK;AACjE,eAAO,cAAc,OAAO,IAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAKD,SAAS,iBAAiB,KAAsB;AAE9C,MAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAAA;AAIF,QAAM,aAAa,YAAY,KAAK,YAAU,IAAI,SAAS,MAAM,CAAC;AAClE,MAAI,YAAY;AACd,WAAO;AAAA,EACT;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,eAAe,YAAY,KAAK,aAAW,IAAI,SAAS,OAAO,CAAC;AAGtE,QAAM,WAAW,CAAC,SAAS,SAAS,SAAS,SAAS,OAAO;AAC7D,QAAM,aAAa,SAAS,KAAK,UAAQ,IAAI,SAAS,IAAI,CAAC;AAE3D,SAAO,gBAAgB;AACzB;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useStrandsAuth.cjs.js");function t(){const{currentSession:t,refreshToken:s,getAuthHeaders:n}=e.useStrandsAuth(),o=async(e,o={})=>{const{autoRefresh:r=!0,requireAuth:a=!0,baseURL:c,...h}=o;if(a&&!t.value?.accessToken)throw new Error("User is not authenticated");let u=e;c&&"string"==typeof e&&!e.startsWith("http")&&(u=new URL(e,c).toString());const i=new Headers(h.headers);if(t.value?.accessToken)try{const e=n();Object.entries(e).forEach(([e,t])=>{i.set(e,t)})}catch(y){if(a)throw y}const p={...h,headers:i};let d=await fetch(u,p);if(401===d.status&&r&&t.value?.refreshToken)try{if(await s()&&t.value?.accessToken){const e=n();Object.entries(e).forEach(([e,t])=>{i.set(e,t)}),d=await fetch(u,{...p,headers:i})}}catch(f){}return d};return{authenticatedFetch:o,get:(e,t)=>o(e,{...t,method:"GET"}),post:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"POST",headers:n,body:"object"==typeof t?JSON.stringify(t):t})},put:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"PUT",headers:n,body:"object"==typeof t?JSON.stringify(t):t})},delete:(e,t)=>o(e,{...t,method:"DELETE"}),patch:(e,t,s)=>{const n=new Headers(s?.headers);return t&&"object"==typeof t&&!n.has("Content-Type")&&n.set("Content-Type","application/json"),o(e,{...s,method:"PATCH",headers:n,body:"object"==typeof t?JSON.stringify(t):t})}}}const s={get:async(e,s)=>{const{get:n}=t();return n(e,s)},post:async(e,s,n)=>{const{post:o}=t();return o(e,s,n)},put:async(e,s,n)=>{const{put:o}=t();return o(e,s,n)},delete:async(e,s)=>{const{delete:n}=t();return n(e,s)},patch:async(e,s,n)=>{const{patch:o}=t();return o(e,s,n)}};exports.$authFetch=s,exports.useAuthenticatedFetch=t;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthenticatedFetch.cjs.js","sources":["../../../../../../apps/accounts-ui/src/nuxt-v4/runtime/composables/useAuthenticatedFetch.ts"],"sourcesContent":["import { useStrandsAuth } from './useStrandsAuth'\nimport type { AuthenticatedFetchOptions } from '../../../types'\n\n/**\n * Enhanced fetch composable that automatically includes auth headers\n * and handles token refresh for API requests\n */\nexport function useAuthenticatedFetch() {\n const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth()\n\n const authenticatedFetch = async (\n url: string | URL,\n options: AuthenticatedFetchOptions = {}\n ): Promise<Response> => {\n const {\n autoRefresh = true,\n requireAuth = true,\n baseURL,\n ...fetchOptions\n } = options\n\n // Check if user is authenticated when required\n if (requireAuth && !currentSession.value?.accessToken) {\n throw new Error('User is not authenticated')\n }\n\n // Construct full URL if baseURL is provided\n let fullUrl: string | URL = url\n if (baseURL && typeof url === 'string' && !url.startsWith('http')) {\n fullUrl = new URL(url, baseURL).toString()\n }\n\n // Prepare headers\n const headers = new Headers(fetchOptions.headers)\n \n // Add auth headers if available\n if (currentSession.value?.accessToken) {\n try {\n const authHeaders = getAuthHeaders()\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n } catch (error) {\n console.warn('[Strands Auth] Failed to get auth headers:', error)\n if (requireAuth) {\n throw error\n }\n }\n }\n\n // Make the request\n const enhancedOptions: RequestInit = {\n ...fetchOptions,\n headers\n }\n\n let response = await fetch(fullUrl, enhancedOptions)\n\n // Handle 401 with auto-refresh\n if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {\n console.log('[Strands Auth] Request failed with 401, attempting token refresh...')\n \n try {\n // Attempt to refresh token\n const refreshed = await refreshToken()\n \n if (refreshed && currentSession.value?.accessToken) {\n // Update headers with new token\n const newAuthHeaders = getAuthHeaders()\n Object.entries(newAuthHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Retry the request with new token\n console.log('[Strands Auth] Retrying request with refreshed token')\n response = await fetch(fullUrl, { ...enhancedOptions, headers })\n }\n } catch (refreshError) {\n console.error('[Strands Auth] Token refresh failed:', refreshError)\n // Return the original 401 response\n }\n }\n\n return response\n }\n\n /**\n * Convenience method for making authenticated GET requests\n */\n const get = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'GET' })\n }\n\n /**\n * Convenience method for making authenticated POST requests\n */\n const post = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n // Auto-set content type for JSON requests\n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'POST',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated PUT requests\n */\n const put = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PUT',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated DELETE requests\n */\n const del = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'DELETE' })\n }\n\n /**\n * Convenience method for making authenticated PATCH requests\n */\n const patch = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PATCH',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n return {\n authenticatedFetch,\n get,\n post,\n put,\n delete: del,\n patch\n }\n}\n\n// Export convenience functions for non-composable usage\nexport const $authFetch = {\n get: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { get } = useAuthenticatedFetch()\n return get(url, options)\n },\n post: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { post } = useAuthenticatedFetch()\n return post(url, body, options)\n },\n put: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { put } = useAuthenticatedFetch()\n return put(url, body, options)\n },\n delete: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { delete: del } = useAuthenticatedFetch()\n return del(url, options)\n },\n patch: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { patch } = useAuthenticatedFetch()\n return patch(url, body, options)\n }\n}"],"names":["useAuthenticatedFetch","currentSession","refreshToken","getAuthHeaders","useStrandsAuth","authenticatedFetch","async","url","options","autoRefresh","requireAuth","baseURL","fetchOptions","value","accessToken","Error","fullUrl","startsWith","URL","toString","headers","Headers","authHeaders","Object","entries","forEach","key","set","error","enhancedOptions","response","fetch","status","newAuthHeaders","refreshError","get","method","post","body","has","JSON","stringify","put","delete","patch","$authFetch","del"],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useStrandsAuth } from "./useStrandsAuth.es.js";
|
|
2
|
+
function useAuthenticatedFetch() {
|
|
3
|
+
const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth();
|
|
4
|
+
const authenticatedFetch = async (url, options = {}) => {
|
|
5
|
+
const {
|
|
6
|
+
autoRefresh = true,
|
|
7
|
+
requireAuth = true,
|
|
8
|
+
baseURL,
|
|
9
|
+
...fetchOptions
|
|
10
|
+
} = options;
|
|
11
|
+
if (requireAuth && !currentSession.value?.accessToken) {
|
|
12
|
+
throw new Error("User is not authenticated");
|
|
13
|
+
}
|
|
14
|
+
let fullUrl = url;
|
|
15
|
+
if (baseURL && typeof url === "string" && !url.startsWith("http")) {
|
|
16
|
+
fullUrl = new URL(url, baseURL).toString();
|
|
17
|
+
}
|
|
18
|
+
const headers = new Headers(fetchOptions.headers);
|
|
19
|
+
if (currentSession.value?.accessToken) {
|
|
20
|
+
try {
|
|
21
|
+
const authHeaders = getAuthHeaders();
|
|
22
|
+
Object.entries(authHeaders).forEach(([key, value]) => {
|
|
23
|
+
headers.set(key, value);
|
|
24
|
+
});
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.warn("[Strands Auth] Failed to get auth headers:", error);
|
|
27
|
+
if (requireAuth) {
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const enhancedOptions = {
|
|
33
|
+
...fetchOptions,
|
|
34
|
+
headers
|
|
35
|
+
};
|
|
36
|
+
let response = await fetch(fullUrl, enhancedOptions);
|
|
37
|
+
if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {
|
|
38
|
+
console.log("[Strands Auth] Request failed with 401, attempting token refresh...");
|
|
39
|
+
try {
|
|
40
|
+
const refreshed = await refreshToken();
|
|
41
|
+
if (refreshed && currentSession.value?.accessToken) {
|
|
42
|
+
const newAuthHeaders = getAuthHeaders();
|
|
43
|
+
Object.entries(newAuthHeaders).forEach(([key, value]) => {
|
|
44
|
+
headers.set(key, value);
|
|
45
|
+
});
|
|
46
|
+
console.log("[Strands Auth] Retrying request with refreshed token");
|
|
47
|
+
response = await fetch(fullUrl, { ...enhancedOptions, headers });
|
|
48
|
+
}
|
|
49
|
+
} catch (refreshError) {
|
|
50
|
+
console.error("[Strands Auth] Token refresh failed:", refreshError);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return response;
|
|
54
|
+
};
|
|
55
|
+
const get = (url, options) => {
|
|
56
|
+
return authenticatedFetch(url, { ...options, method: "GET" });
|
|
57
|
+
};
|
|
58
|
+
const post = (url, body, options) => {
|
|
59
|
+
const headers = new Headers(options?.headers);
|
|
60
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
61
|
+
headers.set("Content-Type", "application/json");
|
|
62
|
+
}
|
|
63
|
+
return authenticatedFetch(url, {
|
|
64
|
+
...options,
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers,
|
|
67
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const put = (url, body, options) => {
|
|
71
|
+
const headers = new Headers(options?.headers);
|
|
72
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
73
|
+
headers.set("Content-Type", "application/json");
|
|
74
|
+
}
|
|
75
|
+
return authenticatedFetch(url, {
|
|
76
|
+
...options,
|
|
77
|
+
method: "PUT",
|
|
78
|
+
headers,
|
|
79
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const del = (url, options) => {
|
|
83
|
+
return authenticatedFetch(url, { ...options, method: "DELETE" });
|
|
84
|
+
};
|
|
85
|
+
const patch = (url, body, options) => {
|
|
86
|
+
const headers = new Headers(options?.headers);
|
|
87
|
+
if (body && typeof body === "object" && !headers.has("Content-Type")) {
|
|
88
|
+
headers.set("Content-Type", "application/json");
|
|
89
|
+
}
|
|
90
|
+
return authenticatedFetch(url, {
|
|
91
|
+
...options,
|
|
92
|
+
method: "PATCH",
|
|
93
|
+
headers,
|
|
94
|
+
body: typeof body === "object" ? JSON.stringify(body) : body
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
authenticatedFetch,
|
|
99
|
+
get,
|
|
100
|
+
post,
|
|
101
|
+
put,
|
|
102
|
+
delete: del,
|
|
103
|
+
patch
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const $authFetch = {
|
|
107
|
+
get: async (url, options) => {
|
|
108
|
+
const { get } = useAuthenticatedFetch();
|
|
109
|
+
return get(url, options);
|
|
110
|
+
},
|
|
111
|
+
post: async (url, body, options) => {
|
|
112
|
+
const { post } = useAuthenticatedFetch();
|
|
113
|
+
return post(url, body, options);
|
|
114
|
+
},
|
|
115
|
+
put: async (url, body, options) => {
|
|
116
|
+
const { put } = useAuthenticatedFetch();
|
|
117
|
+
return put(url, body, options);
|
|
118
|
+
},
|
|
119
|
+
delete: async (url, options) => {
|
|
120
|
+
const { delete: del } = useAuthenticatedFetch();
|
|
121
|
+
return del(url, options);
|
|
122
|
+
},
|
|
123
|
+
patch: async (url, body, options) => {
|
|
124
|
+
const { patch } = useAuthenticatedFetch();
|
|
125
|
+
return patch(url, body, options);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
export {
|
|
129
|
+
$authFetch,
|
|
130
|
+
useAuthenticatedFetch
|
|
131
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthenticatedFetch.es.js","sources":["../../../../../../apps/accounts-ui/src/nuxt-v4/runtime/composables/useAuthenticatedFetch.ts"],"sourcesContent":["import { useStrandsAuth } from './useStrandsAuth'\nimport type { AuthenticatedFetchOptions } from '../../../types'\n\n/**\n * Enhanced fetch composable that automatically includes auth headers\n * and handles token refresh for API requests\n */\nexport function useAuthenticatedFetch() {\n const { currentSession, refreshToken, getAuthHeaders } = useStrandsAuth()\n\n const authenticatedFetch = async (\n url: string | URL,\n options: AuthenticatedFetchOptions = {}\n ): Promise<Response> => {\n const {\n autoRefresh = true,\n requireAuth = true,\n baseURL,\n ...fetchOptions\n } = options\n\n // Check if user is authenticated when required\n if (requireAuth && !currentSession.value?.accessToken) {\n throw new Error('User is not authenticated')\n }\n\n // Construct full URL if baseURL is provided\n let fullUrl: string | URL = url\n if (baseURL && typeof url === 'string' && !url.startsWith('http')) {\n fullUrl = new URL(url, baseURL).toString()\n }\n\n // Prepare headers\n const headers = new Headers(fetchOptions.headers)\n \n // Add auth headers if available\n if (currentSession.value?.accessToken) {\n try {\n const authHeaders = getAuthHeaders()\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n } catch (error) {\n console.warn('[Strands Auth] Failed to get auth headers:', error)\n if (requireAuth) {\n throw error\n }\n }\n }\n\n // Make the request\n const enhancedOptions: RequestInit = {\n ...fetchOptions,\n headers\n }\n\n let response = await fetch(fullUrl, enhancedOptions)\n\n // Handle 401 with auto-refresh\n if (response.status === 401 && autoRefresh && currentSession.value?.refreshToken) {\n console.log('[Strands Auth] Request failed with 401, attempting token refresh...')\n \n try {\n // Attempt to refresh token\n const refreshed = await refreshToken()\n \n if (refreshed && currentSession.value?.accessToken) {\n // Update headers with new token\n const newAuthHeaders = getAuthHeaders()\n Object.entries(newAuthHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Retry the request with new token\n console.log('[Strands Auth] Retrying request with refreshed token')\n response = await fetch(fullUrl, { ...enhancedOptions, headers })\n }\n } catch (refreshError) {\n console.error('[Strands Auth] Token refresh failed:', refreshError)\n // Return the original 401 response\n }\n }\n\n return response\n }\n\n /**\n * Convenience method for making authenticated GET requests\n */\n const get = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'GET' })\n }\n\n /**\n * Convenience method for making authenticated POST requests\n */\n const post = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n // Auto-set content type for JSON requests\n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'POST',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated PUT requests\n */\n const put = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PUT',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n /**\n * Convenience method for making authenticated DELETE requests\n */\n const del = (url: string | URL, options?: AuthenticatedFetchOptions) => {\n return authenticatedFetch(url, { ...options, method: 'DELETE' })\n }\n\n /**\n * Convenience method for making authenticated PATCH requests\n */\n const patch = (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const headers = new Headers(options?.headers)\n \n if (body && typeof body === 'object' && !headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n\n return authenticatedFetch(url, {\n ...options,\n method: 'PATCH',\n headers,\n body: typeof body === 'object' ? JSON.stringify(body) : body\n })\n }\n\n return {\n authenticatedFetch,\n get,\n post,\n put,\n delete: del,\n patch\n }\n}\n\n// Export convenience functions for non-composable usage\nexport const $authFetch = {\n get: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { get } = useAuthenticatedFetch()\n return get(url, options)\n },\n post: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { post } = useAuthenticatedFetch()\n return post(url, body, options)\n },\n put: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { put } = useAuthenticatedFetch()\n return put(url, body, options)\n },\n delete: async (url: string | URL, options?: AuthenticatedFetchOptions) => {\n const { delete: del } = useAuthenticatedFetch()\n return del(url, options)\n },\n patch: async (url: string | URL, body?: any, options?: AuthenticatedFetchOptions) => {\n const { patch } = useAuthenticatedFetch()\n return patch(url, body, options)\n }\n}"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const e=require("nuxt/app").defineNuxtPlugin({name:"strands-auth-interceptor",setup(){if(process.server)return;const e=globalThis.fetch;globalThis.fetch=async(t,s)=>{try{const{useStrandsAuth:o}=await Promise.resolve().then(()=>require("../composables/useStrandsAuth.cjs.js")),{currentSession:c,getAuthHeaders:n}=o();let i;i="string"==typeof t?t:t instanceof URL?t.toString():t.url;const a=function(e){if(!e.startsWith("http"))return!1;const t=["googleapis.com","github.com/api","api.github.com","discord.com/api","graph.microsoft.com","api.stripe.com","api.twilio.com"].some(t=>e.includes(t));if(t)return!1;const s=["/api/","/v1/","/v2/","/graphql","/trpc"].some(t=>e.includes(t)),r=[":3001",":8000",":8080",":5000",":4000"].some(t=>e.includes(t));return s||r}(i);if(a&&c.value?.accessToken)try{const r=n(),o=new Headers(s?.headers);Object.entries(r).forEach(([e,t])=>{o.set(e,t)});const c={...s,headers:o};return e(t,c)}catch(r){}return e(t,s)}catch(r){return e(t,s)}}}});module.exports=e;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-interceptor.client.cjs.js","sources":["../../../../../../apps/accounts-ui/src/nuxt-v4/runtime/plugins/auth-interceptor.client.ts"],"sourcesContent":["import { defineNuxtPlugin } from 'nuxt/app'\n\nexport default defineNuxtPlugin({\n name: 'strands-auth-interceptor',\n setup() {\n // Only run on client side\n if (process.server) return\n\n // Store original fetch function\n const originalFetch = globalThis.fetch\n\n // Create interceptor function\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n try {\n // Import auth composable dynamically to avoid SSR issues\n const { useStrandsAuth } = await import('../composables/useStrandsAuth')\n const { currentSession, getAuthHeaders } = useStrandsAuth()\n\n // Parse request URL to determine if it's an API request that needs auth\n let url: string\n if (typeof input === 'string') {\n url = input\n } else if (input instanceof URL) {\n url = input.toString()\n } else {\n url = input.url\n }\n\n // Check if this is an API request that should include auth headers\n const shouldAddAuth = shouldInjectAuth(url)\n\n if (shouldAddAuth && currentSession.value?.accessToken) {\n // Get auth headers\n try {\n const authHeaders = getAuthHeaders()\n \n // Merge headers with existing headers\n const headers = new Headers(init?.headers)\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Create new init object with merged headers\n const enhancedInit: RequestInit = {\n ...init,\n headers\n }\n\n console.log('[Strands Auth] Injecting auth headers for request:', url)\n return originalFetch(input, enhancedInit)\n } catch (error) {\n // If we can't get auth headers, continue with original request\n console.warn('[Strands Auth] Failed to inject auth headers:', error)\n }\n }\n\n // Return original request\n return originalFetch(input, init)\n } catch (error) {\n // If anything goes wrong, fallback to original fetch\n console.error('[Strands Auth] Error in fetch interceptor:', error)\n return originalFetch(input, init)\n }\n }\n }\n})\n\n/**\n * Determine if a URL should have auth headers injected\n */\nfunction shouldInjectAuth(url: string): boolean {\n // Skip data URLs, blob URLs, etc.\n if (!url.startsWith('http')) {\n return false\n }\n\n // Skip third-party APIs that shouldn't receive our auth tokens\n const skipDomains = [\n 'googleapis.com',\n 'github.com/api',\n 'api.github.com',\n 'discord.com/api',\n 'graph.microsoft.com',\n 'api.stripe.com',\n 'api.twilio.com',\n // Add other third-party APIs here\n ]\n\n const shouldSkip = skipDomains.some(domain => url.includes(domain))\n if (shouldSkip) {\n return false\n }\n\n // Include auth for any API endpoints that contain common API patterns\n const apiPatterns = [\n '/api/',\n '/v1/',\n '/v2/',\n '/graphql',\n '/trpc',\n ]\n\n const isApiRequest = apiPatterns.some(pattern => url.includes(pattern))\n \n // Also check for common backend ports that might be API servers\n const apiPorts = [':3001', ':8000', ':8080', ':5000', ':4000']\n const hasApiPort = apiPorts.some(port => url.includes(port))\n\n return isApiRequest || hasApiPort\n}"],"names":["authInterceptor_client","name","setup","process","server","originalFetch","globalThis","fetch","async","input","init","useStrandsAuth","Promise","resolve","then","require","currentSession","getAuthHeaders","url","URL","toString","shouldAddAuth","startsWith","shouldSkip","some","includes","domain","isApiRequest","pattern","hasApiPort","port","shouldInjectAuth","value","accessToken","authHeaders","headers","Headers","Object","entries","forEach","key","set","enhancedInit","error"],"mappings":"mBAEAA,uCAAgC,CAC9BC,KAAM,2BACN,KAAAC,GAEE,GAAIC,QAAQC,OAAQ,OAGpB,MAAMC,EAAgBC,WAAWC,MAGjCD,WAAWC,MAAQC,MAAOC,EAA0BC,KAClD,IAEE,MAAMC,eAAEA,SAAyBC,QAAAC,UAAAC,KAAA,IAAAC,QAAO,0CAClCC,eAAEA,EAAAC,eAAgBA,GAAmBN,IAG3C,IAAIO,EAEFA,EADmB,iBAAVT,EACHA,EACGA,aAAiBU,IACpBV,EAAMW,WAENX,EAAMS,IAId,MAAMG,EAyCd,SAA0BH,GAExB,IAAKA,EAAII,WAAW,QAClB,OAAO,EAIT,MAWMC,EAXc,CAClB,iBACA,iBACA,iBACA,kBACA,sBACA,iBACA,kBAI6BC,QAAeN,EAAIO,SAASC,IAC3D,GAAIH,EACF,OAAO,EAIT,MAQMI,EARc,CAClB,QACA,OACA,OACA,WACA,SAG+BH,QAAgBN,EAAIO,SAASG,IAIxDC,EADW,CAAC,QAAS,QAAS,QAAS,QAAS,SAC1BL,QAAaN,EAAIO,SAASK,IAEtD,OAAOH,GAAgBE,CACzB,CAhF8BE,CAAiBb,GAEvC,GAAIG,GAAiBL,EAAegB,OAAOC,YAEzC,IACE,MAAMC,EAAcjB,IAGdkB,EAAU,IAAIC,QAAQ1B,GAAMyB,SAClCE,OAAOC,QAAQJ,GAAaK,QAAQ,EAAEC,EAAKR,MACzCG,EAAQM,IAAID,EAAKR,KAInB,MAAMU,EAA4B,IAC7BhC,EACHyB,WAIF,OAAO9B,EAAcI,EAAOiC,EAC9B,OAASC,GAGT,CAIF,OAAOtC,EAAcI,EAAOC,EAC9B,OAASiC,GAGP,OAAOtC,EAAcI,EAAOC,EAC9B,EAEJ"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { defineNuxtPlugin } from "nuxt/app";
|
|
2
|
+
const authInterceptor_client = defineNuxtPlugin({
|
|
3
|
+
name: "strands-auth-interceptor",
|
|
4
|
+
setup() {
|
|
5
|
+
if (process.server) return;
|
|
6
|
+
const originalFetch = globalThis.fetch;
|
|
7
|
+
globalThis.fetch = async (input, init) => {
|
|
8
|
+
try {
|
|
9
|
+
const { useStrandsAuth } = await import("../composables/useStrandsAuth.es.js");
|
|
10
|
+
const { currentSession, getAuthHeaders } = useStrandsAuth();
|
|
11
|
+
let url;
|
|
12
|
+
if (typeof input === "string") {
|
|
13
|
+
url = input;
|
|
14
|
+
} else if (input instanceof URL) {
|
|
15
|
+
url = input.toString();
|
|
16
|
+
} else {
|
|
17
|
+
url = input.url;
|
|
18
|
+
}
|
|
19
|
+
const shouldAddAuth = shouldInjectAuth(url);
|
|
20
|
+
if (shouldAddAuth && currentSession.value?.accessToken) {
|
|
21
|
+
try {
|
|
22
|
+
const authHeaders = getAuthHeaders();
|
|
23
|
+
const headers = new Headers(init?.headers);
|
|
24
|
+
Object.entries(authHeaders).forEach(([key, value]) => {
|
|
25
|
+
headers.set(key, value);
|
|
26
|
+
});
|
|
27
|
+
const enhancedInit = {
|
|
28
|
+
...init,
|
|
29
|
+
headers
|
|
30
|
+
};
|
|
31
|
+
console.log("[Strands Auth] Injecting auth headers for request:", url);
|
|
32
|
+
return originalFetch(input, enhancedInit);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn("[Strands Auth] Failed to inject auth headers:", error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return originalFetch(input, init);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("[Strands Auth] Error in fetch interceptor:", error);
|
|
40
|
+
return originalFetch(input, init);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
function shouldInjectAuth(url) {
|
|
46
|
+
if (!url.startsWith("http")) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const skipDomains = [
|
|
50
|
+
"googleapis.com",
|
|
51
|
+
"github.com/api",
|
|
52
|
+
"api.github.com",
|
|
53
|
+
"discord.com/api",
|
|
54
|
+
"graph.microsoft.com",
|
|
55
|
+
"api.stripe.com",
|
|
56
|
+
"api.twilio.com"
|
|
57
|
+
// Add other third-party APIs here
|
|
58
|
+
];
|
|
59
|
+
const shouldSkip = skipDomains.some((domain) => url.includes(domain));
|
|
60
|
+
if (shouldSkip) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const apiPatterns = [
|
|
64
|
+
"/api/",
|
|
65
|
+
"/v1/",
|
|
66
|
+
"/v2/",
|
|
67
|
+
"/graphql",
|
|
68
|
+
"/trpc"
|
|
69
|
+
];
|
|
70
|
+
const isApiRequest = apiPatterns.some((pattern) => url.includes(pattern));
|
|
71
|
+
const apiPorts = [":3001", ":8000", ":8080", ":5000", ":4000"];
|
|
72
|
+
const hasApiPort = apiPorts.some((port) => url.includes(port));
|
|
73
|
+
return isApiRequest || hasApiPort;
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
authInterceptor_client as default
|
|
77
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-interceptor.client.es.js","sources":["../../../../../../apps/accounts-ui/src/nuxt-v4/runtime/plugins/auth-interceptor.client.ts"],"sourcesContent":["import { defineNuxtPlugin } from 'nuxt/app'\n\nexport default defineNuxtPlugin({\n name: 'strands-auth-interceptor',\n setup() {\n // Only run on client side\n if (process.server) return\n\n // Store original fetch function\n const originalFetch = globalThis.fetch\n\n // Create interceptor function\n globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n try {\n // Import auth composable dynamically to avoid SSR issues\n const { useStrandsAuth } = await import('../composables/useStrandsAuth')\n const { currentSession, getAuthHeaders } = useStrandsAuth()\n\n // Parse request URL to determine if it's an API request that needs auth\n let url: string\n if (typeof input === 'string') {\n url = input\n } else if (input instanceof URL) {\n url = input.toString()\n } else {\n url = input.url\n }\n\n // Check if this is an API request that should include auth headers\n const shouldAddAuth = shouldInjectAuth(url)\n\n if (shouldAddAuth && currentSession.value?.accessToken) {\n // Get auth headers\n try {\n const authHeaders = getAuthHeaders()\n \n // Merge headers with existing headers\n const headers = new Headers(init?.headers)\n Object.entries(authHeaders).forEach(([key, value]) => {\n headers.set(key, value)\n })\n\n // Create new init object with merged headers\n const enhancedInit: RequestInit = {\n ...init,\n headers\n }\n\n console.log('[Strands Auth] Injecting auth headers for request:', url)\n return originalFetch(input, enhancedInit)\n } catch (error) {\n // If we can't get auth headers, continue with original request\n console.warn('[Strands Auth] Failed to inject auth headers:', error)\n }\n }\n\n // Return original request\n return originalFetch(input, init)\n } catch (error) {\n // If anything goes wrong, fallback to original fetch\n console.error('[Strands Auth] Error in fetch interceptor:', error)\n return originalFetch(input, init)\n }\n }\n }\n})\n\n/**\n * Determine if a URL should have auth headers injected\n */\nfunction shouldInjectAuth(url: string): boolean {\n // Skip data URLs, blob URLs, etc.\n if (!url.startsWith('http')) {\n return false\n }\n\n // Skip third-party APIs that shouldn't receive our auth tokens\n const skipDomains = [\n 'googleapis.com',\n 'github.com/api',\n 'api.github.com',\n 'discord.com/api',\n 'graph.microsoft.com',\n 'api.stripe.com',\n 'api.twilio.com',\n // Add other third-party APIs here\n ]\n\n const shouldSkip = skipDomains.some(domain => url.includes(domain))\n if (shouldSkip) {\n return false\n }\n\n // Include auth for any API endpoints that contain common API patterns\n const apiPatterns = [\n '/api/',\n '/v1/',\n '/v2/',\n '/graphql',\n '/trpc',\n ]\n\n const isApiRequest = apiPatterns.some(pattern => url.includes(pattern))\n \n // Also check for common backend ports that might be API servers\n const apiPorts = [':3001', ':8000', ':8080', ':5000', ':4000']\n const hasApiPort = apiPorts.some(port => url.includes(port))\n\n return isApiRequest || hasApiPort\n}"],"names":[],"mappings":";AAEA,MAAA,yBAAe,iBAAiB;AAAA,EAC9B,MAAM;AAAA,EACN,QAAQ;AAEN,QAAI,QAAQ,OAAQ;AAGpB,UAAM,gBAAgB,WAAW;AAGjC,eAAW,QAAQ,OAAO,OAA0B,SAA0C;AAC5F,UAAI;AAEF,cAAM,EAAE,eAAA,IAAmB,MAAM,OAAO,qCAA+B;AACvE,cAAM,EAAE,gBAAgB,eAAA,IAAmB,eAAA;AAG3C,YAAI;AACJ,YAAI,OAAO,UAAU,UAAU;AAC7B,gBAAM;AAAA,QACR,WAAW,iBAAiB,KAAK;AAC/B,gBAAM,MAAM,SAAA;AAAA,QACd,OAAO;AACL,gBAAM,MAAM;AAAA,QACd;AAGA,cAAM,gBAAgB,iBAAiB,GAAG;AAE1C,YAAI,iBAAiB,eAAe,OAAO,aAAa;AAEtD,cAAI;AACF,kBAAM,cAAc,eAAA;AAGpB,kBAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,mBAAO,QAAQ,WAAW,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACpD,sBAAQ,IAAI,KAAK,KAAK;AAAA,YACxB,CAAC;AAGD,kBAAM,eAA4B;AAAA,cAChC,GAAG;AAAA,cACH;AAAA,YAAA;AAGF,oBAAQ,IAAI,sDAAsD,GAAG;AACrE,mBAAO,cAAc,OAAO,YAAY;AAAA,UAC1C,SAAS,OAAO;AAEd,oBAAQ,KAAK,iDAAiD,KAAK;AAAA,UACrE;AAAA,QACF;AAGA,eAAO,cAAc,OAAO,IAAI;AAAA,MAClC,SAAS,OAAO;AAEd,gBAAQ,MAAM,8CAA8C,KAAK;AACjE,eAAO,cAAc,OAAO,IAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAKD,SAAS,iBAAiB,KAAsB;AAE9C,MAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AAC3B,WAAO;AAAA,EACT;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAAA;AAIF,QAAM,aAAa,YAAY,KAAK,YAAU,IAAI,SAAS,MAAM,CAAC;AAClE,MAAI,YAAY;AACd,WAAO;AAAA,EACT;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,eAAe,YAAY,KAAK,aAAW,IAAI,SAAS,OAAO,CAAC;AAGtE,QAAM,WAAW,CAAC,SAAS,SAAS,SAAS,SAAS,OAAO;AAC7D,QAAM,aAAa,SAAS,KAAK,UAAQ,IAAI,SAAS,IAAI,CAAC;AAE3D,SAAO,gBAAgB;AACzB;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./nuxt-v4/module.cjs.js"),t=require("./nuxt-v4/runtime/composables/useStrandsAuth.cjs.js"),s=require("./nuxt-v4/runtime/composables/useAuthenticatedFetch.cjs.js");exports.default=e,exports.useAuthState=t.useAuthState,exports.useAuthUser=t.useAuthUser,exports.useStrandsAuth=t.useStrandsAuth,exports.$authFetch=s.$authFetch,exports.useAuthenticatedFetch=s.useAuthenticatedFetch;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nuxt-v4.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as default2 } from "./nuxt-v4/module.es.js";
|
|
2
|
+
import { useAuthState, useAuthUser, useStrandsAuth } from "./nuxt-v4/runtime/composables/useStrandsAuth.es.js";
|
|
3
|
+
import { $authFetch, useAuthenticatedFetch } from "./nuxt-v4/runtime/composables/useAuthenticatedFetch.es.js";
|
|
4
|
+
export {
|
|
5
|
+
$authFetch,
|
|
6
|
+
default2 as default,
|
|
7
|
+
useAuthState,
|
|
8
|
+
useAuthUser,
|
|
9
|
+
useAuthenticatedFetch,
|
|
10
|
+
useStrandsAuth
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nuxt-v4.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
package/dist/nuxt.cjs.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./nuxt/module.cjs.js"),t=require("./nuxt/runtime/composables/useStrandsAuth.cjs.js"),s=require("./nuxt/runtime/composables/useAuthenticatedFetch.cjs.js");exports.default=e,exports.useAuthState=t.useAuthState,exports.useAuthUser=t.useAuthUser,exports.useStrandsAuth=t.useStrandsAuth,exports.$authFetch=s.$authFetch,exports.useAuthenticatedFetch=s.useAuthenticatedFetch;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nuxt.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|