@lineai/bluebeam-api
Version:
Your unofficial library for Bluebeam API for human and AI developers. Provides TypeScript support, entity classes, and developer-friendly features. Perfect for AI coders, construction professionals, and document management tasks. Includes comprehensive JS
152 lines • 11.8 kB
JavaScript
import { createOAuthClient } from './auth';
import { createHttpClient } from './http-client';
import { createSessionsClient } from './sessions';
import { createSessionsMarkupsClient, } from './sessions-markups';
import { createMemoryStorage } from './storage';
export const loadFromEnvironment = () => ({
client_id: process.env.BLUEBEAM_CLIENT_ID,
client_secret: process.env.BLUEBEAM_CLIENT_SECRET,
access_token: process.env.BLUEBEAM_ACCESS_TOKEN,
redirect_uri: process.env.BLUEBEAM_REDIRECT_URI,
scope: process.env.BLUEBEAM_SCOPE,
base_url: process.env.BLUEBEAM_BASE_URL,
});
export const createBluebeamClient = (config = {}) => {
// Merge environment variables with provided config
const envConfig = loadFromEnvironment();
const mergedConfig = {
...envConfig,
...config,
};
// Extract client and OAuth configs
const clientConfig = {
client_id: mergedConfig.client_id || '',
access_token: mergedConfig.access_token,
base_url: mergedConfig.base_url,
};
const oauthConfig = {
client_id: mergedConfig.client_id || '',
client_secret: mergedConfig.client_secret || '',
redirect_uri: mergedConfig.redirect_uri || '',
scope: mergedConfig.scope || '',
base_url: mergedConfig.base_url,
};
// Validate required OAuth configuration
if (!oauthConfig.client_id || !oauthConfig.client_secret) {
return Promise.reject(new Error('OAuth configuration is required'));
}
/**
* Internal interceptor that handles automatic token refresh on 401 errors
*/
class AuthInterceptor {
config;
auth;
storage;
autoRefresh;
httpClient;
constructor(config, auth, storage, autoRefresh) {
this.config = config;
this.auth = auth;
this.storage = storage;
this.autoRefresh = autoRefresh;
this.httpClient = createHttpClient(config);
}
async get(endpoint) {
return this.executeWithRetry(() => this.httpClient.get(endpoint));
}
async post(endpoint, data, isFormData) {
return this.executeWithRetry(() => this.httpClient.post(endpoint, data, isFormData));
}
async put(endpoint, data) {
return this.executeWithRetry(() => this.httpClient.put(endpoint, data));
}
async delete(endpoint) {
return this.executeWithRetry(() => this.httpClient.delete(endpoint));
}
async executeWithRetry(requestFn) {
try {
return await requestFn();
}
catch (error) {
// Only retry on 401 if autoRefresh is enabled
if (!this.autoRefresh || error.status !== 401) {
throw error;
}
try {
// Refresh token
await this.auth.refreshAccessToken();
// Get fresh token from storage
const tokens = await this.storage.getTokens();
// Create new HTTP client with fresh token
this.httpClient = createHttpClient({
...this.config,
access_token: tokens?.access_token
});
// Retry request once
return await requestFn();
}
catch (refreshError) {
// Refresh failed, throw original error
throw error;
}
}
}
}
const createClientWithConfig = async (config) => {
// Load existing tokens from storage first
const storage = mergedConfig.tokenStorage || createMemoryStorage();
const existingTokens = await storage.getTokens();
// Use token from storage if available, otherwise use provided token
const configWithToken = {
...config,
access_token: existingTokens?.access_token || config.access_token,
};
// Create HTTP client first
const httpClient = createHttpClient(configWithToken);
// Create auth client
const auth = await createOAuthClient({
client_id: oauthConfig.client_id,
client_secret: oauthConfig.client_secret,
redirect_uri: oauthConfig.redirect_uri,
scope: oauthConfig.scope,
base_url: oauthConfig.base_url,
tokenStorage: storage,
httpClient,
});
// Use interceptor if autoRefresh is enabled (default true)
const autoRefresh = mergedConfig.autoRefresh !== false;
const clientForApi = autoRefresh
? new AuthInterceptor(configWithToken, auth, storage, autoRefresh)
: httpClient;
const sessions = createSessionsClient(clientForApi);
const markups = createSessionsMarkupsClient(clientForApi);
const updateAccessToken = (accessToken) => {
const newConfig = { ...config, access_token: accessToken };
return createClientWithConfig(newConfig);
};
return {
auth,
sessions,
markups,
httpClient,
updateAccessToken,
};
};
return createClientWithConfig(clientConfig);
};
export const createBluebeamClientWithToken = (clientId, accessToken, options) => {
const config = {
client_id: clientId,
access_token: accessToken,
...options,
};
const httpClient = createHttpClient(config);
const sessions = createSessionsClient(httpClient);
const markups = createSessionsMarkupsClient(httpClient);
return {
sessions,
markups,
httpClient,
};
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0EsT0FBTyxFQUFFLGlCQUFpQixFQUFlLE1BQU0sUUFBUSxDQUFDO0FBQ3hELE9BQU8sRUFBRSxnQkFBZ0IsRUFBNEIsTUFBTSxlQUFlLENBQUM7QUFDM0UsT0FBTyxFQUFFLG9CQUFvQixFQUFrQixNQUFNLFlBQVksQ0FBQztBQUNsRSxPQUFPLEVBQ0wsMkJBQTJCLEdBRTVCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBMkJoRCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxHQUFtQixFQUFFLENBQUMsQ0FBQztJQUN4RCxTQUFTLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0I7SUFDekMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCO0lBQ2pELFlBQVksRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQjtJQUMvQyxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUI7SUFDL0MsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYztJQUNqQyxRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUI7Q0FDeEMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsQ0FDbEMsU0FBeUIsRUFBRSxFQUNGLEVBQUU7SUFDM0IsbURBQW1EO0lBQ25ELE1BQU0sU0FBUyxHQUFHLG1CQUFtQixFQUFFLENBQUM7SUFDeEMsTUFBTSxZQUFZLEdBQUc7UUFDbkIsR0FBRyxTQUFTO1FBQ1osR0FBRyxNQUFNO0tBQ1YsQ0FBQztJQUVGLG1DQUFtQztJQUNuQyxNQUFNLFlBQVksR0FBaUI7UUFDakMsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUFTLElBQUks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