@mvp-factory/holy-auth-firebase
Version:
Firebase Authentication module with Google Sign-In support
133 lines (132 loc) • 4.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.authenticatedFetch = authenticatedFetch;
exports.authenticatedJSON = authenticatedJSON;
exports.authenticatedPost = authenticatedPost;
exports.authenticatedGet = authenticatedGet;
exports.authenticatedDelete = authenticatedDelete;
exports.authenticatedPut = authenticatedPut;
exports.authenticatedPatch = authenticatedPatch;
exports.authenticatedUpload = authenticatedUpload;
exports.createAuthenticatedClient = createAuthenticatedClient;
const FirebaseAuthManager_1 = require("../core/FirebaseAuthManager");
async function authenticatedFetch(url, options = {}) {
const { skipAuth = false, forceTokenRefresh = false, retryOnUnauthorized = true, maxRetries = 1, ...fetchOptions } = options;
if (skipAuth) {
return fetch(url, fetchOptions);
}
const authManager = FirebaseAuthManager_1.FirebaseAuthManager.getInstance();
const token = await authManager.getIdToken(forceTokenRefresh);
if (!token) {
throw new Error('Not authenticated');
}
const headers = {
...fetchOptions.headers,
'Authorization': `Bearer ${token}`
};
let lastError = null;
let retryCount = 0;
while (retryCount <= maxRetries) {
try {
const response = await fetch(url, { ...fetchOptions, headers });
if (response.status === 401 && retryOnUnauthorized && retryCount < maxRetries) {
const newToken = await authManager.getIdToken(true);
headers['Authorization'] = `Bearer ${newToken}`;
retryCount++;
continue;
}
return response;
}
catch (error) {
lastError = error;
retryCount++;
if (retryCount > maxRetries) {
break;
}
}
}
throw lastError || new Error('Fetch failed');
}
async function authenticatedJSON(url, options = {}) {
const response = await authenticatedFetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
...options.headers
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
return response.json();
}
async function authenticatedPost(url, data, options = {}) {
return authenticatedJSON(url, {
...options,
method: 'POST',
body: JSON.stringify(data)
});
}
async function authenticatedGet(url, options = {}) {
return authenticatedJSON(url, {
...options,
method: 'GET'
});
}
async function authenticatedDelete(url, options = {}) {
return authenticatedJSON(url, {
...options,
method: 'DELETE'
});
}
async function authenticatedPut(url, data, options = {}) {
return authenticatedJSON(url, {
...options,
method: 'PUT',
body: JSON.stringify(data)
});
}
async function authenticatedPatch(url, data, options = {}) {
return authenticatedJSON(url, {
...options,
method: 'PATCH',
body: JSON.stringify(data)
});
}
async function authenticatedUpload(url, file, options = {}) {
const formData = new FormData();
formData.append(options.fieldName || 'file', file);
if (options.body && typeof options.body === 'object') {
Object.entries(options.body).forEach(([key, value]) => {
if (key !== options.fieldName) {
formData.append(key, String(value));
}
});
}
return authenticatedFetch(url, {
...options,
method: 'POST',
body: formData,
headers: {
...options.headers
}
});
}
function createAuthenticatedClient(baseURL) {
const resolveURL = (path) => {
if (path.startsWith('http'))
return path;
return `${baseURL.replace(/\/$/, '')}/${path.replace(/^\//, '')}`;
};
return {
fetch: (path, options) => authenticatedFetch(resolveURL(path), options),
get: (path, options) => authenticatedGet(resolveURL(path), options),
post: (path, data, options) => authenticatedPost(resolveURL(path), data, options),
put: (path, data, options) => authenticatedPut(resolveURL(path), data, options),
patch: (path, data, options) => authenticatedPatch(resolveURL(path), data, options),
delete: (path, options) => authenticatedDelete(resolveURL(path), options),
upload: (path, file, options) => authenticatedUpload(resolveURL(path), file, options)
};
}